@ferris1225/pi-subagents
A managed sub-agent team for pi: research, implementation, independent review, interactive follow-ups, and Git worktree isolation.
Package details
Install @ferris1225/pi-subagents from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@ferris1225/pi-subagents- Package
@ferris1225/pi-subagents- Version
6.0.1- Published
- Oct 29, 2026
- Downloads
- 3,315/mo · 1,743/wk
- Author
- ferris1225
- License
- MIT
- Types
- extension
- Size
- 539.5 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-subagents
Sub-agents for Pi: research, implementation, dependency workflows, and Git worktree isolation.
Install
Requires Pi >= 1.4.0 and Node.js >= 22.19.0. Development and native integration tests use the Pi 1.4.0 SDK.
pi install npm:@ferris1225/pi-subagents
Run /subagents-setup for a role selector and focused settings editor. Wide
terminals place them side by side; narrow terminals stack them. ↑/↓ changes the
role, ←/→ selects Model, Thinking, or Reset, and Enter edits it.
The selected role shows its full model reference, effective reasoning level,
requested level when clamped, and default/override source. Each selection saves
immediately; Esc returns without applying a picker selection and keeps focus.
Model pickers support search, paste, and paging. On short terminals, PgUp/PgDn
scrolls the settings while the selected role and field stay pinned. Setup
reserves space for the workflow's required-acceptance row.
All roles follow the main model by default; thinking defaults to low for scout
and high for artisan, sentinel, and skeptic. The panel distinguishes defaults from overrides and
shows the effective level when model capabilities clamp a preference. Changing
a model preserves the thinking preference. Settings live in
~/.pi/agent/pi-subagents.json as agentModels and agentThinkingLevels.
Agents
| Agent | Use for | Access |
|---|---|---|
scout |
Code, documentation, and web research with citations | Read-only tools; no commands or edits |
artisan |
Implementation and fixes with tests and checks | Parent's tool surface, including codemode |
sentinel |
Inspect an implementation or diff against requirements and callers | Parent's tool surface; instructed not to edit |
skeptic |
Test a named claim, assumption, or review finding with counterexamples | Parent's tool surface; instructed not to edit |
The main model chooses from these role descriptions; names alone do not route a
task. Use sentinel for "inspect this diff" and skeptic for "does this claim
hold?" Default to one review role. Both are justified only by distinct questions, such as
reviewing an implementation and then testing its specific findings. A skeptic
without a named claim reports the gap and stops instead of starting another review.
Sentinel and skeptic may run focused checks, so their no-edit boundary is an instruction, not a tool-enforced restriction. Change reviews focus on introduced defects; a wider audit needs an explicit brief. All roles reuse existing facts and valid checks, filling gaps rather than repeating main or upstream work.
Only scout, artisan, sentinel, and skeptic are valid runtime role names.
Existing model/thinking settings and interrupted run records migrate on load
and are saved with the new names. Explicit valid settings under the new names
win. Custom roles and user-defined workflows are not supported. Retained records
from older releases remain available for recovery.
Children receive a self-contained brief and project instructions, but no parent conversation. They cannot delegate or release. Main owns planning, integration, and the final result. Keep a fix and its regression tests with one owner.
Delegate
Pi proactively looks for useful bounded phases to delegate; no special request is required. Focused ownership, isolated context, parallel progress, and an independent check can each justify a child. A substantial self-contained fix can go to one artisan together with its regression tests, even when there is nothing to parallelize. Quick source checks and small understood edits stay in main. Choose team size from independent work. Explicit requests to work in main or avoid subagents take precedence.
Use one owner per deliverable, including its regression tests. Brief the child with the outcome, done condition, relevant paths, established evidence, write boundaries, required checks, and a compact expected result. Scout retrieves sources; artisan implements, while sentinel and skeptic can execute focused checks. This policy applies the context-isolation, focused-role, and coordination-cost guidance in the official Codex subagents and Claude Code subagents docs to Pi's one-shot leaf runs.
A review request produces findings. Main applies fixes when changes are authorized and requests focused confirmation only when material uncertainty remains. Before reporting success, main checks each done condition and any blockers in the child's answer as well as the integrated diff.
Ask Pi to delegate explicitly, or call the tools directly:
subagent({
agent: "artisan",
phaseId: "cache-fix",
task: "Fix cache invalidation in src/cache, add regression tests, and run the checks.",
scope: { paths: ["src/cache", "test/cache.test.ts"] },
});
Independent tasks can run together:
subagent({
tasks: [
{
agent: "artisan",
phaseId: "config-fix",
task: "Fix config validation and its regression tests.",
scope: { paths: ["src/config.ts", "test/config.test.ts"] },
},
{
agent: "artisan",
phaseId: "provider-docs",
task: "Update docs/providers.md from the established API citations.",
scope: { paths: ["docs/providers.md"] },
},
],
});
Use wait: true when the next step needs the result. subagent,
subagent_workflow, and completed-run subagent_message follow-ups default to
waiting in one-shot pi -p / JSON sessions, so the parent stays alive until the
work finishes. TUI and RPC sessions default to background delivery; wait: false
explicitly selects it in any mode. Each result is delivered once, after
integration, either in the waiting tool call or as a background completion.
Awaited failures are tool errors with retained evidence.
A launch receipt only confirms delegation. Main continues independent work or
pauses until the completion wakes it, then finishes the requested outcome and
final checks. It does not poll or treat a successful launch as task completion.
Use stable phaseId values: completed phases stay owned for the parent session,
and interrupted phases retain ownership across reloads. Equal normalized tasks
in the same cwd are also rejected, even with a different phaseId. Reuse the
result, or use subagent_message for an additional bounded step.
Ownership includes main, individual runs, and workflow nodes still waiting on
dependencies. Main continues only disjoint work and passes its completed research
and checks into the child brief. Pending graph nodes reserve their declared write
scopes; external conflicts reject a batch or graph before any child starts.
Main edit/write calls, including nested calls through codemode, are blocked
on those scopes. In-flight main writes also prevent conflicting dispatches.
Stopped writers keep their claims until execution and integration finish.
These checks use declared phase identity and exact paths/symbols. Main file writes
conservatively conflict with any claimed symbol in that file. Omitted scopes,
arbitrary shell/custom-tool effects, symlink aliases, and differently worded work
without a shared phase id cannot be inferred reliably; this is coordination,
not a sandbox or semantic duplicate detector. Use subagent_status to inspect
phase/scope ownership; an exact run id also retrieves its retained result for reuse.
Workflows
subagent_workflow runs a built-in plan with named task inputs. Its only source
is the catalog in templates.ts: no inline nodes,
file, custom graph name, user directory, or project directory is loaded.
The model's routing rules are embedded in prompt.ts,
so no separate workflow skill needs to be loaded.
| Workflow | Work before acceptance | Required inputs |
|---|---|---|
code-review |
Sentinel inspects the target and produces supported findings | TARGET |
research |
Three scouts investigate first-party sources, practice, and the repository; a fourth synthesizes the answer | QUESTION |
migration |
Two artisans implement disjoint slices; an integrated gate checks and fixes their combined result | TARGET, CONTRACT, CORE_CHANGE, ADAPTER_CHANGE, CORE_SCOPE, CORE_TEST_SCOPE, ADAPTER_SCOPE, ADAPTER_TEST_SCOPE |
subagent_workflow({
workflow: "code-review",
inputs: { TARGET: "HEAD~1..HEAD; inspect the cache invalidation fix" },
wait: true,
});
subagent_workflow({
workflow: "research",
inputs: { QUESTION: "How should this repository invalidate its HTTP cache?" },
});
Migration inputs must name the shared interface contract, both slice briefs, and exact write paths. Each slice owns its implementation and regression tests; shared paths are rejected before any child starts. The integrated gate waits for both slices and can edit their combined scope. For example:
subagent_workflow({
workflow: "migration",
inputs: {
TARGET: "the version 2 cache API",
CONTRACT: "docs/cache-v2.md",
CORE_CHANGE: "Update storage and its invalidation rules",
ADAPTER_CHANGE: "Update HTTP callers to the new interface",
CORE_SCOPE: "src/core",
CORE_TEST_SCOPE: "test/core",
ADAPTER_SCOPE: "src/adapters",
ADAPTER_TEST_SCOPE: "test/adapters",
},
});
Choose a built-in workflow when its fixed phases fit the task. For one bounded
phase use subagent; for independent work use subagent({ tasks: [...] }).
If research must determine the next task or its scope, run it first and decide
in main. Missing, unknown, or unused template inputs are rejected with the exact
parameter names before a child starts. Task inputs remain literal, including
{{...}} text.
Every workflow ends with an independent sentinel acceptance officer. The runtime adds this node, waits until all work has settled and integrated, and passes a bounded evidence brief plus the complete report. Failed and blocked branches are included. The officer reviews the delivered outcome, reuses valid checks, and may run focused checks to close evidence gaps. It does not edit or release. A successful code review can report defects in the target; acceptance judges the accuracy and completeness of that review.
The final answer must end with WORKFLOW_ACCEPTANCE: PASS or
WORKFLOW_ACCEPTANCE: FAIL. A missing, ambiguous, malformed, or negative verdict
fails the workflow even when the reviewer process exits normally. A PASS cannot
clear failures in earlier work. Explicit cancellation or session interruption
stops the graph without starting acceptance. The graph sends one final summary
containing its acceptance result, or returns it in the tool call with wait: true.
Waiting includes integration and acceptance, streams progress, and stops owned
work on parent cancellation without a background wake-up. Main still owns
remediation, the final gate, and release.
Phase identity includes the built-in plan and its inputs. The same deliverable remains owned within its workspace; different questions or targets can run in the same session. Inspect retained results instead of repeating completed work.
Status, cancellation, and recovery
| Tool | Use |
|---|---|
subagent_status({ id: 12 }) |
Inspect a run's progress, result, and recovery paths |
subagent_status({ workflow: 3 }) |
Inspect graph nodes and dependencies |
subagent_message({ id: 12, message: "Check the caller too" }) |
Steer a running child, or continue a completed run using its session when available and a summary otherwise |
subagent_message({ id: 12, message: "Add the test", context: "summary" }) |
Start a new next step with only a bounded summary of the earlier run |
subagent_stop({ id: "12" }) |
Stop a run and retire its retained session |
subagent_stop({ workflow: 3 }) |
Stop a graph and finalize its active nodes |
subagent_stop({ all: true }) |
Stop all active runs and graphs |
The widget is a terminal task board capped at 10 lines: a quiet overview,
workflow identity and work progress, then task rows with status/time at the
right. Failures and blocked reasons get space before optional telemetry; narrow
terminals keep task identity visible. Model, thinking, token usage, and worktree
state appear as secondary detail. Each workflow has a separate Acceptance
required row showing pending, running, PASS, or FAIL. Acceptance does not
inflate the ordinary work count or hidden-task total. Completed work collapses
into progress while acceptance is pending; a successfully accepted workflow
hides automatically. Failed or blocked work stays until the next dispatch.
Completion messages and status lookups retain the results. Overflow reports
hidden tasks. Runs preparing their child process show starting. The refresh
timer runs only while visible active work needs it. There is no process-count
limit or shared-checkout startup lock: independent runs start together, including
separate dispatch calls while another call awaits results.
Usually omit isolation: implementation tasks use detached Git worktrees in
single calls, parallel batches, and workflows. Reading and review use the current
directory. Without a Git repository or committed HEAD, automatic isolation uses
the caller's directory and reports why. Unexpected setup or integration failures
remain failures; an explicit isolation: "worktree" requires isolation and never
falls back. isolation: "shared" is an advanced override for tasks that need to
write directly in the caller's checkout.
Each worktree starts from the caller's current tracked files and non-ignored
untracked files, including uncommitted changes. Its initial snapshot is also the
integration base, so dependent tasks see earlier results without reapplying them.
The caller's index, branch, and HEAD stay unchanged. Declare exact write paths
or symbols in scope to detect conflicts. Worktrees isolate Git changes, not
tool permissions. Independent tasks start together; only the final application
of worktree changes to the original checkout is serialized. Integration leaves
your index untouched, and failures retain recovery artifacts.
Cancelling the parent run with Escape stops unfinished work without waking the
parent. A cancellation receipt is supplied on the next user turn with the stopped
run and workflow ids, so main knows no additional subagent_stop is needed.
Cancelled work must not restart automatically. A stopped run keeps its phase
and declared writer leases until its child and Git finalization quiesce, even if
the stop call reaches its wait deadline. Conversation-tree navigation also
stops unfinished work. New/resume/fork/reload ends old children and retains interrupted work
for manual recovery. Runs do not resume automatically; main finishes incomplete
work from partial changes and artifacts.
A steering call waits for the child's existing RPC channel to acknowledge the
matching request ID. The tool card shows Received · queued when Pi confirms
queueing, Received · handled when an input hook consumes the message, or
Accepted · queue state unconfirmed when no disposition is available.
subagent_status retains the latest acknowledgement, request ID, age, and message
summary. Rejection or a missing acknowledgement is an error, not a receipt.
Queueing delivers at a Pi steering boundary; it does not prove that the model
has executed the instruction.
To continue a successfully completed run, choose the context that fits the follow-up:
context: "auto"(default) continues a private copy of the retained session when available. If cleanup has removed it, the follow-up starts with a bounded summary and explicitly reports that full history is unavailable. No retry is needed for an expired session.context: "session"requires full history for rework that depends on earlier details. If the session is unavailable, the call fails without starting a run.context: "summary"always starts fresh for a new next step, with the earlier objective, final result and touched files. It cannot rely on omitted details or reuse the earlier provider cache.
Session continuations retain the earlier history and provider prompt-cache key
(sessionId). Their private copy is bound to the new run's working directory,
including when a previous temporary worktree has already been removed. Child
startup and the copied session header use the same physical directory, so macOS
path aliases and Windows junctions do not trigger a cross-project fork prompt.
The continuation is instructed to re-read files before editing in the current cwd.
Every follow-up preserves the role, workspace and scope and passes through normal
admission and isolation. Set wait: true to receive its final result in the same
call; this waiting option applies to newly started follow-ups, while steering a
running child returns its acknowledgement. subagent_status reports whether a
completed run has a session available or only summary context. Results and summaries remain
available within the current parent runtime; completed runs are not restored
after reload. Pending runs cannot be steered, and fixed workflow graphs cannot
be edited.
Children use Pi's native --mode rpc CLI with piped input/output, retries, and
session persistence. On Windows, console hiding covers the Pi child and Node
process launches made by its tools and extensions, including pi.exec, pwsh,
and powershell. The child preloads this policy before Pi starts and passes it
to Node descendants through NODE_OPTIONS, preserving existing options. An
explicit child extension installs the same policy for runtimes without Node
preloading. Windows launches stay attached so detachment cannot open a console.
On macOS and Linux, the policy leaves shell options unchanged; the Pi child uses
a separate process group for cancellation and does not launch a terminal app.
RPC communication and process-tree cancellation remain active. Child startup
errors are reported as failed runs. If Windows cannot launch taskkill,
termination falls back to killing the child directly. Commands that explicitly
open a terminal or GUI control their own windows.
A settled provider failure can hand off once to the main model in the same
session. State and full-result files live under
~/.pi/agent/ferris-pi-subagents/, grouped by project. PI_CODING_AGENT_DIR
overrides the agent directory.
Pi codemode compatibility
Call subagent, subagent_workflow, and the control tools directly. They use
Pi's model-only exposure and are intentionally unavailable as nested
tools.subagent(...) calls inside codemode. Children can still use codemode
with their inherited callable tools. Indirect tools retain their exposure;
scout promotes approved read-only tools for direct use. It waits up to ten
seconds for startup registration and activates later arrivals between turns.
Read-only classification uses Pi tool metadata.
Child RPC dialogs that require confirmation, selection, or text input are cancelled with a matching response and an explanation, so an unattended child does not hang waiting for an invisible dialog. No confirmation is approved automatically.
Storage and cleanup
Each project root holds sessions/, worktrees/, tmp/ and results/. Startup
hygiene already drops temp leftovers, artifacts whose Pi process is gone, result
files past their retention window, and project roots idle for three days. Parked
recovery work and manifest references are protected during these sweeps.
Interrupted checkpoints expire after 30 days when no recorded owner or child
from the current boot is alive; expired checkpoints are pruned before restore.
Missing session files do not erase validated recovery paths. Unreadable or
malformed manifests leave artifacts intact and skip automatic reclamation;
explicit cleanup reports the error. Startup warns about failed recovery inspection
and continues initializing the progress widget.
Reclamation is automatic: a settlement may trigger one paced sweep (at most every five minutes) that drops dead-owner artifacts, expired result files, and settled session copies older than 30 minutes, then trims the oldest settled sessions until a project fits its 1.5 GB budget. Under budget pressure, settled sessions older than five minutes can be removed. Live runs, parked recovery work, and manifest references remain protected. Automatic follow-ups use the retained summary when a completed run's transcript has expired. Session shutdown waits for cleanup already in progress and prevents new settlement sweeps.
/subagents-cleanup immediately reclaims unclaimed dead-owner artifacts and idle
project roots, reporting usage and freed bytes. /subagents-cleanup dry-run
measures without deleting anything. Session age and budget reclamation runs
automatically on settlement.
Development
Runtime code lives under src/; the package has no skill or workflow resource
directories. Built-in prompts and plans change with the code and its tests.
| Module | Responsibility |
|---|---|
delegation/ |
Built-in roles, parent routing prompt, and phase/scope ownership |
workflow/ |
Built-in templates, parameter validation, scheduling, and mandatory acceptance |
configuration/ |
Model and thinking settings, plus the setup interface |
presentation/ |
Running task board, activity, status, and result formatting |
execution/, lifecycle/, isolation/ |
Child processes, durable state, cancellation, worktrees, and recovery |
npm ci
npm run check
Pushing an unpublished package version to main runs the checks on Windows,
macOS, and Linux before triggering
publishing and a GitHub Release.