catherd-cli 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +114 -30
  2. package/THIRD_PARTY_NOTICES.md +37 -0
  3. package/catalog/jev.json +89 -0
  4. package/catalog/models.json +236 -0
  5. package/catalog/scores.json +366 -0
  6. package/package.json +24 -8
  7. package/plugin/.claude-plugin/plugin.json +2 -2
  8. package/plugin/.mcp.json +1 -1
  9. package/plugin/commands/catherd.md +1 -1
  10. package/plugin/skills/catherd/SKILL.md +97 -51
  11. package/plugin/skills/catherd-setup/SKILL.md +34 -24
  12. package/src/adapters/all.ts +8 -0
  13. package/src/adapters/backend.ts +144 -0
  14. package/src/adapters/claude-code/events.ts +86 -0
  15. package/src/adapters/claude-code/index.ts +223 -0
  16. package/src/adapters/claude-code/models-api.ts +65 -0
  17. package/src/adapters/claude-code/models.ts +26 -0
  18. package/src/adapters/cli.ts +74 -0
  19. package/src/adapters/codex/events.ts +65 -0
  20. package/src/adapters/codex/home.ts +47 -0
  21. package/src/adapters/codex/index.ts +227 -0
  22. package/src/adapters/discovery.ts +87 -0
  23. package/src/adapters/opencode/agents.ts +84 -0
  24. package/src/adapters/opencode/events.ts +109 -0
  25. package/src/adapters/opencode/index.ts +316 -0
  26. package/src/adapters/registry.ts +14 -0
  27. package/src/cli.ts +159 -19
  28. package/src/domain/agents.ts +60 -0
  29. package/src/domain/budget.ts +45 -0
  30. package/src/domain/catalog.ts +262 -0
  31. package/src/domain/changes.ts +52 -0
  32. package/src/domain/cost.ts +89 -0
  33. package/src/domain/errors.ts +58 -0
  34. package/src/domain/hints.ts +22 -0
  35. package/src/domain/ids.ts +97 -0
  36. package/src/domain/jev.ts +283 -0
  37. package/src/domain/lane.ts +69 -0
  38. package/src/domain/profile-rules.ts +205 -0
  39. package/src/domain/profile.ts +383 -0
  40. package/src/domain/record.ts +84 -0
  41. package/src/{profile → domain}/role-prompts.ts +42 -25
  42. package/src/domain/roles.ts +25 -0
  43. package/src/domain/route.ts +126 -0
  44. package/src/domain/runtime.ts +21 -0
  45. package/src/domain/sanitize.ts +29 -0
  46. package/src/domain/secrets.ts +57 -0
  47. package/src/domain/select.ts +136 -0
  48. package/src/domain/state.ts +33 -0
  49. package/src/domain/util.ts +18 -0
  50. package/src/entry/capture-fixtures-command.ts +57 -0
  51. package/src/entry/catalog-command.ts +106 -0
  52. package/src/entry/cli-kit.ts +36 -0
  53. package/src/entry/deps.ts +16 -0
  54. package/src/entry/doctor-command.ts +45 -0
  55. package/src/entry/glyphs.ts +33 -0
  56. package/src/entry/init-command.ts +142 -0
  57. package/src/entry/lock-command.ts +123 -0
  58. package/src/entry/mcp/dispatch-tools.ts +82 -0
  59. package/src/entry/mcp/handshake.ts +48 -0
  60. package/src/entry/mcp/lane-tools.ts +83 -0
  61. package/src/entry/mcp/result.ts +51 -0
  62. package/src/entry/mcp/run-tools.ts +144 -0
  63. package/src/entry/mcp/server.ts +72 -0
  64. package/src/entry/mcp/setup-tools.ts +81 -0
  65. package/src/entry/profile-command.ts +320 -0
  66. package/src/entry/prompt.ts +103 -0
  67. package/src/entry/runs-command.ts +217 -0
  68. package/src/entry/supervise-bin.ts +18 -0
  69. package/src/entry/supervise-command.ts +37 -0
  70. package/src/entry/tui/commands.ts +545 -0
  71. package/src/entry/tui/effects.ts +270 -0
  72. package/src/entry/tui/fixtures.ts +318 -0
  73. package/src/entry/tui/profile-edits.ts +138 -0
  74. package/src/entry/tui/profile-tree.ts +419 -0
  75. package/src/entry/tui/providers/app.tsx +162 -0
  76. package/src/entry/tui/providers/boundary.tsx +57 -0
  77. package/src/entry/tui/providers/data.tsx +133 -0
  78. package/src/entry/tui/providers/keymap.tsx +166 -0
  79. package/src/entry/tui/providers/root.tsx +45 -0
  80. package/src/entry/tui/providers/theme.tsx +17 -0
  81. package/src/entry/tui/providers/toast.tsx +77 -0
  82. package/src/entry/tui/run.tsx +98 -0
  83. package/src/entry/tui/state.ts +336 -0
  84. package/src/entry/tui/stories.ts +75 -0
  85. package/src/entry/tui/text.ts +118 -0
  86. package/src/entry/tui/theme.ts +139 -0
  87. package/src/entry/tui/views/app.tsx +208 -0
  88. package/src/entry/tui/views/dialogs.tsx +41 -0
  89. package/src/entry/tui/views/profile-actions.ts +321 -0
  90. package/src/entry/tui/views/profiles.tsx +440 -0
  91. package/src/entry/tui/views/runs.tsx +281 -0
  92. package/src/entry/tui/views/save-dialog.tsx +332 -0
  93. package/src/entry/tui/views/status.tsx +206 -0
  94. package/src/entry/tui/widgets/chrome.tsx +114 -0
  95. package/src/entry/tui/widgets/dialog-confirm.tsx +58 -0
  96. package/src/entry/tui/widgets/dialog-prompt.tsx +52 -0
  97. package/src/entry/tui/widgets/dialog-select.tsx +212 -0
  98. package/src/entry/tui/widgets/dialog.tsx +68 -0
  99. package/src/entry/tui/widgets/line.tsx +92 -0
  100. package/src/entry/tui/widgets/list.tsx +196 -0
  101. package/src/entry/tui/widgets/spinner.tsx +49 -0
  102. package/src/entry/tui/widgets/toast.tsx +62 -0
  103. package/src/infra/assets.ts +4 -0
  104. package/src/infra/dispatch-dir.ts +278 -0
  105. package/src/infra/env.ts +43 -0
  106. package/src/infra/filelock.ts +159 -0
  107. package/src/infra/git.ts +91 -0
  108. package/src/infra/heavy-lock.ts +36 -0
  109. package/src/infra/jev-client.ts +162 -0
  110. package/src/infra/launch.ts +25 -0
  111. package/src/infra/log.ts +84 -0
  112. package/src/infra/paths.ts +38 -0
  113. package/src/infra/proc.ts +110 -0
  114. package/src/infra/store.ts +229 -0
  115. package/src/infra/supervisor.ts +257 -0
  116. package/src/infra/version.ts +6 -0
  117. package/src/services/admission.ts +277 -0
  118. package/src/services/agent-links.ts +139 -0
  119. package/src/services/backends.ts +44 -0
  120. package/src/services/budget.ts +47 -0
  121. package/src/services/capture.ts +233 -0
  122. package/src/services/catalog-service.ts +382 -0
  123. package/src/services/dispatch-service.ts +479 -0
  124. package/src/services/dispatches.ts +145 -0
  125. package/src/services/doctor-backends.ts +185 -0
  126. package/src/services/doctor-checks.ts +103 -0
  127. package/src/services/doctor.ts +358 -0
  128. package/src/services/finalize.ts +359 -0
  129. package/src/services/jev-service.ts +183 -0
  130. package/src/services/lane-service.ts +248 -0
  131. package/src/services/ports.ts +132 -0
  132. package/src/services/preflight.ts +207 -0
  133. package/src/services/profile-service.ts +292 -0
  134. package/src/services/profile-store.ts +141 -0
  135. package/src/services/reconcile.ts +101 -0
  136. package/src/services/routing-service.ts +190 -0
  137. package/src/services/run-debug.ts +79 -0
  138. package/src/services/run-service.ts +161 -0
  139. package/src/services/run-store.ts +316 -0
  140. package/src/services/setup.ts +87 -0
  141. package/src/services/state.ts +104 -0
  142. package/src/services/summary.ts +227 -0
  143. package/catalog/catalog.json +0 -112
  144. package/catalog/models-dev.json +0 -56453
  145. package/src/core/codex-events.ts +0 -49
  146. package/src/core/codex.ts +0 -166
  147. package/src/core/harness.ts +0 -89
  148. package/src/core/lanes.ts +0 -67
  149. package/src/core/lock.ts +0 -111
  150. package/src/core/opencode.ts +0 -207
  151. package/src/core/reconcile.ts +0 -26
  152. package/src/core/reply.ts +0 -54
  153. package/src/core/runstore.ts +0 -163
  154. package/src/core/spawn.ts +0 -89
  155. package/src/core/status.ts +0 -193
  156. package/src/files.ts +0 -19
  157. package/src/mcp/dispatch.ts +0 -154
  158. package/src/mcp/lane-tools.ts +0 -200
  159. package/src/mcp/out.ts +0 -6
  160. package/src/mcp/preflight.ts +0 -69
  161. package/src/mcp/run-tools.ts +0 -121
  162. package/src/mcp/runs.ts +0 -118
  163. package/src/mcp/server.ts +0 -26
  164. package/src/mcp/setup-tools.ts +0 -175
  165. package/src/paths.ts +0 -20
  166. package/src/profile/agents.ts +0 -130
  167. package/src/profile/profile.ts +0 -228
  168. package/src/routing/catalog.ts +0 -227
  169. package/src/routing/commands.ts +0 -22
  170. package/src/routing/jev.ts +0 -185
  171. package/src/routing/route.ts +0 -155
  172. package/src/routing/select.ts +0 -90
  173. package/src/tui/backends.ts +0 -57
  174. package/src/tui/commands.ts +0 -53
  175. package/src/tui/dashboard.tsx +0 -245
  176. package/src/tui/editor.tsx +0 -214
  177. package/src/tui/init.tsx +0 -208
  178. package/src/tui/matrix-model.ts +0 -279
  179. package/src/tui/matrix.tsx +0 -512
  180. package/src/tui/profiles.ts +0 -38
  181. package/src/tui/theme.ts +0 -177
  182. package/src/tui/ui.tsx +0 -267
  183. package/src/tui/watch-model.ts +0 -83
  184. package/src/tui/watch.tsx +0 -236
  185. package/src/types.ts +0 -184
  186. package/src/version.ts +0 -7
  187. /package/src/{mcp/commands.ts → entry/mcp/command.ts} +0 -0
package/README.md CHANGED
@@ -6,27 +6,34 @@
6
6
  (")(")
7
7
  ```
8
8
 
9
- Autopilot builds from your own Claude Code session. Claude plans and verifies, Codex and opencode
10
- workers write the code, and [Jev](https://typesafe.ai) picks the model and effort for each piece
9
+ Autopilot builds from your own Claude Code session. Claude plans and verifies, Codex, opencode or
10
+ headless Claude Code workers write the code, and [Jev](https://typesafe.ai) picks the model and effort for each piece
11
11
  of work, climbing a ladder only when a cheaper rung falls short.
12
12
 
13
13
  - **Your harness, as you set it up.** Every role runs in its vendor's own CLI with your config,
14
14
  hooks, skills and `AGENTS.md`. Isolation is an opt-in toggle per profile and harness, for when
15
15
  you'd rather save the tokens your customizations cost.
16
- - **Claude roles stay native.** Claude models run as ordinary Claude Code subagents; Codex and
17
- opencode run through catherd's MCP server.
16
+ - **Claude roles stay native.** `claude:` rungs run as ordinary Claude Code subagents; Codex,
17
+ opencode and headless `claude-code:` rungs run through catherd's MCP server.
18
18
  - **Survives restarts.** Workers are detached processes writing straight to disk, so a dropped
19
19
  MCP server never loses a run.
20
- - **Guard rails for autopilot.** Quota failover to another backend, a preflight check before any
20
+ - **Guard rails for autopilot.** Quota failover to a rung on another quota, a preflight check before any
21
21
  worker starts, per-repo knowledge carried between runs, and a run budget.
22
22
 
23
23
  ## Requirements
24
24
 
25
25
  - [Bun](https://bun.sh) ≥ 1.4
26
26
  - [Claude Code](https://claude.com/claude-code) (desktop app or CLI)
27
- - At least one worker backend: [Codex CLI](https://github.com/openai/codex) and/or
28
- [opencode](https://opencode.ai), logged in
29
- - A TypeSafe API key for Jev, in `TYPESAFE_API_KEY` or `~/.config/typesafe/api_key`
27
+ - At least one worker backend, logged in:
28
+ - [Codex CLI](https://github.com/openai/codex) 0.157.0 or newer
29
+ - [opencode](https://opencode.ai) **v2**, 2.0.16 or newer: `curl -fsSL https://opencode.ai/v2/install | bash`
30
+ (the npm package `opencode-ai` is v1 and is not supported)
31
+ - Claude Code's `claude` CLI 2.1.282 or newer, for headless `claude-code:` rungs
32
+ - Optional: a TypeSafe API key for Jev, in `TYPESAFE_API_KEY` or saved by `catherd init`
33
+
34
+ `catherd doctor` checks each backend's version and login and prints the fix for anything missing. The default
35
+ profile runs its workers on Codex; without Codex, doctor's fix also names how to move those roles to a backend
36
+ you have (`/catherd-setup` in Claude Code, or `catherd profile set roles.<role>.rungs <rung>`).
30
37
 
31
38
  ## Install
32
39
 
@@ -34,15 +41,18 @@ of work, climbing a ladder only when a cheaper rung falls short.
34
41
  bunx catherd-cli init
35
42
  ```
36
43
 
37
- The npm package is `catherd-cli`; the command it installs is `catherd`. `init` asks for the Jev key, finds your backends, and builds your first profile. Then add the
38
- plugin to Claude Code:
44
+ The npm package is `catherd-cli`; the command it installs is `catherd`. `init` asks for the optional Jev key,
45
+ writes the default profile and links its Claude agents, lists your backends' models, and ends with a readiness
46
+ report (`--no-input` asks nothing and keeps what exists; `--profile <name>` sets up and activates that profile
47
+ instead of `default`; piped, it reads one answer per line once stdin closes: the Jev key, the profile, whether to replace it, each on its own line even when a question is skipped). Then add the plugin to Claude Code:
39
48
 
40
49
  ```sh
41
50
  claude plugin marketplace add 47vigen/catherd
42
51
  claude plugin install catherd@catherd
43
52
  ```
44
53
 
45
- Start a new Claude Code session so the plugin, its MCP server and the agent files load.
54
+ Start a new Claude Code session so the plugin, its MCP server and the agent files load, then check with
55
+ `bunx catherd-cli doctor`.
46
56
 
47
57
  ## Use
48
58
 
@@ -54,29 +64,103 @@ In Claude Code:
54
64
 
55
65
  In a terminal:
56
66
 
57
- | Command | What it does |
58
- | ---------------------------------- | ---------------------------------------------------------------- |
59
- | `bunx catherd-cli` | Profile editor: models and efforts per role, with paw checkboxes |
60
- | `bunx catherd-cli watch` | Live view of running and recent runs |
61
- | `bunx catherd-cli lock -- <cmd>` | Runs a heavy command behind the machine-wide semaphore |
62
- | `bunx catherd-cli catalog refresh` | Refreshes the models.dev snapshot |
63
-
64
- `--plain` and `--reduced-motion` work everywhere.
67
+ | Command | What it does |
68
+ | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
69
+ | `catherd` | The dashboard: Status, Profiles and Runs (below) |
70
+ | `catherd init [--no-input] [--profile <p>]` | First-run setup |
71
+ | `catherd doctor [--json]` | Readiness report, one row per check with its fix; exits 3 when not ready |
72
+ | `catherd profile list\|show\|use [--repo]\|new [--from <p>]\|copy\|rm\|diff\|validate` | Profiles; `use --repo` binds one to the repo you are in |
73
+ | `catherd profile use --repo --clear` | Unbinds the repo you are in; it runs on the active profile again |
74
+ | `catherd profile set <path> <value> [--profile <p>]` | One field, e.g. `roles.verifier.access read-only`, `budget.usd 20` |
75
+ | `catherd status [run]`, `catherd watch [--once] [--interval <s>]` | Where runs stand |
76
+ | `catherd runs list [--repo <path>]\|show <id> [--debug [--name <n>]]\|cancel <id> <name>` | Past runs; `--debug` adds exit.json and the stderr and event tails, `--name` one role's |
77
+ | `catherd catalog refresh\|list [--backend <b>] [--role <r>] [--text <t>] [--scored]` | The models catherd can place, filtered |
78
+ | `catherd catalog treat-like <rung> <like>` | Scores an unscored rung as a scored one |
79
+ | `catherd lock [--slots N] -- <cmd>` | Runs a heavy command behind the machine-wide semaphore, in its own session (no /dev/tty) |
80
+ | `catherd mcp` | The MCP server on stdio; the plugin starts it, you never need to |
81
+ | `catherd capture-fixtures [--backend <b>] [--out <dir>]` | Contributors: records sanitized test fixtures from real runs (see CONTRIBUTING.md) |
82
+
83
+ A profile command without a profile name (`show`, `set`, `diff`, `validate`), like the MCP profile tools, acts
84
+ on the profile the repo you are in runs on: the one bound to it, else the active one. Run them as
85
+ `bunx catherd-cli <command>` when catherd is not installed globally. Every read command takes `--json`; a bare `catherd runs` is `catherd runs list`. Exit codes: 0 ok, 1 error, 2 usage, 3 not ready, 130 interrupted; an error prints
86
+ `error E_CODE: message` and a `fix:` line. `--verbose` (or `CATHERD_LOG=debug`) logs more to
87
+ `~/.local/share/catherd/logs/`, kept for 7 days with secrets redacted. The dashboard takes `--plain` (ASCII, no colour)
88
+ and `--reduced-motion`; `doctor` and `init` take `--plain` for ASCII glyphs too. `NO_COLOR` drops colour, never glyphs.
65
89
 
66
90
  Run data lives in `~/.local/share/catherd/`, config in `~/.config/catherd/` (both follow
67
91
  `XDG_*`).
68
92
 
69
- ## Develop
70
-
71
- ```sh
72
- bun install
73
- bun test
74
- bun run typecheck && bun run lint && bun run format:check
75
- ```
76
-
77
- Design: [`docs/specs/2026-09-24-catherd-design.md`](docs/specs/2026-09-24-catherd-design.md).
78
- Releases go through [Changesets](https://github.com/changesets/changesets): add one with
79
- `bunx changeset`.
93
+ ### Environment variables
94
+
95
+ | Variable | What it does |
96
+ | --------------------------- | ----------------------------------------------------------------------------------------------------- |
97
+ | `TYPESAFE_API_KEY` | The Jev key, instead of the one `catherd init` saves |
98
+ | `CATHERD_HOME` | Puts config and data under `$CATHERD_HOME/config` and `$CATHERD_HOME/data` instead of XDG |
99
+ | `CATHERD_LOG` | Log level: `off`, `error`, `warn`, `info` (default) or `debug` (what `--verbose` sets) |
100
+ | `CATHERD_LOCK_SLOTS` | `catherd lock`'s slot count when `--slots` is not given (before the profile's `lock.heavy`) |
101
+ | `CATHERD_REDUCED_MOTION` | Any value: the dashboard's `--reduced-motion` |
102
+ | `CATHERD_NO_KITTY` | Any value: turns off the kitty keyboard protocol in the dashboard, for terminals it breaks |
103
+ | `CATHERD_CLAUDE_AGENTS_DIR` | Where catherd links its Claude agents (default: `$CLAUDE_CONFIG_DIR/agents`, else `~/.claude/agents`) |
104
+ | `NO_COLOR` | Drops colour (the dashboard's and `--help`'s; piped `--help` has none either) |
105
+
106
+ For development only: `CATHERD_STORY=1` opens the dashboard's storybook, `CATHERD_TICK_MS` sets how often a blocked
107
+ `wait` reports progress (default 30000), and `CATHERD_LIVE=1` enables the live tests
108
+ (CONTRIBUTING.md has the rest).
109
+
110
+ ### The dashboard
111
+
112
+ `catherd` opens three tabs: **1 Status** (every check with its fix; `y` copies the fix, `r` checks again),
113
+ **2 Profiles** (one tree per profile: roles with their access, default rung, models and efforts, then routing,
114
+ harness, budget, failover, timeouts and notify) and **3 Runs** (live roles, climbs, routes, the budget, landed
115
+ milestones; `p` pauses). `catherd watch` opens it on Runs.
116
+
117
+ - `ctrl+p` lists every command with its key and CLI twin; `?` lists the keys that work where you are.
118
+ - `ctrl+x` is the leader: `ctrl+x 1`–`3` tabs, `ctrl+x n` new profile, `ctrl+x l` profiles, `ctrl+x u` and
119
+ `ctrl+x r` undo and redo, `ctrl+x q` quit.
120
+ - Lists: arrows or `j`/`k`, `pgup`/`pgdn`, `home`/`g`, `end`/`G`, `/` to filter; `space` ticks, `enter`
121
+ changes or opens, `→`/`←` expand and collapse.
122
+ - Edits are staged: nothing is written until `ctrl+s` shows the diff and you choose Save or Save & make active.
123
+ `enter` never saves.
124
+ - Inside a repo bound to a profile, the dashboard opens on that profile, and making a profile active binds the
125
+ repo to it (as `catherd profile use <name> --repo`).
126
+ - `esc` backs out one level and never quits. `q` quits, asking first if something is unsaved; `ctrl+c` quits
127
+ when nothing is, and pressed twice within 1.5 s discards and exits 130.
128
+ - Deleting a profile or cancelling a live role takes `ctrl+d` twice.
129
+ - `--plain` draws ASCII without colour, `NO_COLOR` drops the colour, `--reduced-motion` stops the spinner.
130
+ - Rebind a key in `~/.config/catherd/config.json`: `"keybinds": { "profile.save": "ctrl+w", "app.help": "none" }`
131
+ (the palette shows each command by title; the ids are listed in
132
+ [`src/entry/tui/commands.ts`](src/entry/tui/commands.ts)).
133
+
134
+ ## Upgrading from 0.x
135
+
136
+ 1.0 is a clean break: run `bunx catherd-cli init` once. It moves your 0.x `config.json`, `projects.json` and
137
+ profiles into a `0.x-backup-<time>/` folder next to them (it never reads or deletes them), writes the 1.0
138
+ default profile, replaces the 0.x Claude agent links with 1.0 ones and keeps your saved Jev key; 0.x run
139
+ folders stay where they are, unread. Then update the plugin
140
+ (`claude plugin marketplace update catherd && claude plugin update catherd@catherd`) and start a new Claude
141
+ Code session. The details are in [MIGRATION.md](MIGRATION.md).
142
+
143
+ ## Docs
144
+
145
+ | Where | What |
146
+ | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
147
+ | [MIGRATION.md](MIGRATION.md) | Upgrading from 0.x |
148
+ | [CHANGELOG.md](CHANGELOG.md) | Releases |
149
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | Development setup, the checks, commits, changesets, live tests |
150
+ | [SECURITY.md](SECURITY.md) | Reporting a vulnerability; what catherd stores and how |
151
+ | [`docs/superpowers/specs/2026-09-25-catherd-1.0-design.md`](docs/superpowers/specs/2026-09-25-catherd-1.0-design.md) | The 1.0 design (binding) |
152
+ | [`docs/dev/`](docs/dev/) | Maintainer docs: live verification, manual tests, dependencies, ideas |
153
+ | [`docs/dev/live-verification.md`](docs/dev/live-verification.md) | What CI cannot run: live tests, fixture capture, the Codex sandbox |
154
+ | [`docs/tui-frames.md`](docs/tui-frames.md) | Every dashboard screen as text (generated, checked in CI) |
155
+ | [`docs/superpowers/`](docs/superpowers/), [`docs/research/`](docs/research/) | How 1.0 was designed and built: plans, reviews, research |
156
+ | [`docs/archive/0.x/`](docs/archive/0.x/) | The 0.x design and plans, for history |
157
+
158
+ ## Contributing
159
+
160
+ See [CONTRIBUTING.md](CONTRIBUTING.md). CI runs the checks on Linux and macOS, on Bun 1.4.0 and the latest Bun;
161
+ what CI cannot run is in [`docs/dev/live-verification.md`](docs/dev/live-verification.md). Report security issues
162
+ privately, as [SECURITY.md](SECURITY.md) describes. Everyone taking part follows the
163
+ [Code of Conduct](CODE_OF_CONDUCT.md).
80
164
 
81
165
  ## License
82
166
 
@@ -0,0 +1,37 @@
1
+ # Third-party notices
2
+
3
+ catherd's TUI adapts code and designs from opencode (<https://github.com/anomalyco/opencode>), used under
4
+ the MIT license below. Each derived file says so in its first lines:
5
+
6
+ - `src/entry/tui/commands.ts`: command ids and default keys (`packages/tui/src/config/keybind.ts`)
7
+ - `src/entry/tui/providers/keymap.tsx`: the keymap setup (`packages/tui/src/context/keymap.tsx`)
8
+ - `src/entry/tui/providers/toast.tsx` and `src/entry/tui/widgets/toast.tsx`: toasts (`packages/tui/src/ui/toast.tsx`)
9
+ - `src/entry/tui/widgets/dialog.tsx`: the dialog panel (`packages/tui/src/ui/dialog.tsx`)
10
+ - `src/entry/tui/widgets/dialog-select.tsx`: the picker (`packages/tui/src/ui/dialog-select.tsx`)
11
+ - `src/entry/tui/widgets/dialog-confirm.tsx`: confirmations (`packages/tui/src/ui/dialog-confirm.tsx`)
12
+ - `src/entry/tui/widgets/dialog-prompt.tsx`: value editors (`packages/tui/src/ui/dialog-prompt.tsx`)
13
+ - `src/entry/tui/widgets/spinner.tsx`: the spinner and its delayed presence (`packages/tui/src/component/spinner.tsx`, `startup-loading.tsx`)
14
+
15
+ ## opencode
16
+
17
+ MIT License
18
+
19
+ Copyright (c) 2025 opencode
20
+
21
+ Permission is hereby granted, free of charge, to any person obtaining a copy
22
+ of this software and associated documentation files (the "Software"), to deal
23
+ in the Software without restriction, including without limitation the rights
24
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
+ copies of the Software, and to permit persons to whom the Software is
26
+ furnished to do so, subject to the following conditions:
27
+
28
+ The above copyright notice and this permission notice shall be included in all
29
+ copies or substantial portions of the Software.
30
+
31
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
+ SOFTWARE.
@@ -0,0 +1,89 @@
1
+ {
2
+ "schema": 1,
3
+ "model": "jev-1.13.0",
4
+ "sets": {
5
+ "route-v2": {
6
+ "questions": {
7
+ "kind": {
8
+ "type": "choice",
9
+ "instructions": "What kind of work does the lane in the state describe?",
10
+ "criteria": {
11
+ "repo_code": "Code and tests inside an application or library repository",
12
+ "terminal": "Shell, build, CI, infrastructure or environment work, where the terminal is the main tool",
13
+ "ui": "User-interface work judged on screen: layout, styling, components",
14
+ "prose": "Writing that is not code: docs, a changelog, release notes, a merge request body",
15
+ "research": "Finding facts to answer a question, with no change to the product",
16
+ "other": "None of the above"
17
+ }
18
+ },
19
+ "difficulty": {
20
+ "type": "score",
21
+ "instructions": "Which situation matches the work the lane in the state asks for?",
22
+ "criteria": [
23
+ "A mechanical change: rename, move, delete or copy existing code, or change constants, with no new behaviour",
24
+ "New code that follows an existing example which the lane names or the repository already has",
25
+ "New logic with state, concurrency, data invariants or tricky edge cases",
26
+ "A cause nobody has found yet, a design across systems to settle, or no example to follow"
27
+ ]
28
+ },
29
+ "names_pattern": {
30
+ "type": "noul",
31
+ "instructions": "Does the lane in the state name an existing file, function, endpoint or test in the repository that the new work should copy or follow?",
32
+ "criteria": {
33
+ "true": "It names a concrete existing example by path or name",
34
+ "false": "It names no existing example, or only says to follow conventions in general"
35
+ }
36
+ },
37
+ "mechanical": {
38
+ "type": "noul",
39
+ "instructions": "Is the work in the lane in the state only mechanical: renaming, moving, deleting or copying code, or changing constants, with no new behaviour?"
40
+ },
41
+ "shared_state": {
42
+ "type": "noul",
43
+ "instructions": "Does the work in the lane in the state involve concurrency, caching, shared mutable state, transactions, or the ordering of events?"
44
+ },
45
+ "unclear_cause": {
46
+ "type": "noul",
47
+ "instructions": "Does the lane in the state ask the worker to find the cause of a bug or failure that the lane does not already explain?"
48
+ },
49
+ "open_design": {
50
+ "type": "noul",
51
+ "instructions": "Does the lane in the state leave an interface, data shape or algorithm for the worker to decide?"
52
+ },
53
+ "cross_boundary": {
54
+ "type": "noul",
55
+ "instructions": "Must the work in the lane in the state keep two or more services, processes or data stores consistent, such as a schema migration together with the code that reads it?"
56
+ },
57
+ "outside_repo": {
58
+ "type": "noul",
59
+ "instructions": "Does the work in the lane in the state depend on something outside the repository: a running service, credentials, network access, hardware or CI configuration?"
60
+ }
61
+ },
62
+ "rule": { "kindMin": 0.8, "trackMin": 0.8, "trackA": ["0", "1"], "trackB": ["2", "3"] }
63
+ },
64
+ "finding": {
65
+ "questions": {
66
+ "finding": {
67
+ "type": "choice",
68
+ "instructions": "A reviewer reported `finding` on the work planned in `lane`. Where is the defect?",
69
+ "criteria": {
70
+ "design": "The plan itself is wrong: its decisions, signatures or data shapes cannot meet the goal",
71
+ "code": "The plan is sound and the code does not implement it correctly",
72
+ "unclear": "The finding does not say enough to tell"
73
+ }
74
+ }
75
+ },
76
+ "rule": { "min": 0.83, "fallback": "code" }
77
+ },
78
+ "same-defect": {
79
+ "questions": {
80
+ "same-defect": {
81
+ "type": "choice",
82
+ "instructions": "Does `after` report the same underlying defect as `before`, even if worded differently or at another line?",
83
+ "criteria": { "yes": "Same underlying defect", "no": "A different defect" }
84
+ }
85
+ },
86
+ "rule": { "min": 0.85, "fallback": "no" }
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,236 @@
1
+ {
2
+ "schema": 1,
3
+ "version": "2026-09-25",
4
+ "sources": {
5
+ "claude": "https://platform.claude.com/docs/en/models/overview (2026-09-25); efforts https://platform.claude.com/docs/en/build-with-claude/effort; prices https://platform.claude.com/docs/en/about-claude/pricing",
6
+ "codex": "codex debug models --bundled, Codex CLI 0.157.0 (2026-09-25); prices https://developers.openai.com/api/docs/pricing; plan weights https://learn.chatgpt.com/docs/pricing",
7
+ "opencode": "opencode models <provider> --verbose on 1.18.32 and the v2 model.list (2026-09-25); https://opencode.ai/docs/zen, https://opencode.ai/docs/go"
8
+ },
9
+ "backends": {
10
+ "codex": {
11
+ "imageGen": {
12
+ "tool": "gpt-image-2",
13
+ "requires": "chatgpt-login",
14
+ "source": "https://learn.chatgpt.com/docs/image-generation"
15
+ }
16
+ }
17
+ },
18
+ "families": [
19
+ {
20
+ "id": "gpt-6-astra",
21
+ "name": "GPT-6 Astra",
22
+ "vendor": "openai",
23
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
24
+ "price": { "input": 10, "cached": 1, "output": 50 },
25
+ "planWeight": 60,
26
+ "on": {
27
+ "codex": {
28
+ "id": "gpt-6-astra",
29
+ "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"],
30
+ "context": 272000
31
+ },
32
+ "opencode": {
33
+ "id": "opencode/gpt-6-astra",
34
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
35
+ "context": 1050000
36
+ }
37
+ },
38
+ "notes": {
39
+ "ultra": "maximum reasoning with automatic task delegation to parallel subagents; never in a default ladder"
40
+ }
41
+ },
42
+ {
43
+ "id": "gpt-6-sol",
44
+ "name": "GPT-6 Sol",
45
+ "vendor": "openai",
46
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
47
+ "price": { "input": 2, "cached": 0.2, "output": 10 },
48
+ "planWeight": 20,
49
+ "on": {
50
+ "codex": {
51
+ "id": "gpt-6-sol",
52
+ "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"],
53
+ "context": 272000
54
+ },
55
+ "opencode": {
56
+ "id": "opencode/gpt-6-sol",
57
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
58
+ "context": 1050000
59
+ }
60
+ },
61
+ "notes": {
62
+ "ultra": "maximum reasoning with automatic task delegation to parallel subagents; never in a default ladder"
63
+ }
64
+ },
65
+ {
66
+ "id": "gpt-6-luna",
67
+ "name": "GPT-6 Luna",
68
+ "vendor": "openai",
69
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
70
+ "price": { "input": 0.1, "cached": 0.01, "output": 0.5 },
71
+ "planWeight": 1,
72
+ "on": {
73
+ "codex": {
74
+ "id": "gpt-6-luna",
75
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
76
+ "context": 272000
77
+ },
78
+ "opencode": {
79
+ "id": "opencode/gpt-6-luna",
80
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
81
+ "context": 1050000
82
+ },
83
+ "opencode-go": {
84
+ "id": "opencode-go/gpt-6-luna",
85
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
86
+ "context": 1050000
87
+ }
88
+ }
89
+ },
90
+ {
91
+ "id": "gpt-5.6-sol",
92
+ "name": "GPT-5.6 Sol",
93
+ "vendor": "openai",
94
+ "status": "legacy",
95
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
96
+ "price": { "input": 4, "cached": 0.4, "output": 20 },
97
+ "planWeight": 30,
98
+ "on": {
99
+ "codex": {
100
+ "id": "gpt-5.6-sol",
101
+ "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"],
102
+ "context": 272000
103
+ },
104
+ "opencode": {
105
+ "id": "opencode/gpt-5.6-sol",
106
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
107
+ "context": 1050000
108
+ }
109
+ },
110
+ "notes": { "upgrade": "Codex offers gpt-6-sol as its upgrade" }
111
+ },
112
+ {
113
+ "id": "gpt-5.6-terra",
114
+ "name": "GPT-5.6 Terra",
115
+ "vendor": "openai",
116
+ "status": "legacy",
117
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
118
+ "price": { "input": 2, "cached": 0.2, "output": 12 },
119
+ "planWeight": 15,
120
+ "on": {
121
+ "codex": {
122
+ "id": "gpt-5.6-terra",
123
+ "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"],
124
+ "context": 272000
125
+ },
126
+ "opencode": {
127
+ "id": "opencode/gpt-5.6-terra",
128
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
129
+ "context": 1050000
130
+ }
131
+ },
132
+ "notes": { "upgrade": "Codex offers gpt-6-sol as its upgrade" }
133
+ },
134
+ {
135
+ "id": "gpt-5.6-luna",
136
+ "name": "GPT-5.6 Luna",
137
+ "vendor": "openai",
138
+ "status": "legacy",
139
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
140
+ "price": { "input": 0.2, "cached": 0.02, "output": 1.2 },
141
+ "planWeight": 1.5,
142
+ "on": {
143
+ "codex": {
144
+ "id": "gpt-5.6-luna",
145
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
146
+ "context": 272000
147
+ },
148
+ "opencode": {
149
+ "id": "opencode/gpt-5.6-luna",
150
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
151
+ "context": 1050000
152
+ },
153
+ "opencode-go": {
154
+ "id": "opencode-go/gpt-5.6-luna",
155
+ "efforts": ["none", "low", "medium", "high", "xhigh", "max"],
156
+ "context": 1050000
157
+ }
158
+ },
159
+ "notes": { "upgrade": "Codex offers gpt-6-luna as its upgrade" }
160
+ },
161
+ {
162
+ "id": "claude-fable-5-1",
163
+ "name": "Claude Fable 5.1",
164
+ "vendor": "anthropic",
165
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
166
+ "price": { "input": 10, "cached": 0.25, "output": 50 },
167
+ "meteredOnPlan": true,
168
+ "on": {
169
+ "claude-code": {
170
+ "id": "claude-fable-5-1",
171
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
172
+ "context": 1000000
173
+ },
174
+ "opencode": {
175
+ "id": "opencode/claude-fable-5-1",
176
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
177
+ "context": 1000000
178
+ }
179
+ },
180
+ "notes": {
181
+ "plan": "Pro and Team Standard pay usage credits for Fable; Max includes it up to half the weekly limit"
182
+ }
183
+ },
184
+ {
185
+ "id": "claude-opus-5-5",
186
+ "name": "Claude Opus 5.5",
187
+ "vendor": "anthropic",
188
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
189
+ "price": { "input": 4, "cached": 0.2, "output": 20 },
190
+ "on": {
191
+ "claude-code": {
192
+ "id": "claude-opus-5-5",
193
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
194
+ "context": 1000000
195
+ },
196
+ "opencode": {
197
+ "id": "opencode/claude-opus-5-5",
198
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
199
+ "context": 1000000
200
+ }
201
+ },
202
+ "notes": { "effort": "the API default effort is medium" }
203
+ },
204
+ {
205
+ "id": "claude-sonnet-5",
206
+ "name": "Claude Sonnet 5",
207
+ "vendor": "anthropic",
208
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
209
+ "price": { "input": 2, "cached": 0.2, "output": 10 },
210
+ "on": {
211
+ "claude-code": {
212
+ "id": "claude-sonnet-5",
213
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
214
+ "context": 1000000
215
+ },
216
+ "opencode": {
217
+ "id": "opencode/claude-sonnet-5",
218
+ "efforts": ["low", "medium", "high", "xhigh", "max"],
219
+ "context": 1000000
220
+ }
221
+ }
222
+ },
223
+ {
224
+ "id": "claude-haiku-4-5",
225
+ "name": "Claude Haiku 4.5",
226
+ "vendor": "anthropic",
227
+ "capabilities": { "toolUse": true, "imageIn": true, "reasoning": true },
228
+ "price": { "input": 1, "cached": 0.1, "output": 5 },
229
+ "on": {
230
+ "claude-code": { "id": "claude-haiku-4-5-20251001", "efforts": [], "context": 200000 },
231
+ "opencode": { "id": "opencode/claude-haiku-4-5", "efforts": ["high", "max"], "context": 200000 }
232
+ },
233
+ "notes": { "effort": "no effort parameter in Claude Code: its only rung there is #default" }
234
+ }
235
+ ]
236
+ }