# pi-subagents

`pi-subagents` lets Pi delegate work to focused child agents. Use it for code review, scouting, implementation, parallel audits, saved workflows, background jobs, and anything else that benefits from a second or third set of model eyes.

https://github.com/user-attachments/assets/702554ec-faaf-4635-80aa-fb5d6e292fd1

## Installation

```bash
pi install npm:pi-subagents
```

That is the only required step. You can add optional pieces later.

## Try this first

You do not need to create agents, write config, or learn slash commands. After installing, ask Pi for delegation in plain language:

```text
Use reviewer to review this diff.
```

```text
Ask oracle for a second opinion on my current plan.
```

```text
Use scout to understand this code based on our discussion then ask me clarification questions.
```

```text
Run parallel reviewers: one for correctness, one for tests, and one for unnecessary complexity.
```

That is enough to start.

## What happens

Pi is the parent session. A subagent is a focused child Pi session with its own job.

When you ask for a subagent, Pi starts the child, gives it the task, and brings the result back. Foreground runs stream in the conversation. Background runs keep working and can be checked later.

Installing the extension does not start an automatic reviewer in the background. It gives Pi a delegation tool. If you want every implementation reviewed, say that in your prompt or put it in your project instructions:

```text
When you finish implementing, run a reviewer subagent before summarizing.
```

## Good first prompts

These cover most day-to-day use:

```text
Ask oracle for a second opinion on my current plan. Challenge assumptions and tell me what I might be missing.
```

```text
Use oracle to help solve this hard bug. Have it inspect the code and propose the best next move before we edit anything.
```

```text
Run parallel reviewers on this diff. I want one focused on correctness, one on tests, and one on unnecessary complexity.
```

```text
Have worker implement this approved plan. Afterward, run parallel reviewers, summarize their feedback, and apply the fixes that make sense.
```

```text
Run a review loop on this change until reviewers stop finding fixes worth doing, with a max of 3 rounds.
```

```text
Use scout to understand the auth flow, then have planner turn that into an implementation plan.
```

Those are ordinary Pi requests. Pi decides whether to call `subagent`, which agent to use, and whether a chain or parallel run makes sense.

## Common workflows

| Want | Ask naturally |
|------|---------------|
| Get a second opinion | “Ask oracle to review this plan and challenge assumptions.” |
| Solve a hard problem | “Use oracle to investigate this bug before we edit.” |
| Review a diff | “Use reviewer to review this diff.” |
| Run parallel reviewers | “Run reviewers for correctness, tests, and cleanup.” |
| Implement then review | “Implement this, then review it.” |
| Review until clean | “Run a review loop on this change with a max of 3 rounds.” |
| Execute a plan carefully | “Have worker implement this approved plan, then run reviewers and apply the feedback.” |
| Scout before planning | “Use scout to inspect the auth flow before planning.” |
| Run in the background | “Run this in the background.” |
| Browse agents | “Show me the available subagents.” |
| Use a saved workflow | “Run the review chain on this branch.” |
| See running work | “Show active async runs.” or “Show the subagent fleet.” |
| Check setup | “Check whether subagents are configured correctly.” |

The extension ships with builtin agents you can use immediately.

## Builtin agents in plain English

| Agent | Use it when you want... |
|-------|--------------------------|
| `scout` | Fast local codebase recon: relevant files, entry points, data flow, risks, and where another agent should start. |
| `researcher` | Web/docs research with sources: official docs, specs, benchmarks, recent changes, and a concise research brief. |
| `planner` | A concrete implementation plan from existing context. It should read and plan, not edit code. |
| `worker` | Implementation work, including approved oracle handoffs. It edits files, validates, and escalates unapproved decisions instead of guessing. |
| `reviewer` | Code review and small fixes. It checks the implementation against the task/plan, tests, edge cases, and simplicity. |
| `context-builder` | A stronger setup pass before planning: gathers code context and writes handoff material such as `context.md` and `meta-prompt.md`. |
| `oracle` | A second opinion before acting. It challenges assumptions, catches drift, and recommends the safest next move without editing. |
| `delegate` | A lightweight general delegate when you want a child agent that behaves close to the parent session. |

A simple rule of thumb: use `scout` before you understand the code, `researcher` before you trust external facts, `planner` before a bigger change, `worker` to implement, `reviewer` to check, and `oracle` when the decision itself feels risky.

## Changing an agent's model

Builtin agents inherit your current Pi default model by default. This keeps new installs from depending on a provider you may not have configured. If you want every subagent without its own model to use a different default, set `subagents.defaultModel`. If you want a role to use a specific model, set an override instead of copying the bundled agent file.

```json
{
  "defaultModel": "deepseek-v4-pro",
  "subagents": {
    "defaultModel": "deepseek-v4-flash",
    "agentOverrides": {
      "oracle": {
        "model": "deepseek-v4-pro"
      }
    }
  }
}
```

For one run, put the override in the command:

```text
/run reviewer[model=anthropic/claude-sonnet-4:high] "Review this diff"
```

For a persistent override, edit settings. This example pins the reviewer everywhere, adds a backup model for provider failures, and keeps the other builtins on your normal default model:

```json
{
  "subagents": {
    "agentOverrides": {
      "reviewer": {
        "model": "anthropic/claude-sonnet-4",
        "thinking": "high",
        "fallbackModels": ["openai/gpt-5-mini"]
      }
    }
  }
}
```

Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.

If your provider rejects model IDs with thinking suffixes, set `subagents.disableThinking: true` in user or project settings. That clears bundled builtin thinking defaults in one place; an explicit higher-precedence `agentOverrides.<name>.thinking` value can opt a role back in.

To inspect what `pi-subagents` has actually loaded right now, use:

```text
/subagents-models
/subagents-models reviewer
```

That reports the live runtime mapping, which can differ from settings on disk until you reload Pi.

You do not have to spell a model exactly. Model ids are matched fuzzily against the registry, so provider separator variations (`anthropic/claude-sonnet-4`, `anthropic:claude-sonnet-4`, or `anthropic.claude-sonnet-4`), id separator variations (`claude-haiku-4.5` vs `claude-haiku-4-5`), case differences (`Claude-Sonnet-4` vs `claude-sonnet-4`), and optional trailing date stamps (`claude-haiku-4-5-20251001` or `claude-haiku-4-5-2025-10-01` vs `claude-haiku-4-5`) all resolve to the same model. Exact `provider/id` matches still win, and a qualified provider query never silently switches providers — it only matches within the named provider. Ambiguous bare ids that exist under multiple providers still require a provider prefix or the current session's provider to disambiguate.

### Choosing a watchdog model

The subagent watchdog is not the `reviewer` subagent. `subagents.defaultModel` and `subagents.agentOverrides.reviewer` do not configure it. The watchdog is an opt-in adversarial change reviewer, so it should usually use a strong complementary model rather than a cheap/light model.

The watchdog reviews repo edits, not ordinary conversation. It runs at the safe `agent_end` boundary only when the current agent or child writer changed the final repo state since the start of that turn. Multiple edits in one turn are coalesced into one review of the final changed state, unchanged/reverted diffs are skipped, and generated `.pi-subagents/` or `tmp/` artifacts do not trigger review. In orchestrated runs, each writing child can review its own edited worktree, and the parent can still review the aggregate repo diff after child changes are applied.

When the watchdog is enabled, it also checks changed TypeScript and JavaScript files for fresh language-server diagnostics before the model review. It auto-detects `typescript-language-server` from the project `node_modules/.bin` or `PATH`; it never installs tools or scans the whole workspace. LSP errors surface as watchdog blockers, warnings as concerns, and info/hints stay in status details. Slow or missing servers are reported in `/subagents-watchdog status` without blocking the turn or emitting late mid-turn warnings. Configure the bounds with `subagents.watchdog.lsp.enabled`, `timeoutMs`, `maxFiles`, and `maxDiagnostics`.

Use `/subagents-watchdog recommend-model` to ask pi-subagents for the current strong pairing. The current recommendation policy is Opus 4.8 with thinking high or GPT 5.5 with thinking high. If your main session is using one, the watchdog should use the other when that model is authenticated.

```text
/subagents-watchdog recommend-model
/subagents-watchdog session model recommended
/subagents-watchdog model recommended
```

`session model recommended` changes only the current Pi session. `model recommended` saves the recommendation to `~/.pi/agent/settings.json`; it does not turn the watchdog on. Enable it separately with `/subagents-watchdog on` when you want the extra review pass.

You can also set the model explicitly:

```text
/subagents-watchdog model anthropic/claude-opus-4-8:high
/subagents-watchdog model openai-codex/gpt-5.5:high
/subagents-watchdog model inherit
/subagents-watchdog check
```

For settings files, use `subagents.watchdog.main.model` and `subagents.watchdog.main.thinking` for the main watchdog. If `main.model` is omitted, the main watchdog uses the current session model and thinking level. If `main.model` is set without a thinking suffix or `main.thinking`, it runs with thinking off, so prefer `:high` or `"thinking": "high"` for the strong-watchdog pairing.

```json
{
  "subagents": {
    "watchdog": {
      "enabled": true,
      "main": {
        "model": "anthropic/claude-opus-4-8",
        "thinking": "high"
      }
    }
  }
}
```

For child subagent watchdogs, use `subagents.watchdog.children.model` as the default child watchdog model, or `subagents.watchdog.children.overrides.<agent>.model` for a specific child role. Child watchdogs are still opt-in and follow the same edit-gated rule: read-only children do not trigger watchdog reviews, while writer children are reviewed at their own `agent_end` if their worktree changed.

Agents can configure the same values through the tool when you ask them to set up the watchdog:

```ts
subagent({ action: "watchdog.recommend-model" })
subagent({ action: "watchdog.configure", model: "recommended", scope: "session" })
subagent({ action: "watchdog.configure", model: "recommended", scope: "project" })
```

Persistent scopes (`user` or `project`) should only be used when you ask for a lasting default. Otherwise the agent should use `scope: "session"`.

To keep subagents inside a budget or compliance profile, enforce a model scope. Put `subagents.modelScope` in user or project settings (project overrides user):

```json
{
  "subagents": {
    "modelScope": {
      "enforce": true,
      "allow": ["anthropic/*", "openai/gpt-5-*"]
    }
  }
}
```

`allow` is a list of glob patterns matched against the resolved `provider/id` (only `*` is special, case-insensitive). A resolved model that matches none of the patterns is rejected. Models you pass explicitly — the tool-call `model`, `--model`, or a clarify pick — error and abort the run. Models that come from agent frontmatter, `subagents.defaultModel`, or the inherited parent session model only warn, so existing configurations keep working while you tighten the scope. `enforce: true` requires a non-empty `allow` list; otherwise the config is rejected at load time.

## Where running subagents show up

Foreground runs stream progress in the conversation while they run.

Background runs keep working after control returns to you. Inspect active runs with `subagent({ action: "status" })`, or a specific run with `subagent({ action: "status", id: "..." })`. `/subagents-fleet` opens a live, inspection-only fleet with current-session foreground work, recent async children, transcript tails, and completed output/session paths. Use `↑`/`↓` or `j`/`k` to select a child, `PgUp`/`PgDn` to scroll its transcript, `r` to refresh immediately, and `Esc` to close. `Ctrl+Alt+F` opens the same inspector even while a foreground turn is active and slash input is queued. Without a TUI, `/subagents-fleet` retains the textual `subagent({ action: "status", view: "fleet" })` fallback. Mutations stay in explicit commands: run `/subagents-stop` and pick from the selector, or use `/subagents-stop <run-id>` / `subagent({ action: "stop", id: "..." })` when you already know the id. To inspect one background child in text, use `subagent({ action: "status", id: "...", view: "transcript" })`; add `index` for a specific child in a parallel or chain run.

They also show a compact async widget and send completion notifications. Parallel background runs show per-agent progress instead of fake chain steps. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child process.

You can also ask naturally:

```text
Show me the current async runs.
```

Async runs also write machine-readable lifecycle artifacts for observability and workflow gates. For a top-level async run, `details.asyncDir` points at a directory containing `status.json`, `events.jsonl`, `output-<index>.log`, and `subagent-log-<runId>.md`; the final summary is written to Pi's subagent results directory as `<runId>.json`. Nested async runs use the same shape under the nested async root and are discoverable through status projections that read the nested-run registry. These files are append/update artifacts only; interactive foreground behavior is unchanged.

Foreground and async runners share bounded child-protocol handling. A child JSONL line above 4 MiB fails with structured `protocolError` code `protocol_output_limit`, stderr retains only its latest 128 KiB, split UTF-8 and final unterminated JSON events remain valid, and `agent_end.willRetry` defers completion until the child settles. Current Pi builds use `agent_settled` as the terminal watermark; older builds retain the bounded terminal-message fallback.

The stable v1 status/result fields are `lifecycleArtifactVersion`, `runId`/`id`, `sessionId`, `mode`, `state`, `startedAt`, `lastUpdate`, `endedAt`, `durationMs`, `cwd`, `asyncDir`, `sessionFile`, `outputFile`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `model`/`attemptedModels`/`modelAttempts`, `toolCount`, `turnCount`, and nested `children` when a child is allowed to launch subagents. `events.jsonl` records lifecycle transitions such as `subagent.run.started`, `subagent.step.started`, `subagent.step.completed`/`failed`/`paused`/`stopped`, control attention events, nested interrupt failures, and `subagent.run.completed`/`stopped`; run boundary events include the lifecycle artifact version. Consumers should read these JSON files instead of scraping terminal output; unknown fields and event types should be ignored for forward compatibility.

Other Pi extensions can use the versioned in-process event-bus RPC instead of scraping slash output or calling internal modules. Listen for `subagents:rpc:v1:ready`, send requests on `subagents:rpc:v1:request`, and read replies from `subagents:rpc:v1:reply:<requestId>`.

```typescript
const requestId = crypto.randomUUID();
pi.events.on(`subagents:rpc:v1:reply:${requestId}`, (reply) => {
  // { version: 1, requestId, success: true, data } or
  // { version: 1, requestId, success: false, error: { code, message } }
});
pi.events.emit("subagents:rpc:v1:request", {
  version: 1,
  requestId,
  method: "spawn",
  params: { agent: "reviewer", task: "Review the current diff", context: "fresh" }
});
```

The v1 methods are `ping`, `status`, `spawn`, `interrupt`, and `stop`. `status` and `interrupt` reuse the normal control actions. `spawn` is async-only: omit `async` or set `async: true`, omit `clarify` or set `clarify: false`, and do not pass management `action` values. It goes through the same executor as the `subagent` tool, so agent discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status all behave the same. `stop` targets current-session top-level async runs through the stop control channel and records a `stopped` lifecycle instead of reporting a timeout.

`pi.events` is in-process only. It does not reach separate Pi processes or child subagents; use the file lifecycle artifacts or `pi-intercom` for cross-process coordination.

If something feels misconfigured, run:

```text
/subagents-doctor
```

or ask:

```text
Check whether subagents and intercom are set up correctly.
```

## Recommended orchestration pattern (scaffolding)

Use orchestration as parent-agent guidance, not as a runtime workflow mode. For implementation work, the recommended loop is:

```text
clarify → planner → worker → fresh reviewers → worker

[1359 more lines in file. Use offset=301 to continue.]


gather-context-and-clarify.md
parallel-cleanup.md
parallel-context-build.md
parallel-handoff-plan.md
parallel-research.md
parallel-review.md
review-loop.md


The package has `prompts/` with workflow prompt templates. These likely are the packaged slash commands (e.g. /parallel-review). They use frontmatter subagent fields. Read one of these prompts to see how they define chain.


---
description: Parallel subagents review
---

Launch parallel reviewers for an adversarial review of the current work.

Use fresh context, not forked context, unless I explicitly ask for forked context. Reviewers should inspect the repository, relevant instructions, and current diff directly from files and commands. Do not rely on the main conversation history.

Give each reviewer a distinct angle. Generate the angles dynamically from the user's intent, the plan, the implemented code, and the current diff. If I specify angles, use mine. Otherwise, choose the highest-value review angles for this specific work.

These are examples, not fixed defaults:

1. Correctness and regressions
   Check whether the change satisfies the request, preserves existing behavior, handles edge cases, and avoids hidden runtime failures.

2. Tests and validation
   Check whether tests or validation were added at the right layer, whether assertions are meaningful, and whether the chosen verification commands are enough.

3. Simplicity and maintainability
   Check for unnecessary complexity, duplicate structure, single-use wrappers, brittle abstractions, confusing names, verbosity, and cleanup that is clearly worth doing.

Choose or adapt angles when the work calls for it:
- TypeScript-heavy changes: include type safety, source-of-truth types, casts, and error-boundary discipline.
- UI-heavy changes: include UX, accessibility, copy, and visual quality.
- Security-sensitive changes: include unsafe input/output handling, auth boundaries, privacy, and data exposure.
- Docs-heavy changes: include clarity, accuracy, completeness, reader flow, and non-robotic prose.
- Large multi-file changes: consider a fourth reviewer for structural friction, module boundaries, and testability.

Prefer three strong reviewers over many vague reviewers.

Give every reviewer a specific task prompt naming its angle. Ask reviewers to return concise, evidence-backed findings with file/line references and suggested fixes. The response should be review feedback, not a context summary. Reviewers must not edit files unless I explicitly ask for a writer pass.

While reviewers run, do your own narrow inspection if useful. After they return, synthesize the feedback into:
- fixes worth doing now
- optional improvements
- feedback to ignore or defer, with a short reason

Do not blindly apply every reviewer suggestion.

Autofix mode: if the invocation contains the exact word `autofix`, treat it as workflow control, not review scope. Remove it before deciding the review target. After synthesis, apply only fixes worth doing now, validate, and summarize. Do not apply optional improvements unless explicitly requested. If there are no fixes worth doing now, do not edit.

Without autofix mode, ask before applying fixes unless I already told you to address review feedback. When you ask, end with a compact numbered menu so I can respond with a number. Use wording suited to the findings, but include these choices when applicable:

```text
Reply with [1], [2], or further instructions:
[1] Apply only the fixes worth doing now.
[2] Apply the fixes worth doing now plus optional improvements.
```

Additional review target or focus from the slash command invocation:

$@

If the invocation provides a URL, issue link, file path, plan path, or freeform focus, treat it as the primary review scope. Read or fetch that target before assigning reviewer angles, and pass the target explicitly into each reviewer task.


---
description: Review/fix loop until clean
---

Run a parent-orchestrated review loop for the requested work.

Use the `subagent` tool. Keep the parent session as the loop controller and final decision-maker. Child subagents must receive concrete role-specific tasks; they must not run subagents or manage the loop themselves unless the parent intentionally selected an explicit fanout agent whose builtin `tools` includes `subagent` for that assigned fanout.

Default to a maximum of 3 review rounds unless I specify a different cap. Count a review round each time fresh-context reviewers inspect the current diff after a worker pass. Stop early when reviewers find no blockers or fixes worth doing now.

If the invocation includes an implementation request, first launch one async `worker` to implement the approved scope. If the current diff is already the target, start with review. The sequence can be launched up front as an async/background chain when the workflow is already clear, or continued as follow-up subagent runs after each async completion. For an initial chain, pass `async: true` so the main chat is unblocked; do not set `clarify: true` unless I explicitly want the foreground clarify UI. Use only one writer against the active worktree at a time unless I explicitly ask for isolated worktrees.

As a conservative orchestration policy, do not set `turnBudget` or a hard `toolBudget` on implementation or fix workers. A default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Give each writer a narrow delivery slice and an outer elapsed deadline with enough margin. Before that deadline, request a checkpoint after the current tool returns with changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be the checkpoint trigger.

For each review round, launch fresh-context `reviewer` agents in parallel. Reviewers must inspect the repository, relevant instructions, and current diff directly from files and commands. They must not rely on the main conversation history and must not edit files.

Choose review angles from the actual change. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability. Add security, performance, docs/API contracts, or user-flow validation when the work calls for it. Prefer three strong reviewers over many vague reviewers.

After reviewers return, synthesize their feedback into:
- blockers or scope/product/architecture decisions that need user approval;
- fixes worth doing now;
- optional improvements;
- feedback to ignore or defer, with a short reason.

Do not blindly apply every reviewer suggestion. If reviewers surface an unapproved product, scope, or architecture decision, pause and ask me before launching a fix worker.

When an async implementation worker completes, treat its handoff as the transition into review, not as final completion, unless I explicitly asked for worker-only work, review-only output, or to stop after implementation.

When there are fixes worth doing now and the workflow is implementation-authorized, launch one async forked `worker` without hard turn or tool-call caps to apply only those synthesized fixes. Ask it to preserve the approved scope, run focused validation, and report changed files, commands run with exit codes, validation evidence, surprises, and anything left undone.

After a fix worker returns, run another review round only when it made material changes or addressed non-trivial findings. Do not keep looping for optional polish, speculative improvements, or findings already deferred by the parent.

Stop and summarize when one of these is true:
- reviewers find no blockers or fixes worth doing now;
- remaining feedback is optional, speculative, or intentionally deferred;
- reviewers surface an unapproved decision that needs me;
- the max review-round cap is reached.

On completion, inspect the final diff yourself, run or confirm focused validation where appropriate, and summarize the loop: rounds run, fixes applied, validation, remaining deferred items, and why the loop stopped.

Additional target, implementation request, max-iteration cap, or review focus from the slash command invocation:

$@


---
description: Use subagents to gather context, then ask clarifying questions
---

Based on our discussion and my intent, launch focused context-gathering subagents before planning or implementing.

Use `scout` to inspect the relevant local files, existing patterns, constraints, tests, and likely integration points. Use `researcher` when external docs, recent sources, ecosystem context, or primary evidence would improve the answer.

Give each subagent a specific meta prompt. Ask them to return concise findings plus the remaining clarification questions that matter for implementation confidence.

After they return, synthesize what we know and use the `interview` tool to ask me the unresolved questions needed to reach a shared understanding.

$@


These prompt templates don't use frontmatter subagent fields; they are instructions to the parent agent to call subagent tool with workflows. The skill says prompt frontmatter can set `subagent`, `model`, etc. Maybe a newer version. But for now, the existing package uses plain prompt templates that tell parent to orchestrate.

User's prompt library `p-*.md` are simple slash prompts. They want to combine some prompts into a chain. There are a few ways:

1. Create a new meta-prompt template (e.g. `p-design-chain.md`) that instructs the parent to run p-brainstorm, then p-plan, etc., sequentially in the same conversation. Since prompt templates just expand, chaining means manually invoking each or writing a meta prompt. Could create a chain prompt that says "Run the following sequence of prompts as separate subagent steps: ..." But these p-* prompts are not subagents. Could convert them into subagent agents or chain definitions.

2. Use pi-subagents saved chains (`~/.pi/agent/chains/*.chain.md`) that invoke builtin subagents (scout/planner/worker/reviewer) for end-to-end workflows, which already exist. But those are not the p-* prompts.

3. Combine prompt templates via `/chain-prompts` command (if extension supports). Maybe there is a native adapter that can run a chain of prompt templates. The skill says prompt frontmatter can set `subagent`, `model`, etc. for the native adapter. Maybe each prompt template can be invoked as a subagent task. But no examples in the package. We need perhaps look at extension source for `/chain-prompts`.


slash/prompt-workflows.ts
 27: "chain-prompts",
 28: "prompt-workflow",
 269: pi.registerCommand("prompt-workflow", {
 270: description: "Run a prompt template through native pi-subagents: /prompt-workflow <name> [args]",
 303: pi.registerCommand("chain-prompts", {
 304: description: "Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args",
 315: ctx.ui.notify("Usage: /chain-prompts prompt-a -> prompt-b -- args", "error");

slash/slash-commands.ts
 26: import { registerPromptWorkflowCommands } from "./prompt-workflows.ts";


Great! Need read prompt-workflows.ts to understand how chain-prompts works and frontmatter fields.


import * as fs from "node:fs";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
import { parseFrontmatter } from "../agents/frontmatter.ts";
import type { SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
import type { ChainStep } from "../shared/settings.ts";
import { getAgentDir, getProjectConfigDir } from "../shared/utils.ts";

interface PromptWorkflow {
	name: string;
	description: string;
	body: string;
	filePath: string;
	agent: string;
	context?: "fresh" | "fork";
	model?: string;
	skill?: string | string[] | false;
	cwd?: string;
	worktree?: boolean;
	chain?: string;
}

type PromptWorkflowRunner = (params: SubagentParamsLike, ctx: ExtensionContext) => Promise<void>;

const RESERVED_COMMAND_NAMES = new Set([
	"chain-prompts",
	"prompt-workflow",
	"run",
	"chain",
	"parallel",
	"run-chain",
	"subagents-doctor",
	"subagents-models",
]);

function packagePromptsDir(): string {
	return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "prompts");
}

function promptDirs(cwd: string): string[] {
	return [
		packagePromptsDir(),
		path.join(getAgentDir(), "prompts"),
		path.join(getProjectConfigDir(cwd), "prompts"),
	];
}

function readPromptFiles(cwd: string): string[] {
	const files: string[] = [];
	for (const dir of promptDirs(cwd)) {
		let entries: fs.Dirent[];
		try {
			entries = fs.readdirSync(dir, { withFileTypes: true });
		} catch {
			continue;
		}
		for (const entry of entries) {
			if (entry.isFile() && entry.name.endsWith(".md")) files.push(path.join(dir, entry.name));
		}
	}
	return files;
}

function firstNonEmptyLine(value: string): string {
	return value.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "Prompt workflow";
}

function stringField(frontmatter: Record<string, string>, key: string): string | undefined {
	const value = frontmatter[key]?.trim();
	return value ? value : undefined;
}

function booleanField(frontmatter: Record<string, string>, key: string): boolean | undefined {
	const value = frontmatter[key]?.trim().toLowerCase();
	if (value === "true" || value === "yes" || value === "1") return true;
	if (value === "false" || value === "no" || value === "0") return false;
	return undefined;
}

function parseSkill(value: string | undefined): string | string[] | false | undefined {
	if (!value) return undefined;
	if (value === "false") return false;
	const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
	return parts.length > 1 ? parts : parts[0];
}

function parseAgent(frontmatter: Record<string, string>): string {
	const subagent = stringField(frontmatter, "subagent");
	if (!subagent || subagent === "true") return "delegate";
	return subagent;
}

function loadPromptWorkflow(filePath: string): PromptWorkflow | undefined {
	const content = fs.readFileSync(filePath, "utf-8");
	const { frontmatter, body } = parseFrontmatter(content);
	const name = path.basename(filePath, ".md");
	if (!name || RESERVED_COMMAND_NAMES.has(name)) return undefined;
	const model = stringField(frontmatter, "model");
	const skill = parseSkill(stringField(frontmatter, "skill"));
	const cwd = stringField(frontmatter, "cwd");
	const chain = stringField(frontmatter, "chain");
	return {
		name,
		description: stringField(frontmatter, "description") ?? firstNonEmptyLine(body),
		body,
		filePath,
		agent: parseAgent(frontmatter),
		...(booleanField(frontmatter, "inheritContext") === true || booleanField(frontmatter, "fork") === true ? { context: "fork" as const } : {}),
		...(booleanField(frontmatter, "fresh") === true ? { context: "fresh" as const } : {}),
		...(model ? { model } : {}),
		...(skill !== undefined ? { skill } : {}),
		...(cwd ? { cwd } : {}),
		...(booleanField(frontmatter, "worktree") === true ? { worktree: true } : {}),
		...(chain ? { chain } : {}),
	};
}

export function discoverPromptWorkflows(cwd: string): PromptWorkflow[] {
	const workflows = new Map<string, PromptWorkflow>();
	for (const file of readPromptFiles(cwd)) {
		const workflow = loadPromptWorkflow(file);
		if (workflow) workflows.set(workflow.name, workflow);
	}
	return [...workflows.values()].sort((a, b) => a.name.localeCompare(b.name));
}

function shellWords(input: string): string[] {
	const words: string[] = [];
	let current = "";
	let quote: "'" | '"' | undefined;
	let escaped = false;
	for (const ch of input) {
		if (escaped) {
			current += ch;
			escaped = false;
			continue;
		}
		if (ch === "\\") {
			escaped = true;
			continue;
		}
		if (quote) {
			if (ch === quote) quote = undefined;
			else current += ch;
			continue;
		}
		if (ch === "'" || ch === '"') {
			quote = ch;
			continue;
		}
		if (/\s/.test(ch)) {
			if (current) {
				words.push(current);
				current = "";
			}
			continue;
		}
		current += ch;
	}
	if (current) words.push(current);
	return words;
}

function substituteArgs(template: string, args: string[]): string {
	const all = args.join(" ");
	return template
		.replace(/\$ARGUMENTS/g, all)
		.replace(/\$@/g, all)
		.replace(/\$\{(\d+):-([^}]*)\}/g, (_match, index: string, fallback: string) => args[Number(index) - 1] || fallback)
		.replace(/\$(\d+)/g, (_match, index: string) => args[Number(index) - 1] ?? "");
}

function parseRuntimeOptions(words: string[]): { args: string[]; agentOverride?: string; fork?: boolean; fresh?: boolean; worktree?: boolean; bg?: boolean } {
	const args: string[] = [];
	let agentOverride: string | undefined;
	let fork = false;
	let fresh = false;
	let worktree = false;
	let bg = false;
	for (let i = 0; i < words.length; i++) {
		const word = words[i]!;
		if (word === "--fork") {
			fork = true;
			continue;
		}
		if (word === "--fresh") {
			fresh = true;
			continue;
		}
		if (word === "--worktree") {
			worktree = true;
			continue;
		}
		if (word === "--bg" || word === "--async") {
			bg = true;
			continue;
		}
		if (word === "--subagent") {
			agentOverride = words[++i];
			continue;
		}
		const eq = word.match(/^--subagent(?:=|:)(.+)$/);
		if (eq) {
			agentOverride = eq[1];
			continue;
		}
		args.push(word);
	}
	return { args, agentOverride, fork, fresh, worktree, bg };
}

function splitChainDeclaration(input: string): { declaration: string; argsText: string } {
	const delimiter = input.indexOf(" -- ");
	if (delimiter === -1) return { declaration: input.trim(), argsText: "" };
	return { declaration: input.slice(0, delimiter).trim(), argsText: input.slice(delimiter + 4).trim() };
}

function splitPromptChain(input: string): string[] {
	return input.split(" -> ").map((part) => part.trim()).filter(Boolean);
}

function workflowParams(workflow: PromptWorkflow, args: string[], runtime: ReturnType<typeof parseRuntimeOptions>): SubagentParamsLike {
	const task = substituteArgs(workflow.body, args).trim();
	const context = runtime.fork ? "fork" : runtime.fresh ? "fresh" : workflow.context;
	return {
		agent: runtime.agentOverride ?? workflow.agent,
		task,
		clarify: false,
		agentScope: "both",
		...(context ? { context } : {}),
		...(workflow.model ? { model: workflow.model } : {}),
		...(workflow.skill !== undefined ? { skill: workflow.skill } : {}),
		...(workflow.cwd ? { cwd: workflow.cwd } : {}),
		...(runtime.worktree || workflow.worktree ? { worktree: true } : {}),
		...(runtime.bg ? { async: true } : {}),
	};
}

function workflowChainStep(workflow: PromptWorkflow, args: string[], runtime: ReturnType<typeof parseRuntimeOptions>): ChainStep {
	const params = workflowParams(workflow, args, runtime);
	return {
		agent: params.agent ?? "delegate",
		task: params.task,
		...(params.model ? { model: params.model } : {}),
		...(params.skill !== undefined ? { skill: params.skill } : {}),
		...(params.cwd ? { cwd: params.cwd } : {}),
	};
}

function findWorkflow(workflows: PromptWorkflow[], name: string): PromptWorkflow | undefined {
	return workflows.find((workflow) => workflow.name === name);
}

function formatWorkflowList(workflows: PromptWorkflow[]): string {
	if (workflows.length === 0) return "No prompt workflows found in package, user, or project prompts.";
	return [
		"Prompt workflows:",
		...workflows.map((workflow) => `- ${workflow.name}: ${workflow.description} (${workflow.filePath})`),
	].join("\n");
}

export function registerPromptWorkflowCommands(input: {
	pi: ExtensionAPI;
	run: PromptWorkflowRunner;
}): void {
	const { pi, run } = input;

	pi.registerCommand("prompt-workflow", {
		description: "Run a prompt template through native pi-subagents: /prompt-workflow <name> [args]",
		handler: async (rawArgs, ctx) => {
			const words = shellWords(rawArgs);
			const name = words.shift();
			const workflows = discoverPromptWorkflows(ctx.cwd);
			if (!name || name === "list") {
				pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
				return;
			}
			const workflow = findWorkflow(workflows, name);
			if (!workflow) {
				ctx.ui.notify(`Unknown prompt workflow: ${name}`, "error");
				return;
			}
			const runtime = parseRuntimeOptions(words);
			try {
				if (workflow.chain) {
					const chainNames = splitPromptChain(workflow.chain);
					const chain = chainNames.map((stepName) => {
						const step = findWorkflow(workflows, stepName);
						if (!step) throw new Error(`Unknown prompt workflow in chain '${workflow.name}': ${stepName}`);
						return workflowChainStep(step, runtime.args, runtime);
					});
					await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...(runtime.bg ? { async: true } : {}) }, ctx);
					return;
				}
				await run(workflowParams(workflow, runtime.args, runtime), ctx);
			} catch (error) {
				ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
			}
		},
	});

	pi.registerCommand("chain-prompts", {
		description: "Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args",
		handler: async (rawArgs, ctx) => {
			const { declaration, argsText } = splitChainDeclaration(rawArgs);
			const workflows = discoverPromptWorkflows(ctx.cwd);
			if (!declaration || declaration === "list") {
				pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
				return;
			}
			const runtime = parseRuntimeOptions(shellWords(argsText));
			const names = splitPromptChain(declaration);
			if (names.length === 0) {
				ctx.ui.notify("Usage: /chain-prompts prompt-a -> prompt-b -- args", "error");
				return;
			}
			try {
				const chain = names.map((name) => {
					const workflow = findWorkflow(workflows, name);
					if (!workflow) throw new Error(`Unknown prompt workflow: ${name}`);
					return workflowChainStep(workflow, runtime.args, runtime);
				});
				await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...(runtime.bg ? { async: true } : {}) }, ctx);
			} catch (error) {
				ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
			}
		},
	});
}


Excellent. We have concrete mechanism:
- Prompt templates can have frontmatter field `subagent` (true or agent name) to make them run as a subagent (default `delegate`). Fields `model`, `skill`, `cwd`, `worktree`, `fork`/`fresh`/`inheritContext`, and `chain`.
- If a prompt template has `chain: "prompt-a -> prompt-b"` in frontmatter, then invoking `/prompt-workflow name` runs a chain of those prompt templates as subagent chain steps.
- Or use `/chain-prompts p-a -> p-b -- args` to run them on the fly.

So the implementation plan should be to convert the selected p-*.md prompts into subagent prompt workflows by adding appropriate frontmatter (subagent, maybe context, output handling), and then create chain recipes either via frontmatter `chain` field or new chain definition files / slash usage.

Need consider that current p-*.md prompts are written as instructions for the current (parent) agent, not for a subagent delegate. They include "Structure your answer as...". If run as subagent `delegate`, the child will be a full pi session with those instructions as task. That might produce output and then parent receives. That is exactly chaining: each prompt becomes a child turn. The chain passes previous output as context to next step? In subagent chain, `{previous}` is available. The prompt-workflow code uses `workflowChainStep` which creates ChainStep with agent, task, model, skill, cwd, but no `output` path. The child receives the prompt body with args substituted. For chain, the runtime does not pass previous output unless subagent framework passes `{previous}` automatically. In a chain, each step receives `{previous}` and `{task}`. The prompt body may reference `{previous}`? The existing p-*.md don't. If they are delegate subagents, they may ignore previous. Chaining them might not pass context automatically unless the framework includes previous conversation. The chain runs subagent sequentially with `context` default? The ChainStep doesn't set context unless frontmatter context is set. Default context for subagent chain steps is maybe forked/inherit? In prompt-workflow code, `context` is set if runtime `--fork/--fresh` or workflow.context. If omitted, subagent defaults to its agent default (delegate likely fresh? Actually default context for subagent tool may be fresh or inherit; skill says defaultContext per agent, delegate defaults maybe inherit? Need check delegate agent). But chain steps likely have `{previous}` placeholder and the task includes prior output? We need test.

But for planning only, we can propose approach and note need to verify context handoff and maybe use `as`/`output` fields if needed. However, prompt-workflow code doesn't support `output` field from frontmatter? It only uses model/skill/cwd; no output, progress, phase. Could enhance? But the existing slash command may be limited. The user asked "is there a way to combine some of these prompt into a chain?" The answer: yes, via `/chain-prompts` and frontmatter `chain`. Implementation plan could just add `chain` frontmatter to a meta prompt, or use new command.

Need understand current p-*.md frontmatter: `description` and `argument-hint`. They have no `subagent` field. So they are currently plain prompt templates invoked as `/p-plan`. To chain them via `/chain-prompts`, we may need to add `subagent: true` to each prompt we want to use as a chain step, because chain-prompts discovers prompt workflows only if they have `subagent`? Actually `loadPromptWorkflow` returns workflow for any .md file, with `agent: parseAgent(frontmatter)` defaulting to `delegate` if no subagent field or subagent true. It does not require `subagent` to be set; all prompts are loaded. So current p-*.md will be loaded as workflows with agent `delegate`. Then `/chain-prompts p-plan -> p-test -- ...` would work? But the prompt bodies of p-*.md expect the parent to produce answer itself, not to spawn a subagent. However when invoked via chain-prompts, the chain step runs the prompt body as a task to a `delegate` subagent, which is a child pi session. The child will then execute tools and produce answer. This might be exactly what chaining means: each prompt is delegated to a subagent. But the result is returned to parent, not necessarily passed to next step as conversation context. Next step gets `{previous}` placeholder and possibly the full prior child output if the subagent chain passes it. We need verify by reading subagent chain execution code. But for plan, we can note the need to test handoff.

Alternative approach: create new wrapper prompt templates specifically for chaining, with frontmatter `subagent` and `chain`, and body that references `{previous}` as needed. The p-*.md prompts could stay as-is for manual use.

Need produce structured plan with sections: Goal, Constraints, Approach, Steps, Verification, Risks, Open Questions. Since the user invoked p-plan, we must follow that format. We should also be concise.

Let's gather more details about delegate agent defaultContext and chain previous passing. Use grep/read.


delegate.md
 2: name: delegate
 10: You are a delegated agent. Execute the assigned task using the provided tools. Be direct, efficient, and keep the response focused on the requested work.

oracle.md
 9: defaultContext: fork

planner.md
 11: defaultContext: fork

worker.md
 9: defaultContext: fork
 40: - If your delegated task expects code or file edits and you have not made those edits, do not return a success summary. Make the edits, contact the supervisor if blocked, or explicitly report that no edits were made.


context-builder.md
delegate.md
oracle.md
planner.md
researcher.md
reviewer.md
scout.md
worker.md


---
name: delegate
description: Lightweight subagent that inherits the parent model with no default reads
systemPromptMode: append
inheritProjectContext: true
tools: read, grep, find, ls, bash, edit, write, contact_supervisor
inheritSkills: false
---

You are a delegated agent. Execute the assigned task using the provided tools. Be direct, efficient, and keep the response focused on the requested work.

If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and stay alive for the reply. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the plan. Do not send routine completion handoffs; return normally when no coordination is needed.


delegate has default context? Not set, so probably default to `fresh`? Need check shared settings or default. But not necessary for plan.

Need perhaps verify how `{previous}` is populated in chain steps. Search.


agents/frontmatter.ts
 15: let previousIsMoreIndented = false;
 28: folded += "\n".repeat(blankLines + (previousIsMoreIndented || currentIsMoreIndented ? 1 : 0));
 30: folded += previousIsMoreIndented || currentIsMoreIndented ? "\n" : " ";
 35: previousIsMoreIndented = currentIsMoreIndented;

agents/skills.ts
 444: const previousPriority = visitedDirectories.get(resolvedDir);
 445: if (previousPriority !== undefined && previousPriority >= priority) return false;

extension/doctor.ts
 172: : snapshot.grantHistory.map((grant) => `+${grant.amount} at ${new Date(grant.grantedAt).toISOString()} (${grant.previousLimit} → ${grant.limit})`).join("; ")}`,

extension/index.ts
 8: * Modes: single (agent + task), parallel (tasks[]), chain (chain[] with {previous})
 197: const previousRuntimeCleanup = globalStore[runtimeCleanupStoreKey];
 198: if (typeof previousRuntimeCleanup === "function") {
 200: previousRuntimeCleanup();
 464: const previousEventUnsubscribes = globalStore[eventUnsubscribeStoreKey];
 465: if (Array.isArray(previousEventUnsubscribes)) {
 466: for (const unsubscribe of previousEventUnsubscribes) {

extension/rpc.ts
 219: ): { runId: string; asyncDir: string; previousState: string; state: "stopping"; message: string } {
 272: previousState: status.state,

extension/schemas.ts
 113: task: Type.Optional(Type.String({ description: "Task template with {task}, {previous}, {chain_dir} variables. Defaults to {previous}." })),
 143: task: Type.Optional(Type.String({ description: "Task template with {item}, {item.path}, {task}, {previous}, {chain_dir}, and {outputs.name} variables." })),
 167: description: "Task template with variables: {task}=original request, {previous}=prior step's text response, {chain_dir}=shared folder, {outputs.name}=prior named output. Required for first step, defaults to '{previous}' for subsequent steps."
 262: chain: Type.Optional(Type.Array(ChainItem, { description: "CHAIN mode: sequential steps; each result becomes {previous}. append-step takes one tail step and may use {chain_dir}/{outputs.name}." })),

extension/tool-description.ts
 31: • {previous} - Text response from the previous step (empty for first step)
 35: • Sequential: { chain: [{agent:"agent-a", task:"Analyze {task}"}, {agent:"agent-b", task:"Plan based on {previous}"}] }
 37: • Mixed: { chain: [{agent:"agent-a", task:"Research {task}"}, {parallel: [{agent:"agent-b", task:"Review {previous}", count: 2}]}, {agent:"agent-c", task:"Summarize {previous}"}] }
 64: • { action: "append-step", id: "...", chain: [{agent:"agent-c", task:"Use {previous}"}] } - append one step to the tail of a running async chain
 83: • Chain templates may use {task}, {previous}, {chain_dir}, and named outputs. Parallel worktree isolation requires a clean git repo.
 84: • Chain example: { chain: [{agent:"agent-a", task:"Analyze {task}"}, {parallel: [{agent:"agent-b", task:"Check {previous}", count: 3}]}] }

intercom/result-intercom.ts
 230: ? "Previous intercom targets below identify child sessions used while they were running. Inspect artifacts or session logs if resume is unavailable."
 238: if (child.intercomTarget) lines.push(`${input.source === "async" ? "Previous intercom target" : "Run intercom target"}: ${child.intercomTarget}`);

runs/background/notify.ts
 200: const previousUnsubscribe = globalStore[unsubscribeStoreKey];
 201: if (typeof previousUnsubscribe === "function") {
 203: previousUnsubscribe();
 208: const previousBatcher = globalStore[batcherStoreKey];
 209: if (previousBatcher && typeof (previousBatcher as { dispose?: () => void }).dispose === "function") {
 211: (previousBatcher as { dispose: () => void }).dispose();

runs/background/subagent-runner.ts
 912: previousOutput: string;
 1051: let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
 1509: previousOutput: string,
 1515: if (!worktreeSetup) return previousOutput;
 1519: if (!diffSummary) return previousOutput;
 1520: return `${previousOutput}\n\n${diffSummary}`;
 1571: let previousOutput = "";
 1598: let previousCumulativeTokens: TokenUsage = { input: 0, output: 0, total: 0 };
 2025: const previous = step.activityState;
 2030: from: previous,
 2316: const previous = step.activityState;
 2321: from: previous,
 2348: const previousInput = step.tokens?.input ?? 0;
 2349: const previousOutput = step.tokens?.output ?? 0;
 2350: step.tokens = { input: previousInput + input, output: previousOutput + output, total: previousInput + previousOutput + input + output };
 2392: const previous = step.activityState;
 2394: if (previous !== "needs_attention") {
 2396: from: previous,
 2655: previousOutput = "Dynamic fanout produced 0 results.";
 2831: previousOutput, placeholder, cwd, sessionEnabled,
 2989: previousOutput = aggregateParallelOutputs(
 3134: previousOutput, placeholder, cwd: taskCwd, sessionEnabled,
 3238: previousCumulativeTokens = {
 3239: input: previousCumulativeTokens.input + taskTokens.input,
 3240: output: previousCumulativeTokens.output + taskTokens.output,
 3241: total: previousCumulativeTokens.total + taskTokens.total,
 3244: statusPayload.totalTokens = { ...previousCumulativeTokens };
 3291: previousOutput = aggregateParallelOutputs(
 3301: previousOutput = appendParallelWorktreeSummary(previousOutput, worktreeSetup, asyncDir, stepIndex, group);
 3343: previousOutput, placeholder, cwd, sessionEnabled,

[Continue with cursor="fff_c1"]


We have enough. The chain engine passes `{previous}` as text response from previous step. So if chain steps are prompt templates, the prompt body for step N can include `{previous}` to receive prior output. But `workflowChainStep` sets task = body substituted with args, no `{previous}` placeholder by default. The chain engine will replace `{previous}` if present. Since our p-*.md don't contain `{previous}`, the prior output will be ignored unless we modify prompt templates or create wrapper prompts that embed `{previous}`. However, the delegate child might inherit parent session history if context is forked, giving it full conversation. But chain step context likely is fresh per default? The prompt-workflow code sets context only if explicit. Default `delegate` no defaultContext; likely fresh. So no prior context.

Thus to chain prompts meaningfully, we need either:
- Create new chain-specific wrapper prompt templates whose bodies include `{previous}` at relevant points, and route to the desired agent.
- Or use forked/inherit context so each step sees conversation history. But a chain of delegate children with inherited context could read prior outputs? Not exactly; they run as separate sessions.

The simplest: define a meta prompt template `p-feature.chain.md` with frontmatter:
```
---
description: End-to-end design → plan → implement → review chain
subagent: true
chain: p-brainstorm -> p-plan -> p-refactor -> p-test -> p-review
---
Run the feature chain for: $@
```
Then `/prompt-workflow p-feature-chain my feature` would run each prompt as delegate subagent. But p-brainstorm etc. don't handle `{previous}`. Maybe acceptable as separate turns with no state transfer, or we can modify them to include a "previous context" section if `{previous}` present.

Better: create dedicated chain files under `~/.pi/agent/chains/` that reference builtin subagents with proper tasks, not prompt templates. But user specifically asked combine some of "these prompts". So the plan should propose making them chainable.

Need inspect if prompt template discovery requires `subagent` frontmatter to be listed in `/prompt-workflow list`. Actually `discoverPromptWorkflows` loads all .md. But slash command registration: pi prompt templates register as slash `/p-plan` independently. The pi-subagents `/prompt-workflow` command reads same files but loads all. However, when a prompt has `chain` frontmatter, it is still a prompt template loaded by pi core? Does pi core ignore unknown frontmatter? Probably yes. So adding `subagent` and `chain` frontmatter shouldn't break `/p-plan` usage? The frontmatter is YAML in `---` block; pi core uses description/argument-hint. Unknown keys likely ignored. So safe.

But pi core's prompt template argument substitution uses shell-style `$1`, `$@`; pi-subagents also uses same syntax. Compatible.

Potential issue: `chain` frontmatter causes `/prompt-workflow` to ignore the body and run chain of other workflows. But `/p-plan` (core) will still use body. Good.

Need maybe create a few chain recipes:
- `p-brainstorm -> p-plan` for design then plan.
- `p-debug -> p-test -> p-commit` for fix flow.
- `p-summarize -> p-plan -> p-test` for big file.
- `p-refactor -> p-test -> p-review -> p-commit`.

But the user question is generic. Plan should include steps to:
1. Decide which prompts to chain and naming conventions.
2. Add minimal frontmatter (`subagent: true` or specific agent, `context: fresh/fork`, maybe `chain`) to each prompt file involved, or create new chain wrapper prompt files to avoid editing existing prompts.
3. Test individual `/prompt-workflow p-plan "task"` and `/chain-prompts p-brainstorm -> p-plan -- "feature"`.
4. Update README/Doc to document chains.
5. Add saved `.chain.md` if wanting agent-based chains with outputs.

Need also note constraints: existing p-*.md are interactive parent instructions; chaining them as subagents will spawn child sessions, potentially costly. Also the `.pi` profile currently has no chains dir; `.pi_1` has examples. We can reuse those examples for agent-based chains, but not prompt-template chains.

Need maybe inspect the difference between `.pi` and `.pi_1`. The user may not know about `.pi_1`. We can mention existing `.pi_1` chain examples as prior art but they use ollama-* custom agents that aren't in current `.pi`. If desired, can port them.

Let's also read pi-subagents README section about chain-prompts and prompt-workflow. Use grep.

ffgrep

chain-prompts|prompt-workflow|prompt templates as subagents|chain:


README.md
 528: `subagent({ chain: [...] })` tool API or a saved `.chain.json` for data-driven fan-out.
 861: Dynamic fanout is available only through direct `subagent({ chain: [...] })` JSON or saved `.chain.json` files. It expands an array from a prior structured named output, runs one child template per item, and stores the ordered collection under `collect.as`. The source must be structured output; prose is never parsed. `expand.maxItems` is required, over-limit arrays fail, nested fanout and arbitrary expressions are not supported, and `.chain.md` has no dynamic syntax in this release.
 1068: { chain: [
 1076: { chain: [...], async: true }
 1079: { chain: [
 1089: { chain: [
 1106: { chain: [
 1254: subagent({ action: "append-step", id: "<run-id>", chain: [{ agent: "worker", task: "Continue from {previous}" }] })
 1278: { chain: [
 1610: `pi-subagents` works standalone through natural language, the `subagent` tool, slash commands, and the packaged prompt shortcuts listed near the top of this README. It also includes a native prompt-workflow adapter for reusable subagent prompt templates, so you do not need `pi-prompt-template-model` for the common subagent workflow path.
 1627: /prompt-workflow take-screenshot https://example.com
 1635: /chain-prompts analyze -> fix -- user arguments here


Intercom delivery events:

- `subagent:control-intercom`
- `subagent:result-intercom`

The result watcher emits `subagent:async-complete`; `src/extension/index.ts` registers the notification handler that consumes it. Control/attention events are surfaced as visible parent notices and persisted for async runs. Native supervisor requests are delivered only to the exact parent session that spawned the child.

## Prompt-template integration

`pi-subagents` works standalone through natural language, the `subagent` tool, slash commands, and the packaged prompt shortcuts listed near the top of this README. It also includes a native prompt-workflow adapter for reusable subagent prompt templates, so you do not need `pi-prompt-template-model` for the common subagent workflow path.

Create a prompt in `.pi/prompts/` or `~/.pi/agent/prompts/`:

```md
---
description: Take a screenshot
model: claude-sonnet-4-20250514
subagent: browser-screenshoter
cwd: /tmp/screenshots
---
Use url in the prompt to take screenshot: $@
```

Then run it through the native adapter:

```text
/prompt-workflow take-screenshot https://example.com
```

The adapter delegates to the named subagent, applies `model`, `skill`, `cwd`, `worktree`, and fork/fresh context metadata, and supports runtime overrides such as `--subagent reviewer`, `--fork`, `--fresh`, `--worktree`, and `--bg`.

For prompt-template chains, use:

```text
/chain-prompts analyze -> fix -- user arguments here
```

Each named prompt becomes a native `subagent` chain step. This is intentionally scoped to subagent workflows; compare-style prompt features such as `/best-of-n` are not part of the built-in adapter.

## Runtime files

The main runtime files are:

| File | Purpose |
|------|---------|
| `src/extension/index.ts` | Extension registration, tool registration, message/render wiring. |
| `src/agents/agents.ts` | Agent and chain discovery, frontmatter parsing. |
| `src/runs/foreground/subagent-executor.ts` | Main execution routing for single, parallel, chain, management, status, interrupt, and doctor actions. |
| `src/runs/foreground/execution.ts` | Core foreground `runSync` handling. |
| `src/runs/background/subagent-runner.ts` | Detached async runner. |
| `src/runs/background/async-execution.ts` | Background launch support. |
| `src/runs/background/async-status.ts` | Status discovery and formatting for async runs. |
| `src/runs/foreground/chain-execution.ts` / `src/agents/chain-serializer.ts` | Chain orchestration and `.chain.md` parsing. |
| `src/shared/settings.ts` | Chain behavior, instructions, and config helpers. |
| `src/runs/shared/worktree.ts` | Git worktree isolation. |
| `src/intercom/intercom-bridge.ts` | Runtime intercom bridge instructions and diagnostics. |
| `src/extension/schemas.ts` / `src/shared/types.ts` | Tool schemas, shared types, and event constants. |
| `test/unit/` / `test/integration/` / `test/e2e/` | Unit, loader-based integration, and real-session E2E tests. |


Great. The native adapter supports exactly chaining prompt templates. The implementation plan can be grounded in this.

Need maybe read `src/shared/settings.ts` ChainStep type and chain frontmatter to know if output/progress etc. But for plan it's enough.

Need maybe inspect if current `.pi` prompt files include frontmatter fields that would accidentally trigger subagent. No.

Now, the user's first message was "Create a structured implementation plan for: the current task" and then they clarified task as the chain question. We should answer with plan. Since they invoked `p-plan` format, we should follow exactly sections 1-7.

Need include specific file paths: `/home/liph/dotfiles/pi/.pi/agent/prompts/p-*.md`, `~/.pi/agent/chains/`, `Doc/README.md`, settings maybe. Since current cwd is dotfiles/pi/.pi/agent/prompts, we can use relative? The plan should mention absolute or relative.

We must not write code yet. Plan only.

Let's formulate. Need be careful with constraints: existing prompt templates are parent-facing instructions. Chaining them through subagent adapter delegates each to a child `delegate` session. The results may be large; need `output` path maybe not supported by adapter? The adapter's workflowChainStep does not pass output. But chain engine uses default output? The delegate has no default output. The child response will be returned inline. For long outputs, maybe too large. But p-*.md outputs are structured and not huge. Could be okay. However, for chains with many steps, passing full prior response into next step can bloat context. We can set `fresh` context per step and rely on `{previous}` snippet if prompts reference it. Or we can create wrapper prompts with `{previous}` sections.

Need open questions: Which prompts to chain? State transfer expectations? Subagent vs parent-run? Read-only vs writing? Cost/concurrency? Also ask whether to create wrapper chain prompts or edit existing prompts? This is ambiguous. We can include in open questions.

Let's think about steps in detail:

Goal: Enable selected `p-*.md` prompt templates to be composed into reusable subagent chains (linear sequences) using the installed `pi-subagents` native prompt-workflow adapter, while keeping individual `/p-<verb>` interactive usage intact.

Constraints:
- Prompt files live in `~/.pi/agent/prompts/` (this repo).
- `pi-subagents` is installed and loaded.
- Native adapter uses frontmatter `subagent`, `chain`, `model`, `skill`, `cwd`, `fresh`/`fork`, `worktree`.
- `/chain-prompts` syntax: `/chain-prompts a -> b -- args`; `/prompt-workflow` can also run a prompt whose frontmatter has `chain: a -> b`.
- Prompt templates use `$@` for args; adapter performs same substitution.
- Existing prompts are structured parent instructions; if run as subagent `delegate`, the child will execute tools and produce the structured answer. No `{previous}` support in existing bodies, so state will not automatically flow unless context is forked/inherited or wrappers add it.
- Need avoid `RESERVED_COMMAND_NAMES`: chain-prompts, prompt-workflow, run, chain, parallel, run-chain, subagents-doctor, subagents-models. Also existing slash commands like /p-plan. New files should not conflict.

Approach:
- Add minimal `subagent: true` frontmatter to the prompts we want chainable (so they are recognized by the adapter; actually not required, but good to be explicit). But keep `description` and `argument-hint`.
- Create a new set of "chain recipe" prompt templates named `p-<name>.chain.md` (or `chain-<name>.md`) that only contain frontmatter `subagent: true`, `chain: p-foo -> p-bar -> p-baz`, and a one-line body referencing `$@`. This avoids editing existing prompts and preserves their parent semantics. Put them in same prompts dir.
- Optionally add a `previous`/`context` section to the chain recipe or to existing prompts so each step receives the prior output via `{previous}` placeholder. But adapter only substitutes args; chain engine substitutes `{previous}`. We can embed `{previous}` in chain recipe? Not directly; chain recipe's body becomes the first step's task? Actually if frontmatter `chain` is set, adapter ignores body and builds chain from named workflows, using each workflow's body as task. So to pass previous, we need to edit the bodies of the chained prompts to include a section "Prior step output: {previous}" when relevant. This is a bigger change.
- For a first minimal version, don't pass previous output; each step runs independently with fresh context. Use this for prompts that don't need prior output (e.g. p-brainstorm -> p-plan where plan step can re-brainstorm? Actually plan benefits from brainstorm output. Without passing, plan step receives no brainstorm. So either use fork/inherit context, or include `{previous}`.
- A better design: create wrapper prompt templates for chain use that embed `{previous}` in the task, e.g. `p-plan-with-context.md` with body "Previous step produced: {previous}\n\nCreate a structured implementation plan for: $@". But this duplicates. Could also modify existing p-*.md to include an optional prior context section: add at top "If a previous step output is provided in {previous}, use it as context." Since chain engine substitutes `{previous}` if present. This makes them chain-aware without breaking interactive use (when not in chain, {previous} is empty string). Need verify engine replaces `{previous}` with empty for first step; yes.

Actually the existing prompts use `${@:-the current task}` etc. If we add `{previous}` text, pi core prompt substitution won't replace it; it will remain literal `{previous}` in parent prompt. That is bad for interactive use. Unless we wrap it in a comment? Hmm. If we edit p-plan.md body to include `{previous}` placeholder, then invoking `/p-plan` will produce literal `{previous}` in user message, which is noisy. Not good.

Alternative: create chain-specific wrappers that import/include the original prompt content? Not possible with simple templates. Could copy. Or use chain files with agent-based steps instead of reusing prompt templates. But user asks combine prompts.

Maybe the best approach: use the existing prompt templates as chain steps but rely on `context: fork` so each delegate child inherits the full parent conversation history, which includes previous child outputs? Wait each chain step is a separate subagent run. If context is `fork`, it branches from current persisted parent session. At the time step 2 starts, step 1 has completed and returned to parent conversation. If forked context includes parent history up to current point, step 2 will see step 1's output in conversation. That provides state transfer. `delegate` default context likely fresh, but we can set `fork: true` in frontmatter. However, forked context includes all parent history, which might be too large/noisy. But acceptable. For chains, prompt-workflow code sets context based on workflow.context; if not set, uses runtime option; otherwise default. We can set `inheritContext: true` or `fork: true` in frontmatter of chainable prompts so each step runs in forked context and sees previous outputs. Need be careful: if first step runs in fork, it inherits parent. That is fine.

But do the existing p-*.md need to run in parent or child? For interactive `/p-plan`, context is parent itself, not subagent. The frontmatter `fork: true` only affects `/prompt-workflow` adapter; pi core ignores it. So safe.

Therefore a minimal plan:
1. Choose 2-3 initial chains and the prompts in each.
2. Add `subagent: true` and `fork: true` (or `fresh: true` depending) to each chosen prompt file. These are extra frontmatter keys; core will ignore, adapter uses them. Keep `description` and `argument-hint`.
3. Create chain recipe prompts with `chain: p-X -> p-Y -> p-Z`. Name them e.g. `p-design-build.md`, `p-fix-commit.md`, etc.
4. Reload pi or use `/reload` and test with `/prompt-workflow list` and `/chain-prompts ...`.
5. Update Doc/README with chain table and examples.
6. Iterate on state handoff and cost.

Need verify via `/prompt-workflow list` that prompts show with agent. But existing p-*.md have no `subagent`, so agent defaults to `delegate`. We can add `subagent: delegate` or true. Also if they have `chain` frontmatter, then `/prompt-workflow` will run chain instead of body. That means the prompt itself becomes a chain recipe. But if we want both individual and chain, we should not put `chain` on the same files; create separate chain recipe files.

Maybe the cleanest: define chain recipes as separate files e.g. `p-feature.chain.md`:
```
---
description: Brainstorm, plan, then implement a feature using existing prompts
subagent: true
chain: p-brainstorm -> p-plan -> p-test -> p-commit
---
Feature or task to work through: $@
```
Then `/prompt-workflow p-feature.chain add user auth` runs p-brainstorm, p-plan, p-test, p-commit sequentially, each as delegate with forked context (if p-* have fork: true). The existing p-* remain individually usable.

Need also consider output paths. Since adapter doesn't support output, the chain results are inline. That may be fine for prompts.

Potential risks:
- Adding frontmatter to existing prompts might be parsed by pi core and break if unknown keys cause errors. But pi core likely only uses known keys. Need test.
- Running each prompt as subagent can be expensive and slower; also child delegate has tools and may behave differently (e.g., may ask clarifying questions). The p-plan etc. include "do not write implementation code" which is fine.
- Chain engine may pass huge previous outputs in context if forked, causing token bloat. Use fresh context per step if no previous state needed, or use selective `{previous}` snippets.
- If a step fails, chain stops. Need decide whether acceptable.
- Naming conflicts: new chain recipe files must not clash with existing slash commands.
- The `RESERVED_COMMAND_NAMES` list includes `chain-prompts` etc. Not relevant.

Open questions to ask user:
1. Which exact prompt sequences do you want to chain? (Examples: design-build, fix-commit, summarize-plan-test, etc.)
2. Do you want each step to see the previous step's output (stateful chain) or run independently? This affects frontmatter `fork`/`fresh` and whether we add `{previous}` handling.
3. Should the chain be triggered via a single slash command (e.g., `/p-design-build`) or only via `/chain-prompts`? (If single slash, create recipe files.)
4. Are you okay with each prompt executing as a subagent (separate child session, extra cost/latency), or did you mean a lightweight "send these prompts one after another in the same session"?

Maybe we can ask these now? The user asked for implementation plan. But to make plan concrete, we need clarifications. p-plan format has an Open Questions section. We can list them and maybe ask. The instructions say ask when ambiguous before starting. Since we are producing a plan, we can include open questions and maybe ask the user for answers. However, the user may expect the plan to proceed. We can give a plan that is parameterized, and ask the open questions at the end. That should be acceptable.

Need also maybe mention alternative approach of using saved `.chain.md` agent chains (like `.pi_1` examples) rather than prompt chains. The user's question is about prompts, but we can note that for end-to-end implementation with code edits, agent chains (scout→planner→worker→reviewer) are already supported and can be saved. However, to chain the existing p-* prompts specifically, use prompt-workflow adapter.

Let's ensure we cite concrete file paths:
- `~/.pi/agent/prompts/p-*.md`
- `~/.pi/agent/prompts/p-<chain>.chain.md` (new chain recipes)
- `~/.pi/agent/prompts/Doc/README.md`
- `~/.pi/agent/settings.json` (if need to override agent context; maybe not)

Verification steps:
- `/reload` in pi to pick up prompt changes.
- `/prompt-workflow list` shows chain recipes and selected p-* with `subagent: true` and context.
- `/prompt-workflow p-<chain>.chain "test task"` runs without "Unknown prompt workflow" and completes all steps.
- `/chain-prompts p-brainstorm -> p-plan -- "test task"` works.
- Check that `/p-plan` still works interactively and produces expected plan.
- Inspect child run status and outputs for state handoff (forked context includes previous outputs? Need verify).

Rollbacks:
- Remove or rename new chain recipe files.
- Revert frontmatter changes in p-*.md via git or backup.
- If `/p-<verb>` broke due to frontmatter, remove added keys.
- Disable subagent adapter? Can't easily; but deleting chain files and frontmatter stops chaining.

Need mention this is in dotfiles repo; use git to commit after each step.

Let's think if there is any test harness for prompt templates. No tests. Manual verification.

Need ensure plan's steps are small and verifiable. We'll enumerate.

Potential subtlety: pi prompt template frontmatter parsing may not accept `subagent`, `chain`, etc. But these are in same file; pi core uses parseFrontmatter? The pi core prompt template loader might be different. It likely ignores unknown keys. But let's verify by reading pi core prompt template loader? Maybe not needed. We can include a verification step: inspect that pi startup header still loads prompts and `/p-plan` autocomplete works.

Let's search pi core code for prompt template frontmatter accepted keys.


CHANGELOG.md
 571: - Added default-value expansion for prompt template positional arguments, e.g. `${1:-7}` ([#5553](https://github.com/earendil-works/pi/pull/5553) by [@dannote](https://github.com/dannote)).
 918: - Fixed prompt template argument parsing to split unquoted multiline input on newlines ([#4553](https://github.com/earendil-works/pi/issues/4553)).
 1236: - Fixed remaining hardcoded `pi` / `.pi` branding to route through `APP_NAME` and `CONFIG_DIR_NAME` extension points, so SDK rebrands get consistent naming in `/quit` description, `process.title`, and the project-local extensions directory ([#3583](https://github.com/badlogic/pi-mono/pull/3583) by [@jlaneve](https://github.com/jlaneve))
 1393: - Prompt templates support an `argument-hint` frontmatter field that renders before the description in the `/` autocomplete dropdown, using `<angle>` for required and `[square]` for optional arguments. See [docs/prompt-templates.md#argument-hints](docs/prompt-templates.md#argument-hints).
 1395: - Compact interactive startup header with a comma-separated view of loaded AGENTS.md files, prompt templates, skills, and extensions. Press `Ctrl+O` to toggle the expanded listing.
 1400: - Added `argument-hint` frontmatter field for prompt templates, displayed before the description in the autocomplete dropdown ([#2780](https://github.com/badlogic/pi-mono/pull/2780) by [@andresvi94](https://github.com/andresvi94))
 1406: - Changed interactive startup header to a compact, comma-separated view of loaded AGENTS.md files, prompt templates, skills, and extensions, with `Ctrl+O` to toggle the expanded listing ([#3267](https://github.com/badlogic/pi-mono/pull/3267))
 1587: - Fixed resource collision precedence so project and user skills, prompt templates, and themes override package resources consistently, and CLI-provided paths take precedence over discovered resources ([#2781](https://github.com/badlogic/pi-mono/issues/2781))
 1806: - Unified source provenance via `sourceInfo`. All resources, commands, tools, skills, and prompt templates now carry structured `sourceInfo` with path, scope, and source metadata. Visible in autocomplete, RPC discovery, and SDK introspection. See [docs/extensions.md](docs/extensions.md).
 1843: - Fixed slash command source attribution for extension commands, prompt templates, and skills in autocomplete and command discovery ([#1734](https://github.com/badlogic/pi-mono/issues/1734))
 1960: - Changed custom tool system prompt behavior so extension and SDK tools are included in the default `Available tools` section only when they provide `promptSnippet`. Omitting `promptSnippet` now leaves the tool out of that section instead of falling back to `description` ([#2285](https://github.com/badlogic/pi-mono/issues/2285))
 2396: - `/export` HTML now includes collapsible tool input schemas (parameter names, types, and descriptions), improving session review and sharing workflows ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev)).
 2397: - `pi.getAllTools()` now exposes tool parameters in addition to name and description, enabling richer extension integrations ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev)).
 2403: - `/export` HTML now includes tool input schema (parameter names, types, descriptions) in a collapsible section under each tool ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev))
 2404: - `pi.getAllTools()` now returns tool parameters in addition to name and description ([#1416](https://github.com/badlogic/pi-mono/pull/1416) by [@marchellodev](https://github.com/marchellodev))
 2609: - Added `ExtensionAPI.getCommands()` to let extensions list available slash commands (extensions, prompt templates, skills) for invocation via `prompt` ([#1210](https://github.com/badlogic/pi-mono/pull/1210) by [@w-winter](https://github.com/w-winter))
 2857: - Hot reload (`/reload`) of resources including AGENTS.md, SYSTEM.md, APPEND_SYSTEM.md, prompt templates, skills, themes, and extensions. See [README.md#commands](README.md#commands) and [README.md#context-files](README.md#context-files).
 2912: - Skill, prompt template, and theme discovery now use settings and CLI path arrays instead of legacy filters ([#645](https://github.com/badlogic/pi-mono/issues/645))
 3055: - Added bash-style argument slicing for prompt templates ([#770](https://github.com/badlogic/pi-mono/pull/770) by [@airtonix](https://github.com/airtonix))
 3104: - Multi-line YAML frontmatter in skills and prompt templates now parses correctly. Centralized frontmatter parsing using the `yaml` library. ([#728](https://github.com/badlogic/pi-mono/pull/728) by [@richardgill](https://github.com/richardgill))
 3127: - Show loaded prompt templates on startup ([#743](https://github.com/badlogic/pi-mono/pull/743) by [@tallshort](https://github.com/tallshort))
 3209: - `pi.getAllTools()` now returns `ToolInfo[]` (with `name` and `description`) instead of `string[]`. Extensions that only need names can use `.map(t => t.name)`. ([#648](https://github.com/badlogic/pi-mono/pull/648) by [@carsonfarmer](https://github.com/carsonfarmer))
 3295: - Symlinked directories in `prompts/` folders are now followed when loading prompt templates ([#601](https://github.com/badlogic/pi-mono/pull/601) by [@aliou](https://github.com/aliou))
 3500: This release unifies hooks and custom tools into a single "extensions" system and renames "slash commands" to "prompt templates". ([#454](https://github.com/badlogic/pi-mono/issues/454))
 3634: "Slash commands" (markdown files defining reusable prompts invoked via `/name`) are renamed to "prompt templates" to avoid confusion with extension-registered commands.
 3756: - System prompt now automatically rebuilds when tools change via `setActiveTools()`, updating tool descriptions and guidelines to match the new tool set
 4460: - **Skills standard compliance**: Skills now adhere to the [Agent Skills standard](https://agentskills.io/specification). Validates name (must match parent directory, lowercase, max 64 chars), description (required, max 1024 chars), and frontmatter fields. Warns on violations but remains lenient. Prompt format changed to XML structure. Removed `{baseDir}` placeholder in favor of relative paths. ([#231](https://github.com/badlogic/pi-mono/issues/231))
 4650: - **Skills system**: Auto-discover and load instruction files on-demand. Supports Claude Code (`~/.claude/skills/*/SKILL.md`), Codex CLI (`~/.codex/skills/`), and Pi-native formats (`~/.pi/agent/skills/`, `.pi/skills/`). Skills are listed in system prompt with descriptions, agent loads them via read tool when needed. Supports `{baseDir}` placeholder. Disable with `--no-skills` or `skills.enabled: false` in settings. ([#169](https://github.com/badlogic/pi-mono/issues/169))
 4995: - **File-based Slash Commands**: Create custom reusable prompts as `.txt` files in `~/.pi/slash-commands/`. Files become `/filename` commands with first-line descriptions. Supports `{{selection}}` placeholder for referencing selected/attached content.

README.md
 15: Pi is a minimal terminal coding harness. Adapt pi to your workflows, not the other way around, without having to fork and modify pi internals. Extend it with TypeScript [Extensions](#extensions), [Skills](#skills), [Prompt Templates](#prompt-templates), and [Themes](#themes). Put your extensions, skills, prompt templates, and themes in [Pi Packages](#pi-packages) and share them with others via npm or git.
 91: Then just talk to pi. By default, pi gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [pi packages](#pi-packages).
 152: - **Startup header** - Shows shortcuts (`/hotkeys` for all), loaded AGENTS.md files, prompt templates, skills, and extensions
 174: Type `/` in the editor to trigger commands. [Extensions](#extensions) can register custom commands, [skills](#skills) are available as `/skill:name`, and [prompt templates](#prompt-templates) expand via `/templatename`.
 594: | `--prompt-template <path>` | Load prompt template (repeatable) |
 595: | `--no-prompt-templates` | Disable prompt template discovery |

dist/config.d.ts
 89: /** Get path to prompt templates directory */

dist/index.d.ts
 31: export { parseFrontmatter, stripFrontmatter } from "./utils/frontmatter.ts";

dist/core/agent-session.d.ts
 146: /** Whether to expand file-based prompt templates (default: true) */
 304: * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
 339: /** File-based prompt templates */
 349: * - Expands file-based prompt templates by default
 367: * Expands skill commands and prompt templates. Errors on extension commands.
 375: * Expands skill commands and prompt templates. Errors on extension commands.

dist/core/keybindings.d.ts
 54: readonly description: "Move cursor up";
 58: readonly description: "Move cursor down";
 62: readonly description: "Move cursor left";
 66: readonly description: "Move cursor right";
 70: readonly description: "Move cursor word left";
 74: readonly description: "Move cursor word right";
 78: readonly description: "Move to line start";
 82: readonly description: "Move to line end";
 86: readonly description: "Jump forward to character";
 90: readonly description: "Jump backward to character";
 94: readonly description: "Page up";
 98: readonly description: "Page down";
 102: readonly description: "Delete character backward";
 106: readonly description: "Delete character forward";
 110: readonly description: "Delete word backward";
 114: readonly description: "Delete word forward";
 118: readonly description: "Delete to line start";
 122: readonly description: "Delete to line end";
 126: readonly description: "Yank";
 130: readonly description: "Yank pop";
 134: readonly description: "Undo";
 138: readonly description: "Insert newline";
 142: readonly description: "Submit input";
 146: readonly description: "Tab / autocomplete";
 150: readonly description: "Copy selection";
 154: readonly description: "Move selection up";
 158: readonly description: "Move selection down";
 162: readonly description: "Selection page up";
 166: readonly description: "Selection page down";
 170: readonly description: "Confirm selection";

[Continue with cursor="fff_c2"]


The docs show frontmatter fields are description, argument-hint. It doesn't mention rejecting others. Pi core likely stores whole frontmatter and only uses known keys. So adding keys safe.

Now formulate final plan. It must be in structured format exactly as requested. Let's draft.

Need be mindful of over-explaining; user asked for plan. We'll include clear sections.

Let's craft final answer with no code but file paths and commands.

Potential steps detail:

1. Select the first chain recipe. Example candidate: `p-brainstorm -> p-plan -> p-test -> p-commit` for a new feature from idea to commit. Another: `p-summarize -> p-diagnose -> p-debug -> p-test` for debugging. We can list a few options and recommend.

Actually the open questions should ask which. But steps can be generic: "Pick 1–2 chain recipes".

Let's propose three candidate recipes in plan as examples, not final. The plan can say "Step 1: Decide on chain recipes (candidates below)". That covers ambiguity.

2. Add minimal `subagent:` frontmatter to the prompt files involved. `subagent: delegate` (or `true`). Also set `context` strategy. For stateful chains, use `fork: true` so each child inherits parent conversation and sees prior outputs. But this might include too much. Alternatively `fresh: true` for independent runs. We can recommend `fork: true` for chains where steps build on each other, `fresh: true` for independent passes. Need mention this is an open question.

3. Create chain recipe files, e.g. `~/.pi/agent/prompts/p-design-build.md`:
```
---
description: Brainstorm alternatives, pick one, plan, implement, test, and commit
subagent: true
chain: p-brainstorm -> p-plan -> p-test -> p-commit
argument-hint: "[feature or problem]"
---
Run the full design-build chain for: $@
```
Need note `subagent: true` maps to `delegate`. `chain` frontmatter triggers native chain. The body becomes the task for the first step? Actually in prompt-workflow code, if chain present, it builds chain from named workflows and uses each workflow's body as task; the top-level body is not used except maybe `task` field set to runtime.args.join(" ") and chain uses each workflow's task. So body can be a comment or just `$@`. Good.

4. Reload Pi and test `/prompt-workflow list` shows new recipes and selected prompts with context.

5. Test each chain recipe with a small safe task in a scratch repo (to avoid real edits). Verify each step completes and the final output appears.

6. Refine state handoff: if prior output is not being used, either keep `fork` context or add `{previous}` placeholder by creating chain-specific wrappers. This is step 6 after initial test.

7. Document in `Doc/README.md`: add chain table, `/chain-prompts` examples, and note frontmatter.

8. Commit changes to dotfiles.

Verification per step:
- Step 2: `/prompt-workflow list` output includes prompts with `subagent:` and context; `/p-plan` still works.
- Step 3: file exists; `/prompt-workflow list` includes recipe.
- Step 5: run chain; inspect `subagent({ action: "status" })` or `/subagents-fleet` for step states; verify no errors.
- Step 6: check next step's output references prior step's conclusions.
- Step 7: README updated and renders.

Risks:
- Frontmatter keys may conflict with pi core in future. Mitigation: keep backups.
- Cost/latency: each prompt as subagent is a full child session. Mitigation: use for non-trivial tasks, limit chain length.
- State bloat with forked context. Mitigation: use fresh context or wrappers with `{previous}`.
- Chain failure stops sequence. Mitigation: run async? But prompt-workflow chain doesn't continue on failure. Could design shorter chains.
- Existing `/p-foo` interactive behavior unchanged if frontmatter additions ignored; but verify.

Open Questions:
1. Which prompt sequences? (provide examples)
2. Stateful or independent steps? (affects `fork`/`fresh` and `{previous}`)
3. Single slash entry points (recipe files) or only `/chain-prompts` ad hoc?
4. Are any of the prompts used for writing code (p-refactor/p-test) where running as subagent may edit files? If so, concurrency/writer isolation?

We should maybe ask these to user. But final answer can list them. Since we have ask_user_question tool, should we ask? The user asked for plan; providing open questions is part of plan. We can ask them now to refine, but it's optional. The plan format includes open questions. I think listing open questions satisfies. However, if we want to be interactive, we could ask. But the instructions: "Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions". We are proceeding with a parameterized plan, not implementation. So no need to ask? But to make the plan actionable, we could include the open questions and note plan can be updated after answers. That is fine.

Need keep final response concise but complete. Also mention that `.pi_1` already has agent chain examples; we could optionally port them. But maybe too much.

Let's craft final. Ensure no code blocks with implementation; only illustrative snippets maybe? The instruction says do not write implementation code yet; only produce the plan. We can include example frontmatter snippets as part of plan; that's not implementation code, it's plan specification. It's okay.

Let's final.

## Implementation Plan: Combine `p-*.md` Prompt Templates into Chains

### 1. Goal
Enable the existing `~/.pi/agent/prompts/p-*.md` templates to be composed into reusable, sequential subagent chains using the already-installed `pi-subagents` native prompt-workflow adapter, while keeping the individual `/p-<verb>` interactive prompts unchanged.

### 2. Constraints
- **Existing prompts** (`p-brainstorm.md`, `p-plan.md`, `p-debug.md`, `p-diagnose.md`, `p-refactor.md`, `p-test.md`, `p-review.md`, `p-commit.md`, `p-doc.md`, `p-explain.md`, `p-summarize.md`, `p-secaudit.md`) are parent-facing instructions intended to be expanded in the main session.
- **Installed machinery**: `pi-subagents` is loaded and exposes:
  - `/prompt-workflow <name> [args]` — runs a prompt template as a subagent step.
  - `/chain-prompts a -> b -> c -- args` — runs prompt templates as a native subagent chain.
  - A prompt frontmatter adapter that reads `subagent`, `chain`, `model`, `skill`, `cwd`, `fork`/`fresh`/`inheritContext`, and `worktree`.
- **No existing chains** in the active `.pi` profile (the backup `.pi_1` has agent-chain examples, but not prompt-template chains).
- **Pi core** only uses `description` and `argument-hint` from prompt frontmatter; extra keys are generally ignored, but this must be verified before relying on it.
- Prompt templates use shell-style argument substitution (`$@`, `$1`, `${@:-...}`), which the native adapter also supports.
- New file names must avoid the `pi-subagents` reserved names (`chain-prompts`, `prompt-workflow`, `run`, `chain`, `parallel`, `run-chain`, `subagents-doctor`, `subagents-models`).

### 3. Approach
Create small **chain-recipe prompt files** that only contain frontmatter-driven orchestration. Keep the original `p-*.md` files untouched except for a few optional adapter hints (`subagent`, `fork`/`fresh`) if we want them to run as child subagents with a specific context mode. Use the `chain:` frontmatter field so `/prompt-workflow <recipe>` expands into a sequence of existing prompts. This avoids turning every existing prompt into a complex workflow object and preserves their current standalone behavior.

### 4. Steps

1. **Pick the first 1–2 chain recipes**
   Candidate recipes to choose from:
   - `p-brainstorm -> p-plan -> p-test -> p-commit` (design → plan → test → commit)
   - `p-summarize -> p-diagnose -> p-debug -> p-test` (understand → diagnose → fix → regression-test)
   - `p-refactor -> p-test -> p-review -> p-commit` (safe refactor → validate → review → commit)
   - `p-secaudit -> p-review -> p-test` (security-first review loop)

2. **Decide the context handoff strategy**
   Two options:
   - **Forked/inherited context** (`fork: true` on each step): each child sees the parent conversation, so later steps implicitly see earlier outputs. Simpler but can bloat context.
   - **Fresh context + explicit `{previous}`**: each child starts clean and the chain engine injects the prior step’s text as `{previous}`. Requires adding `{previous}` handling to the prompts that need it.

3. **Add minimal adapter frontmatter to the prompts used in the chosen recipes**
   Only add `subagent:` (e.g. `subagent: delegate`) and a context hint (`fork: true` or `fresh: true`). Do not change the body text yet. Example addition:
   ```yaml
   ---
   description: ...
   argument-hint: ...
   subagent: true          # new; tells the adapter to delegate this prompt
   fork: true              # new; or fresh: true depending on step 2
   ---
   ```

4. **Create chain-recipe prompt files**
   For each chosen recipe, add a new file such as:
   - `~/.pi/agent/prompts/p-design-build.md`
   - `~/.pi/agent/prompts/p-fix-commit.md`
   Each contains only:
   ```yaml
   ---
   description: <what the chain does>
   argument-hint: "[task description]"
   subagent: true
   chain: p-brainstorm -> p-plan -> p-test -> p-commit
   ---
   Run the full chain for: $@
   ```

5. **Reload Pi and list workflows**
   Run `/reload`, then `/prompt-workflow list` and confirm:
   - New recipe files appear.
   - Existing `p-*.md` files appear with `subagent: delegate` and the chosen context mode.
   - The original `/p-<verb>` autocomplete still works.

6. **Run a dry-run chain in a scratch repo**
   Test one recipe with a harmless task, e.g.:
   ```
   /prompt-workflow p-design-build "a toy feature"
   ```
   or
   ```
   /chain-prompts p-brainstorm -> p-plan -- "a toy feature"
   ```
   Inspect the chain via `/subagents-fleet` or `subagent({ action: "status" })`.

7. **Refine state handoff if needed**
   If later steps are not using earlier outputs:
   - For forked context: verify the child transcript includes the parent turns.
   - For fresh context: create thin wrapper prompt files (e.g. `p-plan-with-context.md`) whose body contains `{previous}` and then re-invokes the original prompt logic, or edit the original prompts to include an optional “Prior context” section guarded by `{previous}`.

8. **Update `Doc/README.md`**
   Add a “Chaining prompts” section with the chain table, example `/chain-prompts` commands, and notes on `subagent`/`chain` frontmatter.

9. **Commit the dotfiles changes**
   Commit the new recipe files and any frontmatter additions so they are tracked and easy to revert.

### 5. Verification
- `/prompt-workflow list` shows recipes and selected `p-*` prompts with the expected `subagent` / context metadata.
- `/p-plan "test task"` still produces a normal plan in the parent session.
- `/chain-prompts p-brainstorm -> p-plan -- "test task"` completes both subagent steps without “Unknown prompt workflow” errors.
- `/prompt-workflow p-design-build "test task"` runs the full recipe and returns final output.
- `subagent({ action: "status" })` shows each chain step in `complete` state.
- For stateful chains, the second step’s output explicitly references conclusions from the first step.
- `Doc/README.md` renders correctly and the new examples work when copied.

### 6. Risks & Rollbacks
| Risk | Mitigation / Rollback |
|------|----------------------|
| Extra frontmatter confuses Pi core and breaks `/p-<verb>` | Test `/p-plan` after adding keys; rollback by removing the new frontmatter lines. |
| Each prompt as a subagent is slower/more expensive than one parent turn | Use chains only for non-trivial tasks; keep recipes short (≤4 steps). |
| Forked context bloats later steps with full conversation history | Switch to `fresh: true` and explicit `{previous}` wrappers. |
| A step fails and aborts the whole chain | Accept for now; chains are meant to be linear. Keep individual prompts available as fallbacks. |
| New recipe file names collide with reserved or existing commands | Check `/prompt-workflow list` and rename if needed. |
| Subagent writes files unexpectedly when chaining `p-refactor` / `p-test` | Mark those recipes as writer chains and run them one at a time; do not parallelize writers unless isolated by worktree. |

### 7. Open Questions
1. **Which exact sequences do you want first?** (e.g. design-build, fix-commit, summarize-diagnose-fix, security-review loop?)
2. **Do steps need to share output, or can they run independently?** This decides `fork` vs. `fresh` and whether we need `{previous}` wrappers.
3. **Do you want named slash recipes** (`/p-design-build`) **or just ad-hoc `/chain-prompts` usage?** Named recipes are more discoverable; ad-hoc is more flexible.
4. **Are you comfortable with each chained prompt running as a full subagent session,** or did you mean a lighter “send these prompts one after another in the same session” mechanism?

Once you answer these, I can tighten the recipe list and produce the exact frontmatter and chain files.


Create a structured implementation plan for: - p-brainstorm -> p-plan -> p-test -> p-commit (design → plan → test → commit) - p-summarize -> p-diagnose -> p-debug -> p-test (understand → diagnose → fix → regression-test) - p-refactor -> p-test -> p-review -> p-commit (safe refactor → validate → review → commit) - p-secaudit -> p-review -> p-test (security-first review loop) 1. create these mentioned chain recipes, but instead of p- use c- (for chain). 2. what should i choos? im unsure. 3. use the slashed version but call the chain c- as in 1. 4. i didnt get the one with the subagent: delegate explain please

Follow this format:
1. **Goal** — one-sentence objective
2. **Constraints** — existing code, dependencies, tests, or assumptions to respect
3. **Approach** — high-level strategy and rationale
4. **Steps** — numbered, actionable tasks small enough to verify one at a time
5. **Verification** — how to confirm each step works (tests, logs, manual checks)
6. **Risks & Rollbacks** — what could go wrong and how to undo safely
7. **Open Questions** — anything that needs clarification before starting

Use the codebase context as needed. Do not write implementation code yet; only produce the plan.