claude-supervisor 0.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.
@@ -0,0 +1,579 @@
1
+ # Claude Supervisor — Architecture
2
+
3
+ ## Overview
4
+
5
+ Automates spinning up parallel Claude Code agents in isolated git worktrees,
6
+ each working on a separate task with a chosen model.
7
+
8
+ ---
9
+
10
+ ## Component Map
11
+
12
+ ```
13
+ bin/supervisor.sh # Entry point — auto-init on first run, then orchestrates agents
14
+ bin/spawn-agent.sh # Spawns a single agent (branch + worktree + tmux + claude)
15
+ bin/collect-learnings.sh # Merges CLAUDE.md updates from worktrees back to main
16
+ bin/setup-shortcuts.sh # Optional: sets up shell shortcuts (PATH or aliases in ~/.zshrc)
17
+ lib/utils.sh # Shared functions (sourced by both scripts)
18
+ templates/tasks.conf # Scaffolded into target project on first run
19
+ templates/CLAUDE.md # Scaffolded into target project .claude/ on first run
20
+ templates/.claude/settings.json # PermissionRequest → Opus hook (scaffolded on first run)
21
+ templates/.claude/agents/reviewer.md # Code review subagent (auto-delegated by agent)
22
+ templates/.claude/agents/debugger.md # Debugging subagent (auto-delegated by agent)
23
+ templates/.claude/agents/test-writer.md # Test writing subagent (auto-delegated by agent)
24
+ templates/.claude/agents/_example-agent.md # Blank template for user-defined subagents
25
+ templates/.claude/commands/techdebt.md # /techdebt skill (user-invoked)
26
+ templates/.claude/commands/explain.md # /explain skill (user-invoked)
27
+ templates/.claude/commands/diagram.md # /diagram skill (user-invoked)
28
+ templates/.claude/commands/learn.md # /learn skill (user-invoked)
29
+ ```
30
+
31
+ ### What the user actually runs
32
+
33
+ ```
34
+ # First run — auto-init fires, project not yet set up:
35
+ supervisor.sh /path/to/project
36
+ → scaffolds project/tasks.conf + project/.claude/ from templates/
37
+ → prints "edit tasks.conf, then run again" → exits
38
+
39
+ # Every subsequent run — agents fire automatically:
40
+ supervisor.sh /path/to/project
41
+ → reads project/tasks.conf
42
+ → for each task line:
43
+ git branch created automatically
44
+ git worktree created at ../project-<branch>/
45
+ .claude/ copied from project root into worktree
46
+ tmux window opened and color-coded
47
+ claude launched with the task, model, and mode
48
+ → summary printed with attach instructions
49
+ ```
50
+
51
+ The user never touches git branches, worktrees, or file copying.
52
+
53
+ ---
54
+
55
+ ## System Overview
56
+
57
+ ```
58
+ ╔══════════════════════════════════════════════════════════════════════╗
59
+ ║ supervisor.sh ║
60
+ ║ ║
61
+ ║ reads tasks.conf → for each [task] block: ║
62
+ ║ - create git branch + worktree ║
63
+ ║ - copy .claude/ into worktree ║
64
+ ║ - open tmux window ║
65
+ ║ - launch claude CLI ║
66
+ ╚══════════╤═══════════════════════╤════════════════════════╤═════════╝
67
+ │ │ │
68
+ ▼ ▼ ▼
69
+ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐
70
+ │ tmux window 0 │ │ tmux window 1 │ ... │ tmux window N │
71
+ │ ───────────── │ │ ───────────── │ │ ───────────── │
72
+ │ claude CLI │ │ claude CLI │ │ claude CLI │
73
+ │ task: "..." │ │ task: "..." │ │ task: "..." │
74
+ │ branch: ... │ │ branch: ... │ │ branch: ... │
75
+ │ worktree: ./ │ │ worktree: ./ │ │ worktree: ./ │
76
+ └───────┬────────┘ └────────────────┘ └────────────────┘
77
+
78
+ │ Inside each agent session:
79
+
80
+ ├── reads ── .claude/CLAUDE.md (project memory, known pitfalls)
81
+
82
+ ├── AUTO-DELEGATES TO ── .claude/agents/
83
+ │ (agent decides when based on description: field)
84
+ │ ├── reviewer.md — code review before PR
85
+ │ ├── debugger.md — errors and root cause analysis
86
+ │ ├── test-writer.md — writing unit/integration tests
87
+ │ └── _example-agent.md (blank template)
88
+
89
+ ├── USER-INVOKED ── .claude/commands/
90
+ │ (you type /command in the tmux window)
91
+ │ ├── /techdebt — find and fix technical debt
92
+ │ ├── /explain — explain what code does and why
93
+ │ ├── /diagram — draw ASCII architecture diagrams
94
+ │ └── /learn — Socratic learning session
95
+
96
+ └── RISKY ACTION ── .claude/settings.json
97
+ PermissionRequest hook fires
98
+ └── claude-opus-4-6 evaluates: allow / deny
99
+ ```
100
+
101
+ **Two triggering mechanisms:**
102
+
103
+ | Mechanism | Who triggers it | How |
104
+ |---|---|---|
105
+ | **Sub-agents** (`.claude/agents/`) | The agent itself, automatically | Agent reads the `description:` of each agent and delegates when the task matches. You can also force it: *"Use the debugger agent."* |
106
+ | **Commands / Skills** (`.claude/commands/`) | You, explicitly | Type `/techdebt`, `/explain`, `/diagram`, or `/learn` inside the tmux window at any point during the session. |
107
+
108
+ ---
109
+
110
+ ## Flow Diagrams
111
+
112
+ ### 1. Startup — dependencies, billing, models
113
+
114
+ Everything that runs before any agent is spawned.
115
+
116
+ ```mermaid
117
+ %%{init: {'flowchart': {'curve': 'linear'}}}%%
118
+ flowchart TD
119
+ A(["supervisor.sh [--reset] [repo_path]\nrepo_path defaults to PWD"]) --> B[source lib/utils.sh]
120
+ B --> C["check_deps()\nscan for: git · tmux · npm · claude"]
121
+
122
+ C --> C1{any tools\nmissing?}
123
+ C1 -- no --> BM
124
+ C1 -- yes --> C2["list all missing tools\n+ install instructions"]
125
+ C2 --> C3{"auto-install?"}
126
+ C3 -- no --> C4[print instructions and exit]
127
+ C3 -- yes --> C5["install in order:\nnvm → npm → claude · tmux"]
128
+ C5 --> C6{succeeded?}
129
+ C6 -- no --> C4
130
+ C6 -- yes --> BM
131
+
132
+ BM["ask_billing_mode(repo_path)"]
133
+ BM --> BM1{ANTHROPIC_API_KEY\nin env var?}
134
+ BM1 -- yes --> BM_API["mode = api"]
135
+ BM1 -- no --> BM1b{ANTHROPIC_API_KEY\nin project .env?}
136
+ BM1b -- yes --> BM_API
137
+ BM1b -- no --> BM2{"saved preference\nin .env?\n(skipped if --reset)"}
138
+ BM2 -- yes --> BM_SAVED["use saved mode"]
139
+ BM2 -- no --> BM3["prompt:\n1) Pro subscription\n2) API key"]
140
+ BM3 --> BM_SAVE["_save_billing_mode()\npersist choice to .env"]
141
+ BM_SAVE --> BM_CHECK
142
+
143
+ BM_API --> BM_CHECK
144
+ BM_SAVED --> BM_CHECK
145
+
146
+ BM_CHECK{"API key\nbilling?"}
147
+ BM_CHECK -- no --> FM
148
+ BM_CHECK -- yes --> AK
149
+
150
+ AK["resolve_api_key(repo_path)"]
151
+ AK --> AK1{already loaded?}
152
+ AK1 -- yes --> AK4["export ANTHROPIC_API_KEY"]
153
+ AK1 -- no --> AK2["prompt: read -s"]
154
+ AK2 --> AK4
155
+ AK4 --> AK5["save_api_key_to_env()\npersist to .env · ensure .gitignore"]
156
+ AK5 --> FM
157
+
158
+ FM["fetch_models()"]
159
+ FM --> FM1{"Pro billing?"}
160
+ FM1 -- yes --> FM2["STATIC_MODELS array\n(no API call)"]
161
+ FM1 -- no --> FM3["curl GET /v1/models"]
162
+ FM2 --> FM5[(AVAILABLE_MODELS)]
163
+ FM3 --> FM4["parse JSON\njq or grep/sed"]
164
+ FM4 --> FM5
165
+ FM3 -- failure --> FM2a["fall back to STATIC_MODELS"]
166
+
167
+ FM5 --> HK{"API billing?"}
168
+ HK -- no --> DONE(["→ task loop"])
169
+ HK -- yes --> HK1["_check_hook_model()\nverify PermissionRequest\nhook model is available"]
170
+ HK1 --> DONE
171
+ ```
172
+
173
+ ### 2. Task loop — parse config and spawn agents
174
+
175
+ The supervisor's orchestration: reads `tasks.conf`, resolves defaults, spawns one agent per block.
176
+
177
+ ```mermaid
178
+ %%{init: {'flowchart': {'curve': 'linear'}}}%%
179
+ flowchart TD
180
+ START(["tasks.conf loaded"]) --> LOOP["for each [task] block"]
181
+
182
+ LOOP --> BR{branch\nempty?}
183
+ BR -- yes --> BR1["slugify(prompt)\n→ branch_name"]
184
+ BR -- no --> MD
185
+ BR1 --> MD
186
+
187
+ MD{model\nin config?}
188
+ MD -- yes --> MO
189
+ MD -- no --> MD1["pick_model()\nnumbered menu\nfrom AVAILABLE_MODELS"]
190
+ MD1 --> MO
191
+
192
+ MO{mode?}
193
+ MO -- "normal (default)" --> SA
194
+ MO -- plan --> SA
195
+
196
+ SA["spawn-agent.sh\nrepo · branch · model\nmode · index · prompt"]
197
+
198
+ SA --> NEXT{more tasks?}
199
+ NEXT -- yes --> LOOP
200
+ NEXT -- no --> END["summary box:\nOption A — tmux attach\nOption B — per-agent\ncd && claude commands"]
201
+ ```
202
+
203
+ ### 3. spawn-agent — worktree, tmux, launch
204
+
205
+ What happens inside each `spawn-agent.sh` call.
206
+
207
+ ```mermaid
208
+ %%{init: {'flowchart': {'curve': 'linear'}}}%%
209
+ flowchart TD
210
+ IN(["spawn-agent.sh\nrepo · branch · model\nmode · index · prompt"]) --> V[validate git repo]
211
+ V --> WT["git worktree add -b branch\n(reuse if exists)"]
212
+ WT --> CP["copy .claude/ into worktree\nCLAUDE.md · agents/\ncommands/ · settings.json"]
213
+ CP --> SC["write startup script\n.claude-agent-start.sh\n• export API key (if set)\n• print banner\n• exec claude --model …"]
214
+
215
+ SC --> TM{tmux session\nexists?}
216
+ TM -- yes --> TM1["tmux new-window\nnamed branch_name\nruns startup script"]
217
+ TM -- no --> TM2["tmux new-session\nnamed repo-agents\nruns startup script"]
218
+ TM1 --> SW
219
+ TM2 --> SW
220
+
221
+ SW["setup_window()\nassign color from palette\nplan mode → yellow"]
222
+ SW --> AP["background: sleep 5\ntmux send-keys\nauto-paste task prompt"]
223
+ AP --> DONE(["agent running"])
224
+ ```
225
+
226
+ ---
227
+
228
+ ## Shared Utilities (lib/utils.sh)
229
+
230
+ | Function | Description |
231
+ |---|---|
232
+ | `check_deps` | Scans for all required tools; lists all missing ones with instructions; offers one-shot auto-install in correct dependency order |
233
+ | `ask_billing_mode` | Determines billing mode (Pro vs API key); checks for saved preference in `.env`; prompts if first run or `--reset` flag used; saves choice to `.env` |
234
+ | `_save_billing_mode` | Persists `CLAUDE_SUPERVISOR_ANTHROPIC_BILLING_MODE` to project's `.env` file; updates existing line or appends; ensures `.env` is gitignored |
235
+ | `resolve_api_key` | **API users only**: Checks env var → project `.env` → prompts via `read -s` if neither; passes explicitly to each tmux window — no reliance on inheritance |
236
+ | `save_api_key_to_env` | Persists `ANTHROPIC_API_KEY` to the project's `.env` file; creates file if needed; appends without destroying existing keys; ensures `.env` is gitignored |
237
+ | `show_available_models` | First-run model discovery: resolves API key (env → `.env` → prompt), fetches models, displays formatted list; soft-fail everywhere |
238
+ | `fetch_models` | **Pro users**: use `STATIC_MODELS` array. **API users**: hits Anthropic API once; populates `AVAILABLE_MODELS` array; `jq` if available, `grep`/`sed` fallback |
239
+ | `pick_model` | Shows task description + numbered model menu from `AVAILABLE_MODELS`; returns model ID — called per agent so user decides deliberately |
240
+ | `slugify "<text>"` | Converts free text to a valid git branch name |
241
+ | `setup_window <index> <mode>` | Assigns a color from palette by agent index; plan-mode gets a distinct color; sets tmux window color + title; sets Ghostty tab title via OSC escape if detected |
242
+
243
+ ---
244
+
245
+ ## Templates
246
+
247
+ The `templates/` directory contains files that are scaffolded into the target project on first run. **The user never edits anything in `templates/` directly.** All files are written to `<project>/` once and then owned by the user.
248
+
249
+ ---
250
+
251
+ ### `templates/tasks.conf` → `<project>/tasks.conf`
252
+
253
+ Read by the supervisor at runtime. The user defines one `[task]` block per agent. Only `prompt` is required — `branch`, `model`, and `mode` are optional. Agents never see this file — each agent IS one task block.
254
+
255
+ ```ini
256
+ # Format: INI-style blocks
257
+ #
258
+ # [task]
259
+ # prompt = description of the task (required)
260
+ # branch = optional-branch-name (default: auto-generated from prompt)
261
+ # model = optional-model-id (default: prompted interactively)
262
+ # mode = normal | plan (default: normal)
263
+
264
+ # --- Plan phase (read-only agents, write the plan before any code changes) ---
265
+
266
+ [task]
267
+ mode = plan
268
+ prompt = review the codebase and write a detailed implementation plan for OAuth2 login
269
+
270
+ [task]
271
+ mode = plan
272
+ prompt = review the above plan as a staff engineer and flag risks or missing steps
273
+
274
+ # --- Execution phase (workers execute once the plan is approved) ---
275
+
276
+ [task]
277
+ branch = feature-auth
278
+ model = claude-sonnet-4-5-20250929
279
+ prompt = implement the OAuth2 login flow per the approved plan
280
+
281
+ [task]
282
+ branch = fix-login-bug
283
+ model = claude-haiku-4-5-20251001
284
+ prompt = fix the login session timeout bug
285
+
286
+ [task]
287
+ prompt = refactor the DB layer to use connection pooling
288
+ ```
289
+
290
+ ---
291
+
292
+ ### `templates/CLAUDE.md` → `<project>/.claude/CLAUDE.md`
293
+
294
+ Copied into every worktree at agent spawn time. This is the project's memory — every agent reads it. The user fills in project specifics; the "Known Pitfalls" section grows over time as agents document corrections.
295
+
296
+ ```markdown
297
+ # Project Memory
298
+ > After every correction, add a note to Known Pitfalls so the next agent doesn't repeat it.
299
+
300
+ ## Project Overview
301
+ - What it does: <describe briefly>
302
+ - Stack: <language · framework · key libraries>
303
+ - Entry point: <e.g. src/main.ts>
304
+
305
+ ## Conventions
306
+ - Style: <e.g. ESLint + Prettier>
307
+ - Tests: <e.g. Jest — run with: npm test>
308
+
309
+ ## Known Pitfalls
310
+ - <example: never use process.env directly — use the config module in src/config.ts>
311
+
312
+ ## Agent Instructions
313
+ - Always explain the WHY behind every change — reasoning and tradeoffs, not just what changed
314
+ - Use subagents for narrow isolated tasks — delegate to keep your main context clean
315
+ - Run tests before marking any task done
316
+ - Use /model to switch to a cheaper model once complex planning is complete
317
+ - Use /agents to see available subagents for this project
318
+ ```
319
+
320
+ ---
321
+
322
+ ### `templates/.claude/settings.json` → `<project>/.claude/settings.json`
323
+
324
+ Copied into every worktree. Configures the `PermissionRequest` hook: when a cheap agent needs permission for a risky action, Opus evaluates it instead of interrupting the user.
325
+
326
+ **Model deprecation risk:** The `"model"` field is hardcoded. When Anthropic deprecates a model ID, the hook fails silently — the permission request goes through without evaluation. The supervisor guards against this: after `fetch_models` it checks whether the model in `settings.json` is still in the live model list. If not, it prints a warning and lists current Opus models as replacements. Users update the one field in their project's `.claude/settings.json` when this happens.
327
+
328
+ ```json
329
+ {
330
+ "hooks": {
331
+ "PermissionRequest": [
332
+ {
333
+ "hooks": [
334
+ {
335
+ "type": "prompt",
336
+ "model": "claude-opus-4-6",
337
+ "prompt": "A Claude agent on a cheaper model is requesting permission. Deny if destructive, irreversible without justification, or out of scope. Approve if clearly safe and aligned with the task. Return only JSON: {\"ok\": true} or {\"ok\": false, \"reason\": \"<why>\"}. Context: $ARGUMENTS",
338
+ "timeout": 30
339
+ }
340
+ ]
341
+ }
342
+ ]
343
+ }
344
+ }
345
+ ```
346
+
347
+ ---
348
+
349
+ ### `templates/.claude/agents/` → `<project>/.claude/agents/`
350
+
351
+ Each `.md` file defines a **subagent** — a specialized Claude instance with its own system prompt, tool access, and `description:` field. Claude Code reads these automatically at session start. The agent delegates to them based on the `description:` field — no user action required.
352
+
353
+ Every worktree gets a copy of this directory, so all spawned agents share the same subagent pool.
354
+
355
+ **Shipped subagents:**
356
+
357
+ | File | `description:` trigger | Tools |
358
+ |---|---|---|
359
+ | `reviewer.md` | Reviews code before PR — flags issues, ends with APPROVE / REQUEST CHANGES | Read, Glob, Grep, Bash |
360
+ | `debugger.md` | Errors, failures, unexpected behavior — root cause + minimal fix | Read, Glob, Grep, Edit, Bash |
361
+ | `test-writer.md` | Writing unit/integration tests for a module or function | Read, Glob, Grep, Edit, Write, Bash |
362
+ | `_example-agent.md` | Blank template — copy and fill in `name:`, `description:`, `tools:`, body | — |
363
+
364
+ ### `templates/.claude/commands/` → `<project>/.claude/commands/`
365
+
366
+ Each `.md` file defines a **skill** (slash command) — invoked by the user with `/command-name` inside any Claude session. Unlike subagents, skills run in the main agent's context and are always user-triggered.
367
+
368
+ **Shipped commands:**
369
+
370
+ | File | Invoked with | What it does |
371
+ |---|---|---|
372
+ | `techdebt.md` | `/techdebt` | Finds and fixes duplicated code, dead code, over-engineering |
373
+ | `explain.md` | `/explain` | Explains code: what/why/how/fits-in/gotchas |
374
+ | `diagram.md` | `/diagram` | Draws ASCII diagrams of architecture, data flow, or call chains |
375
+ | `learn.md` | `/learn` | Socratic session — you explain, Claude asks follow-ups, saves a summary |
376
+
377
+ ---
378
+
379
+ ## Config File Format
380
+
381
+ INI-style blocks. Each `[task]` header starts a new agent. Only `prompt` is required.
382
+
383
+ ```ini
384
+ [task]
385
+ prompt = description of the task # required
386
+ branch = optional-branch-name # default: auto-generated from prompt via slugify
387
+ model = optional-model-id # default: user is prompted with model menu
388
+ mode = normal | plan # default: normal
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Plan Mode Workflow
394
+
395
+ For complex tasks the team pattern is:
396
+
397
+ 1. **Planner agent** — spawned with `--permission-mode plan`; writes a detailed plan before touching any code
398
+ 2. **Reviewer agent** — also in plan mode; reads the plan as a staff engineer and flags risks
399
+ 3. **Worker agents** — spawned in normal mode to execute once the plan is approved
400
+ 4. **Re-plan on failure** — if a worker goes sideways, spawn a new plan-mode agent to reassess before continuing
401
+
402
+ This is reflected in the `mode` config field. Plan mode agents use read-only tools and cannot modify files until the user approves the plan.
403
+
404
+ ---
405
+
406
+ ## CLAUDE.md as Agent Memory
407
+
408
+ When `spawn-agent.sh` creates a worktree it copies `CLAUDE.md` from the main repo root into the worktree. Each agent's banner includes the reminder:
409
+
410
+ > **Update CLAUDE.md if you make a correction — so the next agent doesn't repeat the same mistake.**
411
+
412
+ Over time, CLAUDE.md accumulates project-specific constraints, patterns, and known pitfalls that all agents inherit automatically.
413
+
414
+ ### Why agents update only their worktree's copy
415
+
416
+ Agents do **not** write back to the main repo's `.claude/CLAUDE.md`. This is intentional:
417
+
418
+ 1. **Race conditions** — Multiple agents run in parallel. Concurrent writes to the same file would cause conflicts and corruption.
419
+ 2. **Branch isolation** — Each worktree is a separate git checkout on its own branch. Reaching across into the main repo's working directory to modify files would violate the isolation that makes parallel work safe.
420
+ 3. **Review gate** — Not every agent-discovered pitfall is correct or relevant. The owner should review before merging into the shared memory that all future agents inherit.
421
+
422
+ The reconciliation path is deliberate: agents commit CLAUDE.md changes with their branch work, and the owner runs `collect-learnings.sh [--yes] <repo>` to diff all worktrees against main and selectively merge new lines back. Use `--yes` to auto-approve all merges (useful in CI or scripts). Once merged, commit the updated main CLAUDE.md. Only then can worktrees be safely purged.
423
+
424
+ ---
425
+
426
+ ## Model Selection and Credit Management
427
+
428
+ ### Two separate model choices
429
+
430
+ Opus only activates for permission decisions — not for the actual agent work. There are two completely separate model choices happening:
431
+
432
+ **1. Agent model** — chosen by the user via `pick_model` before each agent spawns. This is the model that does the actual work: reading files, writing code, running commands. The user picks from the live model list fetched from `/v1/models`. There is no hardcoded default — the menu presents all available models and the user selects one per task.
433
+
434
+ **2. PermissionRequest hook model** — hardcoded to `claude-opus-4-6` in `settings.json`. This only fires when an agent needs permission for a potentially risky action. Opus evaluates the request for a few seconds and returns allow/deny. It does not run continuously.
435
+
436
+ Typical flow:
437
+ ```
438
+ User picks Haiku for agent → agent does 95% of the work cheaply
439
+
440
+ Agent tries to delete a file → PermissionRequest hook fires
441
+
442
+ Opus evaluates for ~2s: "is this safe given the task?" → allow / deny
443
+
444
+ Agent continues on Haiku
445
+ ```
446
+
447
+ Opus is the gatekeeper on risky actions, not the worker. The point is to keep the bulk of compute on cheap models while using Opus only where its judgement actually matters.
448
+
449
+ ---
450
+
451
+ ### Agent model menu
452
+
453
+ `pick_model` is called **per agent** when no model is specified in the config. Before showing the menu, the agent's task description is displayed so the user can make an informed decision:
454
+
455
+ ```
456
+ Task : fix the login timeout bug
457
+ Branch: fix-login-bug
458
+
459
+ Available models:
460
+ 1) claude-haiku-4-5-20251001 — fastest · cheapest
461
+ 2) claude-sonnet-4-5-20250929 — balanced
462
+ 3) claude-opus-4-6 — most capable · most expensive
463
+
464
+ Select model for this agent [1]: _
465
+ ```
466
+
467
+ To switch models **mid-session** inside an active agent, use the `/model` command in the claude prompt. This is noted in the banner so users are aware they can downgrade to a cheaper model once a complex planning phase is done.
468
+
469
+ ---
470
+
471
+ ## Subagents & Hooks
472
+
473
+ ### Two levels of agents
474
+
475
+ Agents in this system operate at two levels:
476
+
477
+ | Level | What it is | Who manages it |
478
+ |---|---|---|
479
+ | **Supervisor level** | Each task spawned by `supervisor.sh` is an independent Claude Code process | The supervisor script |
480
+ | **Within each agent** | That agent can itself spawn subagents for narrow sub-tasks via the `Task` tool | Claude Code internally |
481
+
482
+ The second level is free — Claude Code handles it automatically. We support it by:
483
+ 1. Copying `.claude/agents/` from the main repo into each worktree so custom subagent definitions are available
484
+ 2. Including an instruction in the CLAUDE.md template: *"Use subagents for narrow, isolated tasks. Delegate to keep your main context clean."*
485
+ 3. Banner hint: `subagents available — use /agents to view`
486
+
487
+ ### Permission routing via PermissionRequest hook
488
+
489
+ This is the concrete implementation of "route permission checks to Opus":
490
+
491
+ **The pattern:**
492
+ - Worker agent runs on Haiku or Sonnet (cheap, fast)
493
+ - Before a risky tool call fires, the `PermissionRequest` hook intercepts the permission dialog
494
+ - The hook uses `type: "prompt"` with `model: "claude-opus-4-6"` to ask Opus whether to allow or deny
495
+ - Opus evaluates the action in context and returns `{ "ok": true }` or `{ "ok": false, "reason": "..." }`
496
+ - Result: cheap model does 95% of the work, Opus only activates on trust decisions
497
+
498
+ **What the hook looks like (`templates/.claude/settings.json`):**
499
+ ```json
500
+ {
501
+ "hooks": {
502
+ "PermissionRequest": [
503
+ {
504
+ "hooks": [
505
+ {
506
+ "type": "prompt",
507
+ "model": "claude-opus-4-6",
508
+ "prompt": "A Claude agent is requesting permission to use a tool. Evaluate if this action is safe and appropriate given the task context. Deny if it looks destructive, out of scope, or risky. Context: $ARGUMENTS",
509
+ "timeout": 30
510
+ }
511
+ ]
512
+ }
513
+ ]
514
+ }
515
+ }
516
+ ```
517
+
518
+ **How it reaches each agent:**
519
+ `spawn-agent.sh` copies the full `.claude/` directory from the main repo into the worktree. The auto-init step scaffolds `settings.json` from `templates/` into the project on first run, so every agent inherits the hook automatically.
520
+
521
+ ### Other useful hooks (extension points)
522
+
523
+ | Hook | Use case |
524
+ |---|---|
525
+ | `PostToolUse` (Write/Edit) | Auto-run linter or tests after file changes |
526
+ | `Stop` | Block agent from stopping until tests pass |
527
+ | `TaskCompleted` | Enforce quality gates before a task closes |
528
+ | `PreCompact` | Save a summary before context is compacted |
529
+ | `SessionEnd` | Log session stats or notify on completion |
530
+
531
+ These are not implemented by the supervisor — they live in the project's `.claude/settings.json` and travel with each worktree automatically.
532
+
533
+ ---
534
+
535
+ ## Terminal Setup
536
+
537
+ ### Detection
538
+ `setup_window` detects the terminal at runtime:
539
+ - `$TERM_PROGRAM == "ghostty"` → Ghostty is active
540
+ - `$TMUX` set → inside a tmux session
541
+ - Anything else → plain terminal fallback (colors via ANSI only)
542
+
543
+ ### Color-coded windows
544
+ Each agent window gets a color assigned by index from a fixed palette defined in `utils.sh`. Plan-mode agents always get **yellow** to visually distinguish them from workers.
545
+
546
+ | Agent index | tmux color | Ghostty tab |
547
+ |---|---|---|
548
+ | 0 | `colour33` (blue) | OSC `\033]0;branch\007` |
549
+ | 1 | `colour70` (green) | same |
550
+ | 2 | `colour166` (orange) | same |
551
+ | plan mode | `colour220` (yellow) | same |
552
+ | ... | cycles through palette | same |
553
+
554
+ Ghostty tab title is set via standard OSC 0 (`\033]0;title\007`) which Ghostty supports natively. Color per tab is not forced — the color-coding lives in tmux windows, visible when tiling or switching.
555
+
556
+ ### Statusline
557
+ The Claude Code `/statusline` feature (shows context usage + git branch at the bottom of each session) is a **one-time global config** — set it once with `/statusline` in any claude session and it applies everywhere. The agent banner includes a reminder for users who haven't configured it yet.
558
+
559
+ ---
560
+
561
+ ## Key Design Decisions
562
+
563
+ - `check_deps` scans everything upfront, reports all missing tools at once, installs in correct dependency order (nvm → npm → claude)
564
+ - User has **one decision point** for installs — auto or manual — not one per tool
565
+ - `ask_billing_mode` determines Pro vs API billing; saves preference to project's `.env` file to avoid re-prompting; `--reset` flag skips saved preference
566
+ - `resolve_api_key` **API users only**: checks env var → project `.env` → `read -s` prompt; key is passed explicitly to each tmux window, not relying on environment inheritance
567
+ - `save_api_key_to_env` persists the key to the project's `.env` file on every run (idempotent); ensures `.env` is gitignored so secrets are never committed
568
+ - `repo_path` defaults to `$PWD` — no argument needed if running from inside the project
569
+ - `fetch_models` is called **once** per supervisor run — list is reused for all `pick_model` calls
570
+ - `pick_model` is called **per agent** intentionally — user decides model per task to manage credit consumption
571
+ - `/model` mid-session switching is surfaced in the banner for in-flight credit management
572
+ - The full `.claude/` directory is copied into every worktree — agents inherit CLAUDE.md memory, custom subagent definitions, and hook configs
573
+ - `PermissionRequest` hook routes permission decisions to Opus — cheap models work, Opus decides on risky actions
574
+ - Plan mode agents write and review plans before any code is written — workers execute after approval
575
+ - `setup_window` detects Ghostty vs tmux at runtime — no hard dependency on either
576
+ - Plan-mode windows are always yellow — visually distinct from worker windows
577
+ - `/statusline` is a one-time global config; not managed per-agent
578
+ - `spawn-agent.sh` is independently testable without the supervisor
579
+ - All logic shared between scripts lives in `lib/utils.sh`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AlexCD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.