Releases: Codestz/opencode-cockpit
Release list
v0.6.0
Added
-
Cockpit runs on OpenCode 2. Every package now loads on OpenCode 1.18+ and 2.0.15+ from the
same entry: the panels, console, Review, statusline and updater in the interface, and theshell_*
andreview_*tools, system guidance and exit notifications on the agent side. Each bay is written
once against a host (@opencode-cockpit/client/hostand/server) that each version supplies. On
OpenCode 2,/plugins-updatesays to change the version inopencode.json: the updater edits
OpenCode 1's files only. -
One log for everything Cockpit does inside OpenCode. Both halves of every bay write JSON lines
to~/.cache/opencode-cockpit/cockpit.log, beside the daemon'scockpitd.log: which OpenCode
(v1 or v2, and its version) loaded which entry, every error with its stack — including ones that
used to be a toast and nothing else — and every tool that failed.COCKPIT_DEBUG=1 opencodeadds
the detail (console actions, each tool call and how long it took) and turns the daemon's debug
lines on too. The file moves tocockpit.log.1past 5 MB. -
npx opencode-cockpit@latest doctor. Checks a setup and prints the fix for anything wrong,
for the OpenCode you have: its version; every Cockpit entry inopencode.json,tui.jsonand
cli.jsonin either OpenCode's spelling — a bay configured twice, a half missing on OpenCode 1, a
pin older than the newest release, a checkout OpenCode 2 cannot load; what the log says last ran,
and on which OpenCode; recent errors; the daemon;gitandps; settings files and statusline
modules. Runs under Node outside OpenCode, so it works when Cockpit will not load.--jsonfor an
issue; exits 1 when something must be fixed.
Changed
createShellServerandcreateReviewServerreturn a feature fordualServerrather than a v1
plugin function.
Fixed
- Full-screen shell console and the Review pane were see-through on transparent themes. A theme
that leaves its background transparent (OpenCode's "system" theme, which shows the terminal's own)
painted the full-window surface with nothing, and the conversation showed through it. They now use
the first opaque background the theme has, and a solid one when it has none.
v0.5.2
Added
- Review reads like a pull request: every file in one scroll. Each changed file is a card with a
heading you can fold — path,+/−, its notes,+ noteand[ ] viewed— and the heading of the
file you are in stays pinned at the top. Marking a file viewed folds it and moves to the next
unviewed one (below, or the nearest above — never back to the start);zorenterfolds by hand;
very large diffs start folded. Headings are clickable. Only what is on screen is drawn: a
two-hundred-file review scrolls at under a millisecond a frame, and each diff is worked out once.
The file list follows the diff as you scroll. - Review compares a stacked branch with the branch it grew from. On
main ← feature ← X, branch
mode used to compare X withmainand mix in every commit offeature; a stale localmainmixed
in work already merged. It now finds the nearest parent — the branch X has the fewest commits
beyond — the way a pull request from X intofeaturereads.Bpicks another base, remembered per
branch. - Shell console full screen (
w). The same console over the whole window — output, details,
search, every key — remembered for next time;wagain for the dialog. - Scroll back through a shell's screen.
j/k(or the wheel in full screen) scroll the screen
view through the terminal's history, not only the plain log;Gfollows the output again. - Finished agent shells clean themselves up.
lifecycle.removeFinishedAfterMinutes(30 by
default,0keeps them) removes a shell the agent started that long after it exits cleanly. Failed
or killed shells stay until/shells-clear: those are the ones worth reading. - Watchers look like watchers. A watched shell says
watch tsc …from the start — it used to look
like any other shell until its first run finished — and/shellsgroups them under Watching.
Changed
/shellsis a list: every shell in the project, grouped by what needs attention, with "New
shell" first. The dock moved to/shells-dock(ctrl+x ounchanged);/shellstill reopens the
last console.- The pane without the cursor is dimmed less. It blended into the background far enough to read as
disabled; it is now a gentle step back. Bis in Review's key row, and the shell console dialog is centred on screen.
Fixed
- Clicks in the Review pane landed one row off, and
+ noteon a heading closed its own dialog on
mouse release. - Opening the shell console while it was already open left a dialog that
esccould not close.
v0.5.1
Fixed
- The Updater tells a program from a plugin.
opencode-worktree@latestin a plugin list names a
command-line tool on npm, with no plugin entry points; OpenCode refuses it, and the Updater used to
propose pinning it and then fail with that same refusal. It now reads the installed manifest and
applies OpenCode's own rule —exports["./tui"],exports["./server"],mainoroc-themes—
and lists anything else asnot a plugin, with the file to remove the entry from. What OpenCode
already loaded is never questioned, and a manifest it cannot read proves nothing. - A pin says what it is for. The review showed
0.4.1 → 0.4.1, which read as a bug; it now reads
0.4.1 · pin, so latest cannot freeze again. - A watch sees what the run printed before it was attached. A shell that failed in its first
milliseconds could print its failure beforeshell.watcharrived, and the run was judged without
it. A new watcher is now caught up on the current run's recent output — never an earlier run's —
and on its exit, if it has already ended.
v0.5.0
Added
- Updater: every plugin you have installed, what it is really running, and an update checked
against disk. OpenCode installs a plugin into a cache directory named after its spec and never
resolves it again, sosome-plugin@latest— or a bare name — means the release that was newest
the day you first installed it: one person sat on 0.1.2 while 0.4.2 was published./plugins-update
lists every plugin with what is running beside what the config says and what is published;
latest ⚠marks a spec that will not move on its own. The review shows every file and cache
directory that will change before anything is written. An update pins an exact version through
OpenCode's ownopencode plugin -f, removes the stale cache, and reads every file back — the
command prints "Installed" over entries it left alone, so disk is the only evidence. Whatever is
still wrong comes with the exact command that fixes it. Docs - The rescue, for anyone too far behind to have it:
npx opencode-cockpit@latest update(or
bunx). It runs from npm rather than from the copy that is stuck, and both re-resolve@lateston
every run — what OpenCode's cache does not do.--dry-run,--only <name>and--yes. - A failed install says why, and what fixes it. npm's cache holding files you do not own — an old
sudo npm— fails every install that touches them; the result names it and puts
sudo chown -R "$(whoami)" ~/.npmbefore the retry.
Changed
- Every install line pins a version:
opencode plugin opencode-cockpit@0.5.0 --global --force.
The documented bare install was the command that created the frozen state;--forcemakes the same
line the way to move to a newer release. /cockpit-updateopens the Updater, for every plugin rather than only this one. The daily notice
moved with it and counts every plugin;ui.updateCheck: falsestill silences it.- The registry is the one npm uses (
npm_config_registry), so a plugin on a private registry is
asked where it lives.
Fixed
- The update check never got an answer. It asked npm for abbreviated metadata on
/latest, which
npm now refuses with a 406, so no update was ever announced and/cockpit-updateoffered a
reinstall with no version. The test stubbed the request and asserted the header, so it stayed green.
v0.4.3
Fixed
- The documented keys match the keys. Review's table still offered a third source that 0.4.2
removed, the statusline'sgit.diffwas still described as counting the session, and the shell's
console table was missingd,shift+d,backspace,ctrl+]and everything that scrolls — along
with the two keys that open the panel and the console in the first place. Every bay now documents
what it actually binds, including the statusline, which binds nothing and says so.
Changed
- The console names its keys the way Review does, and stops carrying all of them.
i type · c ^C · r restart · tab screen · / search logwas a sentence you had to parse before you
could use it, and at nine keys there was no room left for the words. The row now holds only what
acts on the shell in front of you —[i] Type [c] ^C [r] Restart [x] Stop— and[?] Details,
which opens the panel where the rest are laid out in two columns, under the shell's own facts. The
bracket does the work colour would otherwise have to do, and colour stays with the shells.
v0.4.2
Changed
-
Review reads two sources, not three, and the statusline counts git. "This conversation" is
gone. It was built on OpenCode'ssession.diff, which returns an empty list for a session whose
own snapshots plainly differ — checked against three baselines, with the snapshot trees diffed by
hand to confirm the changes were really there. A mode that cannot answer is worse than one that is
missing, so it has been removed along with the deadFileChange.markedit was reserved for.
[b]now toggles uncommitted and branch.The statusline's
session.diffsegment rested on the same feed and made the same promise. It is
nowgit.diffand readsgit diff --shortstat HEAD— what is uncommitted, a number you can check
by running the command yourself. The old name still resolves, the command runs only when a line
actually carries the segment, and a line without it spawns nothing.
Fixed
-
/cockpit-updateno longer promises an update it cannot make. It cleared the cached copy and
told you to restart — but if your config pinsopencode-cockpit@0.4.1, the next start reinstalls
0.4.1 and the version never moves. It now reads both plugin lists (opencode.jsonand
tui.json), and when a pin is in the way it says which entry to edit instead of clearing a cache
for nothing. A path install and a tag are not pins, so neither is treated as one. -
The handover tells the agent what it needs before it asks. The submit message now names the
files the comments are in, so the first move is not a tool call spent finding out where the work
is; says plainly that resolving is refused while a file still reads as it did, which is what
review_replyactually does; and draws a boundary — these comments, no unrelated work, no
commits, and say so in the reply when a comment turns out to be the tip of something bigger. -
The panel no longer fails in silence. The change store set a
noticein four places — "no
conversation open", every git error, "file too large" — and nothing ever read it, so each of those
reached the screen as an empty pane with no explanation. It is now shown in the footer, and the
empty state names the source it is empty for and points at the key that changes it. -
[s]says how much there is to submit, and says the right thing when there is nothing. The key
carries a live count and dims at zero, and the three ways to have nothing to hand over — no
comments yet, all answered, all outdated — now read differently instead of all claiming every
comment had been answered. Submit also counts outdated comments before offering, so the number it
offers is the number it sends.
v0.4.1
Fixed
-
YOUandAGENTare readable on every theme. The badges on a comment — and thereview
badge in the header — printed their word in the theme's background colour, which paints nothing
at all when a theme leaves that colour transparent: the coloured block appeared, the word inside
it did not. The ink is now chosen rather than assumed, taking the first theme colour that both
paints and stands clear of the block it sits on; where a theme offers nothing that reads, the
block is dropped and the badge is printed in its own colour instead. -
A shell the agent starts from a subagent now belongs to the conversation you are in. A tool
called inside a task runs in a child session, and the shell was stamped with that id — so the
panel, which filters by the session on screen, showed the agent's own shells only under "whole
project", and/shelllisted shells that looked like they came from somewhere else. Ownership now
resolves upparentIDto the conversation that asked, and the guidance the agent reads resolves
the same way, so "this session" means the same thing on both sides.
Added
sidebarOrderputs the bays in the order you want. Shell and Statusline both draw in the
sidebar, in the order they register — which was a constant nobody could reach. Set
ui.sidebarOrderfor Shell (default 150) orstatusline.sidebarOrder(default 200); lower draws
first.
v0.4.0
Fixed
- A file containing
@before a bracket or a space no longer freezes the interface. The Review
syntax scanner accepted@as the start of a word but not as part of one, so it advanced by zero
characters and looped forever — at 100% CPU, with no error, no stack and no way out but killing
OpenCode. Ctrl+C did not help either: a synchronous loop never reaches a signal handler. Every
branch of the scanner must now advance, and the test is every printable character in ten
languages plus all 9,025 two-character pairs. - A daemon whose socket has been deleted now stops instead of stranding its shells. A unix socket
is held by its inode rather than by its name, so removing~/.cache/opencode-cockpit— where
cleanup tools aim — left the daemon running and listening on a path that no longer existed. The
next client found no socket, started a second daemon, and the first kept its shells alive where
nothing could see or stop them: a dev server holding a port, findable only withps. There is no
way back from that state, since a client can only reach the daemon through the path, so it shuts
down and lets its shells go rather than leaving them stranded for the rest of the session.
Added
- Review — a pull request in the terminal. Bay 02,
@opencode-cockpit/review. The diff where
the work happened, comments on the lines they are about, and an agent that can read them, answer
them and mark them resolved. Comments live on the branch rather than in the chat, so they outlive
the conversation;shands the review over, and the notes travel as structured data through
review_listrather than as prose the agent has to parse back out of a message. A resolve is
checked against the file before it counts: an agent that claims "done" over an untouched file has
its reply kept, the thread left open, and is told so plainly. It can open notes of its own with
review_open, which appear in the panel beside yours.<leader>vopens it. bun run clean:daemonsstops cockpit daemons that nothing can reach any more — orphans whose
home is gone, and daemons left behind by an interrupted test run.testandcheckrun it first,
because a leftover daemon does not fail a suite, it hangs one.- The line reports its own failures, on the line. A module that would not load draws a
⚠row
naming it, and a column that ran out of room draws a dim↳ N more — raise maxRows. Both used to
end as segments that were simply not there, which is indistinguishable from a segment that had
nothing to say — the one place this bay's silence rule is wrong. The overflow notice takes a row
of its own, and is the first thing dropped if the column is smaller still.
Changed
preview --module <path>draws that module and nothing else, every segment it declares, with
room for all of them. It used to be added to whatever the config already named while the config's
segments still decided what drew — so pointing the preview at a module whose segments the config
does not list produced a confident picture of somebody else's line.--with-configrestores the
old behaviour, which is what you want once the module is finished and you want to see it in place.
v0.3.2
Added
/statuslinehands the agent in your session a brief instead of drawing a panel: which config
file this project reads, what is drawing now, your modules and any that failed to load, the preset
and segment names, and where the design skill lives. It ends by asking what you want it to show.
Customising a line is an editing job, and the agent is already sitting there.
Fixed
bunx @opencode-cockpit/status previewworks. It was exiting 1 and printing nothing, for two
reasons at once: the published entry had no shebang, so a shell read the JavaScript as a shell
script, andbunx <package>looks for a bin named after the package's last segment, which was
never declared. Both are invisible from a checkout, where nobody runs the bin — so the command
every page here recommends had never once worked from npm.- A statusline module outside a project loads again. The fallback that makes
~/.config/opencode-cockpit/modules/work asked for./authoring.ts, which a built copy does not
have beside it, so it threw — and with it went every module belonging to the people that fallback
exists for. It worked only from a checkout, which is where the tests run. - A missing
psno longer fails every shell. The daemon recorded a process' start time by
spawningpsfrom PATH, on the path that starts a shell, so a daemon that inherited an editor's
slimmer PATH turned everyshell_startinto
ENOENT: no such file or directory, posix_spawn 'ps'. It is a best-effort guard against pid reuse
and now behaves like one.
Documentation
- The design skill contradicted itself about the empty half of a bar, calling for
panelin its
rules and warning two paragraphs later thatpanelis the colour of the panel the bar sits on, and
therefore invisible. The track isborder— the same wrong tone was in the drawing page's examples. - The six sample states are written down, with what each one catches: the wall of zeroes on
fresh, the column widths onlyfullreveals, the invented$0.00onunpriced, the rows that
vanish mid-turn onretrying. - Two glyph rules the last design pass earned: no end caps on a bar in a column, because
▕and
▏are eighth-blocks whose ink sits against one cell edge and indent the row out of alignment;
and print a number once, because a bar and the labelled row below it were both reporting43%.
v0.3.1
Added
-
preview— draw your statusline in a terminal, without restarting OpenCode.
bunx @opencode-cockpit/status preview --watchredraws on every save, against six sample
sessions: a fresh one before the first reply, a long one nearly out of room, one behind a proxy
with nothing declared, a stalled one, and no session at all. Designing a statusline used to mean
editing, restarting and squinting — one sidebar cost about twenty restarts, and three of the
mistakes were glyph choices that read differently on screen than in a sentence. -
"debug": truedraws a placeholder where a segment said nothing, so the three reasons a
segment can be absent stop looking identical:⟨context⟩it ran and had nothing to say,
⟨?contex⟩nothing answers to that name,⟨!name⟩it threw. -
A segment can return several rows. An array is a row each, which is how a gauge, a table or a
row per service is drawn. Returning one used to be a silent no-op. -
italicandunderlineon a run, drawn as markup.strikethroughandinverseare not
offered: OpenTUI has no element for either, so they could never have reached the screen. -
examples/gallery.ts— every technique the renderer offers in one column: six kinds of bar,
braille, sparklines, rules, dots, chips, dividers, emphasis, every tone, and multi-row output.
Run it throughpreviewand copy the row you want. -
A design skill, shipped with the package at
skills/statusline-design/, carrying the rules
this bay learned the expensive way — solid bars rather than dashes, words rather than colour
alone, no headings above optional rows, look at it before shipping it. -
Presets — a whole line by name, built-ins only:
minimal,default,detailed,sidebar.
Anything written beside one wins, so it is a starting point rather than a mode. -
examples/sidebar-budget.ts— a sidebar drawn as a table, and the layout a user arrived at
after five rejected iterations: a fixed six-column label gutter so every value lines up, one bar
with no figure beside it, the tokens split into named rows, a budget read from whatever a proxy
writes to~/.cache/opencode-litellm-iap/spend.json, and the branch's whole diff against its
merge-base rather than what this session happened to touch."demo": truefills in sample
figures for the budget rows, so the column can be looked at before a proxy exists.
Fixed
- A statusline module that fails to load now says so in OpenCode's log, not only in a toast
that is gone in ten seconds. The entry names both the module and the directory resolution was
attempted from, which is the pair that makes an import failure obvious instead of mysterious. maxRowsand the padding settings work at the top level of the config, not only inside a
linesentry. Writing them there is the natural guess, and being quietly ignored cost exactly
the rows they were meant to keep.
Documentation
- The design skill is documented on the site, at What you can draw — where it ships, how to
point an agent at it, and what it actually carries. It existed in the package and was mentioned
only in this file, which is no way to find anything. - Two glyph traps written down:
▕and▏are eighth-blocks whose ink sits against one edge
of the cell, so end caps indent a column's bar out of alignment with its labels; and an empty
track wants a solid█in thebordertone, because░reads as floating gaps andpanelis
the colour of the panel it sits on. - The worked-examples lists name all five modules. They still said two.