Turn any key or button into another key, a chord, a modifier hold, or a whole layer — the same job as AutoHotkey or Karabiner. The logic is identical on Windows, macOS, and Linux and works with any USB keyboard or mouse. Every recipe below runs unchanged in free software mode; add a Rebind Link for hardware output. The building blocks are small and the same throughout:
  • Bind.Remap(from, to) — a declarative one-line key-to-key remap.
  • OnDown(key) / OnUp(key) — return true to let a key pass through, false to swallow it. Send your replacement with HID.Down / HID.Up / HID.Press.
  • Input.IsDown(key) — test whether a physical key is currently held, which is how you build chords, modifier holds, and layers.
Press Left Ctrl + Left Alt + K at any time to stop every running script. (The kill switch uses the left-hand modifiers specifically — right Ctrl / right Alt don’t trigger it.)

Single-key remap

Bind.Remap takes the key you press and the key you want sent in its place — no hooks, no state. Caps Lock becomes Escape; your real Escape is untouched.
Bind.Remap returns a handle, so you can toggle a remap at runtime with :disable() and :enable(). Here a hotkey flips it live, and the handle reports its state through .enabled.
For conditions more nuanced than on/off — “only in this app,” “only while another key is held” — drop down to OnDown / OnUp and decide per event. The remaining recipes all use that form.

Chords and combos

A chord fires one action only when several keys are held together. Read the other keys with Input.IsDown at the moment the trigger key goes down, and swallow the trigger so it doesn’t type on its own.
Checking both orders makes the chord order-independent. For a combo that includes a real modifier, test it the same way — Input.IsDown("LCtrl") — and emit a keyboard combo with the + syntax:

Modifier hold

A modifier hold gives one key two jobs: tap it for its normal value, hold it to change what other keys do. Track when the key went down and whether another key was used while it was held. On release, if nothing else fired and the hold was short, send the tap.
usedAsMod prevents a stray Space when you genuinely used the hold, and TAP_MS keeps a long, lone hold from emitting a late Space. OnBlur clears the state if focus leaves while you’re mid-hold.

Hold-to-access layer

A layer is a modifier hold scaled up: hold one key to expose an alternate set of keys, release it to return to normal. Keep the mappings in a table so adding a key is a one-line edit.
Because the layer is gated on Input.IsDown(layerKey), every other key behaves normally the instant you let go. To make it app-aware — active only in one program — wrap the body in a System.Window() check:

Opposing-key resolution (last pressed wins)

For movement keys mapped to opposite directions — left and right, or up and down — holding both at once is ambiguous: the two presses cancel and you stop. One way to resolve it deterministically: when two opposing directions are held at once, the most recently pressed one is active. Release the newer key and the older one, still held, takes over again. Record the order in which each key of an opposing pair went down, then send only the winner and suppress its opposite.
The behavior is timing-driven: pressedAt stores when each key last went down, activeOf picks the larger timestamp, and refresh makes the live output match. Releasing the newer key calls refresh on the survivor so the older direction resumes with no extra tap. OnBlur releases both outputs if focus changes mid-hold, so a direction can never get stuck on.

Where each recipe runs

See Platforms for the full capability matrix.