原始内容
pi-dark-or-light
Automatically switch Pi between configured dark and light themes.
pi-dark-or-light is a Pi extension for people who want Pi to follow the appearance of their system or terminal without hard-coding a single theme value in settings.json.
User Guide
Why pi-dark-or-light
Terminals, desktop environments, and multiplexers can change between dark and light appearances. This extension detects the current mode and applies the matching Pi theme.
In short: the extension decides dark vs light, and you optionally decide which theme name each mode should use.
Features
- Dark/light detection — resolves the current appearance from OS, tmux, environment, terminal, or fallback signals.
- Theme mapping — map detected
darkandlightmodes to built-in or custom Pi theme names. - UI-only behavior — runs only in interactive UI sessions; headless/non-UI runs are left alone.
- Live polling — re-checks every 5 seconds so appearance changes can be picked up while Pi is running.
- Terminal background query — supports xterm-compatible
OSC 11, useful in multiplexers such as Herdr whenCOLORFGBGis absent. - Project override support — reads global and project Pi settings.
Install
Install from npm:
pi install npm:@mjakl/pi-dark-or-light
Install from git:
pi install git:github.com/mjakl/pi-dark-or-light
Or install from a local checkout:
pi install /path/to/pi-dark-or-light
Package name: @mjakl/pi-dark-or-light.
Quick start
Minimal setup:
{
"dark-or-light": {
"dark": "dark",
"light": "light"
}
}
Example with custom themes:
{
"dark-or-light": {
"dark": "tokyo-night",
"light": "github-light"
}
}
If you do not configure a mapping, the extension uses Pi's built-in dark and light themes.
For Pi theme setup, including built-in and custom themes, see Pi's themes documentation.
Configuration
The extension reads settings from the same places Pi normally uses:
- Global:
~/.pi/agent/settings.json - Project:
.pi/settings.json
Project settings override global settings.
Use either config key:
dark-or-light(recommended)darkOrLight(also accepted)
Supported config:
{
"dark-or-light": {
"dark": "theme-name-for-dark-mode",
"light": "theme-name-for-light-mode",
"default": "dark"
}
}
All keys are optional:
dark— theme name to use when detection resolves to dark mode.light— theme name to use when detection resolves to light mode.default— fallback mode when no detector returns an answer; allowed values aredarkandlight.
Partial config is valid. For example:
{
"dark-or-light": {
"dark": "tokyo-night"
}
}
In that case:
- detected
dark->tokyo-night - detected
light-> built-inlight
You can also change the final fallback mode:
{
"dark-or-light": {
"default": "light",
"light": "github-light"
}
}
In that case, if no detector succeeds, the extension chooses light, which then maps to github-light.
If a mapped theme cannot be loaded
If you map dark or light to a custom theme name and Pi cannot apply it, the extension falls back to the built-in dark or light theme for that detected mode.
Recommended setup
If you want Pi to follow your environment automatically:
- Configure
dark-or-lightonly if you want custom theme names. - Let the extension choose the current mode from OS and terminal signals.
If you want a fixed theme instead, disable or remove this extension.
Technical Reference
These sections document config merging, detector order, and local development details.
When the extension is active
The extension manages the theme whenever it is loaded in a UI session.
If Pi or another workflow writes a top-level theme into settings.json, this extension still applies the detected dark/light result on startup and during polling.
Config merge behavior
Global and project dark-or-light settings are merged field-by-field, with project settings overriding global settings.
Use the same key spelling in both files if you rely on merging. Do not mix dark-or-light in one file with darkOrLight in the other.
Example global settings:
{
"dark-or-light": {
"dark": "tokyo-night",
"light": "github-light"
}
}
Example project settings:
{
"dark-or-light": {
"dark": "gruvbox-dark"
}
}
Result for that project:
dark->gruvbox-darklight->github-light
Detection order
The extension uses a fixed detector chain. The first detector that returns a clear answer wins.
Overall order:
- macOS native appearance
- Windows native appearance
- tmux client theme
DARK_MODEenvironment variable- terminal default background query (
OSC 11) COLORFGBGheuristic- configured
defaultmode, defaulting todark
Detectors that do not apply on the current platform are skipped.
Operating-system-specific order
macOS
On macOS, the extension first asks the OS directly by running osascript and querying System Events for the current dark mode setting.
true->darkfalse->light
macOS order:
- Native macOS appearance via
osascript - tmux
#{client_theme} DARK_MODE- terminal default background query (
OSC 11) COLORFGBG- configured
defaultmode, defaulting todark
Windows
On Windows, the extension first checks:
HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize
It reads AppsUseLightTheme:
0->dark1->light
Windows order:
- Native Windows appearance via
AppsUseLightTheme - tmux
#{client_theme} DARK_MODE- terminal default background query (
OSC 11) COLORFGBG- configured
defaultmode, defaulting todark
Linux and other Unix-like systems
There is no desktop-environment-specific Linux detector. Linux appearance settings vary across GNOME, KDE, sway, Hyprland, remote shells, containers, and headless sessions, so the extension uses terminal-oriented signals instead.
Linux / other Unix order:
- tmux
#{client_theme} DARK_MODE- terminal default background query (
OSC 11) COLORFGBG- configured
defaultmode, defaulting todark
Shared detectors
tmux
If Pi is running inside tmux, the extension tries:
tmux display-message -p #{client_theme}
Accepted values are normalized case-insensitively:
darklight1/true->dark0/false->light
This detector is attempted only when the environment suggests Pi is running in tmux (TMUX is set or TERM_PROGRAM=tmux).
DARK_MODE
If DARK_MODE is set, the extension accepts:
dark,1,true->darklight,0,false->light
This is useful from shell profiles, wrapper scripts, launchers, or platform-specific automation.
Terminal default background (OSC 11)
If no explicit environment override is set, the extension asks the current terminal for its default background color:
ESC ] 11 ; ? ESC \\
Terminals that support this xterm-compatible query answer with an RGB color such as:
ESC ] 11 ; rgb:fafa/fafa/fafa ESC \\
The extension classifies bright backgrounds as light and dark backgrounds as dark.
If the terminal or multiplexer does not answer quickly, the detector times out and the chain continues.
Herdr note: Herdr 0.7.0 captures the host terminal background when the client attaches. If you change your terminal theme while keeping the same Herdr client attached, Herdr may keep answering with the old color until you detach and reattach.
COLORFGBG
If no stronger detector succeeds, the extension uses COLORFGBG, similar to Pi's built-in heuristic.
It parses the second ;-separated field. In the common two-part form, that field is the background color index.
- background color index
< 8->dark - background color index
>= 8->light
Examples:
COLORFGBG=15;0-> second field0->darkCOLORFGBG=0;15-> second field15->light
Unusual multi-part COLORFGBG values may not apply and the detector chain will continue.
Final fallback
If none of the detectors produce an answer, the extension falls back to dark-or-light.default.
Default if unset: dark.
Allowed values: dark, light.
Local development
Install dependencies and run the type check:
npm install
npm run typecheck
One-off local testing:
pi -e /path/to/pi-dark-or-light/src/index.ts
Acknowledgements
This extension was influenced by Pi's own macOS theme example:
License
MIT