Change keyboard shortcuts by asking AI
Any Claude Code session on your machine can read and rebind Omniscio's keyboard shortcuts in plain English once CLI Control is enabled — no clicking through Settings, and the change takes effect immediately with no approval step. Covers the phrasings that trigger it, the validation rules a binding must pass, and the conflict report.
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 skill bundle (keybindings surface — 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
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 (0o600on Unix, an ACL grant to your user on Windows) and deleted when you disable CLI Control or quit Omniscio.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-controlskill 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).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 callsGET /keybindingsto discover them — every endpoint, including reads, requires the bearer token. It will tell you the action label and current bindings before changing anything.Watch for conflicts. The list response includes a
conflictsarray — each entry names two actions in the same context that share a binding. The AI surfaces these and asks before overwriting.Changes apply instantly. As soon as the PATCH/PUT/DELETE succeeds, the renderer's keybindings store re-resolves bindings on the
SETTINGS_CHANGEDpush 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+orCtrl+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:
curl -H "Authorization: Bearer $(cat ~/.amc/cli-token)" \
http://127.0.0.1:19519/keybindings/closePanel
{
"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):
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:
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):
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 — 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 inside registerKeybindingsRoutes(), called once during startup from /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) → 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 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 — 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 with the keybindings-specific reference at /.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 page. If you want to see which of them you actually use — worth knowing before removing a binding — see Hotkey usage, and Hotkey training mode covers learning the bindings in the first place.
- cli-control.md — the parent CLI Control feature (server, token, read-only endpoints)
- create-cron-job-with-ai.md — a sister skill with the same auth pattern but approval-gated
- use-skills.md — how skills work in general
Last verified 2026-09-28