9.3 KiB
Themes Reference
This reference describes theme discovery, selection, schema, color values, and TUI color tokens. For the setup workflow, see Configuration.
Table of Contents
- Add a Theme to Pi
- Selecting a Theme
- Creating a Custom Theme
- Theme Format
- Color Tokens
- Color Values
- Tips
Add a Theme to Pi
Pi includes the dark and light themes. Place a custom theme in your user or project themes directory.
See Loading resources for all supported locations and options.
Selecting a Theme
Select a theme via /settings or in settings.json:
{
"theme": "my-theme"
}
On first run, pi detects your terminal background and defaults to dark or light.
Initial Theme
Start an interactive run with a theme without changing the saved setting:
pi --use-theme light
To follow terminal appearance, use lightTheme/darkTheme syntax:
pi --use-theme light/dark
The CLI value is the initial theme for that run. Choosing another theme later in /settings applies it immediately
and saves it normally.
Creating a Custom Theme
- Create a theme file:
mkdir -p ~/.pi/agent/themes
vim ~/.pi/agent/themes/my-theme.json
- Define the theme with all required colors (see Color Tokens):
{
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"name": "my-theme",
"vars": {
"primary": "#00aaff",
"secondary": 242
},
"colors": {
"accent": "primary",
"border": "primary",
"borderAccent": "#00ffff",
"borderMuted": "secondary",
"success": "#00ff00",
"error": "#ff0000",
"warning": "#ffff00",
"muted": "secondary",
"dim": 240,
"text": "",
"thinkingText": "secondary",
"selectedBg": "#2d2d30",
"scrollbarTrack": "secondary",
"scrollbarThumb": "",
"searchMatchBg": "#2d2d30",
"searchMatchText": "",
"userMessageBg": "#2d2d30",
"userMessageText": "",
"customMessageBg": "#2d2d30",
"customMessageText": "",
"customMessageLabel": "primary",
"toolPendingBg": "#1e1e2e",
"toolSuccessBg": "#1e2e1e",
"toolErrorBg": "#2e1e1e",
"toolTitle": "primary",
"toolOutput": "",
"mdHeading": "#ffaa00",
"mdLink": "primary",
"mdLinkUrl": "secondary",
"mdCode": "#00ffff",
"mdCodeBlock": "",
"mdCodeBlockBorder": "secondary",
"mdQuote": "secondary",
"mdQuoteBorder": "secondary",
"mdHr": "secondary",
"mdListBullet": "#00ffff",
"toolDiffAdded": "#00ff00",
"toolDiffRemoved": "#ff0000",
"toolDiffContext": "secondary",
"syntaxComment": "secondary",
"syntaxKeyword": "primary",
"syntaxFunction": "#00aaff",
"syntaxVariable": "#ffaa00",
"syntaxString": "#00ff00",
"syntaxNumber": "#ff00ff",
"syntaxType": "#00aaff",
"syntaxOperator": "primary",
"syntaxPunctuation": "secondary",
"thinkingOff": "secondary",
"thinkingMinimal": "primary",
"thinkingLow": "#00aaff",
"thinkingMedium": "#00ffff",
"thinkingHigh": "#ff00ff",
"thinkingXhigh": "#ff0000",
"thinkingMax": "#ff0088",
"bashMode": "#ffaa00"
}
}
- Select the theme via
/settings.
Hot reload: Pi automatically watches the active personal theme at ~/.pi/agent/themes/<name>.json. Themes loaded from other sources require /reload after editing.
Theme Format
{
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"name": "my-theme",
"vars": {
"blue": "#0066cc",
"gray": 242
},
"colors": {
"accent": "blue",
"muted": "gray",
"text": "",
...
}
}
nameis required, must be unique, and must not contain/.varsis optional. Define reusable colors here, then reference them incolors.colorsmust define all 51 required tokens. Five optional tokens use the fallbacks listed below.
The $schema field enables editor auto-completion and validation.
Color Tokens
Every theme must define all 51 required color tokens. The optional tokens preserve compatibility with existing themes: scrollbarTrack falls back to muted, scrollbarThumb falls back to text, thinkingMax falls back to thinkingXhigh, searchMatchBg falls back to selectedBg, and searchMatchText falls back to text. Other search matches use searchMatchText on searchMatchBg with an underline; the current match reverses that foreground/background pair and uses bold text.
Core UI (11 required, 2 optional)
| Token | Purpose |
|---|---|
accent |
Primary accent (logo, selected items, cursor) |
border |
Normal borders |
borderAccent |
Highlighted borders |
borderMuted |
Subtle borders (editor) |
success |
Success states |
error |
Error states |
warning |
Warning states |
muted |
Secondary text |
dim |
Tertiary text |
text |
Default text (usually "") |
thinkingText |
Thinking block text |
scrollbarTrack |
Fullscreen scrollbar track foreground; optional, falls back to muted |
scrollbarThumb |
Fullscreen scrollbar thumb foreground; optional, falls back to text |
Backgrounds & Content (11 required, 2 optional)
| Token | Purpose |
|---|---|
selectedBg |
Selected line background |
searchMatchBg |
Transcript search match background and current-match text; optional, falls back to selectedBg |
searchMatchText |
Transcript search match text and current-match background; optional, falls back to text |
userMessageBg |
User message background |
userMessageText |
User message text |
customMessageBg |
Extension message background |
customMessageText |
Extension message text |
customMessageLabel |
Extension message label |
toolPendingBg |
Tool box (pending) |
toolSuccessBg |
Tool box (success) |
toolErrorBg |
Tool box (error) |
toolTitle |
Tool title |
toolOutput |
Tool output text |
Markdown (10 colors)
| Token | Purpose |
|---|---|
mdHeading |
Headings |
mdLink |
Link text |
mdLinkUrl |
Link URL |
mdCode |
Inline code |
mdCodeBlock |
Code block content |
mdCodeBlockBorder |
Code block fences |
mdQuote |
Blockquote text |
mdQuoteBorder |
Blockquote border |
mdHr |
Horizontal rule |
mdListBullet |
List bullets |
Tool Diffs (3 colors)
| Token | Purpose |
|---|---|
toolDiffAdded |
Added lines |
toolDiffRemoved |
Removed lines |
toolDiffContext |
Context lines |
Syntax Highlighting (9 colors)
| Token | Purpose |
|---|---|
syntaxComment |
Comments |
syntaxKeyword |
Keywords |
syntaxFunction |
Function names |
syntaxVariable |
Variables |
syntaxString |
Strings |
syntaxNumber |
Numbers |
syntaxType |
Types |
syntaxOperator |
Operators |
syntaxPunctuation |
Punctuation |
Thinking Level Borders (6 required, 1 optional)
Editor border colors indicating thinking level (visual hierarchy from subtle to prominent):
| Token | Purpose |
|---|---|
thinkingOff |
Thinking off |
thinkingMinimal |
Minimal thinking |
thinkingLow |
Low thinking |
thinkingMedium |
Medium thinking |
thinkingHigh |
High thinking |
thinkingXhigh |
Extra high thinking |
thinkingMax |
Maximum thinking; optional, falls back to thinkingXhigh |
Bash Mode (1 color)
| Token | Purpose |
|---|---|
bashMode |
Editor border in bash mode (! prefix) |
HTML Export (optional)
The export section controls colors for /export HTML output. If omitted, colors are derived from userMessageBg.
{
"export": {
"pageBg": "#18181e",
"cardBg": "#1e1e24",
"infoBg": "#3c3728"
}
}
Color Values
Four formats are supported:
| Format | Example | Description |
|---|---|---|
| Hex | "#ff0000" |
6-digit hex RGB |
| 256-color | 39 |
xterm 256-color palette index (0-255) |
| Variable | "primary" |
Reference to a vars entry |
| Default | "" |
Terminal's default color |
256-Color Palette
0-15: Basic ANSI colors (terminal-dependent)16-231: 6×6×6 RGB cube (16 + 36×R + 6×G + Bwhere R,G,B are 0-5)232-255: Grayscale ramp
Terminal Compatibility
Pi uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, pi falls back to the nearest approximation.
Check truecolor support:
echo $COLORTERM # Should output "truecolor" or "24bit"
Tips
Dark terminals: Use bright, saturated colors with higher contrast.
Light terminals: Use darker, muted colors with lower contrast.
Color harmony: Start with a base palette (Nord, Gruvbox, Tokyo Night), define it in vars, and reference consistently.
Testing: Check your theme with different message types, tool states, markdown content, and long wrapped text.
VS Code: Set terminal.integrated.minimumContrastRatio to 1 for accurate colors.
Examples
See the built-in themes: