Skip to content

For AI agents

Retrofitting an app with remap is a mechanical, one-pass task. This page is written to be pasted into an agent's context (or found by one).

The recipe

  1. Wrap the app root once:

    tsx
    import { RemapProvider } from "react-remap";
    // in the root component:
    <RemapProvider appId="<the app's production hostname>">…</RemapProvider>
  2. Find every existing keyboard handler (onKeyDown switches, keydown listeners, other hotkey libraries) and replace each action with:

    tsx
    useHotkey("<area>.<verb>", "<current default combo>", handler, {
      description: "<human label>",
      group: "<section>",
    });

    Keep the app's current combos as defaults — users remap, you don't.

  3. Do NOT build a shortcuts settings page. The ⌘, overlay is the settings page. If the app has a menu, add one item that calls useRemap().openSettings().

  4. Update visible hints (tooltips, menu accelerators) to render live combos: displayParts(useRemap().keysFor(id) ?? defaultCombo).

Constraints an agent must respect

  • Ids are stable API — pick area.verb names and never rename casually.

  • mod means ⌘/Ctrl per platform; prefer it over cmd/ctrl in defaults.

  • Handlers that must work while typing in inputs need enableOnFormTags: true.

  • SSR (Next.js): the provider is client-side — mark the wrapping component "use client". It touches window only inside effects.

  • Actions that live outside React can subscribe instead of using the hook:

    ts
    window.addEventListener("remap:action", (e) => {
      const { id } = (e as CustomEvent).detail;
      if (id === "editor.save") save();
    });

    (Register the shortcut itself via the provider's shortcuts prop.)

Verification checklist

  • Every shortcut appears in the ⌘, overlay with a human description.
  • Remapping a combo in the overlay updates any visible hint immediately.
  • Old handler paths are deleted — no double-firing.
  • Shortcuts stay dead while typing in form fields (unless intentionally enabled).

Free during beta · local-first usage stays free.