Minimal TUI brightness controller for DDC/CI displays
ddcutilinstalled and accessible in$PATH- Go 1.25+
i2ckernel module loaded (sudo modprobe i2c-dev)- User in
i2cgroup (sudo usermod -aG i2c $USER)
Download the latest release for your platform:
# Linux (amd64)
curl -L https://github.com/mateuspim/luma/releases/download/latest/luma-linux-amd64.tar.gz | tar xz
sudo mv luma /usr/local/bin/
# Linux (arm64)
curl -L https://github.com/mateuspim/luma/releases/download/latest/luma-linux-arm64.tar.gz | tar xz
sudo mv luma /usr/local/bin/
# macOS (Apple Silicon)
curl -L https://github.com/mateuspim/luma/releases/download/latest/luma-darwin-arm64.tar.gz | tar xz
sudo mv luma /usr/local/bin/Copy the example config:
mkdir -p ~/.config/luma
cp config.toml.example ~/.config/luma/config.tomlgit clone https://github.com/mateuspim/luma
cd luma
make build
sudo mv luma /usr/local/bin/Copy the example config:
mkdir -p ~/.config/luma
cp config.toml.example ~/.config/luma/config.tomllumaThe UI fills the terminal window automatically and adapts to any terminal size.
| Key | Action |
|---|---|
↑ / ↓ |
Select display |
+ / - |
Brightness ±small |
[ / ] |
Brightness ±medium |
{ / } |
Brightness ±large |
Enter |
Open slider for selected display |
a |
Open Set All slider |
q |
Quit |
| Key | Action |
|---|---|
← / → |
Brightness ±small |
[ / ] |
Brightness ±medium |
{ / } |
Brightness ±large |
Enter |
Apply and return to list |
Esc |
Discard and return to list |
Step sizes shown in the footer reflect your current config values.
Full annotated config.toml example:
[steps]
small = 1 # +/- keys
medium = 5 # [/] keys
large = 10 # {/} keys
[display]
refresh_interval_ms = 5000 # 0 = disabled, minimum 2000 if enabled
show_display_name = true
[guardrails]
debounce_ms = 300 # wait after last keypress before firing ddcutil [100-2000]
max_ddcutil_procs = 1 # hard cap on concurrent ddcutil processes [1-2]
command_timeout_s = 8 # kill ddcutil if it hangs beyond this [3-30]
[theme]
accent_color = "#9B59B6"[steps]
small(default: 1) — Step size for+/-keysmedium(default: 5) — Step size for[/]keyslarge(default: 10) — Step size for{/}keys
[display]
refresh_interval_ms(default: 5000) — Auto-refresh brightness values. Set to0to disable. Minimum2000if enabled. Refresh only runs when idle (no ddcutil processes running, no pending debounce, not in slider mode).show_display_name(default: true) — Display monitor names in the list view
[guardrails]
debounce_ms(default: 300, range: 100–2000) — Wait time after last keypress before firing ddcutil. Prevents command spam during rapid key presses.max_ddcutil_procs(default: 1, range: 1–2) — Hard cap on concurrent ddcutil processes. Commands are dropped (non-blocking) if the limit is reached.command_timeout_s(default: 8, range: 3–30) — Kill ddcutil if it hangs beyond this timeout.
[theme]
accent_color(default:"#9B59B6") — Hex color for UI accents (header, cursor, selected row, separator, gradient bar fill).
All guardrail values are clamped to their valid ranges — invalid config is silently corrected.
By default, ddcutil is slow (~1.2s per call). To speed it up, create ~/.config/ddcutil/ddcutilrc:
options: --sleep-multiplier 0.1 --skip-ddc-checks --noverify
Bus caching: luma runs ddcutil detect at startup and caches --bus N for each display, dropping per-call overhead from ~1.2s to ~0.124s by avoiding repeated bus enumeration.
The UI adapts to the terminal size:
- Wide (≥74 cols): full bar, 14-char name column, full footer
- Compact (40–73 cols): narrower bar, 10-char name column, abbreviated footer
- Minimal (<40 cols): no bar, percentage only, compact footer
╭────────────────────────────────────────────────────────────────────────╮
│◈ luma v1.0.0 ⠋ │
├────────────────────────────────────────────────────────────────────────┤
│▸ AOC 27G2G4 ╸██████████████████████──────────────────────╺ 50% │
│ CMI GP2711 ╸████████████████████████████████────────────╺ 75% │
├────────────────────────────────────────────────────────────────────────┤
│ ↑/↓ Enter · [a]ll · [q]uit ◆ +/- ±1 · [/] ±5 · {/} ±10 │
╰────────────────────────────────────────────────────────────────────────╯
⠋spinner appears when ddcutil is running▸cursor and█fill rendered inaccent_color- Selected row name and percentage rendered in bold
- Bar fill interpolates from
#000000→accent_color
╭────────────────────────────────────────────────────────────────────────╮
│◈ luma v1.0.0 · AOC 27G2G4 [q]uit │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ ╸████████████████████████████████────────────────────────────╺ 42% │
│ │
├────────────────────────────────────────────────────────────────────────┤
│ ←/→ ±1 · [/] ±5 · {/} ±10 · Enter apply · Esc back │
╰────────────────────────────────────────────────────────────────────────╯
The Set All slider (a from the list) shows · All Displays in the title instead of the display name.
To trigger a versioned release, push a tag:
git tag v1.0.0
git push --tagsThis automatically builds binaries for all platforms and creates a GitHub Release with an auto-generated changelog.
MIT