pi-herdr-spawn 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 duskoide
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,106 @@
1
+ # pi-herdr-spawn
2
+
3
+ Spawn pi agents in isolated Herdr panes to execute tasks in parallel.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pi install npm:pi-herdr-spawn
9
+ ```
10
+
11
+ Or via git:
12
+
13
+ ```bash
14
+ pi install git:github.com/duskoide/pi-herdr-spawn
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### Slash Commands
20
+
21
+ After installing, restart pi or run `/reload`:
22
+
23
+ ```bash
24
+ # Basic usage - spawn with auto-generated name
25
+ /spawn Run tests and report failures
26
+
27
+ # With custom name
28
+ /spawn Review code pi-reviewer
29
+
30
+ # With custom name and model
31
+ /spawn Review code pi-reviewer claude-sonnet-5
32
+
33
+ # Quick spawn (shorthand)
34
+ /spawnp Run the linter and fix errors
35
+
36
+ # List running agents
37
+ /spawnlist
38
+
39
+ # Kill a specific agent
40
+ /spawnkill pi-test-runner
41
+ ```
42
+
43
+ ### Tool Usage
44
+
45
+ You can also use the `spawn_pi` tool directly:
46
+
47
+ ```
48
+ spawn_pi({
49
+ prompt: "Run tests and report any failures",
50
+ name: "pi-test-runner",
51
+ model: "gpt-4o",
52
+ timeout: 180000,
53
+ direction: "right"
54
+ })
55
+ ```
56
+
57
+ ### Command Line
58
+
59
+ ```bash
60
+ ~/.pi/agent/bin/herdr-spawn.sh <agent-name> "<prompt>" [--model <model>] [--timeout <ms>]
61
+
62
+ # Example:
63
+ ~/.pi/agent/bin/herdr-spawn.sh pi-test "Run npm test and report results" --timeout 180000
64
+ ```
65
+
66
+ ## How It Works
67
+
68
+ 1. **Creates a new pane** - Splits the current pane to create an isolated terminal
69
+ 2. **Starts pi agent** - Launches a fresh pi instance in the new pane
70
+ 3. **Sends your prompt** - Submits the task and waits for completion
71
+ 4. **Reads the response** - Gets the agent's output
72
+ 5. **Cleans up** - Closes the pane and stops the agent automatically
73
+
74
+ ## Requirements
75
+
76
+ - Pi must be running inside a Herdr-managed pane (`HERDR_ENV=1`)
77
+ - Herdr must be installed and running
78
+
79
+ ## Use Cases
80
+
81
+ ### Parallel Testing
82
+
83
+ ```bash
84
+ /spawn npm test pi-tests
85
+ /spawn npm run lint pi-linter
86
+ /spawn npm run typecheck pi-types
87
+ ```
88
+
89
+ ### Code Review
90
+
91
+ ```
92
+ spawn_pi({ prompt: "Review the recent git changes and suggest improvements" })
93
+ ```
94
+
95
+ ### Long-Running Tasks
96
+
97
+ ```
98
+ spawn_pi({
99
+ prompt: "Run the build process and report any errors",
100
+ timeout: 300000
101
+ })
102
+ ```
103
+
104
+ ## License
105
+
106
+ MIT
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env bash
2
+ # herdr-spawn.sh - Spawn a pi agent in a new Herdr pane
3
+ #
4
+ # Usage: herdr-spawn.sh <agent-name> <prompt> [--model <model>] [--timeout <ms>]
5
+ #
6
+ # Example:
7
+ # herdr-spawn.sh pi-test "Run tests and report results"
8
+ # herdr-spawn.sh pi-reviewer "Review the code changes" --model gpt-4o
9
+ # herdr-spawn.sh pi-builder "Build project" --model claude-sonnet-5 --timeout 180000
10
+
11
+ set -euo pipefail
12
+
13
+ # Check Herdr environment
14
+ if [[ "${HERDR_ENV:-}" != "1" ]]; then
15
+ echo "Error: Not running in Herdr environment" >&2
16
+ exit 1
17
+ fi
18
+
19
+ # Parse required arguments
20
+ AGENT_NAME="${1:?Usage: herdr-spawn.sh <agent-name> <prompt> [--model <model>] [--timeout <ms>]}"
21
+ PROMPT="${2:?Usage: herdr-spawn.sh <agent-name> <prompt> [--model <model>] [--timeout <ms>]}"
22
+
23
+ # Parse optional arguments
24
+ MODEL=""
25
+ TIMEOUT="120000"
26
+ shift 2 || true
27
+
28
+ while [[ $# -gt 0 ]]; do
29
+ case "$1" in
30
+ --model)
31
+ MODEL="$2"
32
+ shift 2
33
+ ;;
34
+ --timeout)
35
+ TIMEOUT="$2"
36
+ shift 2
37
+ ;;
38
+ *)
39
+ echo "Unknown option: $1" >&2
40
+ exit 1
41
+ ;;
42
+ esac
43
+ done
44
+
45
+ # Validate agent name (lowercase, hyphens, max 31 chars)
46
+ if [[ ! "$AGENT_NAME" =~ ^[a-z][a-z0-9_-]{0,30}$ ]]; then
47
+ echo "Error: Agent name must be lowercase letters, numbers, hyphens; max 31 chars" >&2
48
+ exit 1
49
+ fi
50
+
51
+ # Get current pane context
52
+ CURRENT_PANE=$(herdr pane current --current)
53
+ PANE_ID=$(echo "$CURRENT_PANE" | jq -r '.result.pane.pane_id')
54
+
55
+ if [[ -z "$PANE_ID" ]]; then
56
+ echo "Error: Could not get current pane ID" >&2
57
+ exit 1
58
+ fi
59
+
60
+ # Create new pane
61
+ NEW_PANE=$(herdr pane split --current --direction right --cwd "$PWD" --no-focus)
62
+ NEW_PANE_ID=$(echo "$NEW_PANE" | jq -r '.result.pane.pane_id')
63
+
64
+ if [[ -z "$NEW_PANE_ID" ]]; then
65
+ echo "Error: Could not create new pane" >&2
66
+ exit 1
67
+ fi
68
+
69
+ # Start pi agent (with optional model)
70
+ START_CMD="herdr agent start \"$AGENT_NAME\" --kind pi --pane \"$NEW_PANE_ID\""
71
+ if [[ -n "$MODEL" ]]; then
72
+ START_CMD="$START_CMD -- --model \"$MODEL\""
73
+ fi
74
+
75
+ START_RESULT=$(eval "$START_CMD")
76
+ AGENT_STATUS=$(echo "$START_RESULT" | jq -r '.result.agent.agent_status')
77
+
78
+ if [[ "$AGENT_STATUS" == "unknown" ]]; then
79
+ echo "Error: Failed to start agent" >&2
80
+ exit 1
81
+ fi
82
+
83
+ # Send prompt
84
+ PROMPT_RESULT=$(herdr agent prompt "$AGENT_NAME" "$PROMPT" --wait --timeout "$TIMEOUT")
85
+ PROMPT_STATUS=$(echo "$PROMPT_RESULT" | jq -r '.type')
86
+
87
+ if [[ "$PROMPT_STATUS" != "agent_prompted" ]]; then
88
+ echo "Error: Failed to send prompt" >&2
89
+ exit 1
90
+ fi
91
+
92
+ # Read response
93
+ RESPONSE=$(herdr agent read "$AGENT_NAME" --source recent-unwrapped --lines 100)
94
+
95
+ # Output results
96
+ cat <<EOF
97
+ {
98
+ "pane_id": "$NEW_PANE_ID",
99
+ "agent_name": "$AGENT_NAME",
100
+ "model": "${MODEL:-parent}",
101
+ "status": "completed",
102
+ "response": $(echo "$RESPONSE" | jq -Rs .)
103
+ }
104
+ EOF
105
+
106
+ # Cleanup: Close the pane (this also stops the agent)
107
+ herdr pane close "$NEW_PANE_ID" > /dev/null 2>&1 || true
@@ -0,0 +1,310 @@
1
+ import { z } from "zod";
2
+
3
+ const SpawnPiInput = z.object({
4
+ prompt: z.string().describe("The prompt to send to the spawned pi agent"),
5
+ name: z
6
+ .string()
7
+ .optional()
8
+ .describe(
9
+ "Unique name for the agent (lowercase, hyphens, max 31 chars). Auto-generated if not provided."
10
+ ),
11
+ model: z
12
+ .string()
13
+ .optional()
14
+ .describe(
15
+ "Model to use for the spawned agent (e.g., 'gpt-4o', 'claude-sonnet-5', 'provider/model-id'). Uses parent model if not specified."
16
+ ),
17
+ timeout: z
18
+ .number()
19
+ .optional()
20
+ .default(120000)
21
+ .describe("Timeout in milliseconds for the prompt (default: 120000)"),
22
+ direction: z
23
+ .enum(["right", "down"])
24
+ .optional()
25
+ .default("right")
26
+ .describe("Pane split direction (default: right)"),
27
+ });
28
+
29
+ export default function herdrSpawn() {
30
+ return {
31
+ name: "herdr-spawn",
32
+ description:
33
+ "Spawn a pi agent in a new Herdr pane to execute tasks in parallel. Use when you need to run work in a separate pane without blocking the current session.",
34
+ commands: [
35
+ {
36
+ name: "spawn",
37
+ description:
38
+ "Spawn a pi agent in a new pane to execute a task. Usage: /spawn <prompt> [name] [model] [timeout]",
39
+ execute: async (args: string) => {
40
+ // Parse command args: /spawn <prompt> [name] [model] [timeout]
41
+ const parts = args.trim().split(/\s+/);
42
+
43
+ if (parts.length === 0 || !parts[0]) {
44
+ return {
45
+ message: "Usage: /spawn <prompt> [agent-name] [model] [timeout-ms]\n\nExamples:\n/spawn Run tests and report failures\n/spawn Review code pi-review gpt-4o\n/spawn Build project pi-builder claude-sonnet-5 300000",
46
+ };
47
+ }
48
+
49
+ const prompt = parts[0];
50
+ const name = parts[1] || `pi-${Date.now().toString(36)}`;
51
+ const model = parts[2] || undefined;
52
+ const timeout = parts[3] ? parseInt(parts[3]) : 120000;
53
+
54
+ // Check Herdr environment
55
+ if (process.env.HERDR_ENV !== "1") {
56
+ return {
57
+ error: "Not running in Herdr environment. Cannot spawn pane.",
58
+ };
59
+ }
60
+
61
+ try {
62
+ const { execSync } = require("child_process");
63
+
64
+ // Create new pane
65
+ const splitResult = execSync(
66
+ `herdr pane split --current --direction right --cwd "${process.env.PWD}" --no-focus`,
67
+ { encoding: "utf-8" }
68
+ );
69
+ const split = JSON.parse(splitResult);
70
+ const newPaneId = split.result?.pane?.pane_id;
71
+
72
+ if (!newPaneId) {
73
+ return { error: "Could not create new pane" };
74
+ }
75
+
76
+ // Build start command with optional model
77
+ let startCmd = `herdr agent start "${name}" --kind pi --pane "${newPaneId}"`;
78
+ if (model) {
79
+ startCmd += ` -- --model "${model}"`;
80
+ }
81
+
82
+ // Start agent
83
+ execSync(startCmd, { encoding: "utf-8" });
84
+
85
+ // Send prompt
86
+ const escapedPrompt = prompt.replace(/"/g, '\\"');
87
+ execSync(
88
+ `herdr agent prompt "${name}" "${escapedPrompt}" --wait --timeout ${timeout}`,
89
+ { encoding: "utf-8" }
90
+ );
91
+
92
+ // Read response
93
+ const response = execSync(
94
+ `herdr agent read "${name}" --source recent-unwrapped --lines 100`,
95
+ { encoding: "utf-8" }
96
+ );
97
+
98
+ // Cleanup
99
+ execSync(`herdr pane close "${newPaneId}" 2>/dev/null || true`, {
100
+ encoding: "utf-8",
101
+ });
102
+
103
+ return {
104
+ message: `✅ Agent \"${name}\" completed in pane ${newPaneId}\n\n${response}`,
105
+ };
106
+ } catch (error: any) {
107
+ return { error: `Failed: ${error.message}` };
108
+ }
109
+ },
110
+ },
111
+ {
112
+ name: "spawnp",
113
+ description:
114
+ "Quick spawn: /spawnp <prompt> [model] - spawns agent with auto-generated name",
115
+ execute: async (args: string) => {
116
+ if (!args.trim()) {
117
+ return { error: "Usage: /spawnp <prompt> [model]" };
118
+ }
119
+ // Delegate to /spawn with auto-generated name
120
+ const autoName = `pi-${Date.now().toString(36)}`;
121
+ return this.commands!.find((c) => c.name === "spawn")!.execute(
122
+ `${args.trim()} ${autoName} ${args.split(' ').slice(1).join(' ') || ''}`.trim()
123
+ );
124
+ },
125
+ },
126
+ {
127
+ name: "spawnlist",
128
+ description: "List all currently running spawned agents",
129
+ execute: async () => {
130
+ if (process.env.HERDR_ENV !== "1") {
131
+ return { error: "Not running in Herdr environment" };
132
+ }
133
+
134
+ try {
135
+ const { execSync } = require("child_process");
136
+ const result = execSync("herdr agent list", { encoding: "utf-8" });
137
+ const agents = JSON.parse(result);
138
+
139
+ if (!agents.result?.agents?.length) {
140
+ return { message: "No agents currently running." };
141
+ }
142
+
143
+ const list = agents.result.agents
144
+ .map((a: any) => `- ${a.name} (${a.agent_status}) in ${a.pane_id}`)
145
+ .join("\n");
146
+
147
+ return { message: `Running agents:\n${list}` };
148
+ } catch (error: any) {
149
+ return { error: `Failed: ${error.message}` };
150
+ }
151
+ },
152
+ },
153
+ {
154
+ name: "spawnkill",
155
+ description: "Kill a spawned agent by name: /spawnkill <agent-name>",
156
+ execute: async (args: string) => {
157
+ const agentName = args.trim();
158
+ if (!agentName) {
159
+ return { error: "Usage: /spawnkill <agent-name>" };
160
+ }
161
+
162
+ if (process.env.HERDR_ENV !== "1") {
163
+ return { error: "Not running in Herdr environment" };
164
+ }
165
+
166
+ try {
167
+ const { execSync } = require("child_process");
168
+
169
+ // Get agent info to find pane ID
170
+ const agentInfo = execSync(`herdr agent get "${agentName}"`, {
171
+ encoding: "utf-8",
172
+ });
173
+ const agent = JSON.parse(agentInfo);
174
+ const paneId = agent.result?.agent?.pane_id;
175
+
176
+ if (!paneId) {
177
+ return { error: `Agent "${agentName}" not found` };
178
+ }
179
+
180
+ // Close the pane (this stops the agent)
181
+ execSync(`herdr pane close "${paneId}"`, { encoding: "utf-8" });
182
+
183
+ return { message: `✅ Killed agent "${agentName}" in pane ${paneId}` };
184
+ } catch (error: any) {
185
+ return { error: `Failed: ${error.message}` };
186
+ }
187
+ },
188
+ },
189
+ ],
190
+ tools: [
191
+ {
192
+ name: "spawn_pi",
193
+ description:
194
+ "Spawn a pi agent in a new Herdr pane, send a prompt, wait for response, and return the result. The pane is automatically closed after completion.",
195
+ inputSchema: SpawnPiInput,
196
+ execute: async (input: z.infer<typeof SpawnPiInput>) => {
197
+ // Check if we're in Herdr
198
+ const herdrEnv = process.env.HERDR_ENV;
199
+ if (herdrEnv !== "1") {
200
+ return {
201
+ error: "Not running in Herdr environment. Cannot spawn pane.",
202
+ };
203
+ }
204
+
205
+ const { prompt, timeout = 120000, direction = "right" } = input;
206
+ const agentName =
207
+ input.name ||
208
+ `pi-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
209
+
210
+ // Validate agent name
211
+ if (!/^[a-z][a-z0-9_-]{0,30}$/.test(agentName)) {
212
+ return {
213
+ error:
214
+ "Agent name must be lowercase letters, numbers, hyphens; max 31 chars",
215
+ };
216
+ }
217
+
218
+ try {
219
+ // We'll use bash commands to interact with herdr CLI
220
+ // since this extension runs in the pi process
221
+
222
+ // Get current pane context
223
+ const currentResult = await execCommand(
224
+ "herdr pane current --current"
225
+ );
226
+ const current = JSON.parse(currentResult);
227
+ const currentPaneId = current.result?.pane?.pane_id;
228
+
229
+ if (!currentPaneId) {
230
+ return { error: "Could not get current pane ID" };
231
+ }
232
+
233
+ // Create new pane
234
+ const splitResult = await execCommand(
235
+ `herdr pane split --current --direction ${direction} --cwd "${process.env.PWD}" --no-focus`
236
+ );
237
+ const split = JSON.parse(splitResult);
238
+ const newPaneId = split.result?.pane?.pane_id;
239
+
240
+ if (!newPaneId) {
241
+ return { error: "Could not create new pane" };
242
+ }
243
+
244
+ // Build agent start command with optional model argument
245
+ let startCmd = `herdr agent start "${agentName}" --kind pi --pane "${newPaneId}"`;
246
+ if (model) {
247
+ startCmd += ` -- --model "${model}"`;
248
+ }
249
+
250
+ // Start pi agent
251
+ const startResult = await execCommand(startCmd);
252
+ const start = JSON.parse(startResult);
253
+
254
+ if (!start.result?.agent?.agent_status) {
255
+ return { error: "Failed to start agent" };
256
+ }
257
+
258
+ // Send prompt (escape quotes in prompt)
259
+ const escapedPrompt = prompt.replace(/"/g, '\\"');
260
+ const promptResult = await execCommand(
261
+ `herdr agent prompt "${agentName}" "${escapedPrompt}" --wait --timeout ${timeout}`
262
+ );
263
+ const promptRes = JSON.parse(promptResult);
264
+
265
+ if (promptRes.type !== "agent_prompted") {
266
+ // Cleanup on failure
267
+ await execCommand(`herdr pane close "${newPaneId}" 2>/dev/null || true`);
268
+ return { error: "Failed to send prompt" };
269
+ }
270
+
271
+ // Read response
272
+ const readResult = await execCommand(
273
+ `herdr agent read "${agentName}" --source recent-unwrapped --lines 100`
274
+ );
275
+
276
+ // Cleanup: close the pane
277
+ await execCommand(`herdr pane close "${newPaneId}" 2>/dev/null || true`);
278
+
279
+ return {
280
+ pane_id: newPaneId,
281
+ agent_name: agentName,
282
+ status: "completed",
283
+ response: readResult,
284
+ };
285
+ } catch (error) {
286
+ return {
287
+ error: `Failed to spawn pi agent: ${error.message}`,
288
+ };
289
+ }
290
+ },
291
+ },
292
+ ],
293
+ };
294
+ }
295
+
296
+ // Helper function to execute bash commands
297
+ async function execCommand(command: string): Promise<string> {
298
+ const { execSync } = require("child_process");
299
+ try {
300
+ return execSync(command, {
301
+ encoding: "utf-8",
302
+ timeout: 30000,
303
+ stdio: ["pipe", "pipe", "pipe"],
304
+ });
305
+ } catch (error: any) {
306
+ throw new Error(
307
+ `Command failed: ${command}\n${error.stderr || error.message}`
308
+ );
309
+ }
310
+ }
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "pi-herdr-spawn",
3
+ "version": "1.0.0",
4
+ "description": "Spawn pi agents in isolated Herdr panes for parallel task execution",
5
+ "keywords": ["pi-package", "herdr", "agent", "spawn", "parallel", "multiplexer"],
6
+ "author": "duskoide",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/duskoide/pi-herdr-spawn"
11
+ },
12
+ "pi": {
13
+ "skills": ["./skills"],
14
+ "extensions": ["./extensions"]
15
+ },
16
+ "peerDependencies": {
17
+ "@earendil-works/pi-coding-agent": "*"
18
+ }
19
+ }
@@ -0,0 +1,40 @@
1
+ # Herdr Spawn Skill
2
+
3
+ Spawn pi agents in isolated Herdr panes to execute tasks in parallel.
4
+
5
+ ## Quick Start
6
+
7
+ After installing this package with `pi install npm:pi-herdr-spawn`, use the slash commands:
8
+
9
+ ```bash
10
+ # Basic usage - spawn with auto-generated name
11
+ /spawn Run tests and report failures
12
+
13
+ # With custom name
14
+ /spawn Review code pi-reviewer
15
+
16
+ # With custom name and model
17
+ /spawn Review code pi-reviewer claude-sonnet-5
18
+
19
+ # Quick spawn (shorthand)
20
+ /spawnp Run the linter and fix errors
21
+
22
+ # List running agents
23
+ /spawnlist
24
+
25
+ # Kill a specific agent
26
+ /spawnkill pi-test-runner
27
+ ```
28
+
29
+ ## How It Works
30
+
31
+ 1. **Creates a new pane** - Splits the current pane to create an isolated terminal
32
+ 2. **Starts pi agent** - Launches a fresh pi instance in the new pane
33
+ 3. **Sends your prompt** - Submits the task and waits for completion
34
+ 4. **Reads the response** - Gets the agent's output
35
+ 5. **Cleans up** - Closes the pane and stops the agent automatically
36
+
37
+ ## Requirements
38
+
39
+ - Pi must be running inside a Herdr-managed pane (`HERDR_ENV=1`)
40
+ - Herdr must be installed and running
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: herdr-spawn
3
+ description: Spawns a pi agent in a new Herdr pane to execute isolated tasks in parallel. Use when you need to run work in a separate pane without blocking the current session.
4
+ ---
5
+
6
+ # Herdr Spawn
7
+
8
+ Spawn pi agents in isolated Herdr panes to execute tasks in parallel.
9
+
10
+ ## When to Use
11
+
12
+ - Running long tasks without blocking the current session
13
+ - Parallel execution of independent tasks
14
+ - Isolating potentially destructive operations
15
+ - Running background monitoring or testing
16
+
17
+ ## Workflow
18
+
19
+ ### 1. Verify Herdr Environment
20
+
21
+ ```bash
22
+ test "${HERDR_ENV:-}" = 1 && echo "In Herdr" || echo "Not in Herdr"
23
+ ```
24
+
25
+ If not in Herdr, report the error and stop.
26
+
27
+ ### 2. Get Current Context
28
+
29
+ ```bash
30
+ herdr pane current --current
31
+ ```
32
+
33
+ Extract the `pane_id` from the response.
34
+
35
+ ### 3. Create New Pane
36
+
37
+ Split to create a sibling pane (preserves working directory and user focus):
38
+
39
+ ```bash
40
+ herdr pane split --current --direction right --cwd "$PWD" --no-focus
41
+ ```
42
+
43
+ Extract the new `pane_id` from `.result.pane.pane_id`.
44
+
45
+ ### 4. Start Pi Agent
46
+
47
+ Start a pi agent with a unique, descriptive name. Optionally specify a model:
48
+
49
+ ```bash
50
+ # Without model (uses parent's model)
51
+ herdr agent start <unique-name> --kind pi --pane <new-pane-id>
52
+
53
+ # With specific model
54
+ herdr agent start <unique-name> --kind pi --pane <new-pane-id> -- --model <model-id>
55
+ ```
56
+
57
+ **Naming rules:**
58
+ - Lowercase letters, numbers, hyphens only
59
+ - Maximum 31 characters
60
+ - Must be unique among live agents
61
+ - Example: `pi-test-runner`, `pi-refactor-auth`
62
+
63
+ **Model examples:**
64
+ - `gpt-4o` - Fast, good for simple tasks
65
+ - `claude-sonnet-5` - Strong reasoning
66
+ - `provider/model-id` - Full provider specification
67
+
68
+ ### 5. Send Prompt and Wait
69
+
70
+ Submit the task and wait for completion:
71
+
72
+ ```bash
73
+ herdr agent prompt <agent-name> "<prompt>" --wait --timeout 120000
74
+ ```
75
+
76
+ For complex tasks, increase the timeout.
77
+
78
+ ### 6. Read Response
79
+
80
+ Get the agent's output:
81
+
82
+ ```bash
83
+ herdr agent read <agent-name> --source recent-unwrapped --lines 100
84
+ ```
85
+
86
+ ### 7. Report Results
87
+
88
+ Provide:
89
+ - Pane ID where the agent ran
90
+ - Agent name
91
+ - Complete response from the agent
92
+ - Any errors encountered
93
+
94
+ ### 8. Cleanup (Important!)
95
+
96
+ After getting the response, close the agent and pane to free resources:
97
+
98
+ ```bash
99
+ # Close the pane (this also stops the agent)
100
+ herdr pane close <pane-id>
101
+ ```
102
+
103
+ **Note:** Closing the pane automatically stops any agent running in it. Only close panes you created!
104
+
105
+ ## Example Usage
106
+
107
+ **User request:** "Run tests in a separate pane using a fast model"
108
+
109
+ **Agent execution:**
110
+ 1. Verify Herdr environment
111
+ 2. Create new pane: `herdr pane split --current --direction right --cwd /home/pn --no-focus`
112
+ 3. Start agent with model: `herdr agent start pi-test-run --kind pi --pane w7:p2 -- --model gpt-4o`
113
+ 4. Send prompt: `herdr agent prompt pi-test-run "Run the test suite with 'npm test' and report any failures" --wait`
114
+ 5. Read output: `herdr agent read pi-test-run --source recent-unwrapped --lines 150`
115
+ 6. Report: "Tests completed in pane w7:p2. 15 tests passed, 2 failed. Here are the failures: ..."
116
+ 7. Cleanup: `herdr pane close w7:p2`
117
+
118
+ **User request:** "Review code with claude-sonnet-5"
119
+
120
+ **Agent execution:**
121
+ 1. Verify Herdr environment
122
+ 2. Create new pane
123
+ 3. Start agent with model: `herdr agent start pi-review --kind pi --pane w7:p3 -- --model claude-sonnet-5`
124
+ 4. Send prompt: `herdr agent prompt pi-review "Review the recent code changes" --wait`
125
+ 5. Read output
126
+ 6. Report results
127
+ 7. Cleanup
128
+
129
+ ## Important Notes
130
+
131
+ - Always use `--no-focus` to keep the user's focus on the original pane
132
+ - Use unique agent names to avoid conflicts
133
+ - The spawned agent has access to the same tools and context as the parent
134
+ - For very long tasks, consider using `--timeout` with appropriate values
135
+ - If reading output fails (alternate screen), ask the agent to write results to a file and read that instead