Pi — AI Agent Harness
Overview
Pi is an AI agent toolkit that provides a unified API for multiple LLM providers, an agent runtime with tool calling, and an interactive coding agent CLI1. Beyond cloud providers like OpenAI, Anthropic, and Google, it supports local inference engines such as vLLM, Ollama, and LM Studio through its OpenAI-compatible interface.
| Feature | Pi | OpenCode2 | Hermes3 |
|---|---|---|---|
| Language | TypeScript | TypeScript | Python (+ Node TUI) |
| Runtime | TUI | TUI, desktop app, IDE ext. | CLI, TUI, messaging gateways |
| Local models | Yes | Yes | Limited |
| Built-in permissions | No | Yes (plan agent = read-only) | Yes (safe-mode, worktrees) |
| LSP integration | No | Yes | Yes |
| Messaging platforms | No | No | Yes |
| Voice mode | No | No | Yes (record + TTS) |
| Subagents | No | Yes | Yes |
| Web search | No | Yes | Yes |
| Skills system | Yes | Yes | Yes |
| Cron / scheduling | No | No | Yes |
Pi follows a minimal core, aggressively extensible approach.
Adapt Pi to your workflow, not the other way around. Features other agents bake in are intentionally left out and available through extensions, skills, or third-party packages. Key principles:
- No MCP — Skills with READMEs replace MCP; MCP support can be added via extensions
- No sub-agents — Spawn Pi instances via tmux, or build/install them as extensions
- No permission popups — External sandboxing (containers) instead of inline confirmations
- No plan mode — Write plans to files, or build one with extensions
- No built-in to-dos — They confuse models; use a
TODO.mdfile instead - No background bash — Use tmux for full observability and direct interaction
Pi extends its behavior through two mechanisms:
- Extensions — TypeScript modules that modify Pi’s runtime. They can register custom tools, subscribe to lifecycle events, add commands, or modify the UI. Extensions are what you write to change how Pi works.
- Packages — Distribution units that bundle one or more extensions, skills, prompt templates, and themes together for sharing via npm or git. Packages are how you ship extensions and resources to others.
Install
pi-install4 extracts to ~/opt/pi-<version>/, and symlinks the binary into ~/bin/pi. Pi does not include a built-in permission system by default5. It is recommended to run inside a firejail6 container using the custom pi.profile and pi.local7 installed to ~/.config/firejail.
# run Pi sandboxed with
firejail --profile=pi.profile --whitelist=$(pwd) ~/bin/piThe Firejail profile mounts a tmpfs-backed home-directory with only three whitelisted directories:
| Path | Description |
|---|---|
~/bin |
Path to the pi executable |
~/opt |
Installation directory, e.g. ~/opt/pi-0.80.7 |
~/.pi/agent |
Configuration files (user scope) |
Customize pi.local to your needs, to white list user specific project directories.
Configuration
Models
Local models are defined using a dedicated configuration file8:
| File | Description |
|---|---|
~/.pi/agent/models.json |
User Pi Agent model configuration |
Use the /model command to switch between models.
The configuration nests providers under providers.<name>, each containing a models array. Only the model id is required; the rest are optional compatibility tuners for streaming, role handling, and reasoning.
Example for a vLLM server running on localhost:8000:
{
"providers": {
"vllm": {
"baseUrl": "http://localhost:8000/api/v1/",
"api": "openai-completions",
"apiKey": "!cat ~/.pi/agent/api-key.txt",
"models": [
{
"id": "qwen3.6-27b",
"name": "Qwen3.6 27B",
"contextWindow": 262144,
"maxTokens": 65536,
"reasoning": true,
"compat": {
"supportsDeveloperRole": false
}
}
]
}
}
}Provider-level fields:
| Field | Description |
|---|---|
baseUrl |
Endpoint of the inference server (vLLM, Ollama, LM Studio, etc.) |
api |
API protocol; Pi uses OpenAI-compatible completions for local engines |
apiKey |
API key; the ! prefix runs a shell command to read it from disk |
Model-level fields:
| Field | Description |
|---|---|
id |
Required. Must match the model name registered on the server |
name |
Human-readable display name shown in the Pi UI |
contextWindow |
Maximum input context length in tokens |
maxTokens |
Maximum output tokens per response |
reasoning |
Enables reasoning/thinking mode if the model supports it |
compat |
Set supportsDeveloperRole:false when the engine does not recognize the developer message role |
Settings
Pi uses JSON settings files with project settings overriding global ones9.
Edit directly or use /settings for common options.
| File | Description |
|---|---|
~/.pi/agent/settings.json |
Global Pi Agent settings (all projects) |
.pi/settings.json |
Project-local settings (overrides global) |
Key setting categories include model & thinking, UI & display, compaction, retry, shell, sessions, and resources. Nested objects are merged rather than replaced when project settings override global ones.
Resources in the settings define where Pi loads extensions, skills, and packages:
| Setting | Description |
|---|---|
packages |
npm or git packages to load resources from |
extensions |
Local extension file paths or directories |
skills |
Local skill file paths or directories |
Usage
The Pi editor provides several shortcuts and conveniences for interactive use:
| Feature | Shortcut |
|---|---|
| File reference | Type @ to fuzzy-search project files |
| Path completion | Press Tab to complete paths |
| Copy last response | Ctrl-X or /copy command |
| Shell command (visible) | Prefix with !command — output sent to model |
| Shell command (hidden) | Prefix with !!command — output not sent to model |
| External editor | Ctrl+G opens $VISUAL, $EDITOR, or fallback |
See the keybindings documentation10 for the full list of shortcuts.
Pi also supports slash commands typed in the editor:
| Command | Description |
|---|---|
/new |
Start a new session |
/quit |
Quit Pi |
/compact |
Summarize older messages to free context |
/export |
Export session to HTML or JSONL |
/import |
Import and resume a session from a JSONL file |
Skills
A skill is a self-contained directory with a SKILL.md file containing specialized instructions, helper scripts, and reference docs for a specific task. Pi loads them on-demand when your request matches a skill’s description. Pi discovers skills from these locations:
| Location | Scope |
|---|---|
~/.pi/agent/skills/ |
Global skills (*.md files in root) |
~/.agents/skills/ |
Global skills (directories with SKILL.md) |
.pi/skills/ |
Project-local (trusted projects only) |
.agents/skills/ |
Project-local, recursive discovery |
Skills register as /skill:name commands in the interactive REPL:
/skill:brave-search # Load the skill
/skill:pdf-tools extract # Load with argumentsWithout the slash command, Pi may still load skills automatically when a task matches a skill’s description — the agent reads the SKILL.md on demand and follows its instructions.
Extensions
Extensions are TypeScript modules that modify Pi’s runtime — they register custom tools, subscribe to lifecycle events, add commands, shortcuts, and more. They run directly via jiti11, so no compilation step is needed.
| Location | Scope |
|---|---|
~/.pi/agent/extensions/*.ts |
Global (all projects) |
.pi/extensions/*.ts |
Project-local (trusted only) |
Additional paths can be specified in settings under extensions.
Plan Mode
Pi ships with a plan-mode12 extension in its examples directory. Copy it into your global extensions folder:
# for example
cp -r ~/opt/pi-0.80.7/examples/extensions/plan-mode ~/.pi/agent/extensions/Pi auto-discovers subdirectories with index.ts, so no configuration is needed. Use /plan or Ctrl+Alt+P to toggle read-only exploration mode, then execute or refine the generated plan.
Packages
Manual
Use pi install13 to add packages from npm, git, or local paths. The command writes the package entry to your settings file so Pi loads it persistently on every startup.
pi install npm:pi-web-accessInstalling npm:pi-web-access...
added 1 package, and audited 2 packages in 1s
found 0 vulnerabilities
Installed npm:pi-web-accessInteract with packages:
# show installed packages from settings
pi list
# delete a package
pi remove npm:<name>Settings
Packages can appear in both global and project settings. When the same package exists in both, the project entry takes full precedence. Package identity is determined by name (npm), repository URL without ref (git), or resolved absolute path (local).
~/.pi/agent/settings.json
{
"packages": ["npm:pi-web-access"]
}Missing packages auto-installed when configured in the settings
Web Search
| Package | Description |
|---|---|
pi-web-access |
It registers three tools: web_search (search with cited sources), fetch_content (extract readable content from URLs, GitHub repos, YouTube videos, PDFs, and local video files), and get_search_content (retrieve stored results for later reference). |
Search supports multiple providers — OpenAI, Exa, Brave, Parallel, Tavily, Perplexity, and Gemini — and falls back automatically when a provider is unavailable. It works with zero configuration via Exa MCP, but API keys give more control over which provider is used.
~/.pi/web-search.json
{
"workflow": "none",
"provider": "exa"
}workflow: "none"—web_searchcall returns raw synthesized results immediately — no browser opens, no summary model is invoked, and no interactive review happens. Useful for speed or headless environments. The setting can also be toggled at runtime with/curator on,/curator off, or overridden per-call via theworkflowparameter onweb_search.provider: "exa"— pins a default search provider. Without this,automode tries OpenAI first (when Codex auth is available), then falls through Exa, Brave, Parallel, Tavily, Perplexity, Gemini API, and finally Gemini Web.
Footnotes
Pi Project
https://github.com/earendil-works/pi https://pi.dev/docs/latest↩︎OpenCode
https://opencode.ai↩︎Hermes Agent
https://hermes-agent.nousresearch.com↩︎pi-installScript, GitHub
https://github.com/vpenso/scripts/blob/master/bin/pi-install↩︎Pi Containerization, GitHub
https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/containerization.md↩︎Firejail
https://firejail.wordpress.com
https://github.com/netblue30/firejail↩︎Firejail Profiles, GitHub
https://github.com/vpenso/scripts/tree/master/etc/firejail↩︎Custom Models Documentation
https://pi.dev/docs/latest/models↩︎Settings Documentation
https://pi.dev/docs/latest/settings↩︎Keys, Pi Documentation
https://pi.dev/docs/latest/keybindings↩︎jiti — Just-In-Time TypeScript https://github.com/unjs/jiti↩︎
Plan Mode Extension, GitHub
https://github.com/earendil-works/pi/blob/main/packages/coding-agent/examples/extensions/plan-mode/index.ts↩︎Packages Documentation
https://pi.dev/docs/latest/packages↩︎