@ferris1225/pi-subagents 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,457 +1,475 @@
1
- # pi-subagents
2
-
3
- [![npm version](https://img.shields.io/npm/v/@ferris1225/pi-subagents?color=blue)](https://www.npmjs.com/package/@ferris1225/pi-subagents)
4
- [![downloads](https://img.shields.io/npm/dm/@ferris1225/pi-subagents)](https://www.npmjs.com/package/@ferris1225/pi-subagents)
5
- [![license](https://img.shields.io/npm/l/@ferris1225/pi-subagents)](./LICENSE)
6
- ![platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey)
7
- ![pi](https://img.shields.io/badge/pi-extension-orange)
8
-
9
- Focused background delegation for [pi](https://pi.dev): `explore` / `worker` /
10
- `cleaner` / `reviewer` agents run in **isolated child processes** and hand their
11
- results back to the main agent automatically. Install it, and the main model
12
- starts using it on its own — no prompt engineering, no babysitting.
13
-
14
- ## 2.0.0 — direct model handoff and capability-aware thinking
15
-
16
- Version 2 removes backup pools and global thinking strength. Every agent now has
17
- one optional selected model; any model/provider failure hands its retained session
18
- directly to the current main model, while ordinary tool/task failures stay put.
19
- Thinking defaults to Auto and is clamped through Pi's real model capability map.
20
- The setup menu and normalized config drop the obsolete options instead of carrying
21
- compatibility aliases.
22
-
23
- This release also adds semantic routing to a dedicated evidence-first `cleaner`
24
- and makes the active widget show each run's task, effective model/thinking,
25
- activity, and elapsed time. Every dispatch has a stable run id, so work can be
26
- steered while it runs, parked without losing context, resumed after settlement,
27
- retargeted, or forked into another path. Generation ownership keeps startup-race
28
- retries and stale child processes from corrupting the logical thread without
29
- retaining a duplicate event history.
30
-
31
- The common quality loop now runs end to end without waking the main agent between
32
- steps:
33
-
34
- ```text
35
- reviewer (find issues) → worker (fix every finding) → reviewer (verify) → final PASS/FAIL
36
- ```
37
-
38
- Reviews use a single flat findings list — no severity triage. Every reported
39
- finding is fixed before the change is accepted, and each re-review converges on
40
- an open-finding set: the worker's explicit rejections are adjudicated once, only
41
- defects a fix round introduced or exposed are added, and resolved items never
42
- re-open. `maxFixRounds` stays the hard cap, so a chain always settles and wakes
43
- the main agent with the full picture.
44
-
45
- Cleanup stays a separate lifecycle: explicit cleanup intent can dispatch the
46
- evidence-first `cleaner`; any edits still go through the independent `reviewer`
47
- gate.
48
-
49
- Each chain is delivered as one concise completion group whose footer totals the
50
- aggregate token usage and cost of every included run, while full per-run reports
51
- remain available through `subagent_status`. Its parent stays `running`
52
- until the whole chain settles; completed internal rounds leave active status
53
- immediately, so no `done` row keeps accumulating elapsed time. Selected-to-main
54
- model handoffs keep the same retained context, and isolated parallel workers use
55
- detached Git worktrees whose changes are applied back without touching the parent
56
- index.
57
-
58
- ## Highlights
59
-
60
- - **Zero-setup proactive dispatch** the extension injects a delegation directive
61
- into the main system prompt, so the main model sends broad searches to `explore`,
62
- self-contained implementations to `worker`, explicit cleanup intent to `cleaner`,
63
- and pre-commit reviews to `reviewer`. You just use pi; delegation happens by itself.
64
- - **Multimodal work is a model choice, not a mode** — an agent that should see
65
- screenshots, mockups, or its own rendered pages simply gets a multimodal model
66
- through `/subagents-setup` (the picker labels each model `vision` or
67
- `text-only`). The agent reads images with its `read` tool on whatever model it
68
- runs; no per-task flag, no separate vision override.
69
- - **Results come back on their own** — completions are delivered as messages that
70
- wake the main agent automatically, even mid-turn. No polling, no `sleep`, no
71
- "go check" step. `subagent_wait` is a **non-blocking** in-turn lookup by default
72
- (pass `timeoutMs` to block); `subagent_status` inspects runs; `subagent_stop`
73
- cancels one and delivers its partial output.
74
- - **Active-only live widget, as a tree** — each queued or running sub-agent gets one compact
75
- width-aware primary line with task, effective model/thinking, and elapsed time; current
76
- activity appears only when present on an indented second line. Auto-fix rounds nest under
77
- the triggering reviewer row that owns the chain, so it is always visible who dispatched
78
- what; no run ids appear here the tree and the task label identify each row:
79
- ```text
80
- reviewer · review diff of src/foo.ts · claude-sonnet-4-5/high · 42s
81
- worker · fix round 1 · src/foo.ts · claude-sonnet-4-5/high · 10s
82
- │ grep cacheKey
83
- reviewer · re-review round 1 · claude-sonnet-4-5/high · 3s
84
- ```
85
- Long tasks and activity paths truncate first (preserving a useful path tail when
86
- possible), groups have no blank rows, and settled/parked runs disappear immediately.
87
- - **Results are not re-narrated** a sub-agent's completion is shown to you
88
- verbatim, and the main agent is told not to paraphrase it back. It replies with
89
- only its own conclusion or next step, so the same findings are never paid for
90
- twice in tokens.
91
- - **Evidence-first cleanup, not deletion by guesswork** `cleaner` distinguishes
92
- read-only audit wording from explicit apply wording, proves consumers and dynamic
93
- entrypoints before cutting, and treats finding nothing safe as a valid outcome.
94
- It is periodic/intent-driven, never PR-count-driven or an automatic commit gate.
95
- - **A quality gate that closes the loop** when a reviewer returns `REVIEW_FAIL`,
96
- the extension dispatches a worker briefed with the concrete findings, then a
97
- re-review, up to `maxFixRounds` timesand only then wakes the main agent.
98
- Every reported finding gets fixed (no severity triage), and re-reviews converge
99
- on an open-finding set instead of ping-ponging: worker rejections are adjudicated
100
- once, only defects the fix round introduced are added, and resolved items never
101
- re-open. Every round stays in the triggering reviewer's cwd, and chains that target the
102
- same repository are serialized so shared-checkout edits cannot race.
103
- - **Direct fallback with real thinking capabilities** each agent has at most
104
- one selected model. An unavailable selection, rate limit, invalid key, quota,
105
- missing model, or provider failure hands directly to the current main model.
106
- A child-only provider adapter forces inner request retries to zero; transient
107
- stream drops still use Pi's outer turn retry, and only a settled model-level
108
- failure hands off, without changing user settings. Auto thinking clamps the
109
- agent preference to the
110
- effective model's real `thinkingLevelMap`; manual setup shows only levels that
111
- model supports.
112
- - **Resumes, retargets, and forks preserve context** every run is session-backed.
113
- `subagent_control` can steer active work, retarget it after a stable abort,
114
- park/resume it under the same run id, or fork a parked/settled checkpoint into
115
- a new independent run. Concurrent resume calls are serialized.
116
- - **Concise but honest completions** group completions end with aggregate token
117
- and cost totals across every included run; failed-tool diagnostics stay out of the
118
- delivered message and remain one `subagent_status` call away. Actual process,
119
- model, and integration failures still surface as failures.
120
- - **Parallel fan-out with filesystem isolation** — independent tasks run up to a
121
- configurable limit (default 4). Parallel workers default to detached Git
122
- worktrees; tracked, deleted, untracked, and binary changes are applied back
123
- without touching the parent index. Failed integration keeps recovery artifacts.
124
- - **Recursion is structurally impossible** — children are leaf processes; the
125
- `subagent` tool is excluded from their toolset.
126
- - **Zero runtime dependencies** agents are plain Markdown files; overriding or
127
- adding one is writing a file.
128
- - **Update announcements** when a new configurable feature ships, you are told
129
- about it once (a persisted marker stops the notice from nagging).
130
-
131
- ## What this adds beyond generic subagent dispatch
132
-
133
- This package combines several concrete runtime behaviors rather than only exposing
134
- an undifferentiated child-agent launcher:
135
-
136
- - language-agnostic semantic role guidance for cleanup intent;
137
- - a dedicated evidence-first cleaner, with cleanup kept separate from the
138
- independent reviewer gate;
139
- - isolated, retained threads that can be steered, parked, resumed, retargeted, or
140
- forked under stable run ids;
141
- - the reviewer worker auto-fix reviewer loop, fixing every finding under a
142
- convergence contract with a hard round cap;
143
- - failed-tool diagnostics available by run id through `subagent_status`;
144
- - direct selected→main fallback plus capability-aware Auto thinking;
145
- - detached Git worktree isolation for parallel workers and opt-in write-capable
146
- cleaner runs.
147
-
148
- ## Install
149
-
150
- ```bash
151
- pi install npm:@ferris1225/pi-subagents
152
- ```
153
-
154
- Requires pi **>= 0.83.0**. After installation, open the setup wizard in an
155
- interactive TUI session:
156
-
157
- ```text
158
- /subagents-setup
159
- ```
160
-
161
- Fresh installs enable `explore`, `worker`, `cleaner`, and `reviewer` — you can
162
- start delegating immediately. Existing explicit `enabledAgents` lists are never
163
- silently extended; users upgrading with an existing explicit list get a one-time
164
- notice to opt into `cleaner` with `/subagents-setup`.
165
-
166
- ## The agents
167
-
168
- | Agent | Access | Purpose |
169
- | --- | --- | --- |
170
- | `explore` | Read-only | Fast codebase reconnaissance: broad/open-ended search, multi-file lookups, mapping unfamiliar code. Returns compressed, structured findings. |
171
- | `worker` | Full | Implements, fixes, refactors, and tests a self-contained task end to end, then reports honest verification. |
172
- | `cleaner` | Full | Evidence-first cleanup. Audits and ranks candidates read-only, or applies the smallest proven cuts when removal is explicit; supports worktree isolation. |
173
- | `reviewer` | Read-only | Adversarial pre-commit quality gate: independently reviews worker and cleaner edits, plus plans, proposed solutions, codebase health, and PR/issue validation. |
174
-
175
- Each agent runs in its own isolated `pi` process with a clean context window; it
176
- has no memory of your conversation, so briefs must be self-contained (goal, exact
177
- paths, constraints, expected output).
178
-
179
- ## Usage
180
-
181
- ### Single task
182
-
183
- ```ts
184
- subagent({ agent: "explore", task: "Map the test setup: which files run what, and how is CI wired? Report exact paths." });
185
- subagent({ agent: "worker", task: "Implement X in src/foo.ts, add tests, run npm test." });
186
- subagent({ agent: "cleaner", task: "Audit src/cache for dead code and redundant state; report ranked evidence only." });
187
- subagent({ agent: "cleaner", task: "Remove the proven dead cache adapter, update its tests/docs, and verify the smallest then broad checks." });
188
- subagent({ agent: "reviewer", task: "Review the diff of src/index.ts and tests/load.test.ts for correctness and edge cases." });
189
- ```
190
-
191
- ### Parallel tasks
192
-
193
- ```ts
194
- subagent({
195
- tasks: [
196
- { agent: "explore", task: "Where is the selected-to-main handoff logic?" },
197
- { agent: "worker", task: "Add unit tests for models.ts." },
198
- ],
199
- });
200
- ```
201
-
202
- ### Cleanup routing and lifecycle
203
-
204
- The injected guidance routes `cleaner` by explicit semantic intent in any
205
- language the conversation uses: **code cleanup**, **dead code**, redundancy,
206
- simplification, or over-engineering. Requested periodic maintenance passes also
207
- qualify; PR counts do not, and cleaner is never run automatically as the
208
- pre-commit gate.
209
-
210
- - **Audit mode:** audit/find/report/review wording produces read-only ranked
211
- evidence.
212
- - **Apply mode:** explicit remove/clean/simplify/refactor wording permits the
213
- smallest proven edits plus narrow-then-broad verification.
214
-
215
- ```text
216
- explicit cleanup intent cleaner (audit or apply)
217
- cleaner apply reviewer gate → worker auto-fix (on REVIEW_FAIL) → reviewer
218
- ```
219
-
220
- `reviewer` remains the independent gate for non-trivial cleaner edits. The auto-fix
221
- portion runs only when enabled by `maxFixRounds`; cleaner itself is not a pre-commit
222
- hook or a PR-count scheduler.
223
-
224
- ### Image work (screenshots / mockups / designs)
225
-
226
- There is no vision flag or separate vision model. Give the agent a multimodal
227
- model in `/subagents-setup` and name the exact image paths in the task:
228
-
229
- ```ts
230
- subagent({
231
- agent: "reviewer",
232
- task: "Compare the UI in screenshots/settings.png against the mockup design.png; list every visual mismatch.",
233
- });
234
- ```
235
-
236
- The sub-agent reads images with its `read` tool on its configured model; the
237
- setup picker labels each model `vision` or `text-only` so the choice is visible.
238
- The live widget line, dispatch result row, and `subagent_status` all show each
239
- run's effective model id, and a selected→main handoff is labeled with its
240
- origin.
241
-
242
- ### Controlling and stopping
243
-
244
- Dispatch confirmations, tool result rows, and completion blocks all show the
245
- stable `#id`, so a thread remains directly controllable after its live UI is gone
246
- (the widget itself identifies rows by tree position and task instead of ids).
247
-
248
- - `subagent_control` `steer`, `retarget`, `park`, `resume`, or `fork` a logical
249
- thread by stable run id. Resume accepts an optional replacement objective;
250
- fork creates a new id and leaves the source unchanged. Park active work before
251
- forking it.
252
- - `subagent_wait` — in-turn result lookup. **Non-blocking by default**: a settled
253
- run returns immediately; an active run tells the model to end its turn. Pass
254
- `timeoutMs` only when you must stay in the turn.
255
- - `subagent_status` — active/parked/finished runs and full result by run id.
256
- - `subagent_stop` destructive cancellation. It retires that thread's retained
257
- session (independent forks survive) and delivers exactly one aborted partial
258
- result after the run and any worktree integration have quiesced.
259
-
260
- Examples:
261
-
262
- ```ts
263
- subagent_control({ action: "steer", id: 7, instruction: "Check the Windows path too." });
264
- subagent_control({ action: "park", id: 7 });
265
- subagent_control({ action: "resume", id: 7, objective: "Finish the tests." });
266
- subagent_control({ action: "fork", id: 7, objective: "Try the smaller alternative." });
267
- ```
268
-
269
- ### Worktree isolation
270
-
271
- Single tasks default to `isolation: "shared"`. Parallel `worker` tasks default
272
- to `isolation: "worktree"`; opt into shared mode only when a worker must see the
273
- caller's live uncommitted tree. `cleaner` is also write-capable and supports
274
- worktree mode when explicitly requested (its default remains shared). Worktree
275
- mode requires a Git repository with a committed `HEAD` and is rejected for the
276
- read-only `explore` and `reviewer` agents.
277
-
278
- A parked isolated thread keeps its current worktree. Resume it there; fork is
279
- available after that isolated checkpoint settles and its seed is integrated.
280
- Resuming or forking a settled isolated thread creates a fresh worktree, merges a
281
- recorded checkpoint onto the current `HEAD` (including when the seed was already
282
- committed), and clones the Pi session with the new cwd. Forks then integrate only
283
- their unique follow-on edits, so a shared seed is applied once. A run remains
284
- active while final Git integration is in progress and becomes `done` only after
285
- that boundary finishes.
286
-
287
- Every Git operation has a 120-second deadline and process-tree cleanup; captured
288
- Git output and binary patches are capped at 64 MiB. Setup/bound failures surface
289
- instead of hanging. Finalization failures retain the patch/worktree when
290
- available and are recorded in `~/.pi/agent/pi-subagents-recovery.json`; later
291
- sessions show the recovery paths again until the artifacts are removed.
292
-
293
- ## Configuration
294
-
295
- Stored at `~/.pi/agent/pi-subagents.json` (follows `PI_CODING_AGENT_DIR` when
296
- set). `/subagents-setup` has four top-level choices: enable agents, configure one
297
- agent's model/thinking, runtime settings, or full setup.
298
- After one agent's model + thinking picks, the wizard returns to the agent picker
299
- so several agents can be configured in one pass; Esc at any step ends the pass
300
- and keeps every agent already configured. There is no backup pool or global thinking menu. Model pickers show only in-scope
301
- models with configured authentication and display their real supported thinking
302
- levels. Thinking defaults to **Auto**; manual overrides show only levels supported
303
- by that agent's effective model. `notifyOnReviewPass` and `maxResultLines` remain
304
- direct-file settings.
305
-
306
- ```json
307
- {
308
- "enabledAgents": ["explore", "worker", "cleaner", "reviewer"],
309
- "agentModels": {
310
- "explore": "anthropic/claude-haiku-4-5"
311
- },
312
- "agentThinkingLevels": {
313
- "reviewer": "high"
314
- },
315
- "notifyOnReviewPass": false,
316
- "maxResultLines": 80,
317
- "proactiveInjection": true,
318
- "agentScope": "user",
319
- "maxConcurrency": 4,
320
- "maxFixRounds": 2,
321
- "idleTimeoutSec": 90
322
- }
323
- ```
324
-
325
- | Field | Description |
326
- | --- | --- |
327
- | `enabledAgents` | Agent names exposed to discovery and prompt injection. An empty array disables all agents. |
328
- | `agentModels` | Optional selected `provider/model-id` per agent. Missing = current main model. Model-level failure hands directly to current main. |
329
- | `agentThinkingLevels` | Optional manual preference per agent. Missing = Auto (agent frontmatter preference, or `high`, clamped to the effective model's supported levels). |
330
- | `notifyOnReviewPass` | When `true`, a passing reviewer result is delivered without waking the main agent (default `false`). |
331
- | `maxResultLines` | Max lines of a sub-agent result carried in the completion message (default `80`). Longer results are truncated; full text is written to an extension-named temporary `.md`. At session start and on each write, only recognized result files older than 7 days are removed; each canonical project path has its own newest-50 bucket. |
332
- | `proactiveInjection` | Whether to add the delegation directive to the main system prompt. |
333
- | `agentScope` | `user`, `project`, or `both`; controls which user/project agent directories are discovered. |
334
- | `maxConcurrency` | Max sub-agent processes running at once (1–16, default 4), and the max tasks one parallel `subagent` call accepts. Extra work waits in the queue. |
335
- | `maxFixRounds` | Auto-fix rounds when a reviewer returns `REVIEW_FAIL` (default 2; `0` disables the loop). Hard cap: the chain always settles, delivers its condensed summary, and wakes the main agent. |
336
- | `idleTimeoutSec` | Idle watchdog: a sub-agent whose stdout goes silent for this long is terminated; a selected model then hands to current main. `0` disables it. Default 90. |
337
-
338
- ### Model routing and thinking
339
-
340
- ```text
341
- selected agent model current main-window model
342
- ```
343
-
344
- Without a selected model, current main runs immediately; agent frontmatter model
345
- is used only when no main model exists. A selection missing from Pi's live
346
- available catalog is skipped. Any model-level runtime failure rate limit,
347
- quota, invalid key/auth, missing model, provider error, or idle model stream
348
- hands directly to current main, including stream errors that retain partial text.
349
- A child-only Pi extension wraps the selected provider's registered API stream
350
- with `maxRetries: 0` so a deterministic auth/quota miss fails fast. Transient
351
- stream drops such as xAI `terminated` still use Pi's outer turn retry — the
352
- parent does not `abort_retry` them — and only a settled model-level failure
353
- hands off to current main. This uses supported extension/RPC surfaces in Node
354
- and standalone/Bun builds, never rewrites global or project settings, and does
355
- not alter descendant tool environments. Tool/test failures stay on the same
356
- model because they are task failures, not model availability failures. A child is
357
- probed with RPC `get_state` before the first prompt so the 30s command ACK clock
358
- does not include process boot. Only a zero-activity startup miss can retry — a
359
- silent fast exit, a `get_state` handshake timeout, or an initial prompt ACK
360
- timeout before any agent/turn/stream/tool activity. Those transport misses are
361
- not model-level failures and do not hand the task to the main window. An accepted
362
- prompt or any activity forbids replay.
363
-
364
- Auto thinking starts from the Agent's declared preference (`low` for `explore`,
365
- `high` for the other built-ins) and uses Pi's capability map to clamp it to the
366
- actual model. Non-reasoning models resolve to `off`; `xhigh`/`max` appear in setup
367
- only when that model explicitly supports them. A selected→main handoff re-clamps
368
- thinking for the main model.
369
-
370
- ### Choosing an explore model
371
-
372
- Choose a competent fast code model for `explore`, not automatically the cheapest
373
- model. Cheap reconnaissance is useful for mechanical symbol/path discovery, but
374
- a missed dynamic entrypoint or ownership edge can cost more through downstream
375
- rework. Direct main-model handoff handles provider/runtime failure; it cannot
376
- detect a plausible but incomplete answer.
377
-
378
- `explore` therefore returns an index of exact paths, lines, symbols, and explicit
379
- uncertainty. The main agent, worker, or cleaner must re-read load-bearing files
380
- before editing or deciding deletion, security, compatibility, persistence, or
381
- dynamic reachability. Prefer a stronger model or direct specialist for complex
382
- dynamic loading, concurrency, migrations, and security-sensitive code.
383
-
384
- ### Resuming retained context
385
-
386
- Every run stores its Pi session in a private temp directory. A selected→main
387
- handoff resumes that same session, so searches, reads, reasoning, and edits remain
388
- in context. A parked, completed, or failed thread can later be resumed under its
389
- stable id:
390
-
391
- ```ts
392
- subagent_control({ action: "resume", id: 7 });
393
- subagent_control({ action: "resume", id: 7, objective: "Continue with the repaired credentials." });
394
- ```
395
-
396
- Use `fork` when both paths should remain available. `subagent_stop` is the
397
- explicit destructive operation that retires a retained session; otherwise
398
- sessions live until the parent Pi session shuts down.
399
-
400
- ### Configuration migration
401
-
402
- The config file normalizes itself on load no manual steps after an upgrade.
403
- Configured non-empty agent names are preserved, while invalid and obsolete keys
404
- are removed. This release deletes `agentBackupModels` and global `thinkingLevel`
405
- in addition to older `maxParallelTasks` / `maxSubagentDepth`; per-agent thinking
406
- preferences remain and are capability-clamped at runtime. A pre-existing explicit
407
- `enabledAgents` array is still preserved without appending `cleaner`. Existing
408
- configs without it receive a one-time `/subagents-setup` notice, tracked internally
409
- in `announcedFeatures`.
410
-
411
- ## Agent discovery and overrides
412
-
413
- - Built-in agents ship with the package; user agents live in `~/.pi/agent/agents/`;
414
- project agents in the nearest `.pi/agents/` directory are loaded only when Pi
415
- trusts that project.
416
- - For duplicate names: project overrides user overrides built-in. Keep the
417
- matching filename and `name` field to replace a built-in agent.
418
- - Optional frontmatter: `model` (default model reference), `thinking` (default
419
- thinking strength), `tools` (comma-separated tool allow-list; absent = all
420
- tools). Config overrides win at spawn.
421
-
422
- ## How it stays reliable
423
-
424
- - **Direct model recovery** unavailable selections skip immediately; any
425
- selected-model provider/auth/quota/rate-limit failure hands directly to current
426
- main with thinking re-clamped to the main model.
427
- - **Startup-race retries** — a silent zero-activity child exit (concurrent pi
428
- startup lock contention) is relaunched with backoff; only clean silent exits
429
- qualify, so real work is never duplicated.
430
- - **Idle watchdog** — a stalled selected-model stream (no output for
431
- `idleTimeoutSec`) terminates the child and hands the retained session to current
432
- main.
433
- - **Dispatch failures surface** — partial parallel startup reports every failed
434
- item and reason; if none start, the tool throws so Pi records a real tool error.
435
- Dispatch crashes likewise produce a failed result instead of a silent hang.
436
- - **Safe live status** tool activity is credential-redacted and stripped of terminal control sequences before `subagent_status` can return it.
437
- - **Leaf children** no nested delegation, no runaway trees.
438
-
439
- ## Development
440
-
441
- ```bash
442
- npm install
443
- npm run check
444
- npm test
445
- ```
446
-
447
- The source is modular: `dispatch.ts` (public dispatch contract + auto-fix),
448
- `thread-lifecycle.ts` (queued generations, resume/fork, and isolation settlement),
449
- `rpc-run.ts` / `spawn.ts` (persistent child transport + selected→main handoff),
450
- `worktree.ts` / `session-fork.ts` (filesystem/session branching), `tools.ts`
451
- (wait/status/control/stop), `widget.ts` (active-only TUI status), `announcements.ts`
452
- (recovery and feature notices), and `runtime.ts` (session-scoped ownership). No runtime
453
- dependencies beyond pi peer dependencies.
454
-
455
- ## License
456
-
457
- MIT
1
+ # pi-subagents
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ferris1225/pi-subagents?color=blue)](https://www.npmjs.com/package/@ferris1225/pi-subagents)
4
+ [![downloads](https://img.shields.io/npm/dm/@ferris1225/pi-subagents)](https://www.npmjs.com/package/@ferris1225/pi-subagents)
5
+ [![license](https://img.shields.io/npm/l/@ferris1225/pi-subagents)](./LICENSE)
6
+ ![platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey)
7
+ ![pi](https://img.shields.io/badge/pi-extension-orange)
8
+
9
+ Focused background delegation for [pi](https://pi.dev): `explorer` / `worker` /
10
+ `cleaner` / `reviewer` agents run in **isolated child processes** and hand their
11
+ results back to the main agent automatically. Install it, and the main model
12
+ starts using it on its own — no prompt engineering, no babysitting.
13
+
14
+ ## 4.0.0 — consistent agent names and direct cleanup
15
+
16
+ Version 4 renames the built-in reconnaissance role from `explore` to `explorer`
17
+ and deliberately removes the old alias. Existing explicit configuration must use
18
+ the new key. `cleaner` is now apply-only: explicit cleanup intent authorizes it to
19
+ prove and perform every safe in-scope cut, while generic or read-only assessments
20
+ go to `reviewer` without triggering auto-fix.
21
+
22
+ The main delegation directive is now the single authoritative routing policy;
23
+ duplicated tool guidelines were removed to cut the default parent injection by
24
+ more than half without changing process isolation, worktree rules, retained-session
25
+ fallback, or result handoff. Agent frontmatter model defaults remain because they
26
+ still select a model when no current main model exists; frontmatter comments do not
27
+ enter model context.
28
+
29
+ Every dispatch retains its stable run id and can be steered, parked, resumed,
30
+ retargeted, or forked. The active widget continues to show task, effective model
31
+ and thinking level, activity, and elapsed time.
32
+
33
+ The common quality loop now runs end to end without waking the main agent between
34
+ steps:
35
+
36
+ ```text
37
+ reviewer (find issues) → worker (fix every finding) → reviewer (verify) → final PASS/FAIL
38
+ ```
39
+
40
+ Gate reviews use a single flat findings list no severity triage. Every reported
41
+ finding is fixed before the change is accepted, and each re-review converges on
42
+ an open-finding set: the worker's explicit rejections are adjudicated once, only
43
+ defects a fix round introduced or exposed are added, and resolved items never
44
+ re-open. `maxFixRounds` stays the hard cap, so a chain always settles and wakes
45
+ the main agent with the full picture. Advisory reviewer requests (generic audits,
46
+ code health, plans, and proposed solutions) return evidence without a machine
47
+ verdict, so they never start auto-fix.
48
+
49
+ Cleanup stays a separate lifecycle: only an explicit request authorizing cleanup,
50
+ removal, or simplification edits dispatches the evidence-first `cleaner`. It proves
51
+ candidates, applies every safe in-scope cut end to end, and may validly make zero
52
+ edits; non-trivial changes still go through the independent `reviewer` gate.
53
+
54
+ Each chain is delivered as one concise completion group whose footer totals the
55
+ aggregate token usage and cost of every included run, while full per-run reports
56
+ remain available through `subagent_status`. Its parent stays `running`
57
+ until the whole chain settles; completed internal rounds leave active status
58
+ immediately, so no `done` row keeps accumulating elapsed time. Selected-to-main
59
+ model handoffs keep the same retained context, and isolated parallel workers use
60
+ detached Git worktrees whose changes are applied back without touching the parent
61
+ index.
62
+
63
+ ## Highlights
64
+
65
+ - **Zero-setup proactive dispatch** the extension injects a delegation directive
66
+ into the main system prompt, so the main model sends broad searches to `explorer`,
67
+ self-contained implementations to `worker`, edit-authorizing cleanup to `cleaner`,
68
+ and generic assessments or pre-commit gates to `reviewer`. You just use pi;
69
+ delegation happens by itself.
70
+ - **Multimodal work is a model choice, not a mode** an agent that should see
71
+ screenshots, mockups, or its own rendered pages simply gets a multimodal model
72
+ through `/subagents-setup` (the picker labels each model `vision` or
73
+ `text-only`). The agent reads images with its `read` tool on whatever model it
74
+ runs; no per-task flag, no separate vision override.
75
+ - **Results come back on their own** completions are delivered as messages that
76
+ wake the main agent automatically, even mid-turn. No polling, no `sleep`, no
77
+ "go check" step. `subagent_wait` is a **non-blocking** in-turn lookup by default
78
+ (pass `timeoutMs` to block); `subagent_status` inspects runs; `subagent_stop`
79
+ cancels one and delivers its partial output.
80
+ - **Active-only live widget, as a tree** each queued or running sub-agent gets one compact
81
+ width-aware primary line with task, effective model/thinking, and elapsed time; current
82
+ activity appears only when present on an indented second line. Auto-fix rounds nest under
83
+ the triggering reviewer row that owns the chain, so it is always visible who dispatched
84
+ what; no run ids appear here — the tree and the task label identify each row:
85
+ ```text
86
+ reviewer · review diff of src/foo.ts · claude-sonnet-4-5/high · 42s
87
+ worker · fix round 1 · src/foo.ts · claude-sonnet-4-5/high · 10s
88
+ │ grep cacheKey
89
+ reviewer · re-review round 1 · claude-sonnet-4-5/high · 3s
90
+ ```
91
+ Long tasks and activity paths truncate first (preserving a useful path tail when
92
+ possible), groups have no blank rows, and settled/parked runs disappear immediately.
93
+ - **Results are not re-narrated** a sub-agent's completion is shown to you
94
+ verbatim, and the main agent is told not to paraphrase it back. It replies with
95
+ only its own conclusion or next step, so the same findings are never paid for
96
+ twice in tokens.
97
+ - **Evidence-first cleanup, not deletion by guesswork**`cleaner` is apply-only:
98
+ an explicit cleanup request authorizes edits, but each candidate must be proved
99
+ before every safe in-scope cut is applied and verified. Finding nothing safe and
100
+ making zero edits remains valid. Generic/read-only assessments go to `reviewer`;
101
+ cleaner is periodic/intent-driven, never PR-count-driven or an automatic gate.
102
+ - **A quality gate that closes the loop** — when a gate reviewer returns
103
+ `REVIEW_FAIL`, the extension dispatches a worker briefed with the concrete
104
+ findings, then a re-review, up to `maxFixRounds` times and only then wakes the
105
+ main agent. Advisory reviewer reports omit that verdict and never trigger edits.
106
+ Every reported finding gets fixed (no severity triage), and re-reviews converge
107
+ on an open-finding set instead of ping-ponging: worker rejections are adjudicated
108
+ once, only defects the fix round introduced are added, and resolved items never
109
+ re-open. Every round stays in the triggering reviewer's cwd, and chains that target the
110
+ same repository are serialized so shared-checkout edits cannot race.
111
+ - **Direct fallback with real thinking capabilities** — each agent has at most
112
+ one selected model. An unavailable selection, rate limit, invalid key, quota,
113
+ missing model, or provider failure hands directly to the current main model.
114
+ A child-only provider adapter forces inner request retries to zero; transient
115
+ stream drops still use Pi's outer turn retry, and only a settled model-level
116
+ failure hands off, without changing user settings. Auto thinking clamps the
117
+ agent preference to the
118
+ effective model's real `thinkingLevelMap`; manual setup shows only levels that
119
+ model supports.
120
+ - **Resumes, retargets, and forks preserve context** — every run is session-backed.
121
+ `subagent_control` can steer active work, retarget it after a stable abort,
122
+ park/resume it under the same run id, or fork a parked/settled checkpoint into
123
+ a new independent run. Concurrent resume calls are serialized.
124
+ - **Concise but honest completions** — group completions end with aggregate token
125
+ and cost totals across every included run; failed-tool diagnostics stay out of the
126
+ delivered message and remain one `subagent_status` call away. Actual process,
127
+ model, and integration failures still surface as failures.
128
+ - **Parallel fan-out with filesystem isolation** independent tasks run up to a
129
+ configurable limit (default 4). Parallel workers default to detached Git
130
+ worktrees; tracked, deleted, untracked, and binary changes are applied back
131
+ without touching the parent index. Failed integration keeps recovery artifacts.
132
+ - **Recursion is structurally impossible** — children are leaf processes; the
133
+ `subagent` tool is excluded from their toolset.
134
+ - **Zero runtime dependencies** — agents are plain Markdown files; overriding or
135
+ adding one is writing a file.
136
+ - **Update announcements** when a new configurable feature ships, you are told
137
+ about it once (a persisted marker stops the notice from nagging).
138
+
139
+ ## What this adds beyond generic subagent dispatch
140
+
141
+ This package combines several concrete runtime behaviors rather than only exposing
142
+ an undifferentiated child-agent launcher:
143
+
144
+ - language-agnostic semantic role guidance for cleanup intent;
145
+ - a dedicated evidence-first cleaner, with cleanup kept separate from the
146
+ independent reviewer gate;
147
+ - isolated, retained threads that can be steered, parked, resumed, retargeted, or
148
+ forked under stable run ids;
149
+ - the reviewer → worker auto-fix → reviewer loop, fixing every finding under a
150
+ convergence contract with a hard round cap;
151
+ - failed-tool diagnostics available by run id through `subagent_status`;
152
+ - direct selected→main fallback plus capability-aware Auto thinking;
153
+ - detached Git worktree isolation for parallel workers and opt-in write-capable
154
+ cleaner runs.
155
+
156
+ ## Install
157
+
158
+ ```bash
159
+ pi install npm:@ferris1225/pi-subagents
160
+ ```
161
+
162
+ Requires pi **>= 0.83.0**. After installation, open the setup wizard in an
163
+ interactive TUI session:
164
+
165
+ ```text
166
+ /subagents-setup
167
+ ```
168
+
169
+ Fresh installs enable `explorer`, `worker`, `cleaner`, and `reviewer` — you can
170
+ start delegating immediately. Existing explicit `enabledAgents` lists are never
171
+ silently extended; users upgrading with an existing explicit list get a one-time
172
+ notice to opt into `cleaner` with `/subagents-setup`.
173
+
174
+ ## The agents
175
+
176
+ | Agent | Access | Purpose |
177
+ | --- | --- | --- |
178
+ | `explorer` | Read-only | Fast codebase reconnaissance: broad/open-ended search, multi-file lookups, mapping unfamiliar code. Returns compressed, structured retrieval leads. |
179
+ | `worker` | Full | Implements, fixes, refactors, and tests a self-contained task end to end, then reports honest verification. |
180
+ | `cleaner` | Full | Proves and applies every safe in-scope cleanup authorized by an explicit cleanup/removal/simplification request; zero edits is valid. Supports worktree isolation. |
181
+ | `reviewer` | Read-only | Handles generic audits, code health, plans, proposed solutions, PR/issue validation, and independent pre-commit gates. Advisory reports do not trigger auto-fix. |
182
+
183
+ Each agent runs in its own isolated `pi` process with a clean context window; it
184
+ has no memory of your conversation, so briefs must be self-contained (goal, exact
185
+ paths, constraints, expected output).
186
+
187
+ ## Usage
188
+
189
+ ### Single task
190
+
191
+ ```ts
192
+ subagent({ agent: "explorer", task: "Map the test setup: which files run what, and how is CI wired? Report exact paths." });
193
+ subagent({ agent: "worker", task: "Implement X in src/foo.ts, add tests, run npm test." });
194
+ subagent({ agent: "reviewer", task: "Audit src/cache for dead-code candidates and redundant state; report evidence only." });
195
+ subagent({ agent: "cleaner", task: "Clean up src/cache: prove and apply every safe dead-code or redundancy cut, update tests/docs, and verify." });
196
+ subagent({ agent: "reviewer", task: "Gate the diff of src/index.ts and tests/load.test.ts for correctness and edge cases." });
197
+ ```
198
+
199
+ ### Parallel tasks
200
+
201
+ ```ts
202
+ subagent({
203
+ tasks: [
204
+ { agent: "explorer", task: "Where is the selected-to-main handoff logic?" },
205
+ { agent: "worker", task: "Add unit tests for models.ts." },
206
+ ],
207
+ });
208
+ ```
209
+
210
+ ### Cleanup routing and lifecycle
211
+
212
+ The injected guidance sends only explicit, edit-authorizing cleanup intent to
213
+ `cleaner` in whatever language the conversation uses: clean up/remove dead code,
214
+ reduce redundancy, simplify, remove over-engineering, or run a maintenance cleanup
215
+ pass. Cleaner first proves reachability, ownership, history, and boundaries, then
216
+ applies every safe in-scope cut end to end and verifies it. No proven safe cut means
217
+ zero edits, not a forced deletion.
218
+
219
+ Generic or explicitly read-only **audit**, **inspect**, **report**, **review**,
220
+ **code-health**, **plan**, **proposed-solution**, or cleanup-candidate assessment
221
+ requests go to `reviewer`. Those are advisory reviews: they omit the machine
222
+ `REVIEW_PASS` / `REVIEW_FAIL` marker, cannot start auto-fix, and do not authorize
223
+ the main agent to edit. A follow-up change needs an explicit user request. A
224
+ reviewer emits the marker only for an explicit diff/pre-commit acceptance gate.
225
+
226
+ ```text
227
+ explicit edit-authorizing cleanup cleaner reviewer gate
228
+ read-only/generic assessment → reviewer advisory report (no auto-fix)
229
+ reviewer gate REVIEW_FAIL → worker auto-fix → reviewer gate
230
+ ```
231
+
232
+ Cleaner is never dispatched by PR count and never acts as the commit gate. The
233
+ auto-fix portion runs only for gate verdicts and only when enabled by
234
+ `maxFixRounds`.
235
+
236
+ ### Image work (screenshots / mockups / designs)
237
+
238
+ There is no vision flag or separate vision model. Give the agent a multimodal
239
+ model in `/subagents-setup` and name the exact image paths in the task:
240
+
241
+ ```ts
242
+ subagent({
243
+ agent: "reviewer",
244
+ task: "Compare the UI in screenshots/settings.png against the mockup design.png; list every visual mismatch.",
245
+ });
246
+ ```
247
+
248
+ The sub-agent reads images with its `read` tool on its configured model; the
249
+ setup picker labels each model `vision` or `text-only` so the choice is visible.
250
+ The live widget line, dispatch result row, and `subagent_status` all show each
251
+ run's effective model id, and a selected→main handoff is labeled with its
252
+ origin.
253
+
254
+ ### Controlling and stopping
255
+
256
+ Dispatch confirmations, tool result rows, and completion blocks all show the
257
+ stable `#id`, so a thread remains directly controllable after its live UI is gone
258
+ (the widget itself identifies rows by tree position and task instead of ids).
259
+
260
+ - `subagent_control` — `steer`, `retarget`, `park`, `resume`, or `fork` a logical
261
+ thread by stable run id. Resume accepts an optional replacement objective;
262
+ fork creates a new id and leaves the source unchanged. Park active work before
263
+ forking it.
264
+ - `subagent_wait` in-turn result lookup. **Non-blocking by default**: a settled
265
+ run returns immediately; an active run tells the model to end its turn. Pass
266
+ `timeoutMs` only when you must stay in the turn.
267
+ - `subagent_status` — active/parked/finished runs and full result by run id.
268
+ - `subagent_stop` — destructive cancellation. It retires that thread's retained
269
+ session (independent forks survive) and delivers exactly one aborted partial
270
+ result after the run and any worktree integration have quiesced.
271
+
272
+ Examples:
273
+
274
+ ```ts
275
+ subagent_control({ action: "steer", id: 7, instruction: "Check the Windows path too." });
276
+ subagent_control({ action: "park", id: 7 });
277
+ subagent_control({ action: "resume", id: 7, objective: "Finish the tests." });
278
+ subagent_control({ action: "fork", id: 7, objective: "Try the smaller alternative." });
279
+ ```
280
+
281
+ ### Worktree isolation
282
+
283
+ Single tasks default to `isolation: "shared"`. Parallel `worker` tasks default
284
+ to `isolation: "worktree"`; opt into shared mode only when a worker must see the
285
+ caller's live uncommitted tree. `cleaner` is also write-capable and supports
286
+ worktree mode when explicitly requested (its default remains shared). Worktree
287
+ mode requires a Git repository with a committed `HEAD` and is rejected for the
288
+ read-only `explorer` and `reviewer` agents.
289
+
290
+ A parked isolated thread keeps its current worktree. Resume it there; fork is
291
+ available after that isolated checkpoint settles and its seed is integrated.
292
+ Resuming or forking a settled isolated thread creates a fresh worktree, merges a
293
+ recorded checkpoint onto the current `HEAD` (including when the seed was already
294
+ committed), and clones the Pi session with the new cwd. Forks then integrate only
295
+ their unique follow-on edits, so a shared seed is applied once. A run remains
296
+ active while final Git integration is in progress and becomes `done` only after
297
+ that boundary finishes.
298
+
299
+ Every Git operation has a 120-second deadline and process-tree cleanup; captured
300
+ Git output and binary patches are capped at 64 MiB. Setup/bound failures surface
301
+ instead of hanging. Finalization failures retain the patch/worktree when
302
+ available and are recorded in `~/.pi/agent/pi-subagents-recovery.json`; later
303
+ sessions show the recovery paths again until the artifacts are removed.
304
+
305
+ ## Configuration
306
+
307
+ Stored at `~/.pi/agent/pi-subagents.json` (follows `PI_CODING_AGENT_DIR` when
308
+ set). `/subagents-setup` has four top-level choices: enable agents, configure one
309
+ agent's model/thinking, runtime settings, or full setup.
310
+ After one agent's model + thinking picks, the wizard returns to the agent picker
311
+ so several agents can be configured in one pass; Esc at any step ends the pass
312
+ and keeps every agent already configured. There is no backup pool or global thinking menu. Model pickers show only in-scope
313
+ models with configured authentication and display their real supported thinking
314
+ levels. Thinking defaults to **Auto**; manual overrides show only levels supported
315
+ by that agent's effective model. `notifyOnReviewPass` and `maxResultLines` remain
316
+ direct-file settings.
317
+
318
+ ```json
319
+ {
320
+ "enabledAgents": ["explorer", "worker", "cleaner", "reviewer"],
321
+ "agentModels": {
322
+ "explorer": "anthropic/claude-haiku-4-5"
323
+ },
324
+ "agentThinkingLevels": {
325
+ "reviewer": "high"
326
+ },
327
+ "notifyOnReviewPass": false,
328
+ "maxResultLines": 80,
329
+ "proactiveInjection": true,
330
+ "agentScope": "user",
331
+ "maxConcurrency": 4,
332
+ "maxFixRounds": 2,
333
+ "idleTimeoutSec": 90
334
+ }
335
+ ```
336
+
337
+ | Field | Description |
338
+ | --- | --- |
339
+ | `enabledAgents` | Agent names exposed to discovery and prompt injection. An empty array disables all agents. |
340
+ | `agentModels` | Optional selected `provider/model-id` per agent. Missing = current main model. Model-level failure hands directly to current main. |
341
+ | `agentThinkingLevels` | Optional manual preference per agent. Missing = Auto (agent frontmatter preference, or `high`, clamped to the effective model's supported levels). |
342
+ | `notifyOnReviewPass` | When `true`, a passing reviewer result is delivered without waking the main agent (default `false`). |
343
+ | `maxResultLines` | Max lines of a sub-agent result carried in the completion message (default `80`). Longer results are truncated; full text is written to an extension-named temporary `.md`. At session start and on each write, only recognized result files older than 7 days are removed; each canonical project path has its own newest-50 bucket. |
344
+ | `proactiveInjection` | Whether to add the delegation directive to the main system prompt. |
345
+ | `agentScope` | `user`, `project`, or `both`; controls which user/project agent directories are discovered. |
346
+ | `maxConcurrency` | Max sub-agent processes running at once (1–16, default 4), and the max tasks one parallel `subagent` call accepts. Extra work waits in the queue. |
347
+ | `maxFixRounds` | Auto-fix rounds when a reviewer returns `REVIEW_FAIL` (default 2; `0` disables the loop). Hard cap: the chain always settles, delivers its condensed summary, and wakes the main agent. |
348
+ | `idleTimeoutSec` | Idle watchdog: a sub-agent whose stdout goes silent for this long is terminated; a selected model then hands to current main. `0` disables it. Default 90. |
349
+
350
+ ### Model routing and thinking
351
+
352
+ ```text
353
+ selected agent model current main-window model
354
+ ```
355
+
356
+ Without a selected model, current main runs immediately; agent frontmatter `model`
357
+ is used only when no main model exists, so the shipped defaults remain behaviorally
358
+ load-bearing. From an agent Markdown file, only the body after frontmatter becomes
359
+ the child's appended system prompt; model-selection comments inside YAML
360
+ frontmatter are parser comments, not model prompt tokens. A selection missing from Pi's live
361
+ available catalog is skipped. Any model-level runtime failure rate limit,
362
+ quota, invalid key/auth, missing model, provider error, or idle model stream
363
+ hands directly to current main, including stream errors that retain partial text.
364
+ A child-only Pi extension wraps the selected provider's registered API stream
365
+ with `maxRetries: 0` so a deterministic auth/quota miss fails fast. Transient
366
+ stream drops such as xAI `terminated` still use Pi's outer turn retry — the
367
+ parent does not `abort_retry` them and only a settled model-level failure
368
+ hands off to current main. This uses supported extension/RPC surfaces in Node
369
+ and standalone/Bun builds, never rewrites global or project settings, and does
370
+ not alter descendant tool environments. Tool/test failures stay on the same
371
+ model because they are task failures, not model availability failures. A child is
372
+ probed with RPC `get_state` before the first prompt so the 30s command ACK clock
373
+ does not include process boot. Only a zero-activity startup miss can retry a
374
+ silent fast exit, a `get_state` handshake timeout, or an initial prompt ACK
375
+ timeout before any agent/turn/stream/tool activity. Those transport misses are
376
+ not model-level failures and do not hand the task to the main window. An accepted
377
+ prompt or any activity forbids replay.
378
+
379
+ Auto thinking starts from the Agent's declared preference (`low` for `explorer`,
380
+ `high` for the other built-ins) and uses Pi's capability map to clamp it to the
381
+ actual model. Non-reasoning models resolve to `off`; `xhigh`/`max` appear in setup
382
+ only when that model explicitly supports them. A selected→main handoff re-clamps
383
+ thinking for the main model.
384
+
385
+ ### Choosing an explorer model
386
+
387
+ Choose a competent fast code model for `explorer`, not automatically the cheapest
388
+ model. Cheap reconnaissance is useful for mechanical symbol/path discovery, but
389
+ a missed dynamic entrypoint or ownership edge can cost more through downstream
390
+ rework. Direct main-model handoff handles provider/runtime failure; it cannot
391
+ detect a plausible but incomplete answer.
392
+
393
+ `explorer` therefore returns an index of exact paths, lines, symbols, and explicit
394
+ uncertainty. The main agent, worker, or cleaner must re-read load-bearing files
395
+ before editing or deciding deletion, security, compatibility, persistence, or
396
+ dynamic reachability. Prefer a stronger model or direct specialist for complex
397
+ dynamic loading, concurrency, migrations, and security-sensitive code.
398
+
399
+ ### Resuming retained context
400
+
401
+ Every run stores its Pi session in a private temp directory. A selected→main
402
+ handoff resumes that same session, so searches, reads, reasoning, and edits remain
403
+ in context. A parked, completed, or failed thread can later be resumed under its
404
+ stable id:
405
+
406
+ ```ts
407
+ subagent_control({ action: "resume", id: 7 });
408
+ subagent_control({ action: "resume", id: 7, objective: "Continue with the repaired credentials." });
409
+ ```
410
+
411
+ Use `fork` when both paths should remain available. `subagent_stop` is the
412
+ explicit destructive operation that retires a retained session; otherwise
413
+ sessions live until the parent Pi session shuts down.
414
+
415
+ ### Configuration migration
416
+
417
+ Config loading normalizes schema fields and removes invalid or obsolete keys,
418
+ including `agentBackupModels`, global `thinkingLevel`, `maxParallelTasks`, and
419
+ `maxSubagentDepth`. Per-agent thinking preferences remain capability-clamped.
420
+
421
+ The built-in reconnaissance role is now `explorer`. There is deliberately no
422
+ `explore` alias and no automatic key migration. Existing configurations must change
423
+ that role name in `enabledAgents`, `agentModels`, and `agentThinkingLevels` (or run
424
+ `/subagents-setup`). Configured non-empty names are otherwise preserved, so a stale
425
+ name is not silently rewritten. A pre-existing explicit `enabledAgents` list is
426
+ also still preserved without appending `cleaner`; configs without cleaner receive
427
+ the existing one-time setup notice.
428
+
429
+ ## Agent discovery and overrides
430
+
431
+ - Built-in agents ship with the package; user agents live in `~/.pi/agent/agents/`;
432
+ project agents in the nearest `.pi/agents/` directory are loaded only when Pi
433
+ trusts that project.
434
+ - For duplicate names: project overrides user overrides built-in. Keep the
435
+ matching filename and `name` field to replace a built-in agent.
436
+ - Optional frontmatter: `model` (default model reference), `thinking` (default
437
+ thinking strength), `tools` (comma-separated tool allow-list; absent = all
438
+ tools). Config overrides win at spawn.
439
+
440
+ ## How it stays reliable
441
+
442
+ - **Direct model recovery** — unavailable selections skip immediately; any
443
+ selected-model provider/auth/quota/rate-limit failure hands directly to current
444
+ main with thinking re-clamped to the main model.
445
+ - **Startup-race retries** — a silent zero-activity child exit (concurrent pi
446
+ startup lock contention) is relaunched with backoff; only clean silent exits
447
+ qualify, so real work is never duplicated.
448
+ - **Idle watchdog** a stalled selected-model stream (no output for
449
+ `idleTimeoutSec`) terminates the child and hands the retained session to current
450
+ main.
451
+ - **Dispatch failures surface** partial parallel startup reports every failed
452
+ item and reason; if none start, the tool throws so Pi records a real tool error.
453
+ Dispatch crashes likewise produce a failed result instead of a silent hang.
454
+ - **Safe live status** — tool activity is credential-redacted and stripped of terminal control sequences before `subagent_status` can return it.
455
+ - **Leaf children** — no nested delegation, no runaway trees.
456
+
457
+ ## Development
458
+
459
+ ```bash
460
+ npm install
461
+ npm run check
462
+ npm test
463
+ ```
464
+
465
+ The source is modular: `dispatch.ts` (public dispatch contract + auto-fix),
466
+ `thread-lifecycle.ts` (queued generations, resume/fork, and isolation settlement),
467
+ `rpc-run.ts` / `spawn.ts` (persistent child transport + selected→main handoff),
468
+ `worktree.ts` / `session-fork.ts` (filesystem/session branching), `tools.ts`
469
+ (wait/status/control/stop), `widget.ts` (active-only TUI status), `announcements.ts`
470
+ (recovery and feature notices), and `runtime.ts` (session-scoped ownership). No runtime
471
+ dependencies beyond pi peer dependencies.
472
+
473
+ ## License
474
+
475
+ MIT