catherd-cli 1.0.0 → 1.1.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.
- package/README.md +66 -42
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +2 -2
- package/plugin/bin/catherd-mcp +30 -0
- package/plugin/commands/catherd.md +1 -1
- package/plugin/skills/catherd/SKILL.md +112 -95
- package/plugin/skills/catherd-setup/SKILL.md +3 -3
- package/src/adapters/access.ts +63 -0
- package/src/adapters/backend.ts +19 -4
- package/src/adapters/claude-code/index.ts +95 -1
- package/src/adapters/codex/index.ts +78 -23
- package/src/adapters/opencode/index.ts +17 -0
- package/src/domain/errors.ts +2 -0
- package/src/domain/failover.ts +119 -0
- package/src/domain/lane.ts +23 -0
- package/src/domain/notice.ts +95 -0
- package/src/domain/profile-rules.ts +43 -9
- package/src/domain/profile.ts +12 -6
- package/src/domain/record.ts +2 -0
- package/src/domain/role-prompts.ts +33 -1
- package/src/domain/state.ts +18 -2
- package/src/entry/deps.ts +2 -1
- package/src/entry/doctor-command.ts +7 -1
- package/src/entry/glyphs.ts +2 -1
- package/src/entry/init-command.ts +41 -1
- package/src/entry/mcp/command.ts +5 -1
- package/src/entry/mcp/dispatch-tools.ts +10 -40
- package/src/entry/mcp/handshake.ts +19 -9
- package/src/entry/mcp/lane-tools.ts +7 -6
- package/src/entry/mcp/protocol-tools.ts +57 -0
- package/src/entry/mcp/run-tools.ts +4 -3
- package/src/entry/mcp/server.ts +17 -1
- package/src/entry/mcp/setup-tools.ts +1 -1
- package/src/entry/profile-command.ts +3 -5
- package/src/entry/runs-command.ts +64 -21
- package/src/entry/tui/commands.ts +1 -1
- package/src/entry/tui/effects.ts +98 -56
- package/src/entry/tui/fixtures.ts +352 -85
- package/src/entry/tui/profile-edits.ts +2 -2
- package/src/entry/tui/profile-tree.ts +2 -1
- package/src/entry/tui/providers/data.tsx +35 -8
- package/src/entry/tui/state.ts +26 -6
- package/src/entry/tui/stories.ts +36 -4
- package/src/entry/tui/text.ts +12 -0
- package/src/entry/tui/theme.ts +1 -0
- package/src/entry/tui/views/runs.tsx +409 -117
- package/src/entry/tui/views/status.tsx +5 -2
- package/src/entry/tui/widgets/list.tsx +4 -3
- package/src/infra/claude-session.ts +98 -0
- package/src/infra/dispatch-dir.ts +14 -6
- package/src/infra/env.ts +26 -2
- package/src/infra/peer-inbox.ts +92 -0
- package/src/infra/supervisor.ts +33 -3
- package/src/services/admission.ts +38 -12
- package/src/services/dispatch-service.ts +338 -197
- package/src/services/dispatches.ts +30 -1
- package/src/services/doctor-access.ts +231 -0
- package/src/services/doctor-backends.ts +3 -18
- package/src/services/doctor-checks.ts +46 -1
- package/src/services/doctor-push.ts +109 -0
- package/src/services/doctor.ts +59 -79
- package/src/services/finalize.ts +43 -25
- package/src/services/gate-service.ts +288 -0
- package/src/services/global-install.ts +99 -0
- package/src/services/lane-service.ts +150 -8
- package/src/services/milestones.ts +208 -0
- package/src/services/notifier.ts +296 -0
- package/src/services/peek.ts +103 -0
- package/src/services/ports.ts +7 -4
- package/src/services/preflight.ts +17 -3
- package/src/services/protocol.ts +212 -0
- package/src/services/questions.ts +102 -0
- package/src/services/reconcile.ts +40 -11
- package/src/services/reentry.ts +22 -0
- package/src/services/run-service.ts +42 -9
- package/src/services/run-store.ts +18 -0
- package/src/services/runs-page.ts +254 -0
- package/src/services/session-view.ts +152 -0
- package/src/services/sessions.ts +92 -0
- package/src/services/state.ts +10 -3
- package/src/services/summary.ts +14 -0
package/README.md
CHANGED
|
@@ -17,8 +17,13 @@ of work, climbing a ladder only when a cheaper rung falls short.
|
|
|
17
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
|
-
- **
|
|
21
|
-
|
|
20
|
+
- **Results come to you.** Roles run side by side while you keep talking to Claude; each one that finishes
|
|
21
|
+
arrives in the session as a message, like a native subagent's notice, and `peek` shows how a run stands.
|
|
22
|
+
- **A protocol the tools enforce.** Every lane is routed, every brief ends with the reply contract, and a
|
|
23
|
+
milestone lands only after a reviewer and a verifier passed it. Workers can run their own checks (network,
|
|
24
|
+
loopback, Docker, the lock dir); an owner question parks one milestone, not the run.
|
|
25
|
+
- **Guard rails for autopilot.** Quota failover to a stand-in that clears the same bars, a preflight check
|
|
26
|
+
before any worker starts, per-repo knowledge carried between runs, and a run budget.
|
|
22
27
|
|
|
23
28
|
## Requirements
|
|
24
29
|
|
|
@@ -38,13 +43,18 @@ you have (`/catherd-setup` in Claude Code, or `catherd profile set roles.<role>.
|
|
|
38
43
|
## Install
|
|
39
44
|
|
|
40
45
|
```sh
|
|
41
|
-
|
|
46
|
+
bun add -g catherd-cli
|
|
47
|
+
catherd init
|
|
42
48
|
```
|
|
43
49
|
|
|
44
|
-
The npm package is `catherd-cli`; the command it installs is `catherd`. `init`
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
The npm package is `catherd-cli`; the command it installs is `catherd`. `bunx catherd-cli init` works too: `init`
|
|
51
|
+
installs the global command at its own version (`--no-global` skips it) and says `installing catherd…` before
|
|
52
|
+
it does, though the first `bunx` resolve itself prints nothing for up to half a minute. `init` asks for the
|
|
53
|
+
optional Jev key, writes the default profile and links its Claude agents, lists your backends' models, and ends
|
|
54
|
+
with a readiness report (`--no-input` asks nothing and keeps what exists; `--profile <name>` sets up and activates
|
|
55
|
+
that profile instead of `default`; piped, it reads one answer per line once stdin closes: the Jev key, the
|
|
56
|
+
profile, whether to replace it, each on its own line even when a question is skipped). Then add the plugin to
|
|
57
|
+
Claude Code:
|
|
48
58
|
|
|
49
59
|
```sh
|
|
50
60
|
claude plugin marketplace add 47vigen/catherd
|
|
@@ -52,33 +62,35 @@ claude plugin install catherd@catherd
|
|
|
52
62
|
```
|
|
53
63
|
|
|
54
64
|
Start a new Claude Code session so the plugin, its MCP server and the agent files load, then check with
|
|
55
|
-
`
|
|
65
|
+
`catherd doctor`. Run it once from inside that session too (ask Claude to run `catherd doctor`): its `push` row
|
|
66
|
+
then checks that finished roles can reach the session.
|
|
56
67
|
|
|
57
68
|
## Use
|
|
58
69
|
|
|
59
70
|
In Claude Code:
|
|
60
71
|
|
|
61
|
-
- `/catherd <task>` runs a task on autopilot; `/catherd` alone resumes the latest run.
|
|
72
|
+
- `/catherd <task>` runs a task on autopilot; `/catherd` alone resumes the latest run. While it runs, keep
|
|
73
|
+
talking: each finished role arrives as a message from catherd, and "how is it going?" gets a `peek`.
|
|
62
74
|
- `/catherd-setup` tunes your profile in conversation: which models and efforts each role may
|
|
63
75
|
use, cost or speed, isolation, budget and failover.
|
|
64
76
|
|
|
65
77
|
In a terminal:
|
|
66
78
|
|
|
67
|
-
| Command | What it does
|
|
68
|
-
| ----------------------------------------------------------------------------------------- |
|
|
69
|
-
| `catherd` | The dashboard: Status, Profiles and Runs (below)
|
|
70
|
-
| `catherd init [--no-input] [--profile <p>]`
|
|
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)
|
|
79
|
+
| Command | What it does |
|
|
80
|
+
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `catherd` | The dashboard: Status, Profiles and Runs (below) |
|
|
82
|
+
| `catherd init [--no-input] [--no-global] [--profile <p>]` | First-run setup; installs the global `catherd` at its own version unless `--no-global` |
|
|
83
|
+
| `catherd doctor [--json]` | Readiness report, one row per check with its fix; exits 3 when not ready |
|
|
84
|
+
| `catherd profile list\|show\|use [--repo]\|new [--from <p>]\|copy\|rm\|diff\|validate` | Profiles; `use --repo` binds one to the repo you are in |
|
|
85
|
+
| `catherd profile use --repo --clear` | Unbinds the repo you are in; it runs on the active profile again |
|
|
86
|
+
| `catherd profile set <path> <value> [--profile <p>]` | One field, e.g. `roles.verifier.access read-only`, `roles.worker.network false`, `budget.usd 20` |
|
|
87
|
+
| `catherd status [run]`, `catherd watch [--once] [--interval <s>]` | Where runs stand, grouped by the Claude Code session that drove them |
|
|
88
|
+
| `catherd runs list [--repo <path>]\|show <id> [--debug [--name <n>]]\|cancel <id> <name>` | Past runs, by session; `--debug` adds exit.json and the stderr and event tails, `--name` one role's |
|
|
89
|
+
| `catherd catalog refresh\|list [--backend <b>] [--role <r>] [--text <t>] [--scored]` | The models catherd can place, filtered |
|
|
90
|
+
| `catherd catalog treat-like <rung> <like>` | Scores an unscored rung as a scored one |
|
|
91
|
+
| `catherd lock [--slots N] -- <cmd>` | Runs a heavy command behind the machine-wide semaphore, in its own session (no /dev/tty) |
|
|
92
|
+
| `catherd mcp` | The MCP server on stdio; the plugin starts it, you never need to |
|
|
93
|
+
| `catherd capture-fixtures [--backend <b>] [--out <dir>]` | Contributors: records sanitized test fixtures from real runs (see CONTRIBUTING.md) |
|
|
82
94
|
|
|
83
95
|
A profile command without a profile name (`show`, `set`, `diff`, `validate`), like the MCP profile tools, acts
|
|
84
96
|
on the profile the repo you are in runs on: the one bound to it, else the active one. Run them as
|
|
@@ -103,16 +115,18 @@ Run data lives in `~/.local/share/catherd/`, config in `~/.config/catherd/` (bot
|
|
|
103
115
|
| `CATHERD_CLAUDE_AGENTS_DIR` | Where catherd links its Claude agents (default: `$CLAUDE_CONFIG_DIR/agents`, else `~/.claude/agents`) |
|
|
104
116
|
| `NO_COLOR` | Drops colour (the dashboard's and `--help`'s; piped `--help` has none either) |
|
|
105
117
|
|
|
106
|
-
For development only: `CATHERD_STORY=1` opens the dashboard's storybook, `
|
|
107
|
-
|
|
108
|
-
(CONTRIBUTING.md has the rest).
|
|
118
|
+
For development only: `CATHERD_STORY=1` opens the dashboard's storybook, and `CATHERD_LIVE=1` enables the live
|
|
119
|
+
tests (CONTRIBUTING.md has the rest).
|
|
109
120
|
|
|
110
121
|
### The dashboard
|
|
111
122
|
|
|
112
123
|
`catherd` opens three tabs: **1 Status** (every check with its fix; `y` copies the fix, `r` checks again),
|
|
113
124
|
**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** (
|
|
115
|
-
|
|
125
|
+
harness, budget, failover, timeouts and notify) and **3 Runs** (the Claude Code sessions that drove your runs, newest
|
|
126
|
+
first; a session opens on its runs, their milestones and every role with its rung, status, time and last event, live
|
|
127
|
+
ones first; a milestone opens on its digest (what landed, lanes and climbs, reviewer and verifier, tokens); a role
|
|
128
|
+
opens on its brief, reply and record; the open screen redraws as run files change; `esc` goes back,
|
|
129
|
+
`p` pauses). `catherd watch` opens it on Runs.
|
|
116
130
|
|
|
117
131
|
- `ctrl+p` lists every command with its key and CLI twin; `?` lists the keys that work where you are.
|
|
118
132
|
- `ctrl+x` is the leader: `ctrl+x 1`–`3` tabs, `ctrl+x n` new profile, `ctrl+x l` profiles, `ctrl+x u` and
|
|
@@ -131,7 +145,16 @@ milestones; `p` pauses). `catherd watch` opens it on Runs.
|
|
|
131
145
|
(the palette shows each command by title; the ids are listed in
|
|
132
146
|
[`src/entry/tui/commands.ts`](src/entry/tui/commands.ts)).
|
|
133
147
|
|
|
134
|
-
## Upgrading
|
|
148
|
+
## Upgrading
|
|
149
|
+
|
|
150
|
+
From 1.0: install 1.1 and run its `init` (`bun add -g catherd-cli@latest && catherd init`, or
|
|
151
|
+
`bunx catherd-cli@latest init`; 1.0's own `catherd init` does not upgrade), update the plugin
|
|
152
|
+
(`claude plugin marketplace update catherd && claude plugin update catherd@catherd`) and start a new Claude Code
|
|
153
|
+
session. `wait` is gone: results arrive as messages, `peek` shows a run, `result` reads a record. A profile saved
|
|
154
|
+
by 1.0 keeps its failover map; `catherd profile validate` says what to change. The details are in
|
|
155
|
+
[MIGRATION.md](MIGRATION.md).
|
|
156
|
+
|
|
157
|
+
### From 0.x
|
|
135
158
|
|
|
136
159
|
1.0 is a clean break: run `bunx catherd-cli init` once. It moves your 0.x `config.json`, `projects.json` and
|
|
137
160
|
profiles into a `0.x-backup-<time>/` folder next to them (it never reads or deletes them), writes the 1.0
|
|
@@ -142,18 +165,19 @@ Code session. The details are in [MIGRATION.md](MIGRATION.md).
|
|
|
142
165
|
|
|
143
166
|
## Docs
|
|
144
167
|
|
|
145
|
-
| Where
|
|
146
|
-
|
|
|
147
|
-
| [MIGRATION.md](MIGRATION.md)
|
|
148
|
-
| [CHANGELOG.md](CHANGELOG.md)
|
|
149
|
-
| [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
150
|
-
| [SECURITY.md](SECURITY.md)
|
|
151
|
-
| [`docs/
|
|
152
|
-
| [`docs/
|
|
153
|
-
| [`docs/dev
|
|
154
|
-
| [`docs/
|
|
155
|
-
| [`docs/
|
|
156
|
-
| [`docs/
|
|
168
|
+
| Where | What |
|
|
169
|
+
| -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
170
|
+
| [MIGRATION.md](MIGRATION.md) | Upgrading from 1.0 and from 0.x |
|
|
171
|
+
| [CHANGELOG.md](CHANGELOG.md) | Releases |
|
|
172
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Development setup, the checks, commits, changesets, live tests |
|
|
173
|
+
| [SECURITY.md](SECURITY.md) | Reporting a vulnerability; what catherd stores and how |
|
|
174
|
+
| [`docs/specs/2026-09-28-catherd-1.1-design.md`](docs/specs/2026-09-28-catherd-1.1-design.md) | The 1.1 design (binding; builds on 1.0's) |
|
|
175
|
+
| [`docs/specs/2026-09-25-catherd-1.0-design.md`](docs/specs/2026-09-25-catherd-1.0-design.md) | The 1.0 design |
|
|
176
|
+
| [`docs/dev/`](docs/dev/) | Maintainer docs: live verification, manual tests, dependencies, ideas |
|
|
177
|
+
| [`docs/dev/live-verification.md`](docs/dev/live-verification.md) | What CI cannot run: live tests, fixture capture, the Codex sandbox |
|
|
178
|
+
| [`docs/tui-frames.md`](docs/tui-frames.md) | Every dashboard screen as text (generated, checked in CI) |
|
|
179
|
+
| [`docs/plans/`](docs/plans/), [`docs/handoff/`](docs/handoff/), [`docs/research/`](docs/research/) | How 1.0 was designed and built: plans, reviews, research |
|
|
180
|
+
| [`docs/archive/0.x/`](docs/archive/0.x/) | The 0.x design and plans, for history |
|
|
157
181
|
|
|
158
182
|
## Contributing
|
|
159
183
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "catherd",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Herds coding agents: Claude plans and verifies, Codex, opencode or headless Claude Code workers write the code, and Jev picks the model and effort for each piece.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "47vigen",
|
package/plugin/.mcp.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# catherd's MCP launcher (spec 1.1 §12): the plugin's .mcp.json runs it. The release stamps VERSION
|
|
3
|
+
# (scripts/stamp-plugin-version.mjs), so the plugin always starts the server it was released with.
|
|
4
|
+
VERSION="1.1.0"
|
|
5
|
+
|
|
6
|
+
# a global catherd at this version (catherd init installs one): start it, no resolve at all
|
|
7
|
+
if command -v catherd >/dev/null 2>&1 && [ "$(catherd --version 2>/dev/null)" = "$VERSION" ]; then
|
|
8
|
+
# CATHERD_USER_TMPDIR is only this launcher's own hand-off to the server below; never pass on a stray one
|
|
9
|
+
unset CATHERD_USER_TMPDIR
|
|
10
|
+
exec catherd mcp
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
# else bunx, with its cache out of $TMPDIR: macOS cleans old files there and leaves bunx a broken package.
|
|
14
|
+
# The server gets the user's own TMPDIR back from CATHERD_USER_TMPDIR (empty when it was unset).
|
|
15
|
+
if [ -n "${XDG_CACHE_HOME:-}" ]; then
|
|
16
|
+
cache="$XDG_CACHE_HOME"
|
|
17
|
+
elif [ -n "${HOME:-}" ]; then
|
|
18
|
+
cache="$HOME/.cache"
|
|
19
|
+
else
|
|
20
|
+
echo "catherd-mcp: HOME and XDG_CACHE_HOME are both unset, so there is no cache folder for bunx; set HOME, or install catherd globally: bun add -g catherd-cli@$VERSION" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
CATHERD_USER_TMPDIR="${TMPDIR:-}"
|
|
24
|
+
TMPDIR="$cache/catherd/bunx"
|
|
25
|
+
if ! mkdir -p "$TMPDIR" 2>/dev/null; then
|
|
26
|
+
echo "catherd-mcp: cannot create $TMPDIR for bunx's cache; fix its permissions, or install catherd globally: bun add -g catherd-cli@$VERSION" >&2
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
export CATHERD_USER_TMPDIR TMPDIR
|
|
30
|
+
exec bunx "catherd-cli@$VERSION" mcp
|
|
@@ -7,4 +7,4 @@ Use the `catherd` skill for this, and follow it exactly.
|
|
|
7
7
|
|
|
8
8
|
Task: $ARGUMENTS
|
|
9
9
|
|
|
10
|
-
If the task is empty, resume: call `status()`, tell the user which run it names, and continue that run from its
|
|
10
|
+
If the task is empty, resume: call `status()`, tell the user which run it names, call `peek(run)` once, and continue that run from its `Protocol next` step.
|