{
  "$type": "site.standard.document",
  "description": "feat: configure pi with a Catppuccin/opencode theme, custom extensions, prompts, and a safety guard",
  "path": "/posts/customizing-pi-dev/",
  "publishedAt": "2026-04-30T00:00:00.000Z",
  "site": "https://read.ryancowl.es",
  "tags": [
    "DevEx"
  ],
  "textContent": "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.\n\nPi 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.\n\nI'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.\n\ntl;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 .\n\nThe screenshot above shows the parts of my config I actually care about: the custom prompt editor, safety guard, code block styling, and footer.\n\n  \n\nWhere the config lives\n\nPi reads global config from . Mine is organized like this:\n\nA 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.\n\nThat 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.\n\n  \n\nsettings.json\n\nMy global settings are intentionally boring:\n\nA few of those choices matter day to day:\n* keeps the transcript readable. I want the model to think hard, but I do not need every reasoning block taking up screen space.\nmakes  usable for navigation. When I am jumping around a session, I want my prompts and the assistant responses, not every tool result.\ngives the prompt editor a little breathing room.\nskips the splash and changelog noise. I just want to land in the editor.\n\nI 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.\n\n  \n\nThe theme: Catppuccin Mocha x opencode\n\nThe most visible part of the setup is the theme: .\n\nThe name is literal. The palette is Catppuccin Mocha, but the roles are inspired by opencode.\n\nCatppuccin 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.\n\nopencode 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.\n\nThe theme file itself is just JSON:\n\nThat snippet is shortened, but the pattern is the important part: define a palette in , then assign those colors to Pi's UI roles.\n\n  \n\nThe visual extensions\n\nPi themes cover a lot, but not everything. For the rest, I use small TypeScript extensions in .\n\n| Extension | What it does |\n| --- | --- |\n|  | Replaces the prompt editor with a padded editor and a blue left stripe |\n|  | Gives code blocks a filled background and improves checklist styling |\n|  | Replaces the footer with cwd, model, thinking level, git status, context, and cost |\n|  | Replaces the default spinner with a subtle Catppuccin animation |\n|  | Hides terminal message-boundary markers that I found visually noisy |\n\nThe 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.\n\nThe statusline is the most useful visual change. It gives me the information I normally check while working:\n\nThat 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?\n\n  \n\nThe safety guard\n\nOne extension that helps give me peace of mind is . It intercepts tool calls before Pi runs them.\n\nIt blocks writes or edits to:\nsecret files, except , , and \n, , , , , , , and \n\nIt asks for confirmation before:\nWriting common lockfiles like , , , , and \nRunning bash commands that look risky: , , , , , , or \n\nIt also registers a few commands:\n\nI 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.\n\n  \n\nKeybindings\n\nMy keybindings are small and practical:\n\n 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.\n\nThe function keys are for session movement:\nopens \nopens \nstarts a new session\nopens \n\nThose are the Pi commands I use frequently, so I want them one key away.\n\n  \n\nPrompt templates as slash commands\n\nAny markdown file in  becomes a slash command. Mine are simple workflow prompts:\n\n| Command | Purpose |\n| --- | --- |\n|  | Prepare a clean git commit |\n|  | Explain code, behavior, errors, or decisions |\n|  | Diagnose and fix test, lint, or CI failures |\n|  | Produce a compact checklist-style implementation plan |\n|  | Draft a PR title, body, testing notes, and risk assessment |\n|  | Audit release readiness |\n|  | Review current changes or a target |\n|  | Summarize current branch for handoff |\n|  | Create a targeted verification plan |\n|  | WordPress/PHP-focused review |\n\nThe 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.\n\n  \n\nHow I use it\n\nMost of my Pi usage falls into a few loops:\nExploration. I ask Pi to read a code path and explain how something works.\nPlanning. I use  when a task has more than a couple steps.\nImplementation. I let it make small edits, then I inspect the diff.\nReview. I use  before committing, even when Pi wrote the code.\nHandoff. I use  when I need to pause and come back later.\n\nThe 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.\n\nThat is the balance I am aiming for. Fast enough to be useful, constrained enough that I can relax.\n\n  \n\nThe  workflow\n\nWhen I edit a theme, extension, prompt template, or keybinding, I do not need to restart Pi. I run:\n\nThat 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.\n\nThis makes customization feel low-risk. I can tweak a color, reload, decide I hate it, and tweak it again.\n\n  \n\nClosing thoughts\n\nThe 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 .\n\nThat 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.\n\nIf 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.\n\n  \n\nResources\nPi\nPi on GitHub\nPi documentation\nCatppuccin palette\nopencode\nMy Claude Code statusline post",
  "title": "Customizing Pi, a Terminal Coding Agent Harness"
}