Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
400cc08
scripts/golden.ts: every preview, in every state, snapshotted — the p…
Codestz Oct 4, 2026
6ad3323
Tests: Review's key table and Trail's tone colours, the two the 0.9 r…
Codestz Oct 4, 2026
7ff81f2
Doctor: Status has an agent half since 0.9 — check both of its halves…
Codestz Oct 4, 2026
ee44fcb
tui-smoke: one probe per bay in scripts/smoke/, and install modes — t…
Codestz Oct 4, 2026
369b591
Tooling: lint and tests see only the repository — not a worktree an a…
Codestz Oct 4, 2026
14c1856
Packages publish only the entry points Cockpit uses: six that nothing…
Codestz Oct 4, 2026
314bda5
Trail: the journal moves to io/ — core/ is pure, as CONTRIBUTING says
Codestz Oct 4, 2026
4f673ec
Review: git, the store's files and the viewer move to io/ — and sourc…
Codestz Oct 4, 2026
2ca4cd0
Updater: the real disk and spawning opencode move to io/ — core/ keep…
Codestz Oct 4, 2026
dcf4b59
Status: the budget, the shell, custom modules and the other file move…
Codestz Oct 5, 2026
08ec907
Client: files by what they talk to — daemon/, opencode/, settings/, s…
Codestz Oct 5, 2026
b6a2a88
Settings: names from before 0.9 are no longer recognised — they are u…
Codestz Oct 5, 2026
df9399a
Status: /statusline is gone — /status-setup is the command's only name
Codestz Oct 5, 2026
938e785
Build: clears dist/ and types/ first, and writes the declarations itself
Codestz Oct 5, 2026
2e9a4c9
Client: host splits by OpenCode — host/v1, host/v2, host/keymap, and …
Codestz Oct 5, 2026
50b7180
Client: server splits by concern — server/parts, v1, v2, skills, surf…
Codestz Oct 5, 2026
637eac8
Status: config.ts splits — the shape, reading it, what is wrong with …
Codestz Oct 5, 2026
3776832
Client: setup's conventions split — the section, where it goes, what …
Codestz Oct 5, 2026
dcee044
Sidebar: one measure of a block's width, in client/sidebar — four bay…
Codestz Oct 5, 2026
9709387
Catalog: each bay's own keys in a file of its own — settings/keys/<ba…
Codestz Oct 5, 2026
d2164f7
Trail: the dialog's columns in a file of their own — core/view/column…
Codestz Oct 5, 2026
28ec8d8
Trail's measurement runs on the shared runner, as Review's and Shell'…
Codestz Oct 5, 2026
fedbd46
Smoke: the agent turn is the measurements' turn — one way to run `ope…
Codestz Oct 5, 2026
15721d9
Changelog: 0.10.0's unreleased entries — the home, unknown names, doc…
Codestz Oct 5, 2026
d1c4335
Smoke: OpenCode 2 configured as the install docs say, and Review's no…
Codestz Oct 5, 2026
e35d5ac
Trust: the ledger's explorer splits — the tree, the card, and the scr…
Codestz Oct 5, 2026
d9a534f
Subagents: the pane's items in calls.ts — screen.ts stacks them, head…
Codestz Oct 5, 2026
58304d7
Trust: the interface splits from one closure — paint, requests, the l…
Codestz Oct 5, 2026
2f0ec51
Subagents: the interface splits from one closure — paint, the pane, m…
Codestz Oct 5, 2026
c238547
Review: the panel's verbs split — navigation, threads, and the table …
Codestz Oct 5, 2026
9df81b3
Trust and the updater load on OpenCode 2 when installed alone — each …
Codestz Oct 5, 2026
22092fb
Review fixes: the site engine resolves through exports, pack-check lo…
Codestz Oct 5, 2026
af5759b
Status's statusline-design skill folder is gone, as it said it would …
Codestz Oct 5, 2026
46c38d6
Review: up to 1,000 files, read eight at a time — and a notice no lon…
Codestz Oct 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ media/social/

# OpenCode project-local config and plugins (created by OpenCode in a session here)
/.opencode/

# preview snapshots for refactors (scripts/golden.ts)
/.golden/
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,40 @@ All notable changes to this project are documented here. The format follows

## [Unreleased]

### Changed

- **Cockpit has a home: [cockpit.codestz.dev](https://cockpit.codestz.dev).** The docs are restyled
to match a new landing page, and every window on both is drawn live by the bays' own renderers
instead of a recording. The README is short and visitor-first, each package's README shows its bay
in a GIF made from that window, and every npm page links to its docs.
- **A name Cockpit does not read is said the same way, whatever its age.** 0.9 kept recognising the
names from before it for one release; they are now unknown names like a typo. A top-level one is
`! settings: "statusline" is not a setting: did you mean "status"?` in Status's column and in
doctor; one inside a bay's section (`review.sidebarOrder`) is named by `/cockpit-setup`, like any
key the bay does not read. Their values were not read in 0.9 and still are not. The site's
configuration page keeps the table of old names and new ones, for anyone moving an old file.

### Fixed

- **Trust and the updater load on OpenCode 2 when installed on their own.** OpenCode 2 sets up a
plugin's interface only once its agent half has loaded, and these two had none — so
`opencode plugin add @opencode-cockpit/trust` (or `/updater`), as the install docs say, loaded
nothing at all. Each now has an agent half with nothing of its own; with it, `/cockpit-setup`
works from either alone, too. The bundle was never affected.
- **Doctor checks Status's agent half too.** Status has had one since 0.9 (its `/status-setup`
command and skill), and doctor's list of bays with two halves did not know it; a test now fails
when a bay with an agent half is missing from it.

### Removed

- **`/statusline`.** Its name until 0.9, kept for one release; `/status-setup` is the command.
- **The `statusline-design` skill folder.** Kept in 0.9 for anyone who had copied it;
`skills/status-setup/` carries the same design rules, in `references/design.md`.
- **Six entry points nothing imported:** `@opencode-cockpit/review/frame` (broken since it was
added: it pointed at a file that was never built there), `trail/core`, `trust/core`,
`updater/core`, `status/fixtures` and `client/elements`. Cockpit's own packages never used them;
`status/segment`, for your own segments, stays.

## [0.9.0] - 2026-10-04

### Added
Expand Down
7 changes: 5 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ The router refuses methods missing from the contract, and handler params are typ
Files are grouped by role, not by type, and entry points stay thin:

- `core/` — pure logic with no I/O and no JSX, imported by both halves (finding, classifying,
formatting).
formatting). It never touches the filesystem, git, the network or another process; the clock or an
environment variable is fine as a parameter's default, which a test passes instead.
- `io/` — what a bay reads and writes outside itself: its files, git, processes it spawns. Both halves
use it; it may import `core/`, never the other way round.
- `core/config.ts` — one loader for every setting: global file → project `.cockpit.json` → plugin
options, merged section-wise. Both halves call `loadConfig()` at startup and read from the result;
nothing else parses config, and a broken file resolves to `{}` instead of throwing.
Expand All @@ -156,7 +159,7 @@ must carry explicit types or stay module-private, or `tsc` cannot name them in d
1. `packages/<feature>` named `@opencode-cockpit/<feature>`, exporting `./server` and/or `./tui`
whose default export is a plugin built from factories (`create<Feature>Server`,
`create<Feature>Tui`) that accept a `source` label and start with `claimFeature`.
2. Add it to `BAYS` in `packages/client/src/settings.ts` — the bundle's `FEATURES`, the settings
2. Add it to `BAYS` in `packages/client/src/settings/index.ts` — the bundle's `FEATURES`, the settings
file and doctor all read that one list — and call its factories in the bundle's `server.ts` /
`tui.ts`.
3. Add the directory to `PACKAGES` in `scripts/pack-check.ts` and to the publish loop in
Expand Down
1 change: 1 addition & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.13/schema.json",
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
"files": {
"includes": ["**", "!**/node_modules", "!**/dist", "!**/types", "!**/*.tsbuildinfo", "!site", "!media"]
},
Expand Down
3 changes: 3 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[test]
# Tests live in packages/; a worktree under .claude/ (an agent's) holds a second copy of them, and
# running both at once collides on the real daemons and terminals they start.
root = "packages"
# Tests run real PTYs and a real daemon; shared CI runners can be slow to spawn processes.
timeout = 20000
preload = ["./scripts/test-env.ts"]
48 changes: 22 additions & 26 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,64 +29,60 @@
"default": "./dist/feature.js"
},
"./host": {
"types": "./types/host.d.ts",
"default": "./dist/host.js"
"types": "./types/opencode/host/index.d.ts",
"default": "./dist/opencode/host/index.js"
},
"./server": {
"types": "./types/server.d.ts",
"default": "./dist/server.js"
"types": "./types/opencode/server/index.d.ts",
"default": "./dist/opencode/server/index.js"
},
"./log": {
"types": "./types/log.d.ts",
"default": "./dist/log.js"
},
"./sidebar": {
"types": "./types/sidebar.d.ts",
"default": "./dist/sidebar.js"
"types": "./types/opencode/sidebar.d.ts",
"default": "./dist/opencode/sidebar.js"
},
"./design": {
"types": "./types/design.d.ts",
"default": "./dist/design.js"
},
"./elements": {
"types": "./types/elements.d.ts",
"default": "./dist/elements.js"
},
"./settings": {
"types": "./types/settings.d.ts",
"default": "./dist/settings.js"
"types": "./types/settings/index.d.ts",
"default": "./dist/settings/index.js"
},
"./catalog": {
"types": "./types/catalog.d.ts",
"default": "./dist/catalog.js"
"types": "./types/settings/catalog.d.ts",
"default": "./dist/settings/catalog.js"
},
"./setup": {
"types": "./types/setup.d.ts",
"default": "./dist/setup.js"
"types": "./types/setup/index.d.ts",
"default": "./dist/setup/index.js"
},
"./brief": {
"types": "./types/brief.d.ts",
"default": "./dist/brief.js"
"types": "./types/setup/brief.d.ts",
"default": "./dist/setup/brief.js"
},
"./jsonc": {
"types": "./types/jsonc.d.ts",
"default": "./dist/jsonc.js"
"types": "./types/settings/jsonc.d.ts",
"default": "./dist/settings/jsonc.js"
},
"./plugin-entries": {
"types": "./types/plugin-entries.d.ts",
"default": "./dist/plugin-entries.js"
"types": "./types/settings/plugin-entries.d.ts",
"default": "./dist/settings/plugin-entries.js"
},
"./opener": {
"types": "./types/opener.d.ts",
"default": "./dist/opener.js"
},
"./checks": {
"types": "./types/checks.d.ts",
"default": "./dist/checks.js"
"types": "./types/settings/checks.d.ts",
"default": "./dist/settings/checks.js"
},
"./service": {
"types": "./types/service.d.ts",
"default": "./dist/service.js"
"types": "./types/opencode/service.d.ts",
"default": "./dist/opencode/service.js"
}
},
"files": [
Expand Down
13 changes: 7 additions & 6 deletions packages/client/skills/cockpit-setup/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: cockpit-setup
description: Set up opencode-cockpit ("Cockpit") with the user — which of its bays run, which show a block in OpenCode's sidebar, in what order, how quiet they are when empty — fix settings from before 0.9, and, when they want it, tune Cockpit to how they work (a tour of its keys and the project's conventions (dev server, ticket keys) written to AGENTS.md). Use it whenever the user runs /cockpit-setup or asks to configure, tidy or change Cockpit or its sidebar, even in passing - "make my sidebar quieter", "hide the shells block when it's empty", "move trail above subagents", "turn subagents off", "show trust in the sidebar", "configure cockpit", "tell cockpit our dev server is bun dev", "our tickets are COM-…", or a question about ~/.config/opencode-cockpit/config.json or .cockpit.json. To design what the Status line itself shows, use the status-setup skill instead.
description: Set up opencode-cockpit ("Cockpit") with the user — which of its bays run, which show a block in OpenCode's sidebar, in what order, how quiet they are when empty — fix settings it cannot read, and, when they want it, tune Cockpit to how they work (a tour of its keys and the project's conventions (dev server, ticket keys) written to AGENTS.md). Use it whenever the user runs /cockpit-setup or asks to configure, tidy or change Cockpit or its sidebar, even in passing - "make my sidebar quieter", "hide the shells block when it's empty", "move trail above subagents", "turn subagents off", "show trust in the sidebar", "configure cockpit", "tell cockpit our dev server is bun dev", "our tickets are COM-…", or a question about ~/.config/opencode-cockpit/config.json or .cockpit.json. To design what the Status line itself shows, use the status-setup skill instead.
---

# Setting up Cockpit
Expand All @@ -25,11 +25,12 @@ If the tool is not there, Cockpit's agent side is not loaded: say so, and point

## 2. Fix the notices first

If the tool lists notices, fix them before anything else, in the file each one names: move the value
to the new name and remove the old key (an old order number is just removed — the order is the
top-level `sidebar` list). These names are **not read**, so the value under each is doing nothing
today. Tell the person what you changed in one line each, e.g. `"statusline" → "status"`. Keep their
comments and every other key.
If the tool lists notices, fix them before anything else, in the file each one names. A key that is
not a setting is **not read**, so the value under it is doing nothing today: when the notice says
what was meant (`did you mean "status"?`), move the value there; otherwise ask the person. A value of
the wrong kind falls back to the default — write it in the kind the notice asks for. Tell the person
what you changed in one line each, e.g. `"statusline" → "status"`. Keep their comments and every
other key.

## 3. Offer a starting point

Expand Down
27 changes: 1 addition & 26 deletions packages/client/skills/cockpit-setup/references/settings.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Written by `bun packages/client/src/cli/reference.ts` from packages/client/src/catalog.ts. Do not edit by hand: a test fails when this file and the code disagree. -->
<!-- Written by `bun packages/client/src/cli/reference.ts` from packages/client/src/settings/catalog.ts. Do not edit by hand: a test fails when this file and the code disagree. -->

# Cockpit settings reference

Expand Down Expand Up @@ -121,28 +121,3 @@ Settings are read when OpenCode starts: a change applies after a restart.
| --- | --- | --- | --- |
| `enabled` | boolean | `true` | the bay runs at all, both halves. `false` turns it off entirely: no block, no commands, no tools |
| `updateCheck` | boolean | `true` | check for plugin updates once a day and say so |

## Names from before 0.9

Not read at all. Each one found is a notice in `cockpit_settings` and a `!` row in its bay. In the
same file, move the value to the new name and remove the old one:

| Old | New |
| --- | --- |
| `statusline` | `status` |
| `status.maxRows` | `status.sidebarRows` |
| `watch` | `shell.watch` |
| `kinds` | `shell.kinds` |
| `defaults` | `shell.defaults` |
| `lifecycle` | `shell.lifecycle` |
| `notify` | `shell.notify` |
| `guidance` | `shell.guidance` |
| `listRunningShells` | `shell.listRunningShells` |
| `ui.<key>` | `shell.<key>` |
| `ui.historyMinutes` | `shell.hideFinishedAfterMinutes` |
| `ui.updateCheck` | `updater.updateCheck` |
| `ui.sidebarOrder` | the top-level `sidebar` list (remove it) |
| `<bay>.sidebarOrder` | the top-level `sidebar` list (remove it) |
| `subagents.hideFinishedAfter` | `subagents.hideFinishedAfterMinutes` |
| `subagents.hideNestedAfter` | `subagents.hideNestedAfterSeconds` |
| Status keys at the file's root (`preset`, `segments`, `enabled`…) | the same keys under `status` |
6 changes: 3 additions & 3 deletions packages/client/src/cli/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

import { readFileSync } from "node:fs"
import { emptyBlock, GLYPH, type ToneRun } from "../design.ts"
import { loadSettings, noticeText, type SettingsNotice } from "../settings.ts"
import { settingsReport, settingsText } from "../setup.ts"
import { loadSettings, noticeText, type SettingsNotice } from "../settings/index.ts"
import { settingsReport, settingsText } from "../setup/index.ts"

const HEX: Record<string, string> = {
text: "#eeeeee",
Expand Down Expand Up @@ -54,7 +54,7 @@ const widths = arg("--width") ? [Number(arg("--width"))] : [24, 36]
const config = arg("--config")
const sample = {
statusline: { preset: "sidebar" },
shell: { sidebarOrder: 170 },
shell: { sidebar: [1] },
sidebar: ["status", "shells", "trust"],
}
const settings = loadSettings({
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/cli/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import { writeFileSync } from "node:fs"
import { join } from "node:path"
import { settingsReference } from "../catalog.ts"
import { SETUP_SKILL_DIR } from "../setup.ts"
import { settingsReference } from "../settings/catalog.ts"
import { SETUP_SKILL_DIR } from "../setup/index.ts"

const file = join(SETUP_SKILL_DIR, "references", "settings.md")
writeFileSync(file, settingsReference())
Expand Down
Loading
Loading