# Custom Keybindings

> Customize CodeBuddy Code keyboard shortcuts through the keybindings configuration file.

CodeBuddy Code supports custom keyboard shortcuts. Run the `/keybindings` command to create or open the configuration file located at `~/.codebuddy/keybindings.json`.


## Contexts

Each binding block specifies a **context** that determines when the shortcuts are active:

| Context | Description |
| :--- | :--- |
| `Global` | Active anywhere in the application |
| `Chat` | When the chat input box has focus |
| `InputBox` | When a text input box is active |
| `Terminal` | When the terminal view is active |
| `Autocomplete` | When the autocomplete menu is displayed |
| `Confirmation` | When a confirmation/permission dialog is displayed |
| `HistorySearch` | When searching command history (Ctrl+R) |
| `Task` | When a task/agent is running in the foreground |
| `Settings` | When the settings panel is open |
| `CommandPalette` | When the command palette is open |
| `Select` | When a select/list component has focus |
| `PermissionDialog` | When a tool permission dialog is displayed |
| `Help` | When the help page is open |
| `Plugin` | When the plugin dialog is open |
| `DiffDialog` | When the diff dialog is open |
| `MessageSelector` | When the message selector (rewind) is open |

---

## Available Actions

Actions follow the `namespace:action` format, such as `chat:submit` to send a message or `app:toggleTodos` to toggle the todo list. Each context has specific available actions.

### App Actions

Available in the `Global` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `app:interrupt` | Ctrl+C | Interrupt the current operation |
| `app:exit` | Ctrl+D | Exit CodeBuddy Code |
| `app:redraw` | Ctrl+L | Refresh the terminal screen |
| `app:toggleTodos` | Ctrl+T | Toggle the todo list |
| `app:toggleTranscript` | Ctrl+O | Toggle verbose transcript |
| `app:toggleSidebar` | Cmd+B | Toggle sidebar (Web UI) |
| `app:toggleTerminal` | Cmd+J | Toggle terminal (Web UI) |
| `app:commandPalette` | Cmd+Shift+P / Ctrl+Shift+P | Open command palette (Web UI) |
| `app:newChat` | Cmd+N | New conversation (Web UI) |
| `app:settings` | Cmd+, | Open settings (Web UI) |
| `app:focusInput` | Cmd+L | Focus input box (Web UI) |

### History Actions

For navigating command history:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `history:search` | Ctrl+R | Open history search |
| `history:previous` | Up | Previous history entry |
| `history:next` | Down | Next history entry |

### Chat Actions

Available in the `Chat` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `chat:cancel` | Escape | Cancel current input, or interrupt the current foreground request |
| `chat:submit` | Enter | Send message |
| `chat:killAgents` | Ctrl+X Ctrl+K | Kill all background agents |
| `chat:cycleMode` | Shift+Tab* | Cycle permission mode |
| `chat:modelPicker` | Meta+P | Open model picker |
| `chat:thinkingToggle` | Meta+T | Toggle extended thinking |
| `chat:undo` | Ctrl+_, Ctrl+Shift+- | Undo |
| `chat:externalEditor` | Ctrl+G, Ctrl+X Ctrl+E | Open in external editor |
| `chat:stash` | Ctrl+S | Stash current input |
| `chat:imagePaste` | Ctrl+V (Windows: Alt+V) | Paste image |

\*On Windows without VT mode (Node <24.2.0/<22.17.0, Bun <1.2.23), defaults to Meta+M.

### Autocomplete Actions

Available in the `Autocomplete` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `autocomplete:accept` | Tab | Accept suggestion |
| `autocomplete:dismiss` | Escape | Dismiss menu |
| `autocomplete:previous` | Up | Previous item |
| `autocomplete:next` | Down | Next item |

### Confirmation Actions

Available in the `Confirmation` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `confirm:yes` | Y, Enter | Confirm |
| `confirm:no` | N, Escape | Cancel |
| `confirm:previous` | Up | Previous item |
| `confirm:next` | Down | Next item |
| `confirm:toggle` | Space | Toggle selection |
| `confirm:toggleExplanation` | Ctrl+E | Toggle permission explanation |
| `permission:toggleDebug` | Ctrl+D | Toggle permission debug info |

### Transcript Actions

Available in the `Transcript` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `transcript:toggleShowAll` | Ctrl+E | Toggle show all content |
| `transcript:exit` | Q, Ctrl+C, Escape | Exit transcript view |

### History Search Actions

Available in the `HistorySearch` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `historySearch:next` | Ctrl+R | Next match |
| `historySearch:accept` | Escape, Tab | Accept selection |
| `historySearch:cancel` | Ctrl+C | Cancel search |
| `historySearch:execute` | Enter | Execute selected command |

### Task Actions

Available in the `Task` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `task:background` | Ctrl+B | Send current task to background |

### Help Actions

Available in the `Help` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `help:dismiss` | Escape | Dismiss help menu |

### Settings Actions

Available in the `Settings` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `settings:search` | / | Enter search mode |
| `settings:close` | Enter | Save and close settings panel |

### Select List Actions

Available in the `Select` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `select:next` | Down, J, Ctrl+N | Next item |
| `select:previous` | Up, K, Ctrl+P | Previous item |
| `select:accept` | Enter | Confirm selection |
| `select:cancel` | Escape | Cancel selection |

### Command Palette Actions

Available in the `CommandPalette` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `commandPalette:previous` | Up | Previous item |
| `commandPalette:next` | Down | Next item |
| `commandPalette:execute` | Enter | Execute command |
| `commandPalette:close` | Escape | Close palette |

### Diff Actions

Available in the `DiffDialog` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `diff:dismiss` | Escape | Dismiss diff viewer |
| `diff:previousFile` | Up | Previous file |
| `diff:nextFile` | Down | Next file |
| `diff:viewDetails` | Enter | View details |

### Message Selector Actions

Available in the `MessageSelector` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `messageSelector:up` | Up, K, Ctrl+P | Move up |
| `messageSelector:down` | Down, J, Ctrl+N | Move down |
| `messageSelector:top` | Shift+Up | Jump to top |
| `messageSelector:bottom` | Shift+Down | Jump to bottom |
| `messageSelector:select` | Enter | Select message |

### Plugin Actions

Available in the `Plugin` context:

| Action | Default Key | Description |
| :--- | :--- | :--- |
| `plugin:toggle` | Space | Toggle plugin selection |
| `plugin:install` | I | Install selected plugin |

---

## Key Syntax

### Modifiers

Combine modifiers using the `+` separator:

- `ctrl` or `control` — Control key
- `alt`, `opt`, or `option` — Alt/Option key
- `shift` — Shift key
- `meta`, `cmd`, or `command` — Meta/Command key

Examples:

```
ctrl+k          Single modifier + key
shift+tab       Shift + Tab
meta+p          Command/Meta + P
ctrl+shift+c    Multiple modifiers
```

### Chords

Chords are consecutive key combinations separated by spaces:

```
ctrl+x ctrl+k   Press Ctrl+X, release, then press Ctrl+K
ctrl+x ctrl+e   Press Ctrl+X, release, then press Ctrl+E
```

Chords have a 1000ms timeout. If the second step is not completed before the timeout, the chord is cancelled.

### Special Keys

- `escape` or `esc` — Escape key
- `enter` or `return` — Enter key
- `tab` — Tab key
- `space` — Space key
- `up`, `down`, `left`, `right` — Arrow keys
- `backspace`, `delete` — Delete keys

---

## Unbinding Default Shortcuts

Set an action to `null` to unbind a default shortcut:

```json
{
  "bindings": [
    {
      "context": "Chat",
      "bindings": {
        "ctrl+s": null
      }
    }
  ]
}
```

After unbinding all chord combinations, the prefix key can be used as a single-key binding:

```json
{
  "bindings": [
    {
      "context": "Chat",
      "bindings": {
        "ctrl+x ctrl+k": null,
        "ctrl+x ctrl+e": null,
        "ctrl+x": "chat:newline"
      }
    }
  ]
}
```

If only some chord sequences are unbound, pressing the prefix key will still enter chord waiting mode.

---

## Reserved Shortcuts

The following shortcuts cannot be rebound:

| Shortcut | Reason |
| :--- | :--- |
| Ctrl+C | Hard-coded interrupt/cancel |
| Ctrl+D | Hard-coded exit |
| Ctrl+M | Equivalent to Enter in terminals (both send CR) |

---

## Terminal Conflicts

Some shortcuts may conflict with terminal multiplexers:

| Shortcut | Conflict |
| :--- | :--- |
| Ctrl+B | tmux prefix key (press twice to send) |
| Ctrl+A | GNU screen prefix key |
| Ctrl+Z | Unix process suspend (SIGTSTP) |

---

## Web UI Visual Configuration

In addition to editing the JSON file, you can manage shortcuts through the visual interface in the Web UI:

1. Click **Keybindings** in the sidebar navigation, or use the URL `#/keybindings`
2. Use the search box to filter shortcuts by name, key, or context
3. Click the edit button (pencil icon) to record a new shortcut combination
4. The recording dialog shows real-time conflict detection
5. User-customized bindings are marked with a highlighted left border
6. Click the reset button to restore individual bindings to their defaults

### REST API

The Web UI manages shortcuts through the REST API:

| Endpoint | Method | Description |
| :--- | :--- | :--- |
| `/api/v1/keybindings` | GET | Get all shortcuts (default + user + merged) |
| `/api/v1/keybindings` | PUT | Save user shortcut configuration |
| `/api/v1/keybindings/reset` | POST | Reset to defaults (delete user configuration) |
| `/api/v1/keybindings/validate` | POST | Validate configuration (without saving) |

---

## Validation

CodeBuddy Code validates your keybinding configuration and displays warnings for the following:

- Parse errors (invalid JSON or structure)
- Invalid context names
- Reserved shortcut conflicts
- Terminal multiplexer conflicts
- Duplicate bindings within the same context
