## **Pi Coding Agent: A Minimalist Approach to AI-Assisted Development**
In the rapidly evolving landscape of AI-powered coding assistants, developers are often faced with a trade-off: feature-rich tools that automate complex workflows, or minimalist frameworks that prioritize transparency and control. **Pi** firmly chooses the latter, positioning itself as an “AI coding assistant with read, bash, edit, write tools” — and little else. This article explores what happens when you strip away the noise, examining Pi’s design philosophy, hands-on performance, and real-world utility through a custom extension.
—
## **Introduction**
Most coding agents compete on *capacity* — how much they can do without user intervention. Tools like Claude Code manage sub-agents and plan modes; Cursor wraps an entire IDE around the model. **Pi does the opposite**. Its documentation explicitly lists what it *won’t* support: no MCP, no sub-agents, no plan mode, no permission popups, no built-in to-do lists, and no background bash execution.
This deliberate minimalism forms the basis of our investigation. We installed Pi in a live environment, verified its version against its own changelog, and even built a working TypeScript extension to test its extensibility.
**Prerequisites:**
– Node.js 22 or newer
– An API key for at least one provider (Anthropic, OpenAI, Google, etc.)
—
## **What Pi Actually Is, and Who’s Behind It**
Pi was created by **Mario Zechner**, known for his work on **libGDX**, who published a candid essay explaining why he built this tool. His critique centers on opaque system prompts, hidden behavior changes, and limited visibility into how models are being guided.
The project gained rapid traction:
– Endorsed by **Armin Ronacher** (creator of Flask and Jinja2)
– Acquired by **Earendil Inc.**, who launched **Lefos**, a companion cloud platform
– Published under **RFC 0015**, an open-core governance model
– Over **70,000 GitHub stars** as of this writing
After installing Pi fresh, we confirmed the version:
“`bash
pi –version
# → 0.80.3
“`
—
## **The Four Tools — And What’s Deliberately Missing**
Pi’s core toolset is intentionally narrow:
| Tool | Purpose |
|——–|———|
| `read` | Read files |
| `write` | Write files |
| `edit` | Edit files |
| `bash` | Execute shell commands |
Everything else is treated as something you add yourself. Pi’s documentation clearly states what it *doesn’t* include:
– No built-in MCP support
– No sub-agents or plan mode
– No permission popups
– No background bash execution
– No to-do tracking
**Why?**
Pi’s designers believe frontier models already understand agentic behavior through reinforcement learning. A smaller system prompt leaves more context budget for actual work. The trade-off? You’re responsible for building the features you need.
—
## **Hands-On: Installing and Running a Real Session**
### **Installation**
Install via npm:
“`bash
npm install -g –ignore-scripts @earendil-works/pi-coding-agent
“`
### **Authentication**
Set your API key:
“`bash
export ANTHROPIC_API_KEY=sk-ant-your-key-here
“`
### **Launching a Session**
“`bash
cd your-project-directory
pi
“`
This drops you into an interactive terminal where you can:
– Switch models mid-session with `/model sonnet` or `/model gpt-5`
– Cycle through favorites with **Ctrl+P**
– Browse conversation history using `/tree` to branch discussions
—
## **Building a Real Extension: Permission Gate + Custom Tool**
Pi’s lack of built-in safety mechanisms becomes an opportunity when you extend it. Below is a real-world extension that adds:
1. A **permission gate** for risky bash commands
2. A **custom tool** to count words in text
### **Extension Code**
“`ts
// permission-gate.ts
import type { ExtensionAPI } from “@earendil-works/pi-coding-agent”;
import { Type } from “typebox”;
export default function (pi: ExtensionAPI) {
// Block risky bash commands
pi.on(“tool_call”, async (event, ctx) => {
if (event.toolName === “bash” && typeof event.input.command === “string”) {
const risky = /brms+-rfb|bsudob|bgits+pushs+–forceb/;
if (risky.test(event.input.command)) {
const ok = await ctx.ui.confirm(
“Risky command”,
`Allow: ${event.input.command}`
);
if (!ok) {
return { block: true, reason: “Blocked by permission gate extension” };
}
}
}
});
// Register custom word-count tool
pi.registerTool({
name: “count_words”,
label: “Count Words”,
description: “Counts words in a block of text.”,
promptSnippet: “Count words in a string”,
parameters: Type.Object({
text: Type.String({ description: “Text to count words in” }),
}),
async execute(toolCallId, params) {
const count = params.text.trim().split(/s+/).filter(Boolean).length;
return {
content: [{ type: “text”, text: `${count} words` }],
details: { count },
};
},
});
pi.registerCommand(“gate-status”, {
description: “Show that the permission gate extension is active”,
handler: async (_args, ctx) => {
ctx.ui.notify(“Permission gate extension is active.”, “info”);
},
});
}
“`
### **Loading the Extension**
“`bash
pi -e ./permission-gate.ts –list-models anthropic
“`
During an interactive session, asking the model to run:
“`bash
rm -rf ./tmp
“`
Triggers a confirmation prompt — exactly as intended.
—
## **Where the Minimalism Actually Helps**
Rather than being a limitation, Pi’s small footprint delivers concrete advantages:
1. **Session Trees**
Use `/tree` to branch conversations without losing context — ideal for exploring multiple solutions.
2. **Multi-Provider Flexibility**
Seamlessly switch between Anthropic, OpenAI, Google, Ollama, and more — all in the same session.
3. **Token Efficiency**
With a sub-1,000-token system prompt (vs. 7,000–10,000 in competing tools), more context is available for your actual work.
—
## **Where It Costs You**
Minimalism isn’t free. Consider:
– **No built-in safety nets**: Permission gates and custom tools must be built yourself.
– **Limited out-of-the-box value**: Teams expecting “set-and-forget” automation may struggle.
– **Thinner documentation and community support**: Compared to established tools, edge-case solutions require deeper investigation.
– **Ownership uncertainty**: While the core remains MIT-licensed, future features may live behind Earendil’s Fair Source layers.
A reviewer noted that Pi isn’t suitable for unattended overnight runs — precisely because safety defaults must be added manually.
—
## **The Verdict**
**Pi is ideal if you:**
– Prefer control over convenience
– Work primarily in a terminal
– Want to switch models freely
– Are comfortable building (or commissioning) extensions
**Pi is not ideal if you:**
– Want an overnight-automation solution
– Prefer fully opinionated toolchains
– Need comprehensive built-in safety features
—
## **Conclusion**
Pi’s most radical idea isn’t a new model or clever UI — it’s treating *omission* as a feature. By refusing to build beyond a minimal core, the project hands control directly to the developer.
In this article, we installed Pi, ran a live session, and created a working extension in under thirty lines of TypeScript. The experience confirms that “you *can* build what’s missing” isn’t a slogan — it’s a working promise.
Ultimately, Pi succeeds not by doing more, but by enabling you to decide *exactly* what should be done. For teams that value transparency, control, and flexibility, that’s not just a feature. It’s a fundamentally different way to work with AI.
—
## **FAQ**
### **What is the `pi` tool?**
Pi is a minimalist AI coding assistant that exposes only four core tools: `read`, `write`, `edit`, and `bash`. It avoids built-in features like sub-agents, plan mode, or permission dialogs, allowing users to customize behavior through extensions.
### **How do I install Pi?**
Use the following command:
“`bash
npm install -g –ignore-scripts @earendil-works/pi-coding-agent
“`
macOS/Linux users can also use the standalone installer:
“`bash
curl -fsSL https://raw.githubusercontent.com/earendil-works/pi/main/install.sh | sh
“`
### **Do I need an API key?**
Yes, to run real coding sessions you’ll need an API key from a supported provider (e.g., Anthropic, OpenAI). You can set it via environment variable:
“`bash
export ANTHROPIC_API_KEY=sk-ant-your-key-here
“`
### **Can I switch between AI models?**
Yes. Inside a session, use:
“`bash
/model sonnet
/model gpt-5
/model ollama/llama3
“`
to switch between providers.
### **What is an `AGENTS.md` file?**
Pi automatically loads two optional context files:
– A global `AGENTS.md` (for all projects)
– A local `AGENTS.md` (project-specific)
These files let you store reusable instructions, dependencies, and guidelines for your AI assistant.
### **How do I build extensions for Pi?**
Pi provides a TypeScript extension API that lets you:
– Listen to tool calls (`pi.on(“tool_call”, …)`)
– Register new tools (`pi.registerTool(…)`)
– Add custom commands (`pi.registerCommand(…)`)
Extensions are loaded with the `-e` flag:
“`bash
pi -e ./my-extension.ts
“`
### **What does the permission gate extension do?**
It intercepts `bash` commands that look destructive (e.g., `rm -rf`, `sudo`, `git push –force`) and asks you to confirm before execution. If denied, the command is blocked with a clear reason.
—



