← Guides

Guide

Pi Coding Agent 1.0 — MCP, Code Mode and Hosted Setup

Pi is an open-source terminal coding agent from Earendil Works, published as @earendil-works/pi-coding-agent and run as pi. It has read, bash, edit and write tools, session management, and an extension system. Pi 1.0, released on 1 October 2026, added native MCP support and Code Mode. This guide covers what Pi is, what 1.0 changed, how to add an MCP server, how to run it in a managed cloud workspace, how to point it at a model, how to drive it non-interactively, and the one thing about its security model you should understand before pointing it at a repository. Updated 14 October 2026, against Pi 1.2.0.

What Is Pi?

Pi is a coding agent you run in a terminal. You give it a task in natural language and it reads files, runs shell commands, and edits code to carry the task out — the same shape as Claude Code, Codex CLI, OpenCode or Aider. It is MIT licensed and developed in the open, and it ships as a single npm package with a pi binary.

Two things distinguish it in practice. First, it is broadly model-agnostic: Pi reads provider API keys straight from the environment and supports a long list of providers rather than being tied to one vendor's models. Second, it is deliberately minimal about permissions — which is a real strength when you run it in the right place, and a real hazard when you do not. Both are covered below.

What Changed in Pi 1.0

Earendil shipped Pi 1.0 on 1 October 2026, and by 12 October the current release was 1.2.0. Three changes matter most if you already use Pi.

  • Native MCP support. For most of Pi's life its website said it did not support the Model Context Protocol. Mario Zechner and Armin Ronacher had argued in public that MCP was bloated, wasted tokens, and lost to plain shell commands and CLIs. Pi now connects to MCP servers out of the box. The pi.dev homepage puts it as “No MCP — Now with MCP+Codemode”. MCP extensions still work too.
  • Code Mode. A codemode tool lets the model write a short JavaScript script that calls Pi's other tools, MCP tools included. The script can run calls in parallel and filter or count their results, and only its final output goes back to the model. The large intermediate data never enters the context window.
  • Deferred tool loading. MCP tools are not all declared to the model up front. By default a server's tools stay out of the tool list. Code Mode scripts find them with searchTools(), and a tool_search tool can load just the matching ones for the model to call directly. This is how Pi adds MCP without adding its usual cost: dozens of tool schemas resent on every turn.

The same day, Earendil also released Pi Durable, a separate and explicitly experimental package for building long-running agents that survive a crash. It is covered in its own section below. It is not a feature of the pi CLI, so you do not need it to use MCP or Code Mode.

Installing or Updating Pi

Pi needs Node.js 22.19 or newer. The official installers are:

curl -fsSL https://pi.dev/install.sh | sh                  # macOS / Linux
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi --version

The old @mariozechner/pi-coding-agent npm name stopped at 0.73.1. If pi --version reports something that old, you installed the stale package, so install the @earendil-works one instead. A script install updates with pi update; an npm install updates through npm.

Adding an MCP Server to Pi

Pi reads user-level MCP servers from ~/.pi/agent/mcp.json and project servers from .pi/mcp.json in the repository. The file uses the same mcpServers shape as other MCP clients, so an entry copied from a server's README usually works as-is. The quickest way to add one is the pi mcp command, which writes the file for you:

pi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /workspace
pi mcp add docs --url https://example.com/mcp      # a remote (streamable HTTP) server
pi mcp list                                        # state, tool count and exposure
pi mcp login <server>                              # OAuth sign-in for a remote server

We ran the filesystem line above in a Coding Harness, and pi mcp list then reported filesystem: connected, 14 tools (codemode, global), and the file it wrote was:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
    }
  }
}

A few details that are easy to miss:

  • Remote servers must speak streamable HTTP. The legacy SSE transport is rejected, though many servers that document an /sse endpoint also serve /mcp.
  • A project's .pi/mcp.json is read only after you grant that project trust. A cloned repository cannot add MCP servers to your session on its own. Keep servers that carry credentials in the user-level file.
  • OAuth servers such as Sentry need no token in the file: pi mcp login signs in through the browser and stores tokens in ~/.pi/agent/mcp-auth.json.
  • Inside a session, /mcp shows every server and lets you reconnect it, sign in, change its exposure, or turn it off. Run /reload after you edit the file outside the session. --no-mcp starts Pi with MCP switched off entirely.

Choosing how MCP tools reach the model

Each server's exposure setting decides how the model sees its tools, and a toolExposure map can override it for individual tools:

  • codemode — the default. The tools are not declared to the model. Code Mode scripts call them, and tool_search can load them when it is active. This is the cheapest option in context terms.
  • deferred — the tools stay hidden until tool_search loads a match, after which the model can call them directly.
  • direct — declared on every request, like a built-in tool. Use it only for the handful of tools you want the model to see at all times.
  • hidden — not exposed at all, except for tools you opt back in with toolExposure.

Using Code Mode

Code Mode switches itself on when a server with codemode exposure connects. To keep it available with no MCP servers configured, add it to the default tools, or enable it for a single run:

// ~/.pi/agent/settings.json  (or .pi/settings.json in a project)
{ "defaultTools": ["+codemode"] }

# one run, from the shell
pi --tools +codemode
pi --tools read,bash,codemode,'mcp__filesystem__*'   # codemode limited to one server

The script runs in a QuickJS sandbox with no Node APIs, file system, network or timers. It reaches the outside world only through Pi's tools and a models object. Its tool calls go through the same pipeline, and the same permission gates, as a normal tool call, and they are real: a script that fails halfway does not undo the calls it already made. Through models, a script can run non-LLM models with the session's credentials, such as classifiers (Jev is the example in Pi's docs) and image models. A typical use is fetching 200 GitHub comments through an MCP server, having a classifier label each one, and handing the model only the summary. To stop Code Mode from switching itself on, set "autoEnableCodemode": false beside mcpServers in mcp.json.

Pi Durable — Crash-Safe Agents (Experimental)

Pi Durable (@earendil-works/pi-durable) is a library, not a CLI feature. It is for developers building their own long-running agent: a Slack bot, a personal assistant, anything that has to keep going for hours or days. Before a model turn or tool call runs, Pi Durable writes the intent to storage. If the process dies, the agent resumes where it stopped instead of waiting for someone to type “continue”. A tool runs again after a crash only if it declares that rerunning is safe, so a call that charges a card or sends a message does not run twice. Tasks can start child tasks, and typed JSON documents hold app state next to the transcript.

npm install @earendil-works/pi-durable @earendil-works/pi-ai @earendil-works/chord

Two cautions. The README opens with “Experimental. The API changes without notice between releases”, so pin the version you build against. And the launch coverage is not always accurate: Earendil's own post puts the source at about 15,000 lines without tests, and names a laptop, a remote VM, Bun, an in-memory sandbox and a Cloudflare Durable Object as places to run it. Read the upstream README rather than a summary of it.

If you want a long-running agent and do not want to build one, that is what Hermes and OpenClaw already are. Both stay online, keep their history, and answer you on Telegram, Discord or WhatsApp. Pi Durable is the kit for building your own.

Running Pi in a Coding Harness

A Coding Harness is a managed cloud dev box with the major terminal coding agents pre-installed. Pi is one of them, so there is nothing to install: you pick Pi when you deploy the workspace, open the browser terminal, and run it.

  1. Open your dashboard and deploy a Coding Harness.
  2. Choose Pi from the coding agent dropdown before you deploy.
  3. Open the workspace terminal and run pi to start an interactive session, or pi "your task here" to give it a task straight away.

Your code lives in /workspace, which persists across a reset of the box. Sign-ins and CLI config live in the home directory, which also persists — so you authenticate once rather than on every rebuild.

Which Pi version your workspace runs

Workspaces created or reset from 14 October 2026 run Pi 1.2.0, so MCP and Code Mode work out of the box. MCP servers you add with pi mcp add are saved to ~/.pi/agent/mcp.json in the persisted home directory. Both the terminal and API-started runs use them, and Code Mode switches on with them. Your existing Pi sessions carry over too: we checked that 1.2.0 continues a conversation that the earlier 0.84.1 started.

A box created before that date keeps Pi 0.84.1, which has no MCP support, until you reset it (see below). If you followed an earlier version of this guide and installed Pi into ~/.local, remove that copy so the terminal stops preferring it over the built-in one:

npm uninstall -g --prefix ~/.local @earendil-works/pi-coding-agent
hash -r && pi --version      # 1.2.0, the built-in copy

Already have a workspace?

Pi is only present in workspaces created from the image that includes it. A box you created earlier runs the image it was built from, so it will not have pi on its path yet. Hit Reset on the workspace to move it to the current image — a reset keeps both your code in /workspace and your CLI logins, and only replaces the box around them. If you trigger a Pi run through the API against a workspace that predates it, the API answers with a harness_unavailable error telling you to reset, rather than failing halfway through the run.

Pointing Pi at a Model

Pi picks a provider from the API keys it can see in the environment, and --model selects a specific model. It accepts a plain pattern, a fully qualified provider/id, and an optional thinking level:

pi --model <provider>/<model-id> "Refactor the auth module"
pi --model sonnet:high "Work out why this test is flaky"
pi --list-models              # see what your keys unlock
pi --provider openrouter      # pin a provider explicitly

The simplest route is an OpenRouter key, which gives one credential covering many models. How you supply it depends on how you are running Pi, and the two paths are deliberately different:

  • In the workspace terminal — sign in with /login, or export the key yourself. A key saved on your account is not pushed into the box automatically: keys are never injected under the names a CLI reads, because an environment key silently overrides a sign-in you did yourself and quietly moves your billing. Pi keeps its own credentials in the persisted home directory, so a one-time sign-in survives a reset.
  • On an API run — save the key under API Keys, then pass "use_saved_key": true on the request. Without that flag the run uses whatever login already lives in the box. It is opt-in per request rather than an account setting, for the reasons in the security section below.

See API keys and bring your own key for how key storage works.

One detail worth knowing: pi --help shows a default provider, but that default only applies when nothing else is available. With a single provider key present, Pi selects that provider on its own — you do not have to pass --provider to make an OpenRouter key work.

Non-Interactive and Scripted Runs

Pi has a normal interactive terminal UI, and three modes for running it without a human present:

  • -p / --print — run the prompt, print the answer, exit.
  • --mode json — emit every event as JSON lines, for programmatic consumption.
  • --mode rpc — RPC mode, for integrating Pi into another process.

Print mode also reads piped stdin and merges it into the prompt, which makes it easy to feed a file or the output of another command into a task:

cat CHANGELOG.md | pi -p "Summarise this for a release note"
pi -p --mode json "List every TODO in src/ with file and line"
pi @src/auth.ts @src/session.ts "Review these two files together"

The @file syntax attaches specific files to the prompt. Sessions can be continued with -c, resumed with -r, or kept out of history entirely with --no-session.

You can also start Pi runs from outside the box entirely. The workspace API accepts a harness of pi, starts the run in the background, and hands back a run id you poll for progress and log output — useful for wiring an agent into CI or a script.

Extensions and Skills

Pi has a package system for extending what it can do. Extensions are TypeScript modules; skills, prompt templates and themes can also be loaded from files or directories.

pi install <source>     # add a package
pi list                 # what is installed
pi update --extensions  # update packages only
pi --skill ./my-skill   # load a skill for one run

Project-local extensions, settings and MCP servers are gated behind a trust decision, which matters for the security model below.

Security: Pi Has No Built-In Sandbox

This is the most important thing to understand about Pi, and its own documentation is direct about it: Pi does not include a built-in sandbox. Its tools read files, write files, and run shell commands with the permissions of the user that started it. Extensions, and any MCP server Pi launches as a local command, run with the same permissions. Pi treats real isolation as the operating system's job rather than something it can meaningfully provide in-process.

Upstream's own recommendation is that untrusted repositories, unmonitored work, and unattended automation should run Pi inside a container or VM with only the files and credentials the task needs. That is exactly what a Coding Harness is: a container per workspace, running as a non-root user, with dropped Linux capabilities, no access to the host Docker socket, resource caps, and its own volumes. Your own machine stays out of reach — your laptop's files, your SSH keys and your browser profile are not in the box and cannot be touched by a run.

Be clear about what that does not cover, because a container is a boundary around your machine, not around your credentials. Anything the workspace itself holds is inside the blast radius: the CLI logins kept in its persisted home directory, any key you export in its terminal, and — on an API run you explicitly fund with a saved key — that key too. The agent runs with approvals bypassed and the box has outbound internet, so a prompt injection carried in repository content could read a credential and send it somewhere. Those credentials work outside the box, which is precisely why this matters.

The practical rules that follow: keep the credentials you put in a workspace scoped to what the work needs, prefer a key you can rotate cheaply over one that unlocks everything, and treat a run over an untrusted repository as something to review rather than trust. For API runs, funding with your saved key is opt-in per request rather than an account-wide setting for this exact reason — you decide, run by run, whether the prompt is trustworthy enough to hold the key.

Project trust is a separate, narrower control: it decides whether Pi loads settings and extensions that a repository ships with, so cloning a repo cannot silently change how your agent behaves. In the non-interactive modes it never stops to ask — by default those project-local resources are simply ignored, and --approve / --no-approve override that for a single run. Note that this guards what Pi loads, not what the model does once it is running; prompt injection from repository content is a real risk for every agent of this kind.

How Pi Compares

Pi occupies a similar space to the other terminal agents, with different emphases:

  • Claude Code and Codex are tied to one vendor's models and have the deepest integration with them. Pi is provider-agnostic by design.
  • OpenCode is the closest comparison — open source and model-agnostic. See OpenClaw vs OpenCode.
  • Aider is the most git-centric of the group, built around commits and diffs. See OpenClaw + Aider.

Because a Coding Harness ships all of them, you do not have to choose in advance — you can run Pi on one task and a different agent on the next, in the same box, against the same code.

A Coding Agent Is Not a Chatbot

Pi is a coding tool: you drive it from a terminal, and it stops when the task stops. If what you want is an assistant that stays online and answers messages on Telegram, Discord, WhatsApp or WeChat, that is a different product shape — see what OpenClaw is. The two pair well: an agent for always-on chat, a workspace for the coding work.

Related Guides

Sources: Pi 1.0 announcement, Pi Durable announcement, and Pi's MCP and Code Mode docs.