pi-herdr-agents 0.0.1

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 (49) hide show
  1. package/AGENTS.md +116 -0
  2. package/CONTEXT.md +159 -0
  3. package/LICENSE +21 -0
  4. package/README.md +874 -0
  5. package/RELEASING.md +139 -0
  6. package/agents/adversarial-reviewer.md +80 -0
  7. package/agents/claude-reviewer.md +23 -0
  8. package/agents/planner.md +539 -0
  9. package/agents/poteto.md +32 -0
  10. package/agents/reviewer.md +164 -0
  11. package/agents/scout.md +106 -0
  12. package/agents/visual-tester.md +224 -0
  13. package/agents/worker.md +132 -0
  14. package/config.json.example +8 -0
  15. package/docs/README.md +42 -0
  16. package/docs/adr/0001-btw-ephemeral-side-questions.md +142 -0
  17. package/docs/adr/0002-agent-workflow-skill-runtime-taxonomy.md +265 -0
  18. package/docs/adr/0003-installable-role-packs.md +135 -0
  19. package/docs/adr/0004-require-active-user-approval-for-workflow-execution.md +17 -0
  20. package/docs/adr/0005-parent-owns-workflow-script-authority.md +17 -0
  21. package/docs/adr/0006-limit-v1-execution-effects-to-isolated-worktrees.md +18 -0
  22. package/docs/adr/0007-require-fresh-review-for-workflow-scripts.md +19 -0
  23. package/docs/orchestrated-review-workflow-plan.md +479 -0
  24. package/docs/research/pdw-architecture-assessment.md +525 -0
  25. package/docs/research/pi-workflows-sol-advisor.md +255 -0
  26. package/docs/research/worktree-subagent-orchestration.md +317 -0
  27. package/docs/worktree-subagents.md +196 -0
  28. package/examples/role-pack/extension.ts +18 -0
  29. package/examples/role-pack/package.json +16 -0
  30. package/examples/role-pack/roles/example-reviewer.md +12 -0
  31. package/package.json +58 -0
  32. package/pi-extension/subagents/activity.ts +511 -0
  33. package/pi-extension/subagents/completion.ts +177 -0
  34. package/pi-extension/subagents/herdr.ts +541 -0
  35. package/pi-extension/subagents/index.ts +4730 -0
  36. package/pi-extension/subagents/lifecycle.ts +477 -0
  37. package/pi-extension/subagents/model-config.ts +95 -0
  38. package/pi-extension/subagents/plan-skill.md +262 -0
  39. package/pi-extension/subagents/plugin/.claude-plugin/plugin.json +5 -0
  40. package/pi-extension/subagents/plugin/hooks/hooks.json +15 -0
  41. package/pi-extension/subagents/plugin/hooks/on-stop.sh +68 -0
  42. package/pi-extension/subagents/runtime-routing.ts +313 -0
  43. package/pi-extension/subagents/session.ts +216 -0
  44. package/pi-extension/subagents/status.ts +513 -0
  45. package/pi-extension/subagents/subagent-done.ts +326 -0
  46. package/pi-extension/subagents/terminal.ts +163 -0
  47. package/pi-extension/subagents/workflow-worker.js +56 -0
  48. package/pi-extension/subagents/workflow.ts +1210 -0
  49. package/skills/orchestrate/SKILL.md +184 -0
package/README.md ADDED
@@ -0,0 +1,874 @@
1
+ # Pi Herdr Agents
2
+
3
+ Async subagents for [Pi](https://github.com/earendil-works/pi) running exclusively in [Herdr](https://herdr.dev). Spawn, orchestrate, and manage sub-agent sessions in dedicated herdr tabs or panes. **Fully non-blocking** — the main agent keeps working while subagents run in the background.
4
+
5
+ Package: `pi-herdr-agents` · Repository: [`giuseppecrj/pi-herdr-agents`](https://github.com/giuseppecrj/pi-herdr-agents)
6
+
7
+ ## How It Works
8
+
9
+ Call `subagent()` and it **returns immediately**. The sub-agent runs in its own terminal pane. A live widget above the input shows all tracked agents with their projected state — for example `starting`, `active`, `waiting`, `blocked`, `interrupted`, `stalled`, `running`, or `finalizing`. The header summarizes **active** (processing) vs **open** (not processing). When every tracked subagent is open, the border switches to amber. When a sub-agent finishes, its result is **steered back** into the main session as an async notification — triggering a new turn so the agent can process it.
10
+
11
+ ```
12
+ ╭─ Subagents ──────────────────── 1 active · 1 open ─╮
13
+ │ 00:23 Scout: Auth (scout) active · bash 7m │
14
+ │ 00:45 Scout: DB (scout) waiting 2m │
15
+ ╰────────────────────────────────────────────────────╯
16
+ ```
17
+
18
+ For parallel execution, just call `subagent` multiple times — they all run concurrently:
19
+
20
+ ```typescript
21
+ subagent({ name: "Scout: Auth", agent: "scout", task: "Analyze auth module" });
22
+ subagent({ name: "Scout: DB", agent: "scout", task: "Map database schema" });
23
+ // Both return immediately, results steer back independently
24
+ ```
25
+
26
+ Read-only agents can safely share the parent checkout. For parallel agents that write files, give each task a unique Herdr-managed worktree; see [Worktree subagents](docs/worktree-subagents.md).
27
+
28
+ ## Development
29
+
30
+ Run unit tests and lint locally:
31
+
32
+ ```bash
33
+ npm test
34
+ npm run lint
35
+ ```
36
+
37
+ Run the required end-to-end suite from inside herdr:
38
+
39
+ ```bash
40
+ npm run test:integration
41
+ ```
42
+
43
+ It launches real Pi sessions, Herdr panes, worktrees, and the extension from the working tree, but routes model requests to a local deterministic fixture. It needs no provider credentials or network access.
44
+
45
+ An optional live-provider smoke test remains available for Pi/provider compatibility; it is not a merge gate:
46
+
47
+ ```bash
48
+ PI_TEST_MODEL="openai-codex/gpt-5.6-luna" PI_TEST_TIMEOUT=180000 \
49
+ npm run test:integration:live
50
+ ```
51
+
52
+ `PI_TEST_MODEL` selects the parent and child runtime only in live mode.
53
+
54
+ ## Install
55
+
56
+ Install the package globally from npm:
57
+
58
+ ```bash
59
+ pi install npm:pi-herdr-agents
60
+ ```
61
+
62
+ Use `pi install -l npm:pi-herdr-agents` for a project-local installation, or try it for one run without changing settings:
63
+
64
+ ```bash
65
+ pi -e npm:pi-herdr-agents
66
+ ```
67
+
68
+ Pi packages execute with your user account's full system access. Review the package source before installation. Claude CLI children always launch with `--dangerously-skip-permissions`, so those runs skip Claude's interactive permission prompts.
69
+
70
+ After the one-time first-package bootstrap, changing the `package.json` version on `main` automatically publishes to npm and creates the matching Git tag and GitHub Release. For bootstrap authentication, versioning, verification, and troubleshooting, see [RELEASING.md](RELEASING.md).
71
+
72
+ Start herdr, then run pi inside it:
73
+
74
+ ```bash
75
+ herdr
76
+ pi
77
+ ```
78
+
79
+ herdr is the only supported terminal environment. The extension requires `HERDR_ENV=1` and the `herdr` CLI to be available.
80
+
81
+ If your shell startup is slow and subagent commands sometimes get dropped before the prompt is ready, set `PI_SUBAGENT_SHELL_READY_DELAY_MS` to a higher value (defaults to `500`):
82
+
83
+ ```bash
84
+ export PI_SUBAGENT_SHELL_READY_DELAY_MS=2500
85
+ ```
86
+
87
+ ### Troubleshooting completion delivery
88
+
89
+ If a child finishes but the parent returns an empty or unrelated response, first verify that the result reached the parent session:
90
+
91
+ ```bash
92
+ jq -c 'select(.type == "custom_message" and .customType == "subagent_result")' "$PI_SESSION_FILE" | tail -1
93
+ ```
94
+
95
+ If the entry exists, spawning and result extraction worked; investigate parent wake-up and model-facing delivery rather than the child process. Completion wake-ups must contain the bounded result directly—do not send a separate message that merely tells the parent to look at an adjacent custom message.
96
+
97
+ Git package refs are pinned. To move an installed development copy back to the current `main`, install that ref explicitly and reload the active Pi session:
98
+
99
+ ```bash
100
+ pi install git:github.com/giuseppecrj/pi-herdr-agents@main
101
+ # Then run /reload inside Pi.
102
+ ```
103
+
104
+ Smoke-test delivery with an autonomous subagent instructed to return one exact marker. Success means the marker itself—not only a generic wake-up notice—automatically appears in the parent turn.
105
+
106
+ Subagent tabs, panes, and worktree workspaces are created without stealing keyboard focus. Launch commands target child panes by explicit ID, so focus and command delivery are independent. Note: the `interactive` option controls parent status notifications, not terminal focus.
107
+
108
+ ## What's Included
109
+
110
+ ### Extensions
111
+
112
+ **Subagents** — 5 main-session tools + 5 commands, plus 2 child-only tools:
113
+
114
+ | Tool | Description |
115
+ | -------------------- | ------------------------------------------------------------------------------------------- |
116
+ | `subagent` | Spawn a sub-agent in a dedicated herdr pane (async — returns immediately) |
117
+ | `subagent_interrupt` | Interrupt a running Pi-backed subagent's current turn |
118
+ | `subagents_list` | List available agent definitions |
119
+ | `subagent_resume` | Resume a previous Pi-backed sub-agent session in a new ordinary pane (async) |
120
+ | `herdr_workflow` | Prepare, start, or cancel one exact approved project-local review workflow |
121
+
122
+ | Pi child-only tool | Description |
123
+ | ---------------- | ------------------------------------------------------------------------- |
124
+ | `caller_ping` | Exit and ask the parent for help |
125
+ | `subagent_done` | Mark an interactive child complete and exit; autonomous agents auto-exit |
126
+
127
+ | Command | Description |
128
+ | -------------------------- | ------------------------------------ |
129
+ | `/plan` | Start a full planning workflow |
130
+ | `/iterate` | Fork into a subagent for quick fixes |
131
+ | `/btw <question>` | Open an ephemeral side-question session in a background tab |
132
+ | `/btw-close` | Close the current BTW session |
133
+ | `/subagent <agent> <task>` | Spawn a named agent directly (`/subagent list` lists available agents) |
134
+
135
+ ### Taxonomy and discovery
136
+
137
+ This package uses five distinct concepts:
138
+
139
+ - An **agent role** is a directly runnable responsibility such as scouting,
140
+ implementation, or review.
141
+ - A **workflow** is a user-facing recipe that composes roles, ordering,
142
+ artifacts, and runtime policy.
143
+ - A **skill** is a Pi-native procedure loaded into the current agent. Skills are
144
+ dependencies of roles or workflows, not subagent definitions.
145
+ - A **runtime** is how an invocation executes: Pi or an external CLI, plus its
146
+ model and thinking policy.
147
+ - An **adapter** is a hidden runtime-specific definition used by a workflow.
148
+
149
+ See [ADR-0002](docs/adr/0002-agent-workflow-skill-runtime-taxonomy.md) for the
150
+ accepted decision, rationale, migration boundaries, and evidence.
151
+
152
+ The current workflow inventory is:
153
+
154
+ | Workflow | Entry point | Composition, artifacts, and runtime |
155
+ | -------- | ----------- | ----------------------------------- |
156
+ | Planning | `/plan` | Scout → interactive planner → workers → reviewer; writes `.pi/plans/...` artifacts; runs on Pi. |
157
+ | Iteration | `/iterate` | Opens one interactive full-context Pi fork and returns its completion summary. |
158
+ | Side question | `/btw`, `/btw-close` | Opens one replaceable interactive Pi side session; its answer stays outside the parent transcript. |
159
+ | Approved review runner | `herdr_workflow` (low-level control tool) | Validates and runs exact approved project-local JavaScript with bounded read-only Pi reviewers. The bundled `orchestrate` skill authors this first-flow topology. |
160
+ | Adversarial review | `adversarial-reviewer` | Transitional workflow implementation that runs Pi reviewer passes plus the hidden Claude CLI adapter and writes `.reviews/...` artifacts. It remains visible and launchable until a dedicated workflow surface replaces it. |
161
+
162
+ ### Bundled visible definitions
163
+
164
+ | Definition | Classification | Default runtime | Responsibility |
165
+ | ---------- | -------------- | --------------- | -------------- |
166
+ | **planner** | Coordinator agent role | Config, then parent | Clarifies requirements, explores approaches, and writes plans with ordered tasks. |
167
+ | **scout** | Leaf agent role | Config, then parent | Maps relevant code, conventions, and verification paths. |
168
+ | **worker** | Leaf agent role | Config, then parent | Implements bounded tasks and verifies the result. |
169
+ | **reviewer** | Leaf agent role | Config, then parent | Reviews changes for correctness, security, and maintainability. |
170
+ | **visual-tester** | Leaf agent role | Config, then parent | Performs visual QA through the `chrome-cdp` skill. |
171
+ | **poteto** | Coordinator agent role | Config, then parent | Autonomously investigates, edits minimally, delegates independent work, and verifies. |
172
+ | **adversarial-reviewer** | Transitional workflow implementation | Grok + GPT + Claude | Runs evidence-backed Optimizer and Skeptic review passes. |
173
+
174
+ `claude-reviewer` is an internal Claude CLI adapter. Discovery hides it, but
175
+ workflows can still load and invoke it by exact name. Its CLI and the Claude pass
176
+ in adversarial review require `claude` and always add `--dangerously-skip-permissions`;
177
+ adversarial review also requires live authenticated XAI/Grok and OpenAI Codex
178
+ model IDs. Optional prerequisites fail closed and are not bundled:
179
+
180
+ - `visual-tester` needs an external `chrome-cdp` skill that provides `scripts/cdp.mjs`.
181
+ - `/plan` uses the bundled scout and planner roles and records ordered tasks in
182
+ `plan.md`; it does not require a researcher role, todo tool, or `write-todos` skill.
183
+
184
+ This package does not install optional prerequisites.
185
+
186
+ Bundled agents use model defaults from `config.json` when configured; otherwise
187
+ they inherit the parent model. Thinking defaults still come from agent
188
+ frontmatter or the parent level. The orchestrating agent can override either
189
+ field for a specific task using an exact authenticated model ID and a supported
190
+ Pi thinking level. Prefer changing thinking before changing models.
191
+
192
+ Discovery loads definitions in **package → global → project** order, so effective
193
+ priority remains **project** (`.pi/agents/`) > **global**
194
+ (`$PI_CODING_AGENT_DIR/agents/`, defaulting to `~/.pi/agent/agents/`) >
195
+ **package**. Package definitions include bundled roles and roles contributed by
196
+ installed Pi role packs. Both `subagents_list` and `/subagent list` show each
197
+ visible definition's source; contributed roles include their package identity,
198
+ for example `(package:@acme/security-roles)`. A hidden higher-priority definition
199
+ still suppresses a visible lower-priority definition.
200
+
201
+ Custom roles and installable role packs are the package's main extension points.
202
+ See [Custom Agents](#custom-agents) for the complete create, package, verify, and
203
+ launch workflow.
204
+
205
+ ---
206
+
207
+ ## Async Subagent Flow
208
+
209
+ ```
210
+ 1. Agent calls subagent() → returns immediately ("started")
211
+ 2. Sub-agent runs in herdr pane → widget shows live status
212
+ 3. User keeps chatting → main session fully interactive
213
+ 4. Sub-agent finishes → result steered back as a normal completion/failure
214
+ 5. Main agent processes result → continues with new context
215
+ ```
216
+
217
+ Multiple subagents run concurrently — each steers its result back independently as it finishes. Active watchers survive parent `/reload`, `/new`, `/resume`, and `/fork` transitions, so completion is delivered into the replacement session. Quitting Pi still stops parent-side delivery. The live widget above the input tracks every agent still in flight:
218
+
219
+ ```
220
+ ╭─ Subagents ──────────────────── 1 active · 2 open ─╮
221
+ │ 01:23 Scout: Auth (scout) active · read 7m │
222
+ │ 00:45 Reviewer (reviewer) stalled 4m │
223
+ │ 00:12 Scout: DB (scout) starting… │
224
+ ╰─────────────────────────────────────────────────────────╯
225
+ ```
226
+
227
+ Completion messages render with a colored background and are expandable with `Ctrl+O`. Results larger than 16,000 characters are abbreviated in the parent context while preserving their beginning, conclusion, and session path; the complete result remains in the child session. The extension includes that bounded result directly in the user message that wakes Pi, avoiding empty turns caused by a separate context-free follow-up. Completed rows are removed from the widget as soon as their result is delivered or suppressed.
228
+
229
+ ### In-progress status updates
230
+
231
+ The widget projects each sub-agent from a **process + turn lifecycle**:
232
+
233
+ - **Herdr pane inspection** is the coarse authority for whether the child process is present and whether Herdr reports it as idle, working, blocked, or done.
234
+ - **Child activity snapshots** enrich the label with Pi-only detail (tool name, streaming, etc.) when available.
235
+ - Session JSONL is still used for transcript, resume, lineage, and result extraction — not for liveness.
236
+
237
+ Projected labels include:
238
+
239
+ - `starting` — launched; pane/activity confirmation is still settling
240
+ - `active` — processing work (agent turn, provider request, streaming, or tool execution)
241
+ - `blocked` — Herdr reports the child as blocked
242
+ - `waiting` — turn finished; the process is intentionally open for more input or another stage
243
+ - `interrupted` — the current turn was cancelled (Escape / `subagent_interrupt`); the process stays open and is **not** treated as active processing
244
+ - `stalled` — pane inspection is unhealthy long enough that the parent can no longer trust the run
245
+ - `running` — fallback when only coarse process presence is known (e.g. non-Pi backends)
246
+ - `finalizing` — completion was observed and delivery is in progress; the process elapsed timer freezes here
247
+
248
+ The widget header counts **active** vs **open**:
249
+
250
+ - **active** — `active`, `starting`, `running`, or `blocked`
251
+ - **open** — everything else still tracked (`waiting`, `interrupted`, `stalled`, `finalizing`, …)
252
+
253
+ When `activeCount === 0` (every tracked row is open), the border uses an amber accent. Process elapsed time (`MM:SS` on the left) freezes when the process reaches finalizing/completed/failed. Interrupt does **not** freeze that process clock; the interrupted state shows its own duration on the right while the process remains open.
254
+
255
+ A fixed internal watchdog marks a run as `stalled` when pane inspection fails or the pane disappears without a completion sidecar; valid long-running `active` or `waiting` states do not become `stalled` just because time passes. When a run enters `stalled` or recovers from it, the parent agent receives a steer message so it can react. All other status transitions stay in the widget only.
256
+
257
+ **Interactive subagents stay silent.** Long-running user-driven subagents (e.g. `planner`, or any `/iterate` fork) do not wake the parent session on `stalled`/`recovered` transitions — the user is working directly in the subagent's pane, and a steer message there would just burn an orchestrator turn on a no-op "still waiting" ping. The widget still updates normally, and activity snapshots are still recorded/classified regardless of the `interactive` setting. By default, agents with `auto-exit: true` are treated as autonomous and get stall pings; agents without it are treated as interactive and stay quiet. Override per-agent with `interactive: true|false` in frontmatter, or per-spawn with `interactive: true|false` on the tool call.
258
+
259
+ #### Configuration
260
+
261
+ The extension reads `config.json` from the installed package root—the directory
262
+ containing this README and `package.json`, not `pi-extension/subagents/` or
263
+ Herdr's `config.toml`. That file is package-local: npm or git package updates may
264
+ overwrite it. Common global package roots are:
265
+
266
+ - npm: `~/.pi/agent/npm/node_modules/pi-herdr-agents/`
267
+ - git: `~/.pi/agent/git/<host>/<owner>/pi-herdr-agents/`
268
+
269
+ Project-local installs use the corresponding `.pi/npm/` or `.pi/git/` root.
270
+ From the actual package root, copy the example when you want local overrides:
271
+
272
+ ```bash
273
+ cp config.json.example config.json
274
+ ```
275
+
276
+ ```json
277
+ {
278
+ "status": {
279
+ "enabled": true
280
+ },
281
+ "models": {
282
+ "agents": {}
283
+ }
284
+ }
285
+ ```
286
+
287
+ If `config.json` is absent, status settings fall back to `config.json.example`.
288
+ Model routing does not read the example: no model overrides apply until a real
289
+ `config.json` exists.
290
+
291
+ The copyable example is model-neutral, so it works without requiring credentials
292
+ for a specific provider. To configure models, replace the empty section with
293
+ exact IDs from your authenticated model catalog:
294
+
295
+ ```json
296
+ {
297
+ "models": {
298
+ "default": "your-provider/your-default-model",
299
+ "agents": {
300
+ "scout": "your-provider/your-fast-model",
301
+ "reviewer": "your-provider/your-review-model"
302
+ }
303
+ }
304
+ }
305
+ ```
306
+
307
+ `models.default` sets the model for subagents that do not specify a model.
308
+ `models.agents` sets per-agent defaults, keyed by the agent name passed to
309
+ `subagent({ agent: ... })`. Explicit `model` tool arguments take precedence,
310
+ followed by agent frontmatter, per-agent config, the global default, and finally
311
+ the parent model. Model values must be exact authenticated `provider/model-id`
312
+ references.
313
+
314
+ `config.json` is gitignored in the source tree so local overrides are not
315
+ committed from a checkout. On an installed package root, treat it as disposable
316
+ local state that package updates may replace. Run `/reload` after changing it;
317
+ status and model configuration are loaded when the extension starts.
318
+
319
+ ---
320
+
321
+ ## Spawning Subagents
322
+
323
+ ```typescript
324
+ // Named agent with defaults from agent definition or config.json
325
+ subagent({ name: "Scout", agent: "scout", task: "Analyze the codebase..." });
326
+
327
+ // Force a full-context fork for this spawn
328
+ subagent({ name: "Iterate", fork: true, task: "Fix the bug where..." });
329
+
330
+ // Agent defaults can choose a different session-mode via frontmatter
331
+ subagent({ name: "Planner", agent: "planner", task: "Work through the design with me" });
332
+
333
+ // Custom working directory
334
+ subagent({ name: "Designer", agent: "game-designer", cwd: "agents/game-designer", task: "..." });
335
+
336
+ // Isolated ticket branch in a Herdr-managed Git worktree
337
+ subagent({
338
+ name: "Ticket 123",
339
+ agent: "worker",
340
+ worktree: { branch: "ticket/123", base: "main" },
341
+ task: "Implement ticket 123, test it, and commit the result",
342
+ });
343
+ ```
344
+
345
+ ### Parameters
346
+
347
+ | Parameter | Type | Default | Description |
348
+ | ---------------------- | ------- | -------------- | ------------------------------------------------------------------------------------------------- |
349
+ | `name` | string | required | Display name (shown in widget and pane title) |
350
+ | `task` | string | required | Task prompt for the sub-agent |
351
+ | `agent` | string | — | Load defaults from agent definition |
352
+ | `fork` | boolean | `false` | Force the full-context fork mode for this spawn, overriding any agent `session-mode` frontmatter |
353
+ | `interactive` | boolean | derived | Mark this spawn as interactive (don't wake the parent on stall/recovery). Defaults to the agent's `interactive` frontmatter, otherwise the inverse of `auto-exit`. |
354
+ | `model` | string | configured or parent | Exact authenticated `provider/model-id`; resolution is tool argument → agent frontmatter → per-agent config → global config → parent |
355
+ | `thinking` | string | parent level | Pi thinking level (`off` through `max`); omit to inherit the parent |
356
+ | `systemPrompt` | string | — | Role/system-prompt text for a bare spawn; overrides the body for Claude CLI agents, while named Pi agents keep their definition body |
357
+ | `resumeSessionId` | string | — | Claude CLI session ID to resume; separate from the Pi `subagent_resume` tool |
358
+ | `skills` | string | — | Comma-separated skill names |
359
+ | `tools` | string | — | Comma-separated tool names |
360
+ | `cwd` | string | — | Working directory, or source repository when `worktree` is set (see [Role Folders](#role-folders)) |
361
+ | `worktree` | object | — | Isolated Herdr-managed Git worktree; requires `branch`, with optional `base` (committed `HEAD` by default) |
362
+
363
+ ### Isolated worktree runs
364
+
365
+ Use one worktree per independent writing task; keep read-only agents in ordinary panes. `cwd` selects the source Git repository, `branch` must be unique, and `base` is resolved to an exact commit before creation. If `base` is omitted, the source checkout's committed `HEAD` is used. Parent-checkout changes that have not been committed are not copied.
366
+
367
+ The child starts at the returned worktree root. Tell writing agents to test and commit when you want a commit-based handoff, and tell them not to push, merge, switch branches, or remove the worktree. The parent owns review and integration.
368
+
369
+ Successful, failed, and help-requesting runs retain their workspace. Completion includes the worktree path, Herdr workspace, branch, base/head SHAs, commits ahead, changed and untracked files, and clean/dirty/conflicted state. Here, `clean` means no uncommitted files; the branch may still contain commits. If Git inspection fails, state is reported as unknown rather than guessed.
370
+
371
+ An ownership manifest is written under the parent session's `artifacts/<session-id>/worktree-runs/` directory before Herdr creates resources. V1 does not automatically recover watchers after a full process restart, and `subagent_resume` does not reattach the managed worktree lifecycle.
372
+
373
+ The extension does **not** push, create a PR, merge, cherry-pick, or remove the worktree or branch automatically. For task selection, lifecycle states, review commands, failure recovery, and safe cleanup, read [Worktree subagents](docs/worktree-subagents.md). The [research report](docs/research/worktree-subagent-orchestration.md) records the rationale and deferred roadmap.
374
+
375
+ ---
376
+
377
+ ## Interrupting a running subagent
378
+
379
+ Use `subagent_interrupt` to cancel the active turn of a running Pi-backed subagent:
380
+
381
+ ```typescript
382
+ subagent_interrupt({ id: "abcd1234" });
383
+ // or
384
+ subagent_interrupt({ name: "Scout" });
385
+ ```
386
+
387
+ This sends Escape to the child pane, cancelling the in-progress model turn. The subagent session stays alive — the pane, session file, and background polling all remain intact. After the interrupt, the widget immediately labels the child as `interrupted` (counted as **open**, not active processing). Stale pre-interrupt activity snapshots are ignored so a lagging Herdr/`active` reading cannot overwrite the interrupt. The process elapsed timer keeps running because the pane is still open; only the interrupted-state duration freezes relative to the interrupt request. If the child starts work later, newer observations return it to `active`; completion, failure, and `caller_ping` still flow through normally.
388
+
389
+ This is a turn-level interrupt, not a method for forcibly terminating a subagent session.
390
+
391
+ > **Note:** Only Pi-backed subagents are supported. Claude-backed runs will return an error.
392
+
393
+ ---
394
+
395
+ ## Workflow control (`herdr_workflow`)
396
+
397
+ The parent-only `herdr_workflow` tool prepares, starts, and cancels one exact project-local review workflow. Children never receive this tool.
398
+
399
+ ```typescript
400
+ herdr_workflow({ action: "prepare", path: ".pi/plans/run-1/workflow.js" });
401
+ herdr_workflow({ action: "start", runId: "run-1" }); // after APPROVE <hash prefix>
402
+ herdr_workflow({ action: "cancel", runId: "run-1" });
403
+ ```
404
+
405
+ ### Prepare and start contract
406
+
407
+ - The script must be `<project>/.pi/plans/<run>/workflow.js` in a trusted Git repository with no existing adjacent `run.jsonl`.
408
+ - Its first comment contains strict version-1 JSON metadata that binds the exact committed base, source provenance, review roles, authenticated `provider/model` references, thinking levels, and per-run caps that cannot exceed the fixed limits.
409
+ - Fixed workflow caps: 256 KiB source, 8 agents, concurrency 4, 30-minute deadline, 100,000-character prompts, 100 logs × 4,000 characters, and 64 KiB serialized task result. Metadata may only lower caps.
410
+ - Preparation validates and compiles without evaluating JavaScript, creating a journal or checkout, or launching a child. It returns the exact approval packet and keeps one pending candidate in process memory.
411
+ - Start requires the latest real user message in the same parent session to be exactly `APPROVE <8 lowercase hex characters>`. It revalidates the complete candidate, consumes approval once, creates the append-only journal, and runs in the background.
412
+ - Review children are fresh Pi sessions with derived read-only tools in one detached checkout pinned to the approved base. Parent uncommitted files are absent, intermediate child results stay inside the workflow, and operational failures remain explicit non-retryable evidence for parent-guided recovery.
413
+ - Approved workflow JavaScript runs in a restricted `vm` inside a Worker thread. Neither mechanism is a security boundary; run only project code that the user has inspected and approved.
414
+ - Same-process `/reload` keeps workflow ownership and the Worker alive. A full process restart performs interruption reconciliation only: it marks a stale running journal event `interrupted`, retains sessions/journals/checkouts, and does not replay, restart children, clean up, or expose history.
415
+
416
+ ### Cancel contract
417
+
418
+ - Cancel claims a process-global terminal gate. Completion, failure, interruption, and cancellation cannot each produce a terminal outcome.
419
+ - Queued `agent()` calls resolve as cancelled; no later reviewer or synthesizer starts.
420
+ - Active panes are queried through Herdr process-info before close so foreground process identities can be waited on.
421
+ - After synchronous pane close, cancel waits for pane absence and captured process exit before disposing the reader checkout.
422
+ - If process identity cannot be captured for an active pane, the pane remains present after close, or any captured process still lives after the bounded wait, the checkout is retained and the run ends `failed` with `cancel_termination_failed`. Successful cancellation is not reported in that case.
423
+ - A successful cancel writes one `cancelled` terminal journal event and one result-free delivery. Repeated cancel is idempotent and returns the authoritative terminal outcome (including a prior fail-closed result).
424
+
425
+ There is no list, status, resume, or history action in v1. Workflow ownership and the Worker survive `/reload` in the same Pi process, and the latest parent API receives one final delivery. A full process restart reconciles interruption without replay: startup marks only the last known running journal event as `interrupted`, leaves sessions, journals, and reader checkouts in place, and requires a new approved run.
426
+
427
+ ### Bundled `orchestrate` skill
428
+
429
+ The package bundles the native `/skill:orchestrate` procedure. It accepts local paths, URLs, tickets, or combinations that the parent can already access. The parent performs read-only preflight discovery and materializes exact remote or tracker evidence before writing one unique `.pi/plans/<run>/workflow.js` at a committed base. The skill authors distinct fresh read-only reviewers in bounded parallel and one fresh synthesizer; it permits at most one same-role replacement only for an explicit `retryable: true` failure. It does not use public `subagent()` for workflow nodes and does not author writers, commits, external effects, nested workflows, replay, or a fixed task schema.
430
+
431
+ The parent calls `herdr_workflow prepare`, presents its packet unchanged, and waits for the exact `APPROVE <8-character lowercase hash prefix>` reply before calling `start`. After start, one final delivery is sent without polling. Cancellation is fail-closed and retains evidence when process exit cannot be confirmed. Same-process `/reload` preserves ownership; full restart records interruption without replay, restart, cleanup, or history. Workflow JavaScript runs in a Worker-hosted `vm` for event-loop availability only; neither the Worker nor `vm` is a security boundary, and worktrees do not provide process or security isolation.
432
+
433
+ ---
434
+
435
+ ## caller_ping — Child-to-Parent Help Request
436
+
437
+ The `caller_ping` tool lets a Pi-backed subagent request help from its parent agent. When called, the child session **exits** and the parent receives a notification with the help message. The parent can then **resume** the child session with a response using `subagent_resume`.
438
+
439
+ **`caller_ping` parameters:**
440
+
441
+ - `message` (required): What you need help with
442
+
443
+ **`subagent_resume` parameters (Pi-backed sessions):**
444
+
445
+ - `sessionPath` (required): Path to the child session `.jsonl` file
446
+ - `name` (optional): Display name for the resumed pane (defaults to `Resume`)
447
+ - `message` (optional): Follow-up prompt to send after resuming
448
+ - `autoExit` (optional): Whether the resumed session should auto-exit after its next response. Defaults to `true` for autonomous follow-up work; set `false` when resuming for an interactive handoff.
449
+
450
+ **Interaction flow:**
451
+
452
+ 1. Child calls `caller_ping({ message: "Not sure which schema to use" })`
453
+ 2. Child session exits (like `subagent_done`)
454
+ 3. Parent receives a steer notification: *"Sub-agent Worker needs help: Not sure which schema to use"*
455
+ 4. Parent resumes the child session via `subagent_resume` with the response
456
+ 5. Child picks up where it left off with the parent's guidance
457
+
458
+ **Example:**
459
+
460
+ ```typescript
461
+ // Inside a worker subagent
462
+ await caller_ping({
463
+ message: "Found two conflicting migration files — should I use v1 or v2?"
464
+ });
465
+ // Session exits here. Parent receives the ping, then resumes this session
466
+ // with guidance like "Use v2, v1 is deprecated"
467
+ ```
468
+
469
+ > **Note:** `caller_ping` is only available inside Pi-backed subagent contexts. Calling it from a standalone Pi session returns an error. For a worktree child, the help handoff retains the workspace, but `subagent_resume` does not reattach worktree tracking; continue the work in the retained workspace.
470
+
471
+ ---
472
+
473
+ ## The `/plan` Workflow
474
+
475
+ The `/plan` command orchestrates a full planning-to-implementation pipeline.
476
+
477
+ ```
478
+ /plan Add a dark mode toggle to the settings page
479
+ ```
480
+
481
+ ```
482
+ Phase 1: Investigation → Quick codebase scan
483
+ Phase 2: Planning → Interactive planner subagent (user collaborates)
484
+ Phase 3: Review Plan → Confirm ordered tasks, adjust if needed
485
+ Phase 4: Execute → Sequential workers, or isolated parallel workers for independent tasks
486
+ Phase 5: Integrate → Parent reviews and integrates worktree branches one at a time
487
+ Phase 6: Review → Reviewer subagent checks the integrated changes
488
+ ```
489
+
490
+ The parent workspace and tab names stay unchanged. Subagents are created in newly named tabs or panes for each phase.
491
+
492
+ ---
493
+
494
+ ## The `/iterate` Workflow
495
+
496
+ For quick, focused work without polluting the main session's context.
497
+
498
+ ```
499
+ /iterate Fix the off-by-one error in the pagination logic
500
+ ```
501
+
502
+ This always forks the current session into a subagent with full conversation context. It does not inherit an agent default `session-mode`. Make the fix, verify it, and exit to return. The main session gets a summary of what was done.
503
+
504
+ ---
505
+
506
+ ## The `/btw` Workflow
507
+
508
+ Use `/btw` for a quick side question without adding a turn to the main session:
509
+
510
+ ```text
511
+ /btw What did we decide about session cleanup?
512
+ ```
513
+
514
+ The extension snapshots the current active conversation branch, opens a non-focused Herdr tab, and starts an interactive Pi session with the same model and thinking level. The answer stays in that tab and is never delivered as a subagent result. A second `/btw` replaces the previous one; `/btw-close` closes it explicitly.
515
+
516
+ BTW shares the current working directory. It treats inherited work as reference context and modifies the workspace only when the side question explicitly requests it. Cleanup is best effort; if closing fails, the tab remains available for manual recovery.
517
+
518
+ ---
519
+
520
+ ## Custom Agents
521
+
522
+ Custom agent roles are the package's primary extension mechanism. Create one
523
+ when a child needs a reusable, bounded responsibility such as scouting,
524
+ implementation, or review. If the new concept instead describes a multi-stage
525
+ user outcome, make it a workflow, command, or Pi skill that composes roles; do
526
+ not disguise a workflow as an agent definition.
527
+
528
+ ### 1. Choose the scope
529
+
530
+ | Scope | Location | Use when |
531
+ | ----- | -------- | -------- |
532
+ | Project | `.pi/agents/<name>.md` | The role belongs to one repository |
533
+ | Global | `$PI_CODING_AGENT_DIR/agents/<name>.md` | The role should be available everywhere; the default root is `~/.pi/agent` |
534
+ | Role pack | An installed Pi package's registered `roles/` directory | The role should be independently installable and shareable |
535
+ | Bundled | This package's `agents/<name>.md` | Contributing a fallback role maintained with `pi-herdr-agents` |
536
+
537
+ The filename stem is the launch key. `name` frontmatter is optional because it
538
+ defaults to the filename stem. If supplied, keep it identical so overrides remain
539
+ predictable; role packs reject mismatches.
540
+
541
+ ### 2. Create the definition
542
+
543
+ ```markdown
544
+ ---
545
+ description: Reviews a bounded change for concrete security vulnerabilities
546
+ thinking: high
547
+ tools: read, bash
548
+ system-prompt: append
549
+ session-mode: standalone
550
+ spawning: false
551
+ auto-exit: true
552
+ ---
553
+
554
+ # Security Reviewer
555
+
556
+ Review only the requested change. Trace trust boundaries and affected callers.
557
+ Report concrete findings with file and line references, exploit conditions,
558
+ severity, and the smallest safe correction. Do not modify files.
559
+ ```
560
+
561
+ Omit `model` to use `models.agents.<name>`, then `models.default`, then the
562
+ parent model. Put `model` in frontmatter only when the role itself needs a
563
+ specific exact authenticated `provider/model-id`.
564
+
565
+ `tools` is passed to Pi's `--tools` allowlist and may name any registered
566
+ built-in, extension, or custom tool. Listing a tool does not install its
567
+ extension. Likewise, `skills` names must already be discoverable by Pi; this
568
+ package does not install role prerequisites.
569
+
570
+ ### 3. Verify and launch
571
+
572
+ ```text
573
+ /subagent list
574
+ /subagent security-reviewer Review the authentication changes against main
575
+ ```
576
+
577
+ Or call the tool directly:
578
+
579
+ ```typescript
580
+ subagent({
581
+ name: "Security review",
582
+ agent: "security-reviewer",
583
+ task: "Review the authentication changes against main.",
584
+ });
585
+ ```
586
+
587
+ Agent files are read when definitions are listed or launched, so creating or
588
+ editing one normally does not require `/reload`. Installing, removing, updating,
589
+ or changing the extension code of a role pack uses Pi's normal `/reload` flow.
590
+
591
+ ### Publish a role pack
592
+
593
+ A role pack is an ordinary Pi package with Markdown definitions and a tiny
594
+ extension that registers their directory through Pi's public inter-extension
595
+ event bus:
596
+
597
+ ```text
598
+ security-roles/
599
+ ├── package.json
600
+ ├── extension.ts
601
+ └── roles/
602
+ └── security-reviewer.md
603
+ ```
604
+
605
+ ```json
606
+ {
607
+ "name": "@acme/security-roles",
608
+ "version": "1.0.0",
609
+ "keywords": ["pi-package"],
610
+ "type": "module",
611
+ "pi": {
612
+ "extensions": ["./extension.ts"]
613
+ },
614
+ "peerDependencies": {
615
+ "@earendil-works/pi-coding-agent": "*"
616
+ }
617
+ }
618
+ ```
619
+
620
+ ```typescript
621
+ import { fileURLToPath } from "node:url";
622
+
623
+ const roles = fileURLToPath(new URL("./roles", import.meta.url));
624
+
625
+ export default (pi: any) => {
626
+ const unsubscribe = pi.events.on(
627
+ "pi-herdr-subagents:roles:discover:v1", // stable protocol identifier
628
+ (request: { apiVersion: number; register(path: string): void }) => {
629
+ if (request.apiVersion === 1) request.register(roles);
630
+ },
631
+ );
632
+ pi.on("session_shutdown", unsubscribe);
633
+ };
634
+ ```
635
+
636
+ Install both packages through Pi; the role pack remains inert if
637
+ `pi-herdr-agents` is absent:
638
+
639
+ ```bash
640
+ pi install npm:pi-herdr-agents
641
+ pi install npm:@acme/security-roles
642
+ ```
643
+
644
+ Registration is synchronous and accepts one absolute Markdown file or a
645
+ directory whose direct `.md` children are roles. The bridge must unsubscribe on
646
+ `session_shutdown` as shown so removed or updated packages do not survive a
647
+ reload. A copyable package lives in [`examples/role-pack/`](examples/role-pack/).
648
+ The host reads and validates
649
+ the files, derives package name/version from the nearest `package.json`, and
650
+ reports invalid paths, missing descriptions, filename/name mismatches, and
651
+ package-layer collisions in the listing surfaces.
652
+
653
+ Role packs cannot replace bundled roles, and duplicate role names from multiple
654
+ role packs are disabled rather than resolved by extension load order. Use a
655
+ global or project definition for an intentional override.
656
+
657
+ See [ADR-0003](docs/adr/0003-installable-role-packs.md) for the registration seam,
658
+ collision rules, and rejected alternatives.
659
+
660
+ ### Authoring checklist
661
+
662
+ - The role has one bounded responsibility and a clear report or handoff contract.
663
+ - The filename stem is the role name; if `name` is present, it matches the stem.
664
+ - `description` states the role's input/output responsibility.
665
+ - `tools` and `skills` contain only installed, necessary capabilities.
666
+ - Leaf roles set `spawning: false`.
667
+ - Autonomous roles set `auto-exit: true`; interactive roles leave it off.
668
+ - Generic roles omit `model` unless a particular runtime is functionally required.
669
+ - `/subagent list` shows the expected source and a smoke launch succeeds.
670
+
671
+ The current parser is permissive: unsupported or unknown frontmatter may be
672
+ ignored rather than rejected. Compare definitions against the reference below
673
+ and verify them with `/subagent list` plus a smoke launch.
674
+
675
+ ### Frontmatter Reference
676
+
677
+ | Field | Type | Description |
678
+ | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
679
+ | `name` | string | Optional explicit agent name used in `agent: "my-agent"`; defaults to the filename stem and must match it in role packs |
680
+ | `description` | string | Shown in `subagents_list` output |
681
+ | `model` | string | Optional exact authenticated Pi model default; omit to use per-agent config, global config, then the parent |
682
+ | `cli` | string | Set to `claude` to launch the Claude CLI instead of Pi |
683
+ | `cli-model` | string | Optional model name passed to a Claude CLI agent; separate from Pi model routing |
684
+ | `thinking` | string | Optional Pi thinking default (`off` through `max`); omit to inherit the parent. Thinking overrides are not supported for Claude CLI agents |
685
+ | `system-prompt` | string | `append` passes the agent body through Pi's appended system prompt; `replace` replaces Pi's default system prompt. Without this field, the body is included in the task wrapper. Claude CLI agents always append their body/override |
686
+ | `tools` | string | Comma-separated Pi `--tools` allowlist; may contain any registered built-in, extension, or custom tool name |
687
+ | `skills` | string | Comma-separated installed skill names to auto-load. Use this plural form for new definitions; legacy project/global definitions using singular `skill` remain compatible. |
688
+ | `session-mode` | string | Default child-session mode: `standalone`, `lineage-only`, or `fork` |
689
+ | `spawning` | boolean | Set `false` to deny all subagent-spawning tools |
690
+ | `deny-tools` | string | Comma-separated `pi-herdr-agents` tool names to suppress; this is not a universal cross-extension deny list |
691
+ | `auto-exit` | boolean | Auto-shutdown when the agent finishes its turn — no `subagent_done` call needed. If the user sends any input, auto-exit is permanently disabled and the user takes over the session. Recommended for autonomous agents (scout, worker); not for interactive ones (planner). Also determines the default value of `interactive` (see below). |
692
+ | `interactive` | boolean | Override whether stall/recovery transitions wake the parent session. Defaults to the inverse of `auto-exit`: autonomous agents (`auto-exit: true`) are non-interactive and get stall pings; agents without `auto-exit` are interactive and stay quiet. Explicit values take precedence. |
693
+ | `cwd` | string | Default working directory. Absolute paths are unambiguous; relative agent-frontmatter paths resolve from Pi's agent config directory (`PI_CODING_AGENT_DIR` or `~/.pi/agent`), not the project root |
694
+ | `disable-model-invocation` | boolean | Hide an internal adapter from discovery surfaces like `subagents_list`. The definition remains directly invocable by exact name via `subagent({ agent: "name", ... })`. |
695
+
696
+ ---
697
+
698
+ Discovery still resolves precedence before visibility filtering. If a project-local hidden agent has the same name as a visible global or bundled agent, the hidden project agent wins and the lower-precedence agent does not appear in `subagents_list`.
699
+
700
+ ### `session-mode`
701
+
702
+ Choose how a subagent session starts:
703
+
704
+ - `standalone` — default fresh session with no lineage link to the caller
705
+ - `lineage-only` — fresh blank child session with `parentSession` linkage, but no copied turns from the caller
706
+ - `fork` — linked child session seeded with the caller's prior conversation context
707
+
708
+ `lineage-only` is useful when you want session discovery and fork lineage UX to show the relationship later, but you do **not** want the child to inherit the parent's turns.
709
+
710
+ `fork: true` on the tool call always forces the `fork` mode for that specific spawn. `/iterate` uses this explicit override on purpose.
711
+
712
+ ```yaml
713
+ ---
714
+ name: planner
715
+ session-mode: lineage-only
716
+ ---
717
+ ```
718
+
719
+ ### `auto-exit`
720
+
721
+ When set to `true`, the agent session shuts down automatically as soon as the agent finishes its turn — no explicit `subagent_done` call is needed.
722
+
723
+ **Behavior:**
724
+
725
+ - The session closes after the agent's final message (on the `agent_end` event)
726
+ - If the user sends **any input** before the agent finishes, auto-exit is permanently disabled for that session — the user takes over interactively
727
+ - The modeHint injected into the agent's task is adjusted accordingly: autonomous agents see "Complete your task autonomously." rather than instructions to call `subagent_done`
728
+
729
+ **When to use:**
730
+
731
+ - ✅ Autonomous agents (scout, worker, reviewer) that run to completion
732
+ - ❌ Interactive agents (planner, iterate) where the user drives the session
733
+
734
+ ```yaml
735
+ ---
736
+ name: scout
737
+ auto-exit: true
738
+ ---
739
+ ```
740
+
741
+ ### `interactive`
742
+
743
+ Controls whether status transitions (`stalled`, `recovered`) wake the parent session with a steer message.
744
+
745
+ **Default:** the inverse of `auto-exit`. Autonomous agents (`auto-exit: true`) are non-interactive and ping the parent on stall/recovery; named agents without `auto-exit` are interactive and stay quiet. Bare spawns have no agent definition and default to autonomous auto-exit behavior. `/iterate` is interactive because it explicitly passes `interactive: true`.
746
+
747
+ **Why it exists:** Interactive agents can run for minutes or hours while the user thinks, types, and reads in the subagent's pane. Child snapshots still update the widget, but stalled/recovered supervision messages rarely need to wake the parent for user-driven sessions. Skipping the steer keeps the parent quiet until the child actually finishes.
748
+
749
+ **When to override:**
750
+
751
+ - Set `interactive: false` on an agent that doesn't auto-exit but you still want stall pings for
752
+ - Set `interactive: true` on an autonomous agent you'd rather check on yourself
753
+
754
+ ```yaml
755
+ ---
756
+ name: planner
757
+ # interactive defaults to true because auto-exit is not set
758
+ ---
759
+ ```
760
+
761
+ Or per spawn:
762
+
763
+ ```typescript
764
+ subagent({ name: "Scout", agent: "scout", interactive: true, task: "..." });
765
+ ```
766
+
767
+ ---
768
+
769
+ ## Tool Access Control
770
+
771
+ Without a restrictive `tools` allowlist or spawning policy, a sub-agent can spawn further sub-agents. Control this with frontmatter:
772
+
773
+ ### `spawning: false`
774
+
775
+ Denies all subagent lifecycle tools (`subagent`, `subagent_interrupt`, `subagents_list`, `subagent_resume`):
776
+
777
+ ```yaml
778
+ ---
779
+ name: worker
780
+ spawning: false
781
+ ---
782
+ ```
783
+
784
+ ### `deny-tools`
785
+
786
+ Fine-grained control over tools registered by `pi-herdr-agents`:
787
+
788
+ ```yaml
789
+ ---
790
+ name: focused-agent
791
+ deny-tools: subagent
792
+ ---
793
+ ```
794
+
795
+ ### Recommended Configuration
796
+
797
+ | Agent | `spawning` | Rationale |
798
+ | ---------- | ----------- | -------------------------------------------- |
799
+ | planner | *(default)* | Legitimately spawns scouts for investigation |
800
+ | worker | `false` | Should implement tasks, not delegate |
801
+ | reviewer | `false` | Should review, not spawn |
802
+ | scout | `false` | Should gather context, not spawn |
803
+
804
+ ---
805
+
806
+ ## Role Folders
807
+
808
+ The `cwd` parameter lets sub-agents start in a specific directory with its own configuration:
809
+
810
+ ```
811
+ project/
812
+ ├── agents/
813
+ │ ├── game-designer/
814
+ │ │ └── CLAUDE.md ← "You are a game designer..."
815
+ │ ├── sre/
816
+ │ │ ├── CLAUDE.md ← "You are an SRE specialist..."
817
+ │ │ └── .pi/skills/ ← SRE-specific skills
818
+ │ └── narrative/
819
+ │ └── CLAUDE.md ← "You are a narrative designer..."
820
+ ```
821
+
822
+ ```typescript
823
+ subagent({ name: "Game Designer", cwd: "agents/game-designer", task: "Design the combat system" });
824
+ subagent({ name: "SRE", cwd: "agents/sre", task: "Review deployment pipeline" });
825
+ ```
826
+
827
+ Set a default `cwd` in agent frontmatter. Use an absolute path for a project directory; relative frontmatter paths are resolved from Pi's agent config directory:
828
+
829
+ ```yaml
830
+ ---
831
+ name: game-designer
832
+ cwd: /absolute/path/to/project/agents/game-designer
833
+ spawning: false
834
+ ---
835
+ ```
836
+
837
+ ---
838
+
839
+ ## Tools Widget
840
+
841
+ Every sub-agent session displays a compact tools widget showing available and denied tools. Toggle with `Ctrl+J`:
842
+
843
+ ```
844
+ [scout] — 12 tools · 4 denied (Ctrl+J) ← collapsed
845
+ [scout] — 12 available (Ctrl+J to collapse) ← expanded
846
+ read, bash, edit, write, ...
847
+ denied: subagent, subagents_list, ...
848
+ ```
849
+
850
+ ---
851
+
852
+ ## Requirements
853
+
854
+ - [Pi](https://github.com/earendil-works/pi) — the coding agent
855
+ - [herdr](https://herdr.dev) — the required terminal workspace
856
+
857
+ ```bash
858
+ herdr
859
+ pi
860
+ ```
861
+
862
+ Other multiplexers and terminal backends are not supported. Worktrees provide Git checkout isolation only, not process or security isolation; child agents and installed Pi packages run with your user's filesystem and command permissions. Claude CLI children always launch with `--dangerously-skip-permissions` and therefore skip Claude's interactive permission prompts.
863
+
864
+ ---
865
+
866
+ ## Acknowledgements
867
+
868
+ This package builds on earlier open-source work by [HazAT/pi-interactive-subagents](https://github.com/HazAT/pi-interactive-subagents) and [0xRichardH/pi-herdr-subagents](https://github.com/0xRichardH/pi-herdr-subagents). The sub-agent status supervision and turn-only interruption features were inspired by [RepoPrompt](https://repoprompt.com/)'s sub-agent snapshot polling and run cancellation features.
869
+
870
+ ---
871
+
872
+ ## License
873
+
874
+ MIT. Copyright notice retained from the upstream lineage (`HazAT`).