103 lines
419 KiB
JSON
103 lines
419 KiB
JSON
{"type":"session","version":3,"id":"019f94df-aaa7-7e74-90b6-1799f398b5a9","timestamp":"2026-07-24T16:05:14.023Z","cwd":"/home/liph/dotfiles/pi/.pi/agent/prompts"}
|
||
{"type":"model_change","id":"a2f35fff","parentId":null,"timestamp":"2026-07-24T16:05:15.177Z","provider":"ollama","modelId":"kimi-k2.7-code:cloud"}
|
||
{"type":"thinking_level_change","id":"1d6f912b","parentId":"a2f35fff","timestamp":"2026-07-24T16:05:15.177Z","thinkingLevel":"medium"}
|
||
{"type":"message","id":"7d2c4d5d","parentId":"1d6f912b","timestamp":"2026-07-24T16:06:42.582Z","message":{"role":"user","content":[{"type":"text","text":"is there a way to change the c-{prompt} so they dont create a new pi -p session. once the chain starts i have no option to stop them. is there also an automatic tool that would just use whatever subagent or prompt is the most fitting?"}],"timestamp":1784909202197}}
|
||
{"type":"message","id":"9156898f","parentId":"7d2c4d5d","timestamp":"2026-07-24T16:06:47.380Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The user is asking about pi (the coding agent harness) behavior. They want to know:\n1. Is there a way to change the c-{prompt} behavior so they don't create a new `pi -p` session. Once the chain starts, they have no option to stop them.\n2. Is there an automatic tool that would just use whatever subagent or prompt is the most fitting?\n\nThis is about pi itself, so I should read the pi documentation. The system prompt says:\n- Main documentation: /home/liph/.local/lib/node_modules/@earendil-works/pi-coding-agent/README.md\n- Additional docs: /home/liph/.local/lib/node_modules/@earendil-works/pi-coding-agent/docs\n- Examples: /home/liph/.local/lib/node_modules/@earendil-works/pi-coding-agent/examples (extensions, custom tools, SDK)\n\nThe user is asking about c-{prompt}, which likely refers to command prompts or slash commands in pi. They mention \"c-{prompt}\" which could be \"c-coder\" or similar prompt blueprints in the .pi/agent/prompts directory. Let me first explore the current directory and the pi docs to understand what's available.\n\nI should use ask_user_question if underspecified, but the user is asking general capability questions. I should research the docs first. Let me read the relevant docs.\n\nCurrent working directory: /home/liph/dotfiles/pi/.pi/agent/prompts\n\nLet me look at what's in the current directory and the pi docs.","thinkingSignature":"reasoning"},{"type":"text","text":"I'll look into the pi docs and your current prompts directory to answer both questions accurately."},{"type":"toolCall","id":"functions.bash:0","name":"bash","arguments":{"command":"ls -la /home/liph/dotfiles/pi/.pi/agent/prompts"}},{"type":"toolCall","id":"functions.read:1","name":"read","arguments":{"path":"/home/liph/.local/lib/node_modules/@earendil-works/pi-coding-agent/README.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":15316,"output":405,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":15721,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909202648,"responseId":"chatcmpl-498","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"1c77805f","parentId":"9156898f","timestamp":"2026-07-24T16:06:47.401Z","message":{"role":"toolResult","toolCallId":"functions.bash:0","toolName":"bash","content":[{"type":"text","text":"total 84\ndrwxr-xr-x 5 liph liph 4096 Jul 24 18:02 .\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:05 ..\n-rw-r--r-- 1 liph liph 313 Jul 24 18:02 c-design-build.md\n-rw-r--r-- 1 liph liph 360 Jul 24 17:55 c-fix-commit.md\n-rw-r--r-- 1 liph liph 328 Jul 24 17:55 c-refactor-commit.md\n-rw-r--r-- 1 liph liph 287 Jul 24 17:55 c-security-loop.md\ndrwxr-xr-x 2 liph liph 4096 Jul 24 18:03 Doc\n-rw-r--r-- 1 liph liph 1277 Jul 24 18:02 p-brainstorm.md\n-rw-r--r-- 1 liph liph 1121 Jul 24 18:02 p-commit.md\n-rw-r--r-- 1 liph liph 834 Jul 24 17:55 p-debug.md\n-rw-r--r-- 1 liph liph 1147 Jul 24 17:55 p-diagnose.md\n-rw-r--r-- 1 liph liph 1176 Jul 24 17:55 p-doc.md\n-rw-r--r-- 1 liph liph 677 Jul 24 17:55 p-explain.md\ndrwxr-xr-x 4 liph liph 4096 Jul 24 17:42 .pi-subagents\n-rw-r--r-- 1 liph liph 793 Jul 24 17:55 p-plan.md\n-rw-r--r-- 1 liph liph 1135 Jul 24 17:55 p-refactor.md\n-rw-r--r-- 1 liph liph 874 Jul 24 17:55 p-review.md\n-rw-r--r-- 1 liph liph 1395 Jul 24 17:55 p-secaudit.md\n-rw-r--r-- 1 liph liph 1179 Jul 24 17:55 p-summarize.md\n-rw-r--r-- 1 liph liph 1098 Jul 24 17:55 p-test.md\ndrwxr-xr-x 4 liph liph 4096 Jul 24 18:01 test\n"}],"isError":false,"timestamp":1784909207401}}
|
||
{"type":"message","id":"aab0c292","parentId":"1c77805f","timestamp":"2026-07-24T16:06:47.401Z","message":{"role":"toolResult","toolCallId":"functions.read:1","toolName":"read","content":[{"type":"text","text":"<p align=\"center\">\n <a href=\"https://pi.dev\">\n <img alt=\"pi logo\" src=\"https://pi.dev/logo-auto.svg\" width=\"128\">\n </a>\n</p>\n<p align=\"center\">\n <a href=\"https://discord.com/invite/3cU7Bz4UPx\"><img alt=\"Discord\" src=\"https://img.shields.io/badge/discord-community-5865F2?style=flat-square&logo=discord&logoColor=white\" /></a>\n <a href=\"https://www.npmjs.com/package/@earendil-works/pi-coding-agent\"><img alt=\"npm\" src=\"https://img.shields.io/npm/v/@earendil-works/pi-coding-agent?style=flat-square\" /></a>\n</p>\n\n> New issues and PRs from new contributors are auto-closed by default. Maintainers review auto-closed issues daily. See [CONTRIBUTING.md](../../CONTRIBUTING.md).\n\n---\n\nPi 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.\n\nPi ships with powerful defaults but skips features like sub agents and plan mode. Instead, you can ask pi to build what you want or install a third party pi package that matches your workflow.\n\nPi runs in four modes: interactive, print or JSON, RPC for process integration, and an SDK for embedding in your own apps. See [openclaw/openclaw](https://github.com/openclaw/openclaw) for a real-world SDK integration.\n\n## Share your OSS coding agent sessions\n\nIf you use pi for open source work, please share your coding agent sessions.\n\nPublic OSS session data helps improve models, prompts, tools, and evaluations using real development workflows.\n\nFor the full explanation, see [this post on X](https://x.com/badlogicgames/status/2037811643774652911).\n\nTo publish sessions, use [`badlogic/pi-share-hf`](https://github.com/badlogic/pi-share-hf). Read its README.md for setup instructions. All you need is a Hugging Face account, the Hugging Face CLI, and `pi-share-hf`.\n\nYou can also watch [this video](https://x.com/badlogicgames/status/2041151967695634619), where I show how I publish my `pi-mono` sessions.\n\nI regularly publish my own `pi-mono` work sessions here:\n\n- [badlogicgames/pi-mono on Hugging Face](https://huggingface.co/datasets/badlogicgames/pi-mono)\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Providers & Models](#providers--models)\n- [Interactive Mode](#interactive-mode)\n - [Editor](#editor)\n - [Commands](#commands)\n - [Keyboard Shortcuts](#keyboard-shortcuts)\n - [Message Queue](#message-queue)\n- [Sessions](#sessions)\n - [Branching](#branching)\n - [Compaction](#compaction)\n- [Settings](#settings)\n- [Context Files](#context-files)\n- [Customization](#customization)\n - [Prompt Templates](#prompt-templates)\n - [Skills](#skills)\n - [Extensions](#extensions)\n - [Themes](#themes)\n - [Pi Packages](#pi-packages)\n- [Programmatic Usage](#programmatic-usage)\n- [Philosophy](#philosophy)\n- [CLI Reference](#cli-reference)\n\n---\n\n## Quick Start\n\n```bash\nnpm install -g --ignore-scripts @earendil-works/pi-coding-agent\n```\n\n`--ignore-scripts` disables dependency lifecycle scripts during install. Pi does not require install scripts for normal npm installs.\n\nInstaller alternative:\n\n```bash\ncurl -fsSL https://pi.dev/install.sh | sh\n```\n\nAuthenticate with an API key:\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\npi\n```\n\nOr use your existing subscription:\n\n```bash\npi\n/login # Then select provider\n```\n\nThen 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).\n\n**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [tmux](docs/tmux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)\n\n---\n\n## Providers & Models\n\nFor each built-in provider, pi maintains a list of tool-capable models. Configured provider catalogs refresh automatically; run `pi update --models` to force an immediate refresh. Authenticate via subscription (`/login`) or API key, then select any model from that provider via `/model` (or Ctrl+L).\n\n**Subscriptions:**\n- Anthropic Claude Pro/Max\n- OpenAI ChatGPT Plus/Pro (Codex)\n- GitHub Copilot\n\n**API keys:**\n- Anthropic\n- Ant Ling\n- OpenAI\n- Azure OpenAI\n- DeepSeek\n- NVIDIA NIM\n- Google Gemini\n- Google Vertex\n- Amazon Bedrock\n- Mistral\n- Groq\n- Cerebras\n- Cloudflare AI Gateway\n- Cloudflare Workers AI\n- xAI\n- OpenRouter\n- Vercel AI Gateway\n- ZAI Coding Plan (Global)\n- ZAI Coding Plan (China)\n- OpenCode Zen\n- OpenCode Go\n- Hugging Face\n- Fireworks\n- Together AI\n- Kimi For Coding\n- MiniMax\n- Xiaomi MiMo\n- Xiaomi MiMo Token Plan (China)\n- Xiaomi MiMo Token Plan (Amsterdam)\n- Xiaomi MiMo Token Plan (Singapore)\n\nPi also supports the llama.cpp router server. Configure it with `/login llama.cpp`, manage downloads and loaded models with `/llama`, then select a loaded model with `/model`. See [docs/llama-cpp.md](docs/llama-cpp.md) for setup and usage.\n\nSee [docs/providers.md](docs/providers.md) for other provider setup instructions.\n\n**Custom providers & models:** Add providers via `~/.pi/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).\n\n---\n\n## Interactive Mode\n\n<p align=\"center\"><img src=\"docs/images/interactive-mode.png\" alt=\"Interactive Mode\" width=\"600\"></p>\n\nThe interface from top to bottom:\n\n- **Startup header** - Shows shortcuts (`/hotkeys` for all), loaded AGENTS.md files, prompt templates, skills, and extensions\n- **Messages** - Your messages, assistant responses, tool calls and results, notifications, errors, and extension UI\n- **Editor** - Where you type; border color indicates thinking level\n- **Footer** - Working directory, session name, total token/cache usage (`↑` input, `↓` output, `R` cache read, `W` cache write, `CH` latest cache hit rate), cost, context usage, current model. Totals include assistant responses, usage reported by tools, and summary generation.\n\nThe editor can be temporarily replaced by other UI, like built-in `/settings` or custom UI from extensions (e.g., a Q&A tool that lets the user answer model questions in a structured format). [Extensions](#extensions) can also replace the editor, add widgets above/below it, a status line, custom footer, or overlays.\n\n### Editor\n\n| Feature | How |\n|---------|-----|\n| File reference | Type `@` to fuzzy-search project files |\n| Path completion | Tab to complete paths |\n| Multi-line | Shift+Enter (or Ctrl+Enter on Windows Terminal) |\n| External editor | Ctrl+G opens `externalEditor`, `$VISUAL`, `$EDITOR`, Notepad on Windows, or `nano` elsewhere |\n| Clipboard | Ctrl+V to paste an image or text (Alt+V on Windows), or drag images onto terminal |\n| Bash commands | `!command` runs and sends output to LLM, `!!command` runs without sending |\n\nStandard editing keybindings for delete word, undo, etc. See [docs/keybindings.md](docs/keybindings.md).\n\n### Commands\n\nType `/` 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`.\n\n| Command | Description |\n|---------|-------------|\n| `/login`, `/logout` | Manage provider credentials |\n| [`/llama`](docs/llama-cpp.md) | Download, load, and unload llama.cpp router models |\n| `/model` | Switch models |\n| `/scoped-models` | Enable/disable models for Ctrl+P cycling |\n| `/settings` | Thinking level, theme, message delivery, transport |\n| `/resume` | Pick from previous sessions |\n| `/new` | Start a new session |\n| `/name <name>` | Set session display name |\n| `/session` | Show session info (file, ID, messages, tokens, cost) |\n| `/tree` | Jump to any point in the session and continue from there |\n| `/trust` | Save project trust decision for future sessions (restart required) |\n| `/fork` | Create a new session from a previous user message |\n| `/clone` | Duplicate the current active branch into a new session |\n| `/compact [prompt]` | Manually compact context, optional custom instructions |\n| `/copy` | Copy last assistant message to clipboard |\n| `/export [file]` | Export session to HTML or JSONL file |\n| `/import <file>` | Import and resume a session from a JSONL file |\n| `/share` | Upload as private GitHub gist with shareable HTML link |\n| `/reload` | Reload keybindings, extensions, skills, prompts, themes, and context files |\n| `/hotkeys` | Show all keyboard shortcuts |\n| `/changelog` | Display version history |\n| `/quit` | Quit pi |\n\n### Keyboard Shortcuts\n\nSee `/hotkeys` for the full list. Customize via `~/.pi/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md).\n\n**Commonly used:**\n\n| Key | Action |\n|-----|--------|\n| Ctrl+C | Clear editor |\n| Ctrl+C twice | Quit |\n| Escape | Cancel/abort |\n| Escape twice | Open `/tree` |\n| Ctrl+L | Open model selector |\n| Ctrl+P / Shift+Ctrl+P | Cycle scoped models forward/backward |\n| Shift+Tab | Cycle thinking level |\n| Ctrl+O | Collapse/expand tool output |\n| Ctrl+T | Collapse/expand thinking blocks |\n| Ctrl+X | Copy the last assistant message |\n\n### Message Queue\n\nSubmit messages while the agent is working:\n\n- **Enter** queues a *steering* message, delivered after the current assistant turn finishes executing its tool calls\n- **Alt+Enter** queues a *follow-up* message, delivered only after the agent finishes all work\n- **Escape** aborts and restores queued messages to editor\n- **Alt+Up** retrieves queued messages back to editor\n\nOn Windows Terminal, `Alt+Enter` is fullscreen by default. Remap it in [docs/terminal-setup.md](docs/terminal-setup.md) so pi can receive the follow-up shortcut.\n\nConfigure delivery in [settings](docs/settings.md): `steeringMode` and `followUpMode` can be `\"one-at-a-time\"` (default, waits for response) or `\"all\"` (delivers all queued at once). `transport` selects provider transport preference (`\"sse\"`, `\"websocket\"`, or `\"auto\"`) for providers that support multiple transports.\n\n---\n\n## Sessions\n\nSessions are stored as JSONL files with a tree structure. Each entry has an `id` and `parentId`, enabling in-place branching without creating new files. See [docs/session-format.md](docs/session-format.md) for file format.\n\n### Management\n\nSessions auto-save to `~/.pi/agent/sessions/` organized by working directory.\n\n```bash\npi -c # Continue most recent session\npi -r # Browse and select from past sessions\npi --no-session # Ephemeral mode (don't save)\npi --name \"my task\" # Set session display name at startup\npi --session <path|id> # Use specific session file or ID\npi --fork <path|id> # Fork specific session file or ID into a new session\n```\n\nUse `/session` in interactive mode to see the current session ID before reusing it with `--session <id>` or `--fork <id>`.\n\n### Branching\n\n**`/tree`** - Navigate the session tree in-place. Select any previous point, continue from there, and switch between branches. All history preserved in a single file.\n\n<p align=\"center\"><img src=\"docs/images/tree-view.png\" alt=\"Tree View\" width=\"600\"></p>\n\n- Search by typing, fold/unfold and jump between branches with Ctrl+←/Ctrl+→ or Alt+←/Alt+→, page with ←/→\n- Filter modes (Ctrl+O): default → no-tools → user-only → labeled-only → all\n- Press Ctrl+X to copy the selected message\n- Press Shift+L to label entries as bookmarks and Shift+T to toggle label timestamps\n\n**`/fork`** - Create a new session file from a previous user message on the active branch. Opens a selector, copies the active path up to that point, and places the selected prompt in the editor for modification.\n\n**`/clone`** - Duplicate the current active branch into a new session file at the current position. The new session keeps the full active-path history and opens with an empty editor.\n\n**`--fork <path|id>`** - Fork an existing session file or partial session UUID directly from the CLI. This copies the full source session into a new session file in the current project.\n\n### Compaction\n\nLong sessions can exhaust context windows. Compaction summarizes older messages while keeping recent ones.\n\n**Manual:** `/compact` or `/compact <custom instructions>`\n\n**Automatic:** Enabled by default. Triggers on context overflow (recovers and retries) or when approaching the limit (proactive). Configure via `/settings` or `settings.json`.\n\nCompaction is lossy. The full history remains in the JSONL file; use `/tree` to revisit. Customize compaction behavior via [extensions](#extensions). See [docs/compaction.md](docs/compaction.md) for internals.\n\n---\n\n## Settings\n\nUse `/settings` to modify common options, or edit JSON files directly:\n\n| Location | Scope |\n|----------|-------|\n| `~/.pi/agent/settings.json` | Global (all projects) |\n| `.pi/settings.json` | Project (overrides global) |\n\nSee [docs/settings.md](docs/settings.md) for all options.\n\n### Project Trust\n\nOn interactive startup, pi asks before trusting a project folder that contains project-local settings, resources, or project `.agents/skills` and has no saved decision for the folder or a parent folder in `~/.pi/agent/trust.json`. Trusting a project allows pi to load `.pi/settings.json` and `.pi` resources, install missing project packages, and execute project extensions.\n\nBefore the trust decision, pi loads only context files, user/global extensions, and CLI `-e` extensions so they can handle the `project_trust` event. Project-local extensions, project package-managed extensions, and project settings are loaded only after the project is trusted. This split also applies when switching to a session from a different cwd whose trust has not been resolved in the current process.\n\nNon-interactive modes (`-p`, `--mode json`, and `--mode rpc`) do not show a trust prompt. Without an applicable saved trust decision, they use `defaultProjectTrust` from global settings: `ask` (default) and `never` ignore those project resources, while `always` trusts them. Pass `--approve`/`-a` or `--no-approve`/`-na` to override project trust for one run.\n\nIf no extension or saved decision applies, `defaultProjectTrust` controls the fallback behavior. Set it to `\"ask\"`, `\"always\"`, or `\"never\"` in `~/.pi/agent/settings.json`, or change it with `/settings`.\n\n`pi config` and package commands use the same project trust flow, except `pi update` never prompts. Pass `--approve` to trust project-local settings for one command or `--no-approve` to ignore them.\n\nUse `/trust` in interactive mode to save a project trust decision for future sessions, including trust for the immediate parent folder. It writes `~/.pi/agent/trust.json` only; the current session is not reloaded, so restart pi for changes to take effect.\n\n### Telemetry and update checks\n\nPi has two separate startup features:\n\n- **Update check:** fetches `https://pi.dev/api/latest-version` to check whether a newer Pi version exists. Disable it with `PI_SKIP_VERSION_CHECK=1`. Disabling update checks only turns off this check.\n- **Install/update telemetry:** after first install or a changelog-detected update, sends an anonymous version ping to `https://pi.dev/api/report-install`. This setting also controls optional provider attribution headers for OpenRouter, Cloudflare, and direct NVIDIA NIM requests. Opt out by setting `enableInstallTelemetry` to `false` in `settings.json`, or by setting `PI_TELEMETRY=0`. This does not disable update checks; Pi may still contact `pi.dev` for the latest version unless update checks are disabled or offline mode is enabled.\n\nUse `--offline` or `PI_OFFLINE=1` to disable all startup network operations described here, including update checks, package update checks, and install/update telemetry.\n\n---\n\n## Context Files\n\nPi loads `AGENTS.md` (or `CLAUDE.md`) at startup from:\n- `~/.pi/agent/AGENTS.md` (global)\n- Parent directories (walking up from cwd)\n- Current directory\n\nUse for project instructions (`AGENTS.md`/`CLAUDE.md`), conventions, common commands. All matching files are concatenated.\n\nDisable context file loading with `--no-context-files` (or `-nc`).\n\n### System Prompt\n\nReplace the default system prompt with `.pi/SYSTEM.md` (project) or `~/.pi/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.\n\n---\n\n## Customization\n\n### Prompt Templates\n\nReusable prompts as Markdown files. Type `/name` to expand.\n\n```markdown\n<!-- ~/.pi/agent/prompts/review.md -->\nReview this code for bugs, security issues, and performance problems.\nFocus on: {{focus}}\n```\n\nPlace in `~/.pi/agent/prompts/`, `.pi/prompts/`, or a [pi package](#pi-packages) to share with others. See [docs/prompt-templates.md](docs/prompt-templates.md).\n\n### Skills\n\nOn-demand capability packages following the [Agent Skills standard](https://agentskills.io). Invoke via `/skill:name` or let the agent load them automatically.\n\n```markdown\n<!-- ~/.pi/agent/skills/my-skill/SKILL.md -->\n# My Skill\nUse this skill when the user asks about X.\n\n## Steps\n1. Do this\n2. Then that\n```\n\nPlace in `~/.pi/agent/skills/`, `~/.agents/skills/`, `.pi/skills/`, or `.agents/skills/` (from `cwd` up through parent directories) or a [pi package](#pi-packages) to share with others. See [docs/skills.md](docs/skills.md).\n\n### Extensions\n\n<p align=\"center\"><img src=\"docs/images/doom-extension.png\" alt=\"Doom Extension\" width=\"600\"></p>\n\nTypeScript modules that extend pi with custom tools, commands, keyboard shortcuts, event handlers, and UI components.\n\n```typescript\nexport default function (pi: ExtensionAPI) {\n pi.registerTool({ name: \"deploy\", ... });\n pi.registerCommand(\"stats\", { ... });\n pi.on(\"tool_call\", async (event, ctx) => { ... });\n}\n```\n\nThe default export can also be `async`. pi waits for async extension factories before startup continues, which is useful for one-time initialization such as fetching remote model lists before calling `pi.registerProvider()`.\n\n**What's possible:**\n- Custom tools (or replace built-in tools entirely)\n- Sub-agents and plan mode\n- Custom compaction and summarization\n- Permission gates and path protection\n- Custom editors and UI components\n- Status lines, headers, footers\n- Git checkpointing and auto-commit\n- SSH and sandbox execution\n- MCP server integration\n- Make pi look like Claude Code\n- Games while waiting (yes, Doom runs)\n- ...anything you can dream up\n\nPlace in `~/.pi/agent/extensions/`, `.pi/extensions/`, or a [pi package](#pi-packages) to share with others. See [docs/extensions.md](docs/extensions.md) and [examples/extensions/](examples/extensions/).\n\n### Themes\n\nBuilt-in: `dark`, `light`. Themes hot-reload: modify the active theme file and pi immediately applies changes.\n\nPlace in `~/.pi/agent/themes/`, `.pi/themes/`, or a [pi package](#pi-packages) to share with others. See [docs/themes.md](docs/themes.md).\n\n### Pi Packages\n\nBundle and share extensions, skills, prompts, and themes via npm or git. Find packages on [npmjs.com](https://www.npmjs.com/search?q=keywords%3Api-package) or [Discord](https://discord.com/channels/1456806362351669492/1457744485428629628).\n\n> **Security:** Pi packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.\n\n```bash\npi install npm:@foo/pi-tools\npi install npm:@foo/pi-tools@1.2.3 # pinned version\npi install git:github.com/user/repo\npi install git:github.com/user/repo@v1 # tag or commit\npi install git:git@github.com:user/repo\npi install git:git@github.com:user/repo@v1 # tag or commit\npi install https://github.com/user/repo\npi install https://github.com/user/repo@v1 # tag or commit\npi install ssh://git@github.com/user/repo\npi install ssh://git@github.com/user/repo@v1 # tag or commit\npi remove npm:@foo/pi-tools\npi uninstall npm:@foo/pi-tools # alias for remove\npi list\npi update # update pi only\npi update --all # update pi and packages\npi update --extensions # update packages only\npi update --models # refresh model catalogs only\npi update --self # update pi only\npi update --self --force # reinstall pi even if current\npi update npm:@foo/pi-tools # update one package\npi config # enable/disable extensions, skills, prompts, themes\n```\n\nPackages install to `~/.pi/agent/git/` (git) or `~/.pi/agent/npm/` (npm). Use `-l` for project-local installs (`.pi/git/`, `.pi/npm/`). Git `@ref` values are pinned tags or commits; pinned packages are skipped by `pi update --extensions` and `pi update --all`, so use `pi install git:host/user/repo@new-ref` to move an existing package to a new ref. Git packages install dependencies with `npm install --omit=dev` by default, so runtime deps must be listed under `dependencies`; when `npmCommand` is configured, git packages use plain `install` for compatibility with wrappers. If you use a Node version manager and want package installs to reuse a stable npm context, set `npmCommand` in `settings.json`, for example `[\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"]`.\n\nCreate a package by adding a `pi` key to `package.json`:\n\n```json\n{\n \"name\": \"my-pi-package\",\n \"keywords\": [\"pi-package\"],\n \"pi\": {\n \"extensions\": [\"./extensions\"],\n \"skills\": [\"./skills\"],\n \"prompts\": [\"./prompts\"],\n \"themes\": [\"./themes\"]\n }\n}\n```\n\nWithout a `pi` manifest, pi auto-discovers from conventional directories (`extensions/`, `skills/`, `prompts/`, `themes/`).\n\nSee [docs/packages.md](docs/packages.md).\n\n---\n\n## Programmatic Usage\n\n### SDK\n\n```typescript\nimport { createAgentSession, ModelRuntime, SessionManager } from \"@earendil-works/pi-coding-agent\";\n\nconst modelRuntime = await ModelRuntime.create();\nconst { session } = await createAgentSession({\n sessionManager: SessionManager.inMemory(),\n modelRuntime,\n});\n\nawait session.prompt(\"What files are in the current directory?\");\n```\n\nFor advanced multi-session runtime replacement, use `createAgentSessionRuntime()` and `AgentSessionRuntime`.\n\nSee [docs/sdk.md](docs/sdk.md) and [examples/sdk/](examples/sdk/).\n\n### RPC Mode\n\nFor non-Node.js integrations, use RPC mode over stdin/stdout:\n\n```bash\npi --mode rpc\n```\n\nRPC mode uses strict LF-delimited JSONL framing. Clients must split records on `\\n` only. Do not use generic line readers like Node `readline`, which also split on Unicode separators inside JSON payloads.\n\nSee [docs/rpc.md](docs/rpc.md) for the protocol.\n\n---\n\n## Philosophy\n\nPi is aggressively extensible so it doesn't have to dictate your workflow. Features that other tools bake in can be built with [extensions](#extensions), [skills](#skills), or installed from third-party [pi packages](#pi-packages). This keeps the core minimal while letting you shape pi to fit how you work.\n\n**No MCP.** Build CLI tools with READMEs (see [Skills](#skills)), or build an extension that adds MCP support. [Why?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)\n\n**No sub-agents.** There's many ways to do this. Spawn pi instances via tmux, or build your own with [extensions](#extensions), or install a package that does it your way.\n\n**No permission popups.** Run in a container, or build your own confirmation flow with [extensions](#extensions) inline with your environment and security requirements.\n\n**No plan mode.** Write plans to files, or build it with [extensions](#extensions), or install a package.\n\n**No built-in to-dos.** They confuse models. Use a TODO.md file, or build your own with [extensions](#extensions).\n\n**No background bash.** Use tmux. Full observability, direct interaction.\n\nRead the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/) for the full rationale.\n\n---\n\n## CLI Reference\n\n```bash\npi [options] [@files...] [messages...]\n```\n\n### Package Commands\n\n```bash\npi install <source> [-l] # Install package, -l for project-local\npi remove <source> [-l] # Remove package\npi uninstall <source> [-l] # Alias for remove\npi update [source|self|pi] # Update pi only, or one package source\npi update --all # Update pi and packages\npi update --extensions # Update packages only\npi update --models # Refresh model catalogs only\npi update --self # Update pi only\npi update --self --force # Reinstall pi even if current\npi update --extension <src> # Update one package\npi list # List installed packages\npi config # Enable/disable package resources\n```\n\n`pi config` and project package commands accept `--approve`/`--no-approve` to trust or ignore project-local settings for one command. `pi update` never prompts for project trust.\n\n### Modes\n\n| Flag | Description |\n|------|-------------|\n| (default) | Interactive mode |\n| `-p`, `--print` | Print response and exit |\n| `--mode json` | Output all events as JSON lines (see [docs/json.md](docs/json.md)) |\n| `--mode rpc` | RPC mode for process integration (see [docs/rpc.md](docs/rpc.md)) |\n| `--export <in> [out]` | Export session to HTML |\n\nIn print mode, pi also reads piped stdin and merges it into the initial prompt:\n\n```bash\ncat README.md | pi -p \"Summarize this text\"\n```\n\n### Model Options\n\n| Option | Description |\n|--------|-------------|\n| `--provider <name>` | Provider (anthropic, openai, google, etc.) |\n| `--model <pattern>` | Model pattern or ID (supports `provider/id` and optional `:<thinking>`) |\n| `--api-key <key>` | API key (overrides env vars) |\n| `--thinking <level>` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max` |\n| `--models <patterns>` | Comma-separated patterns for Ctrl+P cycling |\n| `--list-models [search]` | List available models |\n\n### Session Options\n\n| Option | Description |\n|--------|-------------|\n| `-c`, `--continue` | Continue most recent session |\n| `-r`, `--resume` | Browse and select session |\n| `--session <path\\|id>` | Use specific session file or partial UUID |\n| `--fork <path\\|id>` | Fork specific session file or partial UUID into a new session |\n| `--session-dir <dir>` | Custom session storage directory |\n| `--no-session` | Ephemeral mode (don't save) |\n| `--name <name>`, `-n <name>` | Set session display name at startup |\n\n### Tool Options\n\n| Option | Description |\n|--------|-------------|\n| `--tools <list>`, `-t <list>` | Allowlist specific tool names across built-in, extension, and custom tools |\n| `--exclude-tools <list>`, `-xt <list>` | Disable specific tool names across built-in, extension, and custom tools |\n| `--no-builtin-tools`, `-nbt` | Disable built-in tools by default but keep extension/custom tools enabled |\n| `--no-tools`, `-nt` | Disable all tools by default |\n\nAvailable built-in tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`\n\n### Resource Options\n\n| Option | Description |\n|--------|-------------|\n| `-e`, `--extension <source>` | Load extension from path, npm, or git (repeatable) |\n| `--no-extensions` | Disable extension discovery |\n| `--skill <path>` | Load skill (repeatable) |\n| `--no-skills` | Disable skill discovery |\n| `--prompt-template <path>` | Load prompt template (repeatable) |\n| `--no-prompt-templates` | Disable prompt template discovery |\n| `--theme <path>` | Load theme (repeatable) |\n| `--no-themes` | Disable theme discovery |\n| `--no-context-files`, `-nc` | Disable AGENTS.md and CLAUDE.md context file discovery |\n\nCombine `--no-*` with explicit flags to load exactly what you need, ignoring settings.json (e.g., `--no-extensions -e ./my-ext.ts`).\n\n### Other Options\n\n| Option | Description |\n|--------|-------------|\n| `--system-prompt <text>` | Replace default prompt (context files and skills still appended) |\n| `--append-system-prompt <text>` | Append to system prompt |\n| `--verbose` | Force verbose startup |\n| `-a`, `--approve` | Trust project-local files for this run |\n| `-na`, `--no-approve` | Ignore project-local files for this run |\n| `-h`, `--help` | Show help |\n| `-v`, `--version` | Show version |\n\n### File Arguments\n\nPrefix files with `@` to include in the message:\n\n```bash\npi @prompt.md \"Answer this\"\npi -p @screenshot.png \"What's in this image?\"\npi @code.ts @test.ts \"Review these files\"\n```\n\n### Examples\n\n```bash\n# Interactive with initial prompt\npi \"List all .ts files in src/\"\n\n# Non-interactive\npi -p \"Summarize this codebase\"\n\n# Non-interactive with piped stdin\ncat README.md | pi -p \"Summarize this text\"\n\n# Named one-shot session\npi --name \"release audit\" -p \"Audit this repository\"\n\n# Different model\npi --provider openai --model gpt-4o \"Help me refactor\"\n\n# Model with provider prefix (no --provider needed)\npi --model openai/gpt-4o \"Help me refactor\"\n\n# Model with thinking level shorthand\npi --model sonnet:high \"Solve this complex problem\"\n\n# Limit model cycling\npi --models \"claude-*,gpt-4o\"\n\n# Read-only mode\npi --tools read,grep,find,ls -p \"Review the code\"\n\n# Disable one extension or built-in tool while keeping the rest available\npi --exclude-tools ask_question\n\n# High thinking level\npi --thinking high \"Solve this complex problem\"\n```\n\n### Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `PI_CODING_AGENT_DIR` | Override config directory (default: `~/.pi/agent`) |\n| `PI_CODING_AGENT_SESSION_DIR` | Override session storage directory (overridden by `--session-dir`) |\n| `PI_PACKAGE_DIR` | Override package directory (useful for Nix/Guix where store paths tokenize poorly) |\n| `PI_OFFLINE` | Disable startup network operations, including update checks, package update checks, and install/update telemetry |\n| `PI_SKIP_VERSION_CHECK` | Skip the Pi version update check at startup. This prevents the `pi.dev` latest-version request |\n| `PI_TELEMETRY` | Override install/update telemetry and provider attribution headers. Use `1`/`true`/`yes` to enable or `0`/`false`/`no` to disable. This does not disable update checks |\n| `PI_CACHE_RETENTION` | Set to `long` for extended prompt cache (Anthropic: 1h, OpenAI: 24h) |\n| `VISUAL`, `EDITOR` | Fallback external editor for Ctrl+G when `externalEditor` is unset; defaults to Notepad on Windows and `nano` elsewhere |\n\n---\n\n## Contributing & Development\n\nSee [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines and [docs/development.md](docs/development.md) for setup, forking, and debugging.\n\n## License\n\nMIT\n\n## See Also\n\n- [@earendil-works/pi-ai](https://www.npmjs.com/package/@earendil-works/pi-ai): Core LLM toolkit\n- [@earendil-works/pi-agent-core](https://www.npmjs.com/package/@earendil-works/pi-agent-core): Agent framework\n- [@earendil-works/pi-tui](https://www.npmjs.com/package/@earendil-works/pi-tui): Terminal UI components\n\n<p align=\"center\">\n <a href=\"https://pi.dev\">pi.dev</a> domain graciously donated by\n <br /><br />\n <a href=\"https://exe.dev\"><img src=\"docs/images/exy.png\" alt=\"Exy mascot\" width=\"48\" /><br />exe.dev</a>\n</p>\n"}],"isError":false,"timestamp":1784909207401}}
|
||
{"type":"message","id":"3a81a291","parentId":"aab0c292","timestamp":"2026-07-24T16:06:51.813Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The README mentions prompt templates and commands. The user mentions \"c-{prompt}\" which I now see in their current directory: c-design-build.md, c-fix-commit.md, c-refactor-commit.md, c-security-loop.md. These are likely custom prompt templates in their dotfiles.\n\nBut the user says \"c-{prompt} so they don't create a new pi -p session\". This sounds like they have configured something so that when they type `c-design-build` or similar in their shell, it runs `pi -p` with that prompt template, creating a new session each time and running non-interactively. Once the chain starts, they can't stop it.\n\nWait, \"c-{prompt}\" might be commands/shell aliases. Let me look at the actual prompt template files and docs to understand what c-* means.\n\nAlso, they ask about \"an automatic tool that would just use whatever subagent or prompt is the most fitting\". This sounds like they want an extension that automatically routes to the best skill/prompt/subagent.\n\nLet me read the prompt templates docs and the actual c-* files.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:2","name":"read","arguments":{"path":"/home/liph/.local/lib/node_modules/@earendil-works/pi-coding-agent/docs/prompt-templates.md"}},{"type":"toolCall","id":"functions.read:3","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md"}},{"type":"toolCall","id":"functions.read:4","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md"}},{"type":"toolCall","id":"functions.read:5","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md"}},{"type":"toolCall","id":"functions.read:6","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":23842,"output":380,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":24222,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909207404,"responseId":"chatcmpl-643","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"460e9606","parentId":"3a81a291","timestamp":"2026-07-24T16:06:51.818Z","message":{"role":"toolResult","toolCallId":"functions.read:2","toolName":"read","content":[{"type":"text","text":"> pi can create prompt templates. Ask it to build one for your workflow.\n\n# Prompt Templates\n\nPrompt templates are Markdown snippets that expand into full prompts. Type `/name` in the editor to invoke a template, where `name` is the filename without `.md`.\n\n## Locations\n\nPi loads prompt templates from:\n\n- Global: `~/.pi/agent/prompts/*.md`\n- Project: `.pi/prompts/*.md` (only after the project is trusted)\n- Packages: `prompts/` directories or `pi.prompts` entries in `package.json`\n- Settings: `prompts` array with files or directories\n- CLI: `--prompt-template <path>` (repeatable)\n\nDisable discovery with `--no-prompt-templates`.\n\n## Format\n\n```markdown\n---\ndescription: Review staged git changes\n---\nReview the staged changes (`git diff --cached`). Focus on:\n- Bugs and logic errors\n- Security issues\n- Error handling gaps\n```\n\n- The filename becomes the command name. `review.md` becomes `/review`.\n- `description` is optional. If missing, the first non-empty line is used.\n- `argument-hint` is optional. When set, the hint is displayed before the description in the autocomplete dropdown.\n\n### Argument Hints\n\nUse `argument-hint` in frontmatter to show expected arguments in autocomplete. Use `<angle brackets>` for required arguments and `[square brackets]` for optional ones:\n\n```markdown\n---\ndescription: Review PRs from URLs with structured issue and code analysis\nargument-hint: \"<PR-URL>\"\n---\n```\n\nThis renders in the autocomplete dropdown as:\n\n```\n→ pr <PR-URL> — Review PRs from URLs with structured issue and code analysis\n is <issue> — Analyze GitHub issues (bugs or feature requests)\n wr [instructions] — Finish the current task end-to-end\n cl — Audit changelog entries before release\n```\n\n## Usage\n\nType `/` followed by the template name in the editor. Autocomplete shows available templates with descriptions.\n\n```\n/review # Expands review.md\n/component Button # Expands with argument\n/component Button \"click handler\" # Multiple arguments\n```\n\n## Arguments\n\nTemplates support positional arguments, defaults, and simple slicing:\n\n- `$1`, `$2`, ... positional args\n- `$@` or `$ARGUMENTS` for all args joined\n- `${1:-default}` uses arg 1 when present/non-empty, otherwise `default`\n- `${@:-default}` or `${ARGUMENTS:-default}` uses all arguments when present/non-empty, otherwise `default`\n- `${@:N}` for args from the Nth position (1-indexed)\n- `${@:N:L}` for `L` args starting at N\n\nExample:\n\n```markdown\n---\ndescription: Create a component\n---\nCreate a React component named $1 with features: $@\n```\n\nDefault values are useful for optional arguments:\n\n```markdown\nSummarize the current state in ${1:-7} bullet points.\n```\n\nUsage: `/component Button \"onClick handler\" \"disabled support\"`\n\n## Loading Rules\n\n- Template discovery in `prompts/` is non-recursive.\n- If you want templates in subdirectories, add them explicitly via `prompts` settings or a package manifest.\n"}],"isError":false,"timestamp":1784909211818}}
|
||
{"type":"message","id":"499e09fe","parentId":"460e9606","timestamp":"2026-07-24T16:06:51.818Z","message":{"role":"toolResult","toolCallId":"functions.read:3","toolName":"read","content":[{"type":"text","text":"---\ndescription: Brainstorm → plan → test → commit in one background chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n"}],"isError":false,"timestamp":1784909211818}}
|
||
{"type":"message","id":"e23c77e3","parentId":"499e09fe","timestamp":"2026-07-24T16:06:51.818Z","message":{"role":"toolResult","toolCallId":"functions.read:4","toolName":"read","content":[{"type":"text","text":"---\ndescription: Summarize → diagnose → debug → test in one background chain\nargument-hint: \"[symptom, error, or observed behavior]\"\nchain: p-summarize -> p-diagnose -> p-debug -> p-test\n---\nRun the understand → diagnose → fix → regression-test chain for: $@\n\nInvoke with:\n/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n"}],"isError":false,"timestamp":1784909211818}}
|
||
{"type":"message","id":"7096270f","parentId":"e23c77e3","timestamp":"2026-07-24T16:06:51.818Z","message":{"role":"toolResult","toolCallId":"functions.read:5","toolName":"read","content":[{"type":"text","text":"---\ndescription: Refactor → test → review → commit in one background chain\nargument-hint: \"[file path or symbol to refactor]\"\nchain: p-refactor -> p-test -> p-review -> p-commit\n---\nRun the safe refactor → validate → review → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n"}],"isError":false,"timestamp":1784909211818}}
|
||
{"type":"message","id":"595af1c3","parentId":"7096270f","timestamp":"2026-07-24T16:06:51.818Z","message":{"role":"toolResult","toolCallId":"functions.read:6","toolName":"read","content":[{"type":"text","text":"---\ndescription: Security audit → review → test in one background chain\nargument-hint: \"[file path, diff, or feature to audit]\"\nchain: p-secaudit -> p-review -> p-test\n---\nRun the security-first review loop for: $@\n\nInvoke with:\n/prompt-workflow c-security-loop --bg \"auth endpoint\"\n"}],"isError":false,"timestamp":1784909211818}}
|
||
{"type":"message","id":"a978d99b","parentId":"595af1c3","timestamp":"2026-07-24T16:06:58.685Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Interesting! These prompt templates have frontmatter with `chain: p-brainstorm -> p-plan -> p-test -> p-commit` and an `Invoke with: /prompt-workflow c-design-build --bg \"...\"` line. This is NOT standard pi prompt template behavior. This looks like it's using an extension or a custom pi package that implements `/prompt-workflow` command.\n\nWait, actually, the user is in `/home/liph/dotfiles/pi/.pi/agent/prompts` which is a dotfiles repo, but the prompt templates reference `/prompt-workflow` and `chain:` which is not documented in the prompt-templates.md. This must be from a custom extension or pi package they installed.\n\nAlso, they mention \"c-{prompt}\" so \"c-design-build\" is one of the prompt templates. The `c-` prefix likely stands for \"chain\". These templates have a `chain:` frontmatter that defines a workflow.\n\nThe user says: \"is there a way to change the c-{prompt} so they don't create a new pi -p session. once the chain starts i have no option to stop them.\"\n\nSo it seems like these chains are creating new `pi -p` (print mode) sessions and running the whole chain. The user wants to either:\n1. Run them interactively (in the current session), or\n2. Have a way to stop them.\n\nLet me look at the `.pi-subagents` directory and the `Doc` directory. There's also a `test` directory. Maybe this is using the pi-subagents skill or a babysitter workflow. Let me explore.\n\nAlso, the current working directory is the dotfiles repo, so the user might have installed pi packages via npm/git in `~/.pi/agent/`. I should check what packages/extensions they have.\n\nLet me look at the directory structure and check if there's a prompt-workflow extension.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:7","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/"}},{"type":"toolCall","id":"functions.bash:8","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/extensions/ 2>/dev/null || echo 'no extensions dir'"}},{"type":"toolCall","id":"functions.bash:9","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/skills/ 2>/dev/null || echo 'no skills dir'"}},{"type":"toolCall","id":"functions.bash:10","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/npm/ 2>/dev/null || echo 'no npm dir'"}},{"type":"toolCall","id":"functions.bash:11","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/git/ 2>/dev/null || echo 'no git dir'"}},{"type":"toolCall","id":"functions.bash:12","name":"bash","arguments":{"command":"ls -la /home/liph/dotfiles/pi/.pi/agent/prompts/.pi-subagents/"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":25257,"output":598,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":25855,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909211820,"responseId":"chatcmpl-444","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"0123412b","parentId":"a978d99b","timestamp":"2026-07-24T16:06:58.725Z","message":{"role":"toolResult","toolCallId":"functions.bash:7","toolName":"bash","content":[{"type":"text","text":"total 68\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:05 .\ndrwxr-xr-x 6 liph liph 4096 Jul 23 20:54 ..\ndrwxr-xr-x 2 liph liph 4096 Jul 24 17:23 agents\n-rw-r--r-- 1 liph liph 121 Jul 21 21:24 auth.json\ndrwxr-xr-x 4 liph liph 4096 Jul 24 08:22 extensions\n-rw-r--r-- 1 liph liph 1345 Jul 22 12:50 models.json\ndrwxr-xr-x 3 liph liph 4096 Jul 21 21:26 npm\ndrwxr-xr-x 2 liph liph 4096 Jul 23 20:51 profiles\ndrwxr-xr-x 5 liph liph 4096 Jul 24 18:02 prompts\n-rw-r--r-- 1 liph liph 4863 Jul 24 17:47 run-history.jsonl\ndrwxr-xr-x 21 liph liph 4096 Jul 24 16:47 sessions\n-rw-r--r-- 1 liph liph 1452 Jul 24 16:28 settings.json\ndrwxr-xr-x 2 liph liph 4096 Jul 24 09:36 skills\ndrwxr-xr-x 2 liph liph 4096 Jul 23 20:34 state\ndrwxr-xr-x 2 liph liph 4096 Jul 24 08:34 themes\n-rw-r--r-- 1 liph liph 25 Jul 22 12:50 trust.json\n"}],"isError":false,"timestamp":1784909218725}}
|
||
{"type":"message","id":"9c3dcb02","parentId":"0123412b","timestamp":"2026-07-24T16:06:58.725Z","message":{"role":"toolResult","toolCallId":"functions.bash:8","toolName":"bash","content":[{"type":"text","text":"total 16\ndrwxr-xr-x 4 liph liph 4096 Jul 24 08:22 .\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:05 ..\ndrwxr-xr-x 2 liph liph 4096 Jul 22 12:50 pi-web-agent\ndrwxr-xr-x 2 liph liph 4096 Jul 24 08:32 subagent\n"}],"isError":false,"timestamp":1784909218725}}
|
||
{"type":"message","id":"089b1d1d","parentId":"9c3dcb02","timestamp":"2026-07-24T16:06:58.725Z","message":{"role":"toolResult","toolCallId":"functions.bash:9","toolName":"bash","content":[{"type":"text","text":"total 8\ndrwxr-xr-x 2 liph liph 4096 Jul 24 09:36 .\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:05 ..\n"}],"isError":false,"timestamp":1784909218725}}
|
||
{"type":"message","id":"0178ff5d","parentId":"089b1d1d","timestamp":"2026-07-24T16:06:58.725Z","message":{"role":"toolResult","toolCallId":"functions.bash:10","toolName":"bash","content":[{"type":"text","text":"total 864\ndrwxr-xr-x 3 liph liph 4096 Jul 21 21:26 .\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:05 ..\n-rw-r--r-- 1 liph liph 14 Jul 21 21:24 .gitignore\ndrwxr-xr-x 228 liph liph 20480 Jul 23 20:53 node_modules\n-rw-r--r-- 1 liph liph 403 Jul 22 13:03 package.json\n-rw-r--r-- 1 liph liph 845510 Jul 22 13:03 package-lock.json\n"}],"isError":false,"timestamp":1784909218725}}
|
||
{"type":"message","id":"900e9a5f","parentId":"0178ff5d","timestamp":"2026-07-24T16:06:58.725Z","message":{"role":"toolResult","toolCallId":"functions.bash:11","toolName":"bash","content":[{"type":"text","text":"no git dir\n"}],"isError":false,"timestamp":1784909218725}}
|
||
{"type":"message","id":"19cd14af","parentId":"900e9a5f","timestamp":"2026-07-24T16:06:58.725Z","message":{"role":"toolResult","toolCallId":"functions.bash:12","toolName":"bash","content":[{"type":"text","text":"total 16\ndrwxr-xr-x 4 liph liph 4096 Jul 24 17:42 .\ndrwxr-xr-x 5 liph liph 4096 Jul 24 18:02 ..\ndrwxr-xr-x 2 liph liph 4096 Jul 24 18:05 artifacts\ndrwxr-xr-x 5 liph liph 4096 Jul 24 17:45 chain-runs\n"}],"isError":false,"timestamp":1784909218725}}
|
||
{"type":"message","id":"34f6f2b4","parentId":"19cd14af","timestamp":"2026-07-24T16:07:00.812Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"There's an extension called \"subagent\" in ~/.pi/agent/extensions/. And npm package directory. The `.pi-subagents` directory has artifacts and chain-runs. This is definitely the pi-subagents extension/skill creating chains. Let me look at the subagent extension and the npm package.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:13","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/extensions/subagent/"}},{"type":"toolCall","id":"functions.read:14","name":"read","arguments":{"path":"/home/liph/.pi/agent/extensions/subagent/package.json"}},{"type":"toolCall","id":"functions.bash:15","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/npm/node_modules/pi-subagents/ 2>/dev/null || ls -la /home/liph/.pi/agent/npm/"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":26765,"output":161,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":26926,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909218727,"responseId":"chatcmpl-49","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"361a40bf","parentId":"34f6f2b4","timestamp":"2026-07-24T16:07:00.839Z","message":{"role":"toolResult","toolCallId":"functions.bash:13","toolName":"bash","content":[{"type":"text","text":"total 8\ndrwxr-xr-x 2 liph liph 4096 Jul 24 08:32 .\ndrwxr-xr-x 4 liph liph 4096 Jul 24 08:22 ..\n"}],"isError":false,"timestamp":1784909220839}}
|
||
{"type":"message","id":"8415f828","parentId":"361a40bf","timestamp":"2026-07-24T16:07:00.839Z","message":{"role":"toolResult","toolCallId":"functions.read:14","toolName":"read","content":[{"type":"text","text":"ENOENT: no such file or directory, access '/home/liph/.pi/agent/extensions/subagent/package.json'"}],"details":{},"isError":true,"timestamp":1784909220839}}
|
||
{"type":"message","id":"66eb3a9f","parentId":"8415f828","timestamp":"2026-07-24T16:07:00.839Z","message":{"role":"toolResult","toolCallId":"functions.bash:15","toolName":"bash","content":[{"type":"text","text":"total 292\ndrwxr-xr-x 7 liph liph 4096 Jul 22 13:03 .\ndrwxr-xr-x 228 liph liph 20480 Jul 23 20:53 ..\ndrwxr-xr-x 2 liph liph 4096 Jul 22 13:03 agents\n-rw-r--r-- 1 liph liph 128942 Jul 22 13:03 CHANGELOG.md\n-rw-r--r-- 1 liph liph 52 Jul 22 13:03 index.ts\n-rwxr-xr-x 1 liph liph 2703 Jul 22 13:03 install.mjs\ndrwxr-xr-x 4 liph liph 4096 Jul 22 13:03 node_modules\n-rw-r--r-- 1 liph liph 2435 Jul 22 13:03 package.json\ndrwxr-xr-x 2 liph liph 4096 Jul 22 13:03 prompts\n-rw-r--r-- 1 liph liph 106519 Jul 22 13:03 README.md\ndrwxr-xr-x 3 liph liph 4096 Jul 22 13:03 skills\ndrwxr-xr-x 12 liph liph 4096 Jul 22 13:03 src\n"}],"isError":false,"timestamp":1784909220839}}
|
||
{"type":"message","id":"97fafa24","parentId":"66eb3a9f","timestamp":"2026-07-24T16:07:03.851Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"So there is a pi-subagents package installed in ~/.pi/agent/npm/node_modules/pi-subagents/. The extension directory at ~/.pi/agent/extensions/subagent/ is empty (probably a symlink or placeholder? Let me check more carefully). Also there's an index.ts. Let me read the package.json of pi-subagents and explore.\n\nAlso, I should check the user's settings.json to see what's enabled.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:16","name":"read","arguments":{"path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/package.json"}},{"type":"toolCall","id":"functions.read:17","name":"read","arguments":{"path":"/home/liph/.pi/agent/settings.json"}},{"type":"toolCall","id":"functions.bash:18","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/extensions/subagent/ && file /home/liph/.pi/agent/extensions/subagent/* 2>/dev/null"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":27358,"output":175,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":27533,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909220841,"responseId":"chatcmpl-792","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"a61df8e5","parentId":"97fafa24","timestamp":"2026-07-24T16:07:03.872Z","message":{"role":"toolResult","toolCallId":"functions.read:16","toolName":"read","content":[{"type":"text","text":"{\n \"name\": \"pi-subagents\",\n \"version\": \"0.35.1\",\n \"description\": \"Pi extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification\",\n \"author\": \"Nico Bailon\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"exports\": {\n \".\": \"./index.ts\",\n \"./background-work\": \"./src/api/background-work.ts\",\n \"./delegation\": \"./src/api/delegation.ts\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/nicobailon/pi-subagents.git\"\n },\n \"homepage\": \"https://github.com/nicobailon/pi-subagents#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/nicobailon/pi-subagents/issues\"\n },\n \"keywords\": [\n \"pi-package\",\n \"pi\",\n \"pi-coding-agent\",\n \"subagents\",\n \"ai\",\n \"agents\",\n \"cli\"\n ],\n \"bin\": {\n \"pi-subagents\": \"install.mjs\"\n },\n \"files\": [\n \"index.ts\",\n \"src/**/*.ts\",\n \"*.mjs\",\n \"agents/\",\n \"skills/**/*\",\n \"prompts/**/*\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"scripts\": {\n \"test\": \"npm run test:unit\",\n \"test:unit\": \"node --experimental-strip-types --test test/unit/*.test.ts\",\n \"test:integration\": \"node --experimental-transform-types --import ./test/support/register-loader.mjs --test test/integration/*.test.ts\",\n \"test:e2e\": \"node --experimental-transform-types --import ./test/support/register-loader.mjs --test test/e2e/*.test.ts\",\n \"test:all\": \"npm run test:unit && npm run test:integration && npm run test:e2e\"\n },\n \"pi\": {\n \"extensions\": [\n \"./index.ts\"\n ],\n \"skills\": [\n \"./skills\"\n ],\n \"prompts\": [\n \"./prompts\"\n ]\n },\n \"peerDependencies\": {\n \"@earendil-works/pi-agent-core\": \"*\",\n \"@earendil-works/pi-ai\": \"*\",\n \"@earendil-works/pi-coding-agent\": \"*\",\n \"@earendil-works/pi-tui\": \"*\",\n \"typebox\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"@earendil-works/pi-agent-core\": {\n \"optional\": true\n },\n \"@earendil-works/pi-ai\": {\n \"optional\": true\n },\n \"@earendil-works/pi-coding-agent\": {\n \"optional\": true\n },\n \"@earendil-works/pi-tui\": {\n \"optional\": true\n },\n \"typebox\": {\n \"optional\": true\n }\n },\n \"dependencies\": {\n \"jiti\": \"2.7.0\",\n \"yaml\": \"2.8.3\"\n },\n \"devDependencies\": {\n \"@earendil-works/pi-agent-core\": \"0.80.10\",\n \"@earendil-works/pi-ai\": \"0.80.10\",\n \"@earendil-works/pi-coding-agent\": \"0.80.10\",\n \"@earendil-works/pi-tui\": \"0.80.10\",\n \"typebox\": \"1.1.38\"\n }\n}\n"}],"isError":false,"timestamp":1784909223872}}
|
||
{"type":"message","id":"70fad6e6","parentId":"a61df8e5","timestamp":"2026-07-24T16:07:03.872Z","message":{"role":"toolResult","toolCallId":"functions.read:17","toolName":"read","content":[{"type":"text","text":"{\n \"lastChangelogVersion\": \"0.81.1\",\n \"theme\": \"crew-dracula/crew-dracula\",\n \"packages\": [\n \"npm:pi-ollama-cloud\",\n \"npm:context-mode\",\n \"npm:pi-subagents\",\n \"npm:@a5c-ai/babysitter-pi\",\n \"npm:@juicesharp/rpiv-ask-user-question\",\n \"npm:@ff-labs/pi-fff\",\n \"npm:@demigodmode/pi-web-agent\"\n ],\n \"defaultProvider\": \"ollama\",\n \"defaultModel\": \"kimi-k2.7-code:cloud\",\n \"defaultThinkingLevel\": \"medium\",\n \"subagents\": {\n \"agentOverrides\": {\n \"scout\": {\n \"model\": \"ollama/minimax-m3:cloud\",\n \"thinking\": \"high\"\n },\n \"planner\": {\n \"model\": \"ollama/minimax-m3:cloud\",\n \"thinking\": \"high\"\n },\n \"worker\": {\n \"model\": \"ollama/kimi-k2.7-code:cloud\",\n \"thinking\": \"high\"\n },\n \"oracle\": {\n \"model\": \"ollama/minimax-m3:cloud\",\n \"thinking\": \"high\"\n },\n \"reviewer\": {\n \"model\": \"ollama/kimi-k2.6:cloud\",\n \"thinking\": \"high\"\n },\n \"researcher\": {\n \"model\": \"ollama/minimax-m3:cloud\",\n \"thinking\": \"high\"\n },\n \"context-builder\": {\n \"model\": \"ollama/minimax-m3:cloud\",\n \"thinking\": \"high\"\n },\n \"delegate\": {\n \"model\": \"ollama/minimax-m3:cloud\"\n }\n },\n \"modelScope\": {\n \"allow\": [\n \"ollama/minimax-m3:cloud\",\n \"ollama/kimi-k2.6:cloud\",\n \"ollama/kimi-k2.7-code:cloud\",\n \"ollama/gemini-3-flash-preview\"\n ]\n }\n }\n}"}],"isError":false,"timestamp":1784909223872}}
|
||
{"type":"message","id":"a0f366ca","parentId":"70fad6e6","timestamp":"2026-07-24T16:07:03.872Z","message":{"role":"toolResult","toolCallId":"functions.bash:18","toolName":"bash","content":[{"type":"text","text":"total 8\ndrwxr-xr-x 2 liph liph 4096 Jul 24 08:32 .\ndrwxr-xr-x 4 liph liph 4096 Jul 24 08:22 ..\n/home/liph/.pi/agent/extensions/subagent/*: cannot open `/home/liph/.pi/agent/extensions/subagent/*' (No such file or directory)\n"}],"isError":false,"timestamp":1784909223872}}
|
||
{"type":"message","id":"729d7030","parentId":"a0f366ca","timestamp":"2026-07-24T16:07:06.556Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now I understand. The user has pi-subagents package installed. The c-* prompts are custom prompts that use a `/prompt-workflow` command which is likely added by pi-subagents extension, or it's a skill command. The extension directory is empty because packages are loaded from ~/.pi/agent/npm/node_modules/pi-subagents/.\n\nThe user is asking:\n1. Can the c-{prompt} templates be changed so they don't create a new `pi -p` session (i.e., don't start a non-interactive chain)? They want to be able to stop them once started.\n2. Is there an automatic tool that picks the most fitting subagent/prompt?\n\nI need to read the pi-subagents README to understand how `/prompt-workflow` works and if there's an option to run chains interactively vs background. Let me read the relevant sections.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:19","name":"read","arguments":{"path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/README.md","limit":400}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":28909,"output":207,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":29116,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909223873,"responseId":"chatcmpl-951","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"a09b45b7","parentId":"729d7030","timestamp":"2026-07-24T16:07:06.558Z","message":{"role":"toolResult","toolCallId":"functions.read:19","toolName":"read","content":[{"type":"text","text":"<p>\n <img src=\"https://raw.githubusercontent.com/nicobailon/pi-subagents/main/banner.png\" alt=\"pi-subagents\" width=\"1100\">\n</p>\n\n# pi-subagents\n\n`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.\n\nhttps://github.com/user-attachments/assets/702554ec-faaf-4635-80aa-fb5d6e292fd1\n\n## Installation\n\n```bash\npi install npm:pi-subagents\n```\n\nThat is the only required step. You can add optional pieces later.\n\n## Try this first\n\nYou do not need to create agents, write config, or learn slash commands. After installing, ask Pi for delegation in plain language:\n\n```text\nUse reviewer to review this diff.\n```\n\n```text\nAsk oracle for a second opinion on my current plan.\n```\n\n```text\nUse scout to understand this code based on our discussion then ask me clarification questions.\n```\n\n```text\nRun parallel reviewers: one for correctness, one for tests, and one for unnecessary complexity.\n```\n\nThat is enough to start.\n\n## What happens\n\nPi is the parent session. A subagent is a focused child Pi session with its own job.\n\nWhen 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.\n\nInstalling 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:\n\n```text\nWhen you finish implementing, run a reviewer subagent before summarizing.\n```\n\n## Good first prompts\n\nThese cover most day-to-day use:\n\n```text\nAsk oracle for a second opinion on my current plan. Challenge assumptions and tell me what I might be missing.\n```\n\n```text\nUse oracle to help solve this hard bug. Have it inspect the code and propose the best next move before we edit anything.\n```\n\n```text\nRun parallel reviewers on this diff. I want one focused on correctness, one on tests, and one on unnecessary complexity.\n```\n\n```text\nHave worker implement this approved plan. Afterward, run parallel reviewers, summarize their feedback, and apply the fixes that make sense.\n```\n\n```text\nRun a review loop on this change until reviewers stop finding fixes worth doing, with a max of 3 rounds.\n```\n\n```text\nUse scout to understand the auth flow, then have planner turn that into an implementation plan.\n```\n\nThose are ordinary Pi requests. Pi decides whether to call `subagent`, which agent to use, and whether a chain or parallel run makes sense.\n\n## Common workflows\n\n| Want | Ask naturally |\n|------|---------------|\n| Get a second opinion | “Ask oracle to review this plan and challenge assumptions.” |\n| Solve a hard problem | “Use oracle to investigate this bug before we edit.” |\n| Review a diff | “Use reviewer to review this diff.” |\n| Run parallel reviewers | “Run reviewers for correctness, tests, and cleanup.” |\n| Implement then review | “Implement this, then review it.” |\n| Review until clean | “Run a review loop on this change with a max of 3 rounds.” |\n| Execute a plan carefully | “Have worker implement this approved plan, then run reviewers and apply the feedback.” |\n| Scout before planning | “Use scout to inspect the auth flow before planning.” |\n| Run in the background | “Run this in the background.” |\n| Browse agents | “Show me the available subagents.” |\n| Use a saved workflow | “Run the review chain on this branch.” |\n| See running work | “Show active async runs.” or “Show the subagent fleet.” |\n| Check setup | “Check whether subagents are configured correctly.” |\n\nThe extension ships with builtin agents you can use immediately.\n\n## Builtin agents in plain English\n\n| Agent | Use it when you want... |\n|-------|--------------------------|\n| `scout` | Fast local codebase recon: relevant files, entry points, data flow, risks, and where another agent should start. |\n| `researcher` | Web/docs research with sources: official docs, specs, benchmarks, recent changes, and a concise research brief. |\n| `planner` | A concrete implementation plan from existing context. It should read and plan, not edit code. |\n| `worker` | Implementation work, including approved oracle handoffs. It edits files, validates, and escalates unapproved decisions instead of guessing. |\n| `reviewer` | Code review and small fixes. It checks the implementation against the task/plan, tests, edge cases, and simplicity. |\n| `context-builder` | A stronger setup pass before planning: gathers code context and writes handoff material such as `context.md` and `meta-prompt.md`. |\n| `oracle` | A second opinion before acting. It challenges assumptions, catches drift, and recommends the safest next move without editing. |\n| `delegate` | A lightweight general delegate when you want a child agent that behaves close to the parent session. |\n\nA 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.\n\n## Changing an agent's model\n\nBuiltin 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.\n\n```json\n{\n \"defaultModel\": \"deepseek-v4-pro\",\n \"subagents\": {\n \"defaultModel\": \"deepseek-v4-flash\",\n \"agentOverrides\": {\n \"oracle\": {\n \"model\": \"deepseek-v4-pro\"\n }\n }\n }\n}\n```\n\nFor one run, put the override in the command:\n\n```text\n/run reviewer[model=anthropic/claude-sonnet-4:high] \"Review this diff\"\n```\n\nFor 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:\n\n```json\n{\n \"subagents\": {\n \"agentOverrides\": {\n \"reviewer\": {\n \"model\": \"anthropic/claude-sonnet-4\",\n \"thinking\": \"high\",\n \"fallbackModels\": [\"openai/gpt-5-mini\"]\n }\n }\n }\n}\n```\n\nUse `~/.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.\n\nIf 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.\n\nTo inspect what `pi-subagents` has actually loaded right now, use:\n\n```text\n/subagents-models\n/subagents-models reviewer\n```\n\nThat reports the live runtime mapping, which can differ from settings on disk until you reload Pi.\n\nYou 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.\n\n### Choosing a watchdog model\n\nThe 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.\n\nThe 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.\n\nWhen 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`.\n\nUse `/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.\n\n```text\n/subagents-watchdog recommend-model\n/subagents-watchdog session model recommended\n/subagents-watchdog model recommended\n```\n\n`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.\n\nYou can also set the model explicitly:\n\n```text\n/subagents-watchdog model anthropic/claude-opus-4-8:high\n/subagents-watchdog model openai-codex/gpt-5.5:high\n/subagents-watchdog model inherit\n/subagents-watchdog check\n```\n\nFor 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.\n\n```json\n{\n \"subagents\": {\n \"watchdog\": {\n \"enabled\": true,\n \"main\": {\n \"model\": \"anthropic/claude-opus-4-8\",\n \"thinking\": \"high\"\n }\n }\n }\n}\n```\n\nFor 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.\n\nAgents can configure the same values through the tool when you ask them to set up the watchdog:\n\n```ts\nsubagent({ action: \"watchdog.recommend-model\" })\nsubagent({ action: \"watchdog.configure\", model: \"recommended\", scope: \"session\" })\nsubagent({ action: \"watchdog.configure\", model: \"recommended\", scope: \"project\" })\n```\n\nPersistent scopes (`user` or `project`) should only be used when you ask for a lasting default. Otherwise the agent should use `scope: \"session\"`.\n\nTo keep subagents inside a budget or compliance profile, enforce a model scope. Put `subagents.modelScope` in user or project settings (project overrides user):\n\n```json\n{\n \"subagents\": {\n \"modelScope\": {\n \"enforce\": true,\n \"allow\": [\"anthropic/*\", \"openai/gpt-5-*\"]\n }\n }\n}\n```\n\n`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.\n\n## Where running subagents show up\n\nForeground runs stream progress in the conversation while they run.\n\nBackground 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.\n\nThey 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.\n\nYou can also ask naturally:\n\n```text\nShow me the current async runs.\n```\n\nAsync 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.\n\nForeground 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.\n\nThe 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.\n\nOther 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>`.\n\n```typescript\nconst requestId = crypto.randomUUID();\npi.events.on(`subagents:rpc:v1:reply:${requestId}`, (reply) => {\n // { version: 1, requestId, success: true, data } or\n // { version: 1, requestId, success: false, error: { code, message } }\n});\npi.events.emit(\"subagents:rpc:v1:request\", {\n version: 1,\n requestId,\n method: \"spawn\",\n params: { agent: \"reviewer\", task: \"Review the current diff\", context: \"fresh\" }\n});\n```\n\nThe 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.\n\n`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.\n\nIf something feels misconfigured, run:\n\n```text\n/subagents-doctor\n```\n\nor ask:\n\n```text\nCheck whether subagents and intercom are set up correctly.\n```\n\n## Recommended orchestration pattern (scaffolding)\n\nUse orchestration as parent-agent guidance, not as a runtime workflow mode. For implementation work, the recommended loop is:\n\n```text\nclarify → planner → worker → fresh reviewers → worker\n```\n\nUse the optional prompt shortcuts below when you want the pattern to be repeatable.\n\nPackaged `planner`, `worker`, and `oracle` default to forked context when a launch omits `context`; pass `context: \"fresh\"` when you intentionally want a fresh child run.\n\nChild-safety boundaries are enforced at runtime. Spawned child sessions do not receive the bundled `pi-subagents` skill, and forked child context filtering removes parent-only subagent artifacts (including old hidden orchestration-instruction messages, slash/status/control messages, and prior parent `subagent` tool-call/tool-result history) while preserving ordinary prose and unrelated tool calls/results. By default, children do not register the `subagent` tool and receive boundary instructions that they are not the parent orchestrator and must not propose or run subagents. The explicit exception is an agent whose resolved builtin `tools` includes `subagent`; that child gets a child-safe `subagent` tool for the fanout work the parent assigned, still bounded by `maxSubagentDepth`.\n\n## Optional shortcuts\n\nThe package includes reusable prompt templates for common workflows. You do not need them, but they are handy when you want the same shape every time:\n\n| Prompt | Use it for |\n|--------|------------|\n| `/parallel-review` | Launch fresh-context reviewers with distinct angles, then synthesize what to fix. |\n| `/review-loop` | Run parent-controlled worker, reviewer, and fix-worker cycles until clean or capped. |\n| `/parallel-research` | Combine `researcher` and `scout` for external evidence, local code context, and practical tradeoffs. |\n| `/parallel-context-build` | Run `context-builder` agents in parallel to produce planning handoff context and meta-prompts. |\n| `/parallel-handoff-plan` | Combine external research and `context-builder` passes into an implementation handoff plan and meta-prompt. |\n| `/gather-context-and-clarify` | Scout/research first, then ask the user the clarification questions that matter. |\n| `/parallel-cleanup` | Run review-only cleanup passes after implementation. |\n\nAdd `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the synthesized fixes worth doing now after reviewers return.\n\n## Native supervisor coordination\n\nChild agents can talk back to the parent Pi session without installing `pi-intercom`. `pi-subagents` now provides the child-facing `contact_supervisor` tool and the parent-facing `subagent_supervisor({ action: \"reply\" })` path natively. If no external `pi-intercom` tool owns the `intercom` name, the native channel also exposes `intercom` as a compatibility fallback.\n\nUse it for work where the child might need a decision instead of guessing:\n\n```text\nRun this implementation in the background. If the worker gets blocked or needs a product decision, have it ask me through intercom.\n```\n\n```text\nAsk oracle to review this plan. If it sees a decision I need to make, have it ask me instead of assuming.\n```\n\nThe child can use one dedicated coordination tool:\n\n- `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: \"need_decision\"` for blocking decisions or clarification, `reason: \"interview_request\"` for structured input, and `reason: \"progress_update\"` for short non-blocking updates when a discovery changes the plan. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions; no-edit wins.\n\nThe parent replies with `subagent_supervisor({ action: \"reply\", replyTo, message })` or checks pending requests with `subagent_supervisor({ action: \"pending\" })`. Supervisor messages are scoped to the exact Pi session id that spawned the child. A second Pi session in the same repository does not receive those requests.\n\nChild-side routine completion handoffs are still not expected. If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: \"status\" })`, interrupting the run, or nudging the child.\n\nIf messages do not show up, run:\n\n```text\n/subagents-doctor\n```\n\nFor normal use, you do not need to configure anything. Advanced users can tune the bridge with `intercomBridge` in the configuration section below.\n\nAt this point, you know enough to use the plugin. The rest of this README is reference material for exact command syntax, custom agents, saved chains, worktrees, and configuration.\n\n## Optional pi-permission-system integration\n\n[`@gotgenes/pi-permission-system`](https://github.com/gotgenes/pi-packages/tree/main/packages/pi-permission-system)\nadds a second policy layer — `allow` / `ask` / `deny` — on top of\npi-subagents' visibility-based tool restrictions.\n\nThe two compose independently:\n\n| Layer | What it controls | Who provides it |\n|-------|-----------------|-----------------|\n| Visibility | Which tools are registered before the session starts | pi-subagents (`tools:` frontmatter key) |\n| Policy | Runtime allow/ask/deny decisions on every tool call, bash command, MCP operation | pi-permission-system (`permission:` frontmatter key) |\n\n### Installing\n\n```bash\npi install npm:@gotgenes/pi-permission-system\n```\n\nNo configuration is required for the integration — it is automatic when both\nextensions are installed. pi-subagents passes the parent session identity\nto child processes via the `PI_SUBAGENT_PARENT_SESSION` environment variable,\nwhich the permission system uses to forward `ask` prompts from headless\nsubagent processes back to the parent session's UI.\n\n### Per-agent permission frontmatter\n\nAgent files can include a `permission:` block alongside the standard `tools:`\nkey. The permission system reads it independently:\n\n```yaml\n---\nname: worker\ntools: bash,read,write,edit\npermission:\n \"*\": ask\n read: allow\n bash:\n \"*\": ask\n \"git *\": allow\n \"npm test\": allow\n---\n```\n\n\n[1259 more lines in file. Use offset=401 to continue.]"}],"isError":false,"timestamp":1784909226558}}
|
||
{"type":"message","id":"7047c989","parentId":"a09b45b7","timestamp":"2026-07-24T16:07:08.414Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"This is very relevant. The README is large. I need to read more about prompt templates, saved chains, workflow, and specifically the /prompt-workflow command and chains. Let me search for \"prompt-workflow\" and \"chain\" in the README.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.ffgrep:20","name":"ffgrep","arguments":{"pattern":"prompt-workflow|chain:|saved chain|workflow|background","path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/README.md","limit":80}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":34651,"output":108,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":34759,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909226560,"responseId":"chatcmpl-843","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"89093449","parentId":"7047c989","timestamp":"2026-07-24T16:07:08.472Z","message":{"role":"toolResult","toolCallId":"functions.ffgrep:20","toolName":"ffgrep","content":[{"type":"text","text":"README.md\n 7: `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.\n 45: 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.\n 47: 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:\n 83: ## Common workflows\n 95: | Run in the background | “Run this in the background.” |\n 97: | Use a saved workflow | “Run the review chain on this branch.” |\n 247: 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` o...\n 249: 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.\n 257: 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 fil...\n 261: 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.s...\n 297: Use orchestration as parent-agent guidance, not as a runtime workflow mode. For implementation work, the recommended loop is:\n 311: The package includes reusable prompt templates for common workflows. You do not need them, but they are handy when you want the same shape every time:\n 332: Run this implementation in the background. If the worker gets blocked or needs a product decision, have it ask me through intercom.\n 355: At this point, you know enough to use the plugin. The rest of this README is reference material for exact command syntax, custom agents, saved chains, worktrees, and configuration.\n 440: | `/run-chain <chainName> -- <task>` | Launch a saved `.chain.md` or `.chain.json` workflow |\n 470: Use the profile workflow like this:\n 528: `subagent({ chain: [...] })` tool API or a saved `.chain.json` for data-driven fan-out.\n 572: ### Background and forked runs\n 574: Add `--bg` to run in the background:\n 597: Background runs are detached. If the parent agent has other independent work, it should keep working. In an interactive chat, it should normally return control when ready to yield and let Pi deliver the completion notification instead of blocking merely to wait. Override that default and use `subagent_wait` when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its work finishes. In a non-interactiv...\n 607: Tool calls launch directly by default. Set `clarify: true` on single, parallel, or chain runs when you want to preview and edit the workflow before it runs; slash commands launch directly.\n 611: - `Enter` runs in the foreground, or in the background if background is toggled on\n 618: - `b` toggles background execution\n 689: Builtin agents opt into project instruction inheritance by default so they follow repo-specific rules out of the box. `delegate` also uses append mode because its job is orchestration inside the parent workflow.\n 759: | `async` | Default a single-agent launch to background (`true`) or foreground (`false`) when the call omits `async`. Explicit call values and `forceTopLevelAsync` win. |\n 819: Chains are reusable workflows stored separately from agent files. Use `.chain.md` for simple sequential saved chains. Use `.chain.json` when a chain needs dynamic fanout.\n 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.\n 898: Create simple `.chain.md` chains by writing files directly or with the `subagent({ action: \"create\", config: ... })` management action. Create dynamic `.chain.json` chains by writing the JSON file directly. Run saved chains with natural language or:\n 975: - **Prompt workflow recipes**: how to apply the packaged techniques directly with `subagent(...)` when the user describes the workflow in natural language instead of invoking a slash command. This includes parallel review, review-loop, parallel research, parallel context-build, parallel handoff-plan, gather-context-and-clarify, and parallel cleanup\n 981: If you are writing an agent that orchestrates subagents, the bundled skill helps it behave correctly without guessing the patterns. If you are a human user, you do not need to read it directly; the README and prompt shortcuts encode the same workflows in user-facing form.\n 1023: ## Background-work provider API\n 1028: import { registerBackgroundWorkProvider } from \"pi-subagents/background-work\";\n 1030: const dispose = registerBackgroundWorkProvider({\n 1031: name: \"my-background-extension\",\n 1042: Providers share a registry through `Symbol.for(\"pi-subagents.background-work.v1\")`, allowing independently loaded extension modules to meet in one Pi process. Registration is reload-safe: a new provider with the same name replaces the old callback, and the old disposer cannot remove the replacement. Call the disposer during extension shutdown when possible.\n 1068: { chain: [\n 1075: // Chain in the background, suitable for unblocking the main chat\n 1076: { chain: [...], async: true }\n 1079: { chain: [\n 1089: { chain: [\n 1106: { chain: [\n 1216: | `async` | boolean | false | Background execution. For chains, `clarify: true` explicitly keeps the run foreground for the clarify UI. |\n 1217: | `timeoutMs` / `maxRuntimeMs` | number | none | Optional run-level max runtime in milliseconds for foreground and async/background runs. |\n 1254: subagent({ action: \"append-step\", id: \"<run-id>\", chain: [{ agent: \"worker\", task: \"Continue from {previous}\" }] })\n 1278: { chain: [\n 1320: Makes top-level calls use background execution when the request does not explicitly set `async`. Callers can still force foreground with `async: false` unless `forceTopLevelAsync` is enabled.\n 1328: Controls the above-editor widget for background runs. The default is `true`. Set it to `false` when another extension renders async lifecycle data in a custom footer, status line, or dashboard; status tracking, completion notifications, `/subagents-fleet`, and lifecycle events continue to work.\n 1344: Forces depth-0 single, parallel, and chain runs into background mode and bypasses clarify UI by forcing `clarify: false`. Nested calls keep their own inherited settings.\n 1483: Controls smart batching of async-completion notifications. When several background subagents finish within a short window, their successful completions are held briefly and delivered as a single grouped message instead of separate notifications. A hard `maxWaitMs` cap (measured from the first completion in a group) guarantees nothing is held indefinitely, and late-finishing siblings that arrive within `stragglerWindowMs` of a group emit join a shorter straggler group governed by `stragglerDeboun...\n 1520: `status.json` powers the widget and `subagent({ action: \"status\" })` output. `events.jsonl` contains wrapper events plus child Pi JSON events annotated with run and step metadata, including correlated `subagent.steer.requested`, `scheduled`, `routed`, `delivered`, `failed`, and `recovered` events plus failure/partial/recovery notices. Nested fanout status is stored as compact sidecar event/registry metadata and merged into parent status views and result/intercom payloads; full recursive status s..."}],"details":{"totalMatched":50,"totalFiles":380},"isError":false,"timestamp":1784909228472}}
|
||
{"type":"message","id":"40b6dac2","parentId":"89093449","timestamp":"2026-07-24T16:07:12.996Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now I have a much clearer picture. The c-* prompts in the user's prompt directory use frontmatter `chain:` and an invocation `Invoke with: /prompt-workflow c-design-build --bg ...`. This seems to be a custom convention they've set up, perhaps expecting pi-subagents to recognize a `prompt-workflow` command. But pi-subagents doesn't seem to have a `/prompt-workflow` command by default. Let me search more carefully.\n\nWait, maybe the user wrote these prompt templates themselves but the `/prompt-workflow` command doesn't actually exist. Or maybe it's part of another extension. Let me search for \"prompt-workflow\" in the pi-subagents source.\n\nAlso, the user's question: \"is there a way to change the c-{prompt} so they dont create a new pi -p session. once the chain starts i have no option to stop them.\"\n\nIt sounds like they are invoking these chains via `pi -p` from their shell, which spawns a new pi process running in print mode (non-interactive). They want to run them interactively so they can stop them.\n\nThe user also asks: \"is there also an automatic tool that would just use whatever subagent or prompt is the most fitting?\"\n\nThis suggests they want automatic routing to the best subagent/prompt. Pi-subagents says the parent can just ask naturally and it decides which agent to use. But the user seems to want something like \"given my request, automatically choose between c-design-build, c-fix-commit, etc.\"\n\nLet me read the exact command reference sections in the README, especially around /run-chain and /run.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:21","name":"read","arguments":{"path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/README.md","offset":400,"limit":600}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":36905,"output":374,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":37279,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909228473,"responseId":"chatcmpl-753","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"5621f87c","parentId":"40b6dac2","timestamp":"2026-07-24T16:07:12.998Z","message":{"role":"toolResult","toolCallId":"functions.read:21","toolName":"read","content":[{"type":"text","text":"\nIn this example the subagent extension restricts visibility to four tools,\nand the permission system then applies `ask`/`allow` policy within that\nvisible set. Both keys coexist without collision.\n\n### Checking the integration\n\nRun `/subagents-doctor` to check the permission system status.\nIf `ask` prompts from children are not reaching the parent UI, verify both\nextensions are installed:\n\n```bash\npi list\n```\n\n### How it works\n\nAt session start, the interactive (root) session records its own identity in\n`PI_SUBAGENT_PARENT_SESSION`. When pi-subagents launches a child, it passes the\nlaunching session's identity to that child explicitly, falling back to the\ninherited environment variable. When the permission system inside a child\nencounters an `ask` permission, it reads this variable to locate the parent\nsession and forwards the confirmation request there.\n\nThis resolves an interactive prompt only when the parent it points at is the\ninteractive session — i.e. for the direct children of the root session. A\nnested child's parent is itself a headless subagent process with no UI to\nsurface the prompt, so `ask` policies are best placed on agents that run as\ndirect children of the interactive session.\n\n## Direct commands\n\nSkip this section until you want exact syntax.\n\n| Command | Description |\n|---------|-------------|\n| `/run <agent> [task]` | Run one agent; omit the task for self-contained agents |\n| `/chain agent1 \"task1\" -> agent2 \"task2\"` | Run agents in sequence |\n| `/chain scout \"scan\" -> (reviewer \"A\" \\| reviewer \"B\") -> writer \"fix\"` | Run a chain with a static parallel group inline |\n| `/parallel agent1 \"task1\" -> agent2 \"task2\"` | Run agents in parallel |\n| `/run-chain <chainName> -- <task>` | Launch a saved `.chain.md` or `.chain.json` workflow |\n| `/subagent-cost` | Show parent plus child subagent token usage and cost for this session |\n| `/subagents [agent] [model\\|thinking\\|prompt\\|details]` | Interactively inspect or edit an agent's model, thinking level, or system prompt |\n| `/subagents-doctor` | Show read-only setup diagnostics |\n| `/subagents-models [agent]` | Show the runtime-loaded builtin model mapping, optionally filtered to one builtin |\n| `/subagents-watchdog [status|on|off|recommend-model|model ...|session model ...|check]` | Show or configure the opt-in watchdog; use a strong complementary model such as Opus 4.8 high or GPT 5.5 high |\n| `/subagents-profiles` | List saved subagent profiles from `~/.pi/agent/profiles/pi-subagents/` |\n| `/subagents-load-profile <name>` | Replace only `settings.subagents` with a saved profile and optionally switch this session to the profile worker model |\n| `/subagents-refresh-provider-models <provider> [--force]` | Create or refresh the cached provider model catalog |\n| `/subagents-generate-profiles <provider>` | Generate `<provider>.quota.json` and `<provider>.quality.json` profiles |\n| `/subagents-check-profile <name>` | Check a saved profile against the current registry and live model probes |\n\nCommands validate agent names locally, support tab completion, and send results back into the conversation.\n\n`/subagents` opens a compact administration flow for builtin, package, user, and project agents. Model choices refresh Pi's model registry first, thinking choices are filtered to levels declared by the selected model, and prompt editing uses a blocking `$VISUAL`/`$EDITOR` command (with MarkEdit as the macOS fallback). Full metadata is opt-in through `details`. Edits are persisted to the field-owning layer: explicit custom-agent frontmatter remains in the agent file, while settings/profile-managed fields remain in `settings.subagents.agentOverrides`. Package-owned fields and definitions loaded through `PI_SUBAGENT_EXTRA_AGENT_DIRS` stay read-only; settings can still supply model or thinking fields omitted by a package definition.\n\n### Profiles and provider model catalogs\n\nProfiles are stored under:\n\n```text\n~/.pi/agent/profiles/pi-subagents/\n```\n\nProvider model catalogs are cached under:\n\n```text\n~/.pi/agent/profiles/pi-subagents/providers/\n```\n\nUse the profile workflow like this:\n\n```text\n/subagents-refresh-provider-models openai-codex\n/subagents-generate-profiles openai-codex\n/subagents-load-profile openai-codex.quota\n```\n\n`/subagents-refresh-provider-models` writes a serialized provider model catalog with observed registry data, simple role-oriented classification, and live probe results from tiny one-shot `pi -p --model ... --no-tools` checks. The cache refreshes when missing or stale; use `--force` to ignore freshness and probe again immediately.\n\n`/subagents-generate-profiles` uses the provider catalog to produce quota and quality profiles. `/subagents-check-profile` re-checks each assigned model in a saved profile against the current registry and a live probe so you can detect model removals, auth problems, or stale assignments.\n\n### Per-step tasks\n\nUse `->` to separate steps and give each step its own task:\n\n```text\n/chain scout \"scan the codebase\" -> planner \"create an implementation plan\"\n/parallel scanner \"find security issues\" -> reviewer \"check code style\"\n```\n\nBoth double and single quotes work. You can also use `--` as a delimiter:\n\n```text\n/chain scout -- scan code -> planner -- analyze auth\n```\n\nSteps without a task inherit behavior from the execution mode. Chain steps get `{previous}`, the prior step’s output. Parallel steps use the first available task as a fallback.\n\n### Inline parallel groups in `/chain`\n\nWrap a group of agents in parentheses and separate them with `|` to fan them out within a single chain step. The group runs all of its tasks concurrently, then the next `->` step continues once they finish:\n\n```text\n/chain scout \"scan\" -> (reviewer \"review A\" | reviewer \"review B\") -> writer \"fix\"\n```\n\nNotes:\n\n- Groups must contain at least two tasks separated by ` | `, each with its own task.\n- Group syntax is only valid between ` -> ` separators, and the group must appear as a complete step.\n- Only a step that *opens* with `(` is a group. Parentheses inside a shared `--` task (e.g. `/chain scout -- inspect auth (backend)`) stay literal text and keep the legacy single-agent behavior.\n- A group is treated as the prior step’s output for the next sequential step.\n- Tab completion suggests agents inside groups — after `(`, after `|`, and on each new `->` step.\n\nAdd a `[...]` suffix right after the closing `)` to set step-level options on the group:\n\n```text\n/chain scout \"scan\" -> (reviewer \"A\" | reviewer \"B\")[concurrency=2,failFast,worktree] -> writer \"fix\"\n```\n\n| Group option | Description |\n|--------------|-------------|\n| `concurrency=N` | Max tasks running at once within the group. |\n| `failFast` | Stop the group as soon as one task fails. |\n| `worktree` | Run each group task in its own git worktree. |\n\nDynamic fanout (`expand` / `collect`) is intentionally not available inline — use the\n`subagent({ chain: [...] })` tool API or a saved `.chain.json` for data-driven fan-out.\n\n```text\n/chain scout \"analyze auth\" -> planner -> worker\n# scout gets \"analyze auth\"; planner gets scout output; worker gets planner output\n```\n\nFor a shared task, list agents and place one `--` before the task:\n\n```text\n/chain scout planner -- analyze the auth system\n/parallel scout reviewer -- check for security issues\n```\n\n### Inline per-step config\n\nAppend `[key=value,...]` to an agent name to override defaults. `/chain` applies every key below; `/run` and `/parallel` use the execution-behavior keys (`output`, `outputMode`, `reads`, `model`, `skills`, `progress`) and ignore chain-only metadata such as `as`, `label`, `phase`, `count`, `outputSchema`, and `acceptance`.\n\n```text\n/chain scout[output=context.md] \"scan code\" -> planner[reads=context.md] \"analyze auth\"\n/run scout[model=anthropic/claude-sonnet-4] summarize this codebase\n/parallel reviewer[skills=code-review+security] \"review backend\" -> reviewer[model=openai/gpt-5-mini] \"review frontend\"\n```\n\n| Key | Example | Description |\n|-----|---------|-------------|\n| `output` | `output=context.md` | Write results to a file. Absolute paths are used as-is. Relative paths in `/run` resolve under `singleRunOutputBaseDir` when configured, otherwise under the run's output artifact directory. Relative paths in `/chain` and `/parallel` live under the chain or parallel run directory. |\n| `outputMode` | `outputMode=file-only` | Return only a concise file reference for saved output instead of the full saved content. Requires `output`; default is `inline`. |\n| `reads` | `reads=a.md+b.md` | Read files before executing. `+` separates multiple paths. |\n| `model` | `model=anthropic/claude-sonnet-4` | Override model for this step. |\n| `skills` | `skills=planning+review` | Override available skills. `+` separates multiple skills. |\n| `progress` | `progress` | Enable progress tracking. |\n| `as` | `as=context` | Name this step’s output so later steps can reference it. |\n| `label` | `label=Recon` | Human-readable label for the step. |\n| `phase` | `phase=analysis` | Group steps into a named phase. |\n| `cwd` | `cwd=packages/api` | Run the step in a subdirectory. |\n| `count` | `count=3` | Fan a group task into N copies (only inside a `( ... )` group). |\n| `outputSchema` | `outputSchema=schema.json` | Validate structured output against a JSON Schema file (path resolved against the session cwd, not an inline step `cwd`). |\n| `acceptance` | `acceptance=checked` | Inline acceptance level: `auto`, `attested`, or `checked`. Use the tool API or saved `.chain.json` for object contracts such as `none` or `verified`; `reviewed` is inferred-only. |\n\nSet `output=false`, `reads=false`, or `skills=false` to disable that behavior explicitly. Do not use `output=false` for file-only returns; use `outputMode=file-only` with an `output` path.\n\nInline `[...]` values must not contain spaces or commas — keep `label`/`phase` to single tokens.\n\n### Background and forked runs\n\nAdd `--bg` to run in the background:\n\n```text\n/run scout \"audit the codebase\" --bg\n/chain scout \"analyze auth\" -> planner \"design refactor\" -> worker --bg\n/parallel scout \"scan frontend\" -> scout \"scan backend\" --bg\n```\n\nAdd `--fork` to start each child from a real branched session created from the parent’s current leaf:\n\n```text\n/run reviewer \"review this diff\" --fork\n/chain scout \"analyze this branch\" -> planner \"plan next steps\" --fork\n/parallel scout \"audit frontend\" -> reviewer \"audit backend\" --fork\n```\n\nYou can combine them in either order:\n\n```text\n/run reviewer \"review this diff\" --fork --bg\n/run reviewer \"review this diff\" --bg --fork\n```\n\nBackground runs are detached. If the parent agent has other independent work, it should keep working. In an interactive chat, it should normally return control when ready to yield and let Pi deliver the completion notification instead of blocking merely to wait. Override that default and use `subagent_wait` when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its work finishes. In a non-interactive run, Pi auto-drains current-session work at `agent_end`; use `subagent_wait` when this turn must receive results before it ends. It returns when the next initially active run or registered provider item finishes or a subagent needs attention; use `subagent_wait({ all: true })` for all work active at call time, `subagent_wait({ id })` for one async or remembered detached foreground run, and `subagent_wait({ timeoutMs })` to cap the block.\n\nA foreground child can detach while it waits for a supervisor reply. Reply first, then call `subagent_wait({ id: runId })`. The remembered run stays pending until the child exits, then emits a session-scoped completion notification with recovered output and remains inspectable through `subagent({ action: \"status\", id: runId })`. Do not call `resume` or launch a replacement while the child remains detached.\n\nHeadless sessions also auto-drain current-session subagent and registered provider work at `agent_end`, using one absolute timeout and continuing through attention states. This is a final lifecycle safeguard rather than a replacement for explicit orchestration: `subagent_wait` still lets a model react to each result during the turn. Provider, reconciliation, timeout, and malformed-state failures remain visible errors instead of being treated as successful drains.\n\nThe `oracle` and `worker` builtins are designed for an explicit decision loop. A typical pattern is to ask `oracle` for diagnosis and a recommended execution prompt, then only run `worker` after the main agent approves that direction.\n\n## Clarify and launch UI\n\nTool calls launch directly by default. Set `clarify: true` on single, parallel, or chain runs when you want to preview and edit the workflow before it runs; slash commands launch directly.\n\nCommon clarify keys:\n\n- `Enter` runs in the foreground, or in the background if background is toggled on\n- `Esc` cancels or backs out\n- `↑↓` moves between steps or tasks\n- `e` edits the task/template\n- `m` selects a model\n- `t` selects thinking level\n- `s` selects skills\n- `b` toggles background execution\n- `w` edits output/write behavior where supported\n- `r` edits reads where supported\n- `p` toggles progress tracking where supported\nPicker screens use `↑↓`, `Enter`, `Esc`, and type-to-filter. The full-screen editor supports word wrapping, paste, `Esc` to save, and `Ctrl+C` to discard.\n\n## Agents and chains\n\nAgents are markdown files with YAML frontmatter and a system prompt body. They define the specialist that will run in the child Pi process.\n\nAgent locations, lowest to highest priority:\n\n| Scope | Path |\n|-------|------|\n| Builtin | `~/.pi/agent/extensions/subagent/agents/` |\n| Installed package | `package.json` `pi-subagents.agents` or `pi.subagents.agents` |\n| User | `~/.pi/agent/agents/**/*.md` |\n| Project | Project config `agents/**/*.md` (`.pi/agents/**/*.md` in standard Pi) |\n\nProject discovery also reads legacy `.agents/**/*.md` files. Nested subdirectories are discovered recursively. `.chain.md` files do not define agents. Installed Pi packages can expose agent directories from either `{\"pi-subagents\":{\"agents\":[\"./agents\"]}}` or `{\"pi\":{\"subagents\":{\"agents\":[\"./agents\"]}}}` in their package manifest. Package agents load above builtins and below user/project agents. If both `.agents/` and the project config agents directory define the same parsed runtime agent name, the project config directory wins. Use `agentScope: \"user\" | \"project\" | \"both\"` to control discovery; `both` is the default and project definitions win runtime-name collisions.\n\nBuiltin agents load at the lowest priority, so a user or project agent with the same name overrides them. They do not pin a provider model; they inherit your current Pi default model unless you set `subagents.defaultModel` or `subagents.agentOverrides.<name>.model`. `oracle` is an advisory reviewer that critiques direction and proposes an execution prompt without editing files. `worker` is the implementation agent for normal tasks and approved oracle handoffs.\n\nThe `researcher` builtin uses `web_search`, `fetch_content`, and `get_search_content`; those require [pi-web-access](https://github.com/nicobailon/pi-web-access):\n\n```bash\npi install npm:pi-web-access\n```\n\n### Builtin overrides\n\nYou can override selected builtin fields without copying the whole agent. Overrides live in settings:\n\n- User: `~/.pi/agent/settings.json`\n- Project: project config settings file (`.pi/settings.json` in standard Pi)\n\nExample:\n\n```json\n{\n \"subagents\": {\n \"agentOverrides\": {\n \"reviewer\": {\n \"inheritProjectContext\": false\n }\n }\n }\n}\n```\n\nSupported override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use `defaultContext: false` or `acceptanceRole: false` to clear an inherited override. Project overrides beat user overrides.\n\nSet `subagents.defaultModel` to give all subagents without an explicit model their own default model, separate from the parent session model. Per-agent model overrides and agent frontmatter still win.\n\nSet `disabled: true` to hide a builtin from runtime discovery and agent-facing `subagent({ action: \"list\" })` output. For bulk control, set `subagents.disableBuiltins: true` in settings. You can also toggle a single agent without editing settings by hand: `subagent({ action: \"disable\", agent: \"reviewer\" })` writes that override, and `subagent({ action: \"enable\", agent: \"reviewer\" })` removes it.\n\nSet `subagents.disableThinking: true` to clear bundled builtin thinking defaults globally for providers that do not support `:low`, `:medium`, `:high`, or similar model suffixes. A higher-precedence per-agent `thinking` override can opt one builtin back in.\n\n### Prompt assembly\n\nSubagents are designed to be narrow by default. Custom agents start with a clean system prompt and only the context you intentionally give them. They do not automatically inherit Pi’s whole base prompt, project instruction files, or discovered skills catalog.\n\nUse these fields when an agent should see more:\n\n| Field | Effect |\n|-------|--------|\n| `systemPromptMode: append` | Append the agent prompt to Pi’s normal base prompt. |\n| `inheritProjectContext: true` | Keep inherited project instructions from files like `AGENTS.md` and `CLAUDE.md`. |\n| `inheritSkills: true` | Let the child see Pi’s discovered skills catalog. |\n| `defaultContext: fork` | Use forked session context when a launch omits `context`; explicit `context: \"fresh\"` still wins. |\n\nBuiltin agents opt into project instruction inheritance by default so they follow repo-specific rules out of the box. `delegate` also uses append mode because its job is orchestration inside the parent workflow.\n\n### Agent frontmatter\n\nA typical agent looks like this:\n\n```yaml\n---\nname: scout\n# Optional: registers this as code-analysis.scout while preserving name: scout\npackage: code-analysis\ndescription: Fast codebase recon\ntools: read, grep, find, ls, bash, mcp:chrome-devtools\nextensions:\nsubagentOnlyExtensions: ./tools/child-only-search.ts\nmodel: claude-haiku-4-5\nfallbackModels: openai/gpt-5-mini, anthropic/claude-sonnet-4\nthinking: high\nsystemPromptMode: replace\ninheritProjectContext: false\ninheritSkills: false\nskills: safe-bash, review-checklist\nskillPath: ./skills, ../shared-skills\noutput: context.md\ndefaultReads: context.md\ndefaultProgress: true\nasync: true\ntimeoutMs: 900000\nturnBudget: {\"maxTurns\":20,\"graceTurns\":2}\nacceptance: {\"level\":\"none\",\"reason\":\"lightweight lookup\"}\nacceptanceRole: read-only\ncompletionGuard: false\ninteractive: true\nmaxSubagentDepth: 1\n---\n\nYour system prompt goes here.\n```\n\nSimple-scalar list fields accept either the existing comma-separated form or a newline block list with one `- item` per line. This applies to `tools`, `defaultReads`, `skill`/`skills`, `skillPath`, `fallbackModels`, `extensions`, and `subagentOnlyExtensions`; for example:\n\n```yaml\ntools:\n - read\n - mcp:github/search_repositories\nfallbackModels:\n - openai/gpt-5-mini\n - anthropic/claude-sonnet-4\n```\n\nImportant fields:\n\n| Field | Notes |\n|-------|-------|\n| `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |\n| `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools when `pi-mcp-adapter` is installed. |\n| `extensions` | Omitted means normal extensions; empty means no extensions; list values allowlist specific extensions. |\n| `subagentOnlyExtensions` | Extension paths loaded only in spawned child sessions for this agent. Tools registered there are unavailable to the main agent unless also installed through normal Pi extension configuration. |\n| `model` | Default model. Bare ids prefer the current provider when possible, then unique registry matches. |\n| `fallbackModels` | Ordered backup models for provider/model failures such as quota, auth, timeout, or unavailable model. Ordinary task failures do not trigger fallback. |\n| `thinking` | Appended as a `:level` suffix at runtime unless a suffix is already present. |\n| `systemPromptMode` | `replace` by default; `append` keeps Pi’s base prompt. |\n| `inheritProjectContext` | Keeps or strips inherited project instruction blocks. |\n| `inheritSkills` | Keeps or strips Pi’s discovered skills catalog. |\n| `defaultContext` | Optional `fresh` or `fork` launch context default for this agent. |\n| `skills` | Selects specific skills for the child, regardless of `inheritSkills`. |\n| `skillPath` | Invocation-private skill files or discovery directories. Relative paths resolve from the agent definition file. Local matches take precedence, while unresolved or unreadable matches fall back to normal skill discovery. This field discovers candidates only; `skills` still selects what the child receives. |\n| `output` | Default single-agent output file. |\n| `defaultReads` | Files to read before running in chain/parallel behavior. |\n| `defaultProgress` | Maintain `progress.md`. |\n| `async` | Default a single-agent launch to background (`true`) or foreground (`false`) when the call omits `async`. Explicit call values and `forceTopLevelAsync` win. |\n| `timeoutMs` | Positive integer default runtime deadline in milliseconds for single-agent launches. An explicit `timeoutMs` or `maxRuntimeMs` wins. |\n| `turnBudget` | JSON object default such as `{\"maxTurns\":20,\"graceTurns\":2}` for single-agent launches. An explicit call value wins, followed by this agent default, then global `turnBudget` config. |\n| `acceptance` | Acceptance default for single-agent launches. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: \"none\", reason: \"lightweight lookup\" }`. Explicit call values win; chain and parallel acceptance remains task/step configuration. |\n| `acceptanceRole` | Optional `read-only` or `writer` role for automatic acceptance inference. Explicit task mutation or no-edit intent wins; otherwise the declared role replaces agent-name guessing. This does not grant or revoke tools. |\n| `completionGuard` | Set `false` only for non-implementation agents that may mention implementation words while using mutation-capable tools such as `bash`. |\n| `interactive` | Parsed for compatibility but not enforced in v1. |\n| `maxSubagentDepth` | Tightens nested delegation for this agent's children. |\n| `memory` | Opt-in role-specific persistent memory. `memory: { scope: \"project\" \\| \"user\", path: \"<name>\" }` injects the first lines of a `MEMORY.md` from a dedicated `agent-memory/` directory into the child system prompt. Agents with write tools (`edit`/`write`/`bash`) get a read-write block; read-only agents get a read-only fallback. Project scope resolves under `<project>/.pi/agent-memory/`, user scope under `~/.pi/agent/agent-memory/`. Paths are validated against traversal and symlink escape. |\n\nAgent-local `skillPath` candidates never enter Pi's parent/global skills catalog. Pair `inheritSkills: false` with explicit `skills` and `skillPath` when a child should receive only its selected private skills.\n\n### Per-agent persistent memory\n\nA recurring custom agent can opt into a durable, role-specific memory scope with the `memory` frontmatter field. This is independent of Pi's own parent/session/project memory system and writes nothing to it; memory lives under a dedicated `agent-memory/` namespace so the two never collide.\n\n```yaml\nmemory:\n scope: project\n path: security-reviewer\n```\n\nOn each run, the first 200 lines of `MEMORY.md` in the resolved memory directory are injected into the child system prompt so the agent can recall accumulated role notes such as threat-model entries, release gotchas, or verified commands. Agents that have write tools (`edit`, `write`, or `bash`, or no `tools` allowlist at all) are told they may append concise dated entries to the file. Agents without write tools receive a read-only memory block and are not instructed to edit it, so a read-only reviewer can still recall prior notes without being granted write capability. The memory directory is never created eagerly; the agent's own `write` tool creates it (and `MEMORY.md`) on the first persist. Memory paths are validated against `.`/`..` traversal and symlink escape, and an unsafe or unresolvable scope is silently skipped rather than breaking the run.\n\nProject-scoped memory resolves under `<project>/.pi/agent-memory/<path>` and travels with the repo. User-scoped memory resolves under `~/.pi/agent/agent-memory/<path>` and is shared across projects for that agent.\n\n### Tool and extension selection\n\nIf `tools` is omitted, `pi-subagents` does not pass `--tools`, so the child gets Pi’s normal builtin tools. If `tools` is present, regular tool names become an explicit allowlist. An allowlisted name does not load the extension that registers it: load that provider through normal Pi extension discovery, `extensions`, `subagentOnlyExtensions`, or a path-like `tools` entry. `mcp:` entries are split out and forwarded as direct MCP selections. Path-like `tools` entries, such as extension paths or `.ts`/`.js` files, are treated as tool-extension paths rather than tool names. Internal runtime tools such as `structured_output` are added to an explicit allowlist only when their contract is active. Agents that declare only known read-only builtin tools skip the implementation completion guard, but `bash`, unknown tools, and MCP tools stay mutation-capable. Use `completionGuard: false` for bash-enabled validators or advisors that should never be judged as implementation agents.\n\nExamples:\n\n- `tools` omitted and `extensions` omitted: normal builtins and normal extensions.\n- `tools: mcp:chrome-devtools`: normal builtins plus direct Chrome DevTools MCP tools.\n- `tools: read, bash, mcp:chrome-devtools`: only `read` and `bash` as builtins, plus direct Chrome DevTools MCP tools.\n- `tools: subagent, read`: a child-safe `subagent` tool is available inside that child so it can run explicitly assigned nested fanout.\n- `tools: read, fixture_search` plus `subagentOnlyExtensions: ./tools/fixture-search.ts`: the provider loads only in this agent's child process, and the registered `fixture_search` name survives the strict allowlist.\n\nDirect MCP tools require [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter). Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in `mcp.json` is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. An `mcp:` entry named `subagent` does not authorize nested fanout; only the builtin `subagent` tool name does.\n\n`extensions` controls child extension loading:\n\n```yaml\n# Omitted: all normal extensions load\n\n# Empty: no extensions\nextensions:\n\n# Allowlist\nextensions: /abs/path/to/ext-a.ts, /abs/path/to/ext-b.ts\n```\n\nWhen `extensions` is present, normal discovered extensions are disabled; the listed extensions, path-like `tools` entries, required pi-subagents runtime extensions, and `subagentOnlyExtensions` still load.\n\nUse `subagentOnlyExtensions` when a custom extension tool should exist only inside child sessions. It is scoped by agent config: every run of that agent receives those extension paths, while other agents do not unless they declare the same field. The current model does not have a separate named-subagent audience inside one agent definition.\n\nBefore the first model turn, the child runtime compares every explicit tool name with Pi's final filtered registry. A missing provider now fails the run with the unavailable names and concrete `subagentOnlyExtensions`/`extensions` guidance instead of letting a direct or chained child silently continue without its requested tools.\n\n## Chain files\n\nChains are reusable workflows stored separately from agent files. Use `.chain.md` for simple sequential saved chains. Use `.chain.json` when a chain needs dynamic fanout.\n\n| Scope | Path |\n|-------|------|\n| Installed package | `package.json` `pi-subagents.chains` or `pi.subagents.chains` |\n| User | `~/.pi/agent/chains/**/*.chain.md`, `~/.pi/agent/chains/**/*.chain.json` |\n| Project | Project config `chains/**/*.chain.md`, `chains/**/*.chain.json` (`.pi/chains/...` in standard Pi) |\n\nNested subdirectories are discovered recursively. Installed Pi packages can expose chain directories from either `{\"pi-subagents\":{\"chains\":[\"./chains\"]}}` or `{\"pi\":{\"subagents\":{\"chains\":[\"./chains\"]}}}` in their package manifest. Package chains load below user/project chains. If both `.chain.md` and `.chain.json` define the same parsed runtime chain name in the same scope, `.chain.json` wins. If user and project scopes define the same parsed runtime chain name, the project chain wins. Chains support the same optional `package` frontmatter as agents; `name: review-flow` plus `package: code-analysis` runs as `code-analysis.review-flow`.\n\nExample:\n\n```md\n---\nname: scout-planner\ndescription: Gather context then plan implementation\n---\n\n## scout\nphase: Context\nlabel: Map auth flow\nas: context\noutput: context.md\n\nAnalyze the codebase for {task}\n\n## planner\nphase: Planning\nlabel: Implementation plan\nreads: context.md\nmodel: anthropic/claude-sonnet-4-5:high\nprogress: true\n\nCreate an implementation plan based on {outputs.context}\n```\n\nEach `.chain.md` `## agent-name` section is a step. Config lines such as `phase`, `label`, `as`, `outputSchema`, `output`, `outputMode`, `reads`, `model`, `skills`, and `progress` go immediately after the header. A blank line separates config from task text. In saved `.chain.md` files, `outputSchema` is a path to a JSON Schema file; direct tool calls and `.chain.json` files can pass the schema object inline.\n\nFor `output`, `reads`, `skills`, and `progress`, chain behavior is three-state: omitted inherits from the agent, a value overrides, and `false` disables.\n\nUse `phase` to group related work in status output, `label` for a readable step name, and `as` to store a successful step or parallel task result for later `{outputs.name}` references. Duplicate `as` names, invalid identifiers, and unknown output references fail before child execution.\n\nDynamic 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.\n\n```json\n{\n \"name\": \"dynamic-review\",\n \"description\": \"Find review targets, fan out reviewers, then synthesize.\",\n \"chain\": [\n {\n \"agent\": \"scout\",\n \"task\": \"Return {\\\"items\\\":[{\\\"path\\\":\\\"...\\\",\\\"reason\\\":\\\"...\\\"}]} via structured_output.\",\n \"as\": \"targets\",\n \"outputSchema\": { \"type\": \"object\" }\n },\n {\n \"expand\": {\n \"from\": { \"output\": \"targets\", \"path\": \"/items\" },\n \"item\": \"target\",\n \"key\": \"/path\",\n \"maxItems\": 12\n },\n \"parallel\": {\n \"agent\": \"reviewer\",\n \"label\": \"Review {target.path}\",\n \"task\": \"Review {target.path}. Reason: {target.reason}\",\n \"outputSchema\": { \"type\": \"object\" }\n },\n \"collect\": { \"as\": \"reviews\" },\n \"concurrency\": 4\n },\n {\n \"agent\": \"worker\",\n \"task\": \"Synthesize fixes from {outputs.reviews}\"\n }\n ]\n}\n```\n\nCreate simple `.chain.md` chains by writing files directly or with the `subagent({ action: \"create\", config: ... })` management action. Create dynamic `.chain.json` chains by writing the JSON file directly. Run saved chains with natural language or:\n\n```text\n/run-chain scout-planner -- refactor authentication\n```\n\n## Chain variables\n\nTask templates support:\n\n| Variable | Description |\n|----------|-------------|\n| `{task}` | Original task from the first step. |\n| `{previous}` | Output from the prior step, or aggregated output from a parallel step. |\n| `{chain_dir}` | Path to the chain artifact directory. |\n| `{outputs.name}` | Text value from a prior step or completed parallel task with `as: \"name\"`. |\n\nParallel outputs are aggregated with clear separators before being passed to the next step:\n\n```text\n=== Parallel Task 1 (worker) ===\n...\n\n=== Parallel Task 2 (worker) ===\n...\n```\n\n## Skills\n\nSkills are `SKILL.md` files made available to an agent. The prompt includes skill metadata and the file location; the agent reads the full skill file only when the task matches.\n\nDiscovery uses project-first precedence:\n\n1. Project config `skills/{name}/SKILL.md` (`.pi/skills/{name}/SKILL.md` in standard Pi)\n2. Project packages and project settings packages via `package.json -> pi.skills`\n3. Current task cwd package via `package.json -> pi.skills`\n4. Project config `settings.json -> skills`\n5. `~/.pi/agent/skills/{name}/SKILL.md`\n6. User packages and user settings packages via `package.json -> pi.skills`\n7. `~/.pi/agent/settings.json -> skills`\n\nUse agent defaults, override them at runtime, or disable them:\n\n```ts\n{ agent: \"scout\", task: \"...\" }\n{ agent: \"scout\", task: \"...\", skill: \"tmux, safe-bash\" }\n{ agent: \"scout\", task: \"...\", skill: false }\n```\n\nFor chains, `skill` at the top level is additive. A step-level `skill` overrides that step; `false` disables skills for that step.\n\nAvailable skills use this shape:\n\n```xml\nThe following configured skills are available to this subagent.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n<available_skills>\n <skill>\n <name>safe-bash</name>\n <description>Run shell commands safely.</description>\n <location>/absolute/path/to/safe-bash/SKILL.md</location>\n </skill>\n</available_skills>\n```\n\nIf an agent has an explicit `tools` allowlist and resolved skills, `read` is added for that child run so the listed skill files can be loaded on demand.\n\nMissing skills do not fail execution. The result summary shows a warning.\n\n### Bundled skill\n\nThe package bundles a `pi-subagents` skill that is automatically available to the parent agent when the extension is installed. It is for the orchestrating parent only: child subagents never receive it, and their context is explicitly filtered to strip parent-only orchestration instructions.\n\nWhat the bundled skill covers:\n- **Delegation patterns**: when to launch which agent, whether to use single, parallel, chain, or async mode, and whether to use fresh or forked context\n- **Prompt workflow recipes**: how to apply the packaged techniques directly with `subagent(...)` when the user describes the workflow in natural language instead of invoking a slash command. This includes parallel review, review-loop, parallel research, parallel context-build, parallel handoff-plan, gather-context-and-clarify, and parallel cleanup\n- **Role-agent prompting guidance**: compact contract prompts instead of long scripts, what to include in role-specific meta prompts, and retrieval budgets for researchers\n- **Safety boundaries**: child agents must not run subagents unless their resolved builtin tools explicitly include `subagent`, must not invent intercom targets, and must escalate unapproved decisions\n- **Intercom conventions**: when to ask vs send, and how parent-side supervisor/result delivery works through the native channel\n- **Control and diagnostics**: attention signals, soft interrupts, status, and the `doctor` action\n\nIf you are writing an agent that orchestrates subagents, the bundled skill helps it behave correctly without guessing the patterns. If you are a human user, you do not need to read it directly; the README and prompt shortcuts encode the same workflows in user-facing form.\n\n## Extension delegation API\n\nPi extensions can request one configured foreground agent through the typed v1 event contract:\n\n```ts\nimport {\n SUBAGENT_DELEGATION_REQUEST_EVENT,\n SUBAGENT_DELEGATION_RESPONSE_EVENT,\n type SubagentDelegationRequest,\n type SubagentDelegationResponse,\n} from \"pi-subagents/delegation\";\n\nconst request: SubagentDelegationRequest = {\n version: 1,\n requestId: crypto.randomUUID(),\n agent: \"reviewer\",\n task: \"Review the supplied evidence.\",\n\n[660 more lines in file. Use offset=1000 to continue.]"}],"isError":false,"timestamp":1784909232998}}
|
||
{"type":"message","id":"4d65ff73","parentId":"5621f87c","timestamp":"2026-07-24T16:07:27.200Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now I have a good understanding. The pi-subagents package has slash commands like `/run`, `/chain`, `/run-chain`. The user has custom prompt templates (c-*.md) with frontmatter `chain: p-brainstorm -> ...` and text saying `Invoke with: /prompt-workflow c-design-build --bg ...`.\n\nBut `/prompt-workflow` is not a documented pi-subagents command. It looks like the user may have created these prompt templates themselves with a custom command that may not exist, or perhaps they are invoking them via `pi -p` somehow.\n\nWait, let me re-read the prompt templates. They have:\n```markdown\n---\ndescription: ...\nargument-hint: ...\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n```\n\nSo the c-* files are prompt templates. When the user types `/c-design-build` in pi, the template expands. The template content itself mentions `/prompt-workflow c-design-build --bg` in the body. So maybe the user's workflow is:\n1. Type `/c-design-build add a rate-limiter`\n2. The template expands to: `Run the design → plan → test → commit chain for: add a rate-limiter`\n3. Then there's a line `Invoke with: /prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"` which is just instructions/hint text.\n\nBut pi-subagents doesn't have `/prompt-workflow`. Maybe the user intends for the parent pi to read this and then call `/run-chain`? Or maybe they have another custom extension/skill. Hmm.\n\nActually wait - `c-{prompt}` in the user's question might be exactly these prompt template names. And they say \"they dont create a new pi -p session\". So perhaps when they invoke `/c-design-build`, the content tells pi to run `/prompt-workflow c-design-build --bg ...`, but this command doesn't exist, or it's invoking some wrapper that runs `pi -p` in a new session.\n\nLet me check if there's any custom extension in their setup. They have `@demigodmode/pi-web-agent`, `@ff-labs/pi-fff`, `@juicesharp/rpiv-ask-user-question`, `@a5c-ai/babysitter-pi`, `pi-ollama-cloud`, `context-mode`. No obvious prompt-workflow extension.\n\nMaybe `/prompt-workflow` is intended as natural language? Or the user is running these from their shell using `pi -p` with the prompt as input.\n\nWait, the user says: \"once the chain starts i have no option to stop them\". This matches the behavior of `pi -p` (non-interactive print mode). When you run `pi -p` from the shell with a long chain, you can Ctrl+C to stop the process, but if the chain spawns child subagents, those might be detached background processes.\n\nAlso, in pi-subagents, `/run-chain` runs in the current session. If you use `--bg`, it runs as a background async run that you can check and stop via `/subagents-stop` or `subagent({ action: \"stop\", id: ... })`.\n\nThe user likely wants to:\n1. Not spawn a new `pi -p` process - they want the chain to run inside the current interactive pi session, or at least give them control/stop options.\n2. Have an automatic routing tool that picks the best subagent/prompt.\n\nNow, the second question: \"is there also an automatic tool that would just use whatever subagent or prompt is the most fitting?\"\n\nThis is basically asking for an agent router. Pi-subagents allows the parent agent to decide which subagent to use based on natural language. But they want something automatic that maps their c-* prompts. I could suggest:\n- Use the built-in `subagent` tool in the parent and let it decide. The bundled skill covers delegation patterns.\n- Create a \"router\" agent or a top-level prompt that picks the right chain.\n- Use `/run-chain` with a router agent that selects the appropriate saved chain.\n\nActually, the most direct answer is:\n1. The c-* prompts should be converted to proper `.chain.md` files in `~/.pi/agent/chains/` (or `.pi/chains/`), and invoked with `/run-chain <name> -- [task]` in the current interactive session. This runs inside the current pi session, not a new `pi -p` process. If you want background, add `--bg` and you can stop with `/subagents-stop`.\n2. For automatic routing, create a custom agent that reads the task and calls the appropriate chain, or just ask the parent naturally (e.g., \"run the right workflow for adding a rate limiter\"). But there isn't a built-in \"auto-prompt\" command that picks c-* vs p-* templates automatically.\n\nWait, the user has both `p-*.md` and `c-*.md` prompts. The `p-*` are probably regular prompt templates that expand into instructions. The `c-*` are chain prompts. The c-* frontmatter has `chain: p-brainstorm -> p-plan -> ...`. Maybe the user expects a custom `/prompt-workflow` command that reads this `chain:` frontmatter and runs the chain.\n\nHmm, maybe the user is using a custom implementation or wants one. They ask \"is there a way to change the c-{prompt} so they dont create a new pi -p session.\" So they are creating new pi -p sessions somehow. Maybe they're shell aliasing c-design-build to `pi -p /prompt-workflow ...`.\n\nLet me check the dotfiles for shell aliases or scripts. The current working directory is `/home/liph/dotfiles/pi/.pi/agent/prompts`, so there's likely a dotfiles repo. Let me search for `c-design-build` or `prompt-workflow` in the dotfiles.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:22","name":"bash","arguments":{"command":"find /home/liph/dotfiles -type f \\( -name '*.sh' -o -name '*.bash' -o -name '*.zsh' -o -name 'aliases*' -o -name 'config.*' \\) -exec grep -l -E 'c-design-build|prompt-workflow|pi -p' {} \\; 2>/dev/null | head -20"}},{"type":"toolCall","id":"functions.ffgrep:23","name":"ffgrep","arguments":{"pattern":"prompt-workflow","path":"/home/liph/dotfiles","limit":40}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":45659,"output":1396,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":47055,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909232999,"responseId":"chatcmpl-960","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"a6076a8c","parentId":"4d65ff73","timestamp":"2026-07-24T16:07:27.509Z","message":{"role":"toolResult","toolCallId":"functions.bash:22","toolName":"bash","content":[{"type":"text","text":"(no output)"}],"isError":false,"timestamp":1784909247509}}
|
||
{"type":"message","id":"52e2d84a","parentId":"a6076a8c","timestamp":"2026-07-24T16:07:27.510Z","message":{"role":"toolResult","toolCallId":"functions.ffgrep:23","toolName":"ffgrep","content":[{"type":"text","text":"pi/.pi/agent/sessions/--home-liph-dotfiles-pi-.pi-agent-prompts--/2026-07-24T16-05-14-023Z_019f94df-aaa7-7e74-90b6-1799f398b5a9.jsonl [untracked in git]\n 10: {\"type\":\"message\",\"id\":\"499e09fe\",\"parentId\":\"460e9606\",\"timestamp\":\"2026-07-24T16:06:51.818Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"functions.read:3\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Brainstorm → plan → test → commit in one background chain\\nargument-hint: \\\"[task or feature]\\\"\\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\\n---\\nRun the design → plan → test → commit chain for: $@\\n\\nInvoke with:\\n/prompt-workflow c-design-build --bg \\\"add a rat\n 11: {\"type\":\"message\",\"id\":\"e23c77e3\",\"parentId\":\"499e09fe\",\"timestamp\":\"2026-07-24T16:06:51.818Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"functions.read:4\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Summarize → diagnose → debug → test in one background chain\\nargument-hint: \\\"[symptom, error, or observed behavior]\\\"\\nchain: p-summarize -> p-diagnose -> p-debug -> p-test\\n---\\nRun the understand → diagnose → fix → regression-test chain for: $@\\n\\nInvoke with:\\n/prompt\n 12: {\"type\":\"message\",\"id\":\"7096270f\",\"parentId\":\"e23c77e3\",\"timestamp\":\"2026-07-24T16:06:51.818Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"functions.read:5\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Refactor → test → review → commit in one background chain\\nargument-hint: \\\"[file path or symbol to refactor]\\\"\\nchain: p-refactor -> p-test -> p-review -> p-commit\\n---\\nRun the safe refactor → validate → review → commit chain for: $@\\n\\nInvoke with:\\n/prompt-workflow c-\n 13: {\"type\":\"message\",\"id\":\"595af1c3\",\"parentId\":\"7096270f\",\"timestamp\":\"2026-07-24T16:06:51.818Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"functions.read:6\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Security audit → review → test in one background chain\\nargument-hint: \\\"[file path, diff, or feature to audit]\\\"\\nchain: p-secaudit -> p-review -> p-test\\n---\\nRun the security-first review loop for: $@\\n\\nInvoke with:\\n/prompt-workflow c-security-loop --bg \\\"auth endpoi...\n 14: {\"type\":\"message\",\"id\":\"a978d99b\",\"parentId\":\"595af1c3\",\"timestamp\":\"2026-07-24T16:06:58.685Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"Interesting! These prompt templates have frontmatter with `chain: p-brainstorm -> p-plan -> p-test -> p-commit` and an `Invoke with: /prompt-workflow c-design-build --bg \\\"...\\\"` line. This is NOT standard pi prompt template behavior. This looks like it's using an extension or a custom pi package that implements `/prompt-workflow` ...\n 29: {\"type\":\"message\",\"id\":\"729d7030\",\"parentId\":\"a0f366ca\",\"timestamp\":\"2026-07-24T16:07:06.556Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"Now I understand. The user has pi-subagents package installed. The c-* prompts are custom prompts that use a `/prompt-workflow` command which is likely added by pi-subagents extension, or it's a skill command. The extension directory is empty because packages are loaded from ~/.pi/agent/npm/node_modules/pi-subagents/.\\n\\nThe user i...\n 31: {\"type\":\"message\",\"id\":\"7047c989\",\"parentId\":\"a09b45b7\",\"timestamp\":\"2026-07-24T16:07:08.414Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"This is very relevant. The README is large. I need to read more about prompt templates, saved chains, workflow, and specifically the /prompt-workflow command and chains. Let me search for \\\"prompt-workflow\\\" and \\\"chain\\\" in the README.\",\"thinkingSignature\":\"reasoning\"},{\"type\":\"toolCall\",\"id\":\"functions.ffgrep:20\",\"name\":\"ffgrep\",...\n 33: {\"type\":\"message\",\"id\":\"40b6dac2\",\"parentId\":\"89093449\",\"timestamp\":\"2026-07-24T16:07:12.996Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"Now I have a much clearer picture. The c-* prompts in the user's prompt directory use frontmatter `chain:` and an invocation `Invoke with: /prompt-workflow c-design-build --bg ...`. This seems to be a custom convention they've set up, perhaps expecting pi-subagents to recognize a `prompt-workflow` command. But pi-subagents doesn't ...\n 35: {\"type\":\"message\",\"id\":\"4d65ff73\",\"parentId\":\"5621f87c\",\"timestamp\":\"2026-07-24T16:07:27.200Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"Now I have a good understanding. The pi-subagents package has slash commands like `/run`, `/chain`, `/run-chain`. The user has custom prompt templates (c-*.md) with frontmatter `chain: p-brainstorm -> ...` and text saying `Invoke with: /prompt-workflow c-design-build --bg ...`.\\n\\nBut `/prompt-workflow` is not a documented pi-subag...\n\npi/.pi/agent/prompts/.pi-subagents/artifacts/5f01a9ab-6def-4648-b9b0-54d97946fdbf_delegate_1_transcript.jsonl [untracked in git]\n 1: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909141265,\"timestamp\":\"2026-07-24T16:05:41.265Z\",\"sourceEventType\":\"initial_prompt\",\"role\":\"user\",\"text\":\"Create a structured implementation plan for: add a rate-limit\\n /prompt-workflow c-fix-commit --bg the checkout inter /prompt-workflow c-refactor-commit src/utils.ts /prompt-workflow c-security-loop a...\n 2: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909143422,\"timestamp\":\"2026-07-24T16:05:43.422Z\",\"sourceEventType\":\"message_end\",\"role\":\"user\",\"text\":\"Task: Create a structured implementation plan for: add a rate-limit\\n /prompt-workflow c-fix-commit --bg the checkout inter /prompt-workflow c-refactor-commit src/utils.ts /prompt-workflow c-security-loo...\n 3: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909146001,\"timestamp\":\"2026-07-24T16:05:46.001Z\",\"sourceEventType\":\"message_end\",\"role\":\"assistant\",\"model\":\"minimax-m3:cloud\",\"stopReason\":\"toolUse\",\"usage\":{\"input\":3634,\"output\":169,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"The user wan...\n 10: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909147885,\"timestamp\":\"2026-07-24T16:05:47.885Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"---\\ndescription: Summarize → diagnose → debug → test in one background chain\\nargument-hint: \\\"[symptom, error, or observed behavior]\\\"\\nchain: p-summarize -> p-diagnose -> p-debug -> p-test\\n---\\nR...\n 14: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909204143,\"timestamp\":\"2026-07-24T16:06:44.143Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"---\\ndescription: Refactor → test → review → commit in one background chain\\nargument-hint: \\\"[file path or symbol to refactor]\\\"\\nchain: p-refactor -> p-test -> p-review -> p-commit\\n---\\nRun the sa...\n 18: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909205391,\"timestamp\":\"2026-07-24T16:06:45.391Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"---\\ndescription: Security audit → review → test in one background chain\\nargument-hint: \\\"[file path, diff, or feature to audit]\\\"\\nchain: p-secaudit -> p-review -> p-test\\n---\\nRun the security-fir...\n 27: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909209159,\"timestamp\":\"2026-07-24T16:06:49.159Z\",\"sourceEventType\":\"message_end\",\"role\":\"assistant\",\"model\":\"minimax-m3:cloud\",\"stopReason\":\"toolUse\",\"usage\":{\"input\":4398,\"output\":51,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"toolCall\",\"id\":\"call_function_e10l1...\n 28: {\"version\":1,\"recordType\":\"tool_start\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909209160,\"timestamp\":\"2026-07-24T16:06:49.160Z\",\"sourceEventType\":\"tool_execution_start\",\"toolName\":\"bash\",\"argsPreview\":\"grep -r \\\"prompt-workflow\\\" /home/liph/.pi/ -l 2>/dev/null ...\"}\n 30: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909209965,\"timestamp\":\"2026-07-24T16:06:49.965Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"/home/liph/.pi/context-mode/sessions/3ea71be6c83c47ea.db\\n/home/liph/.pi/context-mode/sessions/12c859f108b03852.db\\n/home/liph/.pi/context-mode/content/aa673b1056f331f7.db\\n/home/liph/.pi/agent/npm/n...\n 31: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909211120,\"timestamp\":\"2026-07-24T16:06:51.120Z\",\"sourceEventType\":\"message_end\",\"role\":\"assistant\",\"model\":\"minimax-m3:cloud\",\"stopReason\":\"toolUse\",\"usage\":{\"input\":4989,\"output\":47,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"toolCall\",\"id\":\"call_function_oefsh...\n 34: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909211124,\"timestamp\":\"2026-07-24T16:06:51.124Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"import * as fs from \\\"node:fs\\\";\\nimport * as path from \\\"node:path\\\";\\nimport { fileURLToPath } from \\\"node:url\\\";\\nimport type { ExtensionAPI, ExtensionContext } from \\\"@earendil-works/pi-coding-ag...\n 38: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909212843,\"timestamp\":\"2026-07-24T16:06:52.843Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"import { randomUUID } from \\\"node:crypto\\\";\\nimport * as fs from \\\"node:fs\\\";\\nimport * as path from \\\"node:path\\\";\\nimport { keyText, type ExtensionAPI, type ExtensionContext } from \\\"@earendil-work...\n 46: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909216526,\"timestamp\":\"2026-07-24T16:06:56.526Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"# Chain Commands Reference\\n\\nThis file documents how to invoke the `c-*` chain recipes defined in `~/.pi/agent/prompts/`.\\n\\n## What the chains are\\n\\nThe `c-*` files are orchestration recipes. They...\n 50: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909217986,\"timestamp\":\"2026-07-24T16:06:57.986Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"# Prompts\\n\\nSlash-style prompts for the interactive pi session. Each file is a `p-<verb>.md` template with a frontmatter `description` + `argument-hint` and a structured body. Invoke with `:p-<verb>...\n 51: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909220889,\"timestamp\":\"2026-07-24T16:07:00.889Z\",\"sourceEventType\":\"message_end\",\"role\":\"assistant\",\"text\":\"Now I have full context. The user is asking a question that mixes a real ask with a question. Let me parse the task carefully:\\n\\nThe task title is: \\\"add a rate-limit\\\" and they show 3 invocations of...\n 62: {\"version\":1,\"recordType\":\"message\",\"source\":\"async\",\"runId\":\"5f01a9ab-6def-4648-b9b0-54d97946fdbf\",\"agent\":\"delegate\",\"childIndex\":1,\"cwd\":\"/home/liph/dotfiles/pi/.pi/agent/prompts\",\"ts\":1784909224021,\"timestamp\":\"2026-07-24T16:07:04.021Z\",\"sourceEventType\":\"message_end\",\"role\":\"toolResult\",\"text\":\"/home/liph/.pi/agent/prompts/c-design-build.md\\n---\\ndescription: Brainstorm → plan → test → commit in one background chain\\nargument-hint: \\\"[task or feature]\\\"\\nchain: p-brainstorm -> p-plan -> p-t...\n\npi/.pi/agent/sessions/--home-liph-dotfiles-pi-.pi-agent-prompts--/2026-07-24T15-49-05-219Z_019f94d0-e243-73e1-a106-43567b64e99d/00700bed/run-1/session.jsonl [untracked in git]\n 5: {\"type\":\"message\",\"id\":\"a77d1c0d\",\"parentId\":\"5b91d99e\",\"timestamp\":\"2026-07-24T16:05:43.366Z\",\"message\":{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"Task: Create a structured implementation plan for: add a rate-limit\\n /prompt-workflow c-fix-commit --bg the checkout inter /prompt-workflow c-refactor-commit src/utils.ts /prompt-workflow c-security-loop auth endpoint can i create y shortcut to invoke these prompts more easyly.... or what options do i have\\n\\nFollow this format:\\n1. **Goal**...\n 6: {\"type\":\"message\",\"id\":\"4ff18efb\",\"parentId\":\"a77d1c0d\",\"timestamp\":\"2026-07-24T16:05:45.996Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"The user wants me to create a structured implementation plan for adding a rate-limit shortcut to invoke several /prompt-workflow commands more easily. Let me analyze the request:\\n\\n1. They have several `/prompt-workflow` commands they want to chain/invoke:\\n - `c-fix-commit` (with `--bg` flag, on \\\"the checkout inter\\\")\\n - `c...\n 9: {\"type\":\"message\",\"id\":\"bb1353a1\",\"parentId\":\"91299ce2\",\"timestamp\":\"2026-07-24T16:05:47.883Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_2zug7q023fce_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Summarize → diagnose → debug → test in one background chain\\nargument-hint: \\\"[symptom, error, or observed behavior]\\\"\\nchain: p-summarize -> p-diagnose -> p-debug -> p-test\\n---\\nRun the understand → diagnose → fix → regression-test chain for: $@\\n\\nInvoke wi\n 11: {\"type\":\"message\",\"id\":\"26e1dc28\",\"parentId\":\"c8616c50\",\"timestamp\":\"2026-07-24T16:06:44.141Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_grmugnrkdwcd_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Refactor → test → review → commit in one background chain\\nargument-hint: \\\"[file path or symbol to refactor]\\\"\\nchain: p-refactor -> p-test -> p-review -> p-commit\\n---\\nRun the safe refactor → validate → review → commit chain for: $@\\n\\nInvoke with:\\n/prompt\n 13: {\"type\":\"message\",\"id\":\"7687c91b\",\"parentId\":\"0c68da45\",\"timestamp\":\"2026-07-24T16:06:45.389Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_vg2thxssnd8k_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"---\\ndescription: Security audit → review → test in one background chain\\nargument-hint: \\\"[file path, diff, or feature to audit]\\\"\\nchain: p-secaudit -> p-review -> p-test\\n---\\nRun the security-first review loop for: $@\\n\\nInvoke with:\\n/prompt-workflow c-security-loop --bg \\...\n 18: {\"type\":\"message\",\"id\":\"37d687e0\",\"parentId\":\"6cb88dfa\",\"timestamp\":\"2026-07-24T16:06:49.158Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"toolCall\",\"id\":\"call_function_e10l1c7200ld_1\",\"name\":\"bash\",\"arguments\":{\"command\":\"grep -r \\\"prompt-workflow\\\" /home/liph/.pi/ -l 2>/dev/null | head -20\"}}],\"api\":\"openai-completions\",\"provider\":\"ollama\",\"model\":\"minimax-m3:cloud\",\"usage\":{\"input\":4398,\"output\":51,\"cacheRead\":0,\"cacheWrite\":0,\"reasoning\":0,\"totalTokens\":4449,\"cost\":{\"input\":0,\"output\":...\n 19: {\"type\":\"message\",\"id\":\"10bb2fae\",\"parentId\":\"37d687e0\",\"timestamp\":\"2026-07-24T16:06:49.963Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_e10l1c7200ld_1\",\"toolName\":\"bash\",\"content\":[{\"type\":\"text\",\"text\":\"/home/liph/.pi/context-mode/sessions/3ea71be6c83c47ea.db\\n/home/liph/.pi/context-mode/sessions/12c859f108b03852.db\\n/home/liph/.pi/context-mode/content/aa673b1056f331f7.db\\n/home/liph/.pi/agent/npm/node_modules/pi-subagents/CHANGELOG.md\\n/home/liph/.pi/agent/npm/node_modules/pi...\n 20: {\"type\":\"message\",\"id\":\"04b5e815\",\"parentId\":\"10bb2fae\",\"timestamp\":\"2026-07-24T16:06:51.119Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"toolCall\",\"id\":\"call_function_oefsh1evn4tq_1\",\"name\":\"read\",\"arguments\":{\"path\":\"/home/liph/.pi/agent/npm/node_modules/pi-subagents/src/slash/prompt-workflows.ts\"}}],\"api\":\"openai-completions\",\"provider\":\"ollama\",\"model\":\"minimax-m3:cloud\",\"usage\":{\"input\":4989,\"output\":47,\"cacheRead\":0,\"cacheWrite\":0,\"reasoning\":0,\"totalTokens\":5036,\"cost\":{\"input\":0,\"...\n 21: {\"type\":\"message\",\"id\":\"1b074f21\",\"parentId\":\"04b5e815\",\"timestamp\":\"2026-07-24T16:06:51.121Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_oefsh1evn4tq_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"import * as fs from \\\"node:fs\\\";\\nimport * as path from \\\"node:path\\\";\\nimport { fileURLToPath } from \\\"node:url\\\";\\nimport type { ExtensionAPI, ExtensionContext } from \\\"@earendil-works/pi-coding-agent\\\";\\nimport { parseFrontmatter } from \\\"../agents/frontmatter.ts\\\";\\nimport ...\n 23: {\"type\":\"message\",\"id\":\"1cb702dc\",\"parentId\":\"eb3e78e3\",\"timestamp\":\"2026-07-24T16:06:52.835Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_yyavt24fl6av_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"import { randomUUID } from \\\"node:crypto\\\";\\nimport * as fs from \\\"node:fs\\\";\\nimport * as path from \\\"node:path\\\";\\nimport { keyText, type ExtensionAPI, type ExtensionContext } from \\\"@earendil-works/pi-coding-agent\\\";\\nimport { Key, matchesKey, type Component, type TUI } from...\n 27: {\"type\":\"message\",\"id\":\"5748a7ab\",\"parentId\":\"873fb5d3\",\"timestamp\":\"2026-07-24T16:06:56.523Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_p6340nkhj8xl_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"# Chain Commands Reference\\n\\nThis file documents how to invoke the `c-*` chain recipes defined in `~/.pi/agent/prompts/`.\\n\\n## What the chains are\\n\\nThe `c-*` files are orchestration recipes. They do not contain new prompts; they reuse the existing `p-*` prompts and run them...\n 29: {\"type\":\"message\",\"id\":\"69470efd\",\"parentId\":\"6d0d86a0\",\"timestamp\":\"2026-07-24T16:06:57.983Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_m7a8ktizyn57_1\",\"toolName\":\"read\",\"content\":[{\"type\":\"text\",\"text\":\"# Prompts\\n\\nSlash-style prompts for the interactive pi session. Each file is a `p-<verb>.md` template with a frontmatter `description` + `argument-hint` and a structured body. Invoke with `:p-<verb> [arg]` or via the `:prompts` TUI picker.\\n\\n## When to use which\\n\\n| Prompt ...\n 30: {\"type\":\"message\",\"id\":\"3e2d6dbe\",\"parentId\":\"69470efd\",\"timestamp\":\"2026-07-24T16:07:00.887Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"Now I have full context. The user is asking a question that mixes a real ask with a question. Let me parse the task carefully:\\n\\nThe task title is: \\\"add a rate-limit\\\" and they show 3 invocations of `/prompt-workflow c-*` commands (using chains for different tasks). Then they ask: \\\"can i create y shortcut to invoke these prompts more ea...\n 35: {\"type\":\"message\",\"id\":\"8fa0ef4d\",\"parentId\":\"36764169\",\"timestamp\":\"2026-07-24T16:07:04.017Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_function_5x1hroczkmee_1\",\"toolName\":\"bash\",\"content\":[{\"type\":\"text\",\"text\":\"/home/liph/.pi/agent/prompts/c-design-build.md\\n---\\ndescription: Brainstorm → plan → test → commit in one background chain\\nargument-hint: \\\"[task or feature]\\\"\\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\\n---\\nRun the design → plan → test → commit chain for: $@\\n\\nIn\n\npi/.pi/agent/prompts/.pi-subagents/artifacts/5f01a9ab-6def-4648-b9b0-54d97946fdbf_delegate_0_meta.json [untracked in git]\n 4: \"task\": \"Brainstorm approaches for: add a rate-limit\\n /prompt-workflow c-fix-commit --bg the checkout inter /prompt-workflow c-refactor-commit src/utils.ts /prompt-workflow c-security-loop auth endpoint can i create y shortcut to invoke these prompts more easyly.... or what options do i have\\n\\nStructure your answer as:\\n1. **Problem restatement** — one paragraph; what we're solving, what constraints matter, what \\\"done\\\" looks like\\n2. **Alternatives** — 3 to 5 distinct approaches. For each:...\n 166: \"evidence\": \"Every recommendation is grounded in evidence read from the repo: c-fix-commit.md / c-refactor-commit.md / c-security-loop.md frontmatter, Doc/chain-commands.md (existing /prompt-workflow surface, documented 'pastes text' pitfall for bare /c-... invocation), Doc/prompts.md (existing p-* prompt convention, 'one prompt per turn' guidance, :prompts discoverability note), and test/chain-workflow.test.ts (validates c-*.md frontmatter, chain: resolution, subagent/fork flags — referenced ex\n 185: \"summary\": \"Captured documented /prompt-workflow surface and 'pastes text' pitfall that constrains the shortcut design\"\n 194: \"Problem restatement matches the user's actual three chains (c-fix-commit, c-refactor-commit, c-security-loop) and the documented /prompt-workflow c-... --bg '...' surface.\",\n 202: \"Location of the pi-subagents prompt-workflow adapter is not visible in ~/.pi/agent/prompts/ — Alternative D's time-to-ship is an estimate until that is confirmed.\",\n\npi/.pi/agent/prompts/.pi-subagents/artifacts/5f01a9ab-6def-4648-b9b0-54d97946fdbf_delegate_0_output.md [untracked in git]\n 7: You're invoking three chain recipes (`c-fix-commit`, `c-refactor-commit`, `c-security-loop`) via the verbose `/prompt-workflow <recipe> --bg \"<args>\"` syntax. The friction is **typing + remembering the exact recipe name and flag** every time, not capability — the adapter already works. Constraints that matter: (a) the shortcut must keep running through the existing `pi-subagents` `prompt-workflow` adapter, because that's what `Doc/chain-commands.md` documents and what `test/chain-workflow.test.t...\n 13: **Summary.** Define `fcc`, `rcc`, `scl` (or similar) as shell functions in your dotfiles that expand to `pi /prompt-workflow c-fix-commit --bg \"$@\"` etc.\n 15: **How it works.** Shell functions wrap the verbatim command. pi never sees a new surface; the prompt-workflow adapter and chain recipes are unchanged.\n 33: **Summary.** Create `p-cfix.md`, `p-crefactor.md`, `p-csec.md` (or similar) that contain a single line of body text instructing the model to invoke `/prompt-workflow c-fix-commit --bg \"$@\"` and return.\n 44: - Indirect: the user types `:c-fix \"...\"`, the model has to *decide* to call `/prompt-workflow`, which is a behavior contract you now have to maintain.\n 54: **How it works.** `/prompt-workflow c-fc --bg \"...\"` is shorter than `/prompt-workflow c-fix-commit --bg \"...\"`. No new code, just renaming.\n 69: ### Alternative D — Teach the `pi-subagents` prompt-workflow adapter to accept bare recipe names and a `--shortcut` mapping file\n 71: **Summary.** Add a config file (e.g., `~/.pi/agent/prompts/shortcuts.yaml`) that maps `fcc → c-fix-commit`, `rcc → c-refactor-commit`, `scl → c-security-loop`, so `/prompt-workflow fcc --bg \"...\"` Just Works.\n 73: **How it works.** A small lookup step at the start of the prompt-workflow adapter resolves the shortcut to a full recipe name, then proceeds exactly as today. The chain recipes and `p-*.md` files are unchanged.\n 77: - Discoverable via `/prompt-workflow list --shortcuts` (a small doc/help add).\n 93: **How it works.** The body instructs the model to parse the first token as a subcommand and dispatch to the right `/prompt-workflow` invocation. Everything else routes through the existing adapter.\n 127: 3. `Doc/chain-commands.md` already says chains run through `/prompt-workflow` and that `/c-...` \"just pastes text\" — this is documented behavior. The shortcut should sit at the *shell* layer (where you've already absorbed the verbose command into muscle memory) and not at the prompt layer, which would re-introduce the same \"pastes text instead of running\" pitfall.\n 134: fcc() { pi /prompt-workflow c-fix-commit --bg \"$@\"; }\n 135: rcc() { pi /prompt-workflow c-refactor-commit --bg \"$@\"; }\n 136: scl() { pi /prompt-workflow c-security-loop --bg \"$@\"; }\n 139: Then your real invocation collapses from `/prompt-workflow c-fix-commit --bg \"the checkout inter\"` to `fcc \"the checkout inter\"`. Total on-disk changes: zero.\n 145: 1. **Where does the `pi-subagents` `prompt-workflow` adapter actually live?** Is it a package you can edit, a vendored file, or a third-party dependency? That decides whether D is a 30-minute edit or a fork-and-PR. (Not visible in `~/.pi/agent/prompts/` — it's upstream of this tree.)\n\n[Continue with cursor=\"fff_c1\"]"}],"details":{"totalMatched":61,"totalFiles":997},"isError":false,"timestamp":1784909247509}}
|
||
{"type":"message","id":"4b11d816","parentId":"52e2d84a","timestamp":"2026-07-24T16:07:31.604Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"This is a goldmine. There's a `src/slash/prompt-workflows.ts` in pi-subagents. So `/prompt-workflow` IS a pi-subagents command. Let me read that file and the `Doc/chain-commands.md` in the user's repo.\n\nAlso, the session transcript reveals that the user previously asked about creating shortcuts and got advice. Now they're asking a follow-up: can the c-* prompts be changed so they don't create a new `pi -p` session, and is there an automatic tool that picks the best subagent/prompt.\n\nThe `prompt-workflow` adapter seems to be running `pi -p` to execute chains. The user doesn't like that once started, it's hard to stop. They want it to run in the current interactive session instead.\n\nLet me read the prompt-workflow source to understand how it works.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:24","name":"read","arguments":{"path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/src/slash/prompt-workflows.ts"}},{"type":"toolCall","id":"functions.read:25","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":54646,"output":242,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":54888,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909247512,"responseId":"chatcmpl-429","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"c444e19c","parentId":"4b11d816","timestamp":"2026-07-24T16:07:31.606Z","message":{"role":"toolResult","toolCallId":"functions.read:24","toolName":"read","content":[{"type":"text","text":"import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ExtensionAPI, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { parseFrontmatter } from \"../agents/frontmatter.ts\";\nimport type { SubagentParamsLike } from \"../runs/foreground/subagent-executor.ts\";\nimport type { ChainStep } from \"../shared/settings.ts\";\nimport { getAgentDir, getProjectConfigDir } from \"../shared/utils.ts\";\n\ninterface PromptWorkflow {\n\tname: string;\n\tdescription: string;\n\tbody: string;\n\tfilePath: string;\n\tagent: string;\n\tcontext?: \"fresh\" | \"fork\";\n\tmodel?: string;\n\tskill?: string | string[] | false;\n\tcwd?: string;\n\tworktree?: boolean;\n\tchain?: string;\n}\n\ntype PromptWorkflowRunner = (params: SubagentParamsLike, ctx: ExtensionContext) => Promise<void>;\n\nconst RESERVED_COMMAND_NAMES = new Set([\n\t\"chain-prompts\",\n\t\"prompt-workflow\",\n\t\"run\",\n\t\"chain\",\n\t\"parallel\",\n\t\"run-chain\",\n\t\"subagents-doctor\",\n\t\"subagents-models\",\n]);\n\nfunction packagePromptsDir(): string {\n\treturn path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"..\", \"..\", \"prompts\");\n}\n\nfunction promptDirs(cwd: string): string[] {\n\treturn [\n\t\tpackagePromptsDir(),\n\t\tpath.join(getAgentDir(), \"prompts\"),\n\t\tpath.join(getProjectConfigDir(cwd), \"prompts\"),\n\t];\n}\n\nfunction readPromptFiles(cwd: string): string[] {\n\tconst files: string[] = [];\n\tfor (const dir of promptDirs(cwd)) {\n\t\tlet entries: fs.Dirent[];\n\t\ttry {\n\t\t\tentries = fs.readdirSync(dir, { withFileTypes: true });\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.isFile() && entry.name.endsWith(\".md\")) files.push(path.join(dir, entry.name));\n\t\t}\n\t}\n\treturn files;\n}\n\nfunction firstNonEmptyLine(value: string): string {\n\treturn value.split(/\\r?\\n/).map((line) => line.trim()).find(Boolean) ?? \"Prompt workflow\";\n}\n\nfunction stringField(frontmatter: Record<string, string>, key: string): string | undefined {\n\tconst value = frontmatter[key]?.trim();\n\treturn value ? value : undefined;\n}\n\nfunction booleanField(frontmatter: Record<string, string>, key: string): boolean | undefined {\n\tconst value = frontmatter[key]?.trim().toLowerCase();\n\tif (value === \"true\" || value === \"yes\" || value === \"1\") return true;\n\tif (value === \"false\" || value === \"no\" || value === \"0\") return false;\n\treturn undefined;\n}\n\nfunction parseSkill(value: string | undefined): string | string[] | false | undefined {\n\tif (!value) return undefined;\n\tif (value === \"false\") return false;\n\tconst parts = value.split(\",\").map((part) => part.trim()).filter(Boolean);\n\treturn parts.length > 1 ? parts : parts[0];\n}\n\nfunction parseAgent(frontmatter: Record<string, string>): string {\n\tconst subagent = stringField(frontmatter, \"subagent\");\n\tif (!subagent || subagent === \"true\") return \"delegate\";\n\treturn subagent;\n}\n\nfunction loadPromptWorkflow(filePath: string): PromptWorkflow | undefined {\n\tconst content = fs.readFileSync(filePath, \"utf-8\");\n\tconst { frontmatter, body } = parseFrontmatter(content);\n\tconst name = path.basename(filePath, \".md\");\n\tif (!name || RESERVED_COMMAND_NAMES.has(name)) return undefined;\n\tconst model = stringField(frontmatter, \"model\");\n\tconst skill = parseSkill(stringField(frontmatter, \"skill\"));\n\tconst cwd = stringField(frontmatter, \"cwd\");\n\tconst chain = stringField(frontmatter, \"chain\");\n\treturn {\n\t\tname,\n\t\tdescription: stringField(frontmatter, \"description\") ?? firstNonEmptyLine(body),\n\t\tbody,\n\t\tfilePath,\n\t\tagent: parseAgent(frontmatter),\n\t\t...(booleanField(frontmatter, \"inheritContext\") === true || booleanField(frontmatter, \"fork\") === true ? { context: \"fork\" as const } : {}),\n\t\t...(booleanField(frontmatter, \"fresh\") === true ? { context: \"fresh\" as const } : {}),\n\t\t...(model ? { model } : {}),\n\t\t...(skill !== undefined ? { skill } : {}),\n\t\t...(cwd ? { cwd } : {}),\n\t\t...(booleanField(frontmatter, \"worktree\") === true ? { worktree: true } : {}),\n\t\t...(chain ? { chain } : {}),\n\t};\n}\n\nexport function discoverPromptWorkflows(cwd: string): PromptWorkflow[] {\n\tconst workflows = new Map<string, PromptWorkflow>();\n\tfor (const file of readPromptFiles(cwd)) {\n\t\tconst workflow = loadPromptWorkflow(file);\n\t\tif (workflow) workflows.set(workflow.name, workflow);\n\t}\n\treturn [...workflows.values()].sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction shellWords(input: string): string[] {\n\tconst words: string[] = [];\n\tlet current = \"\";\n\tlet quote: \"'\" | '\"' | undefined;\n\tlet escaped = false;\n\tfor (const ch of input) {\n\t\tif (escaped) {\n\t\t\tcurrent += ch;\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \"\\\\\") {\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote) {\n\t\t\tif (ch === quote) quote = undefined;\n\t\t\telse current += ch;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \"'\" || ch === '\"') {\n\t\t\tquote = ch;\n\t\t\tcontinue;\n\t\t}\n\t\tif (/\\s/.test(ch)) {\n\t\t\tif (current) {\n\t\t\t\twords.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tcurrent += ch;\n\t}\n\tif (current) words.push(current);\n\treturn words;\n}\n\nfunction substituteArgs(template: string, args: string[]): string {\n\tconst all = args.join(\" \");\n\treturn template\n\t\t.replace(/\\$ARGUMENTS/g, all)\n\t\t.replace(/\\$@/g, all)\n\t\t.replace(/\\$\\{(\\d+):-([^}]*)\\}/g, (_match, index: string, fallback: string) => args[Number(index) - 1] || fallback)\n\t\t.replace(/\\$(\\d+)/g, (_match, index: string) => args[Number(index) - 1] ?? \"\");\n}\n\nfunction parseRuntimeOptions(words: string[]): { args: string[]; agentOverride?: string; fork?: boolean; fresh?: boolean; worktree?: boolean; bg?: boolean } {\n\tconst args: string[] = [];\n\tlet agentOverride: string | undefined;\n\tlet fork = false;\n\tlet fresh = false;\n\tlet worktree = false;\n\tlet bg = false;\n\tfor (let i = 0; i < words.length; i++) {\n\t\tconst word = words[i]!;\n\t\tif (word === \"--fork\") {\n\t\t\tfork = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (word === \"--fresh\") {\n\t\t\tfresh = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (word === \"--worktree\") {\n\t\t\tworktree = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (word === \"--bg\" || word === \"--async\") {\n\t\t\tbg = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (word === \"--subagent\") {\n\t\t\tagentOverride = words[++i];\n\t\t\tcontinue;\n\t\t}\n\t\tconst eq = word.match(/^--subagent(?:=|:)(.+)$/);\n\t\tif (eq) {\n\t\t\tagentOverride = eq[1];\n\t\t\tcontinue;\n\t\t}\n\t\targs.push(word);\n\t}\n\treturn { args, agentOverride, fork, fresh, worktree, bg };\n}\n\nfunction splitChainDeclaration(input: string): { declaration: string; argsText: string } {\n\tconst delimiter = input.indexOf(\" -- \");\n\tif (delimiter === -1) return { declaration: input.trim(), argsText: \"\" };\n\treturn { declaration: input.slice(0, delimiter).trim(), argsText: input.slice(delimiter + 4).trim() };\n}\n\nfunction splitPromptChain(input: string): string[] {\n\treturn input.split(\" -> \").map((part) => part.trim()).filter(Boolean);\n}\n\nfunction workflowParams(workflow: PromptWorkflow, args: string[], runtime: ReturnType<typeof parseRuntimeOptions>): SubagentParamsLike {\n\tconst task = substituteArgs(workflow.body, args).trim();\n\tconst context = runtime.fork ? \"fork\" : runtime.fresh ? \"fresh\" : workflow.context;\n\treturn {\n\t\tagent: runtime.agentOverride ?? workflow.agent,\n\t\ttask,\n\t\tclarify: false,\n\t\tagentScope: \"both\",\n\t\t...(context ? { context } : {}),\n\t\t...(workflow.model ? { model: workflow.model } : {}),\n\t\t...(workflow.skill !== undefined ? { skill: workflow.skill } : {}),\n\t\t...(workflow.cwd ? { cwd: workflow.cwd } : {}),\n\t\t...(runtime.worktree || workflow.worktree ? { worktree: true } : {}),\n\t\t...(runtime.bg ? { async: true } : {}),\n\t};\n}\n\nfunction workflowChainStep(workflow: PromptWorkflow, args: string[], runtime: ReturnType<typeof parseRuntimeOptions>): ChainStep {\n\tconst params = workflowParams(workflow, args, runtime);\n\treturn {\n\t\tagent: params.agent ?? \"delegate\",\n\t\ttask: params.task,\n\t\t...(params.model ? { model: params.model } : {}),\n\t\t...(params.skill !== undefined ? { skill: params.skill } : {}),\n\t\t...(params.cwd ? { cwd: params.cwd } : {}),\n\t};\n}\n\nfunction findWorkflow(workflows: PromptWorkflow[], name: string): PromptWorkflow | undefined {\n\treturn workflows.find((workflow) => workflow.name === name);\n}\n\nfunction formatWorkflowList(workflows: PromptWorkflow[]): string {\n\tif (workflows.length === 0) return \"No prompt workflows found in package, user, or project prompts.\";\n\treturn [\n\t\t\"Prompt workflows:\",\n\t\t...workflows.map((workflow) => `- ${workflow.name}: ${workflow.description} (${workflow.filePath})`),\n\t].join(\"\\n\");\n}\n\nexport function registerPromptWorkflowCommands(input: {\n\tpi: ExtensionAPI;\n\trun: PromptWorkflowRunner;\n}): void {\n\tconst { pi, run } = input;\n\n\tpi.registerCommand(\"prompt-workflow\", {\n\t\tdescription: \"Run a prompt template through native pi-subagents: /prompt-workflow <name> [args]\",\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\tconst words = shellWords(rawArgs);\n\t\t\tconst name = words.shift();\n\t\t\tconst workflows = discoverPromptWorkflows(ctx.cwd);\n\t\t\tif (!name || name === \"list\") {\n\t\t\t\tpi.sendMessage({ content: formatWorkflowList(workflows), display: true });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst workflow = findWorkflow(workflows, name);\n\t\t\tif (!workflow) {\n\t\t\t\tctx.ui.notify(`Unknown prompt workflow: ${name}`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst runtime = parseRuntimeOptions(words);\n\t\t\ttry {\n\t\t\t\tif (workflow.chain) {\n\t\t\t\t\tconst chainNames = splitPromptChain(workflow.chain);\n\t\t\t\t\tconst chain = chainNames.map((stepName) => {\n\t\t\t\t\t\tconst step = findWorkflow(workflows, stepName);\n\t\t\t\t\t\tif (!step) throw new Error(`Unknown prompt workflow in chain '${workflow.name}': ${stepName}`);\n\t\t\t\t\t\treturn workflowChainStep(step, runtime.args, runtime);\n\t\t\t\t\t});\n\t\t\t\t\tawait run({ chain, task: runtime.args.join(\" \"), clarify: false, agentScope: \"both\", ...(runtime.bg ? { async: true } : {}) }, ctx);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait run(workflowParams(workflow, runtime.args, runtime), ctx);\n\t\t\t} catch (error) {\n\t\t\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n\n\tpi.registerCommand(\"chain-prompts\", {\n\t\tdescription: \"Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args\",\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\tconst { declaration, argsText } = splitChainDeclaration(rawArgs);\n\t\t\tconst workflows = discoverPromptWorkflows(ctx.cwd);\n\t\t\tif (!declaration || declaration === \"list\") {\n\t\t\t\tpi.sendMessage({ content: formatWorkflowList(workflows), display: true });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst runtime = parseRuntimeOptions(shellWords(argsText));\n\t\t\tconst names = splitPromptChain(declaration);\n\t\t\tif (names.length === 0) {\n\t\t\t\tctx.ui.notify(\"Usage: /chain-prompts prompt-a -> prompt-b -- args\", \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst chain = names.map((name) => {\n\t\t\t\t\tconst workflow = findWorkflow(workflows, name);\n\t\t\t\t\tif (!workflow) throw new Error(`Unknown prompt workflow: ${name}`);\n\t\t\t\t\treturn workflowChainStep(workflow, runtime.args, runtime);\n\t\t\t\t});\n\t\t\t\tawait run({ chain, task: runtime.args.join(\" \"), clarify: false, agentScope: \"both\", ...(runtime.bg ? { async: true } : {}) }, ctx);\n\t\t\t} catch (error) {\n\t\t\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n"}],"isError":false,"timestamp":1784909251606}}
|
||
{"type":"message","id":"bf27bb22","parentId":"c444e19c","timestamp":"2026-07-24T16:07:31.607Z","message":{"role":"toolResult","toolCallId":"functions.read:25","toolName":"read","content":[{"type":"text","text":"# Chain Commands Reference\n\nThis file documents how to invoke the `c-*` chain recipes defined in `~/.pi/agent/prompts/`.\n\n## What the chains are\n\nThe `c-*` files are orchestration recipes. They do not contain new prompts; they reuse the existing `p-*` prompts and run them in sequence through the `pi-subagents` prompt-workflow adapter. Each step is executed as a forked-context subagent, so later steps can see the outputs from earlier steps.\n\n## Available chains\n\n| Command file | Sequence | Use it when |\n|---|---|---|\n| `c-design-build.md` | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |\n| `c-fix-commit.md` | `p-summarize → p-diagnose → p-debug → p-test` | You need to understand a bug, diagnose it, fix it, and add regression tests. |\n| `c-refactor-commit.md` | `p-refactor → p-test → p-review → p-commit` | You want a safe refactor with tests, review, and a commit. |\n| `c-security-loop.md` | `p-secaudit → p-review → p-test` | You need a security-first review plus tests before proceeding. |\n\n## How to run a chain\n\nChains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit \"src/utils.ts\"\n/prompt-workflow c-security-loop \"auth endpoint\"\n```\n\nEach chain runs asynchronously by default. Check progress with:\n\n```text\n/subagents-fleet\n```\n\nor inspect a specific run with:\n\n```text\nsubagent({ action: \"status\" })\n```\n\n## Ad-hoc chains\n\nYou can also run the same sequence on the fly without creating a recipe file:\n\n```text\n/chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- \"add a rate-limiter\"\n/chain-prompts p-summarize -> p-diagnose -> p-debug -> p-test -- \"intermittent timeout\"\n/chain-prompts p-refactor -> p-test -> p-review -> p-commit -- \"src/utils.ts\"\n/chain-prompts p-secaudit -> p-review -> p-test -- \"auth endpoint\"\n```\n\nUse `--bg` or `--async` to detach an ad-hoc chain:\n\n```text\n/chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- \"src/utils.ts\"\n```\n\n## Why individual prompts are the subagents\n\nOnly the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:\n\n1. It sees the `chain:` frontmatter.\n2. It resolves each named step to a `p-*.md` file.\n3. It runs that prompt as a forked-context subagent (`delegate` by default).\n4. The output of each step is passed to the next step via the chain runner.\n\nThis keeps the chain recipes small and the individual prompts reusable as both standalone slash templates and chain steps.\n\n## Context flow\n\nBecause each `p-*` step uses `fork: true`, every subagent inherits the parent session history. That means later steps naturally see what earlier steps produced, without needing explicit `{previous}` placeholders inside the prompt bodies.\n\nThe trade-off is higher per-step context usage. If token cost becomes an issue, a future migration could switch the `p-*` prompts to `fresh: true` and introduce explicit `{previous}` handling inside their bodies.\n\n## Troubleshooting\n\n| Symptom | What to check |\n|---|---|\n| `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |\n| Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |\n| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |\n| Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |\n"}],"isError":false,"timestamp":1784909251607}}
|
||
{"type":"message","id":"4423391a","parentId":"bf27bb22","timestamp":"2026-07-24T16:07:34.430Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now I understand the full picture. Let me also read the prompts.md doc and the p-* prompt files to see how they are configured (subagent: true, fork: true, async: true, etc.).","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:26","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/Doc/prompts.md"}},{"type":"toolCall","id":"functions.read:27","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-brainstorm.md"}},{"type":"toolCall","id":"functions.read:28","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-plan.md"}},{"type":"toolCall","id":"functions.read:29","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-test.md"}},{"type":"toolCall","id":"functions.read:30","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-commit.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":58729,"output":187,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":58916,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909251608,"responseId":"chatcmpl-703","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"8a59741e","parentId":"4423391a","timestamp":"2026-07-24T16:07:34.433Z","message":{"role":"toolResult","toolCallId":"functions.read:26","toolName":"read","content":[{"type":"text","text":"# Prompts\n\nSlash-style prompts for the interactive pi session. Each file is a `p-<verb>.md` template with a frontmatter `description` + `argument-hint` and a structured body. Invoke with `:p-<verb> [arg]` or via the `:prompts` TUI picker.\n\n## When to use which\n\n| Prompt | Use it when… | Pairs well with |\n| ------------------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| **`p-plan`** | You're about to start a non-trivial change and want a structured plan before coding. | `p-brainstorm` (first), then `p-refactor` / `p-test` |\n| **`p-brainstorm`** | You have a problem but no chosen approach yet; want 3–5 alternatives with trade-offs. | `p-plan` (after picking one) |\n| **`p-explain`** | You don't understand a piece of code, a concept, or an error message. | `p-debug` / `p-diagnose` (if it's a problem) |\n| **`p-debug`** | A test, build, or command is failing with a clear error. You have the error in hand. | `p-test` (add a regression test after the fix) |\n| **`p-diagnose`** | Nothing is \"failing\" but behavior is wrong — wrong values, races, perf drift, \"passes locally, broken in prod.\" | `p-debug` (if you find a hard failure) |\n| **`p-review`** | You want a code review of a diff, file, or staged change. General quality feedback. | `p-secaudit` (security subset) |\n| **`p-secaudit`** | Touching auth, input handling, secrets, network, deserialization, or any trust boundary. | `p-review` (broader quality), `p-test` |\n| **`p-refactor`** | Restructuring code without changing behavior. Safety-first, mechanical steps. | `p-test` (first, as the safety net), `p-review` (after) |\n| **`p-test`** | You need to write or expand tests for existing or new code. | `p-debug` (after a failure), `p-refactor` (before) |\n| **`p-doc`** | Writing or improving README, docstrings, JSDoc, godoc, or ADRs. | `p-summarize` (skim the code first) |\n| **`p-commit`** | About to commit. You want a conventional message and (optionally) a PR description. | `p-review` (final check before committing) |\n| **`p-summarize`** | A file, log, diff, or document is too long to read in full. You need the gist + key details. | `p-plan` / `p-debug` (then dive into specifics) |\n\n## Decision flow\n\n```\nGot an idea or vague problem?\n└─ Yes → p-brainstorm → pick an approach → p-plan → implement\n └─ p-test → p-commit\nTouching existing code that needs to change?\n└─ p-refactor (after p-test confirms a safety net) → p-review → p-commit\nSomething is broken?\n├─ Hard failure (error message, failing test) → p-debug\n└─ Soft failure (wrong output, race, perf) → p-diagnose\n → fix → p-test (regression) → p-commit\nTouching a trust boundary, auth, secrets, or untrusted input?\n└─ p-secaudit (then p-review for general quality)\nNeed to understand a long file/log/diff quickly?\n└─ p-summarize\nNeed to write or update docs?\n└─ p-doc\nDon't know what something does or what an error means?\n└─ p-explain\n```\n\n## Chain recipes\n\nThe `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default.\n\n| Recipe | Sequence | Use it when… |\n| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------- |\n| **`c-design-build`** | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |\n| **`c-fix-commit`** | `p-summarize → p-diagnose → p-debug → p-test` | You need to understand a bug, diagnose it, fix it, and add regression tests. |\n| **`c-refactor-commit`** | `p-refactor → p-test → p-review → p-commit` | You want a safe refactor with tests, review, and a commit. |\n| **`c-security-loop`** | `p-secaudit → p-review → p-test` | You need a security-first review plus tests before proceeding. |\n\nInvoke a chain with `/prompt-workflow`, not `/c-recipe`:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n/prompt-workflow c-security-loop --bg \"auth endpoint\"\n```\n\nEach chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n\n```text\n/chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- \"add a rate-limiter\"\n```\n\n## Conventions\n\n- Every prompt uses `$@` for the user-supplied argument. Pass an argument at invocation time; if the request is under-specified, the prompt will ask clarifying questions.\n- Output is structured (numbered sections, fixed categories) so the result is diff-friendly and skim-friendly.\n- Prompts intentionally do **not** overlap with subagent workflows (`agents/`, `chains/`, `skills/`) — those are for orchestration; these are for interactive turns.\n- Prefer one prompt per turn. Chain them yourself (`p-brainstorm` → `p-plan` → `p-refactor`) rather than asking one prompt to do everything.\n"}],"isError":false,"timestamp":1784909254433}}
|
||
{"type":"message","id":"23209f52","parentId":"8a59741e","timestamp":"2026-07-24T16:07:34.433Z","message":{"role":"toolResult","toolCallId":"functions.read:27","toolName":"read","content":[{"type":"text","text":"---\ndescription: Generate 3–5 design alternatives with trade-offs before committing to an approach\nargument-hint: \"[problem or feature to design]\"\nsubagent: true\nfork: true\n---\nBrainstorm approaches for: $@\n\nStructure your answer as:\n1. **Problem restatement** — one paragraph; what we're solving, what constraints matter, what \"done\" looks like\n2. **Alternatives** — 3 to 5 distinct approaches. For each:\n - **Summary** — one or two sentences\n - **How it works** — the key mechanism\n - **Pros** — what it gets right\n - **Cons** — what it costs, risks, or breaks\n - **Best when** — the conditions that would make this the right pick\n3. **Comparison table** — across the alternatives, score or rank on: complexity, time-to-ship, reversibility, performance, fit-with-existing-code\n4. **Recommendation** — which one to pick *given the current codebase*, with the second choice as a fallback\n5. **Unknowns** — questions that, if answered, would change the recommendation\n\nBe opinionated. Surface real trade-offs, not strawmen. If the obvious approach wins decisively, say so and only enumerate 2 alternatives — don't manufacture options for the sake of a full set. If the problem is under-specified, ask clarifying questions before brainstorming.\n"}],"isError":false,"timestamp":1784909254433}}
|
||
{"type":"message","id":"d05d24ae","parentId":"23209f52","timestamp":"2026-07-24T16:07:34.433Z","message":{"role":"toolResult","toolCallId":"functions.read:28","toolName":"read","content":[{"type":"text","text":"---\ndescription: Create a structured implementation plan before coding\nargument-hint: \"[task or feature]\"\nsubagent: true\nfork: true\n---\nCreate a structured implementation plan for: $@\n\nFollow this format:\n1. **Goal** — one-sentence objective\n2. **Constraints** — existing code, dependencies, tests, or assumptions to respect\n3. **Approach** — high-level strategy and rationale\n4. **Steps** — numbered, actionable tasks small enough to verify one at a time\n5. **Verification** — how to confirm each step works (tests, logs, manual checks)\n6. **Risks & Rollbacks** — what could go wrong and how to undo safely\n7. **Open Questions** — anything that needs clarification before starting\n\nUse the codebase context as needed. Do not write implementation code yet; only produce the plan."}],"isError":false,"timestamp":1784909254433}}
|
||
{"type":"message","id":"428ffeac","parentId":"d05d24ae","timestamp":"2026-07-24T16:07:34.434Z","message":{"role":"toolResult","toolCallId":"functions.read:29","toolName":"read","content":[{"type":"text","text":"---\ndescription: Write or expand unit / integration tests for the given code\nargument-hint: \"[file path, function, or feature to test]\"\nsubagent: true\nfork: true\n---\nWrite tests for: $@\n\nStructure your answer as:\n1. **Existing conventions** — name patterns, framework, assertion style, fixtures; match what's already there\n2. **Test cases to add** — grouped as:\n - **Happy path** — the primary expected behavior\n - **Edge cases** — empty, zero, max, boundary, off-by-one\n - **Error cases** — invalid input, missing deps, timeouts, permission failures\n3. **Test code** — minimal, runnable, following the project's framework (jest, pytest, go test, etc.)\n4. **How to run** — the exact command, plus how to run just the new tests\n5. **Coverage gaps** — anything still untestable without a refactor; flag it but do not refactor in this pass\n\nKeep tests independent, deterministic, and fast. Prefer many small tests over one large one. If the codebase has no test setup yet, propose the smallest viable setup and call it out clearly so the user can approve before you scaffold it.\n"}],"isError":false,"timestamp":1784909254434}}
|
||
{"type":"message","id":"d5c17143","parentId":"428ffeac","timestamp":"2026-07-24T16:07:34.434Z","message":{"role":"toolResult","toolCallId":"functions.read:30","toolName":"read","content":[{"type":"text","text":"---\ndescription: Generate a conventional commit message and optional PR description from current changes\nargument-hint: \"[diff, file list, or 'auto' to use git status]\"\nsubagent: true\nfork: true\n---\nGenerate a commit message for: $@\n\nStructure your answer as:\n1. **Type & scope** — one of: feat, fix, refactor, perf, test, docs, build, ci, chore, style; scope is the affected module/subsystem\n2. **Subject** — imperative mood, ≤72 chars, no trailing period, no emoji\n3. **Body** — wrapped at 72 cols, explain *why* not *what*. Use bullet points for multiple distinct changes.\n4. **Footer** — `BREAKING CHANGE: …` if applicable; `Refs: #123` for linked issues\n5. **PR description** (if the change is non-trivial) — Summary, Motivation, Changes, Test plan, Risks\n\nFormat the final message in a single fenced block ready to copy. If the change spans multiple logical commits, propose a split with one subject per commit and the file groups that belong in each.\n\nRead the diff before writing — never invent files, symbols, or behavior. If `git status` is empty or the diff is unclear, ask before fabricating.\n"}],"isError":false,"timestamp":1784909254434}}
|
||
{"type":"message","id":"9211595a","parentId":"d5c17143","timestamp":"2026-07-24T16:07:45.052Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now I have complete context. The user's setup:\n\n1. They have `p-*.md` prompts configured as subagents (`subagent: true`, `fork: true`).\n2. They have `c-*.md` chain recipes with `chain:` frontmatter that list sequences of `p-*.md` prompts.\n3. They invoke them via `/prompt-workflow c-design-build --bg \"...\"` using the pi-subagents prompt-workflow adapter.\n4. The adapter runs these as subagent chains in the current pi session (not a new `pi -p` session per se), but they run **asynchronously** (`--bg`) which detaches them.\n\nWait, the user said \"create a new pi -p session\". But actually `/prompt-workflow` runs them as subagents within the current pi session. Maybe the user is confusing this with `pi -p` because the subagent child processes run headlessly similar to `pi -p`. Or maybe they have a shell alias that uses `pi -p`.\n\nActually, looking at the session history, the previous question was about shortcuts, and the recommendation was shell functions like `fcc() { pi /prompt-workflow c-fix-commit --bg \"$@\"; }`. That would indeed run a new `pi` process (interactive mode by default, not `-p`) from the shell. Wait, `pi /prompt-workflow ...` starts a new interactive pi session with that initial message. Then the `/prompt-workflow` command runs in that new session.\n\nHmm, but the user says \"create a new pi -p session\". Maybe they use `pi -p /prompt-workflow ...` in their shortcut. Or maybe they think subagents are like `pi -p` sessions.\n\nAnyway, the core answer is: yes, you can change them to run in the foreground in the current session. Just remove `--bg`/`--async` from the invocation, or set `async: false` in the recipe frontmatter. When run in foreground, you can stop them with Esc / Ctrl+C.\n\nBut there's a subtlety: the c-*.md files themselves don't run as subagents - they are chain recipes. The chain runs via `run({ chain, task, clarify: false, agentScope: \"both\", ...(runtime.bg ? { async: true } : {}) }, ctx)`. If no `--bg`, the chain runs in foreground. In foreground, you can interrupt with Escape/Ctrl+C.\n\nAlso, the individual p-*.md steps have `fork: true` which means each subagent inherits parent context. They don't create new `pi -p` sessions; they are child pi processes spawned by the parent.\n\nFor the second question: is there an automatic tool that picks the most fitting subagent/prompt? Yes, the parent agent can naturally decide, or you can create a custom agent. But there's no built-in \"auto-router\" command. I can suggest creating a `router` agent or using natural language.\n\nWait, actually pi-subagents has a bundled skill that helps the parent decide. And the parent agent can use `subagent({ agent: \"...\", task: \"...\" })` naturally. But the user specifically asks about \"automatic tool that would just use whatever subagent or prompt is the most fitting\". \n\nI could also suggest creating a prompt template like `p-route` or a custom agent `router` that takes the task and emits which chain to run. But the simplest is to just ask pi naturally: \"Design and implement a rate limiter\" and let the bundled skill decide whether to run a chain.\n\nActually, the most fitting answer is to create a custom agent or use a prompt template that the parent can invoke. For example, a `router.md` prompt or `auto` chain that delegates to the best c-* recipe. But pi-subagents doesn't have a built-in automatic router.\n\nLet me also check the user's dotfiles for any existing `auto` or `router` prompt.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.fffind:31","name":"fffind","arguments":{"pattern":"auto route|router|/prompt-workflow|subagent.*automatic","path":"/home/liph/dotfiles/pi/.pi/agent/prompts"}},{"type":"toolCall","id":"functions.read:32","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-debug.md"}},{"type":"toolCall","id":"functions.read:33","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-diagnose.md"}},{"type":"toolCall","id":"functions.read:34","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-refactor.md"}},{"type":"toolCall","id":"functions.read:35","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-review.md"}},{"type":"toolCall","id":"functions.read:36","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-secaudit.md"}},{"type":"toolCall","id":"functions.read:37","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/p-summarize.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":61383,"output":1029,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":62412,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909254435,"responseId":"chatcmpl-438","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"2b1536e7","parentId":"9211595a","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.fffind:31","toolName":"fffind","content":[{"type":"text","text":"No files found matching pattern"}],"details":{"totalMatched":0,"totalFiles":72,"pageIndex":0,"hasMore":false},"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"1b0de69d","parentId":"2b1536e7","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.read:32","toolName":"read","content":[{"type":"text","text":"---\ndescription: Diagnose a failing test, build, or runtime error\nargument-hint: \"[error message, test name, or stack trace]\"\nsubagent: true\nfork: true\n---\nDiagnose the following failure: $@\n\nStructure your answer as:\n1. **What failed** — one-sentence summary; quote the exact error line\n2. **Likely root cause** — ranked list, most probable first\n3. **Minimal fix** — the smallest change that would resolve it\n4. **How to verify** — the exact command or test to confirm the fix\n5. **How to prevent** — a regression test, invariant, or guard to add\n\nBe specific. If multiple causes are plausible, name each and give a quick disambiguation check (a log line, a flag, a one-line probe) to tell them apart. Do not speculate beyond what the error message and the code actually show — if you need more data, say so explicitly.\n"}],"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"cb50637b","parentId":"1b0de69d","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.read:33","toolName":"read","content":[{"type":"text","text":"---\ndescription: Diagnose unexpected behavior, not just failures (race conditions, perf regressions, weird output)\nargument-hint: \"[symptom or observed behavior]\"\nsubagent: true\nfork: true\n---\nDiagnose the following unexpected behavior: $@\n\nStructure your answer as:\n1. **What's wrong** — restate the observed behavior vs the expected behavior in one sentence each\n2. **Where in the code** — point at the specific functions, lines, or modules most likely responsible\n3. **Hypotheses** — 2–4 ranked explanations with the evidence for and against each\n4. **Disambiguation** — the cheapest experiment (log, flag, breakpoint, minimal repro) that would confirm or rule out each hypothesis\n5. **Likely fix** — once a hypothesis is confirmed, the smallest change that would correct it\n6. **Why it wasn't caught** — what test, type, or invariant would have caught this earlier\n\nUse this when nothing is \"failing\" but behavior is wrong: a value drifts, a UI flashes, a query is slow, two users see different results. Distinguish carefully between \"the test fails\" (use `p-debug`) and \"the test passes but production is broken\" (this prompt).\n"}],"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"cd88930b","parentId":"cb50637b","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.read:34","toolName":"read","content":[{"type":"text","text":"---\ndescription: Safely restructure code without changing behavior\nargument-hint: \"[file path or symbol to refactor]\"\nsubagent: true\nfork: true\n---\nRefactor: $@\n\nStructure your answer as:\n1. **Current shape** — what this code does today, in terms of responsibilities (not lines)\n2. **Target shape** — what the refactor preserves externally (behavior, API, output) and what it improves internally (readability, coupling, testability, reuse)\n3. **Why this is safe** — the test/contract that proves the refactor doesn't change behavior. If none exists, STOP and recommend `p-test` first.\n4. **Step-by-step mechanical changes** — numbered, each one individually committable and runnable\n5. **After each step** — the command to run (test, type-check, lint) to confirm green\n6. **Final verification** — full test suite, plus any manual smoke check\n7. **Rollback** — how to revert each step in isolation (e.g. one commit = one rollback unit)\n\nDo not combine refactor with new features. Do not change behavior \"while you're in there.\" If you spot a bug or a missing test, call it out separately at the end, do not fix it inline.\n"}],"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"272c6600","parentId":"cd88930b","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.read:35","toolName":"read","content":[{"type":"text","text":"---\ndescription: Review code, diffs, or changes with actionable feedback\nargument-hint: \"[target: file path, diff, or PR]\"\nsubagent: true\nfork: true\n---\nReview the following code or changes: $@\n\nProvide feedback in these categories:\n- **Correctness** — bugs, logic errors, edge cases, race conditions\n- **Security** — injection, unsafe defaults, secrets, auth/z issues\n- **Performance** — unnecessary work, memory leaks, hot-path inefficiencies\n- **Maintainability** — naming, complexity, duplication, testability\n- **Style & Idioms** — consistency with the surrounding codebase\n- **Error Handling** — missing or misleading failure modes\n\nFor each issue, include:\n- The specific location (file, line, function)\n- A clear description of the problem\n- A concrete suggestion or example fix\n\nAlso call out anything done well. Keep the review concise and prioritized."}],"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"8a8078ef","parentId":"272c6600","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.read:36","toolName":"read","content":[{"type":"text","text":"---\ndescription: Security-focused review covering OWASP-style categories\nargument-hint: \"[file path, diff, or feature to audit]\"\nsubagent: true\nfork: true\n---\nSecurity-audit: $@\n\nStructure your answer as:\n1. **Trust boundary** — where untrusted input enters, where sensitive data leaves; map the attack surface in one paragraph\n2. **Findings** — grouped by severity (Critical / High / Medium / Low / Info). For each:\n - **Category** — one of: Injection, AuthN/AuthZ, Secrets, Crypto, Input validation, Output encoding, Deserialization, SSRF, Path traversal, Race/TOC-TOU, Dependency, Logging/PII, Configuration, Supply chain\n - **Location** — file, line, function\n - **Description** — the vulnerability, with a concrete exploit scenario\n - **Fix** — the minimal secure change, with a code snippet\n3. **Missing controls** — auth, rate limiting, audit logging, CSRF/CORS, headers, etc. that should exist but don't\n4. **Dependencies** — any third-party packages with known CVEs in this surface (if you can determine versions)\n5. **Threat model gaps** — what's out of scope for this audit but worth a separate pass\n\nBe concrete and adversarial — describe a real attack, not \"consider validating input.\" If the code is sound, say so explicitly and explain what you'd look for if it weren't. Do not pad with general security advice that doesn't apply to the specific code.\n"}],"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"98ae20bf","parentId":"8a8078ef","timestamp":"2026-07-24T16:07:45.060Z","message":{"role":"toolResult","toolCallId":"functions.read:37","toolName":"read","content":[{"type":"text","text":"---\ndescription: Summarize a long file, log, diff, or document into structured notes\nargument-hint: \"[file path, log, or topic to summarize]\"\nsubagent: true\nfork: true\n---\nSummarize: $@\n\nStructure your answer as:\n1. **One-paragraph gist** — what this is, in plain terms, at the level a smart non-expert would understand\n2. **Key points** — 5 to 10 bullets, ordered by importance, each ≤2 lines\n3. **Structure** — how the content is organized: sections, layers, time periods, components\n4. **Important details** — names, numbers, paths, error codes, dates, anything concrete that a later reader will need verbatim\n5. **What's missing or unclear** — gaps, assumptions, things that need a follow-up read\n6. **Pointer to deep-dive sections** — if a reader only has 5 minutes, which 2–3 sections cover 80% of the value\n\nBe ruthless about compression. If the source is long, the summary should be short — that's the whole point. Prefer concrete over abstract. Quote exact strings (paths, error messages, identifiers) rather than paraphrasing them, because the reader will likely need to grep for them later. Do not editorialize or add recommendations; just compress.\n"}],"isError":false,"timestamp":1784909265060}}
|
||
{"type":"message","id":"e208ce54","parentId":"98ae20bf","timestamp":"2026-07-24T16:08:08.397Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now I have full context. Let me think about the best answer.\n\nThe user's two questions:\n1. \"is there a way to change the c-{prompt} so they dont create a new pi -p session. once the chain starts i have no option to stop them.\"\n2. \"is there also an automatic tool that would just use whatever subagent or prompt is the most fitting?\"\n\nFor question 1:\n- The c-* recipes are run via `/prompt-workflow` which uses pi-subagents. They don't actually create new `pi -p` sessions; they spawn child subagent processes within the current pi session. But if the user invokes them from the shell with `pi -p /prompt-workflow ...`, then yes, it's a new process.\n- The key issue is control/stop. The recipes currently have `--bg` in the doc examples, which makes them run asynchronously. Async runs are detached, so the user can't easily stop them.\n- To make them stoppable, run them in the foreground: remove `--bg` / `--async`. In foreground, you can press Escape or Ctrl+C to cancel/interrupt.\n- Alternatively, if running async, you can use `/subagents-stop` or `subagent({ action: \"stop\", id: ... })` to stop them. Also `/subagents-fleet` to inspect.\n- If they want to ensure they don't run in background by default, they can add `async: false` to the c-* recipe frontmatter (though the current pi-subagents code might not read `async` from chain recipe frontmatter directly - it reads `chain`, `agent`, etc., but not `async`. Let me re-check the `workflowParams` function: it only uses `runtime.bg` for `async`. It doesn't parse `async` from workflow frontmatter. So to run foreground, omit `--bg`.\n\nWait, looking at `workflowParams`: it returns `...(runtime.bg ? { async: true } : {})`. If no `--bg`, `async` is undefined, which means it runs in foreground (default). So yes, just remove `--bg`.\n\nBut the `c-*.md` recipes currently say `Invoke with: /prompt-workflow c-design-build --bg \"...\"` in their body text. That's just documentation/hint. The actual frontmatter has `chain: ...`. There's no `async: true` frontmatter field. So by default, `/prompt-workflow c-design-build \"...\"` would run in foreground.\n\nWait, but the user's doc says \"Each chain runs asynchronously by default\". That's because they always use `--bg` in examples. But the adapter doesn't default to background unless `--bg` is passed.\n\nActually, looking more carefully at the user's Doc/chain-commands.md: \"Each chain runs asynchronously by default. Check progress with: /subagents-fleet\". This is misleading. The adapter only runs async if `--bg` is passed. But the doc shows `--bg` in all examples. Maybe the user added `--bg` to all their invocations.\n\nSo my answer should clarify:\n- Don't use `--bg` / `--async` if you want to keep control and be able to stop.\n- Foreground chains run inline; you can press Esc/Ctrl+C to interrupt.\n- If you want async but stoppable, use `/subagents-fleet` to select and inspect, and `/subagents-stop <id>` to stop.\n- If you're invoking from shell with `pi -p`, switch to running inside an existing pi session instead.\n\nFor question 2:\n- There isn't a built-in automatic router that picks between c-* recipes. But you have options:\n - Just ask pi naturally: \"I need to add a rate limiter\" and let the bundled pi-subagents skill decide whether to run a chain. The parent agent has the `subagent` tool and the bundled skill tells it when to use chains.\n - Create a custom `router` agent/prompt that reads the task and dispatches to the best c-* recipe. This is essentially what the user is asking for.\n - Use the existing c-* recipes as building blocks and add a new c-auto recipe with a prompt that says \"given the task, pick the best chain and run it via /prompt-workflow\".\n\nI should probably offer to actually implement these changes for the user, since we're in their dotfiles repo. The user asked if there is a way; I can show them and offer to change it.\n\nGiven that the user has previous context (they asked about shortcuts earlier and got advice), they may want a concrete change. I can:\n1. Update the c-*.md recipes to default to foreground and document how to add `--bg` explicitly.\n2. Update Doc/chain-commands.md and Doc/prompts.md to reflect this.\n3. Optionally create an `auto` or `c-auto` recipe that routes to the best chain.\n\nLet me think about what would be the best concrete answer. The user asks two questions. I should:\n- Answer directly first.\n- Explain the mechanism (how `/prompt-workflow` works, foreground vs async).\n- Provide the fix (remove `--bg` or add a foreground mode).\n- Address the \"automatic tool\" question.\n- Offer to make the edits.\n\nSince this is a coding agent environment, and the user is working on their dotfiles, I should probably just make the changes or ask if they want them. But the user's question is more of a \"is there a way / is there a tool\" question. I can answer and then offer to apply.\n\nI should also be careful not to make assumptions. Maybe ask a clarifying question? But the user seems to want a direct answer. The guidelines say use ask_user_question when requirements are ambiguous. Here, they seem clear enough: they want control over chains and automatic routing.\n\nActually, the user's first question might have a specific meaning: \"so they don't create a new pi -p session\". They might literally be running `pi -p /prompt-workflow ...` from a shell alias. I should address that possibility.\n\nLet me also check if the c-*.md files have any frontmatter that forces async. They don't - they only have `description`, `argument-hint`, `chain`. No `async`.\n\nSo my plan:\n1. Explain that `/prompt-workflow` does not create `pi -p` sessions per se, but `--bg` makes the chain run detached/async. If you invoke from shell with `pi -p`, that's a separate process.\n2. Show how to run in foreground (remove `--bg`).\n3. Explain how to stop: Esc/Ctrl+C in foreground; `/subagents-stop` / `subagent({ action: \"stop\" })` for async.\n4. For automatic routing, explain there's no built-in command, but you can: (a) ask naturally and let the parent decide, (b) create a `c-auto.md` recipe that routes, or (c) create a `router` agent. Offer to create one.\n5. Offer to update the recipes/docs to foreground-by-default and add an auto-router.\n\nI think I should ask the user whether they want me to make these changes, or I can make them directly. Given the context (they're iterating on their dotfiles), making them directly is reasonable. But it's also their config; maybe they want to decide.\n\nLet me present the answer clearly and offer to apply. Since this is a chat, I'll answer the questions first, then ask if they want me to implement.\n\nActually, I can do both: explain and then offer the implementation. Let me structure the response:\n\n- Short answer: yes, both are possible.\n- Mechanism explanation.\n- Concrete fix for c-* foreground/stoppable.\n- Options for auto-routing.\n- Ask: \"Do you want me to update your c-*.md files to default to foreground and add a c-auto router?\"\n\nBut I should not use ask_user_question because I don't have ambiguity that blocks me. I can answer fully and offer.\n\nWait, the user might want me to make the changes now. Given that this is inside their dotfiles repo and they are configuring pi, it's appropriate to offer the implementation. Let me present the options and then apply if they agree, or just apply the simplest changes directly.\n\nHmm, but the user didn't explicitly ask for implementation. They asked \"is there a way\" and \"is there an automatic tool\". The best response is to explain and offer. I'll provide a concise answer with the key info.\n\nLet me also verify one technical detail: if you run `/prompt-workflow c-design-build \"...\"` without `--bg`, does it really run in foreground? Looking at the code: `run({ chain, task, clarify: false, agentScope: \"both\", ...(runtime.bg ? { async: true } : {}) }, ctx)`. The `run` function is `PromptWorkflowRunner` which takes `SubagentParamsLike`. Looking at `SubagentParamsLike`, it's probably from foreground/subagent-executor.ts. If `async` is omitted, it defaults to false, so foreground. Yes.\n\nAlso, the `p-*.md` individual prompts have `fork: true` and `subagent: true`. In the `workflowChainStep`, it creates a `ChainStep` with agent = delegate by default, but the workflow step's agent is `params.agent ?? \"delegate\"`. Wait, in `workflowParams`: `agent: runtime.agentOverride ?? workflow.agent`. And `parseAgent` returns `delegate` if no `subagent` frontmatter. But the c-*.md files don't have `subagent:` frontmatter. So the chain recipe step uses `delegate` agent. But then `workflowChainStep` creates a ChainStep with `agent: params.agent ?? \"delegate\"`, `task: params.task`. \n\nWait, but the chain step is for a p-*.md workflow, not the c-*.md recipe. In `registerPromptWorkflowCommands`, when `workflow.chain` is present, it maps each chain name to a workflow step: `return workflowChainStep(step, runtime.args, runtime)`. So each step is a p-*.md workflow loaded as a ChainStep with agent = delegate (since p-*.md have `subagent: true` which parseAgent treats as \"delegate\"). The task is the substituted p-*.md body.\n\nHmm, so the chain actually runs each p-*.md as a `delegate` subagent. The p-*.md's own `subagent: true` frontmatter is parsed but the agent name becomes \"delegate\". That's interesting. The chain runs with `clarify: false` and `agentScope: \"both\"`. \n\nAnyway, the key point for the user is control. Foreground = stoppable with Esc/Ctrl+C. Async = stoppable with `/subagents-stop`.\n\nNow, let me think about the auto-router. The most useful concrete implementation would be a new prompt template `c-auto.md` that has frontmatter like:\n```yaml\n---\ndescription: Automatically pick and run the best c-* chain for the given task\nargument-hint: \"[task or feature]\"\nsubagent: true\nfork: true\n---\nGiven the task \"$@\", decide which of these chains is most appropriate:\n- c-design-build: for new features / design → plan → test → commit\n- c-fix-commit: for bugs / summarize → diagnose → debug → test\n- c-refactor-commit: for safe refactors / refactor → test → review → commit\n- c-security-loop: for security-sensitive work / secaudit → review → test\n\nPick exactly one. Then run it via /prompt-workflow <chosen> \"$@\" in the foreground (no --bg) so the user can stop it.\n```\n\nBut there's a problem: a subagent running `/prompt-workflow` would need the subagent tool. The `delegate` agent by default may or may not have the subagent tool. The `delegate` builtin is a general delegate that behaves close to parent. It probably has the subagent tool? Let me check the delegate agent definition.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:38","name":"read","arguments":{"path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/agents/delegate.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":64017,"output":2528,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":66545,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909265062,"responseId":"chatcmpl-840","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"3ab9cd8f","parentId":"e208ce54","timestamp":"2026-07-24T16:08:08.408Z","message":{"role":"toolResult","toolCallId":"functions.read:38","toolName":"read","content":[{"type":"text","text":"---\nname: delegate\ndescription: Lightweight subagent that inherits the parent model with no default reads\nsystemPromptMode: append\ninheritProjectContext: true\ntools: read, grep, find, ls, bash, edit, write, contact_supervisor\ninheritSkills: false\n---\n\nYou are a delegated agent. Execute the assigned task using the provided tools. Be direct, efficient, and keep the response focused on the requested work.\n\nIf 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.\n"}],"isError":false,"timestamp":1784909288408}}
|
||
{"type":"message","id":"d551f39d","parentId":"3ab9cd8f","timestamp":"2026-07-24T16:08:43.529Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The delegate agent has tools `read, grep, find, ls, bash, edit, write, contact_supervisor` but NOT `subagent`. So a delegate subagent cannot invoke `/prompt-workflow` or `subagent`. This means creating a c-auto recipe that dispatches to other chains is tricky if it runs as a subagent without the `subagent` tool.\n\nInstead, the auto-router should be a parent-level prompt template (not a subagent) that the parent pi can use to decide which `/prompt-workflow` command to run. But prompt templates just expand text; they don't execute commands. So the parent would see the text and then decide.\n\nAlternatively, create a custom agent with `tools: subagent` that can dispatch. Then invoke it via `/run router \"task\"` or `subagent({ agent: \"router\", task: \"...\" })`.\n\nActually, the simplest auto-router is to just ask the parent naturally and let it use the `subagent` tool with the appropriate agent. The bundled skill guides this. So if you say \"add a rate limiter to the API\", the parent can decide to run the design-build chain.\n\nBut the user wants something more automatic. They could create a `router.md` agent with `tools: subagent` and a prompt that maps tasks to chains. Then invoke it.\n\nLet me also think about whether pi-subagents itself can route automatically. The bundled skill covers \"when to launch which agent, whether to use single, parallel, chain, or async mode\". So if the parent asks naturally, the model should pick the right tool. But for picking between c-* recipes specifically, there is no built-in mapping.\n\nSo my answer for question 2:\n- Not built-in, but you can create one.\n- Option A: Use natural language and let the parent + bundled skill decide.\n- Option B: Create a `router` custom agent with `tools: subagent` that picks the chain.\n- Option C: Create a parent-level prompt template `auto` that expands to instructions for the parent to choose.\n\nI should probably offer to create one of these.\n\nGiven the user's previous context, they are iterating on their prompt setup. Let me provide a concrete plan and ask if they want me to apply it.\n\nActually, I can just apply a minimal change that addresses their concerns:\n1. Update c-*.md to default to foreground (remove `--bg` from the example text, maybe add a note).\n2. Update Doc/chain-commands.md and Doc/prompts.md to document foreground and how to stop.\n3. Add a `c-auto.md` recipe or a `router` agent for automatic routing.\n\nBut I should not make changes without their approval. I'll explain and ask.\n\nWait, actually the user might appreciate if I just do it. But to be safe, I'll explain and offer. The system says \"Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions\". Here, I can proceed with answering, but if I want to make changes, I need to know which option they prefer. So I could ask a question with 2-3 options for the auto-router.\n\nLet me structure a response:\n1. Direct answer to both questions.\n2. Brief technical explanation.\n3. Concrete actionable changes I can make.\n4. Ask: \"Want me to update the c-* files to foreground-by-default and add an auto-router? If yes, which router style: (A) a parent prompt, (B) a subagent-capable router agent, or (C) just rely on natural language?\"\n\nSince I have to use ask_user_question if I need concrete decisions, I can include that. But the user's question can be answered without it. I think I'll provide the answer and then ask one question about implementation preference.\n\nActually, the user asked two questions. I can answer both fully and then offer to implement. No need to force a question. But if I want to make changes, I need a decision. I can phrase it as: \"I can update your files directly. Should I: (A) just switch c-* to foreground docs, (B) also add an auto-router prompt, (C) also add an auto-router agent with subagent tool?\"\n\nI think using ask_user_question is appropriate here because there are distinct implementation choices.\n\nBut wait, the user didn't ask me to implement; they asked if it's possible. So maybe I should just answer and say \"let me know if you want me to apply it\". But given the harness, being proactive is good.\n\nLet me answer concisely first, then use ask_user_question for the implementation options. Actually, I should not stack multiple ask_user_question calls; group into one invocation.\n\nLet me also double check if there's a way to add `async: false` frontmatter to c-*.md that pi-subagents would respect. Looking at the code, `workflowParams` only checks `runtime.bg` for async. It does not parse `async` frontmatter. So adding `async: false` to the c-*.md frontmatter won't work unless I modify the extension source. So the only way is to not pass `--bg`.\n\nBut actually, maybe I could modify the pi-subagents extension to support an `async` frontmatter field. That would be a code change in `~/.pi/agent/npm/node_modules/pi-subagents/src/slash/prompt-workflows.ts`. But that's an installed npm package; modifying it is not ideal (would be overwritten on update). Better to change the docs and examples.\n\nAlternatively, the user could create an issue/PR to pi-subagents to support `async: false` frontmatter.\n\nSo the practical answer: change the invocations to not use `--bg`.\n\nNow, regarding the \"new pi -p session\": I should clarify that `/prompt-workflow` runs within the current pi session, not a new `pi -p` process. The child subagents are headless but are children of the current session. If the user is literally running `pi -p /prompt-workflow ...` from the shell, that starts a new non-interactive process, and yes that's harder to stop. The fix is to run it inside an existing interactive pi session.\n\nOK, let me also think about whether the user might be experiencing the \"chain starts and I can't stop it\" because the chain runs synchronously in foreground and Ctrl+C kills the whole pi process. If in foreground, Escape in pi's TUI cancels/interrupts the current assistant turn. But if the chain is running, the parent is waiting for the `subagent` tool result. Pi might not respond to Escape until the current subagent step returns. However, `/subagents-fleet` can be opened even while a foreground turn is active with `Ctrl+Alt+F` and you can inspect/interrupt. The README says: \"Ctrl+Alt+F opens the same inspector even while a foreground turn is active and slash input is queued.\"\n\nAlso, `subagent({ action: \"interrupt\", id: ... })` can soft-interrupt a paused child. But for a running child, `stop` is needed.\n\nActually, for foreground chain, the parent is blocked on the `run` promise. To interrupt, you'd need the Pi UI to handle Escape. The docs say \"Escape cancels or aborts\" the current assistant turn. If a tool is running, Escape tries to cancel it. But `subagent` tool might not be cancellable mid-run. So foreground might still not be easily stoppable if the child is running.\n\nFor async, you have `/subagents-stop` and `/subagents-fleet`.\n\nSo the best control is actually async with explicit stop commands. The user can check `/subagents-fleet` and stop specific runs.\n\nBut the user says \"once the chain starts i have no option to stop them\". Maybe they don't know about `/subagents-fleet` and `/subagents-stop`. I should tell them.\n\nAlso, they can add `--timeoutMs 600000` to cap runtime.\n\nLet me also look at the `run` function to see if it supports timeout. `workflowParams` supports `timeoutMs`? No, it doesn't parse timeout from frontmatter or runtime. The runtime parser only parses `--fork`, `--fresh`, `--worktree`, `--bg`, `--subagent`. No `--timeout`. So that's not available via `/prompt-workflow`.\n\nOK, I'll provide:\n- Foreground runs (no `--bg`) can be interrupted with Esc/Ctrl+C in the current session.\n- Background runs (`--bg`) can be inspected and stopped with `/subagents-fleet`, `/subagents-stop <id>`, or `subagent({ action: \"stop\", id: ... })`.\n- If running from shell with `pi -p`, switch to running inside an existing pi session.\n- There's no built-in auto-router, but I can create one.\n\nLet me also consider if there is a way to change c-* to not spawn subagents at all (run in the same session as normal prompts). Yes: if you just use the `p-*.md` prompts directly via `/p-brainstorm`, `/p-plan`, etc., they run as subagents too because they have `subagent: true`. Actually, if you type `/p-brainstorm`, it just pastes the prompt into the current chat, and then the parent runs it. It doesn't automatically spawn a subagent unless the parent decides to. Wait, the p-*.md files have `subagent: true` frontmatter. Does pi-subagents intercept the slash expansion to run them as subagents? Or does `/p-brainstorm` just paste the text?\n\nThe doc says: \"Use it with `:p-<verb> [arg]` or via the `:prompts` TUI picker.\" Not `/p-brainstorm`. Pi prompt templates are invoked with `/name`. But the user's doc says `:p-<verb>` (colon prefix) which might be from another extension. Hmm.\n\nActually, the standard pi prompt template is `/p-brainstorm`. The user's doc says `:p-<verb>`. Maybe they configured a custom command. But the c-* doc says `/c-design-build` just pastes text. This is because pi's native prompt expansion just inserts text. The pi-subagents prompt-workflow adapter adds the `/prompt-workflow` command.\n\nSo `/p-brainstorm` would paste the prompt body into the current chat (not run as subagent). The frontmatter `subagent: true` is only used by `/prompt-workflow`. So if the user wants to run individual prompts inline without subagents, they can just use `/p-brainstorm`.\n\nFor chains, `/chain-prompts` and `/prompt-workflow` are the ways.\n\nOK, my answer will be well-informed. Let me write it now.\n\nGiven the complexity, I think I should:\n1. Answer the two questions.\n2. Offer concrete edits to their c-* recipes and docs.\n3. Ask a single multi-option question about which auto-router style they want.\n\nActually, the user might not need a question. They might just want to know. Let me provide the answer and then say \"I can update your files if you want\". I'll include an ask_user_question only if necessary.\n\nHmm, the instructions say \"Use ask_user_question whenever the user's request is underspecified and you cannot proceed without concrete decisions — you can ask up to 4 questions per invocation.\" The user's request is not underspecified; they asked two yes/no/explanation questions. I can answer fully. For implementation, I can ask a follow-up question.\n\nI think I'll answer fully, then ask one question with 3 options about whether they want me to apply changes and which router style.\n\nLet me draft the response:\n\n---\n\n**Short answer:** Yes to both, but the \"automatic tool\" has to be built, not switched on.\n\n**1. Stop the chain from running away**\n\n`/prompt-workflow` itself doesn't spawn a new `pi -p` process — it runs inside your current Pi session. The `c-*.md` recipes are chain wrappers; each `p-*` step is launched as a subagent child of that session. The reason you can't stop it is that you're passing `--bg`/`--async`, which detaches the chain as a background async run.\n\nTo keep it controllable:\n- **Foreground:** drop `--bg`. In foreground you can hit `Esc`/`Ctrl+C` to cancel the current turn, and the chain stays in the current session.\n- **Background with stop:** keep `--bg` but know the controls: `/subagents-fleet` to inspect, `/subagents-stop <id>` or `subagent({ action: \"stop\", id: \"...\" })` to kill a run.\n\nIf you are literally invoking these from a shell alias with `pi -p /prompt-workflow ...`, then yes, that's a brand-new non-interactive process. Switch the alias to start an interactive Pi session, or better, run the command inside an already-open Pi session.\n\n**2. Automatic routing**\n\nThere is no built-in `/auto` command that reads your task and picks the best `c-*` recipe. Pi-subagents gives the parent the `subagent` tool and a bundled skill that guides delegation, so you can just ask naturally, e.g. \"Design and implement a rate limiter\", and the parent can decide to run the right chain. But it doesn't have a fixed mapping between your four recipes.\n\nYou can add an explicit router yourself:\n- **Option A — parent prompt:** create `p-route.md` (no `subagent: true`) that expands to instructions telling the parent which `/prompt-workflow c-*` to run.\n- **Option B — router subagent:** create `agents/router.md` with `tools: subagent` that picks the chain and invokes it via the `subagent` tool.\n- **Option C — smart chain recipe:** create `c-auto.md` with a chain of one step that is a `router` agent.\n\nI can update your files right now:\n1. Change the c-* docs/examples to default to foreground (no `--bg`), and document the stop commands.\n2. Add an auto-router of your choice.\n\nWhich would you like?\n\nActually, I realize the ask_user_question format requires 2-4 options. I can frame it as:\n\n\"Want me to apply these changes? Pick what to add:\"\n- A) Just update c-* docs to foreground-by-default and document stop commands\n- B) A + add a parent-level `p-route` auto-router prompt\n- C) A + add a subagent-capable `router` agent that can dispatch chains\n\nLet me use ask_user_question for this.\n\nBut wait, I should also consider whether the user might be happy with a code-only answer and doesn't want me to edit. Since I have full access to their files, it's reasonable to offer. But the ask_user_question tool might be overkill. I can just ask in prose. However, the instructions say use ask_user_question when there are concrete decisions. This is a concrete decision about implementation.\n\nI'll use ask_user_question with 3 options.\n\nLet me finalize the response structure:\n1. Direct answer (not in ask_user_question).\n2. Technical details.\n3. ask_user_question with implementation options.\n\nActually, I should keep the ask_user_question concise. The bulk of the answer can come first.\n\nLet me also make sure I don't misrepresent the behavior. The c-*.md files don't \"create a new pi -p session\". The subagent children are spawned by the parent pi process. But the user might be invoking from shell, which does create a new process. I'll cover both.\n\nLet me write the final response.","thinkingSignature":"reasoning"},{"type":"text","text":"Yes to both, with one caveat: the \"automatic tool\" has to be added — it isn't a built-in switch.\n\n### 1. Why the chains feel unstoppable\n\n`/prompt-workflow` doesn't create a brand-new `pi -p` process; it runs inside your current Pi session. The `c-*.md` recipes just describe a sequence of `p-*` steps, and pi-subagents spawns each step as a child subagent of that same session.\n\nThe reason you can't stop them is almost certainly the `--bg`/`--async` flag. That detaches the whole chain as a background async run.\n\nWays to keep control:\n\n| What you do | Behavior | How to stop |\n|---|---|---|\n| `/prompt-workflow c-design-build \"task\"` | Foreground in current session | `Esc` or `Ctrl+C` cancels the current turn |\n| `/prompt-workflow c-design-build --bg \"task\"` | Background / async | `/subagents-fleet` to inspect, `/subagents-stop <id>` or `subagent({ action: \"stop\", id: \"...\" })` to kill |\n| `pi -p /prompt-workflow c-design-build \"task\"` from shell | New non-interactive process | Don't do this; run it inside an already-open Pi session instead |\n\nIf you literally have a shell shortcut that does `pi -p /prompt-workflow ...`, change it to open an interactive session, or remove the shortcut and run the command inside Pi.\n\n### 2. Automatic routing\n\nThere is no built-in `/auto` command that maps a task to the best `c-*` recipe. Pi-subagents gives the parent agent the `subagent` tool and a bundled skill that tells it when to delegate, so you can just describe the problem naturally (e.g., \"add a rate limiter to the API\") and the parent can decide to run the right workflow. But it doesn't have a hardcoded mapping between your four recipes.\n\nYou can add an explicit router yourself:\n\n- **Parent-level prompt** (`p-route.md`, no `subagent: true`): expands to instructions that tell the parent which `/prompt-workflow c-*` to run.\n- **Subagent router** (`agents/router.md` with `tools: subagent`): a child agent that picks the recipe and invokes it via the `subagent` tool.\n- **Smart chain recipe** (`c-auto.md`): a single-step chain whose only step is the router agent.\n\nI can update your dotfiles right now to (a) default the existing chains to foreground and document the stop commands, and (b) add an auto-router if you want one."},{"type":"toolCall","id":"functions.ask_user_question:39","name":"ask_user_question","arguments":{"questions":[{"multiSelect":false,"options":[{"description":"Update c-*.md and Doc/chain-commands.md to show foreground invocation as the default, keep --bg as optional, and document /subagents-fleet + /subagents-stop. No router.","label":"Foreground docs only"},{"description":"Same as above, plus add a p-route.md prompt the parent can expand to pick the right c-* recipe.","label":"Foreground docs + parent router prompt"},{"description":"Same as above, plus add an agents/router.md subagent with tools: subagent that can dispatch to the chosen c-* chain itself.","label":"Foreground docs + subagent router"}],"text":"Should I update your prompt files to fix the control issue and add an auto-router?"}]}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":66725,"output":3985,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":70710,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909288409,"responseId":"chatcmpl-106","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"236ddee7","parentId":"d551f39d","timestamp":"2026-07-24T16:08:43.532Z","message":{"role":"toolResult","toolCallId":"functions.ask_user_question:39","toolName":"ask_user_question","content":[{"type":"text","text":"Validation failed for tool \"ask_user_question\":\n - questions.0.question: must have required properties question, header\n\nReceived arguments:\n{\n \"questions\": [\n {\n \"multiSelect\": false,\n \"options\": [\n {\n \"description\": \"Update c-*.md and Doc/chain-commands.md to show foreground invocation as the default, keep --bg as optional, and document /subagents-fleet + /subagents-stop. No router.\",\n \"label\": \"Foreground docs only\"\n },\n {\n \"description\": \"Same as above, plus add a p-route.md prompt the parent can expand to pick the right c-* recipe.\",\n \"label\": \"Foreground docs + parent router prompt\"\n },\n {\n \"description\": \"Same as above, plus add an agents/router.md subagent with tools: subagent that can dispatch to the chosen c-* chain itself.\",\n \"label\": \"Foreground docs + subagent router\"\n }\n ],\n \"text\": \"Should I update your prompt files to fix the control issue and add an auto-router?\"\n }\n ]\n}"}],"details":{},"isError":true,"timestamp":1784909323532}}
|
||
{"type":"message","id":"84ffb303","parentId":"236ddee7","timestamp":"2026-07-24T16:08:47.659Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The ask_user_question failed because I used \"text\" instead of \"question\" and didn't include \"header\". The schema requires `question` and `header` properties? Let me check the tool description. It says:\n\n\"Questions to ask the user (1-4 questions)\" with properties for each question. The error says \"must have required properties question, header\". So each question object needs `question` and `header`. Wait, the examples in the description don't show `header`. Let me re-read.\n\nActually the tool description shows:\n```json\n{\n \"questions\": [...]\n}\n```\nBut doesn't detail the schema. The error says required properties are `question` and `header`. Let me try with `question` (the actual question text) and `header` (a short title). I'll also keep `options`.\n\nActually, looking at typical ask_user_question schemas, `header` might be optional but here it's required. Let me fix.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.ask_user_question:40","name":"ask_user_question","arguments":{"questions":[{"header":"Apply changes to your prompt setup?","multiSelect":false,"options":[{"description":"Update c-*.md and Doc/chain-commands.md to show foreground invocation as the default, keep --bg as optional, and document /subagents-fleet + /subagents-stop. No router.","label":"Foreground docs only"},{"description":"Same as above, plus add a p-route.md prompt the parent can expand to pick the right c-* recipe.","label":"Foreground docs + parent router prompt"},{"description":"Same as above, plus add an agents/router.md subagent with tools: subagent that can dispatch to the chosen c-* chain itself.","label":"Foreground docs + subagent router"}],"question":"Should I update your prompt files to fix the control issue and add an auto-router?"}]}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":70945,"output":375,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":71320,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909323534,"responseId":"chatcmpl-911","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"4ec38f1e","parentId":"84ffb303","timestamp":"2026-07-24T16:08:47.660Z","message":{"role":"toolResult","toolCallId":"functions.ask_user_question:40","toolName":"ask_user_question","content":[{"type":"text","text":"Validation failed for tool \"ask_user_question\":\n - questions.0.header: must not have more than 16 characters\n\nReceived arguments:\n{\n \"questions\": [\n {\n \"header\": \"Apply changes to your prompt setup?\",\n \"multiSelect\": false,\n \"options\": [\n {\n \"description\": \"Update c-*.md and Doc/chain-commands.md to show foreground invocation as the default, keep --bg as optional, and document /subagents-fleet + /subagents-stop. No router.\",\n \"label\": \"Foreground docs only\"\n },\n {\n \"description\": \"Same as above, plus add a p-route.md prompt the parent can expand to pick the right c-* recipe.\",\n \"label\": \"Foreground docs + parent router prompt\"\n },\n {\n \"description\": \"Same as above, plus add an agents/router.md subagent with tools: subagent that can dispatch to the chosen c-* chain itself.\",\n \"label\": \"Foreground docs + subagent router\"\n }\n ],\n \"question\": \"Should I update your prompt files to fix the control issue and add an auto-router?\"\n }\n ]\n}"}],"details":{},"isError":true,"timestamp":1784909327660}}
|
||
{"type":"message","id":"0c5564b2","parentId":"4ec38f1e","timestamp":"2026-07-24T16:08:50.199Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The header must be ≤16 characters. Let me make it short: \"Apply changes?\"","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.ask_user_question:41","name":"ask_user_question","arguments":{"questions":[{"header":"Apply changes?","multiSelect":false,"options":[{"description":"Update c-*.md and Doc/chain-commands.md to show foreground invocation as the default, keep --bg as optional, and document /subagents-fleet + /subagents-stop. No router.","label":"Foreground docs only"},{"description":"Same as above, plus add a p-route.md prompt the parent can expand to pick the right c-* recipe.","label":"Foreground docs + parent router prompt"},{"description":"Same as above, plus add an agents/router.md subagent with tools: subagent that can dispatch to the chosen c-* chain itself.","label":"Foreground docs + subagent router"}],"question":"Should I update your prompt files to fix the control issue and add an auto-router?"}]}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":71581,"output":196,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":71777,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909327662,"responseId":"chatcmpl-658","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"2ec59c58","parentId":"0c5564b2","timestamp":"2026-07-24T16:09:35.547Z","message":{"role":"toolResult","toolCallId":"functions.ask_user_question:41","toolName":"ask_user_question","content":[{"type":"text","text":"User has answered your questions: \"Should I update your prompt files to fix the control issue and add an auto-router?\"=\"Foreground docs + subagent router\". You can now continue with the user's answers in mind."}],"details":{"answers":[{"questionIndex":0,"question":"Should I update your prompt files to fix the control issue and add an auto-router?","kind":"option","answer":"Foreground docs + subagent router"}],"cancelled":false},"isError":false,"timestamp":1784909375547}}
|
||
{"type":"message","id":"be8d6aad","parentId":"2ec59c58","timestamp":"2026-07-24T16:10:10.357Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The user chose \"Foreground docs + subagent router\". So I need to:\n\n1. Update c-*.md files to show foreground invocation as default, keep --bg optional, and document stop commands.\n2. Update Doc/chain-commands.md to reflect foreground default, optional --bg, and stop commands.\n3. Add an agents/router.md subagent with `tools: subagent` that can dispatch to the chosen c-* chain.\n\nLet me plan the exact changes.\n\nFirst, the c-*.md files. They currently have:\n```markdown\n---\ndescription: ...\nargument-hint: ...\nchain: ...\n---\nRun the ... chain for: $@\n\nInvoke with:\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n```\n\nI should change the \"Invoke with\" section to show foreground as default and background as optional. Also add a \"Stop the chain\" note. But wait, the body of the prompt template is used as the task for the subagent. So changing the body text affects what the subagent does. The \"Invoke with\" line is just documentation within the prompt. It doesn't affect execution, but it's misleading. I should update it.\n\nActually, the body text is passed as the task to the first step in the chain. In the current setup, the body says \"Run the design → plan → test → commit chain for: $@ \\n\\nInvoke with:\\n/prompt-workflow c-design-build --bg ...\". That whole string becomes the task for the chain. The \"Invoke with\" line is noise in the task. But since it's there, it's part of the prompt. Better to keep it clean.\n\nFor each c-*.md:\n```markdown\n---\ndescription: ...\nargument-hint: ...\nchain: ...\n---\nRun the ... chain for: $@\n\nInvoke in the current Pi session:\n/prompt-workflow c-design-build \"$@\"\n\nRun detached in the background:\n/prompt-workflow c-design-build --bg \"$@\"\n\nStop a background run:\n/subagents-fleet # select and inspect\n/subagents-stop <run-id>\n```\n\nBut I need to be careful: `$@` in the body is substituted with arguments when the prompt template is expanded. But in the \"Invoke with\" examples, `$@` is just literal text? No, when the template is expanded by `/prompt-workflow`, the entire body is substituted. So if the user passes args, `$@` is replaced. The \"Invoke with\" line would also have `$@` replaced. That's weird but OK.\n\nActually, maybe I should not use `$@` in the documentation line. I should use a placeholder like `\"<task>\"`.\n\nWait, but the body is a template. The first line uses `$@` to insert the user's arguments. The \"Invoke with\" examples should show literal commands, not be substituted. If I write `/prompt-workflow c-design-build \"$@\"`, the `$@` will be replaced by the user's arguments, making the example nonsensical. So I should avoid `$@` in examples, or escape it, or write the examples without it.\n\nActually, prompt template substitution uses `$@`, `$1`, etc. It doesn't substitute inside code blocks or anything special. So any `$@` in the body will be replaced. To avoid substitution, I could use a different placeholder like `<task>` or `TASK`.\n\nLet me change the examples to:\n```markdown\nInvoke in the current Pi session:\n/prompt-workflow c-design-build \"<task>\"\n\nRun detached in the background:\n/prompt-workflow c-design-build --bg \"<task>\"\n\nStop a background run: /subagents-fleet, then /subagents-stop <run-id>\n```\n\nBut the user's current convention uses `$@` in the body task and shows examples with actual quoted text. I can keep the first line with `$@` and use literal examples below.\n\nWait, actually, the c-*.md files are not expanded by the user typing `/c-design-build`; they are loaded by `/prompt-workflow c-design-build \"task\"`. The `/prompt-workflow` command reads the file, substitutes args into the body, and then uses that body as the chain task. So the entire body becomes the task. The \"Invoke with\" examples are not useful to the subagent; they're documentation. But they end up in the task. It would be cleaner to remove them from the body or move them to frontmatter comments? No, frontmatter doesn't support comments the way we want.\n\nActually, the \"Invoke with\" line is only useful to the human. But since the c-*.md is a prompt template, it's part of the prompt. This is a design tradeoff the user already made. I should not remove the examples entirely (they might be relying on them), but I can update them.\n\nAlternatively, I could put the documentation in `Doc/chain-commands.md` and keep the c-*.md body minimal. But the user has examples in the body. I'll update them.\n\nNow, the agent router. I need to create `agents/router.md` in the user's dotfiles. The user agent scope for project is `.pi/agents/**/*.md` in standard Pi. But since this is their global dotfiles, it should be in `~/.pi/agent/agents/`. Wait, the current repo is `/home/liph/dotfiles/pi/.pi/agent/prompts`. The dotfiles repo maps to `~/.pi/agent/`. So to add an agent, I should create it in the dotfiles at `/home/liph/dotfiles/pi/.pi/agent/agents/router.md`. But the user might also want it project-specific. Since these are global prompts, a global agent in `~/.pi/agent/agents/` makes sense.\n\nI need to create the directory if it doesn't exist. Let me check.\n\nAlso, the agent needs `tools: subagent` to dispatch. And a prompt that maps tasks to c-* chains. It should output a `subagent` tool call. But a subagent with `tools: subagent` can call the `subagent` tool. The `subagent` tool can do single, chain, parallel runs. It can also run a chain. But can it run `/prompt-workflow`? The `subagent` tool runs agents. It doesn't directly run prompt workflows. However, the router can call `subagent({ chain: [...] })` with steps that correspond to the p-* prompts, or it can call `subagent({ agent: \"delegate\", task: \"/prompt-workflow c-design-build ...\" })` but the delegate agent doesn't have the subagent tool by default.\n\nHmm, this is tricky. If the router is a subagent with `tools: subagent`, it can invoke other subagents. But it can't invoke `/prompt-workflow` because that's a slash command, not a tool. The `subagent` tool API uses JSON params, not slash commands.\n\nSo the router agent would need to construct a chain of steps using the `subagent` tool. For example, for c-design-build, it would call:\n```json\nsubagent({ chain: [\n { agent: \"delegate\", task: \"Brainstorm approaches for: <task>\" },\n { agent: \"delegate\", task: \"Create a structured implementation plan for: <task>\" },\n { agent: \"delegate\", task: \"Write tests for: <task>\" },\n { agent: \"delegate\", task: \"Generate a commit message for: <task>\" }\n], task: \"<task>\", clarify: false })\n```\n\nBut that duplicates the content of p-*.md prompts. Alternatively, the router could use the `subagent` tool to run a `delegate` agent whose task is to execute `/prompt-workflow c-design-build \"task\"` in the current session. But as mentioned, delegate doesn't have `subagent` tool.\n\nWait, the `subagent` tool is available to the parent. If the router subagent has `tools: subagent`, it can invoke subagents. The `subagent` tool's `chain` parameter can run a sequence of agents. But it cannot directly reference prompt templates (`p-*.md`). It references agent files (`*.md` in agents dirs). The p-*.md are prompt templates, not agents. They have `subagent: true` frontmatter which makes them usable as agents via `/prompt-workflow`, but they are in the prompts dir, not agents dir. The `subagent` tool discovers agents in `~/.pi/agent/agents/**/*.md` and project `.pi/agents/**/*.md`. It does not discover prompts as agents.\n\nSo if the router wants to use the existing p-*.md content, it either:\n1. Reads the p-*.md file content and constructs the task inline.\n2. We move/copy the p-*.md files to the agents dir as agents.\n\nOption 1 is feasible. The router can read the p-*.md files and use their bodies. But it's a subagent, so it has `read` tool. It can read the files.\n\nBut the user already has a working `/prompt-workflow` setup that runs p-*.md as chain steps. The router could simply output a recommendation to the parent: \"Use /prompt-workflow c-design-build ...\". But then the parent has to manually run it. That's not automatic.\n\nAlternatively, the router can be a parent-level prompt (`p-route.md`) that expands to instructions for the parent to run the right `/prompt-workflow` command. The parent sees the text and then the model executes the slash command or `subagent` tool. This is more practical because the parent has access to slash commands.\n\nBut the user chose \"subagent router\". So I need to make a subagent that can dispatch. How can a subagent dispatch to `/prompt-workflow`? It can't use slash commands directly. But it can use the `subagent` tool if it has it.\n\nWait, maybe the subagent can use `bash` to run `pi /prompt-workflow ...`? That's a new process, which is what the user wants to avoid. Also it creates a new session.\n\nAlternatively, the router subagent could be given a custom tool or extension that dispatches. That's too complex.\n\nActually, the cleanest way to have a subagent router is to have it emit a structured decision (which chain to run), and then the parent reads that decision and runs the chain. That's not fully automatic, but it's close: parent asks router -> router picks chain -> parent executes.\n\nBut the user wants \"an automatic tool that would just use whatever subagent or prompt is the most fitting\". Maybe they mean: give a task to a tool/agent, and it automatically picks and runs the right thing. That's exactly what a parent-level orchestration would do, not a subagent.\n\nGiven the constraints, I think the best implementation is:\n1. Update docs to foreground default.\n2. Add an `agents/router.md` agent with `tools: subagent` that, when invoked via `/run router \"task\"` or `subagent({ agent: \"router\", task: \"...\" })`, picks the appropriate c-* recipe and runs it as a chain using the `subagent` tool. To do this, it replicates the p-* content inline or reads the p-*.md files.\n\nBut there's a simpler approach: the router agent can run the chain by calling `subagent` with a chain of delegate steps, each step's task being the content of the corresponding p-*.md file (substituted with the original task). To avoid duplicating content, the router can read the p-*.md files.\n\nActually, maybe the simplest is to create a new `router` agent that has `tools: read, subagent` and a prompt that says:\n\n\"You are a workflow router. Given the user's task, decide which of these chains is most appropriate:\n- c-design-build: p-brainstorm -> p-plan -> p-test -> p-commit\n- c-fix-commit: p-summarize -> p-diagnose -> p-debug -> p-test\n- c-refactor-commit: p-refactor -> p-test -> p-review -> p-commit\n- c-security-loop: p-secaudit -> p-review -> p-test\n\nRead the corresponding p-*.md files from ~/.pi/agent/prompts/ and execute them as a chain using the `subagent` tool. Run in the foreground (async: false) so the user can stop it with Esc/Ctrl+C.\"\n\nBut the `subagent` tool doesn't directly take prompt template content; it takes agent names and tasks. The `subagent` tool's chain can have `agent: \"delegate\"` with a task. So the router reads the p-*.md body and passes it as the task to a delegate subagent.\n\nThis would work, but it's a bit involved. Also, the `subagent` tool can use `skill` to give the delegate access to the pi-subagents skill? No, the pi-subagents skill is for the parent only. Child subagents don't get it.\n\nAnother option: create proper agent files for each p-* prompt in `~/.pi/agent/agents/` (or as subagent-only agents), then the router can reference them by name. But that duplicates the p-* prompts.\n\nHmm, maybe the user chose \"subagent router\" without understanding the complexity. But I should implement what they asked as best as possible.\n\nActually, re-reading the prompt-workflow code: the `subagent` tool in the parent can run a chain. The c-*.md recipes are prompt templates, but when loaded by `/prompt-workflow`, they are converted to chain steps where each step's task is the substituted body of the p-*.md file. So a router subagent could replicate this by reading the c-*.md and p-*.md files and constructing the same chain.\n\nBut a simpler and more robust approach: the router subagent doesn't need to reimplement the chain. Instead, the router can be a parent-level helper that outputs the correct `/prompt-workflow` command, and the parent executes it. But that's not a subagent.\n\nWait, I just realized: the user chose \"Foreground docs + subagent router\" but maybe they mean a subagent that automatically picks the best subagent/prompt. The \"subagent router\" could just be an agent file that the parent invokes, and it returns which chain to run. Then the parent runs it. That's a valid design.\n\nLet me design the router agent as an advisory router: it reads the task, considers the four recipes, and outputs the recommended chain with justification. Then the parent (or the user) can invoke it. This is similar to an `oracle` agent but for workflow selection. It's not fully automatic, but it's useful.\n\nBut the user asked \"automatic tool that would just use whatever subagent or prompt is the most fitting\". If the router just recommends, it's not automatic. It needs to actually dispatch.\n\nOK, let me think about whether a subagent can dispatch to a chain using the existing pi-subagents extension's in-process event bus RPC. The README mentions:\n\n\"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>`.\"\n\nBut that's for other extensions, not for subagents. A subagent in a child process doesn't have access to the parent's event bus.\n\nAnother angle: maybe the router subagent can use `contact_supervisor` to ask the parent to run the chosen chain. But that's not automatic; it requires the parent to act.\n\nGiven all this, the most honest implementation is:\n- Create `agents/router.md` that picks the best c-* recipe and then invokes it by emitting a `subagent` tool call with a chain of delegate steps, where each step's task is derived from the corresponding p-*.md content. This requires the router to read the p-*.md files.\n\nBut that's complex and may not work perfectly. Alternatively, I can create a simpler router agent that just recommends, and then update the c-* docs. But the user explicitly chose subagent router.\n\nWait, maybe there's an easier way: create `agents/p-brainstorm.md`, `agents/p-plan.md`, etc., that wrap the p-*.md prompts as actual agents. Then the router can call `subagent({ chain: [{ agent: \"p-brainstorm\", task: \"...\" }, ...] })`. But that means duplicating or symlinking the prompts.\n\nActually, I could create agents that are thin wrappers:\n```yaml\n---\nname: p-brainstorm\ntools: subagent, read\n---\nRead ~/.pi/agent/prompts/p-brainstorm.md and run its body as a delegate subagent for: {task}\n```\n\nNo, that doesn't make sense.\n\nLet me reconsider the user's request. They might not need a full subagent router. They might just want a way to automatically pick the right workflow. The simplest robust solution is a parent-level prompt `p-route.md` that tells the parent which `/prompt-workflow` to run. The parent then runs it. This is \"automatic\" in the sense that the user just types `/route \"add a rate limiter\"` and the parent does the rest.\n\nBut they chose \"subagent router\". Maybe they think a subagent router is more powerful. It is, but it can't easily dispatch slash commands.\n\nI should probably implement what they asked but make it pragmatic: an agent `router` that recommends AND attempts to dispatch via `subagent` tool by replicating the chain. To replicate the chain, it reads the p-*.md files.\n\nActually, I just realized: the `subagent` tool's chain can include `agent` names. If I create actual agent files in `~/.pi/agent/agents/` for each p-* prompt, then the router can reference them. But the p-* prompts are in the prompts dir. pi-subagents discovers agents in `~/.pi/agent/agents/**/*.md`, not prompts. But maybe if I set `PI_SUBAGENT_EXTRA_AGENT_DIRS` or similar? Let me check the README for agent discovery customization.\n\nActually, I saw in the README earlier: \"Agents and chains\" section mentions agent locations. It doesn't mention extra dirs. But I recall `PI_SUBAGENT_EXTRA_AGENT_DIRS` from somewhere. Let me search.\n\nActually, looking at the user's settings.json, there's no extra agent dir. But pi-subagents package might support it. Let me grep.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.ffgrep:42","name":"ffgrep","arguments":{"pattern":"EXTRA_AGENT_DIRS|extraAgent|extra.*agent|prompt.*agent","path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/src","limit":40}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":71839,"output":3910,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":75749,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909375549,"responseId":"chatcmpl-265","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"2a1cd694","parentId":"be8d6aad","timestamp":"2026-07-24T16:10:10.361Z","message":{"role":"toolResult","toolCallId":"functions.ffgrep:42","toolName":"ffgrep","content":[{"type":"text","text":"src/api/delegation.ts\n 5: export const SUBAGENT_DELEGATION_REQUEST_EVENT = \"prompt-template:subagent:request\";\n 6: export const SUBAGENT_DELEGATION_STARTED_EVENT = \"prompt-template:subagent:started\";\n 7: export const SUBAGENT_DELEGATION_UPDATE_EVENT = \"prompt-template:subagent:update\";\n 8: export const SUBAGENT_DELEGATION_RESPONSE_EVENT = \"prompt-template:subagent:response\";\n 9: export const SUBAGENT_DELEGATION_CANCEL_EVENT = \"prompt-template:subagent:cancel\";\n\nsrc/runs/background/subagent-runner.ts\n 1138: promptFileStem: step.agent,\n\nsrc/runs/foreground/execution.ts\n 226: promptFileStem: agent.name,\n\nsrc/slash/prompt-workflows.ts\n 270: description: \"Run a prompt template through native pi-subagents: /prompt-workflow <name> [args]\",\n 304: description: \"Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args\",\n\nsrc/slash/slash-commands.ts\n 694: const initialText = extractSlashMessageText(initialDetails.result.content) || \"Running subagent...\";\n\nsrc/slash/subagents-admin.ts\n 8: EXTRA_AGENT_DIRS_ENV,\n 129: const configured = process.env[EXTRA_AGENT_DIRS_ENV];\n 144: ? `Cannot update '${agent.name}' because its definition in PI_SUBAGENT_EXTRA_AGENT_DIRS is read-only.`\n 187: lines.push(`System prompt mode: ${agent.systemPromptMode}`);\n 319: : `Cleared system prompt settings override for '${agent.name}' in ${filePath}.`;\n 355: return `System prompt for '${agent.name}' left unchanged.`;\n\nsrc/agents/agent-management.ts\n 566: lines.push(`System prompt mode: ${agent.systemPromptMode}`);\n\nsrc/agents/agents.ts\n 333: function extractSubagentPathsFromPackageRoot(packageRoot: string): PackageSubagentPaths {\n 453: const paths = extractSubagentPathsFromPackageRoot(resolvedRoot);\n 1421: export const EXTRA_AGENT_DIRS_ENV = \"PI_SUBAGENT_EXTRA_AGENT_DIRS\";\n 1424: // launcher via PI_SUBAGENT_EXTRA_AGENT_DIRS (PATH-style, split on os/path delimiter).\n 1429: const raw = process.env[EXTRA_AGENT_DIRS_ENV];"}],"details":{"totalMatched":22,"totalFiles":380},"isError":false,"timestamp":1784909410361}}
|
||
{"type":"message","id":"07243b5e","parentId":"2a1cd694","timestamp":"2026-07-24T16:10:30.055Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"There is `PI_SUBAGENT_EXTRA_AGENT_DIRS` env var. The `subagents-admin.ts` shows it's used. So I could set this env var to include the prompts dir, making the p-*.md files discoverable as agents. But that might have side effects and is not standard.\n\nAlternatively, I can create a router agent that simply reads the appropriate c-*.md and p-*.md files and then constructs a chain using `subagent({ chain: [...] })`. This is doable.\n\nLet me design `agents/router.md`:\n\n```yaml\n---\nname: router\ndescription: Pick the best c-* workflow for a task and run it\ntools: read, subagent\nsystemPromptMode: append\ninheritProjectContext: true\ninheritSkills: false\n---\nYou are a workflow router. Given the user's task, choose exactly one of these chains:\n\n- c-design-build: p-brainstorm → p-plan → p-test → p-commit\n Use for: new features, design problems, \"how should I build X\", vague requirements.\n\n- c-fix-commit: p-summarize → p-diagnose → p-debug → p-test\n Use for: bugs, failures, \"something is broken\", errors, regressions.\n\n- c-refactor-commit: p-refactor → p-test → p-review → p-commit\n Use for: restructuring existing code, safe refactors, code cleanup.\n\n- c-security-loop: p-secaudit → p-review → p-test\n Use for: auth, input handling, secrets, network, deserialization, trust boundaries.\n\nSteps:\n1. Decide which chain is the best fit for the task: {task}\n2. Read the corresponding c-*.md file to get the chain declaration.\n3. Read each p-*.md file in the chain to get the prompt body.\n4. Run the chain using the `subagent` tool with `async: false` (foreground) so the user can stop it with Esc/Ctrl+C.\n Each step should use `agent: \"delegate\"` and the substituted prompt body as the task.\n5. Summarize what you ran and why.\n\nDo not ask the user before running the chain; just pick and execute.\n```\n\nBut there are issues:\n- The `subagent` tool in a child process might not support the same chain syntax as the parent? Actually it should; it's the same tool.\n- The `delegate` agent might not be available? It should be.\n- The router needs to know the path to the prompts. It can use `~/.pi/agent/prompts/` or resolve from cwd. Better to use `~/.pi/agent/prompts/`.\n\nActually, since the router is a subagent, it doesn't have access to the parent's `subagent` tool unless `tools: subagent` is declared. And child-safety boundaries: \"Spawned child sessions do not receive the bundled pi-subagents skill... By default, children do not register the subagent tool and receive boundary instructions that they are not the parent orchestrator and must not propose or run subagents. The explicit exception is an agent whose resolved builtin tools includes `subagent`.\" So with `tools: subagent`, the router gets a child-safe `subagent` tool. Good.\n\nBut the router also needs `read` to read the p-*.md files. The `subagent` tool can pass tasks to delegate. The delegate agent can do the actual work.\n\nWait, the router's job is just to pick and run the chain. It can do that with `read` + `subagent`. But the actual step content is long. Maybe the router should just pick the chain and then run it by invoking the `subagent` tool with `chain` containing the p-* steps as delegate agents with tasks derived from the p-* bodies.\n\nBut this is complex. Let me see if I can make it simpler by having the router output the chosen chain name, and then the parent runs it. But that's not automatic.\n\nAlternatively, I can create a parent-level auto-router prompt `p-route.md` instead of a subagent. This might be more practical. But the user chose subagent router.\n\nHmm. Maybe I should implement a hybrid:\n1. `agents/router.md` — a subagent that picks the best c-* recipe, reads the recipe and its p-* steps, and runs them as a chain via `subagent`.\n2. Also update docs.\n\nBut to make the router's chain work, I need to make sure the p-* prompts are accessible as content. The router can read them with `read`. Then it constructs the chain. The chain uses `agent: \"delegate\"` for each step. The task is the body of the p-* prompt with the user's task substituted.\n\nActually, wait. If I use the `subagent` tool with `chain`, each step can have `agent: \"delegate\"` and a `task`. The task can be the p-* body. The p-* body uses `$@` for the user's argument. The router can substitute `$@` with the original task.\n\nThis is doable but requires the router to parse the p-*.md file (which has frontmatter). The router can read the file, skip the frontmatter, and use the body.\n\nBut the router is an LLM; it can do this. The prompt tells it to do so.\n\nOK, I'll create the router agent with clear instructions. It might not be perfect, but it's a reasonable implementation.\n\nActually, there might be a much simpler approach: the router can use `bash` to run `pi -p /prompt-workflow ...` but that creates a new process. The user wants to avoid that. So no.\n\nAnother idea: the router can use `contact_supervisor` to ask the parent to run the chosen chain. But that's not automatic.\n\nOK, I'll go with the chain-replicating router.\n\nBut before I implement, let me think if there's an even better approach that satisfies \"automatic tool that picks the most fitting prompt/subagent\". Maybe the answer is to use pi-subagents' own delegation naturally. The parent agent can just be told \"for any task, pick the right c-* chain\". I can add a system prompt or a skill that tells the parent this mapping. That's essentially a parent-level router, not a subagent.\n\nBut the user wants a tool/agent. So I'll create the router agent.\n\nActually, maybe the simplest \"automatic\" solution is to add a `c-auto.md` recipe that is itself a chain with a single `router` step. The router step picks and runs the appropriate chain. That way the user just types `/prompt-workflow c-auto \"add a rate limiter\"` and it runs the best chain.\n\nBut the router step needs to dispatch. With `tools: subagent`, it can dispatch a chain.\n\nOK, I'll create:\n1. `agents/router.md` — the routing agent.\n2. `c-auto.md` — a chain recipe that invokes the router.\n3. Update existing c-*.md to foreground examples.\n4. Update Doc/chain-commands.md.\n\nWait, but the user asked for \"foreground docs + subagent router\". They didn't ask for c-auto. But adding c-auto makes the router usable via the existing `/prompt-workflow` command. Maybe I should include it. But to keep it minimal, I'll just add `agents/router.md` and show how to invoke it via `/run router \"task\"` or `subagent({ agent: \"router\", task: \"...\" })`.\n\nHmm, but `router` is a generic name. Maybe use `workflow-router` or `chain-router`. Let me use `workflow-router`.\n\nAlso, I should consider the `tools` for the router. It needs `read` and `subagent`. Does it need `bash`? Probably not. But `read` might not be allowed unless listed. With `tools: read, subagent`, it gets those. But `subagent` tool might require `read` anyway to read the prompt files. Yes.\n\nActually, the `subagent` tool doesn't need `read` to function; it just spawns subagents. But the router needs `read` to read the p-*.md files. So `tools: read, subagent`.\n\nBut wait, the `subagent` tool in a child might not have access to the same agents as the parent. It can reference agents by name. The `delegate` agent is builtin. The p-* prompts are not agents. So the router can't use `agent: \"p-brainstorm\"`. It must use `agent: \"delegate\"` with the prompt body as task.\n\nOK, the router instructions should be clear about that.\n\nAlso, the router needs to know the path to the prompts. Since it's a subagent, `~/.pi/agent/prompts/` might be the right path. But if PI_CODING_AGENT_DIR is overridden, it might differ. I can hardcode it for the user's setup or tell the router to resolve from the agent dir. Actually, the router can use `bash` to get `echo $PI_CODING_AGENT_DIR` or just assume `~/.pi/agent/prompts/`. Since this is the user's personal setup, hardcoding `~/.pi/agent/prompts/` is fine.\n\nBut wait, the router is inside a subagent. It can use the `read` tool with absolute path `/home/liph/.pi/agent/prompts/p-brainstorm.md`. But that's the runtime path, not the dotfiles repo path. The dotfiles repo maps to ~/.pi/agent/. In the current environment, /home/liph/.pi/agent/prompts/ is a symlink or the actual directory? Let me check.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:43","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/prompts/ && readlink -f /home/liph/.pi/agent/prompts/"}},{"type":"toolCall","id":"functions.bash:44","name":"bash","arguments":{"command":"ls -la /home/liph/.pi/agent/agents/ 2>/dev/null || echo 'no agents dir'"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":76262,"output":2093,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":78355,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909410363,"responseId":"chatcmpl-391","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"94b56c55","parentId":"07243b5e","timestamp":"2026-07-24T16:10:30.086Z","message":{"role":"toolResult","toolCallId":"functions.bash:43","toolName":"bash","content":[{"type":"text","text":"total 84\ndrwxr-xr-x 5 liph liph 4096 Jul 24 18:02 .\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:08 ..\n-rw-r--r-- 1 liph liph 313 Jul 24 18:02 c-design-build.md\n-rw-r--r-- 1 liph liph 360 Jul 24 17:55 c-fix-commit.md\n-rw-r--r-- 1 liph liph 328 Jul 24 17:55 c-refactor-commit.md\n-rw-r--r-- 1 liph liph 287 Jul 24 17:55 c-security-loop.md\ndrwxr-xr-x 2 liph liph 4096 Jul 24 18:03 Doc\n-rw-r--r-- 1 liph liph 1277 Jul 24 18:02 p-brainstorm.md\n-rw-r--r-- 1 liph liph 1121 Jul 24 18:02 p-commit.md\n-rw-r--r-- 1 liph liph 834 Jul 24 17:55 p-debug.md\n-rw-r--r-- 1 liph liph 1147 Jul 24 17:55 p-diagnose.md\n-rw-r--r-- 1 liph liph 1176 Jul 24 17:55 p-doc.md\n-rw-r--r-- 1 liph liph 677 Jul 24 17:55 p-explain.md\ndrwxr-xr-x 4 liph liph 4096 Jul 24 17:42 .pi-subagents\n-rw-r--r-- 1 liph liph 793 Jul 24 17:55 p-plan.md\n-rw-r--r-- 1 liph liph 1135 Jul 24 17:55 p-refactor.md\n-rw-r--r-- 1 liph liph 874 Jul 24 17:55 p-review.md\n-rw-r--r-- 1 liph liph 1395 Jul 24 17:55 p-secaudit.md\n-rw-r--r-- 1 liph liph 1179 Jul 24 17:55 p-summarize.md\n-rw-r--r-- 1 liph liph 1098 Jul 24 17:55 p-test.md\ndrwxr-xr-x 4 liph liph 4096 Jul 24 18:08 test\n/home/liph/dotfiles/pi/.pi/agent/prompts\n"}],"isError":false,"timestamp":1784909430086}}
|
||
{"type":"message","id":"f6839092","parentId":"94b56c55","timestamp":"2026-07-24T16:10:30.087Z","message":{"role":"toolResult","toolCallId":"functions.bash:44","toolName":"bash","content":[{"type":"text","text":"total 8\ndrwxr-xr-x 2 liph liph 4096 Jul 24 17:23 .\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:08 ..\n"}],"isError":false,"timestamp":1784909430087}}
|
||
{"type":"message","id":"face5f30","parentId":"f6839092","timestamp":"2026-07-24T16:10:40.379Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Good. `/home/liph/.pi/agent/prompts` is a symlink to `/home/liph/dotfiles/pi/.pi/agent/prompts`. So the dotfiles repo is the live config. And `/home/liph/.pi/agent/agents/` exists and is empty. So I can create `agents/router.md` in the dotfiles at `/home/liph/dotfiles/pi/.pi/agent/agents/router.md` and it will be active.\n\nNow let me design the files to create/edit.\n\n### 1. Update c-*.md files\n\nFor each c-*.md, change the \"Invoke with\" section to foreground default + optional background + stop commands. Also avoid `$@` in examples (use `<task>`).\n\nCurrent c-design-build.md:\n```markdown\n---\ndescription: Brainstorm → plan → test → commit in one background chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n```\n\nNote the description says \"one background chain\". I should change it to \"one chain\" or \"one foreground chain\" to match the new default.\n\nNew:\n```markdown\n---\ndescription: Brainstorm → plan → test → commit in one chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nForeground (default, you can press Esc/Ctrl+C to cancel):\n/prompt-workflow c-design-build \"<task>\"\n\nBackground (detached, use /subagents-fleet to watch and /subagents-stop <id> to kill):\n/prompt-workflow c-design-build --bg \"<task>\"\n```\n\nSimilarly for the other three.\n\n### 2. Update Doc/chain-commands.md\n\nChange the \"How to run a chain\" section to show foreground default. Change \"Each chain runs asynchronously by default\" to \"Each chain runs in the foreground by default; add --bg to detach.\" Add stop instructions.\n\n### 3. Update Doc/prompts.md\n\nThe chain recipes section shows `/prompt-workflow c-design-build --bg \"...\"`. Change to foreground default and add background note.\n\n### 4. Create agents/workflow-router.md\n\nA subagent that picks the best chain and dispatches it. It needs `tools: read, subagent`.\n\nDesign:\n```yaml\n---\nname: workflow-router\ndescription: Pick the best c-* chain for a task and run it in the foreground\ntools: read, subagent\nsystemPromptMode: append\ninheritProjectContext: true\ninheritSkills: false\n---\n\nYou are a workflow router. Your job is to choose and execute the most appropriate c-* chain for the user's task.\n\nAvailable chains (defined in ~/.pi/agent/prompts/):\n\n- c-design-build: p-brainstorm → p-plan → p-test → p-commit\n Best for: new features, design problems, vague requirements, \"how should I build X\".\n\n- c-fix-commit: p-summarize → p-diagnose → p-debug → p-test\n Best for: bugs, failures, errors, regressions, \"something is broken\".\n\n- c-refactor-commit: p-refactor → p-test → p-review → p-commit\n Best for: restructuring existing code, safe refactors, code cleanup.\n\n- c-security-loop: p-secaudit → p-review → p-test\n Best for: auth, input handling, secrets, network, deserialization, trust boundaries.\n\nInstructions:\n1. Read the selected c-*.md file from ~/.pi/agent/prompts/ to confirm the chain order.\n2. Read each p-*.md file in the chain from ~/.pi/agent/prompts/ to get the prompt body.\n3. Run the chain using the `subagent` tool with `async: false` so the user can stop it with Esc/Ctrl+C.\n For each step, use `agent: \"delegate\"` and the prompt body as the `task`, substituting the user's original task for `$@`.\n4. Report which chain you ran and a one-sentence summary of what it will do.\n\nDo not ask the user before running. Pick the single best chain and execute it.\n```\n\nBut there are concerns:\n- The `subagent` tool's chain syntax might require exact field names. Let me check the tool schema in the skill file.\n\nActually, I have the pi-subagents skill available in the skill list. The skill file might document the exact tool usage. Let me read the skill file.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:45","name":"read","arguments":{"path":"/home/liph/.pi/agent/npm/node_modules/pi-subagents/skills/pi-subagents/SKILL.md","limit":400}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":79025,"output":1015,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":80040,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909430089,"responseId":"chatcmpl-855","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"a2243208","parentId":"face5f30","timestamp":"2026-07-24T16:10:40.385Z","message":{"role":"toolResult","toolCallId":"functions.read:45","toolName":"read","content":[{"type":"text","text":"---\nname: pi-subagents\ndescription: |\n Delegate work to builtin or custom subagents with single-agent, chain,\n parallel, async, forked-context, and intercom-coordinated workflows. Use\n for advisory review, implementation handoffs, and multi-step tasks where a\n single agent should stay in control while other agents contribute context,\n planning, or execution.\n---\n\n# Pi Subagents\n\nThis skill is for the main parent orchestrator only. Do not inject or follow it inside spawned child subagents. The parent session owns delegation, orchestration, review fanout, and final fix-worker launches; child subagents should receive concrete role-specific tasks. Ordinary children should not run their own subagent workflows; the explicit exception is a delegated fanout child whose resolved builtin `tools` includes `subagent`, and that child may use `subagent` only for the fanout work the parent assigned.\n\nUse this skill when the parent orchestrator needs to launch a specialized subagent, compose multiple agents into a workflow, or create/edit agents and chains on demand.\n\n## When to Use\n\n- **Complex work orchestration**: use Fable mode as the default parent-agent loop for complex work. Complex means the task has multiple moving parts, unclear acceptance, cross-cutting code, meaningful user-visible impact, expensive or irreversible validation, broad review surface, or the user asks for orchestration. Lightweight one-off delegation can stay lightweight.\n- **Advisory review**: use fresh-context `reviewer` agents for adversarial code review, or fork to `oracle` when inherited decisions and drift matter\n- **Implementation handoff**: have `oracle` advise, then `worker` implement only after an approved direction\n- **Recon and planning**: use `scout` or `context-builder`, then `planner`\n- **Parallel exploration**: run multiple non-conflicting tasks concurrently\n- **Regular skill specialists**: when discovery shows proactive skill subagent suggestions and the current work is broad enough, launch a small fresh-context fanout that asks one subagent per relevant regularly used skill to apply that skill's perspective to the task\n- **Long-running work**: launch async/background runs and inspect them later. For mutation-capable work, bound the delivery slice and elapsed runtime, then request checkpoints after active tool work returns. Reserve hard turn and tool-call caps for explicitly read-only children.\n- **Subagent control**: watch needs-attention signals and soft-interrupt only when a delegated run is genuinely blocked\n- **Agent authoring**: create, update, or override agents and chains for a project\n\n## Tool vs Slash Commands\n\nAgents can use the `subagent(...)` tool directly for execution, management, status, and control.\nHumans often use the slash-command layer instead:\n\n- `/run` — launch a single agent\n- `/chain` — launch a chain of steps\n- `/parallel` — launch top-level parallel tasks\n- `/run-chain` — launch a saved `.chain.md` or `.chain.json` workflow\n- `/subagent-cost` — show parent plus child token usage and cost for the session\n- `/subagents-fleet` — open the live, inspection-only foreground/async fleet; `Ctrl+Alt+F` opens it during an active foreground turn, `↑↓`/`jk` selects children, and `PgUp`/`PgDn` scrolls transcript detail\n- `/subagents-doctor` — diagnose setup, discovery, async paths, and intercom bridge state\n- `/subagents-models [agent]` — show the live runtime-loaded builtin model mapping\n- `/subagents-profiles`, `/subagents-load-profile`, `/subagents-refresh-provider-models`, `/subagents-generate-profiles`, `/subagents-check-profile` — manage model profiles and provider catalogs\n- `/prompt-workflow` and `/chain-prompts` — run prompt templates through native subagent single/chain workflows\n\nPrefer the tool when you are writing agent logic. Prefer the slash commands when\nyou are guiding a human through an interactive flow.\n\nPackaged prompt shortcuts are also available for repeatable workflows. Treat them as reusable orchestration recipes, not just human slash commands. When the user asks for one of these shapes, or when the workflow clearly fits, apply the same pattern directly with `subagent(...)` and other tools:\n- `/parallel-review` — fresh-context reviewers with distinct review angles, then synthesis\n- `/review-loop` — parent-orchestrated worker, fresh-reviewer, and fix-worker cycles until clean or capped\n- `/parallel-research` — combine `researcher` and `scout` for external evidence plus local code context\n- `/parallel-context-build` — parallel `context-builder` passes that produce planning handoff context and meta-prompts\n- `/parallel-handoff-plan` — external-reference research plus local `context-builder` passes, followed by a synthesis handoff plan and implementation-ready meta-prompt\n- `/gather-context-and-clarify` — scout/research first, then ask the user clarifying questions with `interview`\n- `/parallel-cleanup` — two fresh-context reviewers (deslop + verbosity passes) for an adversarial cleanup review of the current diff\n\n## Applying Prompt Techniques Without Slash Commands\n\nThe prompt templates in `prompts/` encode workflows the parent agent can run on demand. If the user provides a URL, issue, PR, plan, local file, screenshot, or freeform target, treat that target as the primary scope: read or fetch it before launching children, then include it explicitly in every child task. Do not depend on the parent conversation history when the recipe calls for fresh context.\n\n### Parallel review technique\n\nUse this when the user wants adversarial review of a diff, plan, issue, file, or implemented work. Launch fresh-context `reviewer` agents with distinct angles generated from the actual target. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability; adapt for TypeScript, UI, security, docs, or large structural changes. Reviewers should inspect files and diffs directly, return concise evidence-backed findings with file/line references, and avoid edits unless the user explicitly asks for a writer pass. The parent synthesizes fixes worth doing now, optional improvements, and feedback to ignore/defer before applying anything.\n\n### Proactive skill-specialist technique\n\nUse this when `{ action: \"list\" }` reports proactive skill subagent suggestions and the user's task would benefit from perspectives the parent regularly uses. These suggestions are conservative: a skill is recommended only when it is available and referenced repeatedly by configured agents or saved chains. Treat the list as an opt-in hint for the current task, not a command to always fan out.\n\nDefault guardrails:\n- Keep the fanout small: usually one or two skill-specialist children, never more than the listed recommendations or configured cap.\n- Prefer `context: \"fresh\"` and include only the files, diff, plan, URL, or request details each child needs. Use forked context only when private/session history is essential and appropriate to share.\n- Use read-only agents for analysis/review unless implementation was explicitly requested; do not create several writers in the same worktree.\n- Skip proactive skill subagents for tiny questions, direct commands, highly private requests, or when the user asks not to delegate.\n- Make cost and concurrency visible by using an ordinary `subagent(...)` call rather than hidden/background automation.\n\nExample shape:\n\n```typescript\nsubagent({\n tasks: [\n { agent: \"reviewer\", task: \"Apply the available 'deslop' skill to review the current diff for concrete cleanup findings only. Do not modify files.\", skill: \"deslop\" },\n { agent: \"reviewer\", task: \"Apply the available 'accessibility' skill to review the UI changes for concrete issues only. Do not modify files.\", skill: \"accessibility\" }\n ],\n context: \"fresh\",\n concurrency: 2\n})\n```\n\n### Review-loop technique\n\nUse this when the user wants implementation or current diff review to continue until reviewers stop finding fixes worth doing now. Keep the loop in the parent session: one async `worker` implements or fixes, fresh-context `reviewer` agents inspect the actual repo and diff, the parent synthesizes accepted fixes, and one async forked `worker` applies them. The parent can express the sequence up front as an async/background chain when the workflow is known, or continue with explicit 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 the user explicitly wants the foreground clarify UI. Treat an async implementation worker handoff as an intermediate state, not final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Stop when reviewers find no blockers or fixes worth doing now, remaining feedback is optional or deferred, an unapproved product/scope/architecture decision appears, or the max review-round cap is reached. Default to 3 review rounds unless the user sets a different cap. Do not loop for optional polish, and do not let children launch subagents or decide the loop outcome.\n\nAs a conservative orchestration policy, do not pass `turnBudget` or a hard `toolBudget` to an implementation worker, fix worker, reviewer with edit authority, or other mutation-capable child. The default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Use a narrow task plus an outer elapsed deadline with enough margin, then request a checkpoint after the current tool returns. The checkpoint should report 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 used as the checkpoint trigger.\n\n### Parallel research technique\n\nUse this when the question needs both external evidence and local implications. Combine `researcher` for official docs, specs, ecosystem behavior, recent changes, benchmarks, and primary sources with `scout` for repository files, patterns, constraints, tests, and likely integration points. Give each child a distinct angle: external evidence, local code context, and practical tradeoffs. Ask for source links or file ranges, confidence level, gaps, and decision implications. Do not ask these children to edit unless implementation was explicitly requested.\n\n### Parallel context-build technique\n\nUse this before planning or implementation when a stronger handoff is needed. Run a chain with one parallel step of `context-builder` agents rather than top-level parallel tasks, so relative output files live under the temporary chain directory. Give every task a distinct output path such as `context-build/request-and-scope.md`, `context-build/codebase-and-patterns.md`, and `context-build/validation-and-risks.md`. Choose two or three builders: request/scope, codebase/patterns, and validation/risks. Each builder must read every relevant file needed to understand its slice, follow imports/callers/tests/docs/config, conduct tool-available web research when needed, and include a compact `meta-prompt` section. The parent synthesizes the outputs into important context, recommended next meta-prompt, open questions, assumptions, and artifact paths.\n\nExample shape:\n\n```typescript\nsubagent({\n chain: [{\n parallel: [\n { agent: \"context-builder\", task: \"Build request/scope context for: ...\", output: \"context-build/request-and-scope.md\" },\n { agent: \"context-builder\", task: \"Build codebase/pattern context for: ...\", output: \"context-build/codebase-and-patterns.md\" },\n { agent: \"context-builder\", task: \"Build validation/risk context for: ...\", output: \"context-build/validation-and-risks.md\" }\n ]\n }],\n context: \"fresh\"\n})\n```\n\n### Parallel handoff-plan technique\n\nUse this when the user needs a solution brief or implementation-ready handoff from an external reference plus local code context, such as “study this library behavior, inspect our codebase, then produce a worker prompt.” Run a chain with a first parallel group and a second synthesis `context-builder` step. The first group usually includes `researcher` for external projects/docs/prompt guidance and `context-builder` for local code context; add a second `context-builder` for implementation strategy only when the scope is large enough to benefit. Use distinct output paths under `handoff/`, then have the synthesis `context-builder` read those outputs and write `handoff/final-handoff-plan.md` with the recommended approach, likely files, constraints, non-goals, validation, risks, unresolved questions, and final compact implementation-ready meta-prompt.\n\nExample shape:\n\n```typescript\nsubagent({\n chain: [\n { parallel: [\n { agent: \"researcher\", task: \"Research the external reference and transferable implementation ideas for: ...\", output: \"handoff/external-reference.md\" },\n { agent: \"context-builder\", task: \"Build local codebase context for: ...\", output: \"handoff/local-context.md\" },\n { agent: \"context-builder\", task: \"Compare evidence and propose implementation strategy for: ...\", output: \"handoff/implementation-strategy.md\" }\n ] },\n { agent: \"context-builder\", task: \"Read {previous} and synthesize the final handoff plan and implementation-ready meta-prompt.\", output: \"handoff/final-handoff-plan.md\" }\n ],\n context: \"fresh\"\n})\n```\n\n### Gather-context-and-clarify technique\n\nUse this at the start of non-trivial work. Launch `scout` for local context and `researcher` only when external docs, recent sources, ecosystem context, or primary evidence would materially improve understanding. Ask children for concise findings plus remaining clarification questions. Then synthesize what is known and use `interview` to ask the unresolved questions needed for shared understanding before planning or implementing.\n\n### Parallel cleanup technique\n\nUse this after implementation when the user wants cleanup review or when a final pass would reduce AI-slop. Launch two fresh-context `reviewer` tasks with `output: false` and `progress: false`: one deslop pass and one verbosity pass. If the `deslop` or `verbosity-cleaner` skills are available, pass the relevant skill to that reviewer; otherwise inline the criteria. Both reviewers are review-only and should flag concrete issues with severity, file/line references, and smallest safe fixes. Phrase the constraint as “Do not modify project/source files; returning findings through the configured output artifact is allowed” when you use `output` or `outputMode: \"file-only\"`. The parent decides what to apply and asks before making changes unless cleanup was already authorized.\n\n### Staged fix orchestration technique\n\nUse this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep the active worktree safe with a three-stage chain:\n\n1. A parallel read-only planning fanout, one planner/reviewer per issue cluster. Each child inspects the real diff and returns exact files, line refs, proposed fixes, and focused validation. They must not edit.\n2. One writer worker. It receives the planner summaries through `{previous}`, the parent’s accepted scope, stop rules, and verification contract. It is the only child allowed to edit the active worktree.\n3. A parallel read-only validation fanout. Validators inspect the worker diff from fresh context with distinct angles, report pass/fail, remaining blockers, and missing verification.\n\nPrefer `async: true`, `context: \"fresh\"` for planners/validators, `outputMode: \"file-only\"` for large summaries, and per-stage output names that will not collide. Add `phase` and `label` to make async status readable, and use `as` plus `{outputs.name}` when a later step needs a specific earlier result instead of the whole `{previous}` blob. Use this pattern instead of launching several writer workers into a dirty worktree. Include non-blocking suggestions in the writer prompt only when they are small, safe, and do not expand product scope; otherwise record them as deferred.\n\nWhen the first step can return a structured target list, prefer dynamic fanout instead of hand-authoring a static parallel group. Use `outputSchema` and `as` on the producer, then an `expand` step with `from: { output, path }`, an explicit `maxItems`, one `parallel` child template, and `collect.as`. Item templates may use `{item}` or a named item such as `{target.path}`. Do not use dynamic fanout for prose outputs, nested fanout, dynamic agent selection, reducers, `when` conditions, or arbitrary expressions; `.chain.md` does not support this syntax, so use direct JSON or a saved `.chain.json`.\n\nExample shape:\n\n```typescript\nsubagent({\n async: true,\n context: \"fresh\",\n chain: [\n { parallel: [\n { agent: \"reviewer\", phase: \"Planning\", label: \"Deploy docs\", as: \"deployPlan\", task: \"Plan fixes for deploy docs/workflow. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.\", output: \"plans/deploy.md\", outputMode: \"file-only\" },\n { agent: \"reviewer\", phase: \"Planning\", label: \"Scheduler contract\", as: \"schedulerPlan\", task: \"Plan fixes for scheduler contract. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.\", output: \"plans/scheduler.md\", outputMode: \"file-only\" },\n { agent: \"reviewer\", phase: \"Planning\", label: \"Sandbox/security\", as: \"sandboxPlan\", task: \"Plan fixes for sandbox/security. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.\", output: \"plans/sandbox.md\", outputMode: \"file-only\" }\n ], concurrency: 3 },\n { agent: \"worker\", phase: \"Implementation\", label: \"Apply accepted fixes\", as: \"workerResult\", task: \"Apply only the accepted fixes from these planning summaries. You are the sole writer for the active worktree. Run focused validation and report changed files, commands, failures, and remaining issues.\\n\\nDeploy plan:\\n{outputs.deployPlan}\\n\\nScheduler plan:\\n{outputs.schedulerPlan}\\n\\nSandbox plan:\\n{outputs.sandboxPlan}\", output: \"worker/fixes.md\", outputMode: \"file-only\", progress: true },\n { parallel: [\n { agent: \"reviewer\", phase: \"Validation\", label: \"Deploy/scheduler validation\", task: \"Validate the post-worker diff for deploy and scheduler fixes. Start from the worker result: {outputs.workerResult}. Do not modify project/source files; returning findings via the configured output artifact is allowed.\", output: \"validation/deploy-scheduler.md\", outputMode: \"file-only\" },\n { agent: \"reviewer\", phase: \"Validation\", label: \"Sandbox validation\", task: \"Validate the post-worker diff for sandbox/security fixes. Start from the worker result: {outputs.workerResult}. Do not modify project/source files; returning findings via the configured output artifact is allowed.\", output: \"validation/sandbox.md\", outputMode: \"file-only\" }\n ], concurrency: 2 }\n ]\n})\n```\n\n## Builtin Agents\n\nBuiltin agents load at the lowest priority. Project agents override user agents,\nand user/project agents override builtins with the same name.\n\n| Agent | Purpose | Model | Typical output / role |\n|-------|---------|-------|------------------------|\n| `scout` | Fast codebase recon | inherits default | Writes `context.md` handoff material |\n| `planner` | Creates implementation plans | inherits default | Writes `plan.md` |\n| `worker` | Implementation and approved oracle handoffs | inherits default | Single-writer implementation with decision escalation |\n| `reviewer` | Review-and-fix specialist | inherits default | Can edit/fix reviewed code |\n| `context-builder` | Requirements/codebase handoff builder | inherits default | Writes structured context files |\n| `researcher` | Web research brief generator | inherits default | Writes `research.md` |\n| `delegate` | Lightweight generic delegate | inherits default | No fixed output; generic delegated work |\n| `oracle` | Decision-consistency advisory review | inherits default | Advisory review, intercom coordination |\n\nBuiltin agents inherit the current Pi default model unless a run, user setting, project setting, or `subagents.defaultModel` overrides `model`. Set `subagents.defaultModel` when subagents should use a different default model than the parent session. Override builtin defaults before copying full agent files when a small tweak is enough.\n\nFor one run, use inline config:\n\n```text\n/run reviewer[model=anthropic/claude-sonnet-4] \"Review this diff\"\n```\n\nFor persistent tweaks, edit `subagents.agentOverrides` in user or project settings. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides. Use `/subagents-models` or `subagent({ action: \"models\" })` to inspect the live mapping after settings and overrides load.\n\nModel ids do not have to be exact. Separator variations (`claude-haiku-4.5` vs `claude-haiku-4-5`), case (`Claude-Sonnet-4`), and optional trailing date stamps (`claude-haiku-4-5-20251001`) all resolve to the same registry model. Exact `provider/id` wins; a qualified `provider/model` never switches providers. To constrain subagents to a budget or compliance profile, set `subagents.modelScope: { enforce: true, allow: [\"anthropic/*\", \"openai/gpt-5-*\"] }` in user or project settings. Out-of-scope models you pass explicitly error and abort; models inherited from frontmatter, `subagents.defaultModel`, agent frontmatter, or the parent session only warn.\n\nFor model fleets, use the profile commands instead of hand-editing repeated overrides: `/subagents-refresh-provider-models <provider>`, `/subagents-generate-profiles <provider>`, `/subagents-load-profile <name>`, and `/subagents-check-profile <name>`. Profiles live under `~/.pi/agent/profiles/pi-subagents/` and replace only `settings.subagents` when loaded.\n\n## Prompting role subagents\n\nBuiltin role agents inherit the current Pi default model unless you override them. When launching them, write the task prompt as a compact contract, not a long procedural script. Define the destination and let the role choose the efficient path.\n\nA strong subagent prompt usually includes:\n- **Goal**: the concrete outcome the child should produce.\n- **Context/evidence**: relevant plan paths, files, diffs, decisions, or user constraints already approved.\n- **Success criteria**: what must be true before the child can finish.\n- **Hard constraints**: true invariants only, such as no edits for review-only tasks, one writer thread, child must not run subagents unless it is an explicitly assigned `tools: subagent` fanout child, or escalation for unapproved decisions.\n- **Validation**: targeted checks to run, or the next-best check when validation is impossible.\n- **Output**: the expected summary shape, artifact path, or finding format.\n- **Stop rules**: when to ask via `intercom`, when to stop after enough evidence, and when not to keep searching.\n\nAvoid carrying over old prompt habits that over-specify every step. Use `must`, `always`, and `never` for real invariants; for judgment calls, give decision rules. For example, tell a reviewer to inspect the staged diff directly and report only evidence-backed findings, rather than prescribing every file or command. Tell a researcher the retrieval budget: start with broad targeted searches, fetch only the strongest sources, search again only when a required fact is missing, then stop.\n\nFor implementation handoffs, name the approved scope and success criteria more clearly than the process. Good prompts say what to change, what not to change, where the evidence lives, how to validate, and when to escalate. They should not ask the child to create another subagent plan or continue the parent conversation.\n\nSettings locations:\n- User scope: `~/.pi/agent/settings.json`\n- Project scope: `.pi/settings.json`\n\nDirect settings example:\n\n```json\n{\n \"subagents\": {\n \"agentOverrides\": {\n \"reviewer\": {\n \"model\": \"anthropic/claude-sonnet-4\",\n \"thinking\": \"high\",\n \"fallbackModels\": [\"openai/gpt-5-mini\"],\n \"acceptanceRole\": \"read-only\"\n }\n }\n }\n}\n```\n\nUseful override fields: `model`, `fallbackModels`, `thinking`,\n`systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`,\n`acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use\n`acceptanceRole: false` to clear an override. Create a user or project\nagent with the same name only when you want a substantially different agent.\n\nIf a provider rejects model IDs with thinking suffixes, use\n`subagents.disableThinking: true` in user or project settings to clear bundled\nbuiltin thinking defaults globally. A higher-precedence per-agent `thinking`\noverride can opt one builtin back in.\n\nTool description modes live in `~/.pi/agent/extensions/subagent/config.json`, not `subagents` settings. Set `toolDescriptionMode` to `compact` to reduce tool-description prompt cost while keeping the execution, async/`subagent_wait`, child-safety, one-writer, management/action, and artifact/status guardrails. Set it to `custom` to read `subagent-tool-description.md` from the project config dir or agent dir; invalid custom files fall back to full mode and the safety guidance is still appended.\n\n## Discovery and Scope Rules\n\nAgent files can live in:\n- `~/.pi/agent/agents/**/*.md` — user scope\n- `.pi/agents/**/*.md` — canonical project scope\n- legacy `.agents/**/*.md` — still read for compatibility, but `.pi/agents/` wins on conflicts\n\nChains live in:\n- `~/.pi/agent/chains/**/*.chain.md` and `~/.pi/agent/chains/**/*.chain.json` — user scope\n- `.pi/chains/**/*.chain.md` and `.pi/chains/**/*.chain.json` — project scope\n\nDiscovery is recursive. `.chain.md` files do not define agents. Use `.chain.md` for simple saved chains and `.chain.json` for dynamic fanout or inline schema objects. Agents and chains can set optional frontmatter/package metadata; `name: scout` plus `package: code-analysis` registers as runtime name `code-analysis.scout` while serialization keeps `name` and `package` separate.\n\nPrecedence is by parsed runtime name:\n1. project scope\n2. user scope\n3. builtin agents\n\n## Running Subagents\n\n### Single agent\n\n```typescript\nsubagent({\n agent: \"oracle\",\n task: \"Review my current direction and challenge assumptions.\"\n})\n```\n\n### Forked context\n\n```typescript\nsubagent({\n agent: \"oracle\",\n task: \"Review my current direction and challenge assumptions.\"\n})\n```\n\n`context: \"fork\"` creates a branched child session from the current persisted\nparent session. It does **not** create a fresh minimal review context or filter\nhistory down to only the relevant parts. Use it when you want a separate review\nor execution thread that can still reference the parent session history.\n\n### Parallel execution\n\n```typescript\nsubagent({\n tasks: [\n { agent: \"scout\", task: \"Explore the auth module\" },\n { agent: \"reviewer\", task: \"Review the API client\" }\n ]\n})\n```\n\nTop-level parallel tasks can override per-task behavior:\n\n```typescript\nsubagent({\n tasks: [\n { agent: \"scout\", task: \"Map auth\", output: \"auth-context.md\", progress: true },\n { agent: \"researcher\", task: \"Research OAuth best practices\", output: \"oauth-research.md\" },\n { agent: \"reviewer\", task: \"Review auth tests\", model: \"anthropic/claude-sonnet-4\" }\n ],\n concurrency: 3\n})\n```\n\nAvoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file. For large saved outputs, set `outputMode: \"file-only\"` together with an `output` path. The parent result then contains only a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` instead of the full saved content. Do not use `output: false` for this; `output: false` means no file output. Read-only children return the complete artifact in their final response and the runtime persists it, so missing write tools are not a supervisor blocker. Mutation-capable children still receive direct-write instructions. Failed runs and save errors still return inline details for debugging.\n\n### Chain execution\n\n```typescript\nsubagent({\n chain: [\n { agent: \"scout\", task: \"Map the auth flow and summarize key files\" },\n { agent: \"planner\", task: \"Create an implementation plan from {previous}\" },\n { agent: \"worker\", task: \"Implement the approved plan based on {previous}\" }\n ]\n})\n```\n\nChain steps can use templated variables such as `{task}`, `{previous}`,\n`{chain_dir}`, and `{outputs.name}`. Use `as: \"name\"` on a successful step or\nparallel task to make that output available to later steps. Prefer named outputs\nwhen a later step needs one specific result; keep `{previous}` for simple linear\nhandoffs or full fan-in summaries. Use `phase` and `label` for status readability.\nUse `outputSchema` when later steps need reliable structured data; the child must\ncall `structured_output` with schema-valid JSON, or the step fails.\n\n### Async/background\n\nPrefer async mode for every subagent launch. Set `async: true` no matter the task unless there is a specific reason to opt into a foreground/blocking run. This applies to scouts, researchers, workers, reviewers, validators, oracle checks, one-off delegates, chains, and parallel groups. Keep the write path single-threaded even when the run is async.\n\nAsync does not mean parallel writes. Do not edit the same active worktree while an async worker is changing it. Parent-side overlap should be reading, validation prep, synthesis, command planning, or review of unaffected context unless the writer is isolated in a separate worktree.\n\nDo not end your turn immediately after launching an async child if you promised to keep working. Continue the local inspection, synthesis, or validation prep, then check the async run when its result is needed.\n\nIn an interactive chat, normally return control when ready to yield and let Pi wake the session on completion; do not call `subagent_wait()` merely to wait. Override that default and call it when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its background work finishes. Headless sessions auto-drain exact current-session work at `agent_end`; call `subagent_wait()` when this turn must receive results before it ends. Never substitute sleep or status-polling loops.\n\n`subagent_wait()` returns when the next initially active async run or registered provider item finishes or a subagent needs attention. Use `subagent_wait({ all: true })` for all work active at call time, `subagent_wait({ id: \"...\" })` for one async or remembered detached foreground run, and `subagent_wait({ timeoutMs })` to cap the block. If a foreground child detaches for supervisor coordination, reply first, then wait on its id; do not resume or launch a replacement while it remains detached. Headless sessions also auto-drain exact current-session work at `agent_end` as a final safeguard.\n\n```typescript\nsubagent({\n agent: \"worker\",\n task: \"Run the full test suite\",\n async: true\n})\n```\n\nFile-only output mode also works for async single runs, top-level parallel task items, sequential chain steps, and chain parallel task items. In chains, `{previous}` receives the compact saved-file reference when the prior step used file-only mode.\n\nFor review fanout where the parent continues a local audit:\n\n```typescript\nconst run = subagent({\n agent: \"reviewer\",\n task: \"Review the current diff for correctness issues. Do not edit files.\",\n async: true,\n context: \"fresh\"\n})\n// Continue local inspection, then later call status with the returned id.\n```\n\nInspect async runs with `subagent({ action: \"status\", id: \"...\" })` or `subagent({ action: \"status\" })` for active runs. Use `subagent({ action: \"status\", view: \"fleet\" })` when supervising several active foreground/background runs and `subagent({ action: \"status\", id: \"...\", view: \"transcript\", index: 0 })` when you need the latest child output without digging through artifacts. If a delegated fanout child launches nested runs, the parent status view shows them as a tree and you can target a nested run directly with its nested id.\n\nUse `steer` for top-level live async guidance and `resume` after a delegated run pauses or finishes. Routed nested runs retain their existing non-destructive live follow-up path:\n\n```typescript\nsubagent({ action: \"steer\", id: \"run-id\", message: \"Focus on the failing test.\" })\nsubagent({ action: \"resume\", id: \"run-id\", message: \"Follow up on this point.\" })\nsubagent({ action: \"resume\", id: \"run-id\", index: 1, message: \"Continue reviewer 2.\" })\nsubagent({ action: \"resume\", id: \"nested-run-id\", message: \"Continue this nested reviewer.\" })\n```\n\nResume behavior:\n- `resume` revives paused, completed, or failed async/foreground children from persisted session files; stopped runs remain non-resumable, and it does not interrupt live top-level async children.\n- Use `steer` for acknowledged guidance to a live top-level async child.\n- A live nested run can still receive a non-destructive `resume` follow-up through its owner route.\n- If an async child has completed, `resume` revives it by starting a new async child from the persisted child session file.\n- Multi-child async runs require `index` unless only one running child is selectable.\n- Completed foreground single, parallel, and chain runs can also be revived by `index` while their run metadata remains in extension state.\n\n[581 more lines in file. Use offset=401 to continue.]"}],"isError":false,"timestamp":1784909440385}}
|
||
{"type":"message","id":"0aee9275","parentId":"a2243208","timestamp":"2026-07-24T16:10:46.932Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The skill file confirms the `subagent` tool schema. I can use `chain: [...]`, `async: false`, etc. Good.\n\nNow, the router design. The router subagent will use `subagent({ chain: [...], async: false })`. Each step will be `agent: \"delegate\"` with a task derived from the p-*.md body.\n\nBut I need to make sure the router can read the p-*.md files. It will be invoked from a subagent, which has its own cwd. The prompt files live at `~/.pi/agent/prompts/`. The router can use absolute paths.\n\nAlso, the router needs to know which p-*.md maps to each step. The c-*.md chain frontmatter tells it.\n\nLet me write the router agent. It should be concise but clear.\n\nAlso, I should add `c-auto.md`? Hmm, the user didn't ask for it, but it would make the router usable via `/prompt-workflow c-auto \"task\"`. But `/prompt-workflow` expects the workflow to be a prompt template, not an agent. If I create `c-auto.md` as a chain recipe with `chain: workflow-router`, that won't work because `workflow-router` is an agent, not a prompt template. The `/prompt-workflow` command resolves names to prompt templates in the prompts dir, not agents. So `c-auto.md` would need to use a different approach.\n\nActually, the user can invoke the router via `/run workflow-router \"task\"` or `subagent({ agent: \"workflow-router\", task: \"...\" })`. That's fine.\n\nBut the user asked for an \"automatic tool\". A slash command like `/run workflow-router \"task\"` is good. Or the parent can naturally invoke it.\n\nOK, let me proceed with:\n1. Edit 4 c-*.md files.\n2. Edit Doc/chain-commands.md.\n3. Edit Doc/prompts.md chain recipes section.\n4. Create agents/workflow-router.md.\n\nI also need to make sure the workflow-router.md uses the right name and is discoverable. The file should be at `/home/liph/dotfiles/pi/.pi/agent/agents/workflow-router.md`.\n\nLet me also check if there are any tests that validate the c-*.md frontmatter. The session history mentioned `test/chain-workflow.test.ts`. I should run or at least check it to make sure my changes don't break tests.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:46","name":"bash","arguments":{"command":"ls -la /home/liph/dotfiles/pi/.pi/agent/prompts/test/"}},{"type":"toolCall","id":"functions.read:47","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/test/chain-workflow.test.ts","limit":200}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":87286,"output":579,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":87865,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909440387,"responseId":"chatcmpl-337","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"8527ee25","parentId":"0aee9275","timestamp":"2026-07-24T16:10:46.966Z","message":{"role":"toolResult","toolCallId":"functions.bash:46","toolName":"bash","content":[{"type":"text","text":"total 52\ndrwxr-xr-x 4 liph liph 4096 Jul 24 18:08 .\ndrwxr-xr-x 5 liph liph 4096 Jul 24 18:02 ..\n-rw-r--r-- 1 liph liph 17965 Jul 24 18:03 chain-workflow.test.ts\ndrwxr-xr-x 2 liph liph 4096 Jul 24 18:00 fixtures\n-rw-r--r-- 1 liph liph 356 Jul 24 18:01 package.json\n-rw-r--r-- 1 liph liph 11881 Jul 24 18:08 rate-limit.design.md\ndrwxr-xr-x 2 liph liph 4096 Jul 24 18:00 support\n"}],"isError":false,"timestamp":1784909446966}}
|
||
{"type":"message","id":"75c80f8a","parentId":"8527ee25","timestamp":"2026-07-24T16:10:46.966Z","message":{"role":"toolResult","toolCallId":"functions.read:47","toolName":"read","content":[{"type":"text","text":"/**\n * Tests for the prompt workflow chain under `.pi/agent/prompts/`.\n *\n * Scope (static, no LLM):\n * - Frontmatter of every `c-*.md` recipe and `p-*.md` step is well-formed\n * and contains the keys the pi-subagents adapter requires.\n * - Every step named in a `chain:` resolves to an existing `p-*.md` file.\n * - Every step has `subagent: true` and `fork: true`, which `Doc/chain-commands.md`\n * calls out as required for `p-*.md` chain steps.\n * - The Doc pages describe the same recipes / sequences that exist on disk.\n *\n * These tests do not exercise the LLM. They are independent, deterministic,\n * and fast (run against the on-disk tree only).\n */\n\nimport { describe, it, before } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { readFileSync, readdirSync } from \"node:fs\";\nimport { join, resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { parseFrontmatter, parseChain } from \"./support/frontmatter.ts\";\n\n// ---------------------------------------------------------------------------\n// Locating the prompts directory\n// ---------------------------------------------------------------------------\n\nconst here = dirname(fileURLToPath(import.meta.url));\n// test/ -> .pi/agent/prompts/\nconst PROMPTS_DIR = resolve(here, \"..\");\n\nfunction readUtf8(path: string): string {\n\treturn readFileSync(path, \"utf8\");\n}\n\nfunction readDoc(path: string): { frontmatter: Record<string, string>; body: string } {\n\treturn parseFrontmatter(readUtf8(path));\n}\n\nlet chainFiles: string[] = [];\nlet promptFiles: string[] = [];\nlet docFiles: string[] = [];\n\nbefore(() => {\n\tchainFiles = readdirSync(PROMPTS_DIR)\n\t\t.filter((n) => n.startsWith(\"c-\") && n.endsWith(\".md\"))\n\t\t.sort()\n\t\t.map((n) => join(PROMPTS_DIR, n));\n\tpromptFiles = readdirSync(PROMPTS_DIR)\n\t\t.filter((n) => n.startsWith(\"p-\") && n.endsWith(\".md\"))\n\t\t.sort()\n\t\t.map((n) => join(PROMPTS_DIR, n));\n\tdocFiles = readdirSync(join(PROMPTS_DIR, \"Doc\"))\n\t\t.filter((n) => n.endsWith(\".md\"))\n\t\t.sort()\n\t\t.map((n) => join(PROMPTS_DIR, \"Doc\", n));\n});\n\nfunction readChain(name: string) {\n\tconst path = join(PROMPTS_DIR, name);\n\treturn { path, name, ...readDoc(path) };\n}\n\nfunction readPrompt(step: string) {\n\t// Accept both `p-brainstorm` and `p-brainstorm.md`; the actual files\n\t// end in `.md` but the chain frontmatter references them without it.\n\tconst fileName = step.endsWith(\".md\") ? step : `${step}.md`;\n\tconst path = join(PROMPTS_DIR, fileName);\n\treturn { path, step, ...readDoc(path) };\n}\n\n// ---------------------------------------------------------------------------\n// Test data\n// ---------------------------------------------------------------------------\n\nconst EXPECTED_CHAINS: Record<string, string[]> = {\n\t\"c-design-build.md\": [\"p-brainstorm\", \"p-plan\", \"p-test\", \"p-commit\"],\n\t\"c-fix-commit.md\": [\"p-summarize\", \"p-diagnose\", \"p-debug\", \"p-test\"],\n\t\"c-refactor-commit.md\": [\"p-refactor\", \"p-test\", \"p-review\", \"p-commit\"],\n\t\"c-security-loop.md\": [\"p-secaudit\", \"p-review\", \"p-test\"],\n};\n\nconst PROMPTS_USED_IN_CHAINS = new Set<string>(\n\tObject.values(EXPECTED_CHAINS).flat(),\n);\n\n// ---------------------------------------------------------------------------\n// 1. Self-tests for the frontmatter/chain helpers (the test infra must work)\n// ---------------------------------------------------------------------------\n\ndescribe(\"support: frontmatter parser\", () => {\n\tit(\"parses a simple key: value block\", () => {\n\t\tconst { frontmatter, body } = parseFrontmatter(\n\t\t\t'---\\nfoo: bar\\nbaz: \"qux\"\\n---\\nhello',\n\t\t);\n\t\tassert.equal(frontmatter.foo, \"bar\");\n\t\tassert.equal(frontmatter.baz, \"qux\");\n\t\tassert.equal(body, \"hello\");\n\t});\n\n\tit(\"returns empty frontmatter when the file has no fence\", () => {\n\t\tconst { frontmatter } = parseFrontmatter(\"no fence here\");\n\t\tassert.deepEqual(frontmatter, {});\n\t});\n\n\tit(\"returns empty frontmatter when the fence is unterminated\", () => {\n\t\tconst { frontmatter } = parseFrontmatter(\"---\\nfoo: bar\\nstill going\");\n\t\tassert.deepEqual(frontmatter, {});\n\t});\n\n\tit(\"de-indents a block scalar and trims leading newlines\", () => {\n\t\tconst { frontmatter } = parseFrontmatter(\n\t\t\t\"---\\nbody: |\\n line one\\n line two\\n line three\\n---\\n\",\n\t\t);\n\t\tassert.equal(frontmatter.body, \"line one\\nline two\\nline three\");\n\t});\n\n\tit(\"strips full-line comments and ignores empty lines between keys\", () => {\n\t\tconst { frontmatter } = parseFrontmatter(\n\t\t\t\"---\\nfoo: bar\\n# full-line comment\\nbaz: qux\\n---\\n\",\n\t\t);\n\t\tassert.equal(frontmatter.foo, \"bar\");\n\t\tassert.equal(frontmatter.baz, \"qux\");\n\t\t// Inline `#` after a value is left in the value (matches the\n\t\t// upstream `parseFrontmatter` in `pi-subagents`). This protects\n\t\t// against accidental whitespace stripping.\n\t\tconst inline = parseFrontmatter(\"---\\nfoo: bar # trailing\\n---\\n\");\n\t\tassert.equal(inline.frontmatter.foo, \"bar # trailing\");\n\t});\n\n\tit(\"normalizes CRLF line endings\", () => {\n\t\tconst { frontmatter, body } = parseFrontmatter(\n\t\t\t\"---\\r\\nfoo: bar\\r\\n---\\r\\nbody\",\n\t\t);\n\t\tassert.equal(frontmatter.foo, \"bar\");\n\t\tassert.equal(body, \"body\");\n\t});\n});\n\ndescribe(\"support: chain parser\", () => {\n\tit(\"splits on ' -> ' and trims\", () => {\n\t\tassert.deepEqual(parseChain(\"a -> b -> c\"), [\"a\", \"b\", \"c\"]);\n\t});\n\n\tit(\"returns [] for undefined\", () => {\n\t\tassert.deepEqual(parseChain(undefined), []);\n\t});\n\n\tit(\"returns [] for an empty string\", () => {\n\t\tassert.deepEqual(parseChain(\"\"), []);\n\t});\n\n\tit(\"drops empty parts from extra spaces\", () => {\n\t\tassert.deepEqual(parseChain(\"a -> -> b\"), [\"a\", \"b\"]);\n\t});\n\n\tit(\"does not split on a single dash\", () => {\n\t\t// A chain value should not use `-` as a separator; the actual\n\t\t// recipes use ` -> `. This protects against future drift.\n\t\tassert.deepEqual(parseChain(\"a-b-c\"), [\"a-b-c\"]);\n\t});\n});\n\n// ---------------------------------------------------------------------------\n// 2. Happy path — the on-disk tree matches what we expect\n// ---------------------------------------------------------------------------\n\ndescribe(\"happy path: chain recipes are present and well-formed\", () => {\n\tfor (const [name, expectedSteps] of Object.entries(EXPECTED_CHAINS)) {\n\t\tit(`loads ${name}`, () => {\n\t\t\tassert.ok(\n\t\t\t\tchainFiles.includes(join(PROMPTS_DIR, name)),\n\t\t\t\t`missing chain recipe: ${name}`,\n\t\t\t);\n\t\t});\n\n\t\tit(`${name} has description, argument-hint, and chain fields`, () => {\n\t\t\tconst { frontmatter } = readChain(name);\n\t\t\tassert.ok(frontmatter.description, \"missing description\");\n\t\t\tassert.ok(frontmatter[\"argument-hint\"], \"missing argument-hint\");\n\t\t\tassert.ok(frontmatter.chain, \"missing chain\");\n\t\t});\n\n\t\tit(`${name}.chain parses to ${expectedSteps.join(\" -> \")}`, () => {\n\t\t\tconst { frontmatter } = readChain(name);\n\t\t\tassert.deepEqual(parseChain(frontmatter.chain), expectedSteps);\n\t\t});\n\n\t\tit(`${name} contains a $@ placeholder for the user argument`, () => {\n\t\t\tconst { body } = readChain(name);\n\t\t\tassert.ok(\n\t\t\t\tbody.includes(\"$@\"),\n\t\t\t\t\"chain recipe body must use $@ for the user-supplied argument\",\n\t\t\t);\n\t\t});\n\t}\n});\n\ndescribe(\"happy path: every prompt step resolves to a real file\", () => {\n\tfor (const step of PROMPTS_USED_IN_CHAINS) {\n\n[293 more lines in file. Use offset=201 to continue.]"}],"isError":false,"timestamp":1784909446966}}
|
||
{"type":"message","id":"2bab9062","parentId":"75c80f8a","timestamp":"2026-07-24T16:10:49.765Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The tests check:\n- c-*.md have description, argument-hint, chain.\n- chain parses to expected steps.\n- body contains `$@`.\n- p-*.md have `subagent: true` and `fork: true`.\n- Doc pages describe the same recipes/sequences.\n\nMy changes to c-*.md must preserve `$@` in the body (which I will do). They must keep description, argument-hint, chain. So they should pass.\n\nI should read the rest of the test to see if it checks for specific text in docs.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:48","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/test/chain-workflow.test.ts","offset":201,"limit":200}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":89914,"output":158,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":90072,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909446969,"responseId":"chatcmpl-29","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"fc559748","parentId":"2bab9062","timestamp":"2026-07-24T16:10:49.768Z","message":{"role":"toolResult","toolCallId":"functions.read:48","toolName":"read","content":[{"type":"text","text":"\t\tit(`step ${step} exists as a p-*.md file`, () => {\n\t\t\tassert.ok(\n\t\t\t\tpromptFiles.includes(join(PROMPTS_DIR, `${step}.md`)),\n\t\t\t\t`chain references ${step} but no such p-*.md exists`,\n\t\t\t);\n\t\t});\n\t}\n});\n\ndescribe(\"happy path: every p-*.md has the required chain-step shape\", () => {\n\tfor (const step of PROMPTS_USED_IN_CHAINS) {\n\t\tit(`${step} declares subagent: true`, () => {\n\t\t\tconst { frontmatter } = readPrompt(step);\n\t\t\tassert.equal(frontmatter.subagent, \"true\");\n\t\t});\n\n\t\tit(`${step} declares fork: true`, () => {\n\t\t\tconst { frontmatter } = readPrompt(step);\n\t\t\tassert.equal(frontmatter.fork, \"true\");\n\t\t});\n\n\t\tit(`${step} has description and argument-hint`, () => {\n\t\t\tconst { frontmatter } = readPrompt(step);\n\t\t\tassert.ok(frontmatter.description, \"missing description\");\n\t\t\tassert.ok(frontmatter[\"argument-hint\"], \"missing argument-hint\");\n\t\t});\n\n\t\tit(`${step} body references $@`, () => {\n\t\t\tconst { body } = readPrompt(step);\n\t\t\tassert.ok(body.includes(\"$@\"), \"p-* body must use $@ for arguments\");\n\t\t});\n\t}\n});\n\n// ---------------------------------------------------------------------------\n// 3. Edge cases — boundaries of the format\n// ---------------------------------------------------------------------------\n\ndescribe(\"edge cases: chain format boundaries\", () => {\n\tit(\"every chain has at least one step\", () => {\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst steps = parseChain(readChain(name).frontmatter.chain);\n\t\t\tassert.ok(steps.length > 0, `${name} chain is empty`);\n\t\t}\n\t});\n\n\tit(\"no chain has a duplicate step\", () => {\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst steps = parseChain(readChain(name).frontmatter.chain);\n\t\t\tassert.equal(\n\t\t\t\tnew Set(steps).size,\n\t\t\t\tsteps.length,\n\t\t\t\t`${name} contains a duplicate step`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"every chain step is lowercase kebab-case starting with 'p-'\", () => {\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst steps = parseChain(readChain(name).frontmatter.chain);\n\t\t\tfor (const step of steps) {\n\t\t\t\tassert.match(step, /^p-[a-z0-9][a-z0-9-]*$/, `${name} step '${step}' is not p-kebab-case`);\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"chain frontmatter uses ' -> ' (single space) and not '->' or ' - >'\", () => {\n\t\t// This is the format the pi-subagents adapter's `splitPromptChain`\n\t\t// actually understands.\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst raw = readChain(name).frontmatter.chain;\n\t\t\tassert.ok(raw, `${name} has no chain value`);\n\t\t\tassert.doesNotMatch(raw, /[^ ]->/, `${name} uses bare '->' which the adapter will not split on`);\n\t\t}\n\t});\n\n\tit(\"every chain ends with a real prompt file, not a typo\", () => {\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst last = parseChain(readChain(name).frontmatter.chain).at(-1);\n\t\t\tassert.ok(last && promptFiles.includes(join(PROMPTS_DIR, `${last}.md`)),\n\t\t\t\t`${name} last step '${last}' does not exist on disk`);\n\t\t}\n\t});\n});\n\ndescribe(\"edge cases: argument-hint style\", () => {\n\tit(\"every argument-hint is non-empty\", () => {\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst hint = readChain(name).frontmatter[\"argument-hint\"];\n\t\t\tassert.ok(hint && hint.length > 0, `${name} has empty argument-hint`);\n\t\t}\n\t\tfor (const step of PROMPTS_USED_IN_CHAINS) {\n\t\t\tconst hint = readPrompt(step).frontmatter[\"argument-hint\"];\n\t\t\tassert.ok(hint && hint.length > 0, `${step} has empty argument-hint`);\n\t\t}\n\t});\n\n\tit(\"argument-hints are wrapped in [...] to match the documented convention\", () => {\n\t\t// Doc/chain-commands.md and the existing recipes all use `[hint]`.\n\t\tconst bracket = /^\\[.+\\]$/;\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst hint = readChain(name).frontmatter[\"argument-hint\"];\n\t\t\tassert.match(hint, bracket, `${name} argument-hint not wrapped in []`);\n\t\t}\n\t\tfor (const step of PROMPTS_USED_IN_CHAINS) {\n\t\t\tconst hint = readPrompt(step).frontmatter[\"argument-hint\"];\n\t\t\tassert.match(hint, bracket, `${step} argument-hint not wrapped in []`);\n\t\t}\n\t});\n});\n\n// ---------------------------------------------------------------------------\n// 4. Error cases — malformed / missing / inconsistent input\n// ---------------------------------------------------------------------------\n\ndescribe(\"error cases: malformed frontmatter\", () => {\n\tit(\"rejects a chain file with no closing fence\", () => {\n\t\tconst { frontmatter } = parseFrontmatter(\n\t\t\t\"---\\ndescription: broken\\nchain: a -> b\\n\",\n\t\t);\n\t\t// Without a closing fence, the parser should return no frontmatter\n\t\t// (mirroring the real adapter), so the chain is empty.\n\t\tassert.deepEqual(frontmatter, {});\n\t});\n\n\tit(\"rejects a chain value with no separator at all\", () => {\n\t\tassert.deepEqual(parseChain(\"only-one-step\"), [\"only-one-step\"]);\n\t\tassert.equal(parseChain(\"only-one-step\").length, 1);\n\t});\n\n\tit(\"flags a chain step that does not exist on disk\", () => {\n\t\t// Simulate what the adapter does: build a fake chain value and\n\t\t// confirm we'd catch the missing file.\n\t\tconst fakeStep = \"p-does-not-exist\";\n\t\tconst steps = parseChain(`p-brainstorm -> ${fakeStep}`);\n\t\tassert.ok(steps.includes(fakeStep));\n\t\tassert.ok(\n\t\t\t!promptFiles.includes(join(PROMPTS_DIR, `${fakeStep}.md`)),\n\t\t\t\"sanity: the fake step should not exist on disk\",\n\t\t);\n\t});\n});\n\ndescribe(\"error cases: required keys\", () => {\n\tit(\"every chain recipe has a non-empty description\", () => {\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\tconst d = readChain(name).frontmatter.description;\n\t\t\tassert.ok(d && d.trim().length > 0, `${name} has empty description`);\n\t\t}\n\t});\n\n\tit(\"no p-* used in a chain is missing the subagent/fork flags\", () => {\n\t\t// This is the failure mode Doc/chain-commands.md calls out:\n\t\t// \"fork: true is required on each p-*.md. Check frontmatter.\"\n\t\tfor (const step of PROMPTS_USED_IN_CHAINS) {\n\t\t\tconst fm = readPrompt(step).frontmatter;\n\t\t\tassert.equal(fm.subagent, \"true\", `${step} missing subagent: true`);\n\t\t\tassert.equal(fm.fork, \"true\", `${step} missing fork: true`);\n\t\t}\n\t});\n});\n\ndescribe(\"error cases: cross-doc consistency\", () => {\n\t// These tests catch the realistic drift bug: someone adds a new chain\n\t// recipe and forgets to add a row to the table in the Doc page. The\n\t// table is the canonical description, so we look for a row, not just\n\t// any mention of the name (the docs also reference recipes in\n\t// `/prompt-workflow <name>` examples, which would mask a missing row).\n\t//\n\t// chain-commands.md table uses the form | `c-design-build.md` | ... |\n\t// prompts.md table uses the form | **`c-design-build`** | ... |\n\n\tit(\"Doc/chain-commands.md has a table row for every chain recipe\", () => {\n\t\tconst text = readUtf8(join(PROMPTS_DIR, \"Doc\", \"chain-commands.md\"));\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\t// The chain-commands.md table uses the full filename in\n\t\t\t// backticks (e.g. `c-design-build.md`).\n\t\t\tconst re = new RegExp(`^\\\\|\\\\s*\\`${name}\\`\\\\s*\\\\|`, \"m\");\n\t\t\tassert.ok(\n\t\t\t\tre.test(text),\n\t\t\t\t`Doc/chain-commands.md is missing a table row for ${name}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"Doc/chain-commands.md table rows show the actual chain sequence\", () => {\n\t\tconst text = readUtf8(join(PROMPTS_DIR, \"Doc\", \"chain-commands.md\"));\n\t\tfor (const [name, steps] of Object.entries(EXPECTED_CHAINS)) {\n\t\t\tconst re = new RegExp(`^\\\\|\\\\s*\\`${name}\\`\\\\s*\\\\|[^|]*\\\\|[^|]*\\\\|`, \"m\");\n\t\t\tconst row = text.match(re);\n\t\t\tassert.ok(row, `Doc/chain-commands.md is missing a row for ${name}`);\n\t\t\tconst rowAscii = row[0].replace(/→/g, \"->\");\n\t\t\tfor (const step of steps) {\n\t\t\t\tassert.ok(\n\t\t\t\t\trowAscii.includes(step),\n\t\t\t\t\t`Doc/chain-commands.md row for ${name} does not list ${step}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t});\n\n[93 more lines in file. Use offset=401 to continue.]"}],"isError":false,"timestamp":1784909449768}}
|
||
{"type":"message","id":"5fd34c84","parentId":"fc559748","timestamp":"2026-07-24T16:10:51.638Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Let me read the remaining tests.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:49","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/test/chain-workflow.test.ts","offset":401,"limit":200}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":92132,"output":50,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":92182,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909449770,"responseId":"chatcmpl-461","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"9eae0baf","parentId":"5fd34c84","timestamp":"2026-07-24T16:10:51.639Z","message":{"role":"toolResult","toolCallId":"functions.read:49","toolName":"read","content":[{"type":"text","text":"\n\tit(\"Doc/prompts.md has a table row for every chain recipe\", () => {\n\t\tconst text = readUtf8(join(PROMPTS_DIR, \"Doc\", \"prompts.md\"));\n\t\tfor (const name of Object.keys(EXPECTED_CHAINS)) {\n\t\t\t// The prompts.md table uses the base name in backticks\n\t\t\t// surrounded by `**` (e.g. `**`c-design-build`**`).\n\t\t\tconst base = name.replace(/\\.md$/, \"\");\n\t\t\tconst re = new RegExp(`^\\\\|\\\\s*\\\\*\\\\*\\`${base}\\`\\\\*\\\\*\\\\s*\\\\|`, \"m\");\n\t\t\tassert.ok(\n\t\t\t\tre.test(text),\n\t\t\t\t`Doc/prompts.md is missing a table row for ${base}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"Doc/prompts.md table rows show the actual chain sequence\", () => {\n\t\tconst text = readUtf8(join(PROMPTS_DIR, \"Doc\", \"prompts.md\"));\n\t\tfor (const [name, steps] of Object.entries(EXPECTED_CHAINS)) {\n\t\t\tconst base = name.replace(/\\.md$/, \"\");\n\t\t\tconst re = new RegExp(`^\\\\|\\\\s*\\\\*\\\\*\\`${base}\\`\\\\*\\\\*\\\\s*\\\\|[^|]*\\\\|`, \"m\");\n\t\t\tconst row = text.match(re);\n\t\t\tassert.ok(row, `Doc/prompts.md is missing a row for ${base}`);\n\t\t\tconst rowAscii = row[0].replace(/→/g, \"->\");\n\t\t\tfor (const step of steps) {\n\t\t\t\tassert.ok(\n\t\t\t\t\trowAscii.includes(step),\n\t\t\t\t\t`Doc/prompts.md row for ${base} does not list ${step}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"Doc/chain-commands.md documents ' -> ' as the chain separator\", () => {\n\t\tconst text = readUtf8(join(PROMPTS_DIR, \"Doc\", \"chain-commands.md\"));\n\t\tassert.ok(\n\t\t\ttext.includes(\"->\") || text.includes(\"→\"),\n\t\t\t\"Doc/chain-commands.md should describe the chain arrow separator\",\n\t\t);\n\t});\n\n\tit(\"Doc/prompts.md mentions every prompt used in any chain\", () => {\n\t\tconst text = readUtf8(join(PROMPTS_DIR, \"Doc\", \"prompts.md\"));\n\t\tfor (const step of PROMPTS_USED_IN_CHAINS) {\n\t\t\tassert.ok(\n\t\t\t\ttext.includes(step),\n\t\t\t\t`Doc/prompts.md does not mention prompt ${step}`,\n\t\t\t);\n\t\t}\n\t});\n});\n\n// ---------------------------------------------------------------------------\n// 5. Directory-level sanity — catches accidental deletions\n// ---------------------------------------------------------------------------\n\ndescribe(\"directory sanity\", () => {\n\tit(\"has at least one chain recipe\", () => {\n\t\tassert.ok(chainFiles.length > 0, \"no c-*.md files found\");\n\t});\n\n\tit(\"has at least one p-*.md prompt\", () => {\n\t\tassert.ok(promptFiles.length > 0, \"no p-*.md files found\");\n\t});\n\n\tit(\"has both Doc pages\", () => {\n\t\tassert.ok(docFiles.some((p) => p.endsWith(\"chain-commands.md\")));\n\t\tassert.ok(docFiles.some((p) => p.endsWith(\"prompts.md\")));\n\t});\n\n\tit(\"Doc/ has no extra markdown files we did not expect\", () => {\n\t\t// If a new doc page is added, the cross-doc tests above should\n\t\t// grow with it. Catches accidental orphans in the other direction.\n\t\tconst known = new Set([\"chain-commands.md\", \"prompts.md\"]);\n\t\tfor (const p of docFiles) {\n\t\t\tconst base = p.split(/[/\\\\]/).pop()!;\n\t\t\tassert.ok(known.has(base), `unexpected Doc file: ${base}`);\n\t\t}\n\t});\n\n\tit(\"every file in the prompts root is a recognized c-*, p-*, or Doc entry\", () => {\n\t\tconst entries = readdirSync(PROMPTS_DIR);\n\t\tconst allowed = (n: string) =>\n\t\t\tn.startsWith(\"c-\") || n.startsWith(\"p-\") || n === \"Doc\" || n === \"test\";\n\t\tfor (const e of entries) {\n\t\t\tif (e.startsWith(\".\")) continue; // .pi-subagents, etc.\n\t\t\tassert.ok(\n\t\t\t\tallowed(e),\n\t\t\t\t`unexpected top-level entry in prompts dir: ${e}`,\n\t\t\t);\n\t\t}\n\t});\n});\n"}],"isError":false,"timestamp":1784909451639}}
|
||
{"type":"message","id":"83a186dd","parentId":"9eae0baf","timestamp":"2026-07-24T16:11:27.859Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The tests are fairly specific. They check:\n- c-*.md table rows in chain-commands.md with filename in backticks.\n- c-*.md table rows in prompts.md with `**`c-name`**`.\n- Rows include the chain sequence (steps).\n- Body contains `$@`.\n- Description, argument-hint, chain fields.\n\nMy changes to the docs must preserve the table rows with the expected format and include the chain steps. The current docs already have this. I can modify surrounding text, but keep the table rows intact.\n\nAlso, the test checks `argument-hint` is wrapped in `[...]`. The current c-*.md have `argument-hint: \"[task or feature]\"`. Good.\n\nNow let me proceed to make the edits.\n\nI'll use the `edit` tool for the 4 c-*.md files, Doc/chain-commands.md, Doc/prompts.md, and `write` for the new agents/workflow-router.md (since the file doesn't exist).\n\nLet me draft each edit carefully.\n\n### c-design-build.md\n\nOld:\n```markdown\n---\ndescription: Brainstorm → plan → test → commit in one background chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n```\n\nNew:\n```markdown\n---\ndescription: Brainstorm → plan → test → commit in one chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-design-build \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-design-build --bg \"<task>\"\n```\n\nSimilarly for others, with appropriate descriptions.\n\n### c-fix-commit.md\n\nOld description: \"Summarize → diagnose → debug → test in one background chain\"\nNew: \"Summarize → diagnose → debug → test in one chain\"\n\nBody:\n```markdown\nRun the understand → diagnose → fix → regression-test chain for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-fix-commit \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-fix-commit --bg \"<task>\"\n```\n\n### c-refactor-commit.md\n\nOld: \"Refactor → test → review → commit in one background chain\"\nNew: \"Refactor → test → review → commit in one chain\"\n\nBody:\n```markdown\nRun the safe refactor → validate → review → commit chain for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-refactor-commit \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-refactor-commit --bg \"<task>\"\n```\n\n### c-security-loop.md\n\nOld: \"Security audit → review → test in one background chain\"\nNew: \"Security audit → review → test in one chain\"\n\nBody:\n```markdown\nRun the security-first review loop for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-security-loop \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-security-loop --bg \"<task>\"\n```\n\n### Doc/chain-commands.md\n\nCurrent relevant sections:\n\n\"## How to run a chain\"\n```markdown\nChains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit \"src/utils.ts\"\n/prompt-workflow c-security-loop \"auth endpoint\"\n```\n\nEach chain runs asynchronously by default. Check progress with:\n\n```text\n/subagents-fleet\n```\n\nor inspect a specific run with:\n\n```text\nsubagent({ action: \"status\" })\n```\n```\n\nI need to change this to foreground default. The code examples currently don't have `--bg` in the \"How to run a chain\" section, but earlier the user had them. Wait, looking at the current Doc/chain-commands.md, the examples do NOT have `--bg`. But the text says \"Each chain runs asynchronously by default.\" That's inconsistent. The actual c-*.md files had `--bg` in their examples. So the doc is already partly foreground in examples but text says async default.\n\nI should update the text to \"Each chain runs in the foreground by default; add `--bg` to run detached.\" and add a stop section.\n\nAlso, I should maybe add a section about the workflow-router agent.\n\nLet me rewrite the relevant part:\n\n```markdown\n## How to run a chain\n\nChains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit \"src/utils.ts\"\n/prompt-workflow c-security-loop \"auth endpoint\"\n```\n\nEach chain runs in the foreground by default. That means it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.\n\nAdd `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n```\n\nStop or inspect a background run:\n\n```text\n/subagents-fleet # live inspector\n/subagents-stop <run-id> # kill a specific run\nsubagent({ action: \"stop\", id: \"<run-id>\" })\n```\n\nYou can also inspect a specific run with:\n\n```text\nsubagent({ action: \"status\" })\n```\n```\n\nI also need to keep the table rows intact. The table is:\n\n```markdown\n| Command file | Sequence | Use it when |\n|---|---|---|\n| `c-design-build.md` | `p-brainstorm → p-plan → p-test → p-commit` | ... |\n...\n```\n\nI will keep the table as is, or maybe update the descriptions. But the tests check the table rows include the steps. I should not change the step sequences.\n\nActually, the table rows can be updated, but the format must remain: `| `c-design-build.md` | `p-brainstorm → ...` | ... |`. The tests use regex `^\\|\\s*`c-design-build.md`\\s*\\|` and check the row includes each step. So I can change the last column (Use it when) but keep the first two columns. I'll keep them mostly the same.\n\nI might also add a section about the workflow-router agent.\n\n### Doc/prompts.md\n\nUpdate the chain recipes section to remove `--bg` from examples and note foreground default.\n\nCurrent:\n```markdown\nInvoke a chain with `/prompt-workflow`, not `/c-recipe`:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n/prompt-workflow c-security-loop --bg \"auth endpoint\"\n```\n\nEach chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n```\n\nChange to:\n```markdown\nInvoke a chain with `/prompt-workflow`, not `/c-recipe`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit \"src/utils.ts\"\n/prompt-workflow c-security-loop \"auth endpoint\"\n```\n\nEach chain runs in the foreground by default, so you can stop it with `Esc` or `Ctrl+C`. Add `--bg` to detach it; then watch with `/subagents-fleet`, stop with `/subagents-stop <id>`, or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n```\n\nKeep the table rows intact (they are tested).\n\n### agents/workflow-router.md\n\nCreate new file.\n\nI want to make this robust. Let me think about the prompt carefully.\n\nThe router will be invoked as a subagent with a task. It needs to:\n1. Choose the best c-* chain based on the task.\n2. Read the c-*.md to get the chain list.\n3. Read each p-*.md to get the body.\n4. Call `subagent({ chain: [...], async: false })` with delegate steps.\n\nBut there's a problem: the p-*.md files have frontmatter. The body starts after `---`. The router needs to extract the body and substitute `$@` with the task.\n\nThe router can do this as an LLM. The prompt will instruct it. But to make it reliable, maybe I should include the actual mappings in the router prompt rather than relying on reading files? That way it doesn't need to parse frontmatter. But if the user changes the p-* prompts later, the router would be stale. Reading is better.\n\nActually, the p-*.md files are simple; the frontmatter is small. The LLM can read them and use the body. I'll instruct it to ignore frontmatter and use the body after the second `---`.\n\nBut the router is an LLM subagent; it might not follow instructions perfectly. However, this is a reasonable design.\n\nAlternatively, I can make the router prompt include the exact body of each p-* prompt inline, but that's long and duplicates content. Not ideal.\n\nAnother approach: the router can just output the chain name, and then a parent-level wrapper (like a slash command or a parent prompt) runs `/prompt-workflow`. But the user chose subagent router.\n\nWait, maybe the simplest robust design is: the router subagent picks the best c-* recipe and returns the recommended `/prompt-workflow` command. Then the user (or parent) runs it. This is less automatic but more reliable. However, the user wants automatic.\n\nI think I can combine: the router picks, reads the p-* files, and runs the chain via `subagent`. I'll write clear instructions and include examples.\n\nLet me draft `agents/workflow-router.md`:\n\n```yaml\n---\nname: workflow-router\ndescription: Pick the best c-* chain for a task and run it in the foreground\ntools: read, subagent\nsystemPromptMode: append\ninheritProjectContext: true\ninheritSkills: false\n---\n\nYou are a workflow router. Given the user's task, choose and execute the single most appropriate c-* chain from `~/.pi/agent/prompts/`.\n\nAvailable chains:\n\n| Chain | Steps | Use it when |\n|---|---|---|\n| `c-design-build` | p-brainstorm → p-plan → p-test → p-commit | Designing or adding a new feature from a vague requirement. |\n| `c-fix-commit` | p-summarize → p-diagnose → p-debug → p-test | A bug, failure, error, or regression. |\n| `c-refactor-commit` | p-refactor → p-test → p-review → p-commit | Restructuring existing code without changing behavior. |\n| `c-security-loop` | p-secaudit → p-review → p-test | Auth, input handling, secrets, network, deserialization, or trust boundaries. |\n\nSteps:\n1. Decide which chain is the best fit for: {task}\n2. Read the selected `~/.pi/agent/prompts/c-<name>.md` file and note the `chain:` frontmatter value.\n3. For each `p-*.md` step in that chain, read `~/.pi/agent/prompts/<step>.md`, ignore its frontmatter, and take the body text (everything after the second `---`).\n4. Run the chain with the `subagent` tool:\n - `async: false` so the user can stop it with `Esc`/`Ctrl+C`.\n - Each step uses `agent: \"delegate\"`.\n - The step `task` is the prompt body with `$@` replaced by the user's original task.\n - Use `label` and `phase` for readability.\n5. Report which chain you chose and why.\n\nDo not ask the user before running. Pick exactly one chain and execute it. If the task truly does not fit any chain, run `c-design-build` as the safest default.\n```\n\nThis looks good. But the `{task}` variable - does the subagent tool substitute `{task}`? Yes, chain variables include `{task}`. But this is in the system prompt, not in a chain task. The router receives the task as its initial prompt. The `{task}` here is just a placeholder in the system prompt. The LLM will see the actual task in the conversation. So it's fine.\n\nActually, I should use `{{task}}` or just say \"the user's task\" to avoid confusion with chain variables. I'll use \"the user's task\" instead of `{task}`.\n\nAlso, I should mention that the router can use `contact_supervisor` if it needs a decision, but it shouldn't. Actually, with `tools: read, subagent`, it doesn't have `contact_supervisor`. The delegate agent has it. But the router doesn't need it.\n\nWait, `tools: read, subagent` means the router only has those two tools. The `subagent` tool is child-safe. Good.\n\nNow, one issue: the router will be a subagent with `tools: subagent`. But child subagents by default do not receive the `subagent` tool unless their resolved `tools` includes `subagent`. The frontmatter `tools: read, subagent` should grant it. Good.\n\nBut will the router be able to run `subagent` with `async: false`? The `subagent` tool in a child should support the same params. The skill says \"child-safe `subagent` tool for the fanout work the parent assigned.\" It should support chain, async, etc.\n\nAlso, the `delegate` agent is a builtin. It will be available.\n\nOK, let me make the edits.\n\nBut first, I should consider whether to also update the tests. My changes don't require test updates because they preserve the tested properties. But adding `agents/workflow-router.md` is in a different directory, so the prompt dir tests won't be affected. Good.\n\nNow, one more thing: the user also asked about \"an automatic tool that would just use whatever subagent or prompt is the most fitting\". My router agent is exactly that. I should mention it in the final response.\n\nLet me now execute the edits. I'll do multiple edits in one call for the 4 c-*.md files. But since they are separate files, I need separate edit calls (one per file). The `edit` tool takes one path and multiple edits. So I'll make 4 edit calls.\n\nThen edit Doc/chain-commands.md and Doc/prompts.md.\n\nThen write agents/workflow-router.md.\n\nAfter edits, run the tests to verify.\n\nLet me proceed.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.edit:50","name":"edit","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md","edits":[{"newText":"---\ndescription: Brainstorm → plan → test → commit in one chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-design-build \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-design-build --bg \"<task>\"","oldText":"---\ndescription: Brainstorm → plan → test → commit in one background chain\nargument-hint: \"[task or feature]\"\nchain: p-brainstorm -> p-plan -> p-test -> p-commit\n---\nRun the design → plan → test → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\""}]}},{"type":"toolCall","id":"functions.edit:51","name":"edit","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md","edits":[{"newText":"---\ndescription: Summarize → diagnose → debug → test in one chain\nargument-hint: \"[symptom, error, or observed behavior]\"\nchain: p-summarize -> p-diagnose -> p-debug -> p-test\n---\nRun the understand → diagnose → fix → regression-test chain for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-fix-commit \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-fix-commit --bg \"<task>\"","oldText":"---\ndescription: Summarize → diagnose → debug → test in one background chain\nargument-hint: \"[symptom, error, or observed behavior]\"\nchain: p-summarize -> p-diagnose -> p-debug -> p-test\n---\nRun the understand → diagnose → fix → regression-test chain for: $@\n\nInvoke with:\n/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\""}]}},{"type":"toolCall","id":"functions.edit:52","name":"edit","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md","edits":[{"newText":"---\ndescription: Refactor → test → review → commit in one chain\nargument-hint: \"[file path or symbol to refactor]\"\nchain: p-refactor -> p-test -> p-review -> p-commit\n---\nRun the safe refactor → validate → review → commit chain for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-refactor-commit \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-refactor-commit --bg \"<task>\"","oldText":"---\ndescription: Refactor → test → review → commit in one background chain\nargument-hint: \"[file path or symbol to refactor]\"\nchain: p-refactor -> p-test -> p-review -> p-commit\n---\nRun the safe refactor → validate → review → commit chain for: $@\n\nInvoke with:\n/prompt-workflow c-refactor-commit --bg \"src/utils.ts\""}]}},{"type":"toolCall","id":"functions.edit:53","name":"edit","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md","edits":[{"newText":"---\ndescription: Security audit → review → test in one chain\nargument-hint: \"[file path, diff, or feature to audit]\"\nchain: p-secaudit -> p-review -> p-test\n---\nRun the security-first review loop for: $@\n\nRun in the current Pi session (foreground, stop with Esc/Ctrl+C):\n/prompt-workflow c-security-loop \"<task>\"\n\nRun detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n/prompt-workflow c-security-loop --bg \"<task>\"","oldText":"---\ndescription: Security audit → review → test in one background chain\nargument-hint: \"[file path, diff, or feature to audit]\"\nchain: p-secaudit -> p-review -> p-test\n---\nRun the security-first review loop for: $@\n\nInvoke with:\n/prompt-workflow c-security-loop --bg \"auth endpoint\""}]}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":93125,"output":4431,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":97556,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909451641,"responseId":"chatcmpl-349","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"fddad5ed","parentId":"83a186dd","timestamp":"2026-07-24T16:11:27.876Z","message":{"role":"toolResult","toolCallId":"functions.edit:50","toolName":"edit","content":[{"type":"text","text":"Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md."}],"details":{"diff":" 1 ---\n- 2 description: Brainstorm → plan → test → commit in one background chain\n+ 2 description: Brainstorm → plan → test → commit in one chain\n 3 argument-hint: \"[task or feature]\"\n 4 chain: p-brainstorm -> p-plan -> p-test -> p-commit\n 5 ---\n 6 Run the design → plan → test → commit chain for: $@\n 7 \n- 8 Invoke with:\n- 9 /prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+ 9 /prompt-workflow c-design-build \"<task>\"\n+10 \n+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+12 /prompt-workflow c-design-build --bg \"<task>\"","patch":"--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md\n+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-design-build.md\n@@ -1,9 +1,12 @@\n ---\n-description: Brainstorm → plan → test → commit in one background chain\n+description: Brainstorm → plan → test → commit in one chain\n argument-hint: \"[task or feature]\"\n chain: p-brainstorm -> p-plan -> p-test -> p-commit\n ---\n Run the design → plan → test → commit chain for: $@\n \n-Invoke with:\n-/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+/prompt-workflow c-design-build \"<task>\"\n+\n+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+/prompt-workflow c-design-build --bg \"<task>\"\n","firstChangedLine":2},"isError":false,"timestamp":1784909487876}}
|
||
{"type":"message","id":"4503a437","parentId":"fddad5ed","timestamp":"2026-07-24T16:11:27.876Z","message":{"role":"toolResult","toolCallId":"functions.edit:51","toolName":"edit","content":[{"type":"text","text":"Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md."}],"details":{"diff":" 1 ---\n- 2 description: Summarize → diagnose → debug → test in one background chain\n+ 2 description: Summarize → diagnose → debug → test in one chain\n 3 argument-hint: \"[symptom, error, or observed behavior]\"\n 4 chain: p-summarize -> p-diagnose -> p-debug -> p-test\n 5 ---\n 6 Run the understand → diagnose → fix → regression-test chain for: $@\n 7 \n- 8 Invoke with:\n- 9 /prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+ 9 /prompt-workflow c-fix-commit \"<task>\"\n+10 \n+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+12 /prompt-workflow c-fix-commit --bg \"<task>\"","patch":"--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md\n+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-fix-commit.md\n@@ -1,9 +1,12 @@\n ---\n-description: Summarize → diagnose → debug → test in one background chain\n+description: Summarize → diagnose → debug → test in one chain\n argument-hint: \"[symptom, error, or observed behavior]\"\n chain: p-summarize -> p-diagnose -> p-debug -> p-test\n ---\n Run the understand → diagnose → fix → regression-test chain for: $@\n \n-Invoke with:\n-/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+/prompt-workflow c-fix-commit \"<task>\"\n+\n+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+/prompt-workflow c-fix-commit --bg \"<task>\"\n","firstChangedLine":2},"isError":false,"timestamp":1784909487876}}
|
||
{"type":"message","id":"5f62765e","parentId":"4503a437","timestamp":"2026-07-24T16:11:27.876Z","message":{"role":"toolResult","toolCallId":"functions.edit:52","toolName":"edit","content":[{"type":"text","text":"Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md."}],"details":{"diff":" 1 ---\n- 2 description: Refactor → test → review → commit in one background chain\n+ 2 description: Refactor → test → review → commit in one chain\n 3 argument-hint: \"[file path or symbol to refactor]\"\n 4 chain: p-refactor -> p-test -> p-review -> p-commit\n 5 ---\n 6 Run the safe refactor → validate → review → commit chain for: $@\n 7 \n- 8 Invoke with:\n- 9 /prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+ 9 /prompt-workflow c-refactor-commit \"<task>\"\n+10 \n+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+12 /prompt-workflow c-refactor-commit --bg \"<task>\"","patch":"--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md\n+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-refactor-commit.md\n@@ -1,9 +1,12 @@\n ---\n-description: Refactor → test → review → commit in one background chain\n+description: Refactor → test → review → commit in one chain\n argument-hint: \"[file path or symbol to refactor]\"\n chain: p-refactor -> p-test -> p-review -> p-commit\n ---\n Run the safe refactor → validate → review → commit chain for: $@\n \n-Invoke with:\n-/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+/prompt-workflow c-refactor-commit \"<task>\"\n+\n+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+/prompt-workflow c-refactor-commit --bg \"<task>\"\n","firstChangedLine":2},"isError":false,"timestamp":1784909487876}}
|
||
{"type":"message","id":"df354d62","parentId":"5f62765e","timestamp":"2026-07-24T16:11:27.876Z","message":{"role":"toolResult","toolCallId":"functions.edit:53","toolName":"edit","content":[{"type":"text","text":"Successfully replaced 1 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md."}],"details":{"diff":" 1 ---\n- 2 description: Security audit → review → test in one background chain\n+ 2 description: Security audit → review → test in one chain\n 3 argument-hint: \"[file path, diff, or feature to audit]\"\n 4 chain: p-secaudit -> p-review -> p-test\n 5 ---\n 6 Run the security-first review loop for: $@\n 7 \n- 8 Invoke with:\n- 9 /prompt-workflow c-security-loop --bg \"auth endpoint\"\n+ 8 Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+ 9 /prompt-workflow c-security-loop \"<task>\"\n+10 \n+11 Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+12 /prompt-workflow c-security-loop --bg \"<task>\"","patch":"--- /home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md\n+++ /home/liph/dotfiles/pi/.pi/agent/prompts/c-security-loop.md\n@@ -1,9 +1,12 @@\n ---\n-description: Security audit → review → test in one background chain\n+description: Security audit → review → test in one chain\n argument-hint: \"[file path, diff, or feature to audit]\"\n chain: p-secaudit -> p-review -> p-test\n ---\n Run the security-first review loop for: $@\n \n-Invoke with:\n-/prompt-workflow c-security-loop --bg \"auth endpoint\"\n+Run in the current Pi session (foreground, stop with Esc/Ctrl+C):\n+/prompt-workflow c-security-loop \"<task>\"\n+\n+Run detached in the background (inspect with /subagents-fleet, stop with /subagents-stop <id>):\n+/prompt-workflow c-security-loop --bg \"<task>\"\n","firstChangedLine":2},"isError":false,"timestamp":1784909487876}}
|
||
{"type":"message","id":"ee0bd2f3","parentId":"df354d62","timestamp":"2026-07-24T16:11:29.548Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Good. Now edit Doc/chain-commands.md. I need to preserve the table rows. Let me read it again to make precise edits.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:54","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":97827,"output":64,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":97891,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909487878,"responseId":"chatcmpl-344","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"1973f726","parentId":"ee0bd2f3","timestamp":"2026-07-24T16:11:29.549Z","message":{"role":"toolResult","toolCallId":"functions.read:54","toolName":"read","content":[{"type":"text","text":"# Chain Commands Reference\n\nThis file documents how to invoke the `c-*` chain recipes defined in `~/.pi/agent/prompts/`.\n\n## What the chains are\n\nThe `c-*` files are orchestration recipes. They do not contain new prompts; they reuse the existing `p-*` prompts and run them in sequence through the `pi-subagents` prompt-workflow adapter. Each step is executed as a forked-context subagent, so later steps can see the outputs from earlier steps.\n\n## Available chains\n\n| Command file | Sequence | Use it when |\n|---|---|---|\n| `c-design-build.md` | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |\n| `c-fix-commit.md` | `p-summarize → p-diagnose → p-debug → p-test` | You need to understand a bug, diagnose it, fix it, and add regression tests. |\n| `c-refactor-commit.md` | `p-refactor → p-test → p-review → p-commit` | You want a safe refactor with tests, review, and a commit. |\n| `c-security-loop.md` | `p-secaudit → p-review → p-test` | You need a security-first review plus tests before proceeding. |\n\n## How to run a chain\n\nChains are not invoked with `/c-...` in the editor, because normal slash expansion just pastes the file body into the chat. Instead, run them through the `pi-subagents` adapter with `/prompt-workflow`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit \"src/utils.ts\"\n/prompt-workflow c-security-loop \"auth endpoint\"\n```\n\nEach chain runs asynchronously by default. Check progress with:\n\n```text\n/subagents-fleet\n```\n\nor inspect a specific run with:\n\n```text\nsubagent({ action: \"status\" })\n```\n\n## Ad-hoc chains\n\nYou can also run the same sequence on the fly without creating a recipe file:\n\n```text\n/chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- \"add a rate-limiter\"\n/chain-prompts p-summarize -> p-diagnose -> p-debug -> p-test -- \"intermittent timeout\"\n/chain-prompts p-refactor -> p-test -> p-review -> p-commit -- \"src/utils.ts\"\n/chain-prompts p-secaudit -> p-review -> p-test -- \"auth endpoint\"\n```\n\nUse `--bg` or `--async` to detach an ad-hoc chain:\n\n```text\n/chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- \"src/utils.ts\"\n```\n\n## Why individual prompts are the subagents\n\nOnly the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:\n\n1. It sees the `chain:` frontmatter.\n2. It resolves each named step to a `p-*.md` file.\n3. It runs that prompt as a forked-context subagent (`delegate` by default).\n4. The output of each step is passed to the next step via the chain runner.\n\nThis keeps the chain recipes small and the individual prompts reusable as both standalone slash templates and chain steps.\n\n## Context flow\n\nBecause each `p-*` step uses `fork: true`, every subagent inherits the parent session history. That means later steps naturally see what earlier steps produced, without needing explicit `{previous}` placeholders inside the prompt bodies.\n\nThe trade-off is higher per-step context usage. If token cost becomes an issue, a future migration could switch the `p-*` prompts to `fresh: true` and introduce explicit `{previous}` handling inside their bodies.\n\n## Troubleshooting\n\n| Symptom | What to check |\n|---|---|\n| `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |\n| Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |\n| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |\n| Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |\n"}],"isError":false,"timestamp":1784909489549}}
|
||
{"type":"message","id":"df50eec0","parentId":"1973f726","timestamp":"2026-07-24T16:11:36.870Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"I need to update:\n1. The \"How to run a chain\" section to foreground default and add stop commands.\n2. The troubleshooting row \"Chain does not run in background\" should be updated because the new default is foreground. Maybe change to \"Chain does not detach\" or keep it.\n3. Add a section about workflow-router.\n\nLet me make the edits. I'll replace the \"How to run a chain\" section and the troubleshooting row, and add a router section.\n\nActually, the troubleshooting row \"Chain does not run in background\" says \"Confirm the recipe has async: true in frontmatter, or add --bg to the command.\" This is still valid if someone wants background. But the title is misleading. I can change it to \"Chain does not detach / run in background\".\n\nAlso, I should add a section about workflow-router agent. Maybe \"## Automatic routing\" after \"Ad-hoc chains\".\n\nLet me write the edits.\n\nFor \"How to run a chain\":\nReplace from \"Each chain runs asynchronously by default...\" to the end of that paragraph with new text.\n\nFor troubleshooting row:\nReplace \"Chain does not run in background\" with \"Want the chain to run in background\".\n\nAdd new section after \"Ad-hoc chains\" about workflow-router.\n\nLet me do the edits.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.edit:55","name":"edit","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md","edits":[{"newText":"Each chain runs in the foreground by default, so it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.\n\nAdd `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs in the background:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n```\n\nStop or inspect a background run:\n\n```text\n/subagents-fleet # live inspector (Ctrl+Alt+F also opens it)\n/subagents-stop <run-id> # kill a specific run\nsubagent({ action: \"stop\", id: \"<run-id>\" })\n```\n\nInspect any run (foreground or background):\n\n```text\nsubagent({ action: \"status\" })\n```","oldText":"Each chain runs asynchronously by default. Check progress with:\n\n```text\n/subagents-fleet\n```\n\nor inspect a specific run with:\n\n```text\nsubagent({ action: \"status\" })\n```"},{"newText":"## Automatic routing\n\nIf you don't want to pick the recipe manually, use the `workflow-router` agent:\n\n```text\n/run workflow-router \"add a rate-limiter to the API\"\n```\n\nThe router reads the task, chooses the best `c-*` chain, and runs it in the foreground (`async: false`) so you can stop it with `Esc`/`Ctrl+C`. It dispatches through the `subagent` tool using the same `p-*` prompt bodies the chain recipes use.\n\nYou can also invoke it from another agent or prompt:\n\n```text\nsubagent({ agent: \"workflow-router\", task: \"the checkout intermittently times out\" })\n```\n\n## Why individual prompts are the subagents","oldText":"## Why individual prompts are the subagents"},{"newText":"| Want the chain to run in background | Add `--bg` or `--async` to the `/prompt-workflow` command. |","oldText":"| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |"}]}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":98871,"output":795,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":99666,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909489551,"responseId":"chatcmpl-89","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"3abc640b","parentId":"df50eec0","timestamp":"2026-07-24T16:11:36.882Z","message":{"role":"toolResult","toolCallId":"functions.edit:55","toolName":"edit","content":[{"type":"text","text":"Successfully replaced 3 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md."}],"details":{"diff":" ...\n 25 /prompt-workflow c-refactor-commit \"src/utils.ts\"\n 26 /prompt-workflow c-security-loop \"auth endpoint\"\n 27 ```\n 28 \n- 29 Each chain runs asynchronously by default. Check progress with:\n+ 29 Each chain runs in the foreground by default, so it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.\n 30 \n+ 31 Add `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs in the background:\n+ 32 \n 31 ```text\n- 32 /subagents-fleet\n+ 34 /prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n 33 ```\n 34 \n- 35 or inspect a specific run with:\n+ 37 Stop or inspect a background run:\n 36 \n 37 ```text\n+ 40 /subagents-fleet # live inspector (Ctrl+Alt+F also opens it)\n+ 41 /subagents-stop <run-id> # kill a specific run\n+ 42 subagent({ action: \"stop\", id: \"<run-id>\" })\n+ 43 ```\n+ 44 \n+ 45 Inspect any run (foreground or background):\n+ 46 \n+ 47 ```text\n 38 subagent({ action: \"status\" })\n 39 ```\n 40 \n 41 ## Ad-hoc chains\n ...\n 54 ```text\n 55 /chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- \"src/utils.ts\"\n 56 ```\n 57 \n+ 68 ## Automatic routing\n+ 69 \n+ 70 If you don't want to pick the recipe manually, use the `workflow-router` agent:\n+ 71 \n+ 72 ```text\n+ 73 /run workflow-router \"add a rate-limiter to the API\"\n+ 74 ```\n+ 75 \n+ 76 The router reads the task, chooses the best `c-*` chain, and runs it in the foreground (`async: false`) so you can stop it with `Esc`/`Ctrl+C`. It dispatches through the `subagent` tool using the same `p-*` prompt bodies the chain recipes use.\n+ 77 \n+ 78 You can also invoke it from another agent or prompt:\n+ 79 \n+ 80 ```text\n+ 81 subagent({ agent: \"workflow-router\", task: \"the checkout intermittently times out\" })\n+ 82 ```\n+ 83 \n 58 ## Why individual prompts are the subagents\n 59 \n 60 Only the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:\n 61 \n ...\n 77 | Symptom | What to check |\n 78 |---|---|\n 79 | `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |\n 80 | Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |\n- 81 | Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |\n+107 | Want the chain to run in background | Add `--bg` or `--async` to the `/prompt-workflow` command. |\n 82 | Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |","patch":"--- /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md\n+++ /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/chain-commands.md\n@@ -25,17 +25,27 @@\n /prompt-workflow c-refactor-commit \"src/utils.ts\"\n /prompt-workflow c-security-loop \"auth endpoint\"\n ```\n \n-Each chain runs asynchronously by default. Check progress with:\n+Each chain runs in the foreground by default, so it stays in the current Pi session and you can cancel the current turn with `Esc` or `Ctrl+C`.\n \n+Add `--bg` (or `--async`) to detach the chain and keep working in the main chat while it runs in the background:\n+\n ```text\n-/subagents-fleet\n+/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n ```\n \n-or inspect a specific run with:\n+Stop or inspect a background run:\n \n ```text\n+/subagents-fleet # live inspector (Ctrl+Alt+F also opens it)\n+/subagents-stop <run-id> # kill a specific run\n+subagent({ action: \"stop\", id: \"<run-id>\" })\n+```\n+\n+Inspect any run (foreground or background):\n+\n+```text\n subagent({ action: \"status\" })\n ```\n \n ## Ad-hoc chains\n@@ -54,8 +64,24 @@\n ```text\n /chain-prompts p-refactor -> p-test -> p-review -> p-commit --bg -- \"src/utils.ts\"\n ```\n \n+## Automatic routing\n+\n+If you don't want to pick the recipe manually, use the `workflow-router` agent:\n+\n+```text\n+/run workflow-router \"add a rate-limiter to the API\"\n+```\n+\n+The router reads the task, chooses the best `c-*` chain, and runs it in the foreground (`async: false`) so you can stop it with `Esc`/`Ctrl+C`. It dispatches through the `subagent` tool using the same `p-*` prompt bodies the chain recipes use.\n+\n+You can also invoke it from another agent or prompt:\n+\n+```text\n+subagent({ agent: \"workflow-router\", task: \"the checkout intermittently times out\" })\n+```\n+\n ## Why individual prompts are the subagents\n \n Only the `p-*.md` files are marked with `subagent: true` and `fork: true`. The `c-*.md` recipe files are pure wrappers. When `/prompt-workflow` loads a recipe:\n \n@@ -77,6 +103,6 @@\n | Symptom | What to check |\n |---|---|\n | `/c-design-build` just pastes text | Use `/prompt-workflow c-design-build ...` instead. |\n | Chain step fails with “Unknown prompt workflow” | Run `/reload`, then `/prompt-workflow list` and confirm each `p-*` in the chain appears. |\n-| Chain does not run in background | Confirm the recipe has `async: true` in frontmatter, or add `--bg` to the command. |\n+| Want the chain to run in background | Add `--bg` or `--async` to the `/prompt-workflow` command. |\n | Steps seem disconnected | `fork: true` is required on each `p-*.md`. Check frontmatter. |\n","firstChangedLine":29},"isError":false,"timestamp":1784909496882}}
|
||
{"type":"message","id":"ffc378fd","parentId":"3abc640b","timestamp":"2026-07-24T16:11:38.486Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now edit Doc/prompts.md. Let me read it again to find the exact text to replace.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:56","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/Doc/prompts.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":99712,"output":55,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":99767,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909496884,"responseId":"chatcmpl-218","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"e29180d1","parentId":"ffc378fd","timestamp":"2026-07-24T16:11:38.487Z","message":{"role":"toolResult","toolCallId":"functions.read:56","toolName":"read","content":[{"type":"text","text":"# Prompts\n\nSlash-style prompts for the interactive pi session. Each file is a `p-<verb>.md` template with a frontmatter `description` + `argument-hint` and a structured body. Invoke with `:p-<verb> [arg]` or via the `:prompts` TUI picker.\n\n## When to use which\n\n| Prompt | Use it when… | Pairs well with |\n| ------------------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| **`p-plan`** | You're about to start a non-trivial change and want a structured plan before coding. | `p-brainstorm` (first), then `p-refactor` / `p-test` |\n| **`p-brainstorm`** | You have a problem but no chosen approach yet; want 3–5 alternatives with trade-offs. | `p-plan` (after picking one) |\n| **`p-explain`** | You don't understand a piece of code, a concept, or an error message. | `p-debug` / `p-diagnose` (if it's a problem) |\n| **`p-debug`** | A test, build, or command is failing with a clear error. You have the error in hand. | `p-test` (add a regression test after the fix) |\n| **`p-diagnose`** | Nothing is \"failing\" but behavior is wrong — wrong values, races, perf drift, \"passes locally, broken in prod.\" | `p-debug` (if you find a hard failure) |\n| **`p-review`** | You want a code review of a diff, file, or staged change. General quality feedback. | `p-secaudit` (security subset) |\n| **`p-secaudit`** | Touching auth, input handling, secrets, network, deserialization, or any trust boundary. | `p-review` (broader quality), `p-test` |\n| **`p-refactor`** | Restructuring code without changing behavior. Safety-first, mechanical steps. | `p-test` (first, as the safety net), `p-review` (after) |\n| **`p-test`** | You need to write or expand tests for existing or new code. | `p-debug` (after a failure), `p-refactor` (before) |\n| **`p-doc`** | Writing or improving README, docstrings, JSDoc, godoc, or ADRs. | `p-summarize` (skim the code first) |\n| **`p-commit`** | About to commit. You want a conventional message and (optionally) a PR description. | `p-review` (final check before committing) |\n| **`p-summarize`** | A file, log, diff, or document is too long to read in full. You need the gist + key details. | `p-plan` / `p-debug` (then dive into specifics) |\n\n## Decision flow\n\n```\nGot an idea or vague problem?\n└─ Yes → p-brainstorm → pick an approach → p-plan → implement\n └─ p-test → p-commit\nTouching existing code that needs to change?\n└─ p-refactor (after p-test confirms a safety net) → p-review → p-commit\nSomething is broken?\n├─ Hard failure (error message, failing test) → p-debug\n└─ Soft failure (wrong output, race, perf) → p-diagnose\n → fix → p-test (regression) → p-commit\nTouching a trust boundary, auth, secrets, or untrusted input?\n└─ p-secaudit (then p-review for general quality)\nNeed to understand a long file/log/diff quickly?\n└─ p-summarize\nNeed to write or update docs?\n└─ p-doc\nDon't know what something does or what an error means?\n└─ p-explain\n```\n\n## Chain recipes\n\nThe `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default.\n\n| Recipe | Sequence | Use it when… |\n| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------- |\n| **`c-design-build`** | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |\n| **`c-fix-commit`** | `p-summarize → p-diagnose → p-debug → p-test` | You need to understand a bug, diagnose it, fix it, and add regression tests. |\n| **`c-refactor-commit`** | `p-refactor → p-test → p-review → p-commit` | You want a safe refactor with tests, review, and a commit. |\n| **`c-security-loop`** | `p-secaudit → p-review → p-test` | You need a security-first review plus tests before proceeding. |\n\nInvoke a chain with `/prompt-workflow`, not `/c-recipe`:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n/prompt-workflow c-security-loop --bg \"auth endpoint\"\n```\n\nEach chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n\n```text\n/chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- \"add a rate-limiter\"\n```\n\n## Conventions\n\n- Every prompt uses `$@` for the user-supplied argument. Pass an argument at invocation time; if the request is under-specified, the prompt will ask clarifying questions.\n- Output is structured (numbered sections, fixed categories) so the result is diff-friendly and skim-friendly.\n- Prompts intentionally do **not** overlap with subagent workflows (`agents/`, `chains/`, `skills/`) — those are for orchestration; these are for interactive turns.\n- Prefer one prompt per turn. Chain them yourself (`p-brainstorm` → `p-plan` → `p-refactor`) rather than asking one prompt to do everything.\n"}],"isError":false,"timestamp":1784909498487}}
|
||
{"type":"message","id":"fc53e84e","parentId":"e29180d1","timestamp":"2026-07-24T16:11:43.901Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"I need to update:\n1. \"Chains run asynchronously by default\" to foreground.\n2. The examples to remove `--bg`.\n3. The text after examples to mention foreground/background.\n4. Optionally add a note about workflow-router.\n\nI must preserve the table rows. The table is fine. I'll only change the surrounding text.\n\nLet me make the edits.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.edit:57","name":"edit","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/Doc/prompts.md","edits":[{"newText":"The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run in the foreground by default (stop with `Esc`/`Ctrl+C`); add `--bg` to detach them.","oldText":"The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default."},{"newText":"Invoke a chain with `/prompt-workflow`, not `/c-recipe`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit \"src/utils.ts\"\n/prompt-workflow c-security-loop \"auth endpoint\"\n```\n\nAdd `--bg` to run detached; then watch with `/subagents-fleet`, stop with `/subagents-stop <id>`, or check status with `subagent({ action: \"status\" })`. To let the agent pick the chain for you, use `/run workflow-router \"<task>\"`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:","oldText":"Invoke a chain with `/prompt-workflow`, not `/c-recipe`:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n/prompt-workflow c-security-loop --bg \"auth endpoint\"\n```\n\nEach chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:"}]}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":101193,"output":614,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":101807,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909498489,"responseId":"chatcmpl-983","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"90d269a0","parentId":"fc53e84e","timestamp":"2026-07-24T16:11:43.911Z","message":{"role":"toolResult","toolCallId":"functions.edit:57","toolName":"edit","content":[{"type":"text","text":"Successfully replaced 2 block(s) in /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/prompts.md."}],"details":{"diff":" ...\n 42 ```\n 43 \n 44 ## Chain recipes\n 45 \n-46 The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default.\n+46 The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run in the foreground by default (stop with `Esc`/`Ctrl+C`); add `--bg` to detach them.\n 47 \n 48 | Recipe | Sequence | Use it when… |\n 49 | ------------------ | ----------------------------------------- | -------------------------------------------------------------------------- |\n 50 | **`c-design-build`** | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |\n ...\n 54 \n 55 Invoke a chain with `/prompt-workflow`, not `/c-recipe`:\n 56 \n 57 ```text\n-58 /prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n-59 /prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n-60 /prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n-61 /prompt-workflow c-security-loop --bg \"auth endpoint\"\n+58 /prompt-workflow c-design-build \"add a rate-limiter to the API\"\n+59 /prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n+60 /prompt-workflow c-refactor-commit \"src/utils.ts\"\n+61 /prompt-workflow c-security-loop \"auth endpoint\"\n 62 ```\n 63 \n-64 Each chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n+64 Add `--bg` to run detached; then watch with `/subagents-fleet`, stop with `/subagents-stop <id>`, or check status with `subagent({ action: \"status\" })`. To let the agent pick the chain for you, use `/run workflow-router \"<task>\"`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n 65 \n 66 ```text\n 67 /chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- \"add a rate-limiter\"\n 68 ```\n ...","patch":"--- /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/prompts.md\n+++ /home/liph/dotfiles/pi/.pi/agent/prompts/Doc/prompts.md\n@@ -42,9 +42,9 @@\n ```\n \n ## Chain recipes\n \n-The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run asynchronously by default.\n+The `c-*` files are not prompts you run directly in the editor. They are orchestration recipes that run a sequence of `p-*` prompts through the `pi-subagents` prompt-workflow adapter. Each `p-*` step is executed as a forked-context subagent, so later steps can see earlier outputs. Chains run in the foreground by default (stop with `Esc`/`Ctrl+C`); add `--bg` to detach them.\n \n | Recipe | Sequence | Use it when… |\n | ------------------ | ----------------------------------------- | -------------------------------------------------------------------------- |\n | **`c-design-build`** | `p-brainstorm → p-plan → p-test → p-commit` | You want to design a feature, plan it, add tests, and commit in one go. |\n@@ -54,15 +54,15 @@\n \n Invoke a chain with `/prompt-workflow`, not `/c-recipe`:\n \n ```text\n-/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n-/prompt-workflow c-fix-commit --bg \"the checkout intermittently times out\"\n-/prompt-workflow c-refactor-commit --bg \"src/utils.ts\"\n-/prompt-workflow c-security-loop --bg \"auth endpoint\"\n+/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n+/prompt-workflow c-fix-commit \"the checkout intermittently times out\"\n+/prompt-workflow c-refactor-commit \"src/utils.ts\"\n+/prompt-workflow c-security-loop \"auth endpoint\"\n ```\n \n-Each chain runs in the background. Watch it with `/subagents-fleet` or check status with `subagent({ action: \"status\" })`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n+Add `--bg` to run detached; then watch with `/subagents-fleet`, stop with `/subagents-stop <id>`, or check status with `subagent({ action: \"status\" })`. To let the agent pick the chain for you, use `/run workflow-router \"<task>\"`. If you want to run the same sequence ad-hoc, use `/chain-prompts`:\n \n ```text\n /chain-prompts p-brainstorm -> p-plan -> p-test -> p-commit -- \"add a rate-limiter\"\n ```\n","firstChangedLine":46},"isError":false,"timestamp":1784909503911}}
|
||
{"type":"message","id":"29d0d8db","parentId":"90d269a0","timestamp":"2026-07-24T16:11:46.146Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now create the agents directory and workflow-router.md file.\n\nI need to create `/home/liph/dotfiles/pi/.pi/agent/agents/workflow-router.md`.\n\nBut wait, the directory already exists at `/home/liph/.pi/agent/agents/` and is empty. The dotfiles path is `/home/liph/dotfiles/pi/.pi/agent/agents/`. I should create it.\n\nLet me check if the dotfiles path exists.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:58","name":"bash","arguments":{"command":"ls -la /home/liph/dotfiles/pi/.pi/agent/"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":101852,"output":121,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":101973,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909503912,"responseId":"chatcmpl-98","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"64a16442","parentId":"29d0d8db","timestamp":"2026-07-24T16:11:46.161Z","message":{"role":"toolResult","toolCallId":"functions.bash:58","toolName":"bash","content":[{"type":"text","text":"total 68\ndrwxr-xr-x 11 liph liph 4096 Jul 24 18:08 .\ndrwxr-xr-x 6 liph liph 4096 Jul 23 20:54 ..\ndrwxr-xr-x 2 liph liph 4096 Jul 24 17:23 agents\n-rw-r--r-- 1 liph liph 121 Jul 21 21:24 auth.json\ndrwxr-xr-x 4 liph liph 4096 Jul 24 08:22 extensions\n-rw-r--r-- 1 liph liph 1345 Jul 22 12:50 models.json\ndrwxr-xr-x 3 liph liph 4096 Jul 21 21:26 npm\ndrwxr-xr-x 2 liph liph 4096 Jul 23 20:51 profiles\ndrwxr-xr-x 5 liph liph 4096 Jul 24 18:02 prompts\n-rw-r--r-- 1 liph liph 4863 Jul 24 17:47 run-history.jsonl\ndrwxr-xr-x 21 liph liph 4096 Jul 24 16:47 sessions\n-rw-r--r-- 1 liph liph 1452 Jul 24 16:28 settings.json\ndrwxr-xr-x 2 liph liph 4096 Jul 24 09:36 skills\ndrwxr-xr-x 2 liph liph 4096 Jul 23 20:34 state\ndrwxr-xr-x 2 liph liph 4096 Jul 24 08:34 themes\n-rw-r--r-- 1 liph liph 25 Jul 22 12:50 trust.json\n"}],"isError":false,"timestamp":1784909506161}}
|
||
{"type":"message","id":"cde13acf","parentId":"64a16442","timestamp":"2026-07-24T16:11:51.762Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The dotfiles path `/home/liph/dotfiles/pi/.pi/agent/agents/` exists. Good. I'll write `workflow-router.md` there.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.write:59","name":"write","arguments":{"content":"---\nname: workflow-router\ndescription: Pick the best c-* chain for a task and run it in the foreground\ntools: read, subagent\nsystemPromptMode: append\ninheritProjectContext: true\ninheritSkills: false\n---\n\nYou are a workflow router. Given the user's task, choose and execute the single most appropriate `c-*` chain from `~/.pi/agent/prompts/`.\n\nAvailable chains:\n\n| Chain | Steps | Use it when |\n|---|---|---|\n| `c-design-build` | `p-brainstorm → p-plan → p-test → p-commit` | Designing or adding a new feature from a vague requirement. |\n| `c-fix-commit` | `p-summarize → p-diagnose → p-debug → p-test` | A bug, failure, error, or regression. |\n| `c-refactor-commit` | `p-refactor → p-test → p-review → p-commit` | Restructuring existing code without changing behavior. |\n| `c-security-loop` | `p-secaudit → p-review → p-test` | Auth, input handling, secrets, network, deserialization, or trust boundaries. |\n\nSteps:\n1. Decide which chain is the best fit for the user's task.\n2. Read `~/.pi/agent/prompts/c-<name>.md` and note the `chain:` frontmatter value.\n3. For each `p-*.md` step in that chain, read `~/.pi/agent/prompts/<step>.md`, ignore its frontmatter, and use the body text (everything after the second `---`).\n4. Run the chain with the `subagent` tool:\n - Set `async: false` so the user can stop it with `Esc` or `Ctrl+C`.\n - Each step uses `agent: \"delegate\"`.\n - The step `task` is the prompt body with `$@` replaced by the user's original task.\n - Use `label` and `phase` for readable status output.\n5. Report which chain you chose and why.\n\nDo not ask the user before running. Pick exactly one chain and execute it. If the task truly does not fit any chain, default to `c-design-build`.\n","path":"/home/liph/dotfiles/pi/.pi/agent/agents/workflow-router.md"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":102397,"output":556,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":102953,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909506163,"responseId":"chatcmpl-29","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"d1b6a298","parentId":"cde13acf","timestamp":"2026-07-24T16:11:51.764Z","message":{"role":"toolResult","toolCallId":"functions.write:59","toolName":"write","content":[{"type":"text","text":"Successfully wrote 1709 bytes to /home/liph/dotfiles/pi/.pi/agent/agents/workflow-router.md"}],"isError":false,"timestamp":1784909511764}}
|
||
{"type":"message","id":"601e5d97","parentId":"d1b6a298","timestamp":"2026-07-24T16:11:53.786Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"Now run the tests to make sure the changes don't break anything.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:60","name":"bash","arguments":{"command":"cd /home/liph/dotfiles/pi/.pi/agent/prompts && npm test 2>&1 | tail -80"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":103001,"output":55,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":103056,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909511766,"responseId":"chatcmpl-892","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"ceb41d92","parentId":"601e5d97","timestamp":"2026-07-24T16:11:53.922Z","message":{"role":"toolResult","toolCallId":"functions.bash:60","toolName":"bash","content":[{"type":"text","text":"npm error Missing script: \"test\"\nnpm error\nnpm error To see a list of scripts, run:\nnpm error npm run\nnpm error A complete log of this run can be found in: /home/liph/.npm/_logs/2026-07-24T16_11_53_858Z-debug-0.log\n"}],"isError":false,"timestamp":1784909513922}}
|
||
{"type":"message","id":"ebe0b65c","parentId":"ceb41d92","timestamp":"2026-07-24T16:11:56.024Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The package.json doesn't have a \"test\" script at the top level? Let me check the test directory's package.json.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.read:61","name":"read","arguments":{"path":"/home/liph/dotfiles/pi/.pi/agent/prompts/test/package.json"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":103153,"output":56,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":103209,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909513925,"responseId":"chatcmpl-477","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"f5dbe786","parentId":"ebe0b65c","timestamp":"2026-07-24T16:11:56.027Z","message":{"role":"toolResult","toolCallId":"functions.read:61","toolName":"read","content":[{"type":"text","text":"{\n \"name\": \"pi-prompt-workflows-tests\",\n \"private\": true,\n \"type\": \"module\",\n \"description\": \"Static tests for the .pi/agent/prompts c-* and p-* workflow chain.\",\n \"scripts\": {\n \"test\": \"node --test --experimental-strip-types test/chain-workflow.test.ts\",\n \"test:file\": \"node --test --experimental-strip-types test/chain-workflow.test.ts\"\n }\n}\n"}],"isError":false,"timestamp":1784909516027}}
|
||
{"type":"message","id":"511fee58","parentId":"f5dbe786","timestamp":"2026-07-24T16:11:58.088Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The test script is in test/package.json. I need to run it from the test directory.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:62","name":"bash","arguments":{"command":"cd /home/liph/dotfiles/pi/.pi/agent/prompts/test && npm test 2>&1 | tail -100"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":103324,"output":72,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":103396,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909516029,"responseId":"chatcmpl-446","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"ce696f79","parentId":"511fee58","timestamp":"2026-07-24T16:11:58.239Z","message":{"role":"toolResult","toolCallId":"functions.bash:62","toolName":"bash","content":[{"type":"text","text":"npm notice run test\nnpm notice run node --test --experimental-strip-types test/chain-workflow.test.ts\nCould not find 'test/chain-workflow.test.ts'\n"}],"isError":false,"timestamp":1784909518239}}
|
||
{"type":"message","id":"daf79ba8","parentId":"ce696f79","timestamp":"2026-07-24T16:12:01.852Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"The script has a wrong path? It says `node --test --experimental-strip-types test/chain-workflow.test.ts`. When run from the `test` directory, it looks for `test/test/chain-workflow.test.ts`. So the script is meant to be run from the parent prompts directory. Let me run from the prompts dir using the test/package.json? Actually `npm test` from test dir uses the script which is wrong. Maybe the script should be `node --test --experimental-strip-types chain-workflow.test.ts`. Let me just run it manually.","thinkingSignature":"reasoning"},{"type":"toolCall","id":"functions.bash:63","name":"bash","arguments":{"command":"cd /home/liph/dotfiles/pi/.pi/agent/prompts/test && node --test --experimental-strip-types chain-workflow.test.ts 2>&1 | tail -100"}}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":103448,"output":178,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":103626,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"toolUse","timestamp":1784909518242,"responseId":"chatcmpl-734","responseModel":"kimi-k2.7-code"}}
|
||
{"type":"message","id":"c4e05ed9","parentId":"daf79ba8","timestamp":"2026-07-24T16:12:02.061Z","message":{"role":"toolResult","toolCallId":"functions.bash:63","toolName":"bash","content":[{"type":"text","text":" ✔ c-security-loop.md.chain parses to p-secaudit -> p-review -> p-test (0.113006ms)\n ✔ c-security-loop.md contains a $@ placeholder for the user argument (0.100224ms)\n✔ happy path: chain recipes are present and well-formed (2.677991ms)\n▶ happy path: every prompt step resolves to a real file\n ✔ step p-brainstorm exists as a p-*.md file (0.180754ms)\n ✔ step p-plan exists as a p-*.md file (0.055804ms)\n ✔ step p-test exists as a p-*.md file (0.052312ms)\n ✔ step p-commit exists as a p-*.md file (0.067817ms)\n ✔ step p-summarize exists as a p-*.md file (0.051823ms)\n ✔ step p-diagnose exists as a p-*.md file (0.068307ms)\n ✔ step p-debug exists as a p-*.md file (0.067189ms)\n ✔ step p-refactor exists as a p-*.md file (0.063837ms)\n ✔ step p-review exists as a p-*.md file (0.061532ms)\n ✔ step p-secaudit exists as a p-*.md file (0.061322ms)\n✔ happy path: every prompt step resolves to a real file (1.096465ms)\n▶ happy path: every p-*.md has the required chain-step shape\n ✔ p-brainstorm declares subagent: true (0.444272ms)\n ✔ p-brainstorm declares fork: true (0.765479ms)\n ✔ p-brainstorm has description and argument-hint (0.146042ms)\n ✔ p-brainstorm body references $@ (0.175236ms)\n ✔ p-plan declares subagent: true (0.117057ms)\n ✔ p-plan declares fork: true (0.101551ms)\n ✔ p-plan has description and argument-hint (0.091285ms)\n ✔ p-plan body references $@ (0.086676ms)\n ✔ p-test declares subagent: true (0.102809ms)\n ✔ p-test declares fork: true (0.101901ms)\n ✔ p-test has description and argument-hint (0.10665ms)\n ✔ p-test body references $@ (0.096313ms)\n ✔ p-commit declares subagent: true (0.082974ms)\n ✔ p-commit declares fork: true (0.080529ms)\n ✔ p-commit has description and argument-hint (0.081646ms)\n ✔ p-commit body references $@ (0.092403ms)\n ✔ p-summarize declares subagent: true (0.122015ms)\n ✔ p-summarize declares fork: true (0.096104ms)\n ✔ p-summarize has description and argument-hint (0.093939ms)\n ✔ p-summarize body references $@ (0.102948ms)\n ✔ p-diagnose declares subagent: true (0.088212ms)\n ✔ p-diagnose declares fork: true (0.08863ms)\n ✔ p-diagnose has description and argument-hint (0.096244ms)\n ✔ p-diagnose body references $@ (0.143038ms)\n ✔ p-debug declares subagent: true (0.116638ms)\n ✔ p-debug declares fork: true (0.116219ms)\n ✔ p-debug has description and argument-hint (0.104904ms)\n ✔ p-debug body references $@ (0.084301ms)\n ✔ p-refactor declares subagent: true (0.07969ms)\n ✔ p-refactor declares fork: true (0.079551ms)\n ✔ p-refactor has description and argument-hint (0.081507ms)\n ✔ p-refactor body references $@ (0.082066ms)\n ✔ p-review declares subagent: true (0.080041ms)\n ✔ p-review declares fork: true (0.090796ms)\n ✔ p-review has description and argument-hint (0.08919ms)\n ✔ p-review body references $@ (0.088421ms)\n ✔ p-secaudit declares subagent: true (0.094917ms)\n ✔ p-secaudit declares fork: true (0.122505ms)\n ✔ p-secaudit has description and argument-hint (0.09338ms)\n ✔ p-secaudit body references $@ (0.090377ms)\n✔ happy path: every p-*.md has the required chain-step shape (6.03709ms)\n▶ edge cases: chain format boundaries\n ✔ every chain has at least one step (0.304725ms)\n ✔ no chain has a duplicate step (0.279652ms)\n ✔ every chain step is lowercase kebab-case starting with 'p-' (0.401667ms)\n ✔ chain frontmatter uses ' -> ' (single space) and not '->' or ' - >' (0.333849ms)\n ✔ every chain ends with a real prompt file, not a typo (0.258629ms)\n✔ edge cases: chain format boundaries (1.76598ms)\n▶ edge cases: argument-hint style\n ✔ every argument-hint is non-empty (0.566916ms)\n ✔ argument-hints are wrapped in [...] to match the documented convention (1.186353ms)\n✔ edge cases: argument-hint style (1.845671ms)\n▶ error cases: malformed frontmatter\n ✔ rejects a chain file with no closing fence (0.11126ms)\n ✔ rejects a chain value with no separator at all (0.085278ms)\n ✔ flags a chain step that does not exist on disk (0.083812ms)\n✔ error cases: malformed frontmatter (0.380226ms)\n▶ error cases: required keys\n ✔ every chain recipe has a non-empty description (0.233904ms)\n ✔ no p-* used in a chain is missing the subagent/fork flags (0.368212ms)\n✔ error cases: required keys (0.684811ms)\n▶ error cases: cross-doc consistency\n ✔ Doc/chain-commands.md has a table row for every chain recipe (0.339856ms)\n ✔ Doc/chain-commands.md table rows show the actual chain sequence (0.649889ms)\n ✔ Doc/prompts.md has a table row for every chain recipe (0.324351ms)\n ✔ Doc/prompts.md table rows show the actual chain sequence (0.421084ms)\n ✔ Doc/chain-commands.md documents ' -> ' as the chain separator (0.106092ms)\n ✔ Doc/prompts.md mentions every prompt used in any chain (0.114263ms)\n✔ error cases: cross-doc consistency (2.242869ms)\n▶ directory sanity\n ✔ has at least one chain recipe (0.087722ms)\n ✔ has at least one p-*.md prompt (0.057271ms)\n ✔ has both Doc pages (0.092332ms)\n ✔ Doc/ has no extra markdown files we did not expect (0.136334ms)\n ✔ every file in the prompts root is a recognized c-*, p-*, or Doc entry (0.165667ms)\n✔ directory sanity (0.669446ms)\nℹ tests 100\nℹ suites 11\nℹ pass 100\nℹ fail 0\nℹ cancelled 0\nℹ skipped 0\nℹ todo 0\nℹ duration_ms 160.816963\n"}],"isError":false,"timestamp":1784909522061}}
|
||
{"type":"message","id":"4eaee73d","parentId":"c4e05ed9","timestamp":"2026-07-24T16:12:08.783Z","message":{"role":"assistant","content":[{"type":"thinking","thinking":"All 100 tests pass. Great.\n\nNow I should provide a final summary to the user. I should also mention that the test package.json script path seems wrong (it expects test/chain-workflow.test.ts but should be chain-workflow.test.ts). Actually, maybe I should not mention it unless they care. But since I noticed it, I could offer to fix it. It's a small thing. But it's not related to their question. I'll leave it unless they ask.\n\nLet me write a concise final response summarizing what I changed and how to use it.","thinkingSignature":"reasoning"},{"type":"text","text":"Done. I updated your dotfiles to make the chains foreground-by-default and added an automatic router agent. All 100 existing tests still pass.\n\n### What changed\n\n**`c-*.md` recipes** — removed the hardcoded `--bg` from the examples. They now show:\n- foreground invocation first (`/prompt-workflow c-design-build \"<task>\"`), so `Esc`/`Ctrl+C` stops it\n- `--bg` as an optional detach flag, with `/subagents-fleet` and `/subagents-stop <id>` documented\n\n**`Doc/chain-commands.md`** — rewritten to foreground-by-default, added the stop commands, and added an \"Automatic routing\" section.\n\n**`Doc/prompts.md`** — examples now omit `--bg`, text explains foreground default + optional detach.\n\n**`~/.pi/agent/agents/workflow-router.md`** (new) — a subagent with `tools: read, subagent` that picks the best `c-*` chain for a task and dispatches it with `async: false`.\n\n### How to use it now\n\nRun a chain in the current session, stoppable with `Esc`/`Ctrl+C`:\n\n```text\n/prompt-workflow c-design-build \"add a rate-limiter to the API\"\n```\n\nLet the agent pick and run the chain for you:\n\n```text\n/run workflow-router \"add a rate-limiter to the API\"\n```\n\nor from another prompt/agent:\n\n```text\nsubagent({ agent: \"workflow-router\", task: \"the checkout intermittently times out\" })\n```\n\nDetach a chain when you want it to run in the background:\n\n```text\n/prompt-workflow c-design-build --bg \"add a rate-limiter to the API\"\n/subagents-fleet\n/subagents-stop <run-id>\n```\n\nIf you're currently invoking these from a shell alias that uses `pi -p`, change the alias to start an interactive session or remove it and run the command inside an already-open Pi session."}],"api":"openai-completions","provider":"ollama","model":"kimi-k2.7-code:cloud","usage":{"input":105368,"output":522,"cacheRead":0,"cacheWrite":0,"reasoning":0,"totalTokens":105890,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"stop","timestamp":1784909522064,"responseId":"chatcmpl-985","responseModel":"kimi-k2.7-code"}}
|