Keybindings

Command Code works beautifully the moment you open it - every shortcut is set up the way most people expect. But your hands are your own. If you live in Emacs, or you reach for Vim motions without thinking, or you just prefer a different key for one thing, you can make Command Code match your muscle memory.

Shortcuts live in a single file, ~/.commandcode/keybindings.json. It's optional - create it only when you want to change something. Anything you don't mention keeps its default, so you're always adjusting, never starting from scratch.

Made an edit mid-session? Run /reload and your changes take effect right away - no need to close and reopen.

Note

Not sure what's currently bound? Run /hotkeys in a session to see every shortcut Command Code recognizes right now, including any of your own overrides.

Each shortcut is a modifier and a key, joined with a plus sign - ctrl+a, alt+left, shift+enter. You can stack modifiers (ctrl+shift+k), and the order never matters: ctrl+shift+k and shift+ctrl+k mean the same thing.

The three modifiers are Control (ctrl), Shift (shift), and Option (alt - you can also write option or meta, whichever feels natural on your keyboard).

For the key itself, use a letter (az), a number (09), a symbol, or one of the named keys: up, down, left, right, home, end, pageUp, pageDown, enter, escape, tab, space, backspace, delete, insert.

Give an action a single shortcut, or a list of them when more than one should work:

{ "app.tools.expand": "ctrl+t", "tui.editor.cursorUp": ["up", "ctrl+p"] }

Each action has a stable name - a short, dotted id you'll use in the file. Here's the full set, grouped by where they act.

Moving the cursor

ActionDefaultWhat it does
tui.editor.cursorLeftleftMove left one character
tui.editor.cursorRightrightMove right one character
tui.editor.cursorUpupMove up one line
tui.editor.cursorDowndownMove down one line
tui.editor.cursorWordLeftalt+left, ctrl+left, alt+bJump back a word
tui.editor.cursorWordRightalt+right, ctrl+right, alt+fJump forward a word
tui.editor.cursorLineStarthome, ctrl+aGo to the start of the line
tui.editor.cursorLineEndend, ctrl+eGo to the end of the line

Editing text

ActionDefaultWhat it does
tui.editor.deleteCharBackwardbackspaceDelete the character behind the cursor
tui.editor.deleteCharForwarddeleteDelete the character ahead of the cursor
tui.editor.deleteWordBackwardctrl+w, alt+backspaceDelete the word behind the cursor
tui.editor.deleteToLineStartctrl+uClear back to the start of the line
tui.editor.deleteToLineEndctrl+kClear forward to the end of the line

Composing a message

ActionDefaultWhat it does
tui.input.newLineshift+enter, ctrl+jAdd a line break instead of sending
tui.input.submitenterSend your message

Working with the session

ActionDefaultWhat it does
app.permission.cycleshift+tab, alt+mSwitch permission mode: default, auto-accept, then plan, cycling back to default. Launched with --yolo, bypass joins as a fourth rung (plan → bypass → default). (alt+m covers Windows terminals where Shift-Tab doesn't come through.)
app.tools.expandctrl+oShow or hide the full tool output
app.model.selectalt+pJump to the model picker (Option-P on a Mac)
app.todos.togglectrl+xOpen the session todo manager (the /todos overlay); press again to close
app.editor.externalctrl+gHand the prompt off to your editor ($EDITOR)
app.input.stashctrl+sSet the current prompt aside, then bring it back
app.interruptescapeStop what's running
app.clipboard.pasteImagectrl+vDrop in an image from the clipboard
Note

Remapping is live today for everything under Moving the cursor, for the word- and line-deletion actions, and for app.permission.cycle, app.tools.expand, app.model.select, and app.todos.toggle. The other actions are listed so you can see the whole picture - Command Code still honors their default keys, and custom bindings for them are on the way. Plain backspace stays put on purpose, so terminals that report Backspace as a "delete" key keep behaving correctly.

On a permission prompt

When Command Code stops and asks you to approve a tool call, press ctrl+e (ctrl+y in VS Code-family terminals, where the IDE intercepts ctrl+e) to get an on-demand, plain-language explanation of what the command will do before you decide. This shortcut is part of the permission prompt itself, not a keybindings.json action, so it isn't listed in the bindable table above and can't be remapped.

Prefer Emacs motions across the input line? Add its bindings alongside the defaults:

{ "tui.editor.cursorUp": ["up", "ctrl+p"], "tui.editor.cursorDown": ["down", "ctrl+n"], "tui.editor.cursorLeft": ["left", "ctrl+b"], "tui.editor.cursorRight": ["right", "ctrl+f"], "tui.editor.cursorWordLeft": ["alt+left", "alt+b"], "tui.editor.cursorWordRight": ["alt+right", "alt+f"], "tui.editor.cursorLineStart": ["home", "ctrl+a"], "tui.editor.cursorLineEnd": ["end", "ctrl+e"] }

Or lean on Vim's home-row motions with Option held down:

{ "tui.editor.cursorUp": ["up", "alt+k"], "tui.editor.cursorDown": ["down", "alt+j"], "tui.editor.cursorLeft": ["left", "alt+h"], "tui.editor.cursorRight": ["right", "alt+l"], "tui.editor.cursorWordLeft": ["alt+left", "alt+b"], "tui.editor.cursorWordRight": ["alt+right", "alt+w"] }

  • Nothing to break: If the file is missing, or a line has a typo, Command Code quietly falls back to the defaults and starts as usual. A single bad entry never takes the rest of your file down with it.
  • Coming from an older setup? Earlier configs used shorter names like cursorUp or expandTools. Command Code recognizes those and updates them to the dotted ids for you, automatically, on launch.
  • Want a key to do nothing? Set the action to an empty list ([]) to clear it.
  • Your terminal is covered: Home, End, and Option-Arrow arrive as different sequences across iTerm2, Terminal, Ghostty, Kitty, Alacritty, WezTerm, and VS Code - Command Code understands them all, matching the defaults above out of the box.
  • Check what's live. Run /hotkeys any time to see your effective bindings, including overrides from keybindings.json.