How to Add Custom Themes to the pi‑AI Interface: A Complete Guide
To add custom themes to the pi‑AI interface, create a JSON file in $HOME/.pi/themes/ defining a palette and component-specific overrides, then select it via Ctrl+T or the --theme flag.
The pi‑AI interactive coding agent in the badlogic/pi-mono repository supports user-defined visual themes through JSON configuration files. By placing properly structured theme files in a specific directory, you can override the built-in color schemes and instantly apply your custom branding or preferred color palette.
Where pi‑AI Looks for Custom Themes
The application discovers user themes by calling getCustomThemesDir() defined in [packages/coding-agent/src/config.ts](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/config.ts). By default, this function returns:
$HOME/.pi/themes
Any file ending in .json placed inside this directory is automatically scanned at startup and made available in the theme selector.
Creating a Custom Theme JSON File
To add custom themes to the pi‑AI interface, you must provide a JSON object that follows the schema defined in [packages/coding-agent/src/modes/interactive/theme/theme.ts](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/modes/interactive/theme/theme.ts). The core functions loadThemeJson, loadThemeFromPath, and loadTheme parse this structure at runtime.
The Theme JSON Schema
A valid theme file requires at minimum:
palette: An object mapping symbolic color names (e.g.,background,foreground,accent) to ANSI color codes or 24‑bit hex strings (#rrggbb).- Component overrides (optional): Objects named after UI components (
editor,markdown,selectList, etc.) that reference palette keys to customize specific elements.
Only the keys you provide override the defaults; missing values are inherited from the built‑in dark theme.
Minimal Theme Example
Create a file at $HOME/.pi/themes/my-dark.json:
{
"palette": {
"background": "#1e1e1e",
"foreground": "#d4d4d4",
"accent": "#569cd6",
"error": "#f44747",
"warning": "#ff8800",
"info": "#9cdcfe"
},
"editor": {
"cursorColor": "accent",
"selectionBg": "#264f78",
"lineNumberFg": "#858585"
},
"markdown": {
"heading": "accent",
"codeBlockBorder": "info",
"quote": "warning"
}
}
The filename without the extension becomes the theme name displayed in the UI (my-dark).
Activating and Hot‑Reloading Custom Themes
Once you add custom themes to the pi‑AI interface, you can activate them through two methods:
- Interactive selector: Press
Ctrl+T, navigate to Theme, and select your custom theme from the list. - Command line: Launch pi‑AI with the
--theme=my-darkflag to apply the theme immediately on startup.
Hot-Reload During Development
The theme system watches custom theme files for changes. When you modify the active theme JSON while pi‑AI is running, the watcher triggers setGlobalTheme(loadTheme(name)) (implemented in theme.ts), reloading the file instantly without requiring a restart. This provides immediate visual feedback while you fine-tune color values.
Key Source Files and Implementation Details
Understanding these files helps when you need to debug or extend theme functionality:
| File | Purpose | Link |
|---|---|---|
packages/coding-agent/src/config.ts |
Defines getCustomThemesDir() which resolves the $HOME/.pi/themes path. |
View source |
packages/coding-agent/src/modes/interactive/theme/theme.ts |
Core loader functions (loadThemeJson, loadThemeFromPath, loadTheme) and hot-reload logic via setGlobalTheme(). |
View source |
packages/coding-agent/docs/themes.md |
Human-readable documentation of the full theme JSON schema and palette conventions. | View docs |
packages/tui/test/test-themes.ts |
Reference implementations showing the complete shape of built-in theme objects. | View tests |
Summary
- Location: Place theme JSON files in
$HOME/.pi/themes/(returned bygetCustomThemesDir()inconfig.ts). - Format: Define a
paletteobject with color mappings and optional component overrides following the schema intheme.ts. - Activation: Select via
Ctrl+T→ Theme, or launch with--theme=<filename>. - Development: Edit files while running to trigger hot-reload through
setGlobalTheme(loadTheme(name)).
Frequently Asked Questions
Where does pi‑AI store custom themes on disk?
By default, pi‑AI looks for custom themes in $HOME/.pi/themes. This path is determined by the getCustomThemesDir() function located in packages/coding-agent/src/config.ts. You can create this directory manually if it does not exist.
What is the minimum required structure for a theme JSON file?
At minimum, a theme file must contain a palette object mapping symbolic names like background, foreground, and accent to color values (hex codes or ANSI values). All other properties are optional; missing component-specific keys inherit from the built-in dark theme. The full schema is defined in packages/coding-agent/src/modes/interactive/theme/theme.ts.
Do I need to restart pi‑AI after editing a custom theme?
No. The theme system watches custom files for changes and automatically reloads the active theme by calling setGlobalTheme(loadTheme(name)) as implemented in theme.ts. This hot-reload functionality provides immediate visual feedback while you adjust colors.
Can I distribute themes via the command line?
Yes. You can activate any custom theme at startup by passing the --theme=<name> flag, where <name> matches the JSON filename without the extension. This is useful for scripting or sharing consistent environments across different machines.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →