Skip to content

Getting Started

Terminal window
npm install @hotter-keys/core
import { createHotkeys } from "@hotter-keys/core";
const hk = createHotkeys();
// Single shortcut
hk.add("ctrl+k", () => {
console.log("Command palette!");
});
// Multi-chord sequence
hk.add("ctrl+k ctrl+c", () => {
console.log("Comment block!");
});
// Clean up when done
hk.destroy();
const hk = createHotkeys();
hk.onHeldKeysChange((keys) => {
console.log("Currently held:", keys);
});
hk.onKeyHold("shift", (held) => {
console.log("Shift held alone:", held);
});

Useful for building “press a key to rebind” UIs:

import { recordShortcut, formatShortcut } from "@hotter-keys/core";
const result = await recordShortcut();
if (result.safe) {
console.log("Recorded:", formatShortcut(result));
} else {
console.warn("Unsafe shortcut:", result.unsafeReason);
}

Based on this analysis of why existing keyboard shortcut libraries are broken:

  1. Match on key, never code/keyCode/which — these are layout-dependent and unreliable.
  2. Only a-z and 0-9 are safe — symbol keys change across keyboard layouts.
  3. Shift is only allowed with a-zShift+2 produces different symbols per locale.
  4. Alt/Option is allowed as an explicit modifier — macOS transforms the character when Alt/Option is pressed (e.g. Alt+cç), so the mod2 virtual keyword resolves to Ctrl on macOS and Alt on Windows/Linux, providing a safe cross-platform secondary modifier.
  5. Progressive enhancement — uses the Keyboard API (Chrome) when available for broader support.

hotter-keys provides two virtual modifier keywords that resolve differently per platform:

KeywordmacOSWindows/LinuxRole
modCmd (⌘)CtrlPrimary modifier
mod2Ctrl (⌃)AltSecondary modifier
// Primary modifier — Cmd on macOS, Ctrl elsewhere
hk.add("mod+s", () => save());
// Secondary modifier — Ctrl on macOS, Alt elsewhere
hk.add("mod2+k", () => togglePanel());
// Both together — Cmd+Ctrl on macOS, Ctrl+Alt elsewhere
hk.add("mod+mod2+p", () => openSettings());

You can also use alt or option directly for explicit Alt bindings, but note that on macOS these will only work if the browser reports the untransformed key value.