
Pi Agent
- 329 installs
- 32.7k repo stars
- Updated August 3, 2026
- k-dense-ai/scientific-agent-skills
Helps with ai & agent building tasks.
About
pi-agent is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- pi-agent
- AI & Agent Building
- AI-coding skill
Pi Agent by the numbers
- 329 all-time installs (skills.sh)
- +41 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #2,183 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/k-dense-ai/scientific-agent-skills --skill pi-agentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 329 |
|---|---|
| repo stars | ★ 32.7k |
| Last updated | August 3, 2026 |
| Repository | k-dense-ai/scientific-agent-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Pi Agent
Use this skill when the user wants to operate Pi or build on top of Pi. Pi is a minimal terminal coding harness extended through TypeScript extensions, skills, prompt templates, themes, packages, custom models/providers, SDK integrations, RPC mode, JSON event streams, and TUI components.
First Decision
Pick the reference before answering or coding:
| User intent | Read |
|---|---|
| Install, authenticate, first run | references/quickstart.md |
| Day-to-day CLI usage, commands, modes, flags | references/usage.md |
| Provider auth, API keys, cloud provider setup | references/providers.md |
| Custom model entries, local models, proxies | references/models.md |
| Extension development, custom tools, events, commands | references/extensions.md |
| Custom provider implementation, OAuth, custom streaming | references/custom-provider.md |
| Embed Pi in Node/TypeScript | references/sdk.md |
| Integrate from another process/language | references/rpc.md |
| Consume JSONL event output | references/json.md |
| Build terminal UI components | references/tui.md |
| Package extensions/skills/prompts/themes | references/packages.md |
| Delegate to subagents, chains, parallel runs, orchestration | references/pi-subagents.md |
| Connect MCP servers, MCP tool discovery/config | references/pi-mcp-adapter.md |
| Interactive interview forms, structured user input | references/pi-interview.md |
| Web search, URL/PDF/repo fetching, video understanding | references/pi-web-access.md |
| Author Pi skills | references/skills.md |
| Prompt templates or themes | references/prompt-templates.md, references/themes.md |
| Sessions, branching, compaction, parsing JSONL | references/sessions.md, references/compaction.md, references/session-format.md |
| Security, sandboxing, trust | references/security.md, references/containerization.md |
| Keyboard or terminal issues | references/keybindings.md, references/terminal-setup.md, references/tmux.md, references/windows.md, references/termux.md, references/shell-aliases.md |
| Working on Pi itself | references/development.md |
Build-On-Pi Defaults
Prefer the SDK for Node/TypeScript apps that need type safety, direct state access, in-process custom tools/extensions, or custom resource loading. Use createAgentSession() for a single stable session; use createAgentSessionRuntime() when the app must replace sessions through new/resume/fork/clone/import flows.
Prefer RPC mode when the client is not Node.js, needs process isolation, or wants a language-agnostic JSONL protocol. Start with pi --mode rpc --no-session for stateless subprocess integration, then add session flags when persistence matters.
Prefer JSON mode for one-shot command-line pipelines that only need streamed events, not bidirectional control: pi --mode json "prompt".
Use extensions for Pi-native behavior: custom tools, command handlers, event hooks, provider registration, custom compaction, path protection, project trust policy, UI prompts, widgets, and TUI components.
Use packages when sharing or installing reusable extensions, skills, prompt templates, or themes across machines or projects.
Safety Defaults
Pi is local and not sandboxed by default. Treat extensions, packages, skills, shell commands, and project-local .pi resources as code with the permissions of the Pi process. For untrusted repos or unattended automation, isolate with Docker, OpenShell, Gondolin, a VM, or a remote sandbox.
Do not store secrets in project files. Prefer env vars, ~/.pi/agent/auth.json, OAuth via /login, or command-backed secret lookups in models.json/provider config.
Common Commands
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi
pi -p "Summarize this codebase"
pi --mode json "List files"
pi --mode rpc --no-session
pi --provider anthropic --model claude-sonnet-4-5
pi --tools read,grep,find,ls -p "Review this repository"Source Coverage
These references summarize the Pi documentation at https://pi.dev/docs/latest and each docs page found under it as of this skill version, plus the package pages for pi-subagents, pi-mcp-adapter, pi-interview, and pi-web-access at https://pi.dev/packages/. When exact API behavior matters, prefer the cited reference page and inspect installed TypeScript definitions under node_modules/@earendil-works/pi-coding-agent/dist/ and node_modules/@earendil-works/pi-ai/dist/.
Compaction and Branch Summarization
Source: https://pi.dev/docs/latest/compaction
Pi uses compaction to summarize older content when context grows too long, and branch summarization to preserve context when changing branches.
Mechanisms
| Mechanism | Trigger | Purpose |
|---|---|---|
| Compaction | context exceeds threshold or /compact | Summarize old messages to free context |
| Branch summarization | /tree navigation | Preserve context when switching branches |
Auto-Compaction
Triggers when:
contextTokens > contextWindow - reserveTokensDefaults: reserveTokens 16384, keepRecentTokens 20000. Configure under compaction in settings.
Compaction finds a cut point, summarizes old messages, appends a CompactionEntry, then reloads session context as summary plus kept messages.
Valid cut points: user messages, assistant messages, bash execution messages, and custom messages. Pi never cuts at tool results.
Split Turns
If one turn exceeds keepRecentTokens, Pi may cut mid-turn at an assistant message, generate a history summary plus turn-prefix summary, and merge them.
Entry Shapes
CompactionEntry contains type, id, parentId, timestamp, summary, firstKeptEntryId, tokensBefore, optional fromHook, and optional details.
BranchSummaryEntry contains type, id, parentId, timestamp, summary, fromId, optional fromHook, and optional details.
Default details track readFiles and modifiedFiles; extensions may store JSON-serializable custom details.
Extension Hooks
session_before_compact can cancel or provide custom compaction. Convert messages with convertToLlm() and serializeConversation() when using a custom summarizer.
session_before_tree can cancel navigation or provide a custom branch summary when the user chose to summarize.
Settings
{
"compaction": {
"enabled": true,
"reserveTokens": 16384,
"keepRecentTokens": 20000
}
}Containerization
Source: https://pi.dev/docs/latest/containerization
Pi runs with all permissions by default. Isolation patterns either run the whole Pi process inside a boundary or run Pi on the host while routing tools into a boundary.
Patterns
- OpenShell: whole Pi process inside policy-controlled sandbox; best for local or remote managed sandboxing.
- Gondolin extension: host Pi with built-in tools and
!commands routed into a local Linux micro-VM. - Plain Docker: whole Pi process in a local container.
Extensions run wherever the Pi process runs. If host Pi routes built-ins into a VM, other extension tools still run on host unless they delegate too.
OpenShell
openshell gateway add <gateway-url> --name <name>
openshell gateway select <name>
openshell sandbox create --name pi-sandbox --from pi -- piRemote gateways do not bind-mount local project files automatically. Upload/download project files explicitly. OpenShell can also route inference so raw provider keys stay outside the sandbox.
Gondolin
cp -R packages/coding-agent/examples/extensions/gondolin ~/.pi/agent/extensions/gondolin
cd ~/.pi/agent/extensions/gondolin
npm install --ignore-scripts
cd /path/to/project
pi -e ~/.pi/agent/extensions/gondolinThe extension mounts host cwd at /workspace in the VM and overrides read, write, edit, bash, grep, find, and ls. Writes under /workspace write through to the host. Requires Node.js >= 23.6.0 and QEMU.
Docker
FROM node:24-bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends bash ca-certificates git ripgrep && rm -rf /var/lib/apt/lists/*
RUN npm install -g --ignore-scripts @earendil-works/pi-coding-agent
WORKDIR /workspace
ENTRYPOINT ["pi"]docker build -t pi-sandbox -f Dockerfile.pi .
docker run --rm -it -e ANTHROPIC_API_KEY -v "$PWD:/workspace" -v pi-agent-home:/root/.pi/agent pi-sandboxMounting host ~/.pi/agent exposes host auth and session files. Use a named volume for container-local settings and sessions.
Custom Providers
Source: https://pi.dev/docs/latest/custom-provider
Extensions can register providers with pi.registerProvider() for proxies, private deployments, OAuth/SSO, and non-standard streaming APIs.
Quick Reference
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
export default function (pi: ExtensionAPI) {
pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
pi.registerProvider("my-provider", {
name: "My Provider",
baseUrl: "https://api.example.com",
apiKey: "$MY_API_KEY",
api: "openai-completions",
models: [{
id: "my-model",
name: "My Model",
reasoning: false,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128000,
maxTokens: 4096
}]
});
}Use an async extension factory for dynamic model discovery so models are available during startup and pi --list-models.
Overrides and New Providers
When only baseUrl and/or headers are provided, existing models for a built-in provider are preserved. When models is provided, it replaces dynamic models for that provider.
pi.unregisterProvider(name) removes dynamic models, API key fallback, OAuth registration, and custom stream handlers, restoring built-in behavior where relevant.
API Types
Common values: anthropic-messages, openai-completions, openai-responses, azure-openai-responses, openai-codex-responses, mistral-conversations, google-generative-ai, google-vertex, bedrock-converse-stream.
Most OpenAI-compatible providers work with openai-completions; use compat for quirks and thinkingLevelMap for model-specific thinking levels.
Auth Header and Secrets
Set authHeader: true to add Authorization: Bearer <apiKey>. apiKey and custom header values use !command, $ENV, ${ENV}, $$, and $! resolution like models.json.
OAuth
Register oauth with login(callbacks), refreshToken(credentials), getApiKey(credentials), and optional modifyModels(models, credentials). Credentials persist in ~/.pi/agent/auth.json with refresh, access, and expires fields. Users authenticate with /login provider-name.
Callbacks include onAuth, onDeviceCode, onPrompt, and onSelect.
Custom Streaming
For non-standard APIs, implement streamSimple(model, context, options). Create an AssistantMessage, push { type: "start", partial }, push content events as data arrives, then push { type: "done", reason, message } or { type: "error", reason, error }, and end the stream.
Content events include text_start, text_delta, text_end, thinking_start, thinking_delta, thinking_end, toolcall_start, toolcall_delta, and toolcall_end. Keep partial updated with the current assistant message state.
For tool calls, accumulate JSON deltas, parse into { id, name, arguments }, and end with toolcall_end.
Testing
Test provider registration with pi --list-models, authenticate through /login or env vars, run a simple prompt, then exercise tools, thinking levels, image input, cache behavior, retry behavior, and context overflow errors.
Development
Source: https://pi.dev/docs/latest/development
Use this when working on Pi itself.
Setup
git clone https://github.com/earendil-works/pi-mono
cd pi-mono
npm install
npm run buildRun from source:
/path/to/pi-mono/pi-test.shThe script can be run from any directory and preserves the caller's cwd.
Forking and Rebranding
Configure package.json:
{
"piConfig": {
"name": "pi",
"configDir": ".pi"
}
}Change name, configDir, and bin for a fork. This affects CLI banner, config paths, and environment variable names.
Path Resolution
Pi has npm install, standalone binary, and tsx-from-source execution modes. Always use src/config.ts helpers such as getPackageDir and getThemeDir for package assets. Do not use __dirname directly for assets.
Debugging and Tests
/debug writes rendered TUI lines and last LLM messages to ~/.pi/agent/pi-debug.log.
./test.sh
npm test
npm test -- test/specific.test.tsProject Structure
packages/
ai/ # LLM provider abstraction
agent/ # Agent loop and message types
tui/ # Terminal UI components
coding-agent/ # CLI and interactive modeExtensions
Source: https://pi.dev/docs/latest/extensions
Extensions are TypeScript modules that extend Pi. They can register tools, commands, shortcuts, flags, custom providers, UI, event handlers, and persistent session entries.
Locations
~/.pi/agent/extensions/*.ts~/.pi/agent/extensions/*/index.ts.pi/extensions/*.ts.pi/extensions/*/index.ts- Paths from settings or packages
Project-local extensions load only after project trust. Use pi -e ./my-extension.ts for quick tests. Auto-discovered extensions can be hot-reloaded with /reload.
Quick Extension
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";
export default function (pi: ExtensionAPI) {
pi.on("session_start", async (_event, ctx) => {
ctx.ui.notify("Extension loaded", "info");
});
pi.on("tool_call", async (event, ctx) => {
if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
const ok = await ctx.ui.confirm("Dangerous", "Allow rm -rf?");
if (!ok) return { block: true, reason: "Blocked by user" };
}
});
pi.registerTool({
name: "greet",
label: "Greet",
description: "Greet someone by name",
parameters: Type.Object({ name: Type.String() }),
async execute(_toolCallId, params) {
return { content: [{ type: "text", text: `Hello, ${params.name}!` }], details: {} };
},
});
pi.registerCommand("hello", {
description: "Say hello",
handler: async (args, ctx) => ctx.ui.notify(`Hello ${args || "world"}`, "info"),
});
}Imports
@earendil-works/pi-coding-agent: extension types and APIs.typebox: schemas for tool parameters.@earendil-works/pi-ai: AI utilities.@earendil-works/pi-tui: TUI components.
Runtime dependencies for distributed packages belong in dependencies; package installs use production installs by default.
Event Flow
Startup: project_trust, session_start, resources_discover.
Prompt: extension commands, input, skill/template expansion, before_agent_start, agent_start, message events, turn events, provider request/response hooks, tool events, agent_end.
Session changes: session_before_switch, session_shutdown, session_start, resources_discover. Fork/clone use session_before_fork.
Compaction/tree: session_before_compact, session_compact, session_before_tree, session_tree.
Model changes: model_select, thinking_level_select.
Shutdown: session_shutdown.
High-Value Hooks
project_trust: user/global or CLI extensions can decide project trust.resources_discover: contribute skill, prompt, and theme paths.before_agent_start: inject custom messages or modify the system prompt.context: non-destructively modify messages before each LLM call.before_provider_request: inspect/replace provider payload for debugging or compatibility.after_provider_response: inspect status/headers before streaming body is consumed.tool_call: block or mutate tool inputs before execution.tool_result: modify tool results.message_end: replace finalized message while preserving role.
Runtime Notes
Extension factories may be async; Pi awaits them before startup continues. Use async factories for startup-only work such as dynamic model discovery. In RPC or JSON/print mode, guard TUI-specific UI with ctx.mode === "tui" and check ctx.hasUI before prompting.
JSON Event Stream Mode
Source: https://pi.dev/docs/latest/json
Use JSON mode for one-shot prompts that output all session events as JSON lines to stdout.
pi --mode json "Your prompt"Event Types
AgentSessionEvent includes base agent events plus queue, compaction, and retry events:
agent_start,agent_endturn_start,turn_endmessage_start,message_update,message_endtool_execution_start,tool_execution_update,tool_execution_endqueue_updatecompaction_start,compaction_endauto_retry_start,auto_retry_end
queue_update emits full pending steering and follow-up queues. Compaction events cover manual and automatic compaction.
Output Format
First line is the session header:
{"type":"session","version":3,"id":"uuid","timestamp":"...","cwd":"/path"}Subsequent lines are events:
{"type":"agent_start"}
{"type":"turn_start"}
{"type":"message_update","message":{},"assistantMessageEvent":{"type":"text_delta","delta":"Hello"}}
{"type":"agent_end","messages":[]}Example
pi --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'For bidirectional control, use RPC instead of JSON mode.
Keybindings
Source: https://pi.dev/docs/latest/keybindings
All shortcuts can be customized in ~/.pi/agent/keybindings.json. Run /reload after editing.
Key Format
Use modifier+key; modifiers are ctrl, shift, and alt. Keys include letters, digits, special keys, function keys, and symbols.
Common Defaults
Editor movement: arrows, Ctrl+B/F, Alt+Left/Right, Ctrl+A/E, PageUp/PageDown.
Deletion: Backspace, Delete/Ctrl+D, Ctrl+W, Alt+Backspace, Alt+D, Ctrl+U, Ctrl+K.
Input: tui.input.submit is Enter, tui.input.newLine is Shift+Enter, tui.input.tab is Tab.
Application: Escape interrupts, Ctrl+C clears editor/copies selection depending context, Ctrl+D exits when editor empty, Ctrl+G opens external editor, Ctrl+V/Alt+V pastes image.
Models: Ctrl+L opens model selector, Ctrl+P cycles forward, Shift+Ctrl+P cycles backward, Shift+Tab cycles thinking level, Ctrl+T toggles thinking block display.
Messages: Ctrl+O expands tools, Alt+Enter queues follow-up, Alt+Up retrieves queued messages.
Custom Config
{
"tui.editor.cursorUp": ["up", "ctrl+p"],
"tui.editor.cursorDown": ["down", "ctrl+n"],
"tui.editor.deleteWordBackward": ["ctrl+w", "alt+backspace"]
}User config overrides defaults. Native Windows has no default app.suspend binding; WSL uses normal Unix Ctrl+Z/fg behavior.
Custom Models
Source: https://pi.dev/docs/latest/models
Add custom providers and models through ~/.pi/agent/models.json for Ollama, LM Studio, vLLM, SGLang, proxies, and custom endpoints.
Minimal Local Example
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"compat": {
"supportsDeveloperRole": false,
"supportsReasoningEffort": false
},
"models": [
{ "id": "llama3.1:8b" },
{ "id": "qwen2.5-coder:7b" }
]
}
}
}The apiKey is required even when the server ignores it. Edit during a session; /model reloads the file.
Supported APIs
openai-completions: OpenAI Chat Completions and compatibles.openai-responses: OpenAI Responses API.anthropic-messages: Anthropic Messages API.google-generative-ai: Google Generative AI.
Provider Fields
baseUrl, api, apiKey, headers, authHeader, models, modelOverrides.
apiKey and headers support command execution (!command), env interpolation ($ENV/${ENV}), escapes ($$, $!), and literals. Shell commands in models.json resolve at request time and do not get built-in TTL/recovery; wrap slow or flaky secret commands yourself.
Model Fields
Required: id.
Optional: name, api, reasoning, thinkingLevelMap, input, contextWindow, maxTokens, cost, compat.
thinkingLevelMap maps Pi levels (off, minimal, low, medium, high, xhigh) to provider values; null hides unsupported levels.
Built-in Overrides
Override a provider base URL without redefining models:
{ "providers": { "anthropic": { "baseUrl": "https://my-proxy.example.com/v1" } } }If models is included, custom models merge into built-ins by id; matching IDs replace built-ins. Use modelOverrides to modify specific built-in models without replacing the provider list.
Compatibility Flags
Anthropic flags include supportsEagerToolInputStreaming, supportsLongCacheRetention, sendSessionAffinityHeaders, supportsCacheControlOnTools, forceAdaptiveThinking, and allowEmptySignature.
OpenAI compatibility flags include supportsStore, supportsDeveloperRole, supportsReasoningEffort, supportsUsageInStreaming, maxTokensField, requiresToolResultName, requiresAssistantAfterToolResult, requiresThinkingAsText, requiresReasoningContentOnAssistantMessages, thinkingFormat, cacheControlFormat, supportsStrictMode, supportsLongCacheRetention, openRouterRouting, and vercelGatewayRouting.
Pi Documentation Overview
Source: https://pi.dev/docs/latest
Pi is a minimal terminal coding harness. The core stays small and most workflow-specific behavior lives in TypeScript extensions, skills, prompt templates, themes, and Pi packages.
Top-Level Areas
- Start here: quickstart, usage, providers, security, containerization, settings, keybindings, sessions, compaction.
- Customization: extensions, skills, prompt templates, themes, Pi packages, custom models, custom providers.
- Programmatic usage: SDK, RPC mode, JSON event stream mode, TUI components.
- Reference: session file format and SessionManager API.
- Platform setup: Windows, Termux, tmux, terminal setup, shell aliases.
- Development: local source setup, rebranding, debug logs, tests, package structure.
Quick Install
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
piOn Linux/macOS, the installer is also available:
curl -fsSL https://pi.dev/install.sh | shAuthenticate with /login for subscription providers or set API keys such as ANTHROPIC_API_KEY before startup.
Pi Packages
Source: https://pi.dev/docs/latest/packages
Pi packages bundle extensions, skills, prompt templates, and themes for sharing through npm, git, URL, or local paths.
Install and Manage
pi install npm:@foo/bar@1.0.0
pi install git:github.com/user/repo@v1
pi install https://github.com/user/repo
pi install /absolute/path/to/package
pi install ./relative/path/to/package
pi remove npm:@foo/bar
pi list
pi update
pi update --extensions
pi update --self
pi update npm:@foo/bar
pi update --extension npm:@foo/barUse -l to write install/remove to project settings .pi/settings.json; otherwise user settings are updated. Project packages install automatically after trust. Use -e/--extension to try a package for one run without installing.
Sources
npm specs support pins. User installs go under ~/.pi/agent/npm/; project installs under .pi/npm/. npmCommand can pin npm operations to a wrapper such as mise.
Git specs support HTTPS, SSH, and shorthand with git:. Refs are pinned tags or commits. Reconciliation may reset/clean clones and run npm install when package.json exists.
Local paths are referenced in settings without copying. Relative paths resolve against the settings file.
Package Manifest
{
"name": "my-package",
"keywords": ["pi-package"],
"pi": {
"extensions": ["./extensions"],
"skills": ["./skills"],
"prompts": ["./prompts"],
"themes": ["./themes"]
}
}If no manifest exists, Pi auto-discovers conventional directories: extensions/, skills/, prompts/, themes/.
Dependencies
Runtime deps belong in dependencies. Pi bundles core packages for extensions/skills; imports of @earendil-works/pi-ai, @earendil-works/pi-agent-core, @earendil-works/pi-coding-agent, @earendil-works/pi-tui, and typebox should be peer dependencies with "*" and not bundled.
Filtering
Object settings can include/exclude resources with globs, !pattern, exact +path, exact -path, or [] to load none for a resource type.
Notable Ecosystem Packages
pi install npm:pi-subagents— delegate to child agents, chains, parallel runs:references/pi-subagents.mdpi install npm:pi-mcp-adapter— token-efficient MCP server access:references/pi-mcp-adapter.mdpi install npm:pi-interview— interactive interview forms for structured user input:references/pi-interview.mdpi install npm:pi-web-access— web search, URL/PDF/repo fetching, video understanding:references/pi-web-access.mdpi install npm:pi-intercom— child-to-parent coordination companion for pi-subagents
Security
Packages run with full system access. Review third-party package code before installing.
pi-interview Package
Source: https://pi.dev/packages/pi-interview
Interactive interview form extension: the agent collects structured user responses through forms with single/multi-select, text input, image upload, and info panels, plus rich media (code, diffs, Markdown, images, Chart.js charts, Mermaid diagrams, tables, HTML). Requires pi-agent v0.35.0+.
pi install npm:pi-interview
pi install npm:glimpseui # optional: native macOS windows (browser fallback otherwise)Invocation
Agents call the tool directly:
await interview({
questions: '/path/to/questions.json',
timeout: 600, // optional, seconds
verbose: false // optional, debug logging
});Question Schema
{
"title": "Project Setup",
"description": "Review my suggestions and adjust as needed.",
"questions": [
{ "id": "context", "type": "info", "question": "Architecture context", "context": "This project needs SSR and edge deployment support." },
{ "id": "framework", "type": "single", "question": "Which framework?",
"options": ["React", "Vue", "Svelte"],
"recommended": "React", "conviction": "strong", "weight": "critical" }
]
}Question types: single (radio), multi (checkbox), text, image (upload), info (non-interactive panel).
| Field | Purpose |
|---|---|
id, type, question | Identifier, type, question text |
options | Choices for single/multi; strings or { label, content } objects |
recommended | Pre-selected option(s) with badge |
conviction | "strong" or "slight" — controls pre-selection |
weight | "critical" or "minor" — visual prominence |
context | Help text |
content | Code/diff/Markdown block: { source, lang, file, lines, highlights, showSource }; lang: "diff" renders diffs, lang: "md" renders Markdown preview |
media | Object or array: types image, table, chart, mermaid, html; each supports position: "above"/"below"/"side" and caption; tables take { headers, rows, highlights } |
Response Format
interface Response { id: string; value: string | string[]; attachments?: string[]; }Settings
~/.pi/agent/settings.json:
{
"interview": {
"timeout": 600,
"port": 19847,
"snapshotDir": "~/.pi/interview-snapshots/",
"autoSaveOnSubmit": true,
"generateModel": "anthropic/claude-haiku-4-5",
"theme": { "mode": "auto", "name": "default", "lightPath": "/path/to/light.css", "darkPath": "/path/to/dark.css", "toggleHotkey": "mod+shift+l" }
}
}Timeout precedence: function parameter > settings > default 600s. Built-in themes: default (monospace) and tufte (serif); modes dark (default), light, auto. Custom themes are CSS files overriding variables like --bg-body, --bg-card, --accent, --error.
Recovery and Snapshots
Abandoned/timed-out interviews save to ~/.pi/interview-recovery/{date}_{time}_{project}_{branch}_{sessionId}.json (auto-deleted after 7 days). Submissions can auto-save snapshots (index.html + images/) to ~/.pi/interview-snapshots/. Resume either by passing the recovery JSON or snapshot index.html path as questions.
Keyboard and Limits
↑/↓ navigate options, ⌘+←/⌘+→ navigate questions (Ctrl on non-macOS), Tab cycles, Enter/Space selects, ⌘+Enter submits, Esc twice quits, ⌘+Shift+L toggles theme. Auto-saves via localStorage; detects multi-agent queues.
Image limits: max 12 per submission, 5MB each, 4096×4096 px, PNG/JPG/GIF/WebP.
pi-mcp-adapter Package
Source: https://pi.dev/packages/pi-mcp-adapter
MCP adapter extension for Pi. Instead of loading hundreds of MCP tool definitions upfront (10,000+ tokens per server), it exposes one mcp proxy tool (~200 tokens) that discovers and calls tools on demand. Servers connect lazily and disconnect when idle.
pi install npm:pi-mcp-adapterRestart Pi after installation.
Configuration Files
Precedence (highest to lowest):
1. ~/.config/mcp/mcp.json — user-global shared config 2. <Pi agent dir>/mcp.json — Pi global override 3. .mcp.json — project-local shared config 4. .pi/mcp.json — Pi project override
{
"mcpServers": {
"chrome-devtools": { "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest"] }
}
}Import existing configs with "imports": ["cursor", "claude-code", "claude-desktop"] (also vscode, windsurf, codex).
Server Options
| Field | Description |
|---|---|
command, args, env, cwd | stdio transport; env/cwd support ${VAR}, $env:VAR, ~ |
url, headers | HTTP endpoint (StreamableHTTP with SSE fallback); headers support interpolation |
auth | "bearer" or "oauth" |
oauth | { grantType, clientId, clientSecret, scope, redirectUri } |
lifecycle | "lazy" (default: connect on first call, idle disconnect), "eager" (connect at startup), "keep-alive" (startup + health checks + auto-reconnect) |
idleTimeout | Minutes before idle disconnect (default 10) |
exposeResources | Expose MCP resources as tools (default true) |
directTools | true, string[], or false — register tools directly instead of via proxy |
excludeTools | Tool names to hide |
debug | Show server stderr (default false) |
Global settings block: toolPrefix, idleTimeout, directTools, disableProxyTool, autoAuth, sampling, samplingAutoApprove, elicitation, elicitationAutoOpenUrls.
Direct tools cost 150–300 tokens each; use for 5–20 targeted tools, the proxy for everything else:
{ "mcpServers": { "github": { "directTools": ["search_repositories", "get_file_contents"] } } }Proxy Tool API
mcp({ }) // list servers
mcp({ server: "name" }) // server details
mcp({ search: "screenshot navigate" }) // search tools
mcp({ describe: "tool_name" }) // tool description
mcp({ tool: "chrome_devtools_take_screenshot", args: '{"format": "png"}' }) // call; args is a JSON string
mcp({ connect: "server-name" })
mcp({ action: "ui-messages" }) // retrieve MCP UI messagesCLI Commands
/mcp # interactive panel and first-run setup
/mcp setup # guided imports and config
/mcp tools # list all available tools
/mcp reconnect [server]
/mcp logout <server> # clear OAuth credentials
/mcp-auth [server] # OAuth setup pickerBehavior Notes
Tool metadata is cached to disk so search/describe work offline. npx-based servers resolve to direct binaries to skip npm overhead. MCP UI–capable tools open in a native macOS window via Glimpse (if installed) or a browser fallback; UI message types prompt, intent, notify, message are retrievable via mcp({ action: "ui-messages" }).
Limitations: no cross-session server sharing; MCP sampling is text-only (context, tools, audio, images rejected).
Subagents (pi-subagents) only receive direct MCP tools when listed in their tools: frontmatter with an mcp: prefix — see references/pi-subagents.md.
pi-subagents Package
Source: https://pi.dev/packages/pi-subagents
Extension for delegating tasks to focused child agents with sequential chains, parallel execution, dynamic fanout, worktree isolation, and acceptance gates.
pi install npm:pi-subagentsBuilt-in Agents
| Agent | Purpose |
|---|---|
scout | Fast local codebase recon: files, entry points, data flow, risks |
researcher | Web/docs research with sources and a concise brief |
planner | Concrete implementation plan from existing context |
worker | Implementation: file editing and validation |
reviewer | Code review and small fixes against task/plan |
context-builder | Setup pass gathering code context and handoff material |
oracle | Second opinion challenging assumptions; no edits |
delegate | Lightweight general delegate close to parent behavior |
Packaged planner, worker, oracle default to context: "fork" (branch from parent session state); others default to fresh.
Commands
/run <agent> [task] # single agent; --bg detached, --fork branch session
/run reviewer[model=anthropic/claude-sonnet-4] summarize this code
/chain scout "scan the codebase" -> planner "create an implementation plan"
/parallel scanner "find security issues" -> reviewer "check code style"
/run-chain <chainName> -- <task> # saved workflow
/subagents-doctor # setup diagnosticsPer-step config uses [key=value,...] on the agent name: output=file.md, outputMode=file-only|inline, reads=a.md+b.md, model=..., skills=a+b, thinking=high, progress.
Natural language also works: "Use reviewer to review this diff", "Run parallel reviewers: one for correctness, one for tests".
Packaged prompt shortcuts: /parallel-review, /review-loop, /parallel-research, /parallel-context-build, /parallel-handoff-plan, /gather-context-and-clarify, /parallel-cleanup (add autofix to apply synthesized fixes).
Programmatic API (subagent tool)
{ agent: "worker", task: "refactor auth" }
{ tasks: [{ agent: "scout", task: "audit frontend" }, { agent: "reviewer", task: "audit backend" }] } // parallel; count: N duplicates a task
{ chain: [{ agent: "scout", task: "Gather context" }, { agent: "planner" }, { agent: "worker" }, { agent: "reviewer" }] }
{ chain: [...], timeoutMs: 30000 }
{ agent: "worker", task: "...", maxRuntimeMs: 600000 }
{ action: "list" | "get" | "create" | "update" | "delete" | "status" | "interrupt" | "resume" | "doctor" }
{ action: "resume", id: "<run-id>", message: "follow-up" }Key parameters: output (file or false), outputMode (inline/file-only), skill (string/array/false), model, concurrency (default 4), worktree, context (fresh/fork), chainDir, clarify (default true for chains), async, cwd, maxOutput (default 200KB/5000 lines), share (Gist upload, off by default), acceptance.
Dynamic fanout: a chain step with expand: { from: { output: "name", path: "/items" }, item: "target", maxItems: N } plus parallel: { agent, task: "Review {target.path}" } and collect: { as: "reviews" } fans out over a prior step's structured output (as + outputSchema).
Agent Definition Files
Markdown with YAML frontmatter. Precedence: project .pi/agents/**/*.md > user ~/.pi/agent/agents/**/*.md > builtin.
---
name: scout
description: Fast codebase recon
model: claude-haiku-4-5
fallbackModels: openai/gpt-5-mini, anthropic/claude-sonnet-4
thinking: high
tools: read, grep, find, ls, bash # allowlist; mcp: prefix for direct MCP tools
extensions: mcp:chrome-devtools # omitted = all; empty = none
skills: safe-bash
systemPromptMode: replace # or append
inheritProjectContext: false
inheritSkills: false
defaultContext: fork # or fresh
output: context.md
defaultReads: context.md
defaultProgress: true
completionGuard: false # false for non-implementation validators
interactive: true
maxSubagentDepth: 1
maxExecutionTimeMs: 600000
maxTokens: 50000
---
Your system prompt goes here.Subagents only receive direct MCP tools when listed in tools: frontmatter (requires pi-mcp-adapter); a global directTools: true is insufficient.
Chain Files
Reusable workflows: project .pi/chains/**/*.chain.md|.chain.json > user ~/.pi/agent/chains/. Markdown chains use ## agent headings with per-step keys (phase, label, as, output, outputMode, reads, model, skills, progress, outputSchema) and a task body. Template variables: {task}, {previous}, {chain_dir}, {outputs.name}.
Configuration
Builtin agent overrides in ~/.pi/agent/settings.json or .pi/settings.json:
{ "subagents": { "agentOverrides": { "reviewer": { "model": "anthropic/claude-sonnet-4", "thinking": "high" } }, "disableBuiltins": false } }Override fields: model, fallbackModels, thinking, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext, disabled, skills, tools, systemPrompt.
Extension config at ~/.pi/agent/extensions/subagent/config.json: asyncByDefault, forceTopLevelAsync, parallel: { maxTasks, concurrency }, defaultSessionDir, maxSubagentDepth, intercomBridge: { mode: "always"|"fork-only"|"off", instructionFile }, worktreeSetupHook (+ worktreeSetupHookTimeoutMs; hook gets stdin JSON with repo/worktree paths and must print { "syntheticPaths": [...] }).
Nesting depth defaults to 2 levels; tighten/relax via PI_SUBAGENT_MAX_DEPTH env var, config maxSubagentDepth, or per-agent frontmatter (per-agent can only tighten). Children never get the subagent tool unless their resolved tools explicitly include it.
Worktree Isolation
worktree: true on parallel tasks or chain steps runs each agent in an isolated git worktree. Requires a git repo with a clean working tree; node_modules/ is symlinked in; task-level cwd overrides must match the shared cwd.
Acceptance Gates
Attach explicit contracts to any run/step:
{ agent: "worker", task: "Implement the fix", acceptance: {
criteria: ["Patch the bug without widening scope"],
evidence: ["changed-files", "tests-added", "commands-run", "residual-risks", "no-staged-files"],
verify: [{ id: "focused", command: "npm test", timeoutMs: 120000 }],
maxFinalizationTurns: 3
} }Provenance levels reported: attested, checked, verified, reviewed, rejected.
Async, Clarify, Observability
--bg / async: true detaches runs; status files under <tmpdir>/pi-subagents-<scope>/async-subagent-runs/<id>/ (status.json, events.jsonl, logs). Chains open a clarify TUI by default to preview/edit steps (e edit, m model, t thinking, s skills, b background, Enter run, Esc cancel). Debug artifacts land in {sessionDir}/subagent-artifacts/ with input/output/jsonl/meta per run; chain artifacts in <tmpdir>/pi-subagents-<scope>/chain-runs/{runId}/. Directories older than 24h are cleaned on startup. Events: subagent:async-started, subagent:async-complete, subagent:control-intercom, subagent:result-intercom.
Optional companion pi install npm:pi-intercom lets children call contact_supervisor (reasons: need_decision, progress_update) and groups completion delivery back to the parent.
Recommended implementation pattern: clarify → planner → worker → fresh reviewers → worker.
pi-web-access Package
Source: https://pi.dev/packages/pi-web-access
Extension adding web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis to Pi.
pi install npm:pi-web-accessWorks immediately without API keys via Exa MCP. Optional: brew install ffmpeg yt-dlp for video frame extraction.
Tools
web_search
Searches via Exa, Perplexity, or Gemini with synthesized answers and citations.
web_search({ query: "TypeScript best practices 2025" })
web_search({ queries: ["query 1", "query 2"] })
web_search({ query: "latest news", numResults: 10, recencyFilter: "week" })
web_search({ query: "...", domainFilter: ["github.com"], provider: "exa" })Parameters: query/queries, numResults, recencyFilter (day/week/month/year), domainFilter, provider (auto/exa/perplexity/gemini), includeContent, workflow.
code_search
Code examples and API references; no API key required.
code_search({ query: "React useEffect cleanup pattern" })
code_search({ query: "Express middleware error handling", maxTokens: 10000 })fetch_content
Readable content from URLs, GitHub repos, YouTube videos, PDFs, and local video files.
fetch_content({ url: "https://example.com/article" })
fetch_content({ urls: ["url1", "url2", "url3"] })
fetch_content({ url: "https://github.com/owner/repo" })
fetch_content({ url: "https://youtube.com/watch?v=abc", prompt: "What libraries are shown?" })
fetch_content({ url: "/path/to/recording.mp4", prompt: "What error appears on screen?" })
fetch_content({ url: "https://youtube.com/watch?v=abc", timestamp: "23:41-25:00", frames: 4 })Parameters: url/urls, prompt, timestamp, frames (max 12), forceClone.
get_search_content
Stored content from previous searches (for content beyond the 30,000-character inline limit): get_search_content({ responseId: "abc123", urlIndex: 0 }) or { responseId, url }.
Capabilities
- GitHub repos: cloned locally for real file contents — root URLs return tree + README,
/tree/paths list directories,/blob/paths show files; repos over 350MB get lightweight API-based views. - YouTube: visual descriptions, timestamped transcripts, chapter markers via Gemini.
- Local video: MP4/MOV/WebM/AVI up to 50MB via Gemini; frame extraction at timestamps with ffmpeg.
- PDFs: text extraction saved to
~/Downloads/as markdown (no OCR). - Blocked pages: automatic retry via Jina Reader, then Gemini URL Context API, for JS-heavy and anti-bot sites.
CLI Commands
/websearch [queries] # open curator; pre-fill comma-separated queries
/curator # toggle curator workflow
/curator on|off|summary-review # configure curator mode
/search # browse stored results interactively
/google-account # display active Google accountCtrl+Shift+W toggles an activity monitor with live request/response data.
Configuration
All settings in ~/.pi/web-search.json are optional. Env vars EXA_API_KEY, GEMINI_API_KEY, PERPLEXITY_API_KEY take precedence over the file.
{
"exaApiKey": "exa-...",
"perplexityApiKey": "pplx-...",
"geminiApiKey": "AIza...",
"provider": "exa",
"chromeProfile": "Profile 2",
"allowBrowserCookies": false,
"searchModel": "gemini-2.5-flash",
"summaryModel": "anthropic/claude-haiku-4-5",
"workflow": "summary-review",
"curatorTimeoutSeconds": 20,
"githubClone": { "enabled": true, "maxRepoSizeMB": 350, "cloneTimeoutSeconds": 30, "clonePath": "/tmp/pi-github-repos" },
"youtube": { "enabled": true, "preferredModel": "gemini-3-flash-preview" },
"video": { "enabled": true, "preferredModel": "gemini-3-flash-preview", "maxSizeMB": 50 },
"shortcuts": { "curate": "ctrl+shift+s", "activity": "ctrl+shift+w" }
}Bundled skill librarian combines GitHub cloning, web search, and git operations for evidence-backed library investigation with permalink citations.
Limitations
Chromium cookie extraction requires opt-in (allowBrowserCookies: true); age-restricted/private YouTube videos may fail; Gemini handles videos up to ~1 hour; non-code GitHub URLs fall through to standard web extraction.
Prompt Templates
Source: https://pi.dev/docs/latest/prompt-templates
Prompt templates are Markdown snippets that expand into full prompts. Invoke them by typing /name where name is the filename without .md.
Locations
- Global:
~/.pi/agent/prompts/*.md - Project:
.pi/prompts/*.mdafter project trust - Packages:
prompts/directories orpi.promptsmanifest entries - Settings:
promptsarray with files/directories - CLI:
--prompt-template, repeatable
Disable discovery with --no-prompt-templates.
Format
---
description: Review staged git changes
argument-hint: "[focus]"
---
Review the staged changes (`git diff --cached`). Focus on: $ARGUMENTSThe description is optional; if missing, Pi uses the first non-empty line. argument-hint appears in autocomplete.
Arguments
$1,$2: positional args.$@or$ARGUMENTS: all args joined.${1:-default}: default value.${@:N}: args from N.${@:N:L}: L args starting at N.
Discovery in prompts/ is non-recursive unless subdirectories are explicitly configured in settings or package manifest.
Providers
Source: https://pi.dev/docs/latest/providers
Pi supports subscription providers via OAuth and API-key providers via env vars or ~/.pi/agent/auth.json. Built-in model lists are updated with each Pi release.
Subscription Providers
Use /login and choose Claude Pro/Max, ChatGPT Plus/Pro (Codex), or GitHub Copilot. Use /logout to clear credentials. Tokens live in ~/.pi/agent/auth.json and refresh automatically.
API Key Providers
Set env vars before startup or use /login to store keys. Common mappings:
ANTHROPIC_API_KEY->anthropicOPENAI_API_KEY->openaiGEMINI_API_KEY->googleMISTRAL_API_KEY->mistralGROQ_API_KEY->groqOPENROUTER_API_KEY->openrouterAI_GATEWAY_API_KEY->vercel-ai-gatewayCLOUDFLARE_API_KEYplus account/gateway vars -> Cloudflare providersAWS_*credentials -> Amazon Bedrock
auth.json entries use { "type": "api_key", "key": "..." } and are created with 0600 permissions.
Key Resolution Syntax
The key field supports:
{ "type": "api_key", "key": "!op read 'op://vault/item/credential'" }
{ "type": "api_key", "key": "$MY_API_KEY" }
{ "type": "api_key", "key": "${KEY_PREFIX}_${KEY_SUFFIX}" }
{ "type": "api_key", "key": "$$literal-dollar" }
{ "type": "api_key", "key": "$!literal-bang" }Auth file credentials take priority over environment variables.
Cloud Providers
Azure OpenAI needs AZURE_OPENAI_API_KEY plus AZURE_OPENAI_BASE_URL or AZURE_OPENAI_RESOURCE_NAME; optional AZURE_OPENAI_API_VERSION and deployment mapping.
Amazon Bedrock uses AWS profile, IAM keys, bearer token, ECS task roles, or IRSA. Set region through AWS_REGION. For application inference profiles that do not include recognizable model names, set AWS_BEDROCK_FORCE_CACHE=1 to force cache points.
Cloudflare AI Gateway requires CLOUDFLARE_API_KEY, CLOUDFLARE_ACCOUNT_ID, and CLOUDFLARE_GATEWAY_ID. Prefer unified billing or stored BYOK.
Google Vertex AI uses Application Default Credentials plus GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION.
Resolution Order
1. CLI --api-key 2. auth.json entry 3. Environment variable 4. Custom provider keys from models.json
Quickstart
Source: https://pi.dev/docs/latest/quickstart
Install and Uninstall
npm install -g --ignore-scripts @earendil-works/pi-coding-agent--ignore-scripts disables dependency lifecycle scripts. Pi does not need install scripts for normal npm installs.
Uninstall with the matching package manager. Curl and npm installs are removed with:
npm uninstall -g @earendil-works/pi-coding-agentUninstalling Pi leaves settings, credentials, sessions, and installed packages in ~/.pi/agent/.
Authenticate
Use /login in interactive mode for subscription providers: Claude Pro/Max, ChatGPT Plus/Pro (Codex), and GitHub Copilot. API-key providers can be configured by environment variable or stored through /login in ~/.pi/agent/auth.json.
export ANTHROPIC_API_KEY=sk-ant-...
piFirst Session
Run Pi in the project directory:
cd /path/to/project
piBy default, the model gets read, write, edit, and bash. Additional read-only built-ins grep, find, and ls are available through tool options.
Project Instructions
Pi loads context files at startup:
~/.pi/agent/AGENTS.mdAGENTS.mdorCLAUDE.mdfrom parent directories and current directory
Run /reload or restart after changing context files.
Common First Tasks
pi @README.md "Summarize this"
pi @src/app.ts @src/app.test.ts "Review these together"
!npm run lint
!!npm run lint
pi -c
pi -r
pi --name "my task"
pi --session <path|id>
pi -p "Summarize this codebase"
cat README.md | pi -p "Summarize this text"
pi --mode json "List files"
pi --mode rpc --no-sessionUse !command to run shell and send output to the model. Use !!command to run without adding output to model context.
RPC Mode
Source: https://pi.dev/docs/latest/rpc
RPC mode runs Pi headlessly over stdin/stdout JSONL. Use it for language-agnostic clients, IDE integrations, custom UIs, or subprocess isolation.
pi --mode rpc [options]Common options: --provider, --model, --name/-n, --no-session, --session-dir.
For Node/TypeScript in-process apps, prefer the SDK unless subprocess isolation is desired.
Framing
Commands are JSON objects sent to stdin, one per line. Responses and events are JSON objects streamed to stdout, one per line. Use LF ( ) as the only record delimiter; strip trailing
for CRLF input. Do not use generic line readers that split on Unicode separators. Node readline is not protocol-compliant because it also splits on U+2028/U+2029.
Commands can include optional id; corresponding responses echo it. Events do not include id.
Prompting Commands
prompt: send a user prompt. Response means accepted, queued, or handled; later failures come through events.
{"id":"req-1","type":"prompt","message":"Hello"}Add images with images: [{"type":"image","data":"base64...","mimeType":"image/png"}].
If streaming, include streamingBehavior: "steer" or "followUp". Extension commands execute immediately; skills and prompt templates expand before sending/queueing.
steer: queue a steering message delivered after current assistant turn tool calls.
follow_up: queue a message delivered after the agent is fully done.
abort: abort current agent operation.
new_session: start fresh, optionally with parentSession; can be cancelled by extension.
State and Model Commands
get_state: returns model, thinkingLevel, streaming/compacting state, queue modes, session info, message counts, auto-compaction.get_messages: returns allAgentMessageobjects.set_model: switch model.cycle_model: cycle next available/scoped model.get_available_models: list configured models.set_thinking_level: setoff,minimal,low,medium,high, orxhigh.cycle_thinking_level: cycle supported levels.
Queue, Compaction, Retry
set_steering_mode:allorone-at-a-time.set_follow_up_mode:allorone-at-a-time.compact: manually compact; acceptscustomInstructions.set_auto_compaction: enable/disable auto compaction.set_auto_retry: enable/disable transient-error retry.abort_retry: cancel retry delay and stop retrying.
Bash
bash executes immediately and returns output. A BashExecutionMessage is stored in agent state but no event is emitted for it. The output reaches the LLM on the next prompt.
abort_bash aborts a running bash command.
Session Commands
get_session_stats: token totals, cost, context usage.export_html: export current session.switch_session: load another session; extension can cancel.fork: create a new fork from an earlier user message.clone: duplicate active branch into a new session.get_fork_messages: list forkable user messages.get_last_assistant_text: last assistant text or null.set_session_name: set display name.
Commands Discovery
get_commands lists extension commands, prompt templates, and skills. Built-in TUI commands such as /settings are interactive-only and are not included.
Events
RPC streams the same major events as the SDK/JSON mode: agent, turn, message, tool execution, queue, compaction, retry, and extension errors.
SDK
Source: https://pi.dev/docs/latest/sdk
Install the main package; the SDK is included:
npm install @earendil-works/pi-coding-agentUse the SDK to embed Pi in apps, build custom UIs, automate workflows, spawn sub-agents, test behavior, or customize tools/resources in process.
Quick Start
import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent";
const authStorage = AuthStorage.create();
const modelRegistry = ModelRegistry.create(authStorage);
const { session } = await createAgentSession({
sessionManager: SessionManager.inMemory(),
authStorage,
modelRegistry,
});
session.subscribe((event) => {
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
await session.prompt("What files are in the current directory?");AgentSession
Core methods: prompt, steer, followUp, subscribe, setModel, setThinkingLevel, cycleModel, cycleThinkingLevel, navigateTree, compact, abortCompaction, abort, and dispose.
State: sessionFile, sessionId, agent, model, thinkingLevel, messages, isStreaming.
Session replacement (new, resume, fork, import) belongs to AgentSessionRuntime, not AgentSession.
Runtime API
Use createAgentSessionRuntime() when replacing the active session and rebuilding cwd-bound services. After runtime.newSession(), runtime.switchSession(), or runtime.fork(), runtime.session changes; re-subscribe to events and re-bind extensions if you manage them manually.
Prompting and Queueing
PromptOptions supports expandPromptTemplates, images, streamingBehavior (steer or followUp), source, and preflightResult.
During streaming, prompt() without streamingBehavior throws. Use session.steer() for steering delivered after current assistant turn tool calls, or session.followUp() for after all work finishes. Extension commands execute immediately and cannot be queued by steer/followUp.
Events
Subscribe to AgentSessionEvent for message_update text/thinking deltas, tool execution events, message lifecycle, agent lifecycle, turn lifecycle, queue updates, compaction, and retry events.
Models and Auth
Use AuthStorage.create() and ModelRegistry.create(authStorage). API key priority: runtime overrides, auth.json, environment variables, then custom provider fallback from models.json.
Use getModel(provider, id) for built-in model lookup and modelRegistry.find(provider, id) for built-in plus custom. modelRegistry.getAvailable() checks auth availability.
Tools
Built-in names: read, bash, edit, write, grep, find, ls. Defaults: read, bash, edit, write. tools allowlists tools; excludeTools disables specific tools. noTools: "all" disables all tools; noTools: "builtin" disables built-ins but keeps custom/extension tools.
The edit tool returns details.diff for TUI display and details.patch as standard unified patch for SDK consumers.
Define custom tools with defineTool() and pass customTools; include custom names in tools if using an allowlist.
Resource Loading
DefaultResourceLoader discovers extensions, skills, prompts, themes, and context files. It supports additional extension paths, inline extension factories, overrides for skills/prompts/context, and a shared event bus.
cwd controls project discovery and tool path resolution. agentDir controls global resources such as ~/.pi/agent.
Sessions and Settings
Use SessionManager.inMemory(), create(), continueRecent(), open(), list(), and listAll(). Tree APIs include getEntries, getTree, getPath, getLeafEntry, getEntry, getChildren, appendLabelChange, branch, branchWithSummary, and createBranchedSession.
SettingsManager.create() loads global plus project settings; SettingsManager.inMemory() is useful for tests. Setters persist asynchronously; call flush() for durability and drainErrors() to report write errors.
Run Modes
The SDK exports run helpers: InteractiveMode, runPrintMode, and runRpcMode. Use these when building custom launchers while reusing Pi's mode implementations.
SDK vs RPC
Prefer SDK when you want type safety, same Node.js process, direct state access, or programmatic tools/extensions. Prefer RPC when integrating from another language, needing process isolation, or building a language-agnostic client.
Important Exports
createAgentSession, createAgentSessionRuntime, AgentSessionRuntime, AuthStorage, ModelRegistry, DefaultResourceLoader, defineTool, getAgentDir, SessionManager, SettingsManager, tool factories, and types for options, results, extensions, tools, skills, and prompt templates.
Security
Source: https://pi.dev/docs/latest/security
Pi is a local coding agent. It runs with the permissions of the user account that starts it and treats files writable by that user as inside the local trust boundary.
Project Trust
Project trust controls whether Pi loads project-local settings, resources, packages, and extensions. It is not a sandbox.
Trust-gated inputs include .pi/ in the current directory and .agents/skills in the current directory or ancestors. Trusting allows loading .pi/settings.json, .pi resources, missing project packages, project extensions, and project package-managed extensions.
AGENTS.md and CLAUDE.md context files load regardless of project trust unless context loading is disabled.
Non-interactive modes do not prompt. Without a saved trust decision, defaultProjectTrust: "ask" and "never" ignore trust-gated resources, while "always" trusts them. Use --approve or --no-approve for one-run override.
No Built-in Sandbox
Built-in tools can read, write, edit, and run shell commands with the permissions of the Pi process. Extensions are TypeScript modules with the same permissions. Package installs and developer tools are ordinary local processes.
Project trust only guards input loading; it does not make untrusted code, prompts, model output, or build output safe.
Untrusted Work
For untrusted repositories, generated code you will not monitor closely, or unattended automation, run Pi in a contained environment. Use Docker, OpenShell, Gondolin, a VM, micro-VM, or remote sandbox. Mount only needed files, avoid mounting host ~/.pi/agent unless required, pass minimum credentials, restrict network where possible, and review diffs before copying results to trusted systems.
Session File Format
Source: https://pi.dev/docs/latest/session-format
Sessions are JSONL files. Each line is a JSON object with type. Entries form a tree through id and parentId.
Location
~/.pi/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonlExisting sessions auto-migrate to current version. Version 3 renamed hookMessage role to custom.
Message Content
Messages use content blocks: text, image, thinking, and toolCall. Base roles include user, assistant, and toolResult. Extended roles include bashExecution, custom, branchSummary, and compactionSummary.
Assistant messages include api, provider, model, usage, stopReason, optional errorMessage, timestamp, and content blocks.
Entry Types
session: header, first line, metadata only.message: wraps anAgentMessage.model_change: model switches.thinking_level_change: thinking level changes.compaction: summary of earlier messages withfirstKeptEntryIdandtokensBefore.branch_summary: summary of an abandoned branch.custom: extension state, not sent to LLM.custom_message: extension-injected message, sent to LLM.label: user-defined bookmark on an entry.session_info: display name metadata.
Context Building
buildSessionContext() walks from current leaf to root. If a CompactionEntry is on the path, Pi emits the summary first, then messages from firstKeptEntryId, then later messages.
SessionManager API
Static factories: create, open, continueRecent, inMemory, forkFrom.
Listing: list, listAll.
Session management: newSession, setSessionFile, createBranchedSession.
Append: appendMessage, appendThinkingLevelChange, appendModelChange, appendCompaction, appendCustomEntry, appendSessionInfo, appendCustomMessageEntry, appendLabelChange.
Tree: getLeafId, getLeafEntry, getEntry, getBranch, getTree, getChildren, getLabel, branch, resetLeaf, branchWithSummary.
Info/context: buildSessionContext, getEntries, getHeader, getSessionName, getCwd, getSessionDir, getSessionId, getSessionFile, isPersisted.
Sessions
Source: https://pi.dev/docs/latest/sessions
Pi auto-saves conversations to ~/.pi/agent/sessions/, organized by working directory. Each session is a JSONL tree.
Session Commands
pi -c
pi -r
pi --no-session
pi --name "my task"
pi --session <path|id>
pi --fork <path|id>Interactive commands: /resume, /new, /name, /session, /tree, /fork, /clone, /compact [prompt], /export [file], /share.
Resuming
/resume and pi -r open a picker. Search by typing; use Ctrl+P to toggle path display, Ctrl+S sort, Ctrl+N named-only filter, Ctrl+R rename, Ctrl+D delete. Pi uses trash when available.
Branching
Sessions are trees with id and parentId. /tree lets you jump to a previous point and continue without creating a new file. Selecting a user/custom message moves to its parent and puts that message in the editor so it can be edited and resubmitted. Selecting assistant/tool/compaction entries moves the leaf there with an empty editor.
Tree vs Fork vs Clone
/tree: same session file, full tree, optional branch summary./fork: new session file from an earlier user message./clone: new session file duplicating current active branch.
Branch Summaries
When switching branches through /tree, Pi can summarize the abandoned branch and attach that context at the new position. See compaction.md for internals.
Settings
Source: https://pi.dev/docs/latest/settings
Pi uses JSON settings files. Project settings override global settings; nested objects merge.
| Location | Scope |
|---|---|
~/.pi/agent/settings.json | Global |
.pi/settings.json | Project |
Project Trust
Project settings are trust-gated. Interactive startup asks according to defaultProjectTrust when project inputs exist and no saved trust decision applies. Non-interactive modes use defaultProjectTrust and do not prompt. --approve and --no-approve override for one run.
Core Settings
Model/thinking: defaultProvider, defaultModel, defaultThinkingLevel, hideThinkingBlock, thinkingBudgets.
UI/display: theme, quietStartup, defaultProjectTrust, collapseChangelog, enableInstallTelemetry, doubleEscapeAction, treeFilterMode, editorPaddingX, autocompleteMaxVisible, showHardwareCursor.
Compaction: compaction.enabled, compaction.reserveTokens, compaction.keepRecentTokens.
Branch summary: branchSummary.reserveTokens, branchSummary.skipPrompt.
Retry: retry.enabled, retry.maxRetries, retry.baseDelayMs, retry.provider.timeoutMs, retry.provider.maxRetries, retry.provider.maxRetryDelayMs.
Message delivery: steeringMode, followUpMode, transport, httpIdleTimeoutMs, websocketConnectTimeoutMs.
Terminal/images: terminal.showImages, terminal.imageWidthCells, terminal.clearOnShrink, images.autoResize, images.blockImages.
Shell: shellPath, shellCommandPrefix, npmCommand.
Sessions: sessionDir; precedence is --session-dir, PI_CODING_AGENT_SESSION_DIR, then setting.
Resources: packages, extensions, skills, prompts, themes, enableSkillCommands.
Network/Telemetry
enableInstallTelemetry only controls anonymous install/update ping. Use PI_SKIP_VERSION_CHECK=1 to disable version checks. Use --offline or PI_OFFLINE=1 to disable startup network operations including update checks, package update checks, and install/update telemetry.
Example
{
"defaultProvider": "anthropic",
"defaultModel": "claude-sonnet-4-5",
"defaultThinkingLevel": "medium",
"theme": "dark",
"compaction": {
"enabled": true,
"reserveTokens": 16384,
"keepRecentTokens": 20000
},
"retry": { "enabled": true, "maxRetries": 3 },
"enabledModels": ["claude-*", "gpt-4o"],
"packages": ["pi-skills"]
}Shell Aliases
Source: https://pi.dev/docs/latest/shell-aliases
Pi runs bash in non-interactive mode (bash -c), so aliases do not expand by default.
To enable aliases, set shellCommandPrefix in ~/.pi/agent/settings.json:
{
"shellCommandPrefix": "shopt -s expand_aliases
eval "$(grep '^alias ' ~/.zshrc)""
}Adjust the shell config path for .zshrc, .bashrc, or your environment.
Skills
Source: https://pi.dev/docs/latest/skills
Pi implements the Agent Skills standard. Skills are self-contained capability packages loaded on demand. They provide instructions, workflows, scripts, and references.
Locations
Global:
~/.pi/agent/skills/~/.agents/skills/
Project, after project trust:
.pi/skills/.agents/skills/in cwd and ancestors up to git root or filesystem root
CLI --skill is repeatable and loads additively even with --no-skills.
Discovery
Directories containing SKILL.md are discovered recursively in all skill locations. In ~/.pi/agent/skills/ and .pi/skills/, direct root .md files are individual skills. In .agents/skills, root .md files are ignored.
How Skills Work
At startup Pi scans skills and extracts names/descriptions. The system prompt includes available skills. The agent should read the full SKILL.md when a task matches; users can force with /skill:name.
Skill Commands
Skills register as /skill:name. Arguments after the command are appended as User: .... Enable/disable with enableSkillCommands.
Structure
my-skill/
SKILL.md
scripts/process.sh
references/api-reference.md
assets/template.jsonUse relative paths from the skill directory.
Frontmatter
Required: name and description. Optional: license, compatibility, metadata, allowed-tools, disable-model-invocation.
Name rules: 1-64 chars, lowercase letters/numbers/hyphens, no leading/trailing hyphens, no consecutive hyphens. Pi warns on most spec violations but does not require the name to match parent directory. Missing description prevents loading.
Security
Skills can instruct the model to perform any action and may include executable code. Review third-party skills before use.
Terminal Setup
Source: https://pi.dev/docs/latest/terminal-setup
Pi uses the Kitty keyboard protocol for reliable modifier detection. Most modern terminals support it; some need setup.
Works Out of Box
Kitty and iTerm2 work out of the box. Apple Terminal uses enhanced key reporting when available and a local macOS fallback for Shift+Enter when running on the same Mac.
Ghostty
Add:
keybind = alt+backspace=text:Remove older shift+enter=text: mappings unless needed for other tools. If keeping that mapping for tmux, add ctrl+j to Pi's newline keybinding.
WezTerm
Usually works. To force Kitty keyboard:
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.enable_kitty_keyboard = true
return configOn macOS, remap Option+Enter to send [13;3u if you want follow-up queueing.
Alacritty
On macOS, add Alt+Enter binding to send [13;3u.
VS Code Integrated Terminal
VS Code 1.109.5+ enables Kitty keyboard by default. Older versions need a Shift+Enter workbench.action.terminal.sendSequence keybinding sending [13;2u.
Windows Terminal
Add actions for Shift+Enter ([13;2u) and Alt+Enter ([13;3u). Fully restart if old fullscreen behavior persists.
Limited Terminals
xfce4-terminal, terminator, and IntelliJ's integrated terminal cannot distinguish modified Enter keys reliably. Use a terminal with Kitty keyboard support for the best experience.
Termux Setup
Source: https://pi.dev/docs/latest/termux
Pi runs on Android through Termux.
Prerequisites
Install Termux from GitHub or F-Droid, not Google Play. Install Termux:API for clipboard and device integrations.
Install
pkg update && pkg upgrade
pkg install nodejs termux-api git
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
mkdir -p ~/.pi/agent
piClipboard
Pi uses termux-clipboard-set and termux-clipboard-get when available. Image clipboard is not supported in Termux.
Useful AGENTS.md Context
Add Termux environment notes to ~/.pi/agent/AGENTS.md: OS is Android/Termux, home is /data/data/com.termux/files/home, prefix is /data/data/com.termux/files/usr, shared storage is /storage/emulated/0, use termux-open-url, termux-open, termux-share, termux-notification, and clipboard commands where appropriate.
Limitations and Troubleshooting
No image clipboard. Some optional native binaries may be unavailable on Android ARM64. Run termux-setup-storage once for /storage/emulated/0. If npm fails, try npm cache clean --force.
Themes
Source: https://pi.dev/docs/latest/themes
Themes are JSON files defining TUI colors.
Locations
- Built-in:
dark,light - Global:
~/.pi/agent/themes/*.json - Project:
.pi/themes/*.jsonafter project trust - Packages:
themes/orpi.themes - Settings:
themesarray - CLI:
--theme, repeatable
Disable with --no-themes. Select through /settings or {"theme": "my-theme"}. Pi detects terminal background on first run.
Format
A theme has $schema, required name, optional vars, required colors, and optional export colors for HTML exports. All 51 color tokens must be defined.
Color values can be 6-digit hex strings, xterm 256-color indices, variable names from vars, or "" for terminal default.
Token Groups
- Core UI: accent, borders, success/error/warning, muted/dim/text/thinkingText.
- Background/content: selected/user/custom/tool states.
- Markdown: headings, links, code, quote, hr, list bullets.
- Tool diffs: added, removed, context.
- Syntax: comment, keyword, function, variable, string, number, type, operator, punctuation.
- Thinking levels: off, minimal, low, medium, high, xhigh.
- Bash mode.
Hot reload applies edits to the active custom theme for immediate feedback.
tmux Setup
Source: https://pi.dev/docs/latest/tmux
tmux strips modifier information from some keys by default. Without configuration, Shift+Enter and Ctrl+Enter are often indistinguishable from Enter.
Recommended Configuration
For tmux 3.5+:
set -g extended-keys on
set -g extended-keys-format csi-uRestart tmux fully:
tmux kill-server
tmuxWith tmux 3.2 through 3.4, omit extended-keys-format csi-u; Pi still supports tmux's default xterm modifyOtherKeys format.
What It Fixes
With CSI-u forwarding, modified Enter keys arrive distinctly:
- Enter:
- Shift+Enter:
[13;2u - Ctrl+Enter:
[13;5u - Alt/Option+Enter:
[13;3u
This affects default Enter submit, Shift+Enter newline, and custom keybindings.
TUI Components
Source: https://pi.dev/docs/latest/tui
Extensions and custom tools can render custom terminal UI components through @earendil-works/pi-tui.
Component Interface
interface Component {
render(width: number): string[];
handleInput?(data: string): void;
wantsKeyRelease?: boolean;
invalidate(): void;
}render(width) returns one string per line; each line must not exceed width. The TUI appends style resets at line ends, so reapply styles per line or use helpers that preserve ANSI styles.
Focusable and IME
Text cursor components that need IME support implement Focusable and emit CURSOR_MARKER before their fake cursor. Containers with embedded inputs must propagate focus to the child input, or IME candidate windows appear in the wrong place. Hardware cursor visibility is controlled by showHardwareCursor, setShowHardwareCursor(true), or PI_HARDWARE_CURSOR=1.
Usage
In extensions:
pi.on("session_start", async (_event, ctx) => {
const handle = ctx.ui.custom(myComponent);
handle.requestRender();
handle.close();
});In custom tools, use pi.ui.custom() inside execute and close handles when done.
Overlays
Pass { overlay: true } to render on top of existing content. overlayOptions controls width, height, anchor, offsets, row/col, margins, and responsive visibility. Overlay handles support focus/unfocus, hide, and visibility toggles. Do not reuse disposed overlay component instances; create fresh ones for each show.
Built-ins
Import Text, Box, Container, Spacer, Markdown, Input, Editor, SelectList, SettingsList, BorderedLoader, and helpers from @earendil-works/pi-tui. Prefer existing components for selectors, settings/toggles, loaders, markdown, and layout before building custom primitives.
Theming Rules
Use the theme object passed into callbacks; do not import a global theme. Implement invalidate() so theme changes clear cached styled output. Use explicit color callback parameters such as (s: string) => theme.fg("accent", s).
Key Rules
- Always respect
render(width). - Implement
invalidate()on custom components and child trees. - Propagate focus for embedded inputs.
- Use overlays for temporary panels/dialogs.
- Guard TUI features when running in non-TUI modes.
Using Pi
Source: https://pi.dev/docs/latest/usage
Interface
Interactive mode has a startup header, message area, editor, and footer. The footer shows cwd, session name, token/cache usage, cost, context usage, and current model. The editor border indicates thinking level.
Editor Features
- Type
@to fuzzy-search project files. - Press Tab for path completion.
- Use Shift+Enter, or Ctrl+Enter on Windows Terminal, for multi-line input.
- Paste or drag images in supported terminals.
- Prefix with
!to run a shell command and include output in context. - Prefix with
!!to run a hidden shell command outside model context. - Ctrl+G opens
$VISUALor$EDITOR.
Slash Commands
Important commands: /login, /logout, /model, /scoped-models, /settings, /resume, /new, /name, /session, /tree, /fork, /clone, /compact [prompt], /copy, /export [file], /share, /reload, /hotkeys, /changelog, /quit.
Skills are available as /skill:name; prompt templates expand as /template-name; extensions can register custom commands.
Message Queue
- Enter while the agent is running queues a steering message.
- Alt+Enter queues a follow-up message for after all current work finishes.
- Escape aborts and restores queued messages to the editor.
- Alt+Up retrieves queued messages.
steeringModeandfollowUpModecontrol one-at-a-time vs all-at-once delivery.
CLI Modes
pi [options] [@files...] [messages...]
pi -p "prompt"
pi --mode json "prompt"
pi --mode rpc
pi --export [out]Print mode reads piped stdin and merges it into the initial prompt.
Common Options
Model: --provider, --model, --api-key, --thinking, --models, --list-models.
Session: -c/--continue, -r/--resume, --session, --fork, --session-dir, --no-session, --name/-n.
Tools: --tools/-t, --exclude-tools/-xt, --no-builtin-tools/-nbt, --no-tools/-nt. Built-ins are read, bash, edit, write, grep, find, ls.
Resources: -e/--extension, --skill, --prompt-template, --theme, and corresponding --no-* flags. --no-context-files disables AGENTS.md/CLAUDE.md discovery.
Other: --system-prompt, --append-system-prompt, --verbose, --approve, --no-approve, --help, --version.
Environment Variables
PI_CODING_AGENT_DIR: config directory, default~/.pi/agent.PI_CODING_AGENT_SESSION_DIR: session storage override.PI_PACKAGE_DIR: package directory override.PI_OFFLINE: disable startup network operations.PI_SKIP_VERSION_CHECK: skip version check.PI_TELEMETRY: override install/update telemetry and provider attribution headers.PI_CACHE_RETENTION: setlongwhere supported.VISUAL,EDITOR: external editor.
Design Principles
Pi intentionally does not include built-in MCP, sub-agents, permission popups, plan mode, to-dos, or background bash. Build or install those workflows as extensions/packages, or use containers/tmux/external tools.
Windows Setup
Source: https://pi.dev/docs/latest/windows
Pi requires a bash shell on Windows. It checks, in order:
1. Custom path from ~/.pi/agent/settings.json. 2. Git Bash: C:\Program Files\Gitinash.exe. 3. bash.exe on PATH, such as Cygwin, MSYS2, or WSL.
Git for Windows is sufficient for most users.
Custom Shell Path
{
"shellPath": "C:\cygwin64\bin\bash.exe"
}