---
title: Change keyboard shortcuts by asking AI
---

# Change keyboard shortcuts by asking AI

## What it is

Omniscio has ~80 keyboard shortcuts you can rebind in **Settings → Keyboard Shortcuts** — global ones like Ctrl+Q (open inbox), session-scoped ones like S (snooze) and P (pause), Gmail two-key chords like `G > I` (go to inbox), and diff-review keys like J/K (next/prev file). Every action carries a label, a description, a default binding list, and your override list. Instead of clicking through that settings page, you can tell an external AI — Claude Code in any project on your machine — "remove E as the close-panel hotkey" or "rebind snooze to Shift+S" and it will do it for you. The AI uses the [`omniscio-control`](/.claude/skills/omniscio-control/SKILL.md) skill bundle (keybindings surface — [keybindings.md](/.claude/skills/omniscio-control/keybindings.md)), which reads the auto-delivered token from `~/.amc/cli-token` and PATCHes Omniscio's local control server at `127.0.0.1:19519`. Changes apply **immediately** to live sessions — no restart, no approval gate. Conflicts (two actions sharing a binding inside the same context) are reported back so the AI can ask before clobbering.

## Where to find it

The shortcuts themselves are listed and edited in **Settings → Keyboard Shortcuts**, which stays the reference for what exists and what is currently bound. The AI route edits the same data and needs switching on once, in **Settings → CLI Control** — after that, a Claude Code session on your machine can read and rebind shortcuts for you with the settings page never opened. Nothing appears in the sidebar or on a panel for this: the whole interface is the conversation you are already having.

## How it behaves

### How to use it

1. **Enable CLI Control once.** Open Omniscio → Settings → **CLI Control** and flip it on. Omniscio starts its local control server and writes your auth token to `~/.amc/cli-token` (on Windows, `%USERPROFILE%\.amc\cli-token`). The file is permission-hardened (`0o600` on Unix, an ACL grant to your user on Windows) and deleted when you disable CLI Control or quit Omniscio.
2. **Ask an AI in plain English.** In any Claude Code session say something like:
   - "Remove E as the archive hotkey in Omniscio"
   - "Rebind snooze to Shift+S"
   - "Reset my close-panel shortcut to defaults"
   - "What's currently bound to Ctrl+Q?"
   - "List every Gmail shortcut"

   The `omniscio-control` skill bundle auto-activates on phrases like _rebind_, _change shortcut_, _change hotkey_, _reset shortcut_, or _what is bound to_ (one of many surfaces it covers — see [omniscio-control.md](omniscio-control.md)).

3. **Let the skill find the right action.** Action IDs are camelCase strings like `closePanel`, `snoozeSession`, `gmailArchive`, `diffNextFile`, `jumpToProject1`. The AI either knows them already or calls `GET /keybindings` to discover them — every endpoint, including reads, requires the bearer token. It will tell you the action label and current bindings before changing anything.
4. **Watch for conflicts.** The list response includes a `conflicts` array — each entry names two actions in the same context that share a binding. The AI surfaces these and asks before overwriting.
5. **Changes apply instantly.** As soon as the PATCH/PUT/DELETE succeeds, the renderer's keybindings store re-resolves bindings on the `SETTINGS_CHANGED` push event, and live sessions pick up the new shortcut without a restart.

**Rate limit**: keybinding mutations share the same **10/min** ceiling as cron and automation mutations. The skill surfaces this if you hit it.

**No approval gate**: unlike cron jobs and automation rules (which land as `pending` until you click Approve), keybinding changes apply immediately. Personal preferences don't carry the same blast radius as scheduled command execution, so the user-in-the-loop step is dropped.

## For agents

### Endpoints

All endpoints require `Authorization: Bearer <token>` from `~/.amc/cli-token`. Mutations (PUT/PATCH/DELETE) count against the 10/min rate limit.

All responses use the standard `{ ok: true, data: <result> }` envelope; the `data` shapes shown below are what's returned inside that envelope (the GET example further down shows the full envelope on the wire).

| Method | Path                     | Purpose                                                                          |
| ------ | ------------------------ | -------------------------------------------------------------------------------- |
| GET    | `/keybindings`           | `data: { actions: ShortcutActionView[], conflicts: Conflict[] }`                 |
| GET    | `/keybindings/:actionId` | `data: ShortcutActionView` (404 on unknown id)                                   |
| PUT    | `/keybindings/:actionId` | Replaces the entire binding list for that action — body `{ bindings: string[] }` |
| PATCH  | `/keybindings/:actionId` | Surgical add/remove — body `{ add?: string[], remove?: string[] }`               |
| DELETE | `/keybindings/:actionId` | Drops the user override → action reverts to its default bindings                 |

`ShortcutActionView` shape: `{ id, label, description, category, defaultBindings, currentBindings, isCustomized }`. `category` is one of `global | navigation | session | gmail | diff-review`.

### Validation rules (server-side)

Every binding string is validated. Invalid strings → 400 with a human-readable message:

- **Length**: ≤ 50 characters
- **OS-reserved blocked**: `Alt+F4`, `Ctrl+R`, `Ctrl+Shift+I`, `F5`, `F11`, `F12` (and a few others) cannot be set — they would either fight the OS/browser or open devtools
- **No trailing modifier**: `Ctrl+` or `Ctrl+Shift+` alone (no key) is rejected
- **Chord form**: Gmail two-key sequences use the literal form `G > I` (uppercase letter, space, `>`, space, uppercase letter). Both sides must be a single key — modifiers in chord positions are rejected
- **Dedup on PUT**: Duplicate strings in the list are silently collapsed
- **Idempotent on DELETE/PATCH-remove**: Removing an already-absent binding is a no-op

### Concrete examples

**Find an action by guessing its ID:**

```bash
curl -H "Authorization: Bearer $(cat ~/.amc/cli-token)" \
  http://127.0.0.1:19519/keybindings/closePanel
```

```json
{
  "ok": true,
  "data": {
    "id": "closePanel",
    "label": "Close panel",
    "description": "...",
    "category": "global",
    "defaultBindings": ["Ctrl+W", "E"],
    "currentBindings": ["Ctrl+W", "E"],
    "isCustomized": false
  }
}
```

**Surgical: remove E from closePanel (keep Ctrl+W):**

```bash
curl -X PATCH \
  -H "Authorization: Bearer $(cat ~/.amc/cli-token)" \
  -H "Content-Type: application/json" \
  -d '{"remove":["E"]}' \
  http://127.0.0.1:19519/keybindings/closePanel
```

**Full replace: bind snooze to ONLY Shift+S:**

```bash
curl -X PUT \
  -H "Authorization: Bearer $(cat ~/.amc/cli-token)" \
  -H "Content-Type: application/json" \
  -d '{"bindings":["Shift+S"]}' \
  http://127.0.0.1:19519/keybindings/snoozeSession
```

**Reset to defaults (drop the override entirely):**

```bash
curl -X DELETE \
  -H "Authorization: Bearer $(cat ~/.amc/cli-token)" \
  http://127.0.0.1:19519/keybindings/closePanel
```

### How it works

The action catalog and validation utilities live in [/src/shared/keybindings.ts](/src/shared/keybindings.ts) — a single `SHORTCUT_ACTIONS` array drives both the Settings UI and the CLI endpoints. `getAllActionsWithBindings(userBindings)`, `getActionView(id, userBindings)`, `validateBindingString(s)`, `isOsReservedBinding(s)`, and `detectConflicts(resolved)` are the pure functions the routes call. Conflicts are computed against the **resolved** binding list (override OR default), not just overrides, so the response reflects what the user actually has.

The CLI endpoints are registered in [/src/main/services/cli/cli-server.ts](/src/main/services/cli/cli-server.ts) inside `registerKeybindingsRoutes()`, called once during startup from [/src/main/index.ts](/src/main/index.ts) right after the project routes register. Each route does: bearer-token auth → rate-limit check (mutations only) → `isShortcutActionId` lookup → Zod parse (`keybindingPutSchema` or `keybindingPatchSchema` from [/src/shared/ipc-schemas.ts](/src/shared/ipc-schemas.ts)) → trim+`validateBindingString` each entry → dedupe → `updateSettings({ keybindings })` → `emitPush(IPC.SETTINGS_CHANGED, { keybindings })` → `trackEvent('cli_control', 'hit', ...)`. PATCH applies remove first then add, preserving order. DELETE is just `delete userBindings[id]` and re-persists.

The renderer side already watches `SETTINGS_CHANGED` — [/src/renderer/src/stores/keybindings-store.ts](/src/renderer/src/stores/keybindings-store.ts) re-runs `resolveBindings` and broadcasts the new map to every consumer, so live sessions, the Settings UI, and any open hotkey overlay all reflect the change in the same paint frame as a renderer-initiated edit. The Settings UI itself is [/src/renderer/src/features/settings/sections/keybindings/KeybindingsSettings.tsx](/src/renderer/src/features/settings/sections/keybindings/KeybindingsSettings.tsx) — it edits the same `settings.keybindings` shape via the regular `onSettingChange` path, so the CLI and the UI cannot drift.

The skill bundle external AIs use is [/.claude/skills/omniscio-control/SKILL.md](/.claude/skills/omniscio-control/SKILL.md) with the keybindings-specific reference at [/.claude/skills/omniscio-control/keybindings.md](/.claude/skills/omniscio-control/keybindings.md) — together they document the trigger phrases, the endpoint table, the validation rules, and a worked example. Token reading falls back from `~/.amc/cli-token` to `$AMC_CLI_TOKEN`, identical to the cron and automation flows in the same bundle.

## Related

What every shortcut does by default, and the context each one applies in, is listed on the [Keyboard shortcuts](keyboard-shortcuts.md) page. If you want to see which of them you actually use — worth knowing before removing a binding — see [Hotkey usage](hotkey-usage.md), and [Hotkey training mode](hotkey-training-mode.md) covers learning the bindings in the first place.

- [cli-control.md](cli-control.md) — the parent CLI Control feature (server, token, read-only endpoints)
- [create-cron-job-with-ai.md](create-cron-job-with-ai.md) — a sister skill with the same auth pattern but approval-gated
- [use-skills.md](use-skills.md) — how skills work in general
