Coding Agent Theming
Relevant source files
The following files were used as context for generating this wiki page:The Coding Agent Theming system provides a flexible and dynamic way to customize the appearance of the Terminal User Interface (TUI). It allows users to define colors for various UI components, including text, borders, messages, and syntax highlighting, through simple JSON files. The system is designed to be extensible, supporting custom user-defined themes, and features live-reloading to apply theme changes without restarting the agent.
The theming engine is initialized at startup and can be controlled at runtime via the /theme slash command within the TUI. This provides an interactive way for users to switch between different visual styles. The system also supports dynamic colors that change based on the agent's state, such as the color of the editor border reflecting the current "thinking level".
Architecture
The theming architecture consists of three main parts: the Theme Engine (theme.ts), Theme Definition Files (.json), and the TUI Renderer (tui-renderer.ts), which consumes the theme.
This diagram shows the flow from application start, where initTheme loads a theme from a JSON file into the global theme object. The TuiRenderer uses this object to style UI components. The ThemeSelectorComponent allows the user to call setTheme to load a different theme at runtime. A file watcher triggers setTheme automatically when a theme file is modified.
Sources: packages/coding-agent/src/main.ts:1103-1105, packages/coding-agent/src/theme/theme.ts, packages/coding-agent/src/tui/tui-renderer.ts:1020-1065
Theme Definition
Themes are defined in JSON files that adhere to a specific schema. Each theme file must contain a name and a colors object. An optional vars object can be used to define reusable color variables.
Sources: packages/coding-agent/src/theme/theme-schema.json:5-8
Schema Structure
The structure of a theme JSON file is defined by theme-schema.json.
This ER diagram illustrates the main components of a theme file: a top-level THEME object containing name, vars (for variables), and the main colors object which holds all the specific color definitions.
Sources: packages/coding-agent/src/theme/theme-schema.json
Color Properties
The colors object contains key-value pairs where the key is a specific UI element and the value is a color. The value can be a hex string (e.g., #RRGGBB), a reference to a variable (e.g., "$blue"), a 256-color palette index (0-255), or an empty string for the terminal default.
The following table lists some of the key color properties:
| Property | Description |
|---|---|
accent | Primary accent color for the logo, selected items, and cursor. |
border | Default color for borders. |
error | Color for error states and messages. |
success | Color for success states. |
muted | Color for secondary or dimmed text. |
userMessageBg | Background color for user message bubbles. |
toolPendingBg | Background color for a tool execution box in a pending state. |
mdHeading | Color for Markdown headings. |
mdCode | Color for inline Markdown code. |
syntaxComment | Color for comments in syntax-highlighted code blocks. |
syntaxKeyword | Color for keywords in syntax-highlighted code blocks. |
thinkingOff | Editor border color when thinking level is "off". |
thinkingHigh | Editor border color when thinking level is "high". |
bashMode | Editor border color when in bash mode (input starts with !). |
Sources: packages/coding-agent/src/theme/theme-schema.json:45-214
Theme Loading and Management
The core logic for loading, applying, and watching themes is in packages/coding-agent/src/theme/theme.ts.
Initialization and Loading
At startup, main.ts calls initTheme with the theme name from user settings. initTheme in turn calls setTheme.
The setTheme function orchestrates the loading process:
- It calls
loadThemeto find and parse the specified theme JSON file. loadThemesearches for the theme file first in the user's custom theme directory (~/.pi/agent/themes/) and then in the application's default theme directory (dist/theme/).- If the theme file is found and parsed successfully, its colors are merged with the base
darktheme to ensure all properties are set. - If the specified theme fails to load, the system falls back to the
darktheme. - The global
themeobject is updated with the new colors. - A file watcher is set up on the loaded theme file to enable live-reloading.
Sources: packages/coding-agent/src/main.ts:1103-1105, packages/coding-agent/src/theme/theme.ts:101-143
The following diagram shows the sequence of events when a theme is changed.
Live Reloading
The theming system supports live reloading. When a theme is loaded via setTheme, a file watcher is attached to the corresponding JSON file. If the file is modified, the onThemeChange callback is triggered, which calls setTheme again to reload the theme and apply the changes to the TUI.
Sources: packages/coding-agent/src/theme/theme.ts:139-141, packages/coding-agent/src/tui/tui-renderer.ts:602-607
Applying Themes in the TUI
The TuiRenderer class is the primary consumer of the theme object. It uses theme colors to style various components.
Dynamic Colors
A key feature is the ability to apply colors dynamically based on the application's state. The editor's border color is a prime example, changing based on the agent's thinkingLevel or if the editor is in bashMode.
// packages/coding-agent/src/tui/tui-renderer.ts:1290-1297
private updateEditorBorderColor(): void {
if (this.isBashMode) {
this.editor.borderColor = theme.getBashModeBorderColor();
} else {
const level = this.agent.state.thinkingLevel || "off";
this.editor.borderColor = theme.getThinkingBorderColor(level);
}
this.ui.requestRender();
}
The getThinkingBorderColor function in theme.ts retrieves the appropriate color from the theme object.
// packages/coding-agent/src/theme/theme.ts:220-222
export function getThinkingBorderColor(level: ThinkingLevel): (text: string) => string {
return theme.fg(theme.colors[`thinking${level.charAt(0).toUpperCase() + level.slice(1)}` as keyof ThemeColors]);
}
Sources: packages/coding-agent/src/tui/tui-renderer.ts:1290-1297, packages/coding-agent/src/theme/theme.ts:220-222
Component Theming
The theme is passed to various TUI components to ensure a consistent look and feel.
- Editor: The
CustomEditorreceives a theme object constructed bygetEditorTheme(). - Markdown: The
Markdowncomponent receives a theme fromgetMarkdownTheme(), which maps markdown elements (like headings and links) to colors defined in the theme. - Messages: Components like
UserMessageComponentandAssistantMessageComponentdirectly use the globalthemeobject to style text and backgrounds.
Sources: packages/coding-agent/src/tui/tui-renderer.ts:175, packages/coding-agent/src/tui/tui-renderer.ts:373, packages/tui/test/markdown.test.ts:11-23
/theme Command
Users can change the active theme at runtime using the /theme slash command. This command triggers the ThemeSelectorComponent, which presents a list of available themes.
This flow shows how the /theme command initiates a UI component that, upon user selection, calls the core setTheme function to apply the new theme and refresh the display.
Sources: packages/coding-agent/src/tui/tui-renderer.ts:508-513, packages/coding-agent/src/tui/tui-renderer.ts:1020-1065
Creating a Custom Theme
Users can create their own themes by placing a JSON file in the user-specific theme directory.
- Locate the themes directory: Create a directory at
~/.pi/agent/themes/. The agent automatically discovers JSON files in this location.
Sources: packages/coding-agent/src/theme/theme.ts:39-42, packages/coding-agent/src/config.js - Create a theme file: Create a new file, e.g.,
my-theme.json. - Define the theme: Use
packages/coding-agent/src/theme/theme-schema.jsonas a reference to define thename,vars(optional), andcolorsproperties. Any color properties not defined in your custom theme will fall back to the values from the defaultdarktheme.
Sources: packages/coding-agent/src/theme/theme-schema.json, packages/coding-agent/src/theme/theme.ts:127-133 - Use the theme: Run the coding agent and use the
/themecommand to select your new theme from the list.
The agent is also instructed via its system prompt to read its own documentation at README.md for guidance on creating custom themes.
Sources: packages/coding-agent/src/main.ts:586-589
Conclusion
The Coding Agent's theming system is a powerful feature for personalizing the user experience. It is built on a simple, file-based JSON structure, making it easy for users to create and share themes. Its support for live-reloading and dynamic, state-aware colors demonstrates a well-integrated and user-friendly design that enhances the TUI's usability and aesthetic appeal.