pi-subagents 0.23.0 → 0.24.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +17 -79
  3. package/agents/reviewer.md +2 -2
  4. package/package.json +1 -1
  5. package/prompts/parallel-cleanup.md +11 -1
  6. package/prompts/parallel-review.md +11 -1
  7. package/skills/pi-subagents/SKILL.md +29 -13
  8. package/src/agents/agent-serializer.ts +0 -42
  9. package/src/agents/agents.ts +1 -1
  10. package/src/extension/index.ts +14 -8
  11. package/src/extension/schemas.ts +1 -1
  12. package/src/intercom/intercom-bridge.ts +4 -1
  13. package/src/intercom/result-intercom.ts +8 -3
  14. package/src/runs/background/async-execution.ts +10 -5
  15. package/src/runs/background/async-resume.ts +57 -31
  16. package/src/runs/background/async-status.ts +16 -50
  17. package/src/runs/background/result-watcher.ts +3 -1
  18. package/src/runs/background/run-status.ts +28 -26
  19. package/src/runs/background/stale-run-reconciler.ts +3 -0
  20. package/src/runs/background/subagent-runner.ts +21 -7
  21. package/src/runs/foreground/chain-clarify.ts +183 -218
  22. package/src/runs/foreground/chain-execution.ts +55 -21
  23. package/src/runs/foreground/execution.ts +6 -3
  24. package/src/runs/foreground/subagent-executor.ts +152 -20
  25. package/src/runs/shared/single-output.ts +21 -6
  26. package/src/shared/settings.ts +19 -0
  27. package/src/shared/status-format.ts +49 -0
  28. package/src/shared/types.ts +18 -5
  29. package/src/slash/slash-commands.ts +1 -74
  30. package/src/tui/render.ts +37 -61
  31. package/src/agents/agent-templates.ts +0 -60
  32. package/src/manager-ui/agent-manager-chain-detail.ts +0 -164
  33. package/src/manager-ui/agent-manager-detail.ts +0 -235
  34. package/src/manager-ui/agent-manager-edit.ts +0 -456
  35. package/src/manager-ui/agent-manager-list.ts +0 -283
  36. package/src/manager-ui/agent-manager-parallel.ts +0 -302
  37. package/src/manager-ui/agent-manager.ts +0 -732
  38. package/src/tui/subagents-status.ts +0 -621
  39. package/src/tui/text-editor.ts +0 -286
package/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.24.0] - 2026-05-03
6
+
7
+ ### Changed
8
+ - Consolidated async step activity and parallel-outcome formatting used by widgets and `subagent({ action: "status" })` output.
9
+ - Updated `/parallel-review` and `/parallel-cleanup` to end review synthesis with numbered follow-up choices, plus an `autofix` mode for automatically applying fixes worth doing now.
10
+ - Include async run output paths in `subagent({ action: "status" })` output so the remaining inspection path covers the logs previously surfaced by the removed overlay.
11
+
12
+ ### Removed
13
+ - Removed the unnecessary `/agents` manager overlay, its `Ctrl+Shift+A` shortcut, and the `agentManager.newShortcut` setting to cut unnecessary UI surface area; agent and chain management remains available through tool actions, settings, and markdown files.
14
+ - Removed persistent save actions from the chain clarify UI: `S` no longer writes runtime overrides back to agent frontmatter, and `W` no longer saves `.chain.md` files. Clarify now only edits the imminent run.
15
+ - Removed the `/subagents-status` read-only overlay and its slash command; async runs remain inspectable through `subagent({ action: "status" })`, completion notifications, logs, and the async widget.
16
+ - Removed the standalone `src/tui/text-editor.ts`; chain clarify now keeps its small runtime editor logic local to the only remaining consumer.
17
+
18
+ ## [0.23.1] - 2026-05-02
19
+
20
+ ### Added
21
+ - Persist async per-child session metadata and remember recent foreground child session metadata so `resume` can revive multi-child async runs and foreground children by index.
22
+
23
+ ### Fixed
24
+ - Keep foreground children alive when they call `contact_supervisor` for a blocking decision by treating it as intercom coordination during parent detach, matching the generic `intercom` handoff path.
25
+ - Pause foreground parallel and chain flows when a child detaches for intercom coordination instead of counting the child as a successful completed result and continuing the workflow, and suppress grouped completion receipts for detached chains.
26
+ - Tighten resume/revive safety by rejecting pending async children, detached foreground children that may still be live, ambiguous foreground/async id prefixes, and exact invalid resume matches that would otherwise be masked by a prefix match in the other namespace.
27
+ - Preserve child session metadata in stale-run repaired results and avoid advertising revive from top-level-only or missing child session files.
28
+ - Stop builtin `reviewer` runs from writing progress by default, clarify that review-only/no-edit instructions win over progress-writing or artifact-writing instructions, and suppress automatic progress injection for explicit no-edit tasks even when chain templates use `{task}`.
29
+ - Treat parsed provider errors as failed foreground and async subagent attempts even when the child process exits successfully, and baseline saved output files per fallback attempt.
30
+ - Preserve output-file read and inspect errors instead of silently overwriting or falling back when a changed saved-output path cannot be read.
31
+ - Show each active async widget row's lifecycle status (`running`, `complete`, `failed`, or `paused`) alongside activity and usage stats.
32
+ - Start new direct, slash, prompt-template, foreground, and async subagent launches in compact view while keeping `Ctrl+O` available for live detail.
33
+ - Label top-level async parallel completion notifications as parallel runs instead of leaking the internal chain-shaped runner plan.
34
+
5
35
  ## [0.23.0] - 2026-05-02
6
36
 
7
37
  ### Fixed
package/README.md CHANGED
@@ -90,7 +90,7 @@ Those are ordinary Pi requests. Pi decides whether to call `subagent`, which age
90
90
  | Run in the background | “Run this in the background.” |
91
91
  | Browse agents | “Show me the available subagents.” |
92
92
  | Use a saved workflow | “Run the review chain on this branch.” |
93
- | See running work | “Show subagent status.” |
93
+ | See running work | “Show active async runs.” |
94
94
  | Check setup | “Check whether subagents are configured correctly.” |
95
95
 
96
96
  The extension ships with builtin agents you can use immediately.
@@ -120,15 +120,7 @@ For one run, put the override in the command:
120
120
  /run reviewer[model=anthropic/claude-sonnet-4:high] "Review this diff"
121
121
  ```
122
122
 
123
- For a persistent override, use `/agents`:
124
-
125
- ```text
126
- /agents
127
- ```
128
-
129
- Choose the builtin agent, press `e`, change the model or other fields, then save a user or project override. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides.
130
-
131
- You can also edit settings directly. This example pins the reviewer everywhere, adds a backup model for provider failures, and keeps the other builtins on your normal default model:
123
+ For a persistent override, edit settings. This example pins the reviewer everywhere, adds a backup model for provider failures, and keeps the other builtins on your normal default model:
132
124
 
133
125
  ```json
134
126
  {
@@ -150,18 +142,14 @@ Use `~/.pi/agent/settings.json` for a user override or `.pi/settings.json` for a
150
142
 
151
143
  Foreground runs stream progress in the conversation while they run.
152
144
 
153
- Background runs keep working after control returns to you. They show a compact async widget, send completion notifications, and can be inspected with:
145
+ Background runs keep working after control returns to you. Inspect active runs with `subagent({ action: "status" })`, or a specific run with `subagent({ action: "status", id: "..." })`.
154
146
 
155
- ```text
156
- /subagents-status
157
- ```
158
-
159
- The status view shows active and recent runs for the current Pi session. Parallel background runs are shown as parallel work, with per-agent progress instead of fake chain steps. Chains with parallel groups keep their grouped shape in both progress and results views, so failed or paused agents stay visible next to completed ones.
147
+ They also show a compact async widget and send completion notifications. Parallel background runs show per-agent progress instead of fake chain steps. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones.
160
148
 
161
149
  You can also ask naturally:
162
150
 
163
151
  ```text
164
- Show me the current subagent status.
152
+ Show me the current async runs.
165
153
  ```
166
154
 
167
155
  If something feels misconfigured, run:
@@ -203,6 +191,8 @@ The package includes reusable prompt templates for common workflows. You do not
203
191
  | `/gather-context-and-clarify` | Scout/research first, then ask the user the clarification questions that matter. |
204
192
  | `/parallel-cleanup` | Run review-only cleanup passes after implementation. |
205
193
 
194
+ Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the synthesized fixes worth doing now after reviewers return.
195
+
206
196
  ## Optional pi-intercom companion
207
197
 
208
198
  `pi-subagents` works without `pi-intercom`. Install `pi-intercom` only if you want child agents to talk back to the parent Pi session while they are running.
@@ -225,11 +215,11 @@ Ask oracle to review this plan. If it sees a decision I need to make, have it as
225
215
 
226
216
  The child can use one dedicated coordination tool:
227
217
 
228
- - `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: "need_decision"` for blocking decisions or clarification, and `reason: "progress_update"` for short non-blocking updates when a discovery changes the plan.
218
+ - `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: "need_decision"` for blocking decisions or clarification, and `reason: "progress_update"` for short non-blocking updates when a discovery changes the plan. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions; no-edit wins.
229
219
 
230
220
  Child-side routine completion handoffs are still not expected. With the intercom bridge active, parent-side `pi-subagents` sends grouped completion results through `pi-intercom`: one grouped message per foreground parent `subagent` run and one per completed async result file. Acknowledged foreground delivery returns a compact receipt with artifact/session paths; if unacknowledged, the normal full output is preserved. Grouped messages include child intercom targets and full child summaries.
231
221
 
232
- If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `/subagents-status`, interrupting the run, or nudging the child.
222
+ If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, interrupting the run, or nudging the child.
233
223
 
234
224
  If messages do not show up, run:
235
225
 
@@ -251,8 +241,6 @@ Skip this section until you want exact syntax.
251
241
  | `/chain agent1 "task1" -> agent2 "task2"` | Run agents in sequence |
252
242
  | `/parallel agent1 "task1" -> agent2 "task2"` | Run agents in parallel |
253
243
  | `/run-chain <chainName> -- <task>` | Launch a saved `.chain.md` workflow |
254
- | `/agents` | Open the Agents Manager overlay |
255
- | `/subagents-status` | Open the active/recent run overlay |
256
244
  | `/subagents-doctor` | Show read-only setup diagnostics |
257
245
 
258
246
  Commands validate agent names locally, support tab completion, and send results back into the conversation.
@@ -338,7 +326,7 @@ The `oracle` and `worker` builtins are designed for an explicit decision loop. A
338
326
 
339
327
  ## Clarify and launch UI
340
328
 
341
- Chains open a clarify UI by default so you can preview and edit the workflow before it runs. Single and parallel tool calls can opt into the same flow with `clarify: true`; slash commands and `/agents` use their own launch screens.
329
+ Chains open a clarify UI by default so you can preview and edit the workflow before it runs. Single and parallel tool calls can opt into the same flow with `clarify: true`; slash commands launch directly.
342
330
 
343
331
  Common clarify keys:
344
332
 
@@ -353,44 +341,8 @@ Common clarify keys:
353
341
  - `w` edits output/write behavior where supported
354
342
  - `r` edits reads where supported
355
343
  - `p` toggles progress tracking where supported
356
- - `S` saves current overrides to the agent frontmatter
357
- - `W` saves a chain configuration to `.chain.md`
358
-
359
344
  Picker screens use `↑↓`, `Enter`, `Esc`, and type-to-filter. The full-screen editor supports word wrapping, paste, `Esc` to save, and `Ctrl+C` to discard.
360
345
 
361
- ## Agents Manager
362
-
363
- Press `Ctrl+Shift+A` or type `/agents` to open the Agents Manager. It is the easiest way to browse, inspect, edit, create, and launch agents and chains.
364
-
365
- Use it when you want to see what agents exist, adjust a builtin override, build a parallel run without writing slash syntax, or save a chain for later.
366
-
367
- The main screens are:
368
-
369
- | Screen | What it does |
370
- |--------|--------------|
371
- | List | Browse agents and chains with search, filters, scope badges, and selection. |
372
- | Detail | View resolved prompt, frontmatter fields, run history, and builtin override path. |
373
- | Edit | Edit models, thinking level, prompt mode, inheritance flags, skills, and prompt text. |
374
- | Chain Detail | Inspect saved chain steps. |
375
- | Parallel Builder | Build parallel slots, including repeated agents and per-slot task overrides. |
376
- | Task Input | Enter the shared task and launch with fork/background/worktree toggles where supported. |
377
- | New Agent | Create from templates such as Scout, Planner, Implementer, Code Reviewer, Blank Agent, or Blank Chain. |
378
-
379
- Useful keys:
380
-
381
- - type to search the list
382
- - `Enter` opens detail screens
383
- - `Shift+Ctrl+N` creates an agent or chain from a template
384
- - `Ctrl+R` launches selected agents as a run or chain
385
- - `Ctrl+P` opens the parallel builder
386
- - `Tab` selects agents in the list or toggles skip-clarify in task input
387
- - `Ctrl+A` adds a slot in the parallel builder
388
- - `e` edits an agent or builtin override
389
- - `Ctrl+S` saves an override; `r` resets the focused override field; `D` removes the override
390
- - `Ctrl+K` clones the current item
391
- - `Ctrl+D` or `Del` deletes the current item or removes a parallel slot
392
- - `Esc` backs out of the current screen
393
-
394
346
  ## Agents and chains
395
347
 
396
348
  Agents are markdown files with YAML frontmatter and a system prompt body. They define the specialist that will run in the child Pi process.
@@ -436,9 +388,7 @@ Example:
436
388
 
437
389
  Supported override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use `defaultContext: false` in builtin overrides to clear an inherited context default. Project overrides beat user overrides.
438
390
 
439
- You can also manage builtin overrides from `/agents`. On a builtin detail screen, press `e`, choose user or project scope if needed, and save the fields you want to override.
440
-
441
- Set `disabled: true` to hide a builtin from runtime discovery and agent-facing `subagent({ action: "list" })` output while keeping it visible in `/agents`. For bulk control, set `subagents.disableBuiltins: true` in settings. Overridden builtins show badges like `[builtin+user]` or `[builtin+project]`; disabled builtins show `off` badges in the manager.
391
+ Set `disabled: true` to hide a builtin from runtime discovery and agent-facing `subagent({ action: "list" })` output. For bulk control, set `subagents.disableBuiltins: true` in settings.
442
392
 
443
393
  ### Prompt assembly
444
394
 
@@ -567,7 +517,7 @@ Each `## agent-name` section is a step. Config lines such as `output`, `outputMo
567
517
 
568
518
  For `output`, `reads`, `skills`, and `progress`, chain behavior is three-state: omitted inherits from the agent, a value overrides, and `false` disables.
569
519
 
570
- Create chains from the Agents Manager template picker, save them from the chain-clarify TUI, or write them by hand. Run them with natural language, `/agents`, or:
520
+ Create chains by writing `.chain.md` files directly or with the `subagent({ action: "create", config: ... })` management action. Run them with natural language or:
571
521
 
572
522
  ```text
573
523
  /run-chain scout-planner -- refactor authentication
@@ -780,11 +730,12 @@ Status and control actions:
780
730
  subagent({ action: "status" })
781
731
  subagent({ action: "status", id: "<run-id>" })
782
732
  subagent({ action: "interrupt", id: "<run-id>" })
783
- subagent({ action: "resume", id: "<async-run-id>", message: "follow-up question" })
733
+ subagent({ action: "resume", id: "<run-id>", message: "follow-up question" })
734
+ subagent({ action: "resume", id: "<run-id>", index: 1, message: "follow-up for child 2" })
784
735
  subagent({ action: "doctor" })
785
736
  ```
786
737
 
787
- `resume` sends the follow-up directly when the async child is still reachable over intercom. After completion, it starts a new async child from the stored single-child session file.
738
+ `resume` sends the follow-up directly when an async child is still reachable over intercom. After completion, it revives the child by starting a new async child from the stored child session file. Multi-child async runs and remembered foreground single, parallel, or chain runs can be revived by passing `index` to choose the child. Revive starts a new child process from the old session context; it does not restart the same OS process, and it requires the chosen child to have a persisted `.jsonl` session file.
788
739
 
789
740
  ## Worktree isolation
790
741
 
@@ -865,18 +816,6 @@ Session directory precedence is: `params.sessionDir`, then `config.defaultSessio
865
816
 
866
817
  Controls nested delegation when no inherited `PI_SUBAGENT_MAX_DEPTH` is already in effect. Per-agent `maxSubagentDepth` can tighten the limit for that agent’s child runs, but cannot relax an inherited stricter limit.
867
818
 
868
- ### `agentManager.newShortcut`
869
-
870
- ```json
871
- {
872
- "agentManager": {
873
- "newShortcut": "shift+ctrl+n"
874
- }
875
- }
876
- ```
877
-
878
- Sets the `/agents` list shortcut for opening the new agent/chain template picker. The default is `shift+ctrl+n`; use Pi key names such as `ctrl+n` if your terminal cannot distinguish Shift for control chords.
879
-
880
819
  ### `intercomBridge`
881
820
 
882
821
  ```json
@@ -951,7 +890,7 @@ Async runs write:
951
890
  subagent-log-<id>.md
952
891
  ```
953
892
 
954
- `status.json` powers the widget and `/subagents-status`. `events.jsonl` contains wrapper events plus child Pi JSON events annotated with run and step metadata. `output-<n>.log` is a live human-readable tail. Fallback information is persisted so background runs are debuggable after completion.
893
+ `status.json` powers the widget and `subagent({ action: "status" })` output. `events.jsonl` contains wrapper events plus child Pi JSON events annotated with run and step metadata. `output-<n>.log` is a live human-readable tail. Fallback information is persisted so background runs are debuggable after completion.
955
894
 
956
895
  ## Live progress
957
896
 
@@ -1037,9 +976,8 @@ The main runtime files are:
1037
976
  | `src/runs/foreground/execution.ts` | Core foreground `runSync` handling. |
1038
977
  | `src/runs/background/subagent-runner.ts` | Detached async runner. |
1039
978
  | `src/runs/background/async-execution.ts` | Background launch support. |
1040
- | `src/runs/background/async-status.ts` / `src/tui/subagents-status.ts` | Status discovery and overlay UI. |
979
+ | `src/runs/background/async-status.ts` | Status discovery and formatting for async runs. |
1041
980
  | `src/runs/foreground/chain-execution.ts` / `src/agents/chain-serializer.ts` | Chain orchestration and `.chain.md` parsing. |
1042
- | `src/manager-ui/agent-manager*.ts` | Agents Manager screens and editing flows. |
1043
981
  | `src/shared/settings.ts` | Chain behavior, instructions, and config helpers. |
1044
982
  | `src/runs/shared/worktree.ts` | Git worktree isolation. |
1045
983
  | `src/intercom/intercom-bridge.ts` | Runtime intercom bridge instructions and diagnostics. |
@@ -7,7 +7,6 @@ systemPromptMode: replace
7
7
  inheritProjectContext: true
8
8
  inheritSkills: false
9
9
  defaultReads: plan.md, progress.md
10
- defaultProgress: true
11
10
  ---
12
11
 
13
12
  You are a disciplined review subagent. Your job is to inspect, evaluate, and report findings with evidence. You do not guess; you verify from the code, tests, docs, or requirements.
@@ -59,9 +58,10 @@ Review a PR or issue by understanding the context, then verifying:
59
58
  - Prefer small corrective edits over broad rewrites.
60
59
  - If everything looks good, say so plainly.
61
60
  - If you are asked to maintain progress, record what you checked and what you found.
61
+ - If review-only or no-edit instructions conflict with progress-writing instructions, review-only/no-edit wins. Do not write `progress.md`; mention the conflict in your final review only if it matters.
62
62
 
63
63
  ## Supervisor coordination
64
- If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the review plan. Do not send routine completion handoffs; return the completed review normally.
64
+ If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing; no-edit wins. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the review plan. Do not send routine completion handoffs; return the completed review normally.
65
65
 
66
66
  Fall back to generic `intercom` only if `contact_supervisor` is unavailable and the runtime bridge instructions identify a safe target. If no safe target is discoverable, do not guess.
67
67
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "Pi extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification",
5
5
  "author": "Nico Bailon",
6
6
  "license": "MIT",
@@ -42,7 +42,17 @@ While reviewers run, do your own narrow inspection if useful. After they return,
42
42
  - optional improvements;
43
43
  - feedback to ignore or defer, with a short reason.
44
44
 
45
- Do not blindly apply every reviewer suggestion. Ask before applying fixes unless I already told you to address review feedback.
45
+ Do not blindly apply every reviewer suggestion.
46
+
47
+ Autofix mode: if the invocation contains the exact word `autofix`, treat it as workflow control, not cleanup scope. Remove it before deciding the cleanup target. After synthesis, apply only fixes worth doing now, validate, and summarize. Do not apply optional improvements unless explicitly requested. If there are no fixes worth doing now, do not edit.
48
+
49
+ Without autofix mode, ask before applying fixes unless I already told you to address review feedback. When you ask, end with a compact numbered menu so I can respond with a number. Use wording suited to the findings, but include these choices when applicable:
50
+
51
+ ```text
52
+ Reply with [1], [2], or further instructions:
53
+ [1] Apply only the fixes worth doing now.
54
+ [2] Apply the fixes worth doing now plus optional improvements.
55
+ ```
46
56
 
47
57
  Additional scope or focus from the slash command invocation:
48
58
 
@@ -35,7 +35,17 @@ While reviewers run, do your own narrow inspection if useful. After they return,
35
35
  - optional improvements
36
36
  - feedback to ignore or defer, with a short reason
37
37
 
38
- Do not blindly apply every reviewer suggestion. Ask before applying fixes unless I already told you to address review feedback.
38
+ Do not blindly apply every reviewer suggestion.
39
+
40
+ Autofix mode: if the invocation contains the exact word `autofix`, treat it as workflow control, not review scope. Remove it before deciding the review target. After synthesis, apply only fixes worth doing now, validate, and summarize. Do not apply optional improvements unless explicitly requested. If there are no fixes worth doing now, do not edit.
41
+
42
+ Without autofix mode, ask before applying fixes unless I already told you to address review feedback. When you ask, end with a compact numbered menu so I can respond with a number. Use wording suited to the findings, but include these choices when applicable:
43
+
44
+ ```text
45
+ Reply with [1], [2], or further instructions:
46
+ [1] Apply only the fixes worth doing now.
47
+ [2] Apply the fixes worth doing now plus optional improvements.
48
+ ```
39
49
 
40
50
  Additional review target or focus from the slash command invocation:
41
51
 
@@ -32,9 +32,7 @@ Humans often use the slash-command layer instead:
32
32
  - `/run` — launch a single agent
33
33
  - `/chain` — launch a chain of steps
34
34
  - `/parallel` — launch top-level parallel tasks
35
- - `/agents` — open the agents manager TUI
36
35
  - `/run-chain` — launch a saved `.chain.md` workflow
37
- - `/subagents-status` — inspect active/recent async runs
38
36
  - `/subagents-doctor` — diagnose setup, discovery, async paths, and intercom bridge state
39
37
 
40
38
  Prefer the tool when you are writing agent logic. Prefer the slash commands when
@@ -105,7 +103,7 @@ Use this at the start of non-trivial work. Launch `scout` for local context and
105
103
 
106
104
  ### Parallel cleanup technique
107
105
 
108
- Use this after implementation when the user wants cleanup review or when a final pass would reduce AI-slop. Launch two fresh-context `reviewer` tasks with `output: false`: one deslop pass and one verbosity pass. If the `deslop` or `verbosity-cleaner` skills are available, pass the relevant skill to that reviewer; otherwise inline the criteria. Both reviewers are review-only and should flag concrete issues with severity, file/line references, and smallest safe fixes. The parent decides what to apply and asks before making changes unless cleanup was already authorized.
106
+ Use this after implementation when the user wants cleanup review or when a final pass would reduce AI-slop. Launch two fresh-context `reviewer` tasks with `output: false` and `progress: false`: one deslop pass and one verbosity pass. If the `deslop` or `verbosity-cleaner` skills are available, pass the relevant skill to that reviewer; otherwise inline the criteria. Both reviewers are review-only and should flag concrete issues with severity, file/line references, and smallest safe fixes. Review-only/no-edit beats progress-writing or artifact-writing instructions. The parent decides what to apply and asks before making changes unless cleanup was already authorized.
109
107
 
110
108
  ## Builtin Agents
111
109
 
@@ -131,7 +129,7 @@ For one run, use inline config:
131
129
  /run reviewer[model=anthropic/claude-sonnet-4] "Review this diff"
132
130
  ```
133
131
 
134
- For persistent tweaks, prefer `/agents`: choose the builtin, press `e`, change the model or other fields, then save a user or project override. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides.
132
+ For persistent tweaks, edit `subagents.agentOverrides` in user or project settings. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides.
135
133
 
136
134
  ## Prompting role subagents
137
135
 
@@ -288,7 +286,22 @@ const run = subagent({
288
286
  // Continue local inspection, then later call status with the returned id.
289
287
  ```
290
288
 
291
- Inspect async runs with `subagent({ action: "status", id: "..." })`, `subagent({ action: "status" })` for active runs, or the `/subagents-status` slash command.
289
+ Inspect async runs with `subagent({ action: "status", id: "..." })` or `subagent({ action: "status" })` for active runs.
290
+
291
+ Use `resume` for follow-up work after a delegated run:
292
+
293
+ ```typescript
294
+ subagent({ action: "resume", id: "run-id", message: "Follow up on this point." })
295
+ subagent({ action: "resume", id: "run-id", index: 1, message: "Continue reviewer 2." })
296
+ ```
297
+
298
+ Resume behavior:
299
+ - If an async child is still running and reachable, `resume` sends the follow-up to that live child over intercom.
300
+ - If an async child has completed, `resume` revives it by starting a new async child from the persisted child session file.
301
+ - Multi-child async runs require `index` unless only one running child is selectable.
302
+ - Completed foreground single, parallel, and chain runs can also be revived by `index` while their run metadata remains in extension state.
303
+ - Revive starts a new child process from the old session context; it does not restart the same OS process.
304
+ - If the chosen child has no persisted `.jsonl` session file, resume fails and reports that directly.
292
305
 
293
306
  Use diagnostics when setup or child startup looks wrong:
294
307
 
@@ -346,10 +359,9 @@ subagent({
346
359
  })
347
360
  ```
348
361
 
349
- Chains default to clarify mode unless you explicitly set `clarify: false`.
362
+ Chains default to clarify mode; set `clarify: false` to skip it. Clarify edits affect only the next run; use management actions, settings, or markdown files for persistent changes.
350
363
  For programmatic background launches, use `clarify: false, async: true`.
351
364
 
352
- The `/agents` manager also has launch toggles for forked context, background execution, and worktree-isolated parallel runs. Use it when guiding a human who wants to inspect or edit the launch before starting.
353
365
 
354
366
  ## Worktree Isolation
355
367
 
@@ -409,6 +421,8 @@ Use `contact_supervisor` with `reason: "need_decision"` when:
409
421
  - a child needs clarification instead of guessing
410
422
  - an approval, product, API, or scope choice is required before continuing safely
411
423
 
424
+ Do not use `contact_supervisor` just to resolve review-only/no-edit versus progress-writing or artifact-writing instructions. No-edit wins, and the child should return review findings without touching files.
425
+
412
426
  Use `contact_supervisor` with `reason: "progress_update"` when:
413
427
  - a child is explicitly asked for progress
414
428
  - a meaningful discovery changes the plan
@@ -490,7 +504,7 @@ subagent({ action: "delete", agent: "code-analysis.my-agent" })
490
504
  Use management actions when the system needs to create or edit subagents on
491
505
  demand without dropping into raw file editing.
492
506
 
493
- Management actions create or update user/project agent files. `config.name` is the local frontmatter name; optional `config.package` registers and looks up the runtime name as `{package}.{name}`. Use the dotted runtime name for `get`, `update`, `delete`, slash commands, and chain steps. For small builtin changes such as a model swap, prefer `/agents` builtin overrides or `subagents.agentOverrides` in settings.
507
+ Management actions create or update user/project agent files. `config.name` is the local frontmatter name; optional `config.package` registers and looks up the runtime name as `{package}.{name}`. Use the dotted runtime name for `get`, `update`, `delete`, slash commands, and chain steps. For small builtin changes such as a model swap, prefer `subagents.agentOverrides` in settings.
494
508
 
495
509
  ## Creating and Editing Agents by File
496
510
 
@@ -528,9 +542,11 @@ The package includes prompt shortcuts for common workflows: `/parallel-review`,
528
542
  `/parallel-research`, `/parallel-context-build`, `/parallel-handoff-plan`,
529
543
  `/gather-context-and-clarify`, and `/parallel-cleanup`. Use them when the user
530
544
  wants repeatable review, research, context handoff, implementation handoff,
531
- clarification, or cleanup-review patterns. Parent agents can also apply the same
532
- recipes directly with `subagent(...)` when the user describes the workflow in
533
- natural language instead of invoking a slash command.
545
+ clarification, or cleanup-review patterns. `/parallel-review autofix` and
546
+ `/parallel-cleanup autofix` synthesize reviewer feedback and then apply only the
547
+ fixes worth doing now. Parent agents can also apply the same recipes directly
548
+ with `subagent(...)` when the user describes the workflow in natural language
549
+ instead of invoking a slash command.
534
550
 
535
551
  If `pi-prompt-template-model` is installed, additional user prompt templates can delegate into
536
552
  `pi-subagents`. This is useful when a slash command should always run through a
@@ -622,7 +638,7 @@ clarify → planner → worker → parallel fresh-context reviewers → worker
622
638
 
623
639
  The first `worker` implements the approved plan. The parallel reviewers inspect the resulting diff from fresh context. The final `worker` applies synthesized review fixes in forked context. Do not stop after parallel review unless the user explicitly asked for review-only output or the review surfaced a decision that needs approval first.
624
640
 
625
- Keep orchestration authority in the parent session. Child subagents should not launch more subagents, read this skill, or run their own orchestration loops. Spawned subagents do not receive the `pi-subagents` skill, parent-only subagent status/control/slash messages, prior parent `subagent` tool-call/tool-result artifacts, or the `subagent` extension tool. Child context filtering also strips old hidden orchestration-instruction messages when they appear in inherited history. Every child also receives a boundary instruction that says the parent owns orchestration, the child must not propose or run subagents, and implementation children must call real edit/write tools instead of printing pseudo tool calls. Pass children concrete role-specific work instead.
641
+ Keep orchestration authority in the parent session. Child subagents should not launch more subagents, read this skill, or run their own orchestration loops. Spawned subagents do not receive the `pi-subagents` skill, parent-only status/control/slash messages, prior parent `subagent` tool-call/tool-result artifacts, or the `subagent` extension tool. Child context filtering also strips old hidden orchestration-instruction messages when they appear in inherited history. Every child also receives a boundary instruction that says the parent owns orchestration, the child must not propose or run subagents, and implementation children must call real edit/write tools instead of printing pseudo tool calls. Pass children concrete role-specific work instead.
626
642
 
627
643
  1. Clarify first. This is mandatory. Gather code context with `scout` or `context-builder`, add `researcher` only when external evidence matters, then ask the user clarifying questions with `interview` until scope, acceptance criteria, constraints, and non-goals are clear.
628
644
  2. Plan when useful. For complex work, call `planner` or write a plan doc yourself and get approval before implementation. For simple work, confirm shared understanding and explicitly note why planning is skipped.
@@ -727,5 +743,5 @@ subagent({ action: "doctor" })
727
743
 
728
744
  **Child fails before starting**
729
745
  ```typescript
730
- // Inspect /subagents-status detail, artifact metadata/output logs, and run doctor. Extension loader errors usually appear in child output logs.
746
+ // Inspect `subagent({ action: "status", id: "..." })`, artifact metadata/output logs, and run doctor. Extension loader errors usually appear in child output logs.
731
747
  ```
@@ -1,4 +1,3 @@
1
- import * as fs from "node:fs";
2
1
  import type { AgentConfig } from "./agents.ts";
3
2
  import { frontmatterNameForConfig } from "./identity.ts";
4
3
 
@@ -83,44 +82,3 @@ export function serializeAgent(config: AgentConfig): string {
83
82
  const body = config.systemPrompt ?? "";
84
83
  return `${lines.join("\n")}\n\n${body}\n`;
85
84
  }
86
-
87
- export function updateFrontmatterField(filePath: string, field: string, value: string | undefined): void {
88
- const raw = fs.readFileSync(filePath, "utf-8");
89
- const normalized = raw.replace(/\r\n/g, "\n");
90
- if (!normalized.startsWith("---")) {
91
- throw new Error("Frontmatter not found");
92
- }
93
-
94
- const endIndex = normalized.indexOf("\n---", 3);
95
- if (endIndex === -1) {
96
- throw new Error("Frontmatter not found");
97
- }
98
-
99
- const frontmatterBlock = normalized.slice(4, endIndex);
100
- const rest = normalized.slice(endIndex + 4);
101
- const lines = frontmatterBlock.split("\n");
102
-
103
- const normalizedField = field === "skill" || field === "skills" ? "skills" : field;
104
- const targetKeys = field === "skills" ? new Set(["skill", "skills"]) : new Set([field]);
105
- let found = false;
106
- const updated: string[] = [];
107
-
108
- for (const line of lines) {
109
- const match = line.match(/^([\w-]+):\s*(.*)$/);
110
- if (match && targetKeys.has(match[1])) {
111
- if (value !== undefined) {
112
- if (!found) updated.push(`${normalizedField}: ${value}`);
113
- found = true;
114
- }
115
- continue;
116
- }
117
- updated.push(line);
118
- }
119
-
120
- if (value !== undefined && !found) {
121
- updated.push(`${normalizedField}: ${value}`);
122
- }
123
-
124
- const frontmatter = `---\n${updated.join("\n")}\n---`;
125
- fs.writeFileSync(filePath, frontmatter + rest, "utf-8");
126
- }
@@ -130,7 +130,7 @@ interface AgentDiscoveryResult {
130
130
  projectAgentsDir: string | null;
131
131
  }
132
132
 
133
- export function getUserChainDir(): string {
133
+ function getUserChainDir(): string {
134
134
  return path.join(os.homedir(), ".pi", "agent", "chains");
135
135
  }
136
136
 
@@ -9,7 +9,7 @@
9
9
  * Toggle: async parameter (default: false, configurable via config.json)
10
10
  *
11
11
  * Config file: ~/.pi/agent/extensions/subagent/config.json
12
- * { "asyncByDefault": true, "forceTopLevelAsync": true, "maxSubagentDepth": 1, "agentManager": { "newShortcut": "shift+ctrl+n" }, "intercomBridge": { "mode": "always", "instructionFile": "./intercom-bridge.md" }, "worktreeSetupHook": "./scripts/setup-worktree.mjs" }
12
+ * { "asyncByDefault": true, "forceTopLevelAsync": true, "maxSubagentDepth": 1, "intercomBridge": { "mode": "always", "instructionFile": "./intercom-bridge.md" }, "worktreeSetupHook": "./scripts/setup-worktree.mjs" }
13
13
  */
14
14
 
15
15
  import * as fs from "node:fs";
@@ -24,7 +24,7 @@ import { resolveCurrentSessionId } from "../shared/session-identity.ts";
24
24
  import { cleanupOldChainDirs } from "../shared/settings.ts";
25
25
  import { renderWidget, renderSubagentResult, stopResultAnimations, stopWidgetAnimation, syncResultAnimation } from "../tui/render.ts";
26
26
  import { SubagentParams } from "./schemas.ts";
27
- import { createSubagentExecutor } from "../runs/foreground/subagent-executor.ts";
27
+ import { createSubagentExecutor, type SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
28
28
  import { createAsyncJobTracker } from "../runs/background/async-job-tracker.ts";
29
29
  import { createResultWatcher } from "../runs/background/result-watcher.ts";
30
30
  import { registerSlashCommands } from "../slash/slash-commands.ts";
@@ -245,6 +245,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
245
245
  baseCwd: process.cwd(),
246
246
  currentSessionId: null,
247
247
  asyncJobs: new Map(),
248
+ foregroundRuns: new Map(),
248
249
  foregroundControls: new Map(),
249
250
  lastForegroundControlId: null,
250
251
  pendingForegroundControlNotices: new Map(),
@@ -336,11 +337,16 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
336
337
  return new SubagentControlNoticeComponent({ ...details, noticeText: formatSubagentControlNotice(details, content) }, theme);
337
338
  });
338
339
 
340
+ const executeSubagentCollapsed = (id: string, params: SubagentParamsLike, signal: AbortSignal, onUpdate: ((result: AgentToolResult<Details>) => void) | undefined, ctx: ExtensionContext) => {
341
+ if (ctx.hasUI) ctx.ui.setToolsExpanded(false);
342
+ return executor.execute(id, params, signal, onUpdate, ctx);
343
+ };
344
+
339
345
  const slashBridge = registerSlashSubagentBridge({
340
346
  events: pi.events,
341
347
  getContext: () => state.lastUiContext,
342
348
  execute: (id, params, signal, onUpdate, ctx) =>
343
- executor.execute(id, params, signal, onUpdate, ctx),
349
+ executeSubagentCollapsed(id, params, signal, onUpdate, ctx),
344
350
  });
345
351
 
346
352
  const promptTemplateBridge = registerPromptTemplateDelegationBridge({
@@ -348,7 +354,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
348
354
  getContext: () => state.lastUiContext,
349
355
  execute: async (requestId, request, signal, ctx, onUpdate) => {
350
356
  if (request.tasks && request.tasks.length > 0) {
351
- return executor.execute(
357
+ return executeSubagentCollapsed(
352
358
  requestId,
353
359
  {
354
360
  tasks: request.tasks,
@@ -363,7 +369,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
363
369
  ctx,
364
370
  );
365
371
  }
366
- return executor.execute(
372
+ return executeSubagentCollapsed(
367
373
  requestId,
368
374
  {
369
375
  agent: request.agent,
@@ -419,14 +425,14 @@ MANAGEMENT (use action field, omit agent/task/chain/tasks):
419
425
  CONTROL:
420
426
  • { action: "status", id: "..." } - inspect an async/background run by id or prefix
421
427
  • { action: "interrupt", id?: "..." } - soft-interrupt the current child turn and leave the run paused
422
- • { action: "resume", id: "...", message: "..." } - follow up with a live async child or revive a completed single-child async run from its session
428
+ • { action: "resume", id: "...", message: "...", index?: 0 } - follow up with a live async child or revive a completed async/foreground child from its session
423
429
 
424
430
  DIAGNOSTICS:
425
431
  • { action: "doctor" } - read-only report for runtime paths, discovery, sessions, and intercom`,
426
432
  parameters: SubagentParams,
427
433
 
428
434
  execute(id, params, signal, onUpdate, ctx) {
429
- return executor.execute(id, params, signal, onUpdate, ctx);
435
+ return executeSubagentCollapsed(id, params, signal, onUpdate, ctx);
430
436
  },
431
437
 
432
438
  renderCall(args, theme) {
@@ -467,7 +473,7 @@ DIAGNOSTICS:
467
473
  };
468
474
 
469
475
  pi.registerTool(tool);
470
- registerSlashCommands(pi, state, config);
476
+ registerSlashCommands(pi, state);
471
477
 
472
478
  const eventUnsubscribeStoreKey = "__piSubagentEventUnsubscribes";
473
479
  const controlNoticeSeenStoreKey = "__piSubagentVisibleControlNotices";
@@ -116,7 +116,7 @@ export const SubagentParams = Type.Object({
116
116
  description: "Async run directory for action='status' or action='resume'."
117
117
  })),
118
118
  index: Type.Optional(Type.Integer({ minimum: 0, description: "Zero-based child index for actions that target a specific child." })),
119
- message: Type.Optional(Type.String({ description: "Follow-up message for action='resume'." })),
119
+ message: Type.Optional(Type.String({ description: "Follow-up message for action='resume'. Use index to choose a child from multi-child runs." })),
120
120
  // Chain identifier for management (can't reuse 'chain' — that's the execution array)
121
121
  chainName: Type.Optional(Type.String({
122
122
  description: "Chain name for get/update/delete management actions"
@@ -31,6 +31,7 @@ const DEFAULT_INTERCOM_BRIDGE_TEMPLATE = `The inherited thread is reference-only
31
31
  Use contact_supervisor first. It resolves the supervisor session "{orchestratorTarget}" and run metadata automatically.
32
32
  - Need a decision, blocked, approval, or product/API/scope ambiguity: contact_supervisor({ reason: "need_decision", message: "<question>" })
33
33
  - After contact_supervisor with reason "need_decision", stay alive and continue only after the reply arrives. Do not finish your final response with a choose-one question.
34
+ - Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions. Review-only/no-edit wins; leave files unchanged and mention the conflict in your final result only if it matters.
34
35
  - Meaningful progress or unexpected discoveries that change the plan: contact_supervisor({ reason: "progress_update", message: "UPDATE: <summary>" })
35
36
  - Generic intercom is lower-level plumbing/fallback only: intercom({ action: "ask", to: "{orchestratorTarget}", message: "<question>" })
36
37
 
@@ -116,7 +117,9 @@ function intercomConfigStatus(configPath: string): { enabled: boolean; error?: u
116
117
  function readJsonBestEffort(filePath: string): unknown {
117
118
  try {
118
119
  return JSON.parse(fs.readFileSync(filePath, "utf-8"));
119
- } catch {
120
+ } catch (error) {
121
+ const code = error && typeof error === "object" && "code" in error ? (error as NodeJS.ErrnoException).code : undefined;
122
+ if (code !== "ENOENT") console.warn(`Failed to read JSON from '${filePath}'.`, error);
120
123
  return null;
121
124
  }
122
125
  }
@@ -1,4 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
+ import * as fs from "node:fs";
2
3
  import {
3
4
  type Details,
4
5
  type IntercomEventBus,
@@ -76,11 +77,15 @@ function asyncResumeGuidance(input: {
76
77
  asyncId?: string;
77
78
  }): string | undefined {
78
79
  if (input.source !== "async" || !input.asyncId) return undefined;
79
- if (input.children.length === 1 && typeof input.children[0]?.sessionPath === "string") {
80
+ const resumable = input.children.filter((child) => typeof child.sessionPath === "string" && fs.existsSync(child.sessionPath));
81
+ if (input.children.length === 1 && resumable.length === 1) {
80
82
  return `Revive: subagent({ action: "resume", id: "${input.asyncId}", message: "..." })`;
81
83
  }
82
- if (input.children.length > 1) return "Resume: unsupported for multi-child async runs until per-child session files are persisted.";
83
- return "Resume: unavailable; no single child session file was persisted.";
84
+ if (resumable.length > 0) {
85
+ const firstIndex = resumable[0]?.index ?? input.children.indexOf(resumable[0]!);
86
+ return `Revive child: subagent({ action: "resume", id: "${input.asyncId}", index: ${firstIndex}, message: "..." })`;
87
+ }
88
+ return "Resume: unavailable; no child session file was persisted.";
84
89
  }
85
90
 
86
91
  function formatSubagentResultIntercomMessage(input: {