Theme System
14 built-in themes, accent color override, live preview, terminal color schemes, and theme sharing through JSON export and import.
Overview
The theme system controls the appearance of all app UI chrome: surfaces, text, borders, accents, shadows, and frosted glass effects. Each theme is a hand-crafted color palette, compiled into over 140 CSS tokens so every surface stays consistent.
Daintree ships with 14 built-in themes, split evenly between dark and light. Daintree is the default dark theme, with a eucalyptus green accent. Bondi Beach is the default light theme, a deep coastal teal. On first launch, the app picks whichever matches your operating system's current appearance.
There are three places to switch themes. The Settings picker is an inline listbox under Settings → Appearance → App. The theme palette (Cmd+K, T) is a floating fuzzy-search switcher for keyboard-first changes. The Theme Browser is a full drawer that slides in from the right edge, opened from the "Change theme…" button in Settings or from the Action Palette (Cmd+Shift+P → "Change Theme…"). All three preview themes live as you browse, so you see a scheme applied across the whole app before you commit to it. An accent color override sits below the theme list if you want to keep a theme's surfaces but swap its accent.
If none of the built-in options fit, export any theme as a JSON file, edit the colors, and import it back as a custom theme. See Theme Export and Import below.
App themes and terminal color schemes are two separate settings. The app theme controls all UI chrome: sidebar, toolbar, panels, dock. Terminal color schemes control ANSI output rendering inside terminal panels. Both live under Settings > Appearance, on different subtabs.
Built-in Themes
Every built-in theme draws its palette from a real-world natural ecosystem. The accent color anchors the visual identity; surface and text colors are tuned to complement it. All 14 themes include frosted glass effects, driven by per-theme material blur and saturation values.
Dark Themes
| Theme | Accent | Inspired by |
|---|---|---|
| Daintree | #36CE94 eucalyptus green | Daintree Rainforest, QLD, Australia |
| Arashiyama | #C46240 terracotta copper | Arashiyama Bamboo Grove, Kyoto, Japan |
| Fiordland | #3AB7C5 fjord teal | Fiordland, South Island, New Zealand |
| Galapagos | #4A9E7F ocean teal-green | Galapagos Islands, Ecuador |
| Highlands | #9B86AE heather purple | Scottish Highlands, Scotland |
| Namib | #86ABC3 desert sky blue | Namib Desert, Namibia |
| Redwoods | #4E9A53 forest green | Redwood National Park, California, USA |
Light Themes
| Theme | Accent | Inspired by |
|---|---|---|
| Bondi Beach | #145A44 deep teal-green | Bondi Beach, Sydney, Australia |
| Atacama | #9B4B2A rust terracotta | Atacama Desert, Chile |
| Bali | #228243 tropical green | Bali, Indonesia |
| Hokkaido | #586CD6 frost indigo | Hokkaido, Japan |
| Serengeti | #A28224 savanna gold | Serengeti National Park, Tanzania |
| Svalbard | #2D7A96 arctic blue | Svalbard Archipelago, Norway |
| Table Mountain | #A8456E fynbos rose | Table Mountain, Cape Town, South Africa |
Changing Your Theme
The theme picker lives under Settings → Appearance → App. It's an inline listbox: a palette strip hero at the top showing the active theme's colors, a search input and a Dark/Light type toggle below the strip, and a scrollable list of theme rows underneath. The active theme is highlighted. Click any row and that theme applies immediately across the whole app.
A shuffle button sits above the list for jumping to a random theme. The Export and Import buttons sit below it for round-tripping themes through JSON. An accent color swatch and its "Reset to theme default" button sit below the list as well, covered further down in Accent Color Override.
A "Change theme…" button also sits in the picker. It opens the Theme Browser, a larger drawer with hero previews and a dedicated list, covered below.
The shuffle button above the list cycles through all 14 themes in random order. A quick way to find themes you haven't tried.
The first-run welcome dialog prompts you to choose between Daintree and Bondi Beach. It auto-selects based on your OS appearance, but you can switch. A note below the choice cards points to Settings → Appearance for all 14 themes.
Live Preview
Hover over a theme row and its colors preview across the whole app after a 300ms debounce: sidebar, toolbar, panels, dock, everything. Moving to a different row replaces the preview. Moving off the list reverts to your saved theme. Keyboard focus, from tabbing or arrowing into the list, previews immediately with no debounce, so keyboard navigation stays instant.
Previews are transient. The saved theme doesn't change until you click a row, or press Enter in the theme palette. Pressing Escape while a preview is active also reverts, which is handy when you want to compare something quickly without committing by accident.
Previewing a theme doesn't save it. The preview only sticks when you deliberately select a row. Move away, press Escape, or close the picker, and you're back on your saved theme.
Reveal Animation
When you deliberately select a theme, by clicking a row, shuffling, or committing from the Settings picker, the UI plays a short directional sweep as the new theme swaps in. The direction follows your click position. Clicks on the left half of the window sweep the old theme out to the right; clicks on the right half sweep it left. The whole thing runs in about 400ms.
The animation is built on document.startViewTransition with a WAAPI clip-path slide, so it composites on the GPU. It turns off automatically when prefers-reduced-motion: reduce is set, when performance mode is active, when the document is hidden, or when the browser doesn't support View Transitions. In those cases the switch happens instantly with no animation.
Switching Themes from the Theme Palette
To switch themes from the keyboard without opening Settings, press Cmd+K, T. It's a chord: press Cmd+K, release, then press T. A floating theme palette opens, seeded to your current theme, with a fuzzy search across every available theme.
Arrow keys walk the list with instant live preview on each step, no debounce. Enter commits the focused theme and closes the palette. Escape reverts to the theme that was active when you opened the palette, then closes. Clicking a row also commits immediately.
Each result row shows a palette strip of the theme's colors, its name, its Dark or Light label, the file path for custom themes, and an "Active" badge on the currently applied theme. The palette works from anywhere in the app.
Cmd+K, T is the fastest way to switch themes without leaving what you're doing. Fuzzy search narrows to any theme in a few keystrokes, and arrow-key previews let you compare before you commit.
Toggling Dark and Light
To flip between your preferred dark and light themes without scrolling a list, there's a Toggle Dark/Light Theme command. It has no default keyboard shortcut, but you can run it from the Action Palette: press Cmd+Shift+P and type "toggle theme". The command switches to whichever of your preferred themes, set under Match System Appearance, is the opposite of what you're on now, then shows a brief toast with the new theme name.
The Theme Browser
The Theme Browser is a 380px drawer that slides in from the right edge of the window. It's the most spacious way to shop for a theme: a hero preview at the top, a searchable list with thumbnails, and a commit bar at the bottom. The theme palette is built for a quick keyboard switch. The browser is built for browsing and comparing before you decide.
Opening the Browser
The browser has no default keyboard shortcut. There are two ways to open it:
- In Settings → Appearance → App, click the "Change theme…" button.
- From the Action Palette (
Cmd+Shift+P), type "Change Theme" and select Change Theme…
To be clear: Cmd+K, T does not open the browser. It opens the theme palette, a separate, lighter-weight surface. The browser is the drawer; the palette is the floating quick-switcher.
Layout
The drawer is laid out top to bottom:
- Hero (200px, sticky): shows the active or previewing theme's hero image, falling back to a color swatch strip when a theme has no image. The theme's name and location sit in a caption at the bottom; a close (X) button sits in the top-right corner.
- Search and Dark/Light toggle: a search input filters the list by name, and a Dark/Light segmented toggle filters by type. Switching the type filter reverts any active preview first, so a theme you can no longer see in the list can't be committed by accident.
- Theme list: a scrollable list where each row shows a thumbnail or color swatch, the theme name, a color strip, and a checkmark on the theme you currently have committed. Custom themes also show their file path, and any theme with validation warnings shows a small warning pill. An empty search reads "No themes match your search."
- Commit bar (sticky): a Cancel button and a Set theme button pinned to the bottom.
Previewing and Committing
Clicking a row previews that theme immediately across the whole app, with no debounce. This differs from the Settings picker, where hovering waits 300ms before previewing. A click in the browser only previews. It doesn't save anything until you commit.
Arrow keys (Up, Down, Page Up, Page Down) walk the list with the same instant visual preview on each step. The screen-reader announcement of the focused theme is debounced by 300ms so it doesn't fire on every keystroke during a fast scroll. Arrow keys work whether focus is in the list or in the search input, so you can type to filter and then arrow through results without moving your hands.
Set theme (or Enter) commits the previewed theme. It turns off match system appearance if it was on, plays the reveal sweep from the button's position, closes the drawer, and saves your choice. Cancel, Escape, the close (X) button, or clicking the dimmed area behind the drawer all revert the preview and close without saving. One exception: if you've typed a search query, the first Escape clears the query rather than closing the drawer.
Settings and Panel Behavior
Opening the browser closes the Settings dialog so you can see the live preview across the full app. When you close the browser, Settings re-opens to the Appearance tab only if that's where you opened it from. Opening the browser from the Action Palette doesn't re-open Settings afterward.
While the Theme Browser is open, the rest of the app is dimmed and non-interactive. You can't click panels behind the drawer, and they're removed from the accessibility tree. If the Portal (the built-in web browser) is open, it hides temporarily so it doesn't draw over the preview, and its toggle is blocked. Closing the browser brings everything back exactly as it was.
Accent Color Override
The Accent color section under the theme picker lets you override a theme's accent with any CSS color. Use it when a theme's surfaces are right but you want a different accent: a team brand color, a personal preference, or more contrast for color vision reasons.
Click the color swatch to open your OS native color picker. Changes apply live as you adjust, with no debounce, so you can drag through the picker and watch the app update in real time. The Reset to theme default button next to the swatch clears the override and restores whatever accent the current theme originally shipped with.
The override persists across app restarts and rides alongside any theme you switch to. Live previews, whether from hover, keyboard focus, or theme palette arrowing, show the override combined with the previewed theme, so what you see is what you get.
Exporting a theme while an accent override is active bakes the override into the exported JSON, as the accent-primary token. So an export is a handy way to share a themed variant with a custom accent color, no JSON editing required.
Match System Appearance
The Match system appearance toggle in the theme picker tells Daintree to follow your operating system's dark/light mode. When it's on, the app switches automatically whenever your OS appearance changes.
Two sub-pickers appear below the toggle: Preferred dark theme and Preferred light theme. These set which specific theme to use for each mode. The defaults are Daintree for dark and Bondi Beach for light.
One thing to note: selecting a theme from the main picker while follow-system is on disables the toggle. That stops the OS from overriding a deliberate choice.
Terminal Color Schemes
Terminal color schemes control the ANSI color palette used inside terminal panels: the foreground, background, and 16 ANSI colors that programs use for syntax highlighting, status output, and prompts. They're configured separately from the app theme, under Settings → Appearance → Terminal.
The Terminal subtab also covers font size (8–24 px), font family (JetBrains Mono or system monospace), and other terminal display settings. Color scheme selection is the focus of this section.
Choosing a Color Scheme
The color scheme picker is a two-column scrollable grid. Each card shows a mini terminal mockup rendered with the scheme's actual colors, displaying sample output like $ ls src/, $ git status, and test results, so you can see how the scheme looks in practice.
A sticky search input sits at the top of the grid for filtering by name. Light schemes carry a small "light" badge on their card. Selecting a scheme applies it immediately to all open terminal and agent panels, since both use ANSI rendering.
Match App Theme
Match App Theme is the default selection. It keeps your terminal colors in sync with whatever app theme you're using. Instead of a fixed palette, it reads the active theme's terminal color tokens and applies them to the terminal in real time.
Daintree and Bondi Beach have hand-crafted terminal color mappings, designed alongside their app themes. Every other app theme supplies its own terminal colors through CSS custom properties, so each one gets a distinct terminal palette that complements its UI chrome. There's no generic fallback here. Switching from Fiordland to Highlands gives you a genuinely different terminal look.
The hybrid input bar, the command input inside terminal panels, also takes its colors from the active terminal scheme. Background, foreground, cursor, and chip colors all update to match, keeping the input bar consistent with the terminal output above it.
Match App Theme is dynamic. Switch app themes and the terminal colors update automatically. To lock in a specific terminal look regardless of the app theme, pick one of the named schemes instead.
Built-in Schemes
Daintree ships with 25 built-in terminal color schemes. Seven are Daintree originals, designed to pair with the app's own themes. The other eighteen are community favorites ported from popular editor and terminal projects.
Daintree originals
- Match App Theme: dynamic, derives colors from the active app theme
- Daintree: dark, eucalyptus green accent paired with the Daintree app theme
- Fiordland: dark, cold fjord palette with teal cursor
- Daintree Ember: dark, warm terracotta and ember tones
- Redwoods: dark, forest brown and green
- Hokkaido: light, frost-blue winter palette
- Bondi: light, coastal teal paired with the Bondi Beach app theme
Community dark schemes
- Dracula
- One Dark
- Monokai
- Solarized Dark
- GitHub Dark
- Catppuccin Mocha
- Tokyo Night
- Gruvbox Dark
- Everforest Dark
- Oceanic Next
- Kanagawa Dragon
- Tomorrow Night
Community light schemes
- Solarized Light
- Rosé Pine Dawn
- Catppuccin Latte
- Atom One Light
- Gruvbox Light
- Ayu Light
Importing Custom Schemes
If the built-in options don't cover your preferred palette, you can import custom color schemes from files. The Import color scheme... button sits below the picker grid in the Terminal subtab.
Click the button to open a native file dialog. Select a color scheme file and it's added to your list straight away, as the active scheme. Imported schemes persist across app restarts.
Three file formats are supported:
- iTerm2 (
.itermcolors): the XML plist format used by iTerm2 and many other macOS terminals. It's the most widely shared format in the terminal theming community. - Base16 JSON: JSON files with
base00throughbase0Fkeys, following the Base16 convention common in the Neovim and editor theming ecosystem. - VS Code JSON: JSON files with
terminal.ansiBlack,terminal.background, and similar keys matching VS Code's terminal color token format.
Format detection is automatic, based on file extension and key patterns. Any ANSI slots missing from the imported file are filled with sensible defaults.
The iTerm2-Color-Schemes GitHub repository has over 200 free .itermcolors files you can import directly into Daintree. A quick way to try a wide range of palettes.
Imported custom schemes can't currently be removed through the Settings UI. Once a scheme is imported, it stays in your list. To stop using one, select a different scheme.
Theme Export and Import
Themes are shared as JSON files. The Export app theme and Import app theme buttons in the theme picker let you save any theme to a file, edit the colors, and pass it to someone else.
Exporting a Theme
Export works on any theme, including the built-in ones. The exported file is a clean JSON document, ready for sharing or editing.
- Open Settings > Appearance and select the theme to export
- Click Export app theme... below the theme picker
- Choose a save location in the file dialog. The filename defaults to
ThemeName.json
The exported file contains the theme's name, its type (dark or light), and the full set of color tokens. Internal metadata like the location and builtin flags is stripped, so the file is clean for redistribution. Cancelling the save dialog does nothing, with no error message.
Importing a Theme
Importing adds a theme to your custom themes list and switches to it.
- Open Settings > Appearance and click Import app theme... below the theme picker
- Select a
.jsontheme file from the file dialog - The theme loads, validates, and activates. You'll see a confirmation:
Imported "Theme Name".
If the file has non-fatal warnings (see below), the message changes to Imported "Theme Name" with N warning(s). and lists the specific issues, but the theme still loads. If the file has validation errors, like invalid colors or an invalid heroImage, the import is blocked entirely and the errors appear inline. Cancelling the file dialog is silent.
The Theme File Format
Exported themes use a straightforward JSON structure: the theme name, type, and a tokens object holding the color values.
{
"name": "My Custom Theme",
"type": "dark",
"tokens": {
"surface-canvas": "#1a1a2e",
"surface-sidebar": "#1e1e34",
"surface-panel": "#232340",
"text-primary": "#e8e8ed",
"text-secondary": "#a0a0b0",
"accent-primary": "#36ce94",
"border-default": "#2a2a45"
}
} You don't need to specify all ~140 token keys. Any tokens you leave out fall back to the defaults from the matching built-in theme: Daintree for dark themes, Bondi Beach for light themes. A handful of core tokens, surfaces, text, accent, and borders, is enough to define a distinct look.
The importer also accepts a flat format where token keys sit at the root level alongside the metadata fields. Both formats work the same way.
If you omit the type field, Daintree infers dark or light from the luminance of the surface colors. Including type explicitly avoids the inference warning.
A few newer tokens cover form controls and validation states. You don't have to set any of them. Each one is derived automatically from tokens you've already defined, so a theme that omits them still looks correct. Set them when you want explicit control:
| Token | What it controls | Default if omitted |
|---|---|---|
surface-disabled | Background of disabled inputs | A mix of surface-input and surface-canvas |
status-danger-surface | The wash behind an invalid form field | The danger color at roughly 8–10% alpha |
knob-base | The fill of switch and slider knobs | Off-white on dark themes, near-black on light themes |
state-modified | The dot marking a setting changed from its default | Derived from status-info, not the accent |
Informational UI now draws from status-info rather than the accent. Info pills, banners, toasts, and per-row markers all use status-info. The accent is reserved for focus rings, switch tracks, primary buttons, and selection states. Older custom themes that never defined status-info still work. They fall back to the matching built-in theme's blue, so info elements stay readable. To set a specific info color, define status-info in your theme.
Import Validation
Imports run through two layers of checks: hard errors that block the import entirely, and soft warnings that let the theme load with a note.
Invalid color values now block the import outright. That's a change from the earlier behavior, where malformed colors came through as non-fatal warnings. Old custom theme files that used to import with warnings may need to be cleaned up before they'll load.
Errors: import is blocked
Daintree collects every validation error in a single pass and reports them together, so you see all the issues at once instead of one at a time.
- Invalid color values: any color token whose value isn't a valid CSS color fails the import. The error message is:
Invalid color values for token(s): <list>. Values must be valid CSS colors (hex, rgb/rgba, hsl/hsla, oklch/oklab, color-mix, var, or named color). - Invalid
heroImage: theheroImagevalue has to be either adata:image/URL or a relative or root-relative path (./themes/foo.pngor/themes/foo.png). Remote URLs (http:,https:), file URLs,javascript:, protocol-relative URLs (//cdn.example.com), and absolute Windows or UNC paths are all rejected. - Invalid
accent-rgb: this token is the one exception to the CSS-color rule. It expects a comma-separated RGB triplet like"62, 144, 102", each component an integer between 0 and 255.
Accepted CSS color formats for any color token:
- Hex: 3-, 4-, 6-, and 8-digit (
#abc,#abcd,#aabbcc,#aabbccdd) rgb()andrgba(), both legacy comma and modern space syntaxhsl()andhsla()oklch()andoklab()color-mix()(validated one level deep)var()references, optionally with a color fallback- All 147 CSS named colors, plus
transparentandcurrentcolor
Non-color tokens, like material-blur, radius-scale, and shadow values, are only checked for being a non-empty string. They're passed through verbatim.
Warnings: import succeeds with a note
These are non-fatal. The theme still imports and activates, but a message appears below the buttons listing anything worth a look.
- Inferred type: the file didn't include a
typefield, so Daintree guessed dark or light from the luminance of the surface colors. Add"type": "dark"or"type": "light"to the file to make it explicit. - Unknown tokens: the
tokensobject contains keys Daintree doesn't recognize. These are silently ignored. It usually happens when you import a theme from a newer version of Daintree into an older one. - Contrast issues: certain text/surface color combinations don't meet WCAG contrast ratios. Daintree checks key pairs:
text-primaryon surface colors (4.5:1 minimum),text-secondaryon panels (3.0:1 minimum), and terminal foreground on terminal background. Low-contrast themes still import, but may be hard to read.
Contrast warnings don't block the import, but themes with low contrast ratios can be hard to read for some users. Worth a review if you plan to share the theme publicly.
Sharing Themes
Theme sharing is file-based and works with any transfer method. Export a .json file, send it over Slack or email or commit it to a repo, and the recipient imports it. An exported file can be re-imported without data loss, so round-tripping works cleanly.
Built-in themes are fully exportable, which makes them a good starting point for team themes. Export a built-in, adjust the accent and surface colors to match your team's branding, and distribute the file. Everyone imports the same file and gets an identical setup.
Imported themes appear in the auto-switching picker and the random shuffle pool alongside the built-in options.
Color Vision Accessibility
Daintree has color vision deficiency (CVD) modes that make status indicators and terminal output more distinguishable. They live in Settings > Appearance under the Color Vision section.
Three modes are available:
- Default: the standard color palette, no adjustments.
- Red-Green (Deuteranopia and Protanopia): remaps red and green status indicators to more distinguishable alternatives.
- Blue-Yellow (Tritanopia): remaps blue and yellow indicators the same way.
CVD modes affect status indicator colors (success, danger, GitHub state colors) and terminal ANSI color mappings. They don't touch the theme's accent color or surface palette, so your chosen theme still looks like itself.