Getting Started with Pi Coding Agent: A Minimal Core, Session Trees, and the 1.0 Update
Pi (@earendil-works/pi-coding-agent) takes a different design approach from mainstream coding agents. Claude Code offers a full-featured environment that works out of the box, with built-in permission review. Pi positions itself as a minimal core you can extend yourself, adding capabilities as you need them.
The project officially released 1.0.0 on October 1, 2026. The release continues its commitment to keeping the core minimal (“hold the line”), bringing proven Codemode, native MCP support, five tool exposure levels, and a fullscreen terminal interface (TUI) into the core. It also introduces Pi Durable, an experimental framework for long-running agents.
For developers familiar with AGENTS.md and Claude Code, Pi natively supports multiple model providers and local endpoints, and offers tree-structured conversation history (sessions) and a TypeScript extension system with no build step, making it easy to adjust your workflow as your needs change.
A Minimal Core and a Commitment to Open Source: Pi’s Origins and Design
Pi’s creator, Mario Zechner (GitHub: badlogic), also created the cross-platform Java game framework libGDX and RoboVM. Development began as an independent project in August 2025. In April 2026, the project officially joined Earendil Works, co-founded by Armin Ronacher, the creator of Flask and Sentry.
In his announcement, “I’ve sold out”, Zechner promised that the project would remain open source permanently, with no added barriers to contributing:
MIT, forever. Non-negotiable. No CLA, no DCO, no new hoops to jump through.
Although Earendil owns the trademark, the founding team jointly retains authority over architectural decisions, aiming to avoid the familiar path of open-source projects becoming closed after a commercial acquisition.
+--------------------------------------------------------+
| CLI / TUI / Print / JSON / RPC / TypeScript SDK |
+--------------------------------------------------------+
| Extensions & MCP Tools | QuickJS Codemode (WASM) |
+--------------------------------------------------------+
| pi-agent-core (4 Tools: read, bash, edit, write) |
+--------------------------------------------------------+
| pi-ai (Unified Provider Engine: Anthropic, Local, etc) |
+--------------------------------------------------------+
Three Core Design Principles
The official repository describes Pi as a “self-extensible coding agent” and makes three design choices:
- Minimal core: Pi enables only four basic tools by default:
read,bash,edit, andwrite(withpowershell,grep,find, andlsalso available as options). Everything else, including permission controls, plan mode, sub-agents, and external integrations, uses the same extension API. - Model neutrality: The core is not tied to a particular model vendor.
@earendil-works/pi-aiprovides a unified API layer with native support for subscription authentication, API keys, local GGUF model files, and compatible endpoints from different providers (OpenAI / Anthropic / Google / Meta Muse). - Direct use of local permissions: By default, all tools run with the current operating-system user’s permissions. Pi itself has no built-in sandbox. For isolation, the official guidance recommends adding a microVM (such as Gondolin, a lightweight Linux isolation environment), a container (Docker), or a sandbox policy engine (such as OpenShell).
NOTE
Further reading: The Evolution of Vibe Coding (Part 2): Production Outages, Long-Term Costs, and the Non-Negotiables of Software Engineering
Five Execution Modes and Environment Setup
Pi requires Node.js 22.19 or later. Install it with the official script or with a global npm install:
# One-command installer for macOS / Linux
curl -fsSL https://pi.dev/install.sh | sh
# Or install globally through npm (--ignore-scripts skips install scripts)
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
Run pi --version after installation to verify it.
Five Execution Modes
Pi supports interactive terminal use and embedding in other programs, with five execution modes:
- Interactive TUI mode: Run
piin the terminal; this is the default interface for everyday development. Since 1.0, it runs fullscreen by default. - Print mode:
pi --print "task"outputs the result and exits when the task is complete. It also accepts piped input, such asgit diff | pi --print "Review this change". - JSON mode:
pi --mode json "..." > events.jsonloutputs a complete structured event stream for later analysis and auditing. - RPC mode: Reads JSONL commands from stdin and returns events through stdout, allowing external programs, IDEs, or custom toolchains to control Pi continuously.
- TypeScript SDK: Embeds the Pi runtime directly in Node.js/TypeScript applications.
Two Configuration Layers
Pi separates configuration into user and project layers:
- User layer (
~/.pi/agent/): Stores global preferences insettings.json, login credentials inauth.json, custom endpoints inmodels.json, globalmcp.json, and four resource directories:extensions/,skills/,prompts/, andthemes/. - Project layer (
.pi/in the working directory): Uses the same directory structure as the user layer, except that the credential fileauth.jsonand the custom endpoint filemodels.jsonexist only in the user layer. Executable project code, such as customextensions/, loads only after granting “project trust” by saving a decision with/trustin interactive mode or passing the-astartup flag. Use-na(no-approve) to reject project configuration. Plain-text instruction files such asAGENTS.mdare loaded as read-only input regardless of project trust settings.
Connecting Models and Local Endpoints
Run /login in interactive mode to select a provider and sign in with a subscription or enter an API key (1.0 supports ChatGPT subscription login and the Earendil Radius service). Use /model to switch models. Model strings follow the format provider/model:thinking, with thinking levels ranging from off to max. Adjust the level with /thinking, then press Ctrl+S to save it as the startup default.
To connect to a local model server, such as Ollama or vLLM, use the built-in llama.cpp router to discover GGUF files automatically, or configure a compatible endpoint in ~/.pi/agent/models.json:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [{ "id": "qwen2.5-coder:7b" }]
}
}
}
The apiKey field accepts $ENV_VAR to read the value from an environment variable, or !command to run a command at request time and use its output as the value.
Everyday Commands and Session Tree Workflows
Everyday use falls into three areas: input prefixes, in-task message handling, and session branch management.
Common Input Prefixes and Keyboard Shortcuts
Interactive mode supports three input prefixes:
@file: Fuzzy-search for a file and add its contents to the model’s context.!cmd: Run a terminal command and send its output into the conversation.!!cmd: Run a command locally without adding its output to the context, so unnecessary content never enters the conversation.
During a task, keyboard shortcuts let you adjust what happens next:
Enter(steering): Type a message while the agent is working on a long task. It is inserted after the current assistant turn ends to steer the work that follows.Alt+Enter(queued follow-up): Queue a task to run in order after all current work finishes. If you pressEscapeto interrupt, queued messages return to the editor instead of being lost.Ctrl+OandCtrl+T: Expand or collapse tool output and the model’s thinking at any time.
From the command line, pi -c (--continue) quickly resumes the previous conversation.
Managing Session Tree Branches
Unlike the linear conversations in traditional tools, a Pi session is a tree stored as JSONL, saved in ~/.pi/agent/sessions/. Each node has an ID and a parent pointer:
(Msg A) ---> (Msg B) ---> (Msg C) [Main Branch]
\
+-------> (Msg D) [Experimental Branch]
The /tree command lets you navigate different branches within one session file. Select an earlier user message, edit it, and submit it to create another conversation branch; select an assistant response to continue from that node. When leaving a branch, you can generate a summary to carry into the path ahead; the original record stays in the file.
Three branching commands serve different purposes:
| Command | Result | When to use it |
|---|---|---|
/tree | Switch paths within the same session | Different approaches to the same problem are worth comparing together |
/fork | Create a new session from an earlier user message | Another approach has become a separate task |
/clone | Copy the active branch into a new session | Keep the current context and continue working in a separate session |
For example, when investigating API latency, first ask Pi to analyze database queries. If that turns up too little to go on, use /tree to return to the initial question and investigate external HTTP calls instead. The model receives the current branch’s history. Other branches contribute context only when you choose to bring in a summary, keeping the details of the two diagnostic paths separate.
IMPORTANT
Conversation branches do not restore files: The session tree manages messages and tool records. Changes that earlier tools made to the working directory remain in place. To compare two implementations, use Git branches, worktrees, or commits to manage file state.
Putting the Commands Together in Daily Work
Start pi in a project, use @ to bring in relevant files, and describe the task. When you want to inspect test results yourself, run the command with !! to keep the full output from consuming context. Use /tree to try another approach, then continue editing and verifying once you decide which path to keep.
After working for a while, use /compact to trim the history while retaining API design decisions and unresolved diagnostic leads. Compaction adds a summary and keeps recent messages; the original session record remains. Before finishing, name the session with /name and check token usage and cost with /session. The next day, pi -c resumes the most recent session in the current directory; use pi -r to open the selector for other records.
NOTE
Further reading: Context Engineering: Why Larger Windows Haven’t Made Agents More Reliable
When you need to hand off a record, /export can write it out as HTML or JSONL, while /share uploads the record and creates a viewing link. These records may contain tool arguments, command output, and file contents. Check for credentials or internal data before sharing.
The Extension Ecosystem and Tool Controls
Pi offers several levels of customization. Developers can choose the simplest mechanism that meets their needs:
| Need | Recommended mechanism | Details |
|---|---|---|
| Project instructions stored in a directory | AGENTS.md | Native support; no additional trust setting required |
| Reusable prompt shortcuts | Prompt template | Stored in ~/.pi/agent/prompts/ or the project’s .pi/prompts/; automatically exposed as slash commands |
| Task instructions and supporting documents | Skill | Stored in ~/.pi/agent/skills/ or the project’s .pi/skills/; descriptions stay available to the model, while full instructions load on demand |
| Additional tools and event listeners | Extension | TypeScript modules loaded directly, with no build step |
NOTE
Further reading: pstack Explained: A Cursor Engineer’s Agent Skill Pack
For advanced use, Pi also supports custom terminal UI components, custom model providers, and Pi packages that can be distributed across projects.
Installing and Managing Extensions with Packages
A Pi package can distribute extensions, skills, prompts, and themes together. It is an ordinary npm package or directory that uses conventional directory names or declares resource locations in the pi field of package.json.
The following commands use illustrative package names from the official documentation. Replace them with the source you want to install:
# Pin an npm version or a Git tag
pi install npm:@example/[email protected]
pi install git:github.com/example/pi-tools@v1
# Load a local directory when developing your own extensions
pi install ./local-package
# Try it for this launch only, without saving it to configuration
pi -e npm:@example/pi-tools
By default, installation declarations are saved to the user-level settings.json. Add --local to save them to the project’s .pi/settings.json, where project trust settings apply. npm packages with a specified version and Git sources with a specified tag or commit stay pinned to that version; updating packages does not automatically switch them to another version.
For routine management, use pi list to view resources, pi config to enable or disable them, pi remove <source> to remove a declaration, or pi update --extensions to synchronize package installation state. After manually changing settings or resources, run /reload in interactive mode. Extension code still executes even when you only try it with -e, so review the source first.
You can also load just part of a package. For example, to load only its extensions, use an object in the existing packages list:
{
"source": "npm:@example/[email protected]",
"skills": [],
"prompts": [],
"themes": []
}
Omitting extensions loads all extensions allowed by the package; an empty array disables that resource category. This lets you decide separately which package to install and which capabilities to enable.
TypeScript Extensions with No Build Step and Five Tool Exposure Levels
Pi extensions use jiti to load code at runtime, letting developers write TypeScript without running a build step first. A basic extension looks like this:
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
export default function (pi: ExtensionAPI) {
pi.registerCommand("hello", {
description: "Show a greeting notification",
handler: async (name, ctx) => {
ctx.ui.notify(`Hello, ${name || "world"}!`, "info");
},
});
}
When registering a tool, an extension can set exposure to one of five levels. This determines how the tool is offered to the model or scripts and controls how much context its definition uses:
direct: Always declared directly to the model.model-only: Visible to the model but hidden from the sandbox environment (Codemode scripts).codemode: Available only to Codemode scripts; its definition is not listed in the model prompt.deferred: Loaded on demand; its definition enters the context only when Tool Search finds it.hidden: Available only to internal code or extension workflows.
How Codemode, Tool Search, and MCP Work Together
Pi previously argued that it did not need MCP. In “You Said No MCP!”, the team explains the change: tools need searchable descriptions and structured results so programs can combine them effectively. The core also needs to know whether to expose tools directly to the model, load them on demand, or make them available only in Codemode. The tool descriptions and metadata available through third-party MCP plugins were insufficient to fully support these arrangements.
Consider a task such as “summarize the PRs merged in the past week” to understand how the three components divide the work. This is an illustrative use case; actual tool names and parameters depend on the connected MCP server:
- Find tools: The model uses
tool_searchto find query tools that have not been declared directly. Codemode scripts can also usesearchTools()anddescribeTool()to retrieve tool descriptions and parameter definitions. - Orchestrate calls: Fetch the PR list first, then fetch the details of individual PRs in parallel when the queries are independent. Calls with dependencies still run in sequence.
- Process results: JavaScript removes unnecessary fields and summarizes authors and types of changes, returning only a summary to the model for writing the weekly report.
MCP provides the external tool interface, Tool Search finds the capabilities needed, and Codemode handles call order and result processing. This gives the five exposure levels a practical role: large numbers of rarely used tools can load on demand, and tools that scripts use to process data don’t each need a place on the model’s tool list.
According to the Codemode documentation, scripts run in a QuickJS sandbox without Node APIs, direct file access, or networking. External operations must go through tools. The sandbox constrains the script itself; the permissions of the tools it calls still depend on their execution environment. A file written through bash is not automatically rolled back if the script fails.
If you are not yet using MCP, enable batch orchestration in settings.json:
{
"defaultTools": ["+codemode"]
}
Configure MCP connections with pi mcp add and check them with pi mcp list. In interactive mode, /mcp shows connections, login options, and tool exposure settings. After changing server configuration outside the session, run /reload to load it again. MCP tools are exposed through Codemode by default. If you use only the four built-in basic tools, you can enable Codemode yourself as needed.
NOTE
Further reading: How Bear CLI and MCP Reshape Apple-Native Note Automation
What 1.0 Means: A Mature Core and an Experimental Framework
Capabilities Included in the Stable Release
The 0.99.0 release notes already list built-in Codemode, Tool Search, MCP, and Virtual models. Version 1.0 continues in this direction, makes the TUI fullscreen by default, and improves the stability of existing features. When reading the announcement, distinguish capabilities included in the stable release from capabilities first added on release day.
For example, the official measurement in the 1.0.0 release notes reduced the prompt for one GPT-5.6 request from about 5,300 tokens to 3,300, using the default tools plus Codemode. The roughly 40% reduction came from slimmer tool descriptions and loading documentation on demand. It does not mean the total cost of every task falls by 40%.
Another capability to watch is Virtual models. Once a user selects a virtual model, an extension chooses the actual model and thinking level for each request based on the task, cost, or conversation state.
The official release demonstration uses Claude for planning and GPT for implementation, with the Jev classifier deciding when to switch. /session shows each model’s cost separately. This is a routing mechanism you can design yourself; installing Pi does not automatically give you this division of work.
NOTE
Further reading: The AI That Never Speaks: TypeSafe Jev and System One Models Explained
The team’s promise for 1.0 is software that individuals and businesses can rely on, refined through user feedback and improvements. However, this review of the announcement and the v1.0.0 README found no explicit API deprecation timeline or compatibility policy. Teams writing extensions should still pin versions, read release notes, and verify upgrades. The version number alone cannot replace that work.
Pi Durable Addresses a Different Kind of Workload
Pi Durable is a framework released the same day. Agents that receive messages from multiple people through different interfaces, run for extended periods, or resume tasks after an unexpected process termination need a design beyond a single-user terminal workflow.
Durable treats model calls and tool executions as tasks, checkpointing progress step by step. After a process restarts, it resumes from the saved progress.
Its built-in storage backends are memory, SQLite, and JSONL. The latter two do not depend on Node APIs and can run in Bun or a Cloudflare Durable Object through adapters. The tool execution environment can also be separated from the harness that coordinates the agent, allowing conversation management and execution to run on different machines.
WARNING
Durable 1.0.0 is still an experimental package: Its README explicitly says APIs may change between versions without notice. If you only use the terminal coding agent, upgrading Pi does not require adopting Durable. Evaluate the framework and its migration costs when building long-running applications.
Fitting Pi into an Existing Workflow: Claude Code, Upgrades, and Choosing a Tool
Native AGENTS.md Support
Pi natively uses AGENTS.md as its primary instruction file and also reads CLAUDE.md. Loading AGENTS.md as read-only input does not require project trust. Rules in the working directory and its parent directories are inherited automatically, level by level. Pi also supports its own SYSTEM.md (replaces the entire system prompt) and APPEND_SYSTEM.md (appends instructions) for further prompt customization.
Pi and Claude Code: Core Features Compared
| Aspect | Pi (@earendil-works) | Claude Code |
|---|---|---|
| Permission model | No sandbox by default; runs directly with local OS permissions; isolation relies on container-based solutions | Built-in permission modes and interactive review |
| Model support | Any provider (API keys, local GGUF, custom endpoints) | Primarily the Anthropic Claude family |
| Extension system | TypeScript extensions with no build step and npm/git packages | Plugins, Marketplace, and Skills |
| Automation interfaces | Print, JSON, RPC, TypeScript SDK | Headless mode and SDK |
| Session model | Tree-structured JSONL branches with /tree and /fork | Linear resume; /rewind can roll back conversations and file changes |
| Preferred instruction files | Native AGENTS.md first, with CLAUDE.md also read | CLAUDE.md first, with AGENTS.md as a fallback |
| MCP and orchestration | Built-in MCP, five exposure levels, and QuickJS Codemode | Support for connecting MCP servers |
What Existing Users Should Check When Upgrading to 1.0
When upgrading to 1.0.0, developers should review three areas:
- Fullscreen interaction by default: The TUI now defaults to fullscreen mode. To retain the terminal’s native scrollback, add
tuiMode: "regular"to your settings. - Strict CLI argument validation:
--providerwithout--modelis no longer silently ignored; Pi reports an error and exits. Check custom scripts and CI configuration accordingly. - Syntax and API migrations:
- In Codemode scripts, replace
typeof tools.namewith"name" in toolswhen checking whether a tool exists. - MCP OAuth credentials are now stored separately by server name and URL.
- The Extension API has removed
shouldStopAfterTurn; usefinishTurnreturning{ action: "end" }instead.
- In Codemode scripts, replace
Five Steps to Get Started and Decide Whether Pi Fits
- Start with the basics on day one: Run
/loginto sign in to your usual provider. Learn@for file references,!for commands,pi -cto resume the previous conversation, andEscapeto interrupt. Complete one familiar development task first. - Learn the session tree: Use
/treeto branch on the same refactoring problem, then try and compare different solutions. - Configure extensions and Codemode as needed: Start with
pi listto inspect existing resources. Enable"+codemode"insettings.jsonwhen you need to orchestrate tool calls in batches. - Set up isolation: When handling untrusted or external repositories, follow the official security guidance to restrict accessible files, credentials, and networks. Run the whole Pi process in a container or VM if needed.
-nacan reject project resource loading, but it does not restrict tools’ OS permissions and cannot replace isolation. - Choose a tool or use both: Consider Pi if you need non-Anthropic models, want to compare debugging paths through session trees, or are building an automated toolchain with RPC/SDK interfaces. Allow time to assemble and maintain model, extension, and isolation settings yourself. Consider Claude Code if you need sandbox protection by default and permission review out of the box. Both can also work together in a repository with well-defined
AGENTS.mdinstructions.