Chapter 12 · Themes Customization
Chapter goals: Understand pi themes' JSON structure and 51 required color tokens; learn to install/switch themes; and从头编写 a shareable完整自定义主题.
12.1 What a Theme Is and Where It Lives
pi's themes are JSON files defining TUI配色. Load positions覆盖按优先级:
| Source | Path | Note |
|---|---|---|
| Built-in | — | dark; light two sets |
| Global | ~/.pi/agent/themes/*.json | Available to all projects |
| Project | .pi/themes/*.json | Loads only after the project is trusted |
| Package | The包's themes/ directory or the pi.themes declaration in package.json | Distributed with the包 |
| Settings | The themes array in settings.json | Specify files or directories |
| CLI | --theme <path> (可重复) | Temporarily append |
Use --no-themes to禁用所有 discovery mechanisms; leaving only the built-in themes.
12.2 Three Ways to Switch Themes
# Method 1: Switch in-interactive (立即生效并保存)
/settings # Select the theme in the menu
# Method 2: Write into settings.json
{
"theme": "my-theme"
}
# Method 3: Effective only for this run (does not改 saved settings)
pi --use-theme lightA贴心细节 — auto-select following the terminal's外观:
pi --use-theme light/dark
# Slash syntax: use light for浅色调终端; dark for深色调终端On首次运行时 pi检测s the terminal background color; defaulting to dark or light.
12.3 Building a Complete Theme from Scratch
mkdir -p ~/.pi/agent/themesCreate ~/.pi/agent/themes/solar-mint.json:
{
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"name": "solar-mint",
"vars": {
"mint": "#2dd4a7",
"ink": "#1b2430",
"paper": "#f5f3ec",
"gray": 242,
"amber": "#d97706"
},
"colors": {
"accent": "mint",
"border": "mint",
"borderAccent": "#14b8a6",
"borderMuted": "gray",
"success": "#16a34a",
"error": "#dc2626",
"warning": "amber",
"muted": "gray",
"dim": 240,
"text": "",
"thinkingText": "gray",
"selectedBg": "#e7f6f0",
"userMessageBg": "#eef2f7",
"userMessageText": "",
"customMessageBg": "#f0fdf9",
"customMessageText": "",
"customMessageLabel": "mint",
"toolPendingBg": "#fffbeb",
"toolSuccessBg": "#f0fdf4",
"toolErrorBg": "#fef2f2",
"toolTitle": "mint",
"toolOutput": "",
"mdHeading": "amber",
"mdLink": "mint",
"mdLinkUrl": "gray",
"mdCode": "#0f766e",
"mdCodeBlock": "",
"mdCodeBlockBorder": "gray",
"mdQuote": "gray",
"mdQuoteBorder": "mint",
"mdHr": "gray",
"mdListBullet": "mint",
"toolDiffAdded": "#16a34a",
"toolDiffRemoved": "#dc2626",
"toolDiffContext": "gray",
"syntaxComment": "gray",
"syntaxKeyword": "#0369a1",
"syntaxFunction": "#7c3aed",
"syntaxVariable": "amber",
"syntaxString": "#15803d",
"syntaxNumber": "#be185d",
"syntaxType": "#0369a1",
"syntaxOperator": "#475569",
"syntaxPunctuation": "gray",
"thinkingOff": "gray",
"thinkingMinimal": "mint",
"thinkingLow": "#0ea5e9",
"thinkingMedium": "#06b6d4",
"thinkingHigh": "#8b5cf6",
"thinkingXhigh": "#d946ef",
"bashMode": "amber"
}
}要点解析:
$schemagives editorsauto-completion and validation;varsdefine复用 color variables; referenced by name incolors;colorsmust定义全部 51 required tokens; optional tokens (thinkingMax;scrollbarThumb;searchMatchBg/Text) have fallback values (e.g.scrollbarThumbfalls back toselectedBg) when missing.
Hot Reload
After editing the currently active custom theme file; pi auto-reloads;改色即时可见;非常适合调配色.
12.4 Four Color Value Formats and Terminal Compatibility
| Format | Example | Description |
|---|---|---|
| Hex | "#ff0000" | 6-digit hex RGB |
| 256-color | 39 | xterm 256-color palette index (0-255) |
| Variable reference | "primary" | Points to an entry in vars |
| Terminal default | "" | Use the terminal's default foreground/background |
256-color index calculation:基础 ANSI colors 0-15; RGB cube 16 + 36×R + 6×G + B (R/G/B取 0-5); 232-255 are灰阶渐变.
echo $COLORTERM
# Output truecolor or 24bit indicates the terminal supports真彩pi uses 24-bit RGB;老终端 only having 256 colors auto-fallbacks to the closest color. VS Code users建议把 terminal.integrated.minimumContrastRatio set to 1;避免 VS Code私自调整 your配色.
12.5 Sharing Themes and Programmatic操作
Sharing is putting the JSON into a pi包 (detailed in the next chapter): place a themes/ directory inside the包; or declare in package.json:
{
"name": "my-themes-pack",
"keywords": ["pi-package"],
"pi": {
"themes": ["./themes"]
}
}Extensions can also查询 and切换 programmatically:
export default function (pi: ExtensionAPI) {
pi.registerCommand("theme-light"; {
description: "Switch to the light theme";
handler: async (_args; ctx) => {
const themes = ctx.ui.getAllThemes(); // [{ name; path? }; ...]
const light = ctx.ui.getTheme("light"); // Load但不切换
const result = ctx.ui.setTheme(light!); // Or setTheme("light") switch by name
if (!result.success) {
ctx.ui.notify(`Switch failed: ${result.error}`; "error");
}
ctx.ui.theme.fg("accent"; "Switched"); // The current theme object可直接取色渲染
},
});
}Note: the theme API degrades in RPC mode (getAllThemes() returns an empty array etc.); this is a明确列出的限制 in the官方 doc.
Chapter Summary
- A theme = JSON with
$schema; 51 required tokens + a少量 optional tokens (with fallback rules); - Three install locations (global/project/package) +
--use-theme单次生效 + thelight/dark跟随终端 syntax; - Four color formats: hex / 256-color index / vars references / terminal default
""; - The currently active theme file supports hot-reload;配色调试体验极佳;
- Extensions可编程式管理 themes via
ctx.ui.getAllThemes()/getTheme()/setTheme().
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. How many required color tokens must a合法 pi custom theme define?
2. What happens when the currently used custom theme file is修改?
3. What does pi --use-theme light/dark mean?
4. What does writing the color value as 39 in a theme JSON mean?
🛠️ Hands-on Practice
- Base your preferred配色体系 (Nord/Gruvbox/Tokyo Night etc.) on
varsto组织 a完整主题 and enable it via/settings. 2.故意 delete themdHeadingtoken from the theme; observe what pi报错s; then补回来验证 the validation logic. - Write a小 extension: register a
/theme-cyclecommand; each call循环 in thegetAllThemes()list and switch themes;提示 the current theme name vianotify.
After completing; continue to Chapter 13: Pi Packages Ecosystem and Distribution.