> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rebind.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# rb.bind

> Bind a key, chord, or mouse button to a function, a toggle, or another key.

`rb.bind` hands a key, chord, mouse button or wheel step to the script. A script
reaches for it to run a function on a hotkey, to flip a setting with [`rb.bind.toggle`](#rb-bind-toggle), or to
make one key act as another with [`rb.bind.remap`](#rb-bind-remap).

This script logs F11 and lets it through, logs an Alt click and takes it, sends
Ctrl+C for A on the device nicknamed `lenovo_kb`, and turns Mouse4 into Ctrl+V:

```luau theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
-- rebind: min_sdk=3.9.0 name=example version=1.0.0
rb.bind("F11", function()
  rb.log.info("F11 pressed")
end, { swallow = false })

rb.bind("Mouse1", function()
  rb.log.info("Alt click")
end, {
  when = function()
    return rb.input.is_down("LAlt")
  end,
})

rb.bind("A", function() rb.hid.combo("LCtrl+C") end, { device = "lenovo_kb" })
rb.bind.remap("Mouse4", "LCtrl+V")
```

`rb.bind(key: string, fn: ((device: InputDevice?) -> ...any)?, options: RbBindOptions?) -> BindHandle`

Runs `fn` when `key` is pressed and takes the key: the computer never sees the
press or its release. Rebind intercepts only bound keys, so other keys stay real
hardware events and the script takes no exclusive capture.

| Option | Type | Effect |
| - | - | - |
| `swallow` | boolean? | `false` lets the key through as well. Default: the key is taken |
| `when` | `(device) -> boolean` | checked on each press; `false` skips the bind for that press |
| `release` | `(device) -> ()` | runs when the key is released; it receives no duration, so to time a press see [`rb.input`](https://docs.rebind.gg/reference/sdk/input) |
| `device` | string? | a nickname or id; the bind answers only to that [device](https://docs.rebind.gg/reference/sdk/events.md#devices) |

The callback's return value is ignored; `swallow` alone decides. `fn` may be
`nil`, which takes the key and does nothing else. `fn`, `when` and `release`
receive the device as their argument, or nothing when it is unknown.

**Chords.** `"LCtrl+M"` triggers on M while LCtrl is held. `Ctrl`, `Shift`,
`Alt` and `Win` accept either side; `LCtrl` and the other sided names require
that side. Extra held modifiers still match. A modifier name Rebind does not know
raises ``Bind(): `<name>` in `<trigger>` is not a modifier`` followed by the accepted names.

**Wheel.** `"WheelUp"` and `"WheelDown"` trigger on one step of the mouse wheel,
alone or in a chord such as `"LShift+WheelUp"`; `WheelUp` is a positive
[`scroll`](https://docs.rebind.gg/reference/sdk/events#input-events) delta. The bind runs once for each wheel event Rebind
receives and `release` runs right after it: a wheel step has no hold, so
`rb.bind.remap("WheelUp", "X")` presses and releases X. A step the bind takes
does not scroll, unless the bind sets `swallow = false`. On macOS a continuous
scroll (a trackpad, a Magic Mouse, momentum) is not a wheel step and never
triggers these binds.

**Order.** Binds on a key are tried with the most specific chord first, then
binds with a `device` before plain binds, then in the order they were created. A press that `when` rejects falls through to the
next bind, then to `down` handlers. A bind with `swallow = false` runs and the
press continues to the binds and handlers after it. A bind releases the key only
on the release of a press it took.

**Per device.** A bind with `device` ignores input from other devices and from
sources that cannot tell devices apart. In Windows and macOS software mode it
never fires, yet its key is still intercepted and re-emitted. A plain bind on the
same key is the fallback for every other device (see **Order**). Two keyboards
can hold the same key at once: each device bind runs `release` on the release
from its own device.

**Pinned keys.** A user can restrict an [`rb.ui.keybind`](https://docs.rebind.gg/reference/sdk/ui) setting to the
device that pressed it. The saved value is then `"<key>@<device id>"`, for
example `"PadA@dev_0123456789abcdef"`, and `rb.bind`, `rb.bind.toggle` and
`rb.bind.remap` read the suffix as the `device` filter, so
`rb.bind(cfg.jump, fn)` needs no `device` option. An explicit `device` option
replaces the pin. The id is the stable `id` of the [device](https://docs.rebind.gg/reference/sdk/events.md#devices); a pinned
device that is not connected never fires the bind. Any other use of `@` in a key raises
`` Bind(): `<trigger>` has an `@` that is not `<key>@<device id>` ``. Code that
compares or sends `cfg.key` itself, such as `rb.input.is_down(cfg.key)`, sees the
suffix; pass the setting to `rb.bind` instead.

The key string is read when `rb.bind` runs. Binding `cfg.hotkey` from an
[`rb.ui.keybind`](https://docs.rebind.gg/reference/sdk/ui) uses the saved value at load; a change in the panel restarts a
script loaded from a file, which then binds the new key.

Errors: a non-function callback, `when` or `release` raises
`rb.bind: the callback must be a function` (or names `when` or `release`).

Every call on this page returns a [BindHandle](https://docs.rebind.gg/reference/sdk/handles.md) that
stops, disables or enables the bind.

## rb.bind.toggle

`rb.bind.toggle(key: string, ui_id: string) -> BindHandle`

Takes the key and flips the boolean UI value `ui_id` on each press. A
pinned key (see **Pinned keys**) flips it only for that device.

## rb.bind.remap

`rb.bind.remap(from: string, to: string) -> BindHandle`

Takes `from` and holds `to` for as long as `from` is held. `to` may be a chord
such as `"LCtrl+C"`. A remap or toggle answers to every device unless the key is
a pinned key (see **Pinned keys**); a pinned remap releases `to` on the release
from the device that pressed it, or on a release that carries no device, so `to`
is never left held.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.