Personal Pi agent configuration with extensively customized extensions, packages, skills, and TUI theme.
- Node.js 20+ (use nvm or your package manager)
- npm bundled with Node.js
git clone <repo-url> ~/.pi/agent
cd ~/.pi/agentnpm install -g @earendil-works/pi-coding-agentVerify:
pi --versionCopy the template and fill in your own values:
cp .env .env.localEdit .env.local:
| Variable | Description | Required |
|---|---|---|
LITELLM_BASE_URL |
Base URL of your LiteLLM proxy | Yes — no LLM access without it |
LITELLM_API_KEY |
API key for the LiteLLM proxy | Yes |
TAVILY_API_KEY |
API key for Tavily web search | Optional — needed for web search skills |
PI_EXT_NTFY_ENABLED |
Set to 1 to enable mobile push notifications via ntfy |
Optional |
PI_EXT_NTFY_TOPIC |
ntfy topic name (any unique string) | Required if ntfy is enabled |
Treat .env.local as sensitive — it's already in .gitignore.
cd npm
npm install
cd ..This installs all pi packages declared in npm/package.json (litellm provider, tavily, subagents, amplike, etc.).
pi --list-modesExpected output: rush, smart, deep.
Try a quick test:
pi "hello, world"The skills/ directory contains custom skills:
- code-explorer — deep code understanding and tracing across multi-file flows
- skill-creator — create, edit, and benchmark agent skills
They are auto-discovered from ~/.pi/agent/skills/.
The agents/ directory can hold custom subagent definitions (currently empty).
# Update pi itself + all npm packages in npm/
pi update
# Or just packages (skip pi self-update):
pi update --extensions
# Pull config changes from the repo:
cd ~/.pi/agent && git pullpi update --extensions handles the npm packages declared in npm/package.json automatically. You only need to manually npm install in npm/ on a fresh clone (step 4 in Quick start).
Extensions in
extensions/are auto-discovered — both single.tsfiles and directories withindex.tsare loaded automatically. No need to register them anywhere insettings.json.
Pi starts with the current shell environment, which is the highest priority and is never overwritten. The _env-injector extension (extensions/_env-injector.ts) then adds variables that the shell does not already define, layering file-based sources in this priority order (later overrides earlier):
| Priority | Source | Description |
|---|---|---|
| — (highest) | Shell / OS environment | Actual shell env vars, .profile, systemd, etc. Always wins; file sources can only add variables the shell does not define. |
| 1 (lowest) | ~/.pi/agent/settings.json → "env" block |
Global Pi settings, supports $VAR / ${VAR} expansion |
| 2 | ~/.pi/agent/.env |
Global dotenv (checked into version control) |
| 3 | ~/.pi/agent/.env.local |
Global dotenv secrets (gitignored) |
| 4 | .pi/settings.json → "env" block |
Per-project Pi settings, supports $VAR / ${VAR} expansion |
| 5 | $cwd/.env |
Project-level defaults |
| 6 (file sources) | $cwd/.env.local |
Project-level local overrides |
Tiers 4–6 apply only to trusted projects. A file tier that redefines a shell variable has no effect, and later tiers referencing that name expand to the shell value.
Project trust is resolved the way Pi resolves it, except that .env/.env.local count as trust-requiring even though Pi does not list them:
--approve/-atrusts,--no-approve/-nadeclines (last flag wins, parsing stops at--).- The nearest saved decision in
~/.pi/agent/trust.jsonwins — Pi walks up parent folders, so trusting a parent trusts its subdirectories. defaultProjectTrust:"always"trusts,"never"declines,"ask"(or unset) cannot be answered before extensions load."ask"defers to asession_starthandler that applies tiers 4–6 ifctx.isProjectTrusted()— this covers an interactive Trust answer, including this session only, and projects whose only trust-requiring resource is their env files (which Pi auto-trusts).
So a repo Pi gates on cannot inject or override LITELLM_API_KEY via its .env.local, while --no-approve or a saved false also suppresses project tiers for a project you normally trust. A repo whose only trust-requiring resource is its env files is still auto-trusted by Pi, so its env files apply at session_start unless you decline with -na or a saved false.
Values the injector wrote itself are recorded by hash in __PI_ENV_INJECTOR_KEYS, so they are not mistaken for shell variables on a later run in the same process. Editing an env file and running /reload — or switching sessions — re-reads it, as does a nested pi started from a pty shell. Only a value that differs from the recorded hash is left untouched: a genuine export, including FOO=bar pi in a nested shell. Only hashes are stored, never values.
| Extension | Description |
|---|---|
left-strip-tools.ts |
Replaces the default full-block colored backgrounds on tool call/result lines with a thin colored bar on the left edge. Preserves syntax highlighting, diffs, and truncation warnings. Each tool (read, bash, write, grep, find, ls) gets a color-coded strip — pending (blue), success (green), error (red). edit is intentionally not wrapped (its built-in renderer paints its own line backgrounds, which clash with the strip). Results are collapsed by default (showing line count) with Ctrl+O to expand. |
keybindings.json |
Overrides tui.input.newLine to use Shift+Enter / Ctrl+N instead of plain Enter (which submits). |
themes/dark-strip.json — Custom dark-strip theme |
Dark theme tuned for the left-strip tool rendering with distinct colors for tool states (toolPendingBg, toolSuccessBg, toolErrorBg), custom message backgrounds, and a cyan/blue accent palette. |
| Extension | Description |
|---|---|
notify.ts |
Alerts you when pi waits for human input (agent_end). Sound: terminal bell + native audio player (paplay/pw-play/aplay) with bundled notification.wav fallback. Desktop: OSC 777 / Kitty OSC 99 / Windows toast. Mobile push (optional): sends an ntfy.sh notification if no activity within a configurable timeout (default 30s). Set PI_EXT_NTFY_ENABLED=1 and PI_EXT_NTFY_TOPIC in .env.local. Tags, priority, sound all configurable. Includes idle detection via xprintidle to avoid spamming when you're away. |
| Extension | Description |
|---|---|
tool-call-revert.ts |
Detects when a model outputs malformed tool calls (e.g., DeepSeek V4 DSML text blocks instead of proper API blocks) and automatically reverts + retries the prompt as if the bad response never happened. The bad response is filtered out of context so the model never sees it — even on future turns. Gives up after 5 consecutive failures to prevent infinite loops. |
models.json — Model compatibility overrides |
Configures DeepSeek V4 Flash with reasoning: true, a custom thinking-level map (off→null, medium→high, high→max), and DeepSeek-compat thinking format. |
| Extension | Description |
|---|---|
fusion.ts |
Runs a prompt against a panel of models in parallel, then a judge model compares responses and returns structured JSON analysis: consensus, contradictions, partial coverage, unique insights, and blind spots. Configured via ~/.pi/agent/fusion.json or .pi/fusion.json. Toggle with /fusion on/off. Widget: shows status in the footer. Self-contained (no external packages). |
| Extension | Description |
|---|---|
web-search.ts |
Registers a web_search tool powered by the Tavily API. Supports time-range filtering, search depth selection (ultra-fast through advanced), and rich result rendering with line-count summaries. Requires TAVILY_API_KEY. Also includes a web_research tool (disabled) for deep Tavily research (30–120s, async delivery). |
visit-webpage.ts |
Registers a visit_webpage tool that fetches URLs via Jina Reader (JavaScript-rendered HTML → markdown) or downloads images to temp files. Supports Jina auth via JINA_API_KEY. Handles retries on 5xx/451 errors, content-length limits (5MB for images, 100KB for pages), and 60s timeout. |
| Extension | Description |
|---|---|
subagent.ts |
Registers a subagent tool that spawns isolated child sessions for parallel or single-task delegation. Provides 6 built-in agent roles: reviewer (code review), scout (codebase recon), researcher (web research), context-builder (analysis), worker (implementation), delegate (generic). Supports concurrent execution (up to panel concurrency). Widget: shows per-agent status in the footer. Shortcut Alt+O: opens a TUI overlay to peek subagent output, navigate between agents (←/→), and scroll (↑/↓). Automatically compatible with tool-call-revert inside child sessions. |
| Extension | Description |
|---|---|
pty/index.ts |
Full-featured PTY manager with 6 tools: pty_start (spawn SSH/REPL/db shell), pty_send (send input with escape-sequence interpretation), pty_drain (read new output, cursor-advancing), pty_tail (peek without advancing), pty_list (list all sessions), pty_kill (terminate). Uses zigpty + @xterm/headless for accurate terminal emulation. Widget: shows active sessions in the footer. Shortcut Alt+T: opens a TUI overlay with tabbed per-session viewport and scrolling. Supports \n, \t, \x1b, \uXXXX escape sequences in input. |
| Extension | Description |
|---|---|
pi-goal-audit.ts & pi-goal-audit-helpers.ts |
Custom fork of Michaelliv/pi-goal that adds an independent auditor subagent before marking goals complete. The auditor uses read-only tools (read, grep, find, ls, bash) and must output <approved/> for the goal to pass. Supports --tokens budget flag, continuation prompts, and token/time tracking. /goal command manages goal lifecycle (set, pause/stop, resume, clear/cancel, complete, blocked). Auto-continuation stops when a run makes no progress, pauses the goal on user abort (TUI Esc or RPC/IDE abort), and pauses after 20 consecutive audit failures; the auditor has a 100-minute timeout and UI dialogs time out instead of hanging RPC clients. |
| Extension | Description |
|---|---|
preset.ts |
Switchable named presets that filter active tools and skills. Supports allowlist (tools-enabled) and denylist (tools-disabled) per category. Stored in ~/.pi/agent/presets.json (global) and .pi/presets.json (project). Menu: /preset opens an interactive selector. Fast path: /preset <name> activates directly. Shortcut Ctrl+Shift+P: cycles through presets. CLI flag: --preset <name> at startup. Built-in all and none presets. Interactive editor via /preset → Edit/Customize with full category browsing, toggle (Space), mode toggle (m), select all/none (a/n), and description scrolling (←/→). Widget: shows active preset name + tool/skill counts in the footer. |
| Extension | Description |
|---|---|
perf-speed.ts |
Per-turn prefill and decode speed widget for the footer. Measures prefill speed (new input token delta / time-to-first-token, tok/s) and decode speed (output tokens / generation time, tok/s). Uses pi-footer event widget (widget ID: perf-speed). Emits values only on change to avoid unnecessary updates. |
| Extension | Description |
|---|---|
prompt-history.ts |
Persists all submitted prompts to ~/.pi/agent/prompt-history.json (last 20). On startup, injects them into the editor's history so ↑ immediately recalls previous prompts — no first submit needed. Uses prototype patching on Editor.prototype.handleInput and addToHistory. |
| Extension | Description |
|---|---|
_env-injector.ts |
Loads environment variables from settings.json env blocks and .env/.env.local files (both global and project-level) before any other extension runs. Shell env vars always win (file sources only add what the shell does not define); file tiers then cascade global settings → global .env → global .env.local → project settings → project .env → project .env.local. Project tiers honor Pi's trust decision (--approve/--no-approve, nearest trust.json entry, defaultProjectTrust, else an interactive answer via a session_start fallback), with .env/.env.local counted as trust-requiring. Its own values stay overridable on /reload, session switch, and in nested pi processes (tracked by value hash in __PI_ENV_INJECTOR_KEYS). Supports $VAR, ${VAR}, and $$ shell-style expansion within values. |
_install-deps.ts |
Scans sibling extension directories for package.json files and auto-runs npm install if node_modules is missing or incomplete. Runs before other extensions, ensuring deps like zigpty and @xterm/headless (used by the PTY extension) are ready. |
| Extension | Description |
|---|---|
context-dump.ts |
Registers /context-dump command that dumps the full session context (all messages, model info, token usage, raw session entries, system prompt) to a timestamped JSON file. Useful for debugging context bleed, audit traces, or inspecting what the LLM actually sees. |
| Package | Description |
|---|---|
pi-provider-litellm |
LiteLLM API provider — connects to a private proxy exposing multiple local/cloud models (DeepSeek, Qwen, more). |
pi-skill-tavily |
Tavily web search skills (tavily-research, tavily-search, tavily-extract) for the agent. |
pi-amplike |
Amplike modes system: /mode command, /handoff, /session query, btw footnotes, mode definitions in modes.json. |
pi-footer |
Customizable footer bar with widgets: cwd, context bar, compaction status, model name, token cost, git branch/diff/remote, preset status, fusion status, perf-speed. Configured in extensions/pi-footer.json. |
pi-mcp-adapter |
MCP (Model Context Protocol) adapter — connects to external MCP servers defined in mcp.json. Ready for use. |
pi-agentic-compaction |
Intelligent context compaction that condenses old turns to save tokens while preserving key information. Runs on DeepSeek V4 Flash. |
pi-openplan |
Structured planning: /plan commands (write, read, list, edit, question), plan_write/plan_read/plan_edit/plan_question/plan_list tools, auto-formatted YAML frontmatter, plan storage in .pi/plans/. |
pi-interactive-shell |
Interactive CLI session overlay (interactive_shell tool) for delegating to TUI coding agents (pi, Claude Code, Gemini, Codex, Cursor) with modes: interactive, hands-free, dispatch, monitor. |
@dreki-gg/pi-context7 |
Fetches current library documentation by name or Context7 ID before coding against third-party APIs — prevents relying on stale training data. |
Configured in modes.json — all use DeepSeek V4 Flash via LiteLLM with different thinking levels:
| Mode | Thinking | Use Case |
|---|---|---|
rush |
Off (no thinking) | Quick lookups, simple edits, low-latency tasks |
smart |
Medium (mapped to high) |
Default balance — general coding |
deep |
High (mapped to max) |
Complex architecture, debugging, planning |
| Skill | Description |
|---|---|
| code-explorer | Deep code understanding and tracing across multi-file flows. Uses CodeGraph and CodeSearch for fast cross-file analysis. Automatically triggered before complex cross-file edits. |
| skill-creator | Tools to create, edit, and benchmark custom agent skills. |
| pi-goal-writer | Drafts and reviews strong /goal objectives with clear success criteria, verification steps, constraints, and iteration policy. |
~/.pi/agent/
├── AGENTS.md # Agent rules (coding guidelines, git conventions)
├── settings.json # Main pi config — models, packages, modes
├── modes.json # Mode definitions (rush/smart/deep)
├── models.json # Per-provider model overrides (thinking maps, compat)
├── litellm-models.json # Cached LiteLLM model catalog
├── mcp.json # MCP server config (empty, ready for use)
├── .env # Template — copy to .env.local
├── .env.local # Local secrets (gitignored)
├── npm/ # Pi packages (package.json + node_modules)
├── extensions/ # Custom TS/JS extensions
│ ├── _env-injector.ts # Dotenv/settings env injection (shell env wins)
│ ├── _install-deps.ts # Auto npm install for sibling extensions
│ ├── context-dump.ts # /context-dump command for debugging
│ ├── fusion.ts # Multi-model deliberation panel + judge
│ ├── left-strip-tools.ts # Colored left-strip tool call rendering
│ ├── notify.ts # Sound/desktop/ntfy push notifications
│ ├── perf-speed.ts # Prefill/decode speed widget
│ ├── pi-footer.json # Footer widget layout config
│ ├── pi-goal-audit.ts # Goal mode with independent auditor
│ ├── pi-goal-audit-helpers.ts # Goal audit helper functions
│ ├── preset.ts # Switchable tool/skill presets
│ ├── prompt-history.ts # Persisted prompt history across sessions
│ ├── subagent.ts # Isolated child session delegation
│ ├── tool-call-revert.ts # Auto-retry on malformed tool calls
│ ├── visit-webpage.ts # Webpage/image fetch tool (Jina Reader)
│ ├── web-search.ts # Tavily web search tool
│ ├── notification.wav # Sound file for notification extension
│ └── pty/ # Persistent PTY session manager
│ ├── index.ts # pty_start / send / drain / tail / list / kill
│ └── package.json # Deps: zigpty, @xterm/headless
├── skills/ # Custom skills
│ ├── code-explorer/ # Multi-file code tracing & understanding
│ ├── pi-goal-writer/ # Goal objective drafting & review
│ └── skill-creator/ # Create, edit & benchmark agent skills
├── agents/ # Custom subagent definitions (empty)
├── themes/ # Custom TUI themes
│ └── dark-strip.json # Dark theme for left-strip tools
├── sessions/ # Session logs
├── bin/ # Helper binaries (rg, fd)
└── keybindings.json # Custom keybindings (Shift+Enter newline)