komorebi-tray-grid
July 8, 2026 · View on GitHub
A tiny Windows system-tray indicator for the komorebi tiling window manager. Each tray icon is a 3×3 grid that mirrors the state of the nine workspaces on a single monitor; when multiple monitors are connected, one tray icon is created per monitor.

Per-cell visuals:
| Cell state | Appearance |
|---|---|
| empty workspace | transparent (no fill) |
| workspace with 1 window | dim gray fill |
| workspace with 2 windows | medium gray fill |
| workspace with 3+ windows | light gray fill |
| focused workspace | bright blue fill (overrides gray tiers) |
| workspace contains a full-screen container | yellow border (composes with the fill above) |
See spec.md for the original spec and plan.md for the design plan.
Usage
komorebi must be installed and running. Start komorebi as usual, then launch:
.\target\release\komorebi-tray-grid.exe
Tray Menu
Right-clicking any tray icon (or using the global hotkey) opens a menu where you can:
- Switch workspaces: Click a workspace item to focus it. The menu lists window titles for each workspace; the currently focused workspace is marked with a checkmark.
- Enable autostart — Toggle a per-user
HKCU\Software\Microsoft\Windows\CurrentVersion\Runentry so the app launches on logon. - Quit — Terminate the app and remove all tray icons.
Logs go to stderr; the log level can be tuned with KOMOREBI_TRAY_LOG, e.g.
$env:KOMOREBI_TRAY_LOG = "debug".
Configuration
The app can be customized with a JSON config file at:
%APPDATA%\komorebi-tray-grid\config.json
(Typically C:\Users\<your-user>\AppData\Roaming\komorebi-tray-grid\config.json)
If the file is missing or invalid, the app falls back to built-in defaults.
Example Configuration
{
"colors": {
"dark": {
"focused": "#2E9BFFFF",
"non_empty_1": "#6B6B6BFF",
"non_empty_2": "#8C8C8CFF",
"non_empty_3_plus": "#B0B0B0FF",
"full_screen_border": "#FFD500FF",
"active_monitor_border": "#2E9BFFFF",
"inactive_monitor_border": "#8C8C8CFF",
"empty": "#00000000"
},
"light": {
"focused": "#0067C0FF",
"non_empty_1": "#868686FF",
"non_empty_2": "#6A6A6AFF",
"non_empty_3_plus": "#4F4F4FFF",
"full_screen_border": "#C7A000FF",
"active_monitor_border": "#0067C0FF",
"inactive_monitor_border": "#6A6A6AFF",
"empty": "#00000000"
}
},
"menu": {
"show_hotkey": "Ctrl+Alt+G",
"max_title_length": 64,
"max_combined_title_length": 96
}
}
Colors
The app tracks Windows app mode (AppsUseLightTheme) and switches colors instantly between dark and light mode.
- Keys: All keys must be under
colors.darkandcolors.light. - Format: Supported formats are
#RRGGBB(alpha defaults toFF) and#RRGGBBAA. - Note:
colors.non_emptyhas been removed and is no longer used.
Menu & Global Hotkey
show_hotkey(optional string): A global keyboard shortcut to open the menu.- Format:
Modifier+KeyorModifier+Modifier+Key. - Modifiers:
Ctrl,Alt,Shift,Win. - Keys:
A-Z,0-9,F1-F12. - Examples:
Ctrl+Shift+K,Alt+F1,Win+Alt+G. - If you have multiple monitors, pressing the hotkey repeatedly will cycle the menu across each monitor's tray icon.
- Format:
max_title_length(optional integer, default64): Maximum length of an individual window title before it's ellipsized.max_combined_title_length(optional integer, default96): Maximum length of the joined string of all window titles in a workspace menu item.
Status
Early but functional. The MVP described in spec.md is implemented end-to-end —
renderer, komorebi event worker, per-monitor tray icons, right-click menu with the autostart
toggle, single-instance guard, interactive tray menu, and a CI-built NSIS installer — and tagged as v0.4.0. See the
releases page for prebuilt binaries.
Expect rough edges; bug reports and PRs are welcome.
Releases
Prebuilt binaries are published on the GitHub releases page.
Tagged pushes (v*) trigger
.github/workflows/release.yml, which builds on
windows-latest, runs tests, and uploads both a zipped portable .exe and the
NSIS *-setup.exe installer as release assets.
How it works
The app talks to komorebi directly over its AF_UNIX socket via the
komorebi-client crate, so
komorebic.exe doesn't need to be on PATH. On startup it:
- Acquires a
Global\komorebi-tray-gridnamed mutex so only one instance can run. - Queries
SocketMessage::Stateto seed the initial UI. - Calls
komorebi_client::subscribe(<unique name>)to register a per-process subscriber socket under%LOCALAPPDATA%\komorebi\. - Adds one tray icon per monitor reported by komorebi and updates it on every notification,
coalescing bursts (~50 ms debounce) into a fresh
Statequery. - If the subscription breaks, re-subscribes with exponential backoff and re-queries state.
Build
Prerequisites:
- Windows 10 or 11
- The pinned Rust toolchain from
rust-toolchain.toml(currently1.90.0,x86_64-pc-windows-msvctarget). Withrustupinstalled, the toolchain is picked up automatically on the firstcargoinvocation in this directory.
# Debug build
cargo build
# Release build (this is what CI ships)
cargo build --release --locked
# Run the tests (renderer + komorebi state mapping)
cargo test --locked
The release binary lands at target\release\komorebi-tray-grid.exe.
App icon
The Windows resource compiler embeds assets\app.ico as the exe's Explorer / Alt-Tab
icon, and the same file is used by the NSIS installer (see below). It is generated
on demand from the in-process renderer so it always matches the tray's visual style:
# Regenerate assets\app.ico and docs\icon.png.
cargo run --example gen_icon
The files are committed to the repository, so a fresh checkout builds without
running this step first; build still works (without an icon) even if you
delete assets\app.ico and docs\icon.png.
Windows installer
A signed-able NSIS installer can be built with
cargo-packager:
# One-time setup
cargo install cargo-packager --locked
# Build the installer (.exe). Runs `cargo build --release --locked` internally.
cargo packager --release
The resulting komorebi-tray-grid_<version>_x64-setup.exe lands in
target\packager\. The installer is per-user only (%LOCALAPPDATA%\Programs\…,
no UAC elevation): the app communicates with komorebi over an AF_UNIX socket at
the user's integrity level, and an elevated install would auto-launch the app
with a High-IL token that komorebi (Medium-IL) cannot write events into.
Installer settings live under [package.metadata.packager] in
Cargo.toml; to additionally build a .msi, add
"wix" to the formats array.