### Run mise setup Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Installs the pinned Node.js, pnpm, and hook tools, then enables the tracked hk hooks for the checkout. ```sh mise run setup ``` -------------------------------- ### MirrorRuntime setup in createPiHerdExtension Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herd.md Code executed on session_start to create a Unix socket path, instantiate the MirrorServer and HerdrMirrorPaneLauncher, and start the MirrorRuntime. Requires HERDR_ENV and HERDR_PANE_ID to be present. ```typescript const socketPath = join(tmpdir(), `pi-herd-${process.pid}-${Date.now()}.sock`); const server = new MirrorServer({ socketPath }); const launcher = new HerdrMirrorPaneLauncher({ pi, currentPaneId }); runtime = new MirrorRuntime({ source, server, launcher, socketPath }); await runtime.start(); ``` -------------------------------- ### Install from a local checkout Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Installs from a local checkout, including commands to install the package and run the source file. ```sh pi install ./packages/pi-subagents pi -e ./packages/pi-subagents/src/index.ts ``` -------------------------------- ### Install into project settings with pi install -l Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herdr/README.md Installs into project settings (.pi/settings.json) so trusted project sessions auto-install it on startup. ```sh pi install -l npm:@weshipwork/pi-herdr ``` -------------------------------- ### start Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herd.md Starts the MirrorServer. Creates the parent directory, removes any stale socket, and listens. Rejects with the listen error if binding fails. ```APIDOC ## start ### Description Starts the MirrorServer. Creates the parent directory, removes any stale socket, and listens. Rejects with the listen error if binding fails. ### Method start ### Signature `async start(): Promise` ### Parameters None ### Returns `Promise` - Resolves when the server is listening. ### Errors Rejects with the listen error if binding fails. ``` -------------------------------- ### Install both packages in the Delegator Pi session Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.mirror.md Install @weshipwork/pi-subagents and @weshipwork/pi-herd in the Delegator Pi session using the pi install command. ```sh pi install npm:@weshipwork/pi-subagents pi install npm:@weshipwork/pi-herd ``` -------------------------------- ### Install from local checkout Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Installs from a local checkout of the monorepo. ```sh pi install ./packages/pi-herdr pi install ./packages/pi-subagents pi install ./packages/pi-herd ``` -------------------------------- ### Install globally with pi install Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herdr/README.md Installs the extension globally for user settings (~/.pi/agent/settings.json). ```sh pi install npm:@weshipwork/pi-herdr ``` -------------------------------- ### Install both packages for project-local settings Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.mirror.md Install @weshipwork/pi-subagents and @weshipwork/pi-herd locally for the project using the -l flag. ```sh pi install -l npm:@weshipwork/pi-subagents pi install -l npm:@weshipwork/pi-herd ``` -------------------------------- ### Install into project settings Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Installs the package locally for project settings with the -l flag. ```sh pi install -l npm:@weshipwork/pi-subagents ``` -------------------------------- ### Clone and install dependencies Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Clones the repository and installs dependencies with pnpm. ```sh git clone https://github.com/WeShipWork/threeonefour.git cd threeonefour pnpm install ``` -------------------------------- ### AgentManager usage example Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-manager.md Shows how to instantiate AgentManager with a callback and max concurrency, spawn an agent with options, check its status, abort it if running, wait for all agents to finish, and dispose the manager. The spawn call returns an ID and the agent starts as 'queued' or 'running'. ```typescript import { AgentManager } from "@weshipwork/pi-subagents/src/agent-manager.js"; // path import from a checkout const manager = new AgentManager( (record) => console.log(`[demo] ${record.description} → ${record.status}`), 4, // max concurrent ); const id = manager.spawn(pi, ctx, "Explore", "Map the API routes", { description: "Map API routes", run_in_background: true, maxTurns: 10, }); console.log("spawned", id); // "queued" or "running" // later if (manager.getRecord(id)?.status === "running") manager.abort(id); await manager.waitForAll(); manager.dispose(); ``` -------------------------------- ### Install globally for user settings Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Installs the package globally for user settings. ```sh pi install npm:@weshipwork/pi-subagents ``` -------------------------------- ### Persistence and Worktree Usage Example Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/persistence.md Demonstrates initializing an output file, streaming session data, and managing a git worktree for agent tasks. ```ts import { createOutputFilePath, writeInitialEntry, streamToOutputFile } from "@weshipwork/pi-subagents/src/output-file.js"; import { createWorktree, cleanupWorktree } from "@weshipwork/pi-subagents/src/worktree.js"; const out = createOutputFilePath(cwd, agentId, sessionId); writeInitialEntry(out, agentId, "Do the thing", cwd); const cleanupStream = streamToOutputFile(session, out, agentId, cwd); const wt = createWorktree(cwd, agentId); // undefined outside a git repo if (wt) { console.log("agent works at", wt.workPath, "branch", wt.branch); const result = cleanupWorktree(cwd, wt, "my task"); // result.hasChanges → branch "pi-agent-" holds the committed work } cleanupStream(); ``` -------------------------------- ### Mirror protocol example transcripts Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/endpoints.md Example transcripts showing the subscribe payload, immediate snapshot, and live events exchanged over the Mirror socket. ```text # subscribe payload written by the viewer {"agentId":"a1b2c3d4e5f6789"} # immediate snapshot (if one exists) {"type":"snapshot","agent":{"id":"a1b2c3d4e5f6789","type":"Explore","description":"find auth","status":"running","assistantText":"Looking for auth files…","updatedAt":1750000000000},"sequence":0} # live events {"type":"status","agentId":"a1b2c3d4e5f6789","status":"running","sequence":1} {"type":"assistant_text_delta","agentId":"a1b2c3d4e5f6789","delta":"Found 5 files","sequence":2} {"type":"status","agentId":"a1b2c3d4e5f6789","status":"completed","sequence":3} ``` -------------------------------- ### Usage example with subagent prompts and model resolution Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/prompting.md Shows how to call `buildAgentPrompt`, `buildParentContext`, `resolveModel`, and the enabled-model helpers together. The example passes a config, cwd, Git context, and parent prompt, then resolves a model by name (logging a warning if not found) and checks whether a specific model is in scope. ```typescript import { buildAgentPrompt } from "@weshipwork/pi-subagents/src/prompts.js"; import { buildParentContext } from "@weshipwork/pi-subagents/src/context.js"; import { resolveModel } from "@weshipwork/pi-subagents/src/model-resolver.js"; import { isModelInScope, readEnabledModels, resolveEnabledModels } from "@weshipwork/pi-subagents/src/enabled-models.js"; const prompt = buildAgentPrompt(cfg, cwd, { isGitRepo: true, branch: "main", platform: "linux" }, parentPrompt, { memoryBlock: "…", skillBlocks: [{ name: "api-conventions", content: "…" }], }); const inherited = buildParentContext(ctx); // "" when the branch is empty const resolved = resolveModel("haiku", ctx.modelRegistry); if (typeof resolved === "string") console.warn(resolved); // "Model not found: ..." else console.log(resolved.id); const allowed = resolveEnabledModels(readEnabledModels(cwd), ctx.modelRegistry, cwd); if (allowed && !isModelInScope({ provider: "anthropic", id: "claude-opus-4-6" }, allowed)) { console.warn("out of scope"); } ``` -------------------------------- ### Install pi-subagents, pi-herd, and pi-herdr globally Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herd/README.md Installs the required packages globally for user settings (~/.pi/agent/settings.json). ```sh pi install npm:@weshipwork/pi-subagents pi install npm:@weshipwork/pi-herd pi install npm:@weshipwork/pi-herdr ``` -------------------------------- ### herdr interface usage example from a Pi session Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herdr.md Shows model-side calls to the herdr tool with actions pane_split, run, watch, and wait_agent. Each call is a plain object with action-specific fields; the tool returns human-readable result strings shown as comments. No explicit setup is given on the page. ```ts // From inside a Pi session running in a Herdr pane, the tool is exposed to the // model as "herdr". A typical model-side call: herdr({ action: "pane_split", direction: "right", newPane: "server", cwd: "/workspace/myapp", }); // → "Created pane '' by splitting '' right, aliased as 'server'" herdr({ action: "run", pane: "server", command: "pnpm dev", lines: 30 }); // → "Started 'pnpm dev' in pane 'server' ()\n\n" herdr({ action: "watch", pane: "server", match: "Ready in", timeout: 60000 }); // → "Matched: Ready in ...\n\n" herdr({ action: "wait_agent", panes: ["server", "reviewer"], statuses: ["done"], mode: "all", timeout: 120000 }); // → "wait_agent satisfied (all: done)\n\nserver=done, reviewer=done" ``` -------------------------------- ### Programmatic wiring of MirrorServer and MirrorBridge Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herd.md Shows how to set up the mirror server and bridge programmatically, including importing from per-path modules, starting the bridge, and upserting a snapshot. Also includes the viewer side with streamMirrorEvents and renderMirrorEvent. ```ts // Programmatic wiring without the extension (as done by cicada tests / future hosts): import { MirrorServer } from "@weshipwork/pi-herd/src/mirror-server.js"; // per-path import from a checkout import { MirrorBridge } from "@weshipwork/pi-herd/src/mirror-bridge.js"; const server = new MirrorServer({ socketPath: "/tmp/pi-herd-demo.sock" }); const bridge = new MirrorBridge({ server, source: myObservationSource }); await bridge.start(); // binds socket, subscribes server.upsertSnapshot({ id: "a1", type: "Explore", description: "find auth", status: "running", assistantText: "", updatedAt: Date.now() }); // Viewer side: import { streamMirrorEvents } from "@weshipwork/pi-herd/src/mirror-client.js"; import { renderMirrorEvent } from "@weshipwork/pi-herd/src/viewer-render.js"; const socket = await streamMirrorEvents({ socketPath: "/tmp/pi-herd-demo.sock", agentId: "a1" }, (event) => { process.stdout.write(renderMirrorEvent(event)); }); await bridge.stop(); ``` -------------------------------- ### Install pi-subagents, pi-herd, and pi-herdr into project settings Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herd/README.md Installs the packages into project settings (.pi/settings.json) so trusted project sessions auto-install them on startup. ```sh pi install -l npm:@weshipwork/pi-subagents pi install -l npm:@weshipwork/pi-herd pi install -l npm:@weshipwork/pi-herdr ``` -------------------------------- ### AgentManager Usage Example Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-manager.md Example of creating an AgentManager, spawning a subagent, checking its status, aborting it, waiting for all agents to complete, and disposing the manager. ```APIDOC ## AgentManager Usage Example ### Description Demonstrates how to instantiate an AgentManager, spawn a subagent, monitor its status, abort it if running, wait for all agents to finish, and dispose of the manager. ### Constructor `new AgentManager(onStatusChange, maxConcurrent)` - **onStatusChange** (function) - Callback invoked with `(record)` whenever an agent's status changes. - **maxConcurrent** (number) - Maximum number of concurrently running agents. ### Methods #### `spawn(pi, ctx, type, description, options)` - **pi** (object) - The PI instance. - **ctx** (object) - The context object. - **type** (string) - The subagent type (e.g., "Explore"). - **description** (string) - A description of the task. - **options** (object) - Optional settings: - **description** (string) - Description of the agent. - **run_in_background** (boolean) - Whether to run in background. - **maxTurns** (number) - Maximum number of turns. - Returns: **id** (string) - The agent record ID. #### `getRecord(id)` - **id** (string) - The agent record ID. - Returns: **AgentRecord | undefined** - The agent record or undefined if not found. #### `abort(id)` - **id** (string) - The agent record ID. - Aborts the running agent. #### `waitForAll()` - Returns: **Promise** - Resolves when all agents have completed. #### `dispose()` - Cleans up resources. ### Example Code ```ts import { AgentManager } from "@weshipwork/pi-subagents/src/agent-manager.js"; // path import from a checkout const manager = new AgentManager( (record) => console.log(`[demo] ${record.description} → ${record.status}`), 4, // max concurrent ); const id = manager.spawn(pi, ctx, "Explore", "Map the API routes", { description: "Map API routes", run_in_background: true, maxTurns: 10, }); console.log("spawned", id); // "queued" or "running" // later if (manager.getRecord(id)?.status === "running") manager.abort(id); await manager.waitForAll(); manager.dispose(); ``` ``` -------------------------------- ### Default and example scoping configurations Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Shows defaults for both options and several configurations for narrowing or expanding tools and extensions. Note that `tools: "*"` is an alias for `all`, `tools: none` is an alias for `""`, and `extensions: [mcp]` loads only the mcp extension. Array and string forms are equivalent. ```yaml # Default (both omitted): all extensions load, all 7 built-ins surface tools: read, grep, find # narrow to listed built-ins; extensions still load tools: "*" # all 7 built-ins (alias: `all`) tools: none # zero built-ins (alias: `""`) tools: "*, ext:mcp/search" # built-ins plus one extension tool extensions: false # no extensions load extensions: [mcp] # only mcp loads extensions: ["*", "/abs/foo.ts"] # all defaults plus one path-loaded extension exclude_extensions: pi-notify # everything except pi-notify (with extensions: true) # Specialist: load one extension, expose only one of its tools, keep built-ins extensions: [mcp] tools: "*, ext:mcp/search" isolated: true # hermetic: built-ins only, no extensions/skills/context ``` -------------------------------- ### Usage example: SubagentScheduler integration Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/schedule.md Shows how to import and use SubagentScheduler with ScheduleStore. It creates a scheduler, starts it with the session context, adds a job with a cron schedule, checks the next run, and stops the scheduler. ```typescript import { SubagentScheduler } from "@weshipwork/pi-subagents/src/schedule.js"; import { ScheduleStore, resolveStorePath } from "@weshipwork/pi-subagents/src/schedule-store.js"; const scheduler = new SubagentScheduler(); scheduler.start(pi, ctx, manager, new ScheduleStore(resolveStorePath(cwd, sessionId))); const job = scheduler.addJob({ name: "weekly triage", description: "Weekly commit review", schedule: "0 0 9 * * 1", // 9am Monday, 6-field cron subagent_type: "Explore", prompt: "Summarize last week's commits", }); console.log(scheduler.getNextRun(job.id)); // ISO string if (!scheduler.isActive()) { /* scheduler not bound to a session yet */ } scheduler.removeJob(job.id); scheduler.stop(); ``` -------------------------------- ### Usage example: ConversationViewer with createViewerKeys Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/ui.md Shows how to create viewer keys and open a ConversationViewer overlay. The createViewerKeys call is optional; the overlay is centered with 90% width and a max height based on VIEWPORT_HEIGHT_PCT. ```ts import { ConversationViewer, VIEWPORT_HEIGHT_PCT } from "@weshipwork/pi-subagents/src/ui/conversation-viewer.js"; import { createViewerKeys } from "@weshipwork/pi-subagents/src/ui/viewer-keys.js"; const keys = createViewerKeys(keybindings); // optional await ctx.ui.custom( (tui, theme, kb, done) => new ConversationViewer(tui, session, record, activity, theme, done, onStop, kb), { overlay: true, overlayOptions: { anchor: "center", width: "90%", maxHeight: `${VIEWPORT_HEIGHT_PCT}%` } }, ); ``` -------------------------------- ### Usage example for runAgent, steerAgent, getAgentConversation Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-runner.md Shows how to run an agent with runAgent, then conditionally steer it with steerAgent and retrieve the conversation with getAgentConversation. The example imports from '@weshipwork/pi-subagents/src/agent-runner.js' and uses options like pi, agentId, maxTurns, cwd, and callbacks onToolActivity and onTextDelta. ```TypeScript import { runAgent, steerAgent, getAgentConversation } from "@weshipwork/pi-subagents/src/agent-runner.js"; const { responseText, session, aborted, steered } = await runAgent(ctx, "Explore", "Find the API routes", { pi, agentId: "a1b2c3d4", maxTurns: 20, cwd: "/workspace/myapp", onToolActivity: (a) => console.log(a.type, a.toolName), onTextDelta: (delta) => process.stdout.write(delta), }); if (!aborted && !steered) { await steerAgent(session, "Now check the auth code too"); const conversation = getAgentConversation(session); console.log(conversation); } ``` -------------------------------- ### Spawn a sub-agent Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Example of using the Agent tool to spawn a sub-agent. ```text Agent({ subagent_type: "Explore", prompt: "Find all files that handle authentication", description: "Find auth files", run_in_background: true, }) ``` -------------------------------- ### Pin exact npm version with pi install Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herdr/README.md Pins an exact npm version for installation. ```sh pi install npm:@weshipwork/pi-herdr@0.1.0 ``` -------------------------------- ### Use local checkout with pi install and pi -e Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herdr/README.md Uses a local checkout of the package for installation and execution. ```sh pi install ./packages/pi-herdr ``` ```sh pi -e ./packages/pi-herdr/extensions/herdr.ts ``` -------------------------------- ### Usage example for createMirrorEventHub Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/mirror.md Shows how to create a mirror event hub, subscribe to events, publish a status event, and unsubscribe. The listener logs agent snapshot details when an `AGENT_SNAPSHOT` event is received. ```typescript import { createMirrorEventHub, agentRecordToMirrorSnapshot, PI_SUBAGENTS_MIRROR_EVENT_TYPE } from "@weshipwork/pi-subagents/src/mirror.js"; const hub = createMirrorEventHub(() => manager.listAgents()); const unsubscribe = hub.subscribeToMirrorEvents((event) => { if (event.type === PI_SUBAGENTS_MIRROR_EVENT_TYPE.AGENT_SNAPSHOT) { console.log(event.agent.id, event.agent.status, event.agent.assistantText.length, "chars"); } }); hub.publish({ type: PI_SUBAGENTS_MIRROR_EVENT_TYPE.STATUS, agentId: "abc", status: "running" }); unsubscribe(); ``` -------------------------------- ### Usage example for spawning an agent via RPC Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/rpc.md Shows how to emit a spawn RPC request and listen for the reply. Uses crypto.randomUUID() for requestId and subscribes to the reply channel before emitting. ```typescript import { crypto } from "node:crypto"; import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; export default function (pi: ExtensionAPI) { const requestId = crypto.randomUUID(); const unsubscribe = pi.events.on(`subagents:rpc:spawn:reply:${requestId}`, (raw: unknown) => { unsubscribe(); const reply = raw as { success: boolean; data?: { id: string }; error?: string }; if (!reply.success) { console.error(`spawn failed: ${reply.error}`); return; } console.log(`spawned agent ${reply.data?.id}`); }); pi.events.emit("subagents:rpc:spawn", { requestId, type: "general-purpose", prompt: "Do something useful", options: { description: "My task", run_in_background: true, model: "anthropic/claude-haiku-4-5-20251001", // string model accepted cwd: "/workspace/myapp", }, }); } ``` -------------------------------- ### Global subagents.json defaults example Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/configuration.md Example global defaults for the pi-subagents settings file. Missing file falls back to defaults; malformed JSON logs '[pi-subagents] Ignoring malformed settings at : ' on stderr and uses defaults; out-of-range values are dropped per-field. ```json { "maxConcurrent": 16, "graceTurns": 10 } ``` -------------------------------- ### Use a local checkout of pi-subagents and pi-herd Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herd/README.md Installs from local package paths and runs with local source files. ```sh pi install ./packages/pi-subagents pi install ./packages/pi-herd pi -e ./packages/pi-subagents/src/index.ts -e ./packages/pi-herd/extensions/herd.ts ``` -------------------------------- ### Run root-level package commands Source: https://github.com/weshipwork/threeonefour/blob/main/AGENTS.md Run from the repo root. Installs dependencies and runs all package checks, typechecks, and tests where present. ```sh pnpm install pnpm check # all package checks where present pnpm typecheck # all package typechecks where present pnpm test # all package tests where present ``` -------------------------------- ### spawn(pi, ctx, type, prompt, options): string Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-manager.md Spawns a new agent. Validates the working directory, generates a unique ID, creates a record, and queues or starts the agent. Throws on invalid cwd or strict worktree failure. ```APIDOC ## spawn(pi, ctx, type, prompt, options): string ### Description Spawns a new agent. Validates the working directory, generates a unique ID, creates a record, and queues or starts the agent. Throws on invalid cwd or strict worktree failure. ### Method spawn ### Signature `spawn(pi: ExtensionAPI, ctx: ExtensionContext, type: SubagentType, prompt: string, options: SpawnOptions): string` ### Parameters - **pi** (ExtensionAPI) - Required - The extension API instance. - **ctx** (ExtensionContext) - Required - The extension context. - **type** (SubagentType) - Required - The type of subagent to spawn. - **prompt** (string) - Required - The prompt for the agent. - **options** (SpawnOptions) - Required - Spawn options, including `isBackground` and `cwd`. ### Return string - The generated agent ID (17-character random UUID). ### Throws - Invalid `cwd` or strict worktree failure. The record is deleted on throw. ``` -------------------------------- ### Manage installed Pi packages Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herd/README.md Lists, updates, and removes Pi packages. ```sh pi list pi update --extensions pi update npm:@weshipwork/pi-herd pi remove npm:@weshipwork/pi-herd ``` -------------------------------- ### Pin exact npm versions Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Pins exact npm versions for reproducible installs. ```sh pi install npm:@weshipwork/pi-herdr@0.1.0 pi install npm:@weshipwork/pi-subagents@0.10.3-mirror.0 pi install npm:@weshipwork/pi-herd@0.1.0 ``` -------------------------------- ### Set Global Defaults for Max Concurrency and Grace Turns Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Bash commands to create ~/.pi/agent/subagents.json with maxConcurrent 16 and graceTurns 10, setting global defaults that every project starts with. Use the menu to override per project. ```bash mkdir -p ~/.pi/agent cat > ~/.pi/agent/subagents.json <<'EOF' { "maxConcurrent": 16, "graceTurns": 10 } EOF ``` -------------------------------- ### SpawnOptions interface Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-manager.md Interface for options accepted by spawn and spawnAndWait. Includes fields for model, maxTurns, isolation, thinking level, background/queue behavior, cwd, signal, and callbacks for tool activity, text deltas, session creation, turn end, usage, and compaction. Key semantics: isBackground uses concurrency limit and may queue; bypassQueue starts immediately; cwd is validated eagerly and at start; signal aborts subagent. ```ts interface SpawnOptions { description: string; model?: Model; maxTurns?: number; isolated?: boolean; inheritContext?: boolean; thinkingLevel?: ThinkingLevel; isBackground?: boolean; bypassQueue?: boolean; isolation?: IsolationMode; cwd?: string; invocation?: AgentInvocation; signal?: AbortSignal; onToolActivity?: (activity: ToolActivity) => void; onTextDelta?: (delta: string, fullText: string) => void; onSessionCreated?: (session: AgentSession) => void; onTurnEnd?: (turnCount: number) => void; onAssistantUsage?: (usage: { input: number; output: number; cacheWrite: number }) => void; onCompaction?: (info: CompactionInfo) => void; } ``` -------------------------------- ### Usage example: loadSettings and saveSettings Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/settings.md Shows how to load and save settings using the pi-subagents settings module. loadSettings returns a merged view, and saveSettings returns true if persisted to .pi/subagents.json, otherwise warns about session-only settings. ```typescript import { loadSettings, saveSettings } from "@weshipwork/pi-subagents/src/settings.js"; console.log(loadSettings("/workspace/myapp")); // merged view if (saveSettings({ maxConcurrent: 16, graceTurns: 10 }, "/workspace/myapp")) { console.log("persisted to .pi/subagents.json"); } else { console.warn("session-only settings"); } ``` -------------------------------- ### createMirrorEventHub Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/mirror.md Builds a mirror event hub with a listener set. The hub provides listMirrorSnapshots() to get the current snapshots, subscribeToMirrorEvents(listener) to add a listener and return an unsubscribe function, and publish(event) to fan out events to all listeners. ```APIDOC ## Function: createMirrorEventHub ### Description Creates a PiSubagentsMirrorHub instance that manages a set of listeners and provides methods to list snapshots, subscribe to events, and publish events to all subscribers. ### Signature ```ts createMirrorEventHub(listRecords: () => readonly AgentRecord[]): PiSubagentsMirrorHub ``` ### Parameters - **listRecords** (function) - Required - A function that returns the current list of AgentRecord objects. ### Returns - **PiSubagentsMirrorHub** - The hub object implementing the mirror service interface. ### Methods - **listMirrorSnapshots()** - Returns a readonly array of PiSubagentsMirrorSnapshot by mapping the listRecords() result through agentRecordToMirrorSnapshot. - **subscribeToMirrorEvents(listener)** - Adds a listener (PiSubagentsMirrorListener) to the listener set and returns a function to unsubscribe. - **publish(event)** - Fans out the given PiSubagentsMirrorEvent to all listeners asynchronously, catching and ignoring errors per listener. ### Usage Example ```ts const hub = createMirrorEventHub(() => manager.listAgents()); const unsubscribe = hub.subscribeToMirrorEvents((event) => { // handle event }); hub.publish({ type: PI_SUBAGENTS_MIRROR_EVENT_TYPE.STATUS, agentId: "abc", status: "running" }); unsubscribe(); ``` ``` -------------------------------- ### Usage example: GroupJoinManager Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/group-join.md Shows how to create a GroupJoinManager with a callback that logs partial/full batch and record descriptions, register a group, feed completions, and dispose. Expected return values are shown in comments: 'held' for grouped agents, 'pass' for ungrouped, 'delivered' for the completion that triggers the callback. ```ts import { GroupJoinManager } from "@weshipwork/pi-subagents/src/group-join.js"; const join = new GroupJoinManager((records, partial) => { console.log(partial ? "partial batch" : "full batch", records.map((r) => r.description)); }, 30_000); join.registerGroup("batch-1", ["a1", "a2", "a3"]); console.log(join.onAgentComplete(recordA1)); // "held" console.log(join.onAgentComplete(recordUngrouped)); // "pass" console.log(join.onAgentComplete(recordA2)); // "held" console.log(join.onAgentComplete(recordA3)); // "delivered" → callback fires once for all three join.dispose(); ``` -------------------------------- ### Spawn and poll a subagent via RPC Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-subagents-tools.md Use this TypeScript example inside a Pi extension to listen for subagent readiness and completion events, then spawn a subagent via the RPC bus. It emits a spawn request with a unique requestId and handles the reply on a scoped channel. ```TypeScript // Inside another Pi extension, spawn + poll a subagent via the global facade, // or via the RPC bus (see ./rpc.md). Direct event-bus example: import { defineTool, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; export default function (pi: ExtensionAPI) { // wait for readiness, then listen for lifecycle activity pi.events.on("subagents:ready", () => { pi.events.on("subagents:completed", (data) => { const { id, description, tokens } = data as { id: string; description: string; tokens?: { total: number } }; console.log(`[demo] agent ${description} (${id}) used ${tokens?.total ?? 0} tokens`); }); // fire-and-forget spawn via RPC (reply arrives on scoped channel) const requestId = crypto.randomUUID(); pi.events.on(`subagents:rpc:spawn:reply:${requestId}`, (reply) => { if (!reply.success) console.error(`spawn failed: ${reply.error}`); }); pi.events.emit("subagents:rpc:spawn", { requestId, type: "Explore", prompt: "Find all files handling authentication", options: { description: "Find auth files", run_in_background: true }, }); }); } ``` -------------------------------- ### Register custom agents and inspect agent types Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-registry.md Registers custom agents from a directory and queries available types and agent configuration. The example logs the available agent types and checks if the "auditor" agent uses persistent memory. ```ts import { loadCustomAgents } from "@weshipwork/pi-subagents/src/custom-agents.js"; import { registerAgents, getAvailableTypes, getAgentConfig } from "@weshipwork/pi-subagents/src/agent-types.js"; registerAgents(loadCustomAgents("/workspace/myapp")); console.log(getAvailableTypes()); // ["general-purpose", "Explore", "Plan", ...custom] const cfg = getAgentConfig("auditor"); if (cfg?.memory === "project") { console.log("auditor uses persistent memory"); } ``` -------------------------------- ### Type definitions and AgentManager class constructor Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-manager.md Defines callback types and the AgentManager class constructor. Constructor accepts onComplete, maxConcurrent (default 4), onStart, and onCompact. Starts an unref'ed 60-second cleanup interval removing records older than 10 minutes. Note: default max concurrent is 4, and completed records are kept for resume until cleanup. ```ts export type OnAgentComplete = (record: AgentRecord) => void; export type OnAgentStart = (record: AgentRecord) => void; export type OnAgentCompact = (record: AgentRecord, info: CompactionInfo) => void; export type CompactionInfo = { reason: "manual" | "threshold" | "overflow"; tokensBefore: number }; export class AgentManager { constructor( onComplete?: OnAgentComplete, maxConcurrent = DEFAULT_MAX_CONCURRENT, onStart?: OnAgentStart, onCompact?: OnAgentCompact, ) { ... } ``` -------------------------------- ### Tool denylist frontmatter YAML: disallowed_tools Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Frontmatter YAML block that blocks specific tools from an agent, even if provided by extensions. This example disallows 'write' and 'edit' tools. ```yaml --- tools: read, bash, grep, write disallowed_tools: write, edit --- ``` -------------------------------- ### Ping subagents extension (subagents:rpc:ping) Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Use a unique request ID and listen on the reply channel to check if the extension is loaded and get the protocol version. ```typescript const requestId = crypto.randomUUID(); const unsub = pi.events.on(`subagents:rpc:ping:reply:${requestId}`, (reply) => { unsub(); if (reply.success) console.log("Protocol version:", reply.data.version); }); pi.events.emit("subagents:rpc:ping", { requestId }); ``` -------------------------------- ### herdr error handling example: invalid or forbidden actions throw Errors Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herdr.md Pane actions throw plain Error objects that surface as tool failures. The lines show missing required field ('pane' is required for run), refusing to close the pane pi is running in, and targeting a wrong entity type (run targets panes, not workspaces). The fallback error is 'Unknown action: ' when neither workspace nor pane action handler matches. ```ts herdr({ action: "run", command: "pnpm test" }); // → Error: 'pane' is required for run herdr({ action: "stop", pane: paneIdOfCurrentPiSession }); // → Error: Refusing to close the pane pi is running in. herdr({ action: "run", pane: "nope", workspace: "ws-1" }); // → Error: run targets panes, not workspace... ``` -------------------------------- ### Run both packages for local development from this repository Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.mirror.md Run @weshipwork/pi-subagents and @weshipwork/pi-herd for local development from this repository using the -e flag with local paths. ```sh pi -e ./packages/pi-subagents/src/index.ts -e ./packages/pi-herd/extensions/herd.ts ``` -------------------------------- ### clearCompleted(skipUnconsumed = false): void Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-manager.md Removes terminal records immediately. Called on session start or switch. ```APIDOC ## clearCompleted(skipUnconsumed = false): void ### Description Removes terminal records immediately. Called on session start or switch. ### Method clearCompleted ### Signature `clearCompleted(skipUnconsumed = false): void` ### Parameters - **skipUnconsumed** (boolean) - Optional - If `true`, skips records that have not been consumed. ### Return void ``` -------------------------------- ### Run pi-herd-viewer for local debugging Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herd/README.md Launches the viewer binary with a socket and agent ID for local debugging from the repository. ```sh pnpm --dir packages/pi-herd exec tsx bin/pi-herd-viewer.ts --socket /path/to/pi-herd.sock --agent-id ``` -------------------------------- ### Custom Agent Tool Description with Placeholders Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Markdown template for the custom Agent tool description, stored in .pi/agent-tool-description.md (project) or agentDir/agent-tool-description.md (global, project wins). Placeholders: {{typeList}}, {{compactTypeList}}, {{agentDir}}, {{scheduleGuideline}}; unknown placeholders are left verbatim with a stderr warning, missing/empty falls back to 'full'. ```markdown Launch an autonomous agent. Available types: {{typeList}} Custom agents live in .pi/agents/ or {{agentDir}}/agents/. ``` -------------------------------- ### Try extension for one run with pi -e Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herdr/README.md Runs the extension for one Pi run without writing settings. ```sh pi -e npm:@weshipwork/pi-herdr ``` -------------------------------- ### ScheduleChangeEvent, NewJobInput, and SubagentScheduler class declaration Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/schedule.md Defines the union of schedule change events, the input object for creating a new scheduled job, and the start of the SubagentScheduler class. ```typescript export type ScheduleChangeEvent = | { type: "added"; job: ScheduledSubagent } | { type: "removed"; jobId: string } | { type: "updated"; job: ScheduledSubagent } | { type: "fired"; jobId: string; agentId: string; name: string } | { type: "error"; jobId: string; error: string }; export interface NewJobInput { name: string; description: string; schedule: string; subagent_type: SubagentType; prompt: string; model?: string; thinking?: ThinkingLevel; max_turns?: number; isolated?: boolean; isolation?: IsolationMode; } export class SubagentScheduler { ``` -------------------------------- ### Discovery - subagents:ready Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Listen for the 'subagents:ready' event to know when RPC handlers are available. ```APIDOC ## Event: subagents:ready ### Description Listen for this event to know when RPC handlers are registered and safe to call. ### Event Name `subagents:ready` ### Usage ```typescript pi.events.on("subagents:ready", () => { // RPC handlers are registered — safe to call ping/spawn/stop }); ``` ``` -------------------------------- ### Agent Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Launch a sub-agent with various configuration options. ```APIDOC ## Agent ### Description Launch a sub-agent to perform a task. ### Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `prompt` | string | yes | The task for the agent | | `description` | string | yes | Short 3-5 word summary (shown in UI) | | `subagent_type` | string | yes | Agent type (built-in or custom) | | `model` | string | no | Model — `provider/modelId` or fuzzy name (`"haiku"`, `"sonnet"`) | | `thinking` | string | no | Thinking level: off, minimal, low, medium, high, xhigh | | `max_turns` | number | no | Max agentic turns. Omit for unlimited (default) | | `run_in_background` | boolean | no | Run without blocking | | `resume` | string | no | Agent ID to resume a previous session | | `isolated` | boolean | no | No extension/MCP tools | | `isolation` | `"worktree"` | no | Run in an isolated git worktree | | `inherit_context` | boolean | no | Fork parent conversation into agent | ``` -------------------------------- ### Try packages for one Pi run Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Tries the packages for one Pi run without writing settings. ```sh pi -e npm:@weshipwork/pi-herdr pi -e npm:@weshipwork/pi-subagents pi -e npm:@weshipwork/pi-herd ``` -------------------------------- ### Try mirror mode for one Pi run without writing settings Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-herd/README.md Runs Pi with the two packages loaded for a single run without persisting settings. ```sh pi -e npm:@weshipwork/pi-subagents -e npm:@weshipwork/pi-herd ``` -------------------------------- ### Exported symbols from extensions/herd.ts Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herd.md Lists the exported constants, types, and functions from the extension entry point. Includes the observation source key, mirror service key, resolver type, and the main functions for installing, resolving, and creating the extension. ```typescript export const PI_HERD_OBSERVATION_SOURCE_KEY = "__piHerdObservationSource"; export const PI_SUBAGENTS_MIRROR_SERVICE_KEY = "__piSubagentsMirrorService"; export type MirrorObservationSourceResolver = () => MirrorObservationSource | undefined; export function installPiHerdObservationSource(source: MirrorObservationSource): void export function resolveGlobalObservationSource(): MirrorObservationSource | undefined export function createPiHerdExtension(resolveSource: MirrorObservationSourceResolver = resolveGlobalObservationSource) export default createPiHerdExtension(); ``` -------------------------------- ### Repository layout Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Shows the top-level directory structure of the repository, including the packages/ directory with pi-herdr, pi-herd, and pi-subagents, and the root package.json for workspace scripts. ```text . ├─ packages/ │ ├─ pi-herdr/ # Herdr tool extension │ ├─ pi-herd/ # Transcript mirror runtime and viewer │ └─ pi-subagents/ # Subagents fork with mirror observation support └─ package.json # Workspace scripts ``` -------------------------------- ### MirrorServer options and constructor Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/pi-herd.md Defines the options interface and class constructor for the MirrorServer. The socketPath option specifies the Unix socket path for the server. ```ts export interface MirrorServerOptions { socketPath: string; } export class MirrorServer { constructor(private readonly options: MirrorServerOptions) {} ``` -------------------------------- ### FleetView navigable list Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Renders below the editor while subagents run. Lists agents, shows keyboard shortcuts and agent details. Use arrow keys with empty prompt to focus and navigate. ```text esc to interrupt · ← for agents · ↓ to manage ⏺ main ◯ general-purpose Sleep then report 1 11s · ↓ 13.1k tokens ◯ general-purpose Sleep then report 2 11s · ↓ 13.1k tokens ↓ 3 more ``` -------------------------------- ### Listen for subagents:ready event Source: https://github.com/weshipwork/threeonefour/blob/main/packages/pi-subagents/README.md Subscribe to the 'subagents:ready' event to know when RPC handlers are available before calling ping, spawn, or stop. ```typescript pi.events.on("subagents:ready", () => { // RPC handlers are registered — safe to call ping/spawn/stop }); ``` -------------------------------- ### loadCustomAgents function signature Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-registry.md Loads custom agents from project and global directories. Discovery priority: project /.pi/agents/*.md, then global $PI_CODING_AGENT_DIR/agents/*.md (default ~/.pi/agent/agents/*.md). Parses frontmatter with pi's parseFrontmatter; body becomes systemPrompt. ```ts export function loadCustomAgents(cwd: string): Map ``` -------------------------------- ### buildAgentPrompt interface and function signature Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/prompting.md Defines the PromptExtras interface and the buildAgentPrompt function signature. The function builds a system prompt for a pi coding agent sub-agent, with modes 'replace' and 'append'. In 'replace' mode, it outputs an active agent tag and a header. In 'append' mode, it prepends the parent system prompt verbatim for KV cache reuse, then adds a sub-agent context bridge and optional agent instructions wrapper. ```typescript export interface PromptExtras { memoryBlock?: string; skillBlocks?: { name: string; content: string }[]; } export function buildAgentPrompt( config: AgentConfig, cwd: string, env: EnvInfo, parentSystemPrompt?: string, extras?: PromptExtras, ): string ``` -------------------------------- ### resumeAgent(session, prompt, options = {}) → Promise Source: https://github.com/weshipwork/threeonefour/blob/main/_autodocs/api-reference/agent-runner.md Resumes an agent session with a new prompt, firing the same event callbacks as runAgent and returning the assistant's text response. ```APIDOC ## resumeAgent(session, prompt, options = {}) → Promise ### Description Resumes an agent session with a new prompt, firing the same event callbacks (onToolActivity, onAssistantUsage, onCompaction, signal) and returns the assistant text. ### Method Function ### Signature resumeAgent(session, prompt, options = {}) → Promise ### Parameters - **session** (Session) - Required - The agent session to resume. - **prompt** (string) - Required - The new prompt to send to the agent. - **options** (object) - Optional - Options object, same as runAgent options. ### Returns - **Promise** - The assistant's text response. ### Example ```ts const responseText = await resumeAgent(session, "Continue with the next task"); ``` ``` -------------------------------- ### Launch pi-herd-viewer manually Source: https://github.com/weshipwork/threeonefour/blob/main/README.md Launches a viewer manually for debugging. Requires the socket path and the subagent ID. Transcript mirrors are observation surfaces only; steering and aborting remain owned by pi-subagents tools and UI. ```sh pi-herd-viewer --socket /path/to/pi-herd.sock --agent-id ```