cuekit 0.0.12 → 0.0.13

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 (2) hide show
  1. package/README.md +363 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,363 @@
1
+ # cuekit
2
+
3
+ A child-agent delegation substrate for coding agents.
4
+
5
+ cuekit gives a parent agent a stable way to spawn child coding agents, attach to them live via tmux, steer them, collect normalized results, and clean up. The same protocol surface is exposed as a grouped human CLI (`cuekit task ...`) and a grouped MCP tool surface for AI callers.
6
+
7
+ ## Philosophy
8
+
9
+ cuekit is **not a workflow engine**. The parent agent stays the decision-maker; cuekit is the substrate that makes delegation observable and steerable.
10
+
11
+ - **Teams** are a lightweight view over related child tasks, not a swarm OS.
12
+ - **Strategies** are development playbooks, not workflow control.
13
+ - No automatic scheduling, auto-wake, or auto-steer that replaces parent judgment.
14
+
15
+ ## Requirements
16
+
17
+ - [Bun](https://bun.sh) ≥ 1.2
18
+ - A terminal multiplexer on `PATH`. By default cuekit uses **tmux** (with `new-session -e` support); children run in tmux sessions you can `tmux attach` into. Alternatively, cuekit can use **[zellij](https://github.com/zellij-org/zellij)** ≥ 0.43 or **[herdr](https://herdr.dev)** ≥ 0.5 by setting `multiplexer.backend: zellij` or `multiplexer.backend: herdr` in `.cuekit.yaml` — see [Multiplexer](#multiplexer) below.
19
+
20
+ ## Install
21
+
22
+ Pinned to a specific release tag (recommended):
23
+
24
+ ```sh
25
+ bun install -g github:takemo101/cuekit#v0.0.8
26
+ cuekit doctor
27
+ cuekit mcp config # prints the snippet to register cuekit with your MCP client
28
+ ```
29
+
30
+ Or resolve the most recent release tag at install time (no need to look up the version):
31
+
32
+ ```sh
33
+ # Option A — uses the GitHub CLI:
34
+ bun install -g github:takemo101/cuekit#$(gh release view --repo takemo101/cuekit --json tagName -q .tagName)
35
+
36
+ # Option B — curl-only:
37
+ bun install -g github:takemo101/cuekit#$(curl -s https://api.github.com/repos/takemo101/cuekit/releases/latest | jq -r .tag_name)
38
+ ```
39
+
40
+ Bun has no `#latest` shorthand for GitHub installs, so the one-liners above resolve the tag at command-execution time and pin the install to that exact version. After install, `cuekit update` is the advisory-only command that prints the next install command when a newer release exists.
41
+
42
+ When upgrading an existing global GitHub install, remove first and then install the new tag:
43
+
44
+ ```sh
45
+ bun remove -g cuekit-workspace
46
+ bun install -g github:takemo101/cuekit#v0.0.8
47
+ ```
48
+
49
+ This avoids Bun global-install dependency-loop errors that can occur when installing a newer `github:takemo101/cuekit#...` tag over an older one.
50
+
51
+ Use an immutable release tag for normal installs. Avoid floating `#main` outside development — Bun's caching semantics for branches are less explicit. After installing a newer tag, restart MCP clients.
52
+
53
+ > **Naming gotcha**: the binary is named `cuekit` but the workspace `package.json#name` is `cuekit-workspace`. This matters when you uninstall (see below) and when you list installed packages (`bun pm ls -g | grep cuekit`).
54
+
55
+ ### Uninstall
56
+
57
+ ```sh
58
+ bun remove -g cuekit-workspace
59
+ ```
60
+
61
+ `bun remove -g cuekit` is a **silent no-op** because no package by that name exists — Bun returns success without removing anything. Always remove by the package name `cuekit-workspace`. Verify with `which cuekit` (should report nothing) or `bun pm ls -g | grep cuekit-workspace` (should be empty).
62
+
63
+ For a deeper cleanup including state, transcript, and tmux sessions, see the uninstall recipe at the bottom of this file.
64
+
65
+ ### Local development
66
+
67
+ ```sh
68
+ git clone https://github.com/takemo101/cuekit
69
+ cd cuekit
70
+ bun install
71
+ bun link # exposes `cuekit` from the workspace
72
+ # or run directly:
73
+ bun packages/cli/src/bin.ts <command>
74
+ ```
75
+
76
+ ## Quick start
77
+
78
+ ```sh
79
+ # Submit a child agent task in your repo:
80
+ cuekit task submit \
81
+ --objective "add retry logic to src/api/client.ts" \
82
+ --agent_kind claude-code \
83
+ --model sonnet \
84
+ --cwd /path/to/repo
85
+ # → { task_id: "t_abc...", attach_hint: "tmux attach-session -t cuekit-task-t_abc..." }
86
+
87
+ # Watch the child live in another terminal:
88
+ cuekit task status --task_id t_abc... --format json | jq -r '.attach_hint'
89
+ # → use the printed attach command (tmux/zellij/herdr attach)
90
+
91
+ # Steer it without attaching:
92
+ cuekit task steer --task_id t_abc... --message "also cover exponential backoff"
93
+
94
+ # Collect the normalized result:
95
+ cuekit task result --task_id t_abc...
96
+ ```
97
+
98
+ ## CLI
99
+
100
+ Commands are grouped by resource. Option names are `snake_case`. Every command accepts `--help`, `--llms` / `--llms-full` (machine-readable manifest), `--schema`, and `--format` (`toon` / `json` / `yaml` / `md` / `jsonl`).
101
+
102
+ | Group | Examples |
103
+ |---|---|
104
+ | `task` | `submit`, `status`, `steer`, `cancel`, `result`, `wait`, `list` |
105
+ | `team` | `create`, `submit`, `start`, `result`, `steer`, `delete` |
106
+ | `agent` | `list` (discover role profiles) |
107
+ | `adapter` | `list` (runtime capabilities) |
108
+ | `tui` | interactive task cockpit |
109
+ | `mcp` | `config` (print MCP client snippet) |
110
+ | top-level | `init`, `doctor`, `update` |
111
+
112
+ Flat aliases like `cuekit submit_task` are intentionally not supported — only MCP tool names use that flat form.
113
+
114
+ ### Agent profiles
115
+
116
+ Use `--role` to submit with focused child-agent instructions. Profiles resolve in this order: project (`<repo>/.cuekit/agents/*.md`) → user (`~/.cuekit/agents/*.md`) → builtins. `--agent_kind` / `--model` override profile defaults.
117
+
118
+ ```sh
119
+ cuekit agent list
120
+ cuekit task submit --objective "review this diff" --role reviewer --cwd /path/to/repo
121
+ cuekit task submit --objective "debug the failing auth tests" --role auto --cwd /path/to/repo
122
+ ```
123
+
124
+ `role: "auto"` uses deterministic keyword selection and records the chosen role and reason in task status. See [Agent Profiles guide](docs/guides/agent-profiles.md).
125
+
126
+ ### Project config
127
+
128
+ ```sh
129
+ cuekit init # writes a safe .cuekit.yaml and adds .cuekit/tasks/ to .gitignore
130
+ ```
131
+
132
+ `.cuekit.yaml` defines project identity, safe submit defaults, TUI scope, and Task Teams defaults. The generated file uses prompt-safe adapter permissions; pass `cuekit init --unsafe-bypass` only in trusted repos when you want project-local defaults to request bypass behavior. Project-derived role/agent defaults still force prompt-safe adapter options unless a caller explicitly supplies `adapter_options`. See [Project Config guide](docs/guides/project-config.md) and [`.cuekit.example.yaml`](.cuekit.example.yaml).
133
+
134
+ ### TUI
135
+
136
+ `cuekit tui` opens an interactive task cockpit for humans. The flat CLI stays optimized for agents/scripts; the TUI is a separate surface for browsing and acting.
137
+
138
+ ```text
139
+ ↑/↓ or j/k select task a attach to task pane/session (one-way; exits TUI)
140
+ t switch tasks/teams A attach selected team dashboard (teams mode)
141
+ r refresh s steer selected task
142
+ c cancel selected d delete terminal task / empty team
143
+ q / Esc quit
144
+ ```
145
+
146
+ The task detail panel's `LIVE OUTPUT` section sources from the running task's multiplexer pane (e.g. `tmux capture-pane`) so the rendered screen matches what `tmux attach` would show — useful for TUI children (Gemini CLI, opencode TUI) whose output gets buried by redraws in the persisted transcript. Terminal tasks fall back to the file-tail. The header indicates which source is active. See [`docs/designs/cuekit-tui-live-pane-transcript-design.md`](docs/designs/cuekit-tui-live-pane-transcript-design.md).
147
+
148
+ ## MCP
149
+
150
+ Start the stdio server:
151
+
152
+ ```sh
153
+ cuekit --mcp
154
+ ```
155
+
156
+ Grouped tool surface: `submit_task`, `submit_team_tasks`, `start_team_strategy`, `create_team`, `get_status`, `get_task_result`, `get_team_result`, `wait`, `cancel_tasks`, `list`, `report_task_event`, `steer`, `steer_task`, `steer_team`, `cleanup`, `delete`.
157
+
158
+ - `list({ kind: "tasks" | "teams" | "events" | "adapters" | "agent_profiles" | "strategies" })` — pass `cwd` for project-local strategy discovery.
159
+ - `steer({ kind: "task" | "team", ... })` — preferred. `steer_task` / `steer_team` remain as compatibility aliases.
160
+ - `delete({ kind: "team", ... })` — for empty teams only.
161
+ - `cuekit mcp config` is CLI-only; no MCP setup helpers are exposed as tools.
162
+
163
+ ### Waiting on child work
164
+
165
+ `wait` is the parent-side polling primitive. Prefer **short bounded waits** over one long request:
166
+
167
+ ```jsonc
168
+ { "kind": "tasks", "task_ids": ["t_..."], "timeout_ms": 30000, "poll_interval_ms": 5000 }
169
+ ```
170
+
171
+ A wait timeout only stops waiting; child work keeps running. Team waits are snapshot-based by default — coordinator-led / strategy-backed teams that submit workers after waiting begins can pass `follow_new_tasks: true`.
172
+
173
+ When a bounded wait times out, call `get_status`. If a task includes `attention_hint` (e.g. `stop_hook_or_idle_prompt_suspected`), use `steer({ kind: "task", ... })` with a short instruction. Inspect durable child reports with `list({ kind: "events", task_id: "t_..." })`.
174
+
175
+ ## Execution model
176
+
177
+ Pane adapters default to **interactive** mode: the child runs in a dedicated `cuekit-task-<id>` tmux session so cuekit can attach, steer, and capture transcripts while the runtime stays alive.
178
+
179
+ For single-shot jobs, opt into batch mode per task:
180
+
181
+ ```sh
182
+ cuekit task submit --objective "review this diff once and exit" \
183
+ --agent_kind claude-code \
184
+ --adapter_options '{"mode":"batch"}'
185
+ ```
186
+
187
+ Batch tasks still run in a pane and are attachable, but `metadata.adapter_mode: "batch"` and `supports_steering: false`; `steer_task` rejects them with `steering_unsupported`. Adapter list reports default capabilities; task status reports the actual mode chosen.
188
+
189
+ ### Adapter defaults
190
+
191
+ - `claude-code` defaults to runtime permission bypass so delegated panes don't stall.
192
+ - `opencode` defaults to its interactive TUI; permission bypass applies only to opt-in batch/run mode.
193
+ - `gemini` defaults to runtime permission bypass (`-y`) and always passes `--skip-trust` so unattended panes don't stall on the trusted-folder gate.
194
+
195
+ See [`docs/specs/2026-04-23-cuekit-adapter-spec.md`](docs/specs/2026-04-23-cuekit-adapter-spec.md) §3.7 for the full pane-backend contract.
196
+
197
+ ### Multiplexer
198
+
199
+ cuekit defaults to **tmux** as the terminal multiplexer. Projects can opt into **zellij** ≥ 0.43 via `.cuekit.yaml`:
200
+
201
+ ```yaml
202
+ multiplexer:
203
+ backend: zellij # default is "tmux"
204
+ strict: false # optional. true → hard-fail when zellij is missing instead of soft-falling-back to tmux
205
+ ```
206
+
207
+ Behavioural differences when `multiplexer.backend: zellij` is active:
208
+
209
+ - Solo tasks live in compact `ct-<task_id>` zellij sessions (mirrors the tmux model).
210
+ - Team tasks share one compact `ctm-<team_id_suffix>` zellij session. In the TUI, `A` on the team list attaches to this multi-pane dashboard; `a` on a member/task focuses that member pane before attaching to the same dashboard session.
211
+ - Attach uses `zellij attach <session-name>` instead of `tmux attach-session`.
212
+ - The TUI's transcript pane sources from `zellij action dump-screen` instead of `tmux capture-pane`. Output formatting differs subtly (escape-sequence canonicalisation).
213
+ - Zellij pane state queries are slower than tmux on some systems, especially for multi-pane team dashboards. The TUI keeps list navigation responsive by using cached/persisted list rows, debouncing zellij detail loads, and showing a `Loading detail…` spinner while the selected detail refreshes. A small detail-panel lag is expected when zellij is selected.
214
+ - When zellij is configured but its binary is missing, cuekit logs a warning and silently falls back to tmux. To turn this into a hard failure (e.g. CI configs that want to surface the missing dependency), set `multiplexer.strict: true`.
215
+ - Per-task multiplexer dispatch: a task spawned under one backend stays attachable via that backend even if `.cuekit.yaml` is later switched. The active backend is per-task, recorded at spawn time.
216
+
217
+ See [`docs/designs/cuekit-multiplexer-backend-design.md`](docs/designs/cuekit-multiplexer-backend-design.md) for the full design and the zellij team-dashboard work tracked under Phase 4.
218
+
219
+ #### Herdr backend
220
+
221
+ Projects can also opt into **[herdr](https://herdr.dev)** ≥ 0.5 as the multiplexer:
222
+
223
+ ```yaml
224
+ multiplexer:
225
+ backend: herdr
226
+ strict: false
227
+ ```
228
+
229
+ Herdr uses **workspaces** instead of sessions. Solo tasks get one workspace each; team tasks share one workspace with **named tabs per position** (for example, coordinator, worker, reviewer). Attach uses `herdr --session <name>`.
230
+
231
+ Key differences:
232
+ - **Team model**: one workspace per team with position-named tabs; same position shares a tab, different positions get separate tabs.
233
+ - **Pane IDs**: compacted on close (IDs may shift), so cuekit uses transcript identity verification to avoid closing the wrong pane.
234
+ - **Cross-process persistence**: team workspace handles are persisted in `task_teams.metadata_json` so coordinator-spawned members reuse the same workspace even across process restarts.
235
+ - **Fallback**: when herdr is missing and `strict: false`, cuekit falls back to tmux with a logged warning.
236
+
237
+ See [`docs/designs/cuekit-herdr-multiplexer-backend-design.md`](docs/designs/cuekit-herdr-multiplexer-backend-design.md) for the full design.
238
+
239
+ ## State
240
+
241
+ | Where | What |
242
+ |---|---|
243
+ | `~/.cuekit/state.db` | global SQLite index — `sessions`, `tasks`, `schema_migrations`. WAL mode, `foreign_keys = ON`, one connection per process. |
244
+ | `<worktree>/.cuekit/tasks/<task_id>/` | per-task artifacts: `transcript.txt`, runtime-emitted `result.json`, anything else the adapter drops. Stored as `transcript_ref` / `result_ref` on the task row. |
245
+ | `cuekit-task-<id>` | one multiplexer session/workspace per task. Killed on terminal transition or explicit cancel. |
246
+
247
+ ## Packages
248
+
249
+ | Package | Purpose |
250
+ |---|---|
251
+ | `@cuekit/core` | Protocol types, Zod schemas, lifecycle helpers. No runtime deps. |
252
+ | `@cuekit/store` | SQLite persistence at `~/.cuekit/state.db` with migrations. |
253
+ | `@cuekit/adapters` | Runtime bindings. Ships tmux, zellij, and herdr pane backends with adapters for claude-code, pi, opencode (stub), `jcode repl`, and gemini. |
254
+ | `@cuekit/agent-profiles` | Role-based child-agent profiles. |
255
+ | `@cuekit/project-config` | `.cuekit.yaml` loading, validation, and defaults. |
256
+ | `@cuekit/mcp` | MCP server and protocol/control command projection. |
257
+ | `@cuekit/cli` | The `cuekit` binary, setup helpers, diagnostics. |
258
+ | `@cuekit/tui` | OpenTUI-based human task cockpit. |
259
+
260
+ ## Documentation
261
+
262
+ The full documentation index is at [`docs/README.md`](docs/README.md).
263
+
264
+ | Area | When to read |
265
+ |---|---|
266
+ | [`docs/specs/`](docs/specs/README.md) | What cuekit is — protocol, state model, MCP API, adapter contract. |
267
+ | [`docs/architecture/`](docs/architecture/README.md) | How cuekit must be built — package boundaries, coding rules, error taxonomy. |
268
+ | [`docs/decisions/`](docs/decisions/) | ADRs and durable design decisions. |
269
+ | [`docs/designs/`](docs/designs/README.md) | Stable feature/subsystem designs (teams, strategies, profiles, TUI, ...). |
270
+ | [`docs/guides/`](docs/guides/README.md) | Operator/developer guides for implemented features. |
271
+ | [`docs/issues/`](docs/issues/README.md) | Active investigations and bug reports. |
272
+ | [`docs/plans/`](docs/plans/) | Implementation plans and execution notes. |
273
+ | [`docs/references/`](docs/references/README.md) | Local copies of third-party docs (e.g. OpenTUI). |
274
+
275
+ ## Development
276
+
277
+ ```sh
278
+ bun run typecheck # tsc --noEmit across all packages
279
+ bun run test # bun:test across all packages
280
+ bun run check # Biome lint + format check
281
+ bun run fix # Biome auto-fix
282
+ ```
283
+
284
+ Tests use `FakeTmuxRunner` and `FakeHerdrRunner` (exported from `@cuekit/adapters`) so the default run does not require `tmux` or `herdr`. A small integration suite in `@cuekit/adapters` exercises real tmux when available and skips otherwise.
285
+
286
+ ### Manual smoke tests
287
+
288
+ Adapter end-to-end checks against real runtimes are documented per adapter:
289
+
290
+ - [jcode adapter smoke test](docs/guides/jcode-adapter.md)
291
+ - [gemini adapter smoke test](docs/guides/gemini-adapter.md)
292
+ - Real `claude` CLI: `just install`, then submit a task with `--agent_kind claude-code` and attach via the hint from `cuekit task status --task_id <id>`. The transcript persists at `<cwd>/.cuekit/tasks/<task_id>/transcript.txt` after the session is killed.
293
+
294
+ ### Cutting a release
295
+
296
+ Releases are GitHub-tagged (`v0.0.x`) and consumed via `bun install -g github:takemo101/cuekit#vX.Y.Z`. The published binary is the pre-built bundle at `bin/cuekit.js` — `package.json#bin.cuekit` points at it directly, so Bun installs it verbatim.
297
+
298
+ ```sh
299
+ # 1. Bump version in every workspace package's package.json (and the
300
+ # project root if it tracks one). Update CHANGELOG.md.
301
+ # 2. Verify the bundle is in sync with the new version:
302
+ bun run release:check
303
+ # 3. If `release:check` reports the bundle was stale, commit the
304
+ # regenerated bin/cuekit.js it produced, then re-run.
305
+ # 4. Open the release PR and merge. After merge, tag the merge commit
306
+ # with `vX.Y.Z` and push.
307
+ ```
308
+
309
+ `release:check` rebuilds the bundle, fails if the committed `bin/cuekit.js` differs from the freshly-built output (= the bundle was stale), and double-checks that the bundle contains the expected version string. Without this gate v0.0.2 and v0.0.3 both shipped a stale bundle that reported `0.0.1` from its baked-in `package.json` copy — see [#388](https://github.com/takemo101/cuekit/issues/388).
310
+
311
+ ## v0 scope
312
+
313
+ | Supported | Deferred |
314
+ |---|---|
315
+ | `submit_task` / `get_status` / `get_task_result` / `wait` / `cancel_tasks` | Workflow engine, kanban, swarm OS |
316
+ | Grouped `list` / `cleanup` / `delete` MCP tools | Distributed worker pools, DAG scheduling |
317
+ | `steer_task` (best-effort, adapter-dependent) | Remote tenancy / auth model |
318
+ | tmux / zellij / herdr attach for every running task | Cost accounting, long-term memory |
319
+
320
+ Full v0 protocol: [`docs/specs/README.md`](docs/specs/README.md).
321
+
322
+ ## Full uninstall
323
+
324
+ The basic `bun remove -g cuekit-workspace` (see [Uninstall](#uninstall)) removes only the binary. To wipe state, transcripts, and project artifacts as well:
325
+
326
+ ```sh
327
+ # 1. Binary + Bun cache
328
+ bun remove -g cuekit-workspace
329
+ rm -rf ~/.bun/install/cache/@GH@takemo101-cuekit-*
330
+ rm -rf ~/.bun/install/global/node_modules/cuekit-workspace
331
+
332
+ # 2. Global state DB (task history, sessions, events)
333
+ rm -rf ~/.cuekit
334
+
335
+ # 3. Per-project artifacts (run inside each repo that used cuekit)
336
+ find . -name '.cuekit' -type d -prune -exec rm -rf {} +
337
+ rm -f ./.cuekit.yaml # if `cuekit init` was run
338
+
339
+ # 4. Kill any remaining multiplexer sessions
340
+ # tmux:
341
+ tmux ls 2>/dev/null | grep cuekit-task | cut -d: -f1 | xargs -I {} tmux kill-session -t {}
342
+ # herdr:
343
+ herdr workspace list 2>/dev/null | jq -r '.result.workspaces[].workspace_id' | xargs -I {} herdr workspace close {}
344
+
345
+ # 5. Remove the cuekit entry from MCP client configs
346
+ # Claude Code: `~/.claude.json` → `mcpServers.cuekit`
347
+ # Project: `<repo>/.mcp.json` → `mcpServers.cuekit`
348
+ # Cursor / Claude Desktop: each client's MCP config
349
+ # Restart the client after editing.
350
+ ```
351
+
352
+ Verify the removal:
353
+
354
+ ```sh
355
+ which cuekit # should report nothing
356
+ ls ~/.cuekit # should be "No such file"
357
+ tmux ls 2>/dev/null | grep cuekit- # should be empty
358
+ herdr workspace list 2>/dev/null | grep cuekit # should be empty
359
+ ```
360
+
361
+ Step 1 is enough for most cases. Steps 2 and 3 are destructive — back up `transcript.txt` files first if you need them for review or postmortem.
362
+
363
+ Note: `bun remove -g cuekit` (without `-workspace`) returns success but removes nothing — the workspace package is named `cuekit-workspace` even though its binary is `cuekit`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cuekit",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "cuekit — delegation substrate for coding agents",
5
5
  "type": "module",
6
6
  "exports": {