Customizing Pi, a Terminal Coding Agent Harness
After putting together a custom statusline for Claude Code, I started looking for a terminal coding agent that treated customization as a first-class feature instead of a settings shim. That's how I landed on Pi, a minimal terminal coding harness from Mario Zechner.
Pi is open source, model-agnostic, and unusually hackable. Themes are JSON. Extensions are TypeScript. Prompt templates are markdown. Keybindings are a small JSON file. The whole setup lives in a folder I can read and back up.
I've been using it as my daily driver for a few weeks now, and my config has turned into a small, opinionated environment that looks and behaves the way I want.
tl;dr: Pi reads my global config from . I run a Catppuccin Mocha theme with role assignments borrowed from opencode, a custom editor stripe, a custom footer, slash commands for common workflows, and a safety guard that blocks writes to files or asks before risky commands like .
The screenshot above shows the parts of my config I actually care about: the custom prompt editor, safety guard, code block styling, and footer.
Where the config lives
Pi reads global config from . Mine is organized like this:
A project can also have a local directory. Project config overrides the global config, which is useful for experiments. I keep a sandbox project around for trying new extensions before promoting them into the global folder.
That is the part I appreciate most. This setup is not trapped in a settings UI. If I want to understand why something looks or behaves a certain way, I open the file.
settings.json
My global settings are intentionally boring:
A few of those choices matter day to day:
- keeps the transcript readable. I want the model to think hard, but I do not need every reasoning block taking up screen space. makes usable for navigation. When I am jumping around a session, I want my prompts and the assistant responses, not every tool result. gives the prompt editor a little breathing room. skips the splash and changelog noise. I just want to land in the editor.
I also keep a local LM Studio provider in for experiments. I do not use it as the default, but it is nice to have a zero-cost local model one away.
The theme: Catppuccin Mocha x opencode
The most visible part of the setup is the theme: .
The name is literal. The palette is Catppuccin Mocha, but the roles are inspired by opencode.
Catppuccin Mocha for the palette. The theme file defines the usual Mocha colors: , , , , , , , , plus the / / background stack and the / / ramp. I added for headings and for assistant text that needed a little more contrast.
opencode for the role assignments. Blue is the primary accent. Peach handles headings and bash mode. Mauve is saved for extension and system labels. Tool boxes sit on their own panel background. Errors get a darker wine-tinted panel instead of an aggressive red border.
The theme file itself is just JSON:
That snippet is shortened, but the pattern is the important part: define a palette in , then assign those colors to Pi's UI roles.
The visual extensions
Pi themes cover a lot, but not everything. For the rest, I use small TypeScript extensions in .
| Extension | What it does |
|---|---|
| Replaces the prompt editor with a padded editor and a blue left stripe | |
| Gives code blocks a filled background and improves checklist styling | |
| Replaces the footer with cwd, model, thinking level, git status, context, and cost | |
| Replaces the default spinner with a subtle Catppuccin animation | |
| Hides terminal message-boundary markers that I found visually noisy |
The editor extension is the one that makes Pi feel like mine. Instead of a generic prompt box, I get a slightly padded input area with a blue accent stripe on the left. It is a small thing, but it gives the prompt a stable visual anchor.
The statusline is the most useful visual change. It gives me the information I normally check while working:
That line answers most of my ambient questions without opening another panel: where am I, what model is active, is the repo dirty, how much context is left, and roughly what has this session cost?
The safety guard
One extension that helps give me peace of mind is . It intercepts tool calls before Pi runs them.
It blocks writes or edits to: secret files, except , , and , , , , , , , and
It asks for confirmation before: Writing common lockfiles like , , , , and Running bash commands that look risky: , , , , , , or
It also registers a few commands:
I have not had an agent do anything catastrophic, but I have had models confidently try to rewrite files. I would rather make that impossible by default.
Keybindings
My keybindings are small and practical:
is the important one. Some terminals swallow , and I refuse to live without a way to add a newline to a prompt without sending it.
The function keys are for session movement: opens opens starts a new session opens
Those are the Pi commands I use frequently, so I want them one key away.
Prompt templates as slash commands
Any markdown file in becomes a slash command. Mine are simple workflow prompts:
| Command | Purpose |
|---|---|
| Prepare a clean git commit | |
| Explain code, behavior, errors, or decisions | |
| Diagnose and fix test, lint, or CI failures | |
| Produce a compact checklist-style implementation plan | |
| Draft a PR title, body, testing notes, and risk assessment | |
| Audit release readiness | |
| Review current changes or a target | |
| Summarize current branch for handoff | |
| Create a targeted verification plan | |
| WordPress/PHP-focused review |
The benefit is not that these prompts are magical. It is that they are consistent. Every PR summary has the same shape. Every review asks for the same classes of problems. Every plan comes back as a short checklist instead of a wall of text.
How I use it
Most of my Pi usage falls into a few loops: Exploration. I ask Pi to read a code path and explain how something works. Planning. I use when a task has more than a couple steps. Implementation. I let it make small edits, then I inspect the diff. Review. I use before committing, even when Pi wrote the code. Handoff. I use when I need to pause and come back later.
The config is tuned for those loops. The footer keeps context visible. The tree view is filtered so I can navigate old decisions. The prompt templates keep routine tasks consistent. The safety guard lets me give the agent tools without fully trusting every proposed write.
That is the balance I am aiming for. Fast enough to be useful, constrained enough that I can relax.
The workflow
When I edit a theme, extension, prompt template, or keybinding, I do not need to restart Pi. I run:
That picks up the changed files in place. The only exception is a deep renderer monkey-patch getting weird after several reloads. When that happens, a full restart fixes it.
This makes customization feel low-risk. I can tweak a color, reload, decide I hate it, and tweak it again.
Closing thoughts
The reason this setup has stuck is that it is legible. Every customization is a file. If I want to know why the editor has a blue stripe, I open . If I want to know why Pi refuses to write to , I open . If I want to change how PR summaries are drafted, I edit .
That kind of legibility is rare in dev tools. Pi gives me enough defaults to get started, but enough surface area to make the tool match how I actually work.
If you want to try Pi, start with the quickstart, use the built-in dark theme for a bit, then add one customization at a time. My recommendation: start with a safety guard before you start making it pretty.
Resources Pi Pi on GitHub Pi documentation Catppuccin palette opencode My Claude Code statusline post
Discussion in the ATmosphere