pi-herdr-subagents 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,55 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ concurrency:
13
+ group: npm-publish-${{ github.ref }}
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ publish:
18
+ name: Test and publish
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Check out repository
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Set up Node.js
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: 22
29
+ registry-url: https://registry.npmjs.org
30
+ cache: npm
31
+
32
+ - name: Install dependencies
33
+ run: npm ci
34
+
35
+ - name: Run tests
36
+ run: npm test
37
+
38
+ - name: Verify tag matches package version
39
+ shell: bash
40
+ run: |
41
+ package_version="$(node --input-type=module -e "import pkg from './package.json' with { type: 'json' }; process.stdout.write(pkg.version)")"
42
+ tag_version="${GITHUB_REF_NAME#v}"
43
+
44
+ if [[ "$package_version" != "$tag_version" ]]; then
45
+ echo "Tag version ($tag_version) does not match package.json ($package_version)."
46
+ exit 1
47
+ fi
48
+
49
+ - name: Verify package contents
50
+ run: npm pack --dry-run
51
+
52
+ - name: Publish package
53
+ run: npm publish --access public --provenance
54
+ env:
55
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,8 @@
1
+ {
2
+ "extensions": [
3
+ "../pi-extension/subagents/index.ts"
4
+ ],
5
+ "skills": [
6
+ "./skills/run-integration-tests/SKILL.md"
7
+ ]
8
+ }
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: run-integration-tests
3
+ description: Run the integration test suite and verify all sessions end-to-end. Use when asked to run integration or e2e tests, test before release, or check everything works.
4
+ ---
5
+
6
+ # Run integration tests
7
+
8
+ Run this workflow from inside herdr. This project supports no other terminal backend.
9
+
10
+ ## Preflight
11
+
12
+ ```bash
13
+ echo "HERDR_ENV=$HERDR_ENV"
14
+ command -v herdr
15
+ npm test
16
+ ```
17
+
18
+ Stop and ask the user to start pi inside herdr if `HERDR_ENV` is not `1` or the CLI is missing.
19
+
20
+ ## Integration suite
21
+
22
+ From the repository root:
23
+
24
+ ```bash
25
+ npm run test:integration
26
+ ```
27
+
28
+ The harness loads the extension directly from the working tree and creates isolated test agents. Report passing, failing, and skipped tests. Do not claim full verification when herdr-dependent tests were skipped.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HazAT
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,483 @@
1
+ # pi-herdr-subagents
2
+
3
+ Async subagents for [pi](https://github.com/badlogic/pi-mono) 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
+ https://github.com/user-attachments/assets/30adb156-cfb4-4c47-84ca-dd4aa80cba9f
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 running agents with their current state — `starting`, `active`, `waiting`, `stalled`, or `running`. 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 ──────────────────────────── 2 running ─╮
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
+ ## Install
27
+
28
+ Install the package explicitly from this repository (replace the URL if you use a fork):
29
+
30
+ ```bash
31
+ pi install git:github.com/0xRichardH/pi-herdr-subagents
32
+ ```
33
+
34
+ This project does not install or load `HazAT/pi-interactive-subagents` automatically.
35
+
36
+ For maintainers publishing a release to npm, see [RELEASING.md](RELEASING.md).
37
+
38
+ Start herdr, then run pi inside it:
39
+
40
+ ```bash
41
+ herdr
42
+ pi
43
+ ```
44
+
45
+ herdr is the only supported terminal environment. The extension requires `HERDR_ENV=1` and the `herdr` CLI to be available.
46
+
47
+ 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`):
48
+
49
+ ```bash
50
+ export PI_SUBAGENT_SHELL_READY_DELAY_MS=2500
51
+ ```
52
+
53
+ Subagent tabs and panes 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.
54
+
55
+ ## What's Included
56
+
57
+ ### Extensions
58
+
59
+ **Subagents** — 4 main-session tools + 3 commands, plus 1 subagent-only tool:
60
+
61
+ | Tool | Description |
62
+ | -------------------- | ------------------------------------------------------------------------------------------- |
63
+ | `subagent` | Spawn a sub-agent in a dedicated herdr pane (async — returns immediately) |
64
+ | `subagent_interrupt` | Interrupt a running Pi-backed subagent's current turn |
65
+ | `subagents_list` | List available agent definitions |
66
+ | `subagent_resume` | Resume a previous sub-agent session (async) |
67
+
68
+ | Command | Description |
69
+ | -------------------------- | ------------------------------------ |
70
+ | `/plan` | Start a full planning workflow |
71
+ | `/iterate` | Fork into a subagent for quick fixes |
72
+ | `/subagent <agent> <task>` | Spawn a named agent directly |
73
+
74
+ ### Bundled Agents
75
+
76
+ | Agent | Model | Role |
77
+ | ----------------- | ---------------------- | ---------------------------------------------------------------------------------------- |
78
+ | **planner** | Opus (medium thinking) | Brainstorming — clarifies requirements, explores approaches, writes plans, creates todos |
79
+ | **scout** | Haiku | Fast codebase reconnaissance — maps files, patterns, conventions |
80
+ | **worker** | Sonnet | Implements tasks from todos — writes code, runs tests, makes polished commits |
81
+ | **reviewer** | Opus (medium thinking) | Reviews code for bugs, security issues, correctness |
82
+ | **visual-tester** | Sonnet | Visual QA via Chrome CDP — screenshots, responsive testing, interaction testing |
83
+
84
+ Agent discovery follows priority: **project-local** (`.pi/agents/`) > **global** (`~/.pi/agent/agents/`) > **package-bundled**. Override any bundled agent by placing your own version in the higher-priority location.
85
+
86
+ ---
87
+
88
+ ## Async Subagent Flow
89
+
90
+ ```
91
+ 1. Agent calls subagent() → returns immediately ("started")
92
+ 2. Sub-agent runs in herdr pane → widget shows live status
93
+ 3. User keeps chatting → main session fully interactive
94
+ 4. Sub-agent finishes → result steered back as a normal completion/failure
95
+ 5. Main agent processes result → continues with new context
96
+ ```
97
+
98
+ Multiple subagents run concurrently — each steers its result back independently as it finishes. The live widget above the input tracks all running agents:
99
+
100
+ ```
101
+ ╭─ Subagents ───────────────────────────────── 3 running ─╮
102
+ │ 01:23 Scout: Auth (scout) active · write 7m │
103
+ │ 00:45 Researcher (researcher) stalled 4m │
104
+ │ 00:12 Scout: DB (scout) starting… │
105
+ ╰─────────────────────────────────────────────────────────╯
106
+ ```
107
+
108
+ Completion messages render with a colored background and are expandable with `Ctrl+O` to show the full summary and session file path.
109
+
110
+ ### In-progress status updates
111
+
112
+ The widget tracks each Pi-backed sub-agent from a child-written runtime snapshot and labels it with a coarse state:
113
+
114
+ - `starting` — launched, but no valid child snapshot has been observed yet
115
+ - `active` — the child is doing observed runtime work: agent turn, provider request, streaming, or tool execution
116
+ - `waiting` — the child finished a turn and is intentionally open for more input or another stage
117
+ - `stalled` — the parent has gone too long without a valid current child snapshot and can no longer trust the run is healthy
118
+ - `running` — fallback for backends without child snapshots (e.g. Claude)
119
+
120
+ These labels are no longer derived from session-file growth. Session JSONL is still used for transcript, resume, lineage, and result extraction, but Pi-backed liveness now comes from a small activity snapshot written by the child extension. A fixed internal watchdog marks a run as `stalled` when valid snapshots never appear, stop being readable, or stop matching the current child; 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.
121
+
122
+ **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 child 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.
123
+
124
+ #### Configuration
125
+
126
+ Status display is controlled by `config.json` in the extension directory. Copy `config.json.example` to get started:
127
+
128
+ ```bash
129
+ cp config.json.example config.json
130
+ ```
131
+
132
+ ```json
133
+ {
134
+ "status": {
135
+ "enabled": true
136
+ }
137
+ }
138
+ ```
139
+
140
+ `config.json` is gitignored so local overrides don't get committed.
141
+
142
+ ---
143
+
144
+ ## Spawning Subagents
145
+
146
+ ```typescript
147
+ // Named agent with defaults from agent definition
148
+ subagent({ name: "Scout", agent: "scout", task: "Analyze the codebase..." });
149
+
150
+ // Force a full-context fork for this spawn
151
+ subagent({ name: "Iterate", fork: true, task: "Fix the bug where..." });
152
+
153
+ // Agent defaults can choose a different session-mode via frontmatter
154
+ subagent({ name: "Planner", agent: "planner", task: "Work through the design with me" });
155
+
156
+ // Custom working directory
157
+ subagent({ name: "Designer", agent: "game-designer", cwd: "agents/game-designer", task: "..." });
158
+ ```
159
+
160
+ ### Parameters
161
+
162
+ | Parameter | Type | Default | Description |
163
+ | ---------------------- | ------- | -------------- | ------------------------------------------------------------------------------------------------- |
164
+ | `name` | string | required | Display name (shown in widget and pane title) |
165
+ | `task` | string | required | Task prompt for the sub-agent |
166
+ | `agent` | string | — | Load defaults from agent definition |
167
+ | `fork` | boolean | `false` | Force the full-context fork mode for this spawn, overriding any agent `session-mode` frontmatter |
168
+ | `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`. |
169
+ | `model` | string | — | Override agent's default model |
170
+ | `systemPrompt` | string | — | Append to system prompt |
171
+ | `skills` | string | — | Comma-separated skill names |
172
+ | `tools` | string | — | Comma-separated tool names |
173
+ | `cwd` | string | — | Working directory for the sub-agent (see [Role Folders](#role-folders)) |
174
+
175
+ ---
176
+
177
+ ## Interrupting a running subagent
178
+
179
+ Use `subagent_interrupt` to cancel the active turn of a running Pi-backed subagent:
180
+
181
+ ```typescript
182
+ subagent_interrupt({ id: "abcd1234" });
183
+ // or
184
+ subagent_interrupt({ name: "Scout" });
185
+ ```
186
+
187
+ 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 moves the child back to `waiting`, and stale pre-interrupt snapshots are ignored. If the child starts work later, newer snapshots return it to `active`; completion, failure, and `caller_ping` still flow through normally.
188
+
189
+ This is a turn-level interrupt, not a method for forcibly terminating a subagent session.
190
+
191
+ > **Note:** Only Pi-backed subagents are supported. Claude-backed runs will return an error.
192
+
193
+ ---
194
+
195
+ ## caller_ping — Child-to-Parent Help Request
196
+
197
+ The `caller_ping` tool lets a 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`.
198
+
199
+ **`caller_ping` parameters:**
200
+ - `message` (required): What you need help with
201
+
202
+ **`subagent_resume` parameters:**
203
+ - `sessionPath` (required): Path to the child session `.jsonl` file
204
+ - `name` (optional): Display name for the resumed pane (defaults to `Resume`)
205
+ - `message` (optional): Follow-up prompt to send after resuming
206
+ - `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.
207
+
208
+ **Interaction flow:**
209
+ 1. Child calls `caller_ping({ message: "Not sure which schema to use" })`
210
+ 2. Child session exits (like `subagent_done`)
211
+ 3. Parent receives a steer notification: *"Sub-agent Worker needs help: Not sure which schema to use"*
212
+ 4. Parent resumes the child session via `subagent_resume` with the response
213
+ 5. Child picks up where it left off with the parent's guidance
214
+
215
+ **Example:**
216
+ ```typescript
217
+ // Inside a worker subagent
218
+ await caller_ping({
219
+ message: "Found two conflicting migration files — should I use v1 or v2?"
220
+ });
221
+ // Session exits here. Parent receives the ping, then resumes this session
222
+ // with guidance like "Use v2, v1 is deprecated"
223
+ ```
224
+
225
+ > **Note:** `caller_ping` is only available inside subagent contexts. Calling it from a standalone pi session returns an error.
226
+
227
+ ---
228
+
229
+ ## The `/plan` Workflow
230
+
231
+ The `/plan` command orchestrates a full planning-to-implementation pipeline.
232
+
233
+ ```
234
+ /plan Add a dark mode toggle to the settings page
235
+ ```
236
+
237
+ ```
238
+ Phase 1: Investigation → Quick codebase scan
239
+ Phase 2: Planning → Interactive planner subagent (user collaborates)
240
+ Phase 3: Review Plan → Confirm todos, adjust if needed
241
+ Phase 4: Execute → Scout + sequential workers implement todos
242
+ Phase 5: Review → Reviewer subagent checks all changes
243
+ ```
244
+
245
+ Tab/window titles update to show current phase:
246
+
247
+ ```
248
+ 🔍 Investigating: dark mode → 💬 Planning: dark mode
249
+ → 🔨 Executing: 1/3 → 🔎 Reviewing → ✅ Done
250
+ ```
251
+
252
+ ---
253
+
254
+ ## The `/iterate` Workflow
255
+
256
+ For quick, focused work without polluting the main session's context.
257
+
258
+ ```
259
+ /iterate Fix the off-by-one error in the pagination logic
260
+ ```
261
+
262
+ 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.
263
+
264
+ ---
265
+
266
+ ## Custom Agents
267
+
268
+ Place a `.md` file in `.pi/agents/` (project) or `~/.pi/agent/agents/` (global):
269
+
270
+ ```markdown
271
+ ---
272
+ name: my-agent
273
+ description: Does something specific
274
+ model: anthropic/claude-sonnet-4-6
275
+ thinking: minimal
276
+ tools: read, bash, edit, write
277
+ session-mode: lineage-only
278
+ spawning: false
279
+ ---
280
+
281
+ # My Agent
282
+
283
+ You are a specialized agent that does X...
284
+ ```
285
+
286
+ ### Frontmatter Reference
287
+
288
+ | Field | Type | Description |
289
+ | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
290
+ | `name` | string | Agent name (used in `agent: "my-agent"`) |
291
+ | `description` | string | Shown in `subagents_list` output |
292
+ | `model` | string | Default model (e.g. `anthropic/claude-sonnet-4-6`) |
293
+ | `thinking` | string | Thinking level: `minimal`, `medium`, `high` |
294
+ | `tools` | string | Comma-separated **native pi tools only**: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls` |
295
+ | `skills` | string | Comma-separated skill names to auto-load |
296
+ | `session-mode` | string | Default child-session mode: `standalone`, `lineage-only`, or `fork` |
297
+ | `spawning` | boolean | Set `false` to deny all subagent-spawning tools |
298
+ | `deny-tools` | string | Comma-separated extension tool names to deny |
299
+ | `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). |
300
+ | `interactive` | boolean | derived | 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. |
301
+ | `cwd` | string | Default working directory (absolute or relative to project root) |
302
+ | `disable-model-invocation` | boolean | Hide this agent from discovery surfaces like `subagents_list`. The agent still remains directly invokable by explicit name via `subagent({ agent: "name", ... })`. |
303
+
304
+ ---
305
+
306
+ 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`.
307
+
308
+ ### `session-mode`
309
+
310
+ Choose how a subagent session starts:
311
+
312
+ - `standalone` — default fresh session with no lineage link to the caller
313
+ - `lineage-only` — fresh blank child session with `parentSession` linkage, but no copied turns from the caller
314
+ - `fork` — linked child session seeded with the caller's prior conversation context
315
+
316
+ `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.
317
+
318
+ `fork: true` on the tool call always forces the `fork` mode for that specific spawn. `/iterate` uses this explicit override on purpose.
319
+
320
+ ```yaml
321
+ ---
322
+ name: planner
323
+ session-mode: lineage-only
324
+ ---
325
+ ```
326
+
327
+ ### `auto-exit`
328
+
329
+ 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.
330
+
331
+ **Behavior:**
332
+
333
+ - The session closes after the agent's final message (on the `agent_end` event)
334
+ - If the user sends **any input** before the agent finishes, auto-exit is permanently disabled for that session — the user takes over interactively
335
+ - 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`
336
+
337
+ **When to use:**
338
+
339
+ - ✅ Autonomous agents (scout, worker, reviewer) that run to completion
340
+ - ❌ Interactive agents (planner, iterate) where the user drives the session
341
+
342
+ ```yaml
343
+ ---
344
+ name: scout
345
+ auto-exit: true
346
+ ---
347
+ ```
348
+
349
+ ### `interactive`
350
+
351
+ Controls whether status transitions (`stalled`, `recovered`) wake the parent session with a steer message.
352
+
353
+ **Default:** the inverse of `auto-exit`. Autonomous agents (`auto-exit: true`) are non-interactive and ping the parent on stall/recovery; agents without `auto-exit` are interactive and stay quiet. Bare spawns with no agent defs (e.g. `/iterate` with `fork: true`) are treated as interactive.
354
+
355
+ **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.
356
+
357
+ **When to override:**
358
+
359
+ - Set `interactive: false` on an agent that doesn't auto-exit but you still want stall pings for
360
+ - Set `interactive: true` on an autonomous agent you'd rather check on yourself
361
+
362
+ ```yaml
363
+ ---
364
+ name: planner
365
+ # interactive defaults to true because auto-exit is not set
366
+ ---
367
+ ```
368
+
369
+ Or per spawn:
370
+
371
+ ```typescript
372
+ subagent({ name: "Scout", agent: "scout", interactive: true, task: "..." });
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Tool Access Control
378
+
379
+ By default, every sub-agent can spawn further sub-agents. Control this with frontmatter:
380
+
381
+ ### `spawning: false`
382
+
383
+ Denies all subagent lifecycle tools (`subagent`, `subagent_interrupt`, `subagents_list`, `subagent_resume`):
384
+
385
+ ```yaml
386
+ ---
387
+ name: worker
388
+ spawning: false
389
+ ---
390
+ ```
391
+
392
+ ### `deny-tools`
393
+
394
+ Fine-grained control over individual extension tools:
395
+
396
+ ```yaml
397
+ ---
398
+ name: focused-agent
399
+ deny-tools: subagent
400
+ ---
401
+ ```
402
+
403
+ ### Recommended Configuration
404
+
405
+ | Agent | `spawning` | Rationale |
406
+ | ---------- | ----------- | -------------------------------------------- |
407
+ | planner | _(default)_ | Legitimately spawns scouts for investigation |
408
+ | worker | `false` | Should implement tasks, not delegate |
409
+ | researcher | `false` | Should research, not spawn |
410
+ | reviewer | `false` | Should review, not spawn |
411
+ | scout | `false` | Should gather context, not spawn |
412
+
413
+ ---
414
+
415
+ ## Role Folders
416
+
417
+ The `cwd` parameter lets sub-agents start in a specific directory with its own configuration:
418
+
419
+ ```
420
+ project/
421
+ ├── agents/
422
+ │ ├── game-designer/
423
+ │ │ └── CLAUDE.md ← "You are a game designer..."
424
+ │ ├── sre/
425
+ │ │ ├── CLAUDE.md ← "You are an SRE specialist..."
426
+ │ │ └── .pi/skills/ ← SRE-specific skills
427
+ │ └── narrative/
428
+ │ └── CLAUDE.md ← "You are a narrative designer..."
429
+ ```
430
+
431
+ ```typescript
432
+ subagent({ name: "Game Designer", cwd: "agents/game-designer", task: "Design the combat system" });
433
+ subagent({ name: "SRE", cwd: "agents/sre", task: "Review deployment pipeline" });
434
+ ```
435
+
436
+ Set a default `cwd` in agent frontmatter:
437
+
438
+ ```yaml
439
+ ---
440
+ name: game-designer
441
+ cwd: ./agents/game-designer
442
+ spawning: false
443
+ ---
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Tools Widget
449
+
450
+ Every sub-agent session displays a compact tools widget showing available and denied tools. Toggle with `Ctrl+J`:
451
+
452
+ ```
453
+ [scout] — 12 tools · 4 denied (Ctrl+J) ← collapsed
454
+ [scout] — 12 available (Ctrl+J to collapse) ← expanded
455
+ read, bash, edit, write, todo, ...
456
+ denied: subagent, subagents_list, ...
457
+ ```
458
+
459
+ ---
460
+
461
+ ## Requirements
462
+
463
+ - [pi](https://github.com/badlogic/pi-mono) — the coding agent
464
+ - [herdr](https://herdr.dev) — the required terminal workspace
465
+
466
+ ```bash
467
+ herdr
468
+ pi
469
+ ```
470
+
471
+ Other multiplexers and terminal backends are not supported.
472
+
473
+ ---
474
+
475
+ ## Acknowledgements
476
+
477
+ 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.
478
+
479
+ ---
480
+
481
+ ## License
482
+
483
+ MIT