Summary
A custom UI theme can restyle every surface except the code and diff viewers, which stay on the library's default pierre-dark. I'd like a UI theme to be able to declare its own code theme.
Proposed API
One optional field on the appearance schema (packages/domain/src/app-theme.ts, today { themeId, customCss, faviconColor }), where each side is a bundled Shiki theme name or a path to a theme file:
codeTheme: z
.object({
dark: z.string().optional(),
light: z.string().optional(),
})
.optional(),
Both sides are optional and resolved independently: an omitted dark falls back to pierre-dark, an omitted light to pierre-light. A dark-only theme declares dark alone and light mode is left untouched.
Built-in code theme
bb theme code-theme github-dark github-light
Resolves through Shiki's bundle. Roughly 60 of those themes already ship as lazy chunks in the app (github-dark, nord, monokai, vitesse-dark, …) and only the two pierre-* are ever requested today, so this case adds no payload.
Custom code theme shipped with the UI theme
A bundled name gets close, but a UI theme ported from an editor theme wants its own colors — so the same field should also take a path, resolved the way css already is, relative to the plugin directory:
The file is a standard VS Code / TextMate theme JSON — { name, type, colors, tokenColors } — passed to loadTheme() and referenced by its registered name. Anyone porting an editor theme already has this file, so shipping it alongside the CSS is a copy step rather than new work, and it makes a UI theme self-contained: chrome and code colors travel together and stay in sync.
Settings: a second, separate selector
Code theme should be its own control, not folded into the UI theme picker. They are independent choices — someone may want one UI theme with a different code theme, and someone running no custom UI theme at all may still want their editor's syntax colors in diffs.
UI theme [ My Theme ▾ ]
Code theme [ Use UI theme's default ▾ ]
├─ Use UI theme's default
├─ ── Built-in ──
├─ GitHub Dark
├─ Monokai
├─ Nord
├─ Vitesse Dark
└─ Custom theme file… (stretch goal)
"Use UI theme's default" is the default value, and it means: whatever the active UI theme declares in its codeTheme manifest field, falling back to the library default if it declares none. So a UI theme that ships code colors gets them automatically on selection, and selecting one that ships none changes nothing — no migration, no surprise for existing users.
Resolution and failure
Explicit user selection → active UI theme's codeTheme → library default. The user's choice wins because it is the more specific act; leaving the selector on "Use UI theme's default" is what hands control back to the UI theme.
Switching UI themes should not silently discard an explicit code-theme choice — keep it set, since it was chosen against the UI theme, not as part of it.
An unknown bundled name, an unreadable path, or a JSON that fails theme validation should log and fall back to the library default rather than failing the render.
Stretch goal: a code theme without authoring a UI theme
Everything above ties a code theme to a UI theme: the UI theme declares it — bundled name or shipped file — and the user selects the UI theme. That covers theme authors, but not the more common case — someone who likes bb's stock look and just wants their own editor's syntax colors in diffs. Authoring and installing a plugin to carry one JSON file is a lot of ceremony for that.
So: let a code theme be set on its own, pointing at a file the user already has.
bb theme code-theme ~/Downloads/my-editor-theme.json
In Settings, the "Custom theme file…" entry opens a native file picker. On selection the file is copied into <data-dir>/code-theme/<name>.json — copied rather than referenced, so the theme survives the source file moving or being deleted — and the entry then reads back as that theme's name, listed under a "Custom" group alongside the built-ins:
Code theme [ My Editor Theme ▾ ]
├─ Use UI theme's default
├─ ── Built-in ──
├─ GitHub Dark
├─ …
├─ ── Custom ──
├─ My Editor Theme
└─ Custom theme file…
Anything already in <data-dir>/code-theme/ is listed too, mirroring how custom UI themes are discovered from <data-dir>/theme/<name>/theme.css — so dropping a file in that directory and picking it from the CLI are the same operation as using the picker.
Reading and validating a theme file is already needed for the case above, so what is left here is the file picker, the copy, and discovery — which is why it can land separately, and why it needs no schema change when it does.
Summary
A custom UI theme can restyle every surface except the code and diff viewers, which stay on the library's default
pierre-dark. I'd like a UI theme to be able to declare its own code theme.Proposed API
One optional field on the appearance schema (
packages/domain/src/app-theme.ts, today{ themeId, customCss, faviconColor }), where each side is a bundled Shiki theme name or a path to a theme file:Both sides are optional and resolved independently: an omitted
darkfalls back topierre-dark, an omittedlighttopierre-light. A dark-only theme declaresdarkalone and light mode is left untouched.Built-in code theme
Resolves through Shiki's bundle. Roughly 60 of those themes already ship as lazy chunks in the app (
github-dark,nord,monokai,vitesse-dark, …) and only the twopierre-*are ever requested today, so this case adds no payload.Custom code theme shipped with the UI theme
A bundled name gets close, but a UI theme ported from an editor theme wants its own colors — so the same field should also take a path, resolved the way
cssalready is, relative to the plugin directory:The file is a standard VS Code / TextMate theme JSON —
{ name, type, colors, tokenColors }— passed toloadTheme()and referenced by its registeredname. Anyone porting an editor theme already has this file, so shipping it alongside the CSS is a copy step rather than new work, and it makes a UI theme self-contained: chrome and code colors travel together and stay in sync.Settings: a second, separate selector
Code theme should be its own control, not folded into the UI theme picker. They are independent choices — someone may want one UI theme with a different code theme, and someone running no custom UI theme at all may still want their editor's syntax colors in diffs.
"Use UI theme's default" is the default value, and it means: whatever the active UI theme declares in its
codeThememanifest field, falling back to the library default if it declares none. So a UI theme that ships code colors gets them automatically on selection, and selecting one that ships none changes nothing — no migration, no surprise for existing users.Resolution and failure
Explicit user selection → active UI theme's
codeTheme→ library default. The user's choice wins because it is the more specific act; leaving the selector on "Use UI theme's default" is what hands control back to the UI theme.Switching UI themes should not silently discard an explicit code-theme choice — keep it set, since it was chosen against the UI theme, not as part of it.
An unknown bundled name, an unreadable path, or a JSON that fails theme validation should log and fall back to the library default rather than failing the render.
Stretch goal: a code theme without authoring a UI theme
Everything above ties a code theme to a UI theme: the UI theme declares it — bundled name or shipped file — and the user selects the UI theme. That covers theme authors, but not the more common case — someone who likes bb's stock look and just wants their own editor's syntax colors in diffs. Authoring and installing a plugin to carry one JSON file is a lot of ceremony for that.
So: let a code theme be set on its own, pointing at a file the user already has.
bb theme code-theme ~/Downloads/my-editor-theme.jsonIn Settings, the "Custom theme file…" entry opens a native file picker. On selection the file is copied into
<data-dir>/code-theme/<name>.json— copied rather than referenced, so the theme survives the source file moving or being deleted — and the entry then reads back as that theme'sname, listed under a "Custom" group alongside the built-ins:Anything already in
<data-dir>/code-theme/is listed too, mirroring how custom UI themes are discovered from<data-dir>/theme/<name>/theme.css— so dropping a file in that directory and picking it from the CLI are the same operation as using the picker.Reading and validating a theme file is already needed for the case above, so what is left here is the file picker, the copy, and discovery — which is why it can land separately, and why it needs no schema change when it does.