piagent_
← ~/guides

Themes and Color

Last updated: Aug 7, 2026

$ pi –theme

TL;DR. Themes are JSON files that must declare all 51 required color tokens (Markdown, tool diffs, syntax highlighting, thinking-level borders, bash mode) and may reference shared vars. Discovery order: built-in dark/light, then ~/.pi/agent/themes/, then .pi/themes/ (after the project is trusted), then packaged. Selection: settings.json’s theme key, /settings, or pi --theme <path> (repeatable). Edits to the active custom theme hot-reload live. Package themes via pi: { themes: [...] } in package.json for pi install npm: distribution.

Every pixel of the Pi TUI comes from a JSON theme file. Built-in dark and light themes ship with the agent, and everything else — Catppuccin, Tokyo Night, your own custom palette — is a JSON file in one of the standard discovery locations. This guide covers how themes are selected, what the 51 required color tokens actually control, and how to author and package your own. The authoritative reference is the Themes documentation and the JSON schema in the repo.

How Pi chooses a theme

There are four ways to select a theme, in increasing priority:

  1. First-run detection. On first launch Pi samples your terminal background and defaults to dark or light.
  2. /settings. The interactive settings UI lists every discovered theme.
  3. settings.json. Set "theme": "my-theme" to make it persistent across projects.
  4. CLI flag. pi --theme <path> (repeatable, so you can layer several) or pi --no-themes to skip discovery entirely.
# Use a specific theme file
pi --theme ~/.pi/agent/themes/catppuccin-mocha.json

# Combine a base theme with a project-specific override
pi --theme ~/.pi/agent/themes/tokyonight.json --theme ./.pi/themes/local-tweaks.json

Edits to the active custom theme file reload automatically — there is no need to restart Pi or run /reload to see your changes.

Where theme files live

Pi discovers themes from four locations, in this order:

  • Built-in: dark and light, compiled into the agent.
  • Global: ~/.pi/agent/themes/*.json.
  • Project: .pi/themes/*.json (only after the project has been trusted).
  • Packages: themes/ directories or pi.themes entries inside an installed package’s package.json.

For packaged themes, you can also list files or directories in settings.json under a themes array, which is useful when you want to point at a theme outside the standard paths without copying it.

The site resource map lists a few ready-to-use themes under the themes category — see pi-catppuccin, pi-tokyonight, and pi-ansi-themes for installable examples.

Anatomy of a theme file

A minimal but valid theme looks like this:

{
  "$schema": "https://pi.dev/schema/theme.json",
  "name": "my-theme",
  "vars": {
    "primary": "#ff7b00"
  },
  "colors": {
    "accent": "primary",
    "border": "#3a3a3a",
    "text": "#e6e6e6"
    // ...the remaining 48 required tokens
  }
}
  • name is required, must be unique, and must not contain /.
  • vars is optional and lets you reference a color from multiple tokens.
  • colors must define all 51 required tokens (see below). Two are optional: thinkingMax falls back to thinkingXhigh, and scrollbarThumb falls back to selectedBg.
  • $schema enables editor auto-completion and validation against theme-schema.json — keep it.
  • export is an optional section that customizes how the theme renders in HTML exports (pageBg, cardBg, infoBg).

Color values can be a hex string ("#ff0000"), an xterm 256-color integer, a reference to a vars entry ("primary"), or an empty string to use the terminal’s default color.

The 51 required tokens

The schema groups them into seven functional buckets:

  • 11 core UI tokens: accent, border, borderAccent, borderMuted, success, error, warning, muted, dim, text, thinkingText.
  • 11 background / message tokens: selectedBg, userMessageBg, userMessageText, customMessageBg, customMessageText, customMessageLabel, toolPendingBg, toolSuccessBg, toolErrorBg, toolTitle, toolOutput. (scrollbarThumb is the optional 12th.)
  • 10 Markdown tokens: mdHeading, mdLink, mdLinkUrl, mdCode, mdCodeBlock, mdCodeBlockBorder, mdQuote, mdQuoteBorder, mdHr, mdListBullet.
  • 3 tool-diff tokens: toolDiffAdded, toolDiffRemoved, toolDiffContext.
  • 9 syntax-highlighting tokens: syntaxComment, syntaxKeyword, syntaxFunction, syntaxVariable, syntaxString, syntaxNumber, syntaxType, syntaxOperator, syntaxPunctuation.
  • 6 thinking-level border tokens (with thinkingMax optional): thinkingOff, thinkingMinimal, thinkingLow, thinkingMedium, thinkingHigh, thinkingXhigh. The thinkingMax token, introduced in v0.80.6, draws the border for the new opt-in max thinking level above xhigh.
  • 1 bash-mode token: bashMode.

The full list is maintained in theme-schema.json — refer to it whenever you wonder whether a token exists for the visual you are tweaking.

A worked example

Suppose you want a dark theme with a warm orange accent, cool gray borders, and a higher-contrast user-message background. Start from dark.json and override what you need:

{
  "$schema": "https://pi.dev/schema/theme.json",
  "name": "dusk",
  "vars": {
    "accent": "#ff7b00",
    "border": "#3a3a3a",
    "userBg": "#1a1f2b"
  },
  "colors": {
    "accent": "accent",
    "border": "border",
    "borderAccent": "accent",
    "borderMuted": "border",
    "text": "#e6e6e6",
    "userMessageBg": "userBg"
  }
}

Save this as ~/.pi/agent/themes/dusk.json, then /settings → Theme, or run pi --theme ~/.pi/agent/themes/dusk.json. Edits are picked up live.

Terminal compatibility

Pi uses 24-bit RGB and expects a truecolor terminal:

echo $COLORTERM
# Expected: "truecolor" or "24bit"

On older terminals Pi approximates to the nearest 256-color value rather than degrading to 16 colors. If a custom theme looks washed out, the terminal is the first place to look.

Packaging a theme for distribution

If you want to share a theme via pi install, package it as an npm or git package with a pi field pointing at the theme entry:

{
  "name": "pi-theme-dusk",
  "pi": {
    "themes": ["./dusk.json"]
  }
}

Users install it via pi install npm:pi-theme-dusk, and Pi discovers the theme through the package’s themes/ directory or its pi.themes listing in package.json. The Packages documentation covers the full publishing flow; the same pi.extensions mechanism used by code extensions applies to themes.

Further reading