---
title: Hotkey Training Mode (block the mouse to learn the keyboard)
---

# Hotkey Training Mode (block the mouse to learn the keyboard)

## What it is

Hotkey Training Mode is an **opt-in** mode that helps you build keyboard-shortcut
muscle memory by gently refusing the mouse. When it's on, the **first click** on a
button that _also_ has a keyboard shortcut is **blocked**, and a small **"Press
&lt;key&gt;"** bubble pops up at your cursor showing the shortcut to use instead.
If you're in a hurry, there's a **3-click soft escape hatch**, so you're never
truly stuck: the **second click** on the same control (within ~3 seconds) is still
blocked but pops a **"Click again to allow"** bubble, and the **third click** goes
through — with a small green **"Allowed ✓"** confirmation.

It's the forceful sibling of the lighter [Shortcut Efficiency](shortcut-efficiency.md)
nudges: the "Instant Whisper" only _suggests_ a key after you click; Training Mode
_blocks_ the click so you actually reach for the key.

It is **off by default**. Turn it on at **Settings → Sessions → "Hotkey training
mode."**

## Where to find it

It is opt-in and lives under Settings → Lab. Nothing changes until you turn it on, and turning it off restores ordinary clicking straight away.

## How it behaves

- **Only real left-clicks are blocked.** Right-click and middle-click pass through,
  and a button you activate with the keyboard (Enter/Space while it's focused) is
  never blocked — that's already keyboard use.
- **Keyboard shortcuts always work**, exactly as before. Training Mode only affects
  the mouse.
- **It takes three clicks to force it through.** The first click is blocked ("Press
  &lt;key&gt;"); an immediate second click on the _same_ control is **still blocked**
  and shows "Click again to allow"; the third click performs the action, with a green
  "Allowed ✓" confirmation. Each step is keyed to the same control within ~3 seconds of
  the previous click. (Click a _different_ control and it starts blocked from the
  first click — the escape hatch is per-control.)
- **Touch screens are exempt.** On a phone or tablet (any touch-only device with no
  hover-capable pointer) there's no keyboard to reach for, so nothing is ever
  blocked there.
- **You can always get out.** The Settings gear has no keyboard shortcut, so it's
  never blocked — you can always reach Settings to turn the mode back off.
- **A blocked click doesn't count as a "mouse use"** in the Shortcut Efficiency
  stats (the action didn't happen) — neither the first nor the second; only the
  third, successful click does.

### What it covers

Training Mode blocks every control that carries an internal "this triggers a
keyboard shortcut" marker. Today that's the high-traffic actions that have both a
button and a hotkey — for example: New Session, Archive / Snooze / Pause / File
Explorer / Aside / Tag (the session ⋯ menu), the composer Attach and Quick-Reply
buttons, the **AI suggestion chips** (Alt+1/2/3) and the **quick-replies button**
(Alt+S), the Continue / Keep-waiting banner buttons, the Plain Speak toggle, and
the toolbar Super Prompts / Scratchpad / Help / Get Help / New-alarm buttons.

Pure navigation keys are deliberately **not** trained — clicking a project or a
session in the sidebar isn't "the same action" as the Ctrl+number / Tab keys (each
click targets a _different_ item), so those clicks are never blocked. (The old
deferred list — the AI-suggestion chips and the quick-replies button — was closed
in the 2026-07-04 hotkey overhaul; both are covered now.)

**The Tasks board's own shortcuts are covered too.** The Tasks (v2) command buttons
that have a keyboard shortcut are trained the same way — Context, Cut, Paste, Move
up / down, Move to project, Break it down, Finish, and Insert link (the row ⋯ and
right-click menus), Launch agent and Waiting (on the row), Snooze and Priority (the
project header), and Find and the keyboard cheat-sheet (the header). Tasks' pure
direct-manipulation keys are **not** trained: moving the highlight, indent / outdent,
the fold triangle, select-all, the command line, and the due-date / estimate setters
(you set those from the details panel, not a one-click button).

**Supermail's shortcuts are covered too.** Supermail — the built-in email app — runs its
own Superhuman-style keyboard shortcuts, and Training Mode now trains those as well. Its
triage-bar buttons (Done, Snooze, Mark unread, Trash, Label, Spam, Reply, Forward) and its
compose formatting toolbar (bold / italic / underline / strikethrough / lists / quote /
link / indent / outdent) block on the first click and show Supermail's own key. Two things
are deliberately **not** trained: the triage Previous / Next buttons (their key changes
with the view — the reading pane uses different keys, so a fixed hint could be wrong) and
Follow-up / Create-task / Link-to-task (no keyboard shortcut). Everything else in Supermail
— the keyboard-only navigation, the command palette, filters — has no one-click button to
block, so it's untouched.

**What's NOT covered: marketplace webview plugins.** Plugins that run in their own embedded
window (Nighty Tidy 2, decks, and the rest) are sealed off from Omniscio's main window, and
none of them define keyboard shortcuts today — so there's nothing for Training Mode to block
there. Supermail is the exception only because it runs _inside_ Omniscio's own window rather
than a sealed plugin frame.

## For agents

### How it works (for agents)

- **The markers.** A control opts in by carrying a marker: `data-hotkey-action="<id>"`
  for a central shortcut (via `hotkeyActionAttr(id)`), `data-hotkey-tasksv2="<id>"` for a
  Tasks-v2 command (via `tasksV2HotkeyAttr(id)`) — both in
  [/src/renderer/src/lib/hotkey-action-attr.ts](/src/renderer/src/lib/hotkey-action-attr.ts) —
  or `data-hotkey-supermail="<keymap id>"` for a Supermail command (a RAW attribute spread
  on the vendored Supermail button, no AMC import). Toolbar/sidebar items get the central
  marker automatically from their `shortcutAction` field; other buttons spread a marker
  explicitly with a literal id.
- **The completeness guards (one per shortcut system).** Two build-time lint tests —
  [/tests/unit/lint/hotkey-action-marker-completeness.test.ts](/tests/unit/lint/hotkey-action-marker-completeness.test.ts)
  for central shortcuts and
  [/tests/unit/lint/hotkey-tasksv2-marker-completeness.test.ts](/tests/unit/lint/hotkey-tasksv2-marker-completeness.test.ts)
  for Tasks-v2 commands — force EVERY shortcut to be classified exactly once: either its
  control is marked, or it's listed (with a reason) in the matching allow-list
  (`HOTKEY_ACTIONS_WITHOUT_BUTTON` / `TASKSV2_COMMANDS_WITHOUT_BUTTON`). A new hotkey-backed
  button therefore can't silently escape the mode: forget to mark it and the build fails.
  Supermail (a vendored sub-app AMC can't fully enumerate) gets a **bounded** guard
  ([/tests/unit/lint/hotkey-supermail-marker-completeness.test.ts](/tests/unit/lint/hotkey-supermail-marker-completeness.test.ts)):
  it validates the trained command list against Supermail's live keymap and asserts the
  shared button components still carry the marker, so a Supermail re-vendor can't silently
  kill training.
- **The interceptor.** `useHotkeyTrainingInterceptor`
  ([/src/renderer/src/hooks/useHotkeyTrainingInterceptor.ts](/src/renderer/src/hooks/useHotkeyTrainingInterceptor.ts)),
  mounted once in `App.tsx`, runs a window-capture `click` listener (only when the
  setting is on). It matches any of the three markers: central + Tasks-v2 resolve the
  control's current (rebind-aware) key through the shared `appHotkeyBindingsForEl` (the same
  resolver the hover tooltips use); Supermail resolves against its own keymap via
  `supermailHotkeyKeyText`
  ([/src/renderer/src/features/supermail/supermail-hotkey-bindings.ts](/src/renderer/src/features/supermail/supermail-hotkey-bindings.ts)).
  It tracks a per-control block `count` within the escape-hatch
  window (`BLOCKS_BEFORE_ALLOW = 2`): the first two clicks block with
  `preventDefault()` + `stopPropagation()` (not `stopImmediatePropagation` — sibling
  capture listeners like the usage tracker must still fire), showing the hotkey-whisper
  layer's `required` bubble ("Press &lt;key&gt;") then its `escalate` bubble ("Click
  again to allow"); the third click is allowed through and shows the green `allowed`
  confirmation bubble.
- **The setting.** `hotkeyTrainingMode` (default `false`) in `ChatUiSettings`
  ([/src/shared/types/settings/chat-ui-settings.ts](/src/shared/types/settings/chat-ui-settings.ts))
  - the matching Zod field.

The full set of test-locked invariants (completeness, the block/allow state
machine, the sibling-listener rule, the bubble copy, and the honest limits) lives
in the contract:
[/.claude/memory/contracts/hotkey-training-mode-contract.md](/.claude/memory/contracts/hotkey-training-mode-contract.md).

## Related

- [shortcut-efficiency.md](shortcut-efficiency.md) — the passive mouse-vs-keyboard
  stat + the lighter "Instant Whisper" nudge this mode escalates.
- [keyboard-shortcuts.md](keyboard-shortcuts.md) — the full list of Omniscio shortcuts
  and how to rebind them.
