@gotgenes/pi-subagents 5.0.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,47 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [5.2.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v5.1.0...pi-subagents-v5.2.0) (2026-05-19)
9
+
10
+
11
+ ### Features
12
+
13
+ * add SubagentRuntime interface and factory ([b316c12](https://github.com/gotgenes/pi-packages/commit/b316c1222cecf34d1149fa2a847a1c11883164c1))
14
+ * thread defaultMaxTurns and graceTurns through RunOptions ([db9f1ac](https://github.com/gotgenes/pi-packages/commit/db9f1ac7c47b7b42559ddf659f86c02f78a82d23))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * remove pi-subagents/README.md from rumdl exclude and fix 131 lint issues ([50f334c](https://github.com/gotgenes/pi-packages/commit/50f334c83edf08ee2cb413b1e6520f6c5a26cd41))
20
+
21
+
22
+ ### Documentation
23
+
24
+ * enforce one-sentence-per-line across all markdown files ([a533869](https://github.com/gotgenes/pi-packages/commit/a533869e09ea33a2da8c4ac022d9be4674be4b18))
25
+ * one sentence per line throughout architecture.md; add Issue-prefix and sentence rules to markdown-conventions ([f274ea8](https://github.com/gotgenes/pi-packages/commit/f274ea8003e23c3ad37516422d052f7c815da638))
26
+ * **pi-subagents:** add structural refactoring roadmap with issue sequencing ([a820538](https://github.com/gotgenes/pi-packages/commit/a8205382624acbd26721594630d25976373fc617))
27
+ * plan SubagentRuntime to eliminate module-scope mutable state ([#69](https://github.com/gotgenes/pi-packages/issues/69)) ([fa5eee4](https://github.com/gotgenes/pi-packages/commit/fa5eee4434724fd47dc384092787b50ea9859f4d))
28
+ * **retro:** add follow-up retro notes for issue [#57](https://github.com/gotgenes/pi-packages/issues/57) ([629e11f](https://github.com/gotgenes/pi-packages/commit/629e11f2eaed1294fa756ad3e54fe692428e1c0e))
29
+ * **retro:** add retro notes for issue [#57](https://github.com/gotgenes/pi-packages/issues/57) ([1701841](https://github.com/gotgenes/pi-packages/commit/1701841f387b3418286f670ae0eb10613b5f2b4b))
30
+
31
+ ## [5.1.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v5.0.0...pi-subagents-v5.1.0) (2026-05-19)
32
+
33
+
34
+ ### Features
35
+
36
+ * add debugLog utility gated on PI_SUBAGENTS_DEBUG ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([2b8874a](https://github.com/gotgenes/pi-packages/commit/2b8874aeaa28bc09550dd0f8977b7b57d996b254))
37
+ * thread debugLog into agent-manager and notification catch blocks ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([07943a3](https://github.com/gotgenes/pi-packages/commit/07943a341fbe0a0a35f25af3f4b15bc28cdee7a2))
38
+ * thread debugLog into custom-agents and memory catch blocks ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([e239925](https://github.com/gotgenes/pi-packages/commit/e2399253410dc644b38269b52de6e6a4bfa75d3a))
39
+ * thread debugLog into env catch blocks ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([f5ff82f](https://github.com/gotgenes/pi-packages/commit/f5ff82f0c06be3c1dfe5d5ec0ff3621105b55ad0))
40
+ * thread debugLog into output-file catch block ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([a72b11b](https://github.com/gotgenes/pi-packages/commit/a72b11bc1f36bf256f520b9f13e546295fc6cb64))
41
+ * thread debugLog into skill-loader catch block ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([b57231c](https://github.com/gotgenes/pi-packages/commit/b57231cc5de56a834c34f9e171b909d03939505c))
42
+ * thread debugLog into worktree catch blocks ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([049f489](https://github.com/gotgenes/pi-packages/commit/049f4891ab5b09c9d1a301f7d8af797cb165cb4c))
43
+
44
+
45
+ ### Documentation
46
+
47
+ * plan structured debug logging for silenced catch blocks ([#57](https://github.com/gotgenes/pi-packages/issues/57)) ([28e403e](https://github.com/gotgenes/pi-packages/commit/28e403ea2605405da1a57871af946ee2971ee289))
48
+
8
49
  ## [5.0.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v4.1.1...pi-subagents-v5.0.0) (2026-05-19)
9
50
 
10
51
 
package/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  # @gotgenes/pi-subagents
2
2
 
3
- A [pi](https://pi.dev) extension that brings **Claude Code-style autonomous sub-agents** to pi. Spawn specialized agents that run in isolated sessions — each with its own tools, system prompt, model, and thinking level. Run them in foreground or background, steer them mid-run, resume completed sessions, and define your own custom agent types.
3
+ A [pi](https://pi.dev) extension that brings **Claude Code-style autonomous sub-agents** to pi.
4
+ Spawn specialized agents that run in isolated sessions — each with its own tools, system prompt, model, and thinking level.
5
+ Run them in foreground or background, steer them mid-run, resume completed sessions, and define your own custom agent types.
4
6
 
5
7
  > **Fork notice:** This package is a friendly fork of [`tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents), published to npm as `@gotgenes/pi-subagents`.
6
8
  > It carries a small number of patches on top of upstream — peer-dep migration to `@earendil-works/pi-*`, a post-`bindExtensions` active-tool re-filter, and an `<active_agent>` system-prompt tag for permission resolution.
7
9
  > See [Deviations from upstream](#deviations-from-upstream) at the bottom of this README for details.
8
-
10
+ >
9
11
  > **Status:** Early release.
10
12
 
11
13
  <img width="600" alt="pi-subagents screenshot" src="https://github.com/gotgenes/pi-subagents/raw/main/media/screenshot.png" />
12
14
 
13
-
14
- https://github.com/user-attachments/assets/8685261b-9338-4fea-8dfe-1c590d5df543
15
-
15
+ <https://github.com/user-attachments/assets/8685261b-9338-4fea-8dfe-1c590d5df543>
16
16
 
17
17
  ## Features
18
18
 
@@ -24,17 +24,18 @@ https://github.com/user-attachments/assets/8685261b-9338-4fea-8dfe-1c590d5df543
24
24
  - **Mid-run steering** — inject messages into running agents to redirect their work without restarting
25
25
  - **Session resume** — pick up where an agent left off, preserving full conversation context
26
26
  - **Graceful turn limits** — agents get a "wrap up" warning before hard abort, producing clean partial results instead of cut-off output
27
- - **Case-insensitive agent types** — `"explore"`, `"Explore"`, `"EXPLORE"` all work. Unknown types fall back to general-purpose with a note
27
+ - **Case-insensitive agent types** — `"explore"`, `"Explore"`, `"EXPLORE"` all work.
28
+ Unknown types fall back to general-purpose with a note
28
29
  - **Fuzzy model selection** — specify models by name (`"haiku"`, `"sonnet"`) instead of full IDs, with automatic filtering to only available/configured models
29
30
  - **Context inheritance** — optionally fork the parent conversation into a sub-agent so it knows what's been discussed
30
31
  - **Persistent agent memory** — three scopes (project, local, user) with automatic read-only fallback for agents without write tools
31
32
  - **Git worktree isolation** — run agents in isolated repo copies; changes auto-committed to branches on completion
32
33
  - **Skill preloading** — inject named skills into agent system prompts, discovered from `.pi/skills/`, `.agents/skills/`, and global locations (Pi-standard `<name>/SKILL.md` directory layout supported)
33
34
  - **Tool denylist** — block specific tools via `disallowed_tools` frontmatter
34
- - **Styled completion notifications** — background agent results render as themed, compact notification boxes (icon, stats, result preview) instead of raw XML. Expandable to show full output
35
+ - **Styled completion notifications** — background agent results render as themed, compact notification boxes (icon, stats, result preview) instead of raw XML.
36
+ Expandable to show full output
35
37
  - **Event bus** — lifecycle events (`subagents:created`, `started`, `completed`, `failed`, `steered`, `compacted`) emitted via `pi.events`, enabling other extensions to react to sub-agent activity
36
38
 
37
-
38
39
  ## Install
39
40
 
40
41
  ```bash
@@ -51,7 +52,7 @@ pi -e ./src/index.ts
51
52
 
52
53
  The parent agent spawns sub-agents using the `Agent` tool:
53
54
 
54
- ```
55
+ ```text
55
56
  Agent({
56
57
  subagent_type: "Explore",
57
58
  prompt: "Find all files that handle authentication",
@@ -60,13 +61,14 @@ Agent({
60
61
  })
61
62
  ```
62
63
 
63
- Foreground agents block until complete and return results inline. Background agents return an ID immediately and notify you on completion.
64
+ Foreground agents block until complete and return results inline.
65
+ Background agents return an ID immediately and notify you on completion.
64
66
 
65
67
  ## UI
66
68
 
67
69
  The extension renders a persistent widget above the editor showing all active agents:
68
70
 
69
- ```
71
+ ```text
70
72
  ● Agents
71
73
  ├─ ⠹ Agent Refactor auth module · ⟳5≤30 · 5 tool uses · 33.8k token (62%) · 12.3s
72
74
  │ ⎿ editing 2 files…
@@ -78,25 +80,28 @@ The extension renders a persistent widget above the editor showing all active ag
78
80
  ```
79
81
 
80
82
  The token field is annotated with two optional signals inside parens:
81
- - **`NN%`** — context-window utilization (color-coded: <70% dim, 70–85% warning, ≥85% error). Omitted when the model has no declared `contextWindow`, or briefly right after compaction.
82
- - **`↻N`**number of times the session has compacted, when > 0. Stays dim; the percent's color carries urgency.
83
+
84
+ - **`NN%`**context-window utilization (color-coded: <70% dim, 70–85% warning, ≥85% error).
85
+ Omitted when the model has no declared `contextWindow`, or briefly right after compaction.
86
+ - **`↻N`** — number of times the session has compacted, when > 0.
87
+ Stays dim; the percent's color carries urgency.
83
88
 
84
89
  Individual agent results render Claude Code-style in the conversation:
85
90
 
86
- | State | Example |
87
- |-------|---------|
88
- | **Running** | `⠹ ⟳3≤30 · 3 tool uses · 12.4k token (8%)` / `⎿ searching, reading 3 files…` |
89
- | **Completed** | `✓ ⟳8 · 5 tool uses · 33.8k token (62%) · 12.3s` / `⎿ Done` |
91
+ | State | Example |
92
+ | -------------- | ---------------------------------------------------------------------------------------- |
93
+ | **Running** | `⠹ ⟳3≤30 · 3 tool uses · 12.4k token (8%)` / `⎿ searching, reading 3 files…` |
94
+ | **Completed** | `✓ ⟳8 · 5 tool uses · 33.8k token (62%) · 12.3s` / `⎿ Done` |
90
95
  | **Wrapped up** | `✓ ⟳50≤50 · 50 tool uses · 89.1k token (84% · ↻2) · 45.2s` / `⎿ Wrapped up (turn limit)` |
91
- | **Stopped** | `■ ⟳3 · 3 tool uses · 12.4k token (8%)` / `⎿ Stopped` |
92
- | **Error** | `✗ ⟳3 · 3 tool uses · 12.4k token (8%)` / `⎿ Error: timeout` |
93
- | **Aborted** | `✗ ⟳55≤50 · 55 tool uses · 102.3k token (95% · ↻3)` / `⎿ Aborted (max turns exceeded)` |
96
+ | **Stopped** | `■ ⟳3 · 3 tool uses · 12.4k token (8%)` / `⎿ Stopped` |
97
+ | **Error** | `✗ ⟳3 · 3 tool uses · 12.4k token (8%)` / `⎿ Error: timeout` |
98
+ | **Aborted** | `✗ ⟳55≤50 · 55 tool uses · 102.3k token (95% · ↻3)` / `⎿ Aborted (max turns exceeded)` |
94
99
 
95
100
  Completed results can be expanded (ctrl+o in pi) to show the full agent output inline.
96
101
 
97
102
  Background agent completion notifications render as styled boxes:
98
103
 
99
- ```
104
+ ```text
100
105
  ✓ Find auth files completed
101
106
  ⟳3 · 3 tool uses · 12.4k token · 4.1s
102
107
  ⎿ Found 5 files related to authentication...
@@ -107,28 +112,32 @@ The LLM receives structured `<task-notification>` XML for parsing, while the use
107
112
 
108
113
  ## Default Agent Types
109
114
 
110
- | Type | Tools | Model | Prompt Mode | Description |
111
- |------|-------|-------|-------------|-------------|
112
- | `general-purpose` | all 7 | inherit | `append` (parent twin) | Inherits the parent's full system prompt — same rules, CLAUDE.md, project conventions |
113
- | `Explore` | read, bash, grep, find, ls | haiku (falls back to inherit) | `replace` (standalone) | Fast codebase exploration (read-only) |
114
- | `Plan` | read, bash, grep, find, ls | inherit | `replace` (standalone) | Software architect for implementation planning (read-only) |
115
+ | Type | Tools | Model | Prompt Mode | Description |
116
+ | ----------------- | -------------------------- | ----------------------------- | ---------------------- | ------------------------------------------------------------------------------------- |
117
+ | `general-purpose` | all 7 | inherit | `append` (parent twin) | Inherits the parent's full system prompt — same rules, CLAUDE.md, project conventions |
118
+ | `Explore` | read, bash, grep, find, ls | haiku (falls back to inherit) | `replace` (standalone) | Fast codebase exploration (read-only) |
119
+ | `Plan` | read, bash, grep, find, ls | inherit | `replace` (standalone) | Software architect for implementation planning (read-only) |
115
120
 
116
- The `general-purpose` agent is a **parent twin** — it receives the parent's entire system prompt plus a sub-agent context bridge, so it follows the same rules the parent does. Explore and Plan use standalone prompts tailored to their read-only roles.
121
+ The `general-purpose` agent is a **parent twin** — it receives the parent's entire system prompt plus a sub-agent context bridge, so it follows the same rules the parent does.
122
+ Explore and Plan use standalone prompts tailored to their read-only roles.
117
123
 
118
124
  Default agents can be **ejected** (`/agents` → select agent → Eject) to export them as `.md` files for customization, **overridden** by creating a `.md` file with the same name (e.g. `.pi/agents/general-purpose.md`), or **disabled** per-project with `enabled: false` frontmatter.
119
125
 
120
126
  ## Custom Agents
121
127
 
122
- Define custom agent types by creating `.md` files. The filename becomes the agent type name. Any name is allowed — using a default agent's name overrides it.
128
+ Define custom agent types by creating `.md` files.
129
+ The filename becomes the agent type name.
130
+ Any name is allowed — using a default agent's name overrides it.
123
131
 
124
132
  Agents are discovered from two locations (higher priority wins):
125
133
 
126
- | Priority | Location | Scope |
127
- |----------|----------|-------|
128
- | 1 (highest) | `.pi/agents/<name>.md` | Project — per-repo agents |
129
- | 2 | `$PI_CODING_AGENT_DIR/agents/<name>.md` (default `~/.pi/agent/agents/<name>.md`) | Global — available everywhere |
134
+ | Priority | Location | Scope |
135
+ | ----------- | -------------------------------------------------------------------------------- | ----------------------------- |
136
+ | 1 (highest) | `.pi/agents/<name>.md` | Project — per-repo agents |
137
+ | 2 | `$PI_CODING_AGENT_DIR/agents/<name>.md` (default `~/.pi/agent/agents/<name>.md`) | Global — available everywhere |
130
138
 
131
- Project-level agents override global ones with the same name, so you can customize a global agent for a specific project. The global location follows the upstream `PI_CODING_AGENT_DIR` env var — set it to relocate all pi-coding-agent state (agents, skills, settings) to a custom directory.
139
+ Project-level agents override global ones with the same name, so you can customize a global agent for a specific project.
140
+ The global location follows the upstream `PI_CODING_AGENT_DIR` env var — set it to relocate all pi-coding-agent state (agents, skills, settings) to a custom directory.
132
141
 
133
142
  ### Example: `.pi/agents/auditor.md`
134
143
 
@@ -141,7 +150,9 @@ thinking: high
141
150
  max_turns: 30
142
151
  ---
143
152
 
144
- You are a security auditor. Review code for vulnerabilities including:
153
+ You are a security auditor.
154
+ Review code for vulnerabilities including:
155
+
145
156
  - Injection flaws (SQL, command, XSS)
146
157
  - Authentication and authorization issues
147
158
  - Sensitive data exposure
@@ -152,7 +163,7 @@ Report findings with file paths, line numbers, severity, and remediation advice.
152
163
 
153
164
  Then spawn it like any built-in type:
154
165
 
155
- ```
166
+ ```text
156
167
  Agent({ subagent_type: "auditor", prompt: "Review the auth module", description: "Security audit" })
157
168
  ```
158
169
 
@@ -160,26 +171,28 @@ Agent({ subagent_type: "auditor", prompt: "Review the auth module", description:
160
171
 
161
172
  All fields are optional — sensible defaults for everything.
162
173
 
163
- | Field | Default | Description |
164
- |-------|---------|-------------|
165
- | `description` | filename | Agent description shown in tool listings |
166
- | `display_name` | — | Display name for UI (e.g. widget, agent list) |
167
- | `tools` | all 7 | Comma-separated built-in tools: read, bash, edit, write, grep, find, ls. `none` for no tools |
168
- | `extensions` | `true` | Inherit MCP/extension tools. `false` to disable |
169
- | `skills` | `true` | Inherit skills from parent. Can be a comma-separated list of skill names to preload (see [Skill Preloading](#skill-preloading) for discovery locations) |
170
- | `memory` | — | Persistent agent memory scope: `project`, `local`, or `user`. Auto-detects read-only agents |
171
- | `disallowed_tools` | — | Comma-separated tools to deny even if extensions provide them |
172
- | `isolation` | — | Set to `worktree` to run in an isolated git worktree |
173
- | `model` | inherit parent | Model — `provider/modelId` or fuzzy name (`"haiku"`, `"sonnet"`) |
174
- | `thinking` | inherit | off, minimal, low, medium, high, xhigh |
175
- | `max_turns` | unlimited | Max agentic turns before graceful shutdown. `0` or omit for unlimited |
176
- | `prompt_mode` | `replace` | `replace`: body is the full system prompt (no AGENTS.md / CLAUDE.md inheritance). `append`: body appended to parent's prompt (agent acts as a "parent twin" — inherits parent's AGENTS.md / CLAUDE.md) |
177
- | `inherit_context` | `false` | Fork parent conversation into agent |
178
- | `run_in_background` | `false` | Run in background by default |
179
- | `isolated` | `false` | No extension/MCP tools, only built-in |
180
- | `enabled` | `true` | Set to `false` to disable an agent (useful for hiding a default agent per-project) |
181
-
182
- Frontmatter is authoritative. If an agent file sets `model`, `thinking`, `max_turns`, `inherit_context`, `run_in_background`, `isolated`, or `isolation`, those values are locked for that agent. `Agent` tool parameters only fill fields the agent config leaves unspecified.
174
+ | Field | Default | Description |
175
+ | ------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
176
+ | `description` | filename | Agent description shown in tool listings |
177
+ | `display_name` | — | Display name for UI (e.g. widget, agent list) |
178
+ | `tools` | all 7 | Comma-separated built-in tools: read, bash, edit, write, grep, find, ls. `none` for no tools |
179
+ | `extensions` | `true` | Inherit MCP/extension tools. `false` to disable |
180
+ | `skills` | `true` | Inherit skills from parent. Can be a comma-separated list of skill names to preload (see [Skill Preloading](#skill-preloading) for discovery locations) |
181
+ | `memory` | — | Persistent agent memory scope: `project`, `local`, or `user`. Auto-detects read-only agents |
182
+ | `disallowed_tools` | — | Comma-separated tools to deny even if extensions provide them |
183
+ | `isolation` | — | Set to `worktree` to run in an isolated git worktree |
184
+ | `model` | inherit parent | Model — `provider/modelId` or fuzzy name (`"haiku"`, `"sonnet"`) |
185
+ | `thinking` | inherit | off, minimal, low, medium, high, xhigh |
186
+ | `max_turns` | unlimited | Max agentic turns before graceful shutdown. `0` or omit for unlimited |
187
+ | `prompt_mode` | `replace` | `replace`: body is the full system prompt (no AGENTS.md / CLAUDE.md inheritance). `append`: body appended to parent's prompt (agent acts as a "parent twin" — inherits parent's AGENTS.md / CLAUDE.md) |
188
+ | `inherit_context` | `false` | Fork parent conversation into agent |
189
+ | `run_in_background` | `false` | Run in background by default |
190
+ | `isolated` | `false` | No extension/MCP tools, only built-in |
191
+ | `enabled` | `true` | Set to `false` to disable an agent (useful for hiding a default agent per-project) |
192
+
193
+ Frontmatter is authoritative.
194
+ If an agent file sets `model`, `thinking`, `max_turns`, `inherit_context`, `run_in_background`, `isolated`, or `isolation`, those values are locked for that agent.
195
+ `Agent` tool parameters only fill fields the agent config leaves unspecified.
183
196
 
184
197
  ## Tools
185
198
 
@@ -187,62 +200,66 @@ Frontmatter is authoritative. If an agent file sets `model`, `thinking`, `max_tu
187
200
 
188
201
  Launch a sub-agent.
189
202
 
190
- | Parameter | Type | Required | Description |
191
- |-----------|------|----------|-------------|
192
- | `prompt` | string | yes | The task for the agent |
193
- | `description` | string | yes | Short 3-5 word summary (shown in UI) |
194
- | `subagent_type` | string | yes | Agent type (built-in or custom) |
195
- | `model` | string | no | Model — `provider/modelId` or fuzzy name (`"haiku"`, `"sonnet"`) |
196
- | `thinking` | string | no | Thinking level: off, minimal, low, medium, high, xhigh |
197
- | `max_turns` | number | no | Max agentic turns. Omit for unlimited (default) |
198
- | `run_in_background` | boolean | no | Run without blocking |
199
- | `resume` | string | no | Agent ID to resume a previous session |
200
- | `isolated` | boolean | no | No extension/MCP tools |
201
- | `isolation` | `"worktree"` | no | Run in an isolated git worktree |
202
- | `inherit_context` | boolean | no | Fork parent conversation into agent |
203
+ | Parameter | Type | Required | Description |
204
+ | ------------------- | ------------ | -------- | ---------------------------------------------------------------- |
205
+ | `prompt` | string | yes | The task for the agent |
206
+ | `description` | string | yes | Short 3-5 word summary (shown in UI) |
207
+ | `subagent_type` | string | yes | Agent type (built-in or custom) |
208
+ | `model` | string | no | Model — `provider/modelId` or fuzzy name (`"haiku"`, `"sonnet"`) |
209
+ | `thinking` | string | no | Thinking level: off, minimal, low, medium, high, xhigh |
210
+ | `max_turns` | number | no | Max agentic turns. Omit for unlimited (default) |
211
+ | `run_in_background` | boolean | no | Run without blocking |
212
+ | `resume` | string | no | Agent ID to resume a previous session |
213
+ | `isolated` | boolean | no | No extension/MCP tools |
214
+ | `isolation` | `"worktree"` | no | Run in an isolated git worktree |
215
+ | `inherit_context` | boolean | no | Fork parent conversation into agent |
203
216
 
204
217
  ### `get_subagent_result`
205
218
 
206
219
  Check status and retrieve results from a background agent.
207
220
 
208
- | Parameter | Type | Required | Description |
209
- |-----------|------|----------|-------------|
210
- | `agent_id` | string | yes | Agent ID to check |
211
- | `wait` | boolean | no | Wait for completion |
212
- | `verbose` | boolean | no | Include full conversation log |
221
+ | Parameter | Type | Required | Description |
222
+ | ---------- | ------- | -------- | ----------------------------- |
223
+ | `agent_id` | string | yes | Agent ID to check |
224
+ | `wait` | boolean | no | Wait for completion |
225
+ | `verbose` | boolean | no | Include full conversation log |
213
226
 
214
227
  ### `steer_subagent`
215
228
 
216
- Send a steering message to a running agent. The message interrupts after the current tool execution.
229
+ Send a steering message to a running agent.
230
+ The message interrupts after the current tool execution.
217
231
 
218
- | Parameter | Type | Required | Description |
219
- |-----------|------|----------|-------------|
220
- | `agent_id` | string | yes | Agent ID to steer |
221
- | `message` | string | yes | Message to inject into agent conversation |
232
+ | Parameter | Type | Required | Description |
233
+ | ---------- | ------ | -------- | ----------------------------------------- |
234
+ | `agent_id` | string | yes | Agent ID to steer |
235
+ | `message` | string | yes | Message to inject into agent conversation |
222
236
 
223
237
  ## Commands
224
238
 
225
- | Command | Description |
226
- |---------|-------------|
239
+ | Command | Description |
240
+ | --------- | --------------------------------- |
227
241
  | `/agents` | Interactive agent management menu |
228
242
 
229
243
  The `/agents` command opens an interactive menu:
230
244
 
231
- ```
245
+ ```text
232
246
  Running agents (2) — 1 running, 1 done ← only shown when agents exist
233
247
  Agent types (6) ← unified list: defaults + custom
234
248
  Create new agent ← manual wizard or AI-generated
235
249
  Settings ← max concurrency, max turns, grace turns
236
250
  ```
237
251
 
238
- - **Agent types** — unified list with source indicators: `•` (project), `◦` (global), `✕` (disabled). Select an agent to manage it:
252
+ - **Agent types** — unified list with source indicators: `•` (project), `◦` (global), `✕` (disabled).
253
+ Select an agent to manage it:
239
254
  - **Default agents** (no override): Eject (export as `.md`), Disable
240
255
  - **Default agents** (ejected/overridden): Edit, Disable, Reset to default, Delete
241
256
  - **Custom agents**: Edit, Disable, Delete
242
257
  - **Disabled agents**: Enable, Edit, Delete
243
258
  - **Eject** — writes the embedded default config as a `.md` file to project or personal location, so you can customize it
244
- - **Disable/Enable** — toggle agent availability. Disabled agents stay visible in the list (marked `✕`) and can be re-enabled
245
- - **Create new agent** choose project/personal location, then manual wizard (step-by-step prompts for name, tools, model, thinking, system prompt) or AI-generated (describe what the agent should do and a sub-agent writes the `.md` file). Any name is allowed, including default agent names (overrides them)
259
+ - **Disable/Enable** — toggle agent availability.
260
+ Disabled agents stay visible in the list (marked `✕`) and can be re-enabled
261
+ - **Create new agent** — choose project/personal location, then manual wizard (step-by-step prompts for name, tools, model, thinking, system prompt) or AI-generated (describe what the agent should do and a sub-agent writes the `.md` file).
262
+ Any name is allowed, including default agent names (overrides them)
246
263
  - **Settings** — configure max concurrency, default max turns, and grace turns at runtime
247
264
 
248
265
  ## Graceful Max Turns
@@ -253,27 +270,33 @@ Instead of hard-aborting at the turn limit, agents get a graceful shutdown:
253
270
  2. Up to 5 grace turns to finish cleanly
254
271
  3. Hard abort only after the grace period
255
272
 
256
- | Status | Meaning | Icon |
257
- |--------|---------|------|
258
- | `completed` | Finished naturally | `✓` green |
259
- | `steered` | Hit limit, wrapped up in time | `✓` yellow |
260
- | `aborted` | Grace period exceeded | `✗` red |
261
- | `stopped` | User-initiated abort | `■` dim |
273
+ | Status | Meaning | Icon |
274
+ | ----------- | ----------------------------- | ---------- |
275
+ | `completed` | Finished naturally | `✓` green |
276
+ | `steered` | Hit limit, wrapped up in time | `✓` yellow |
277
+ | `aborted` | Grace period exceeded | `✗` red |
278
+ | `stopped` | User-initiated abort | `■` dim |
262
279
 
263
280
  ## Concurrency
264
281
 
265
- Background agents are subject to a configurable concurrency limit (default: 4). Excess agents are automatically queued and start as running agents complete. The widget shows queued agents as a collapsed count.
282
+ Background agents are subject to a configurable concurrency limit (default: 4).
283
+ Excess agents are automatically queued and start as running agents complete.
284
+ The widget shows queued agents as a collapsed count.
266
285
 
267
286
  Foreground agents bypass the queue — they block the parent anyway.
268
287
 
269
288
  ## Persistent Settings
270
289
 
271
- Runtime tuning values set via `/agents` → Settings (max concurrency, default max turns, grace turns) persist across pi restarts. Two files, merged on load:
290
+ Runtime tuning values set via `/agents` → Settings (max concurrency, default max turns, grace turns) persist across pi restarts.
291
+ Two files, merged on load:
272
292
 
273
- - **Global:** `~/.pi/agent/subagents.json` — your machine-wide defaults. Edit by hand; the `/agents` menu never writes here.
274
- - **Project:** `<cwd>/.pi/subagents.json` per-project overrides. Written by `/agents` Settings.
293
+ - **Global:** `~/.pi/agent/subagents.json` — your machine-wide defaults.
294
+ Edit by hand; the `/agents` menu never writes here.
295
+ - **Project:** `<cwd>/.pi/subagents.json` — per-project overrides.
296
+ Written by `/agents` → Settings.
275
297
 
276
- **Precedence:** project overrides global on any field present in both. Missing fields fall back to the hardcoded defaults (max concurrency `4`, default max turns unlimited, grace turns `5`).
298
+ **Precedence:** project overrides global on any field present in both.
299
+ Missing fields fall back to the hardcoded defaults (max concurrency `4`, default max turns unlimited, grace turns `5`).
277
300
 
278
301
  **Example — global defaults for a beefy machine:**
279
302
 
@@ -287,7 +310,8 @@ cat > ~/.pi/agent/subagents.json <<'EOF'
287
310
  EOF
288
311
  ```
289
312
 
290
- Every project now starts with concurrency 16 and grace 10, without ever touching the menu. Individual projects can still override via `/agents` → Settings.
313
+ Every project now starts with concurrency 16 and grace 10, without ever touching the menu.
314
+ Individual projects can still override via `/agents` → Settings.
291
315
 
292
316
  **Failure behavior:** missing file is silent; malformed JSON logs a `[pi-subagents] Ignoring malformed settings at …` warning to stderr; invalid/out-of-range field values are dropped per-field; write failures downgrade the `/agents` toast to a warning with `(session only; failed to persist)`.
293
317
 
@@ -295,22 +319,25 @@ Every project now starts with concurrency 16 and grace 10, without ever touching
295
319
 
296
320
  Agent lifecycle events are emitted via `pi.events.emit()` so other extensions can react:
297
321
 
298
- | Event | When | Key fields |
299
- |-------|------|------------|
300
- | `subagents:created` | Background agent registered | `id`, `type`, `description`, `isBackground` |
301
- | `subagents:started` | Agent transitions to running (including queued→running) | `id`, `type`, `description` |
302
- | `subagents:completed` | Agent finished successfully | `id`, `type`, `durationMs`, `tokens` (lifetime `{ input, output, total }`), `toolUses`, `result` |
303
- | `subagents:failed` | Agent errored, stopped, or aborted | same as completed + `error`, `status` |
304
- | `subagents:steered` | Steering message sent | `id`, `message` |
305
- | `subagents:compacted` | Agent's session successfully compacted | `id`, `type`, `description`, `reason` (`"manual"` / `"threshold"` / `"overflow"`), `tokensBefore`, `compactionCount` |
306
- | `subagents:settings_loaded` | Persisted settings applied at extension init | `settings` (merged global + project) |
307
- | `subagents:settings_changed` | `/agents` → Settings mutation was applied | `settings`, `persisted` (`boolean` — `false` on write failure) |
308
-
309
- `tokens.total` = `input + output + cacheWrite`. `cacheRead` is excluded — each turn's `cacheRead` is the cumulative cached prefix re-read on that one API call, so summing per-message would over-count it. Use `contextUsage.percent` (surfaced as `(NN%)` in the widget) for current context size.
322
+ | Event | When | Key fields |
323
+ | ---------------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
324
+ | `subagents:created` | Background agent registered | `id`, `type`, `description`, `isBackground` |
325
+ | `subagents:started` | Agent transitions to running (including queued→running) | `id`, `type`, `description` |
326
+ | `subagents:completed` | Agent finished successfully | `id`, `type`, `durationMs`, `tokens` (lifetime `{ input, output, total }`), `toolUses`, `result` |
327
+ | `subagents:failed` | Agent errored, stopped, or aborted | same as completed + `error`, `status` |
328
+ | `subagents:steered` | Steering message sent | `id`, `message` |
329
+ | `subagents:compacted` | Agent's session successfully compacted | `id`, `type`, `description`, `reason` (`"manual"` / `"threshold"` / `"overflow"`), `tokensBefore`, `compactionCount` |
330
+ | `subagents:settings_loaded` | Persisted settings applied at extension init | `settings` (merged global + project) |
331
+ | `subagents:settings_changed` | `/agents` → Settings mutation was applied | `settings`, `persisted` (`boolean` — `false` on write failure) |
332
+
333
+ `tokens.total` = `input + output + cacheWrite`.
334
+ `cacheRead` is excluded — each turn's `cacheRead` is the cumulative cached prefix re-read on that one API call, so summing per-message would over-count it.
335
+ Use `contextUsage.percent` (surfaced as `(NN%)` in the widget) for current context size.
310
336
 
311
337
  ## Persistent Agent Memory
312
338
 
313
- Agents can have persistent memory across sessions. Set `memory` in frontmatter to enable:
339
+ Agents can have persistent memory across sessions.
340
+ Set `memory` in frontmatter to enable:
314
341
 
315
342
  ```yaml
316
343
  ---
@@ -318,13 +345,16 @@ memory: project # project | local | user
318
345
  ---
319
346
  ```
320
347
 
321
- | Scope | Location | Use case |
322
- |-------|----------|----------|
323
- | `project` | `.pi/agent-memory/<name>/` | Shared across the team (committed) |
324
- | `local` | `.pi/agent-memory-local/<name>/` | Machine-specific (gitignored) |
325
- | `user` | `~/.pi/agent-memory/<name>/` | Global personal memory |
348
+ | Scope | Location | Use case |
349
+ | --------- | -------------------------------- | ---------------------------------- |
350
+ | `project` | `.pi/agent-memory/<name>/` | Shared across the team (committed) |
351
+ | `local` | `.pi/agent-memory-local/<name>/` | Machine-specific (gitignored) |
352
+ | `user` | `~/.pi/agent-memory/<name>/` | Global personal memory |
326
353
 
327
- Memory uses a `MEMORY.md` index file and individual memory files with frontmatter. Agents with write tools get full read-write access. **Read-only agents** (no `write`/`edit` tools) automatically get read-only memory — they can consume memories written by other agents but cannot modify them. This prevents unintended tool escalation.
354
+ Memory uses a `MEMORY.md` index file and individual memory files with frontmatter.
355
+ Agents with write tools get full read-write access.
356
+ **Read-only agents** (no `write`/`edit` tools) automatically get read-only memory — they can consume memories written by other agents but cannot modify them.
357
+ This prevents unintended tool escalation.
328
358
 
329
359
  The `disallowed_tools` field is respected when determining write capability — an agent with `tools: write` + `disallowed_tools: write` correctly gets read-only memory.
330
360
 
@@ -332,15 +362,18 @@ The `disallowed_tools` field is respected when determining write capability —
332
362
 
333
363
  Set `isolation: worktree` to run an agent in a temporary git worktree:
334
364
 
335
- ```
365
+ ```text
336
366
  Agent({ subagent_type: "refactor", prompt: "...", isolation: "worktree" })
337
367
  ```
338
368
 
339
- The agent gets a full, isolated copy of the repository. On completion:
369
+ The agent gets a full, isolated copy of the repository.
370
+ On completion:
371
+
340
372
  - **No changes:** worktree is cleaned up automatically
341
373
  - **Changes made:** changes are committed to a new branch (`pi-agent-<id>`) and returned in the result
342
374
 
343
- If the worktree cannot be created (not a git repo, no commits, or `git worktree add` fails), the `Agent` tool returns a clear error instead of running unisolated — `isolation: "worktree"` is a strict guarantee, not a hint. Initialize git and commit at least once, or omit `isolation`.
375
+ If the worktree cannot be created (not a git repo, no commits, or `git worktree add` fails), the `Agent` tool returns a clear error instead of running unisolated — `isolation: "worktree"` is a strict guarantee, not a hint.
376
+ Initialize git and commit at least once, or omit `isolation`.
344
377
 
345
378
  ## Skill Preloading
346
379
 
@@ -354,13 +387,13 @@ skills: api-conventions, error-handling
354
387
 
355
388
  **Discovery roots** (checked in this order, first match wins):
356
389
 
357
- | Scope | Path | Source |
358
- |---|---|---|
359
- | Project | `<cwd>/.pi/skills/` | Pi-standard |
360
- | Project | `<cwd>/.agents/skills/` | [Agent Skills spec](https://agentskills.io/integrate-skills) |
361
- | User | `$PI_CODING_AGENT_DIR/skills/` (default `~/.pi/agent/skills/`) | Pi-standard |
362
- | User | `~/.agents/skills/` | [Agent Skills spec](https://agentskills.io/integrate-skills) |
363
- | User | `~/.pi/skills/` | Legacy (pre-Pi) |
390
+ | Scope | Path | Source |
391
+ | ------- | -------------------------------------------------------------- | ------------------------------------------------------------ |
392
+ | Project | `<cwd>/.pi/skills/` | Pi-standard |
393
+ | Project | `<cwd>/.agents/skills/` | [Agent Skills spec](https://agentskills.io/integrate-skills) |
394
+ | User | `$PI_CODING_AGENT_DIR/skills/` (default `~/.pi/agent/skills/`) | Pi-standard |
395
+ | User | `~/.agents/skills/` | [Agent Skills spec](https://agentskills.io/integrate-skills) |
396
+ | User | `~/.pi/skills/` | Legacy (pre-Pi) |
364
397
 
365
398
  **Per root, a skill named `foo` resolves to the first of:**
366
399
 
@@ -368,9 +401,12 @@ skills: api-conventions, error-handling
368
401
  - `<root>/foo/SKILL.md` — directory skill (top-level)
369
402
  - `<root>/*/.../foo/SKILL.md` — directory skill, found by recursive descent
370
403
 
371
- Recursion skips dotfile directories and `node_modules`. A directory that itself contains a `SKILL.md` is treated as a single skill — we don't descend into it. Traversal is byte-order sorted for deterministic resolution across filesystems.
404
+ Recursion skips dotfile directories and `node_modules`.
405
+ A directory that itself contains a `SKILL.md` is treated as a single skill — we don't descend into it.
406
+ Traversal is byte-order sorted for deterministic resolution across filesystems.
372
407
 
373
- **Security:** symlinks are rejected at every layer (root, flat file, skill directory, `SKILL.md` inside a skill directory) — intentional deviation from Pi, which follows symlinks. Skill names with path-traversal characters (`..`, `/`, `\`, spaces, leading dot, >128 chars) are rejected.
408
+ **Security:** symlinks are rejected at every layer (root, flat file, skill directory, `SKILL.md` inside a skill directory) — intentional deviation from Pi, which follows symlinks.
409
+ Skill names with path-traversal characters (`..`, `/`, `\`, spaces, leading dot, >128 chars) are rejected.
374
410
 
375
411
  ## Tool Denylist
376
412
 
@@ -387,7 +423,7 @@ This is useful for creating agents that inherit extension tools but should not h
387
423
 
388
424
  ## Architecture
389
425
 
390
- ```
426
+ ```text
391
427
  src/
392
428
  index.ts # Extension entry: tool/command registration, rendering
393
429
  types.ts # Type definitions (AgentConfig, AgentRecord, etc.)
@@ -410,11 +446,18 @@ src/
410
446
 
411
447
  ## Deviations from upstream
412
448
 
413
- This fork carries three divergences from [`tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents). Each has a corresponding upstream PR:
414
-
415
- 1. **Peer-dep migration to `@earendil-works/pi-*`** — `peerDependencies` and all imports point at `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, and `@earendil-works/pi-tui` (the active scope on npm) instead of the deprecated `@mariozechner/pi-*` scope. Also fixes a latent bug where `ThinkingLevel` was imported from `pi-agent-core` (an undeclared transitive dep that breaks under pnpm). Upstream PR: [tintinweb/pi-subagents#71](https://github.com/tintinweb/pi-subagents/pull/71).
416
- 2. **Post-`bindExtensions` active-tool re-filter** (`src/agent-runner.ts`) — `runAgent` re-runs its active-tool filter after `session.bindExtensions(...)` so extension-registered tools join the child's active tool set. Without this, the `extensions: string[]` allowlist branch was functionally dead for extension tools, and `extensions: true` with a `disallowedTools` denylist let denylisted extension tools slip through. Upstream PR: [tintinweb/pi-subagents#72](https://github.com/tintinweb/pi-subagents/pull/72).
417
- 3. **`<active_agent>` system-prompt tag** (`src/prompts.ts`) `buildAgentPrompt` prepends `<active_agent name="${config.name}"/>` to every assembled child system prompt (both `replace` and `append` modes). Downstream extensions like [`@gotgenes/pi-permission-system`](https://github.com/gotgenes/pi-permission-system) parse this tag to resolve per-agent `permission:` frontmatter inside the child session. Upstream PR: [tintinweb/pi-subagents#73](https://github.com/tintinweb/pi-subagents/pull/73).
449
+ This fork carries three divergences from [`tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents).
450
+ Each has a corresponding upstream PR:
451
+
452
+ 1. **Peer-dep migration to `@earendil-works/pi-*`** — `peerDependencies` and all imports point at `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, and `@earendil-works/pi-tui` (the active scope on npm) instead of the deprecated `@mariozechner/pi-*` scope.
453
+ Also fixes a latent bug where `ThinkingLevel` was imported from `pi-agent-core` (an undeclared transitive dep that breaks under pnpm).
454
+ Upstream PR: [tintinweb/pi-subagents#71](https://github.com/tintinweb/pi-subagents/pull/71).
455
+ 2. **Post-`bindExtensions` active-tool re-filter** (`src/agent-runner.ts`) — `runAgent` re-runs its active-tool filter after `session.bindExtensions(...)` so extension-registered tools join the child's active tool set.
456
+ Without this, the `extensions: string[]` allowlist branch was functionally dead for extension tools, and `extensions: true` with a `disallowedTools` denylist let denylisted extension tools slip through.
457
+ Upstream PR: [tintinweb/pi-subagents#72](https://github.com/tintinweb/pi-subagents/pull/72).
458
+ 3. **`<active_agent>` system-prompt tag** (`src/prompts.ts`) — `buildAgentPrompt` prepends `<active_agent name="${config.name}"/>` to every assembled child system prompt (both `replace` and `append` modes).
459
+ Downstream extensions like [`@gotgenes/pi-permission-system`](https://github.com/gotgenes/pi-permission-system) parse this tag to resolve per-agent `permission:` frontmatter inside the child session.
460
+ Upstream PR: [tintinweb/pi-subagents#73](https://github.com/tintinweb/pi-subagents/pull/73).
418
461
 
419
462
  The upstream `vitest` suite plus tests added for each patch all pass on every commit.
420
463