KEYBARS PRO
The command line
keybars Pro comes with one command, keybars-pro, for everything the window does that’s worth doing from a terminal: lighting keys when a build finishes, starting a Focus session from a keybind, keeping your rules in a dotfiles repo, or letting a coding agent tap you on the shoulder. keybars Pro isn’t out yet; this is its command line as it will ship.
keybars-pro # open keybars Pro, or bring its window forward
keybars-pro run -- make test # light the keyboard while it runs, then green or red
keybars-pro light esc red # hold Escape red until you clear it
keybars-pro focus start 50m # a 50-minute Focus session
keybars-pro help # every command
Install
The command comes with the app. In keybars Pro, open App settings and choose Install the command-line tool under Command line. That puts keybars-pro on your PATH:
| System | Where it goes |
|---|---|
| Linux, macOS | a link in /usr/local/bin if keybars Pro can write there, else ~/.local/bin |
| Windows | a small keybars-pro.cmd in %LocalAppData%\keybars-pro\bin, which is added to your user PATH |
It never replaces a file it didn’t make. If the folder isn’t on your PATH yet, the app says so: add ~/.local/bin to your shell’s PATH, or on Windows open a new terminal. Remove in the same place takes it off again.
Behind the link is a small program that sits beside the app, keybars-pro-cli. You don’t need its name, except that hooks written by the coding agents’ Set up for me use its full path so they work without a PATH at all.
How it works
The command talks to the running app through a local socket that only your user account can open: $XDG_RUNTIME_DIR/keybars-pro.sock on Linux, and control.sock beside the settings elsewhere. It isn’t reachable over the network.
- The app has to be running. Every command but
keybars-proon its own,completion,engineandmcp’s startup needs it. When it isn’t, the command sayskeybars Pro isn't runningand exits with status 3.keybars-prowith no command starts it. - It does what the window does. Each command calls the same code as the window’s buttons, so a change made here shows in the window at once, and is checked and saved the same way.
- Free copies work too. As in the window, Pro features play in the preview on a free copy and on the keyboard with a licence.
keybars-pro statussays which you have. - Flags go anywhere after the command:
keybars-pro light esc red -for 5sandkeybars-pro light -for 5s esc redare the same. Anything after--is left alone. -jsonon any command that prints something gives JSON instead, for scripts andjq.
Exit status
| Status | Means |
|---|---|
| 0 | done |
| 1 | it failed; the reason is on standard error |
| 2 | the command or its arguments weren’t right; its usage is printed |
| 3 | keybars Pro isn’t running |
| other | run passes on the exit status of the command it ran |
Builds and scripts
run
keybars-pro run [-name build] [-q] -- command [args...]
Runs a command and lights the keyboard for it: build.running as it starts, then build.passed or build.failed by its exit status, which run passes on as its own. Standard input and output go straight through, and Ctrl-C reaches the command. With the default rules, the top row chases amber while it runs and Escape holds red if it fails.
keybars-pro run -- make test
keybars-pro run -name deploy -- ./ship.sh # deploy.running, deploy.passed, deploy.failed
keybars-pro run -q -- go test ./... # no warning when the app isn't open
If keybars Pro isn’t running, the command runs anyway, with a one-line warning unless -q.
notify
keybars-pro notify [-q] [-source cli|github|forgejo] [-repo r] [-branch b] event [state]
Sends an event to your Notify rules. The second word turns a task into an event name:
| You type | Event sent |
|---|---|
notify build 0 | build.passed |
notify build 1, or any other number | build.failed |
notify build $? | whichever the last command’s status says |
notify build running | build.running |
notify deploy.done | deploy.done, as written |
-repo and -branch say what the event is about, for rules that only fire for one repository or branch. -source is cli unless you say otherwise; a tool that watches GitHub or Forgejo itself, such as herdr-gh, sends -source github (or forgejo) with their event names, so rules for that service play its events whether they came through the relay or not. -q prints nothing and exits 0 even when the app isn’t running, which is what agents’ hooks want. Without it, notify prints the rules the event played, or no rule matches.
make test; keybars-pro notify build $?
keybars-pro notify -repo keybars -branch main deploy.done
keybars-pro notify -source github -repo me/app pull_request.merged
Lighting keys
light
keybars-pro light keys colour [-effect hold] [-for 5s]
Lights keys straight away, with no rule to set up. keys is one or more key names, comma-separated; colour is a colour name or #rrggbb. The effect is any of the nine effects, hold if you leave it out. Held lights stay until you clear them; -for clears them after that long (5s, 2m).
keybars-pro light esc red
keybars-pro light top-row amber -effect pulse
keybars-pro light all green -effect wave -for 5s
keybars-pro light r1c1,r1c12 '#ff3df2' -effect breathe
Lighting the same keys again replaces the light that was there. Lights play over the music and under nothing: they sit at the top of your rules.
clear
keybars-pro clear [lights | rule name]
| You type | It stops |
|---|---|
clear | everything playing: lights, held rules and effects |
clear lights | everything lit with light |
clear CI failed | that rule, by its name |
clear top-row | the light on those keys |
Key names
A keyboard tells keybars where a key is, never what it types: that’s up to your layout. So keys are named by position, top row first and the left-most key first, counted from 1. keybars-pro map prints your keyboard’s positions.
| Name | Keys |
|---|---|
all | every key |
top-row, home-row, bottom-row | the top row, the third row down, the bottom row |
thumbs | the bottom row: the thumb keys on a Moonlander or Voyager |
left, right | each half |
top-left, esc | the top-left key, Escape on most layouts |
top-right | the top-right key |
row:2, col:5 | a whole row or column |
r3c4 | the key at row 3, column 4 |
led:12 | the key with LED 12, as map numbers them |
row:1-2, col:2-4, led:1-4 | a range of rows, columns or LEDs |
r1c2-r2c5 | every key in the rectangle between two corners, in either order |
Combine them with commas: esc,top-right, row:1,col:12, r1c2-r1c5,led:30. Case and spaces don’t matter.
Colours
red, amber, orange, green, blue, cyan, purple, pink, white, and off (dark), or any #rrggbb (quote it in most shells: '#ff3df2').
Effects
| Effect | Plays | What it does |
|---|---|---|
flash | 0.9 s | on and off three times |
pulse | 3 s | fades up and down three times |
wave | 1.5 s | sweeps left to right across the keys |
fade | 3 s | lights up, then fades away |
sparkle | 3 s | the keys twinkle at random |
ripple | 1.5 s | rings spread over the whole board from each key |
hold | until cleared | stays lit |
breathe | until cleared | glows up and down slowly, never dark |
chase | until cleared | a light runs along the keys, for something running |
The app
status
keybars-pro status [-json]
on · Pro, updates until 2027-10-14 · Voyager
bars: music · typing: off · focus: work, 18:42 left
hearing: Built-in Audio Analog Stereo
playing: CI failed, Agent waiting
service: github connected
Whether the keyboard is lit, the licence and how long its updates run, the keyboard, what the bars show, Typing, Focus, what the app hears, the rules playing now, connected services, and any startup step that failed. -json adds the startup steps in full.
on, off, toggle
The switch at the top of the window. off hands the keyboard back to its own layout and the preview with it; on lights it again; toggle flips it, which is the one to bind to a key in your desktop’s shortcuts.
test
keybars-pro test plays the 30-second test (a sweep through every column and row, with no music needed); keybars-pro test stop ends it early.
open, quit, retry
open brings the window forward; keybars-pro with no command does the same, and starts the app if it isn’t running. quit quits keybars Pro. retry starts again after a startup step failed, such as the keyboard being unplugged.
devices, map
keybars-pro devices [-json]
keybars-pro map [forget]
devices shows the keyboard (how it’s connected, its LEDs and, on a ZSA board, its Oryx protocol), the map in use, the audio source and whether OpenRGB’s server answers. map prints the keyboard’s map, each key’s LED number in its place, for led:N and rRcC:
# voyager: each key's LED, rows top to bottom; - for no key
0 1 2 3 4 5 26 27 28 29 30 31
6 7 8 9 10 11 32 33 34 35 36 37
map forget drops a map saved with Find keys, going back to the built-in one.
system
keybars-pro system [-json] prints CPU, memory and temperature now, as System mode reads them: CPU 12% over 8 cores · memory 41% · 52 °C. macOS doesn’t give apps a temperature.
licence
keybars-pro licence [-json]
keybars-pro licence activate KEY
keybars-pro licence activate -here
keybars-pro licence deactivate
Shows the licence on this computer and how long its updates run. activate takes the key from your email. A key is good on three computers; when it’s active on another one, activate -here moves it to this one. deactivate frees this computer’s place.
Modes
focus
keybars-pro focus [start [25m] | stop | status] [-json]
The Focus timer. start begins a session of your usual length, or this one’s: start 50m, start 1h, start 25 (minutes). stop ends it. On its own, or with status, it prints work, 18:42 left, break, 3:10 left or idle.
bars
keybars-pro bars music or bars cpu: what the bars show, the music or each CPU core’s load (System mode).
typing
keybars-pro typing on | off | stats [-json]
Typing mode lights your key presses in place of the music, on ZSA boards. stats prints 62 wpm now · 88 best today · 4210 keys today.
ambient
keybars-pro ambient [scene | on | off | list] [-brightness 40] [-speed 100] [-when-quiet on|off] [-json]
Ambient mode loops a calm scene on the keyboard in place of the music, with no events or sound. Naming a scene turns it on: ambient rain. list shows them all:
| Scene | Plays |
|---|---|
rain | drops fall down the columns and splash along the bottom row |
zen | one slow colour breathing across the board, teal to violet |
autumn | orange, red and gold leaves blown across in gusts |
aurora | green and violet curtains rippling sideways |
ocean | waves rolling in, white at the crest |
fireflies | warm dots blinking on and off at random |
snow | flakes drifting down and piling on the bottom row |
embers | a fire flickering at the bottom, sparks rising |
breathing | box breathing: rows fill for 4 seconds, hold, empty, hold |
-brightness caps it, 5 to 100 percent (40 to start, so it stays calm); -speed runs it slower or faster, 25 to 400 percent. -when-quiet on plays the scene whenever the music stops, in place of the keyboard’s own layout. Notify’s rules and Focus still show on top. On its own, ambient prints on · rain · 40% bright · 100% speed.
clock
keybars-pro clock [rows | ring | spelled | binary | off]
A clock on the keyboard, through Ambient mode:
| Clock | Shows |
|---|---|
rows | the hour on the top row (a key each, 1 to 12), five-minute steps on the second with the current key filling, and a key walking the third row with the seconds |
ring | the board’s outer keys as a clock face: the hour amber, the minute cyan, a faint second hand |
spelled | the time spelled on the number row’s digit keys, one at a time: for 14:30, 1, 4, a pause, 3, 0 |
binary | hours, minutes and seconds as six bits on the top three rows |
clock on its own is the rows clock; clock off turns Ambient off.
timer
keybars-pro timer [10m [name] | stop] [-json]
A countdown draining across the top two rows, green to amber to red, flashing for three seconds when it’s done. It plays over whatever’s showing: the music, a scene, Typing. timer 25m tea names it; on its own, timer prints tea, 18:42 left.
Notify rules
A rule lights keys when an event arrives. The window’s rule editor is the easy way to paint keys; these are for everything else.
rules
keybars-pro rules [list] [-json]
keybars-pro rules add name event -keys k [-colour red] [-source cli] [-effect hold]
[-clear-on events] [-clear-after minutes] [-repo r] [-branch b] [-off]
keybars-pro rules remove | on | off | try name
keybars-pro rules export > rules.json
keybars-pro rules import [-replace] rules.json
| Action | What it does |
|---|---|
list | each rule: on or off, its name, source, event, effect and how many keys |
add | a new rule at the top, where the window adds them; -keys takes key names |
remove | deletes a rule |
on, off | switches a rule without deleting it |
try | plays a rule now, as the editor’s Test does |
export | prints every rule as JSON |
import | adds rules from a file, or standard input with -; -replace replaces yours |
Rules are found by name, ignoring case. The higher a rule, the more it wins when two light the same key.
keybars-pro rules add "CI failed" ci.failed -source github -keys esc -colour red -clear-on ci.passed
keybars-pro rules add "Doorbell" doorbell -source webhook -keys all -colour cyan -effect ripple
keybars-pro rules add "Agent waiting" agent.waiting -keys top-right -colour blue \
-effect breathe -clear-on "agent.working agent.done" -clear-after 60
-source is where the event comes from: cli (this command and agents’ hooks), github, forgejo, webhook or system. Held effects (hold, breathe, chase) stay until one of -clear-on’s events arrives, space-separated, or -clear-after minutes pass (0 for never), or you clear them.
events
keybars-pro events [-n 10] [-json] lists what Notify got lately, newest first, with the rules each played:
14:02:11 github pull_request.merged jwarykowski/keybars main PR merged
13:58:40 cli build.failed Escape red
Event names
| Source | Events |
|---|---|
cli | anything you send: build.running, build.passed, build.failed, deploy.done, … |
| agents’ hooks | agent.working, agent.waiting, agent.done |
github | pull_request.merged, pull_request.opened, pull_request.closed, pull_request.review_requested, review.approved, review.changes_requested, ci.running, ci.passed, ci.failed, push, release.published, issue.opened |
forgejo | as GitHub’s, without ci.running (Forgejo only reports finished runs) |
webhook | the name at the end of the address, or a JSON body’s "event" |
system | cpu.high, cpu.normal, memory.high, memory.normal, temperature.high, temperature.normal |
Services
GitHub, Forgejo and any other service reach keybars Pro through a relay, which gives each a private address and passes events on while the app is open.
services, connect, disconnect
keybars-pro services [-json]
keybars-pro connect github | forgejo | webhook
keybars-pro disconnect github | forgejo | webhook
services lists what’s connected, its state and when the last delivery came. connect makes an address and prints it, with the secret to paste into GitHub’s or Forgejo’s webhook settings. disconnect removes the service; its address stops working, so delete the webhook on the other side too.
webhook
keybars-pro webhook url [event] [-secret]
keybars-pro webhook test
keybars-pro webhook secret on | off
For Any webhook: url backup.failed prints the address for that event, ready to paste into a monitor, a deploy hook or Home Assistant; -secret also prints the Authorization: Bearer header. test sends a test event through the relay. secret on makes the relay refuse anything without the secret; with it off, the address itself is the secret.
curl -X POST "$(keybars-pro webhook url deploy.done)"
Coding agents
agents
keybars-pro agents [-json]
keybars-pro agents setup claude | codex | gemini | cursor | opencode | aider
keybars-pro agents remove claude
Lists the agents keybars Pro knows, and whether each is on this computer and set up. setup adds keybars Pro’s hooks to the agent’s own settings beside the hooks already there, after copying the file to <file>.keybars-backup; remove takes them out and leaves the rest. Each hook runs notify -q agent working, agent waiting or agent done. Codex and Aider take only one notify command; if one is already set, agents says so and you add keybars Pro’s by hand.
| Agent | Settings file | Sends |
|---|---|---|
| Claude Code | ~/.claude/settings.json | working, waiting, done |
| Codex CLI | ~/.codex/config.toml | done |
| Gemini CLI | ~/.gemini/settings.json | working, waiting, done |
| Cursor | ~/.cursor/hooks.json | working, done |
| OpenCode | ~/.config/opencode/plugins/keybars.js | waiting, done |
| Aider | ~/.aider.conf.yml | done |
mcp
keybars-pro mcp is a Model Context Protocol server on standard input and output, so an agent can use keybars Pro as tools of its own, with no hooks to set up:
claude mcp add keybars -- keybars-pro mcp
| Tool | Does |
|---|---|
light_keys | lights keys, as light |
clear_keys | clears them, as clear |
notify | sends an event to your rules |
status | reads the app’s status |
focus | starts, stops or reads the Focus timer |
Other agents take the same command in their MCP settings.
Marketplace
market
keybars-pro market search [words] [-json]
keybars-pro market show item [-json]
keybars-pro market install item
keybars-pro market remove id
keybars-pro market list [-json]
Looks, rule packs, key maps and integrations from the marketplace. item is an ID (ci-pack), a .keybars file or a link to one. Items from keybars.app are signed, and one whose signature doesn’t check out is refused; with no connection, search and install fall back to keybars’ own items, which come with the app.
install applies a look, adds a pack’s rules at the top of your Notify rules, or saves a key map, and records what it changed. remove undoes exactly that: a look puts back the settings you had (where you haven’t changed them since), a pack’s rules come out, a map goes back to the one before. Installing again replaces the version that’s there. An integration isn’t installed: show gives the link it installs from. list shows what’s installed.
A pack names keys by where they are (top-row, esc, r1c2-r1c5), so it fits your board whatever it is.
Sharing your own
keybars-pro market export look -name "Night bus" [-o night-bus.keybars]
keybars-pro market export pack -name "Deploy alerts" -rules a1,b2 -o deploy.keybars
keybars-pro market export map -name "Keychron Q1" [-keyboard name]
keybars-pro market login
keybars-pro market publish deploy.keybars
keybars-pro market logout
export makes a .keybars item from your settings: your look as it is, the rules you list (every rule without -rules; rules shows their IDs), or the map Find keys saved for this keyboard (or -keyboard’s). -id (made from the name otherwise), -version (1.0), -licence (an SPDX name such as MIT) and -description fill in the rest. A pack rule has one colour, so a rule that lights keys in several keeps its most used one; export says when, and when a key isn’t on your keyboard’s map. It prints the item, or writes it to -o’s file. The app’s Share buttons (beside Import, on Notify’s rules and on the keyboard in Devices) make the same files.
publish sends a file (or - for standard input) to the marketplace, where it’s checked and, if it passes, live under your name straight away. It needs login first, which asks for a token from the publish page (Publishing from the terminal) and keeps it in market-token beside the settings, readable only by you. KEYBARS_MARKET_TOKEN is used instead when it’s set. logout forgets the token; delete it on the publish page too if you’re done with it.
KEYBARS_MARKET points every market command at another marketplace, such as a local one while developing.
Settings
settings
keybars-pro settings get [key]
keybars-pro settings set key value
keybars-pro settings export > keybars.json
keybars-pro settings import keybars.json
Settings are named by their key in the settings file, dotted: equaliser.gain, focus.work. get prints one as JSON, or every setting with no key. set takes JSON where it parses, else text: set equaliser.gain 1.5, set equaliser.peaks false, set equaliser.colours '["#00ff00","#ff0000"]', set typing.look heatmap. A value out of range is refused, with the reason, and nothing changes. export prints the whole settings file; import reads one (or a keybars config) as the window’s Import does, and prints what it left out.
| Key | Means |
|---|---|
theme | system, light or dark |
palette | green, meter, ice, sunset, synthwave or ember |
surprise, matchKeyboard, startInTray | a new theme each launch; the bars in the theme’s colours; start in the tray |
equaliser.device | the audio source; empty for what the computer plays |
equaliser.lowHz, equaliser.highHz | the frequency range, 50 to 12000 by default |
equaliser.gain | higher reaches the top more often; 1.5 by default |
equaliser.colours, equaliser.brightness | the bars’ colours bottom to top, and brightness 0 to 100 |
equaliser.peaks, equaliser.peakColour, equaliser.peakHoldMs, equaliser.peakFall | peak dots: on, colour, how long they hold, how fast they fall |
equaliser.smoothing, equaliser.fps | 0 jumpy to 100 smooth; frames a second |
equaliser.symmetry | empty (mirror split boards), off, centre or edges |
equaliser.keyboard, equaliser.openrgb, equaliser.model, equaliser.height | which keyboard, OpenRGB’s address, the built-in map, how many rows the bars use |
equaliser.reserve, equaliser.idleMs | LEDs the bars leave alone; how long silence lasts before the layout comes back |
system.bars, system.colours | CPU cores on the bars; their colours |
system.cpu, system.memory, system.temperature | the alert limits, percent and °C, 0 for off |
focus.work, focus.break | minutes |
focus.homeRow, focus.quiet, focus.colour, focus.breakColour | dim all but the home row; only held rules during work; the timer’s colours |
typing.on, typing.look, typing.colours, typing.gauge, typing.target | Typing: on, ripple, afterglow or heatmap, its colours, the speed gauge, target words a minute |
Rules have their own command, rules.
theme
keybars-pro theme [palette] [-scheme system|light|dark]
On its own, prints the theme. With a palette, green, meter, ice, sunset, synthwave or ember, it colours the window, the tray icon, and the bars too with Match the keyboard on. -scheme sets light or dark.
colours
keybars-pro colours [colour,colour,...] [-of bars|cpu|typing]
The bars’ colours, bottom to top, by name or #rrggbb: keybars-pro colours green,amber,red. On its own it prints them. -of cpu sets System’s CPU bars and -of typing Typing’s colours instead. It’s a short way to settings set equaliser.colours.
reset
keybars-pro reset equaliser | system | focus | typing | appearance | all puts that part of the settings back to a fresh install’s. all keeps your rules and saved key maps.
Watching
watch
keybars-pro watch [-only events] [-format template]
Prints a JSON line each time something happens, until you stop it with Ctrl-C: the same news the window gets. Status bars, scripts and dashboards can follow along.
{"event":"notified","data":{"source":"cli","name":"build.failed","rules":["Escape red"],"at":"2026-10-17T14:02:11+11:00"}}
{"event":"focus","data":{"phase":"work","remaining":1122,"length":1500}}
| Event | When | Its data |
|---|---|---|
notified | an event reaches Notify | source, name, repo, branch, number, rules played, at |
focus | each second of a session | phase (work, break or empty), remaining and length in seconds |
typing | each second Typing is on | wpm, best, today |
paused | the On switch changes | true when off |
step | a startup step changes | id (keyboard, map, audio, mode), state, detail |
services | a service connects, drops or gets a delivery | the list services prints |
settings | settings are saved | every setting |
test | the test plays | running, elapsed, length, part |
-only focus,typing picks events. -format prints a Go template of each event’s data instead of the JSON, with mmss to show seconds as minutes and seconds.
keybars-pro watch -only focus -format '{{mmss .remaining}}' # 18:42
keybars-pro watch -only typing -format '{{.wpm}} wpm'
In a status bar
A waybar module showing the Focus timer:
"custom/focus": {
"exec": "keybars-pro watch -only focus -format '{{if .phase}}{{.phase}} {{mmss .remaining}}{{end}}'",
"on-click": "keybars-pro focus start",
"on-click-right": "keybars-pro focus stop"
}
In tmux, status-right can run a command; keybars-pro focus prints the time left each time it’s asked.
Shell completion
keybars-pro completion zsh > "${fpath[1]}/_keybars-pro" # zsh
source <(keybars-pro completion bash) # bash, in ~/.bashrc
keybars-pro completion fish > ~/.config/fish/completions/keybars-pro.fish
keybars-pro completion powershell | Out-String | Invoke-Expression # in your $PROFILE
It completes commands and their words: actions, key names, colours, effects, themes, agents and settings parts, and your rule names for clear and rules on, off, try and remove, asked of the running app.
Running the engine alone
keybars-pro engine runs the equaliser in the terminal with the app’s saved settings and without the app: -preview draws the bars in the terminal too, -test plays the 30-second test and exits. It’s for trying the engine out; with the app open, the two would fight over the keyboard.