Customize Shortcuts
Changing Daintree keyboard shortcuts: opening the editor, assigning and removing bindings, recording chords, what happens on a conflict, per-platform differences, unbound actions, and resetting to defaults.
Customizing shortcuts
Open Settings with Command-, Control-, Control-, and switch to the Keyboard tab. The panel carries a search field, Import and Export buttons, and Reset All; bindings are grouped by the same categories the reference dialog uses, each row showing its description and current combo as a pill.
- Record a combo: click a pill and press the keys. If the first keystroke could begin a chord, the recorder waits one second for a second keystroke before saving; press one and you get a chord, wait and you get the single combo. Alt-tabbing mid-capture cancels rather than saving a combo with unknowable modifier state.
- Unbind: clear the recorded combo without saving a new one, leaving the action reachable only from the palette and menus.
- Reset to default: appears on a customized row and snaps just that row back to the shipped binding.
- Reset All: confirms, then clears every override at once.
- Customized rows render in the accent color, so overrides are visible at a glance against the defaults.
Conflicts
The recorder checks a candidate combo against every registered binding in an overlapping scope and reports two distinct outcomes:
- Conflict — the same combo already belongs to another action. The conflicting action is listed with an inline Unbind button; clicking it frees the combo and raises a five-second toast carrying an Undo.
- Shadowed — a chord-prefix overlap, such as binding Command-K Control-K Control-K on its own while chords start with it. Unbinding cannot resolve this, because neither combo equals the other, so Daintree names the relationship in the direction it applies (this shadows that, or is shadowed by it) and leaves the decision to you.
Scope matters here: a global candidate is checked against both global and scoped bindings, while a scoped one only clashes within its own scope and the global set. That is why the portal can keep Command-T Control-T Control-T for a new tab without disturbing duplicate-panel everywhere else.
Scopes and priority
Every binding carries a scope and a priority, and resolution takes the highest-priority match whose scope is active.
| Scope | Active when |
|---|---|
global | Always. |
portal | The portal browser has focus. |
dev-preview | A dev preview panel has focus. |
worktreeGrid | Focus is in the worktree grid and outside a terminal — what makes the bare X X X arm toggle safe. |
| Priority | Source |
|---|---|
| 0 | Shipped default |
| 1 | Plugin contribution |
| 5 | Elevated default — a binding that must beat an ordinary one, such as the fleet broadcasts and region focus |
| 10 | Override — yours, or a default that must win outright |
Plugins can contribute keybindings at priority 1, so a plugin can claim a free combo but never quietly outrank one of your rebinds. Plugin bindings may also carry a when clause evaluated against live context — whether a terminal is focused, a modal or palette is open, the fleet is armed or has a waiting agent, and whether the sidebar is visible.
Shortcut profiles
Export writes a JSON file containing only your overrides, not the full default table, so profiles stay small and survive version changes. Import merges a file's overrides onto your current configuration rather than replacing it.
{
"schemaVersion": 1,
"exportedAt": "2026-08-18T12:00:00.000Z",
"app": "daintree",
"overrides": {
"terminal.new": ["Cmd+Alt+T"],
"git.stageAll": ["Cmd+K Cmd+G"]
}
} On import Daintree checks the file size (100 KB maximum), rejects a mismatched schemaVersion outright, and validates the shape before applying anything. Action ids that no longer exist are dropped rather than failing the import, so a profile stays usable across releases. A binding whose default moved to a successor action carries your override with it, so a rename does not silently strand a rebind.