Pi coding agent settings
Pi is configured from pnpm-managed packages plus readonly chezmoi sources under home/dot_pi/agent/. The page covers the installed packages, profile-specific settings and models, the shared MCP registry path, and the APPEND_SYSTEM.md operating layer that gives Pi the same working rules other harnesses receive.
Mental model
| Piece | Source | Target / effect |
|---|---|---|
| Pi packages | home/readonly_dot_default-pnpm-pkgs | pnpm globals used by Pi |
| Settings + models | home/dot_pi/agent/readonly_settings.{work,personal}.json + work/shared readonly_models.json or personal readonly_models.personal.json | ~/.pi/agent/ |
| MCP servers | home/.chezmoidata/mcp_servers.yaml | ~/.pi/agent/mcp.json |
| System prompt | home/dot_pi/agent/readonly_APPEND_SYSTEM.md | ~/.pi/agent/APPEND_SYSTEM.md, appended to Pi's default prompt |
| Session diagnostics | scripts/analyze_pi_session.py | privacy-safe aggregate metrics from one saved Pi v3 session |
Using it
Installed packages
Pi globals are installed via pnpm from home/readonly_dot_default-pnpm-pkgs to ~/.default-pnpm-pkgs.
| Package | Purpose |
|---|---|
@earendil-works/pi-coding-agent | Core Pi agent |
@earendil-works/pi-tui | Pi TUI (work profile) |
pi-mcp-adapter | MCP adapter extension |
pi-subagents | Subagent delegation extension (parallel, isolated context) |
Profile defaults
| Profile | Default | Extra providers/models |
|---|---|---|
| work | anthropic / claude-fable-5.1 | configured work models |
| personal | anthropic / claude-fable-5.1 | llama-cpp |
The local llama.cpp provider for Pi is covered in Model registry & routing and llama.cpp local inference. Both readonly_models*.json files also carry providers.openrouter.modelOverrides: moonshotai/kimi-k3 allows only Fireworks, Together, and BaseTen under a $16/M completion cap, while z-ai/glm-5.3-flash and z-ai/glm-5.2 allow only FP8-or-higher quantization with a 24 t/s preferred floor, and deepseek/deepseek-v4.1-flash carries a 35 t/s preferred floor under a $1.20/M completion cap with no quantization filter (user call 2026-09-11: few DeepSeek endpoints declare a quantization, so the allowlist starved the route), and openai/gpt-6-astra allows only OpenAI's Flex service tier (only: ["openai/flex"], half the standard endpoint price; base slugs never match service tiers). None of these objects set sort, so OpenRouter's default load balancer keeps uptime then price-weights remaining endpoints. Both use compat.openRouterRouting (see OpenRouter routing).
Shared settings
| Setting area | Behavior |
|---|---|
| Context compaction | Automatic context compaction uses a hybrid sliding window. |
| Cache visibility | Significant prompt-cache misses appear in the transcript; the footer and /session expose Pi's own cache accounting. |
| Retries | Exponential backoff retries. |
| Extension loading | Pi loads the chezmoi-managed runtime extensions plus pi-mcp-adapter and pi-subagents from the stable ~/.local/share/pnpm-global-links/node_modules/ tree that ,install-pnpm-pkgs rebuilds after every sync (pnpm 11+ global install paths are hashed and move on update). |
| Native tools | runtime-parity.ts enables grep, find, and ls alongside Pi's default tools unless explicit CLI tool-selection flags override the defaults. |
| Delegation | pi-subagents adds subagent and subagent_wait for isolated child contexts; named review profiles cover reviewer, verifier, live-UI, and findings-audit phases. |
| Session hooks | ai-kb-recall.ts invokes the shared session-context hook, stages depth-aware per-turn recall candidates for the k-agent-smol judge (pointer injection only) plus the correction directive, and forwards tool results to the shared worklog. |
| PATH | Shell PATH order keeps ~/.local/share/pnpm/bin ahead of runtime-manager shims so pi resolves to the pnpm-managed binary. |
| Secrets | GEMINI_API_KEY and OPENROUTER_API_KEY are picked up from environment variables exported via pass in config.fish.tmpl. ANTHROPIC_API_KEY and OPENAI_API_KEY are not exported; those are subscription logins, and any tool needing a raw key reads pass itself. |
Automatic context compaction triggers when context exceeds contextWindow − reserveTokens (16384), keeps the most recent keepRecentTokens (80000) verbatim, and LLM-summarizes older turns. It merges iteratively with the prior summary so it never decays into a summary-of-a-summary.
keepRecentTokens is raised from Pi's 20000 default to preserve far more high-fidelity recent context before any lossy summarization. The setting is global, not per-model.
80000 is sized for the 262144-token local Nemotron window, ~30% recent-verbatim. It also remains below the work-profile Qwen3.8 131072-token context and the configured OpenRouter default's context limit.
GPT context selection
Pi and OMP share ~/lib/shared/context_mode.ts, loaded by each harness's managed context-mode.ts extension.
GPT models default to a short working window. Other model families and global settings stay unchanged.
| Command | Effect |
|---|---|
/context-mode short | Use the smaller of the native window and the catalog's long-context input threshold. If tier metadata is absent, use a 272,000-token working budget. |
/context-mode long | Opt this provider/model into its known native or advertised maximum. |
/context-mode status | Show the selected mode and effective working window. |
For Copilot Astra, short uses 272,000 tokens. The fallback for other GPT models is a working budget, not a guarantee about their pricing.
Thresholds come from Pi's cost.tiers[].inputTokensAbove or OMP's cost.longContext.inputThreshold; the earliest valid threshold wins.
Selections are custom session entries, not prompt text or global preferences. They follow the active branch and survive resume; selecting another provider/model does not inherit the previous model's override.
Pi reapplies on model selection and before each prompt. OMP reapplies before each prompt or an idle /context-mode command because its native model-change event is not exposed to extensions.
Switching to short with history already at or above the short window is refused without running a summarizer.
Use /compact or start a new session, then select short. An active turn/model change also prevents selection.
Native compaction and output sizing use the selected window; the model route, explicit effort, output-capacity metadata, and cache controls are not replaced.
Earlier compaction is not a hard pre-send token limit or a credit cap: large pending input and compaction itself can still cost money.
The selector requires the extension to load; it does not rewrite separately pinned child roles or enable extensions in restricted native workers.
Prompt-cache and compaction diagnostics
Both profiles set showCacheMissNotices: true. Pi emits a transcript notice only for a significant miss after cache activity has been observed; providers that never report cache counters are not treated as misses. The interactive footer shows the latest cache-hit rate, and /session shows cached versus uncached prompt tokens plus cumulative cache re-billing.
The repo does not duplicate Pi's cache-miss algorithm. scripts/analyze_pi_session.py adds the offline view Pi lacks:
python3 scripts/analyze_pi_session.py /path/to/session.jsonl
python3 scripts/analyze_pi_session.py /path/to/session.jsonl \
--max-compactions 2 \
--max-reread-ratio 0.25 \
--min-cache-hit-rate 0.50
The analyzer accepts only Pi session format v3. It follows the active parentId chain, aggregates assistant token/cache/cost fields, records compaction tokensBefore, and compares structured built-in read calls after compaction with the compaction's details.readFiles. It reports only counts and ratios: prompts, summaries, tool output, and file paths never appear.
cache.hit_rate is null until a positive provider cache counter is observed. compaction.reread_ratio is null when no post-compaction reads can be measured, and read_tracking_complete shows whether every active-branch compaction exposed default read-file details. Exit status 2 means an explicit threshold failed; malformed input or an unsupported format exits 1.
Pi loads packages from the pnpm global link tree paths to avoid Pi-managed npm update prompts; pi install is not used. Each package's package.json pi field declares its extension/skills/prompts, which Pi auto-loads.
The installed Pi discovers ~/.agents/skills/ natively, so no skills bridge package is configured. See Runtime recall wiring. @earendil-works/pi-tui stays pnpm-managed but is not loaded as a Pi extension package.
The subagent tool supports review, scout, and parallel audits while keeping the parent session's token use bounded on long tasks. It is fully local: no network/telemetry beyond the model calls the child agents make.
Harness operating layer (APPEND_SYSTEM.md)
Pi's built-in default prompt is minimal: persona, tools list, "be concise", and "show file paths". Cursor injects a thicker operating layer: tool policy, task/todo discipline, code citations, proactiveness, and edit-scope rules.
~/.pi/agent/APPEND_SYSTEM.md closes that gap.
Prompt order:
Pi default -> operating layer -> project context
Pi discovers APPEND_SYSTEM.md through DefaultResourceLoader and appends it before the <project_context> block that wraps AGENTS.md / CLAUDE.md. ,q skips this file: it passes a short --system-prompt and an empty --append-system-prompt.
Why APPEND_SYSTEM.md, not SYSTEM.md:
- additive file preserves Pi's default tools list and self-doc pointers.
- replacement file would lose those defaults.
- source is profile-agnostic and installed readonly.
Scope: this is harness parity, not a replacement for AGENTS.md.
runtime-parity.ts supplies the full home SOP outside $HOME through before_agent_start. It preserves the existing system prompt and skips insertion when a canonical native context path or the complete SOP body is already present. Explicit no-extension workflows bypass this adapter. A missing SOP emits a diagnostic and preserves the base prompt.
Ported mechanics are the set difference:
Cursor built-in prompt - Pi built-in prompt
Included mechanics:
- tone/style: no emojis, no colon before a tool call, backtick paths/symbols.
- tool calling: use dedicated file tools, parallelize independent calls, don't name tools to the user.
- code changes: read before edit, fix introduced linter errors, avoid narrating comments.
- autonomy: finish before yielding.
- task management: todos for complex tasks.
- structured enumerated questions.
file_path:line_numbercitations.
Excluded Cursor-only mechanics:
@-mentions and system-tag handling.- terminal-files convention.
- Plan/Agent mode selection.
- Cursor's
start:end:pathcitation UI. - inline line-number disambiguation, because Pi's read tool returns raw text without
LINE|prefixes.
The read-tool detail was verified in core/tools/read.ts; there is no line-prefix stream for the inline-number rule to disambiguate.
Where project context overlaps, AGENTS.md wins.