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.
- package/ARCHITECTURE.md +579 -0
- package/LICENSE +21 -0
- package/README.md +970 -0
- package/VERSION +1 -0
- package/bin/collect-learnings.sh +186 -0
- package/bin/setup-shortcuts.sh +147 -0
- package/bin/spawn-agent.sh +167 -0
- package/bin/supervisor.sh +357 -0
- package/lib/utils.sh +536 -0
- package/package.json +44 -0
- package/templates/.claude/agents/_example-agent.md +28 -0
- package/templates/.claude/agents/debugger.md +42 -0
- package/templates/.claude/agents/reviewer.md +32 -0
- package/templates/.claude/agents/test-writer.md +38 -0
- package/templates/.claude/commands/diagram.md +24 -0
- package/templates/.claude/commands/explain.md +19 -0
- package/templates/.claude/commands/learn.md +30 -0
- package/templates/.claude/commands/techdebt.md +24 -0
- package/templates/.claude/settings.json +16 -0
- package/templates/CLAUDE.md +55 -0
- package/templates/tasks.conf +40 -0
package/ARCHITECTURE.md
ADDED
|
@@ -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.
|