GuidesHosting choices

Pi extensions: where they live and what they can reach

What a Pi coding agent extension is, where Pi loads extensions from, installing packages with pi install, and the keys and files an extension can reach.

October 20, 2026The Everpod team
The short answer

A Pi extension is a TypeScript module that Pi loads into its own process to add tools the model can call, / commands, shortcuts, event hooks, model providers, MCP servers or screen elements. Pi finds your own in ~/.pi/agent/extensions/ and a project’s in .pi/extensions/, and installs shared ones as packages with pi install npm:<package>, which puts them in ~/.pi/agent/npm/node_modules/. An extension runs with your account’s full permissions and can read the model keys Pi holds; Pi doesn’t sandbox extensions, its maintainers said in June 2026 that they don’t scan the packages its gallery lists, and as of version 1.3.0 installing a package also runs that package’s npm install scripts. Read a package’s source before you install it, and run Pi inside a container or virtual machine if you want a real boundary.

Extensions beside Pi’s other add-ons

Pi has four kinds of add-on, and only one of them runs code:

KindWhat it isRuns code
Extension
A TypeScript or JavaScript module loaded into PiYes, inside Pi
Skill
Instructions and files in the open Agent Skills format, loaded when a task calls for themOnly what the model then chooses to run
Prompt template
A Markdown file that becomes a / commandNo
Theme
Colours for the terminal interface and HTML exportsNo

A package is the way any of these is shared: Pi’s packages page says packages “install and distribute extensions, skills, prompt templates, and themes as one unit,” and a package is an ordinary npm package or folder. Pi’s extensions page draws the line between the first two: use an extension “when a workflow needs tools, commands, event handlers, model providers, session state, or terminal UI rather than instructions alone.”

What an extension can add

An extension exports one function that receives Pi’s extension API and registers what it adds. Pi loads it with jiti, so there is no build step. Among what it can register:

Pi also ships four extensions of its own, loaded by default: builtin:mcp, builtin:llama.cpp, builtin:codemode and builtin:tool-search. MCP support has been one since version 0.99 (September 29, 2026), and an installed extension that registers /mcp, such as pi-mcp-adapter, replaces it.

Where extensions live

PlaceLoaded
~/.pi/agent/extensions/
Always, for every project
.pi/extensions/ in a project
Only after you trust that project
Paths listed under extensions in settings.json
With the settings file they are in
pi -e ./my-extension.ts
For that one run

In those folders Pi loads a .ts or .js file directly, a subfolder with an index.ts or index.js, or a subfolder whose package.json has a pi field, and goes no deeper than one level. An extension you drop in by hand brings no dependencies with it: Pi’s docs say to put them in a package.json beside it and run npm install there. /reload picks up changes without restarting. PI_CODING_AGENT_DIR moves ~/.pi/agent elsewhere.

When two extensions add the same tool, the first in Pi’s order keeps it: a project’s before yours, yours before a package’s. Pi reports the clash as Failed to load extension "…": Tool "web_search" conflicts with …, though both stay loaded; only the first one’s tool is used. Two web-search packages installed side by side is the common way to meet it.

Installing a package

pi install npm:@example/pi-tools          # from npm
pi install npm:@example/pi-tools@1.0.0    # pinned to a version
pi install git:github.com/example/pi-tools # from git (https:// and ssh:// work too)
pi install ./my-package                   # a folder on disk, used where it is
pi install -l npm:@example/pi-tools       # for this project only
pi -e npm:@example/pi-tools               # one run, not added to settings

pi list                    # what is installed, and where
pi update --extensions     # update installed packages (pi update alone updates Pi)
pi remove npm:@example/pi-tools

There is no confirmation step: pi install installs and prints Installed <source>. Where the package lands:

The record of what you installed is the packages list in ~/.pi/agent/settings.json. A version you name is pinned, and so are git tags and commits; an unpinned npm package moves with pi update --extensions. pi config turns individual resources from a package, or Pi’s built-in extensions, on and off.

The gallery at pi.dev/packages lists every npm package carrying the pi-package keyword: 5,437 of them on October 20, 2026, extensions, skills, prompt templates and themes together. Its download counts are npm’s. A package is listed by carrying the keyword; each entry has a link to report a malicious one, and one of Pi’s maintainers wrote in June 2026: “We don’t scan extensions proactively today.”

What an extension can reach

Everything you can. Pi’s own warning: an extension “runs inside the Pi process with the same operating-system permissions. It can inspect prompts, tool calls, files, credentials, and session history, so load extensions only from sources you trust.” In particular:

This is by design, not an oversight. Pi’s security policy says “the Pi coding agent intentionally does not have a sandbox” and lists “Behavior of pi extensions or skills installed by the user” and “Risks from installing untrusted extensions, skills, packages, or tools” as outside what it treats as a vulnerability.

Project trust is the one check. Pi asks before loading a folder’s .pi/settings.json, .pi/extensions, skills, prompts and the rest, which since version 0.79.0 (June 2026) stops a cloned repository from running its own extensions the moment you open it; before that, it did (CVE-2026-54325). Pi’s page is plain about the limit: “Project trust does not limit what tool calls can access or affect.” And AGENTS.md and CLAUDE.md load whether or not you trust the folder.

Extensions on a server, with nobody watching

Extensions load in every mode: the interactive terminal, RPC, JSON and print (pi -p). Their interface does not. In print and JSON modes there is nobody to ask, so a confirmation dialog answers no: an extension that asks before running rm -rf blocks it instead, which is the safe way round but means an unattended run stops short wherever a gate would have asked.

For a real boundary, Pi’s containerization page is clear about where it sits: when the whole Pi process runs in an isolated environment, “its extensions run there too.” Two catches from the same page: mounting ~/.pi/agent into the container “exposes your Pi credentials, settings, extensions, and sessions,” and isolating only the built-in tools, as the Gondolin example does, leaves other extensions’ tools on the host. On a server, running Pi as a user account of its own is a simpler boundary of the same kind: its extensions reach that account’s files and keys, and not yours.

Before you install someone else’s

What the Pi coding agent is covers installing Pi and choosing where to run it, and Pi against OpenCode how its no-prompts design compares.

Run the Pi coding agent on an always-on developer pod.

A developer pod is a permanent cloud computer (VPS), set up and secured for you, with your pick of Claude Code, Codex, OpenCode, Pi, Hermes and OpenClaw installed. Run more agents at once than your laptop can hold, and keep them working when it’s closed. From $24 a month, built in about ten minutes.