Keyboard shortcuts
Configure the live CompozyOS keymap, inspect effective bindings, and apply the Terminal preset.
CompozyOS keeps shortcut defaults in the daemon. The web app, Settings, and the keyboard reference all read the same effective keymap: daemon defaults plus your validated overrides.
Inspect the keymap
Use the Settings API when you need the typed contract:
curl http://localhost:2123/api/settings/window-managerThe response separates stored and effective state:
config.shortcuts: only stored overrides.effective_shortcuts: the complete map used by the shell now.aliases: workspace aliases keyed by command ID.commands: registry metadata used to group every bindable command by source.extension_defaults: extension-provided defaults, including dormant conflicts.
The CLI exposes the same discovery data under value:
compozy config get window_manager -o jsonConfigure a binding
Each action accepts one chord string or an array of chord strings. An empty string or array disables
the action. A chord uses modifier names followed by one browser KeyboardEvent.code.
[window_manager.shortcuts]
"window.focus.left" = ["control+ArrowLeft", "alt+KeyH"]
"window.tile.bottom" = ""Indexed action families accept range bindings. Array members may also be ranges:
[window_manager.shortcuts]
"desktop.switch" = ["control+Digit1..9", "meta+Digit1..9"]
"window.tab.jump" = "control+alt+Digit1..8"The daemon expands ranges before validation. A duplicate anywhere in the complete effective map rejects the whole update; no partial binding is stored.
Use config set with a JSON array for alternates:
compozy config set 'window_manager.shortcuts.window.focus.left' \
'["control+ArrowLeft","alt+KeyH"]'For workspace-scoped changes, use the command-palette verbs. They update the complete keymap atomically through the daemon:
compozy cmd-palette bind window.focus.left control+ArrowLeft --workspace acme
compozy cmd-palette unbind window.focus.left --workspace acme
compozy cmd-palette bindings --workspace acme -o jsonWhen a chord belongs to another command, the daemon names that owner and stores nothing. Add
--overwrite to transfer the chord from the named owner.
Configure a global hotkey
The desktop shell can register a global chord for each command from anywhere outside CompozyOS. The daemon owns the intended map under
[window_manager.global_shortcuts]; each desktop shell reports whether its chord is active, captured
by another application, blocked by permission, or unsupported.
compozy cmd-palette bind palette.summon.global meta+shift+Space --global
compozy cmd-palette unbind palette.summon.global --globalA plain browser cannot register these chords and shows requires desktop shell without changing the in-app keymap. Read Global hotkeys for registration states, Accessibility recovery, and platform behavior.
Configure an alias
Aliases are workspace vocabulary for command search. They contain 1–32 characters with no whitespace and are unique within the workspace.
compozy cmd-palette alias set session.new new --workspace acme
compozy cmd-palette alias clear session.new --workspace acmeUse --overwrite to transfer an alias already owned by another command. You can also declare
aliases in a workspace overlay:
[cmd_palette.aliases]
"session.new" = "new"Default keymap
meta renders as Command on Apple platforms. A single-primary meta chord maps to Control on other
platforms; an explicit control remains Control everywhere.
| Action | Default |
|---|---|
palette.open | ⌘K, ⌘⇧P |
palette.view.sessions | ⌘E |
session.new | ⌘N |
scope.global.toggle | ⌘⇧G |
window.nav.back | ⌘[ |
session.cycle.previous / session.cycle.next | ⌃⇧↑ / ⌃⇧↓ |
session.focus.attention | ⌃⌥A |
workspace.picker | ⌘⇧O |
workspace.cycle.previous / workspace.cycle.next | ⌘⇧[ / ⌘⇧] |
desktop.switch.1 … .9 | ⌃1 … ⌃9 |
desktop.create | ⌘⇧N |
desktop.overview | ⌘⇧D |
desktop.switch.previous / .next | ⌃⇧← / ⌃⇧→ |
sidebar.toggle | ⌘B |
window.focus.last | ⌃⌥O |
window.close / .minimize | ⌘W / ⌘M |
window.zoom / .toggle_floating | ⌃⌥Z / ⌃⌥F |
window.tile.left / .right | ⌃⌥← / ⌃⌥→ |
window.tile.top / .bottom | ⌃⌥↑ / ⌃⌥↓ |
window.tile.top-left / .top-right | ⌃⌥U / ⌃⌥I |
window.tile.bottom-left / .bottom-right | ⌃⌥J / ⌃⌥K |
window.tab.new | ⌘T |
window.tab.next / .previous | ⌃Tab / ⌃⇧Tab |
window.tab.last | ⌘9 |
window.tab.reopen | ⌘⇧T |
window.tab.jump.1 … .8 | ⌘1 … ⌘8 |
window.focus.left / .right | ⌃← / ⌃→ |
window.focus.up / .down | ⌃↑ / ⌃↓ |
layout.arrange.two-up / .grid | Unbound |
layout.balance | ⌃⌥B |
layout.undo / .redo | ⌘Z / ⌘⇧Z |
shortcuts.cheatsheet | ?, ⌘/ |
Press ? outside an editable field, or press ⌘/ anywhere, to open the live keyboard reference.
Escape remains a fixed close/focus-return key and is not part of the configurable map.
Terminal preset
Settings → Layouts → Shortcuts can preview and apply this preset as one atomic change. Revert restores
the values that those preset keys had immediately before apply. The same block can be pasted into
config.toml:
[window_manager.shortcuts]
"window.focus.left" = ["control+ArrowLeft", "alt+KeyH"]
"window.focus.down" = ["control+ArrowDown", "alt+KeyJ"]
"window.focus.up" = ["control+ArrowUp", "alt+KeyK"]
"window.focus.right" = ["control+ArrowRight", "alt+KeyL"]
"window.focus.last" = ["control+alt+KeyO", "alt+KeyO"]
"window.close" = ["meta+KeyW", "alt+KeyW"]
"window.zoom" = ["control+alt+KeyZ", "alt+KeyY"]
"window.tab.new" = ["meta+KeyT", "alt+KeyT"]
"window.tab.next" = ["control+Tab", "control+alt+KeyL"]
"window.tab.previous" = ["control+shift+Tab", "control+alt+KeyH"]
"window.tab.jump" = "control+alt+Digit1..8"
"window.tab.last" = "control+alt+Digit9"
"session.cycle.next" = ["control+shift+ArrowDown", "control+alt+KeyJ"]
"session.cycle.previous" = ["control+shift+ArrowUp", "control+alt+KeyK"]
"window.tile.bottom-left" = "control+alt+shift+KeyJ"
"window.tile.bottom-right" = "control+alt+shift+KeyK"
"session.focus.attention" = ["control+alt+KeyA", "alt+KeyI"]
"workspace.picker" = ["meta+shift+KeyO", "meta+control+KeyP"]
"workspace.cycle.next" = ["meta+shift+BracketRight", "meta+control+KeyJ"]
"workspace.cycle.previous" = ["meta+shift+BracketLeft", "meta+control+KeyK"]
"desktop.create" = ["meta+shift+KeyN", "meta+control+KeyN"]
"desktop.switch" = ["control+Digit1..9", "meta+Digit1..9"]The preset moves tab jumps to the Control+Option digit layer and moves the two bottom-corner tiles to Control+Option+Shift. That frees Command digits for desktops and Control+Option J/K for session cycling.
Platform notes
- Control+digit may switch browser tabs outside the desktop app on non-Apple platforms.
- Control+Option can alias AltGr on some keyboard layouts. Test the J/K layer before depending on it.
?depends on the current layout's Shift+Slash mapping. ⌘/ is the reliable alternative on non-US layouts.- A focused control keeps its own local shortcuts. The keyboard reference marks those rows read-only.