All posts
·Rebind

Rebind Script Examples: From Beginner to Advanced

A collection of ready-to-use Rebind Luau scripts — key remaps, text expansion, mouse precision, auto-clicker, per-app shortcuts, Twitch integration, and more. Copy and run.

rebind scriptrebind lualua macrohardware macrosexamples

These are complete scripts you can paste directly into the Rebind UI. Each one demonstrates a different part of the SDK. Start with the ones that match your immediate need, then read the ones beyond your current use case to understand what's possible.

All scripts are written in Luau (a typed variant of Lua) and run on dedicated USB hardware. The output reaches your PC as standard keyboard and mouse input.


Beginner

Log every input event

The best first script. Doesn't modify anything — just shows you what key names Rebind uses for every input event.

-- rebind: name=Input Logger

function OnDown(key)
    Log.Info("DOWN: " .. key)
    return true
end

function OnUp(key, duration)
    Log.Info("UP: " .. key .. " (held " .. duration .. "ms)")
    return true
end

function OnScroll(delta)
    Log.Info("SCROLL: " .. delta)
    return true
end

Open the Logs tab in the Rebind UI and press keys. You'll see exactly what string names to use in your own scripts.


Remap CapsLock to Escape

The classic Vim remap. Block CapsLock entirely and send Escape instead.

-- rebind: name=CapsLock to Escape

function OnDown(key)
    if key == "CapsLock" then
        HID.Press("Escape")
        return false
    end
    return true
end

function OnUp(key)
    if key == "CapsLock" then
        return false
    end
    return true
end

Mouse side buttons as media controls

Map Mouse4/Mouse5 to previous/next track.

-- rebind: name=Mouse Media Keys

function OnDown(key)
    if key == "Mouse4" then
        HID.Press("MediaPrev")
        return false
    end
    if key == "Mouse5" then
        HID.Press("MediaNext")
        return false
    end
    return true
end

function OnUp(key)
    if key == "Mouse4" or key == "Mouse5" then
        return false
    end
    return true
end

Scroll to zoom with a modifier

Hold Right Alt and scroll to zoom. Works in browsers, image viewers, editors — anywhere that responds to Ctrl+scroll.

-- rebind: name=Scroll Zoom

local cfg = UI.Schema({
    modifier = UI.Keybind("RAlt", { label = "Modifier Key" }),
})

function OnScroll(delta)
    if Input.IsDown(cfg.modifier) then
        HID.Down("LCtrl")
        HID.Scroll(delta)
        HID.Up("LCtrl")
        return false
    end
    return true
end

Intermediate

Text expander

Type an abbreviation and hit a trigger key to expand it. @@ expands to your email address, ## to your signature, /date to today's date.

-- rebind: name=Text Expander

local cfg = UI.Schema({
    trigger = UI.Keybind("F8",           { label = "Expand Key" }),
    email   = UI.Text("user@example.com", { label = "Email", maxLength = 60 }),
    sig     = UI.Text("Best regards,",   { label = "Signature", maxLength = 100 }),
})

local snippets = {}

function OnStart()
    snippets = {
        ["@@"]   = cfg.email,
        ["##"]   = cfg.sig,
        ["/date"] = os.date("%Y-%m-%d"),
        ["/time"] = os.date("%H:%M"),
    }
end

local buffer = ""

function OnDown(key)
    if key == cfg.trigger then
        for abbr, expansion in pairs(snippets) do
            if buffer:sub(-#abbr) == abbr then
                Run(function()
                    for i = 1, #abbr do
                        HID.Press("Backspace")
                        Sleep(20)
                    end
                    HID.Type(expansion, 15)
                end)
                buffer = ""
                return false
            end
        end
        return false
    end

    if #key == 1 then
        buffer = buffer .. key
        if #buffer > 20 then buffer = buffer:sub(-20) end
    elseif key == "Backspace" and #buffer > 0 then
        buffer = buffer:sub(1, -2)
    elseif key == "Space" or key == "Enter" then
        buffer = ""
    end

    return true
end

Browser tab navigation

Mouse4/Mouse5 navigate tabs in Chrome, Firefox, Edge, and Brave. Middle-click + Alt closes the tab. Completely inert in all other applications.

-- rebind: name=Browser Tabs
-- rebind: process=chrome.exe
-- rebind: process=firefox.exe
-- rebind: process=msedge.exe
-- rebind: process=brave.exe

function OnDown(key)
    if key == "Mouse4" then
        HID.Press("LCtrl+PageUp")
        return false
    end
    if key == "Mouse5" then
        HID.Press("LCtrl+PageDown")
        return false
    end
    if key == "Mouse3" and Input.IsDown("LAlt") then
        HID.Press("LCtrl+W")
        return false
    end
    return true
end

Sticky modifier

Tap Shift once and it stays held until you tap it again. Useful for accessibility or one-handed workflows.

-- rebind: name=Sticky Modifier

local cfg = UI.Schema({
    target = UI.Keybind("LShift", { label = "Modifier to Toggle" }),
})

local held = false

function OnDown(key)
    if key == cfg.target then
        held = not held
        if held then
            HID.Down(cfg.target)
            UI.Notify("Modifier locked", "info")
        else
            HID.Up(cfg.target)
            UI.Notify("Modifier released", "info")
        end
        return false
    end
    return true
end

function OnUp(key)
    if key == cfg.target then
        return false
    end
    return true
end

function OnBlur()
    if held then
        held = false
        HID.Up(cfg.target)
    end
end

Precision mouse

Hold middle mouse to slow movement down to a configurable percentage. Useful for image editing, CAD, or any precision work.

-- rebind: name=Precision Mouse

local cfg = UI.Schema({
    hold_key = UI.Keybind("Mouse3",  { label = "Hold Key" }),
    slowdown = UI.Slider(25, { min = 5, max = 75, suffix = "%", label = "Speed %" }),
})

function OnMove(dx, dy)
    if Input.IsDown(cfg.hold_key) then
        local factor = cfg.slowdown / 100
        HID.Move(dx * factor, dy * factor)
        return false
    end
    return true
end

Photoshop shortcuts

Alt+scroll changes brush size. Mouse4/Mouse5 become undo/redo. Only active when Photoshop is focused.

-- rebind: name=Photoshop Shortcuts
-- rebind: process=Photoshop.exe

local cfg = UI.Schema({
    brush_step = UI.Slider(5, { min = 1, max = 20, label = "Brush Step" }),
})

function OnScroll(delta)
    if Input.IsDown("LAlt") then
        Run(function()
            for i = 1, cfg.brush_step do
                HID.Press(delta > 0 and "RightBrace" or "LeftBrace")
                Sleep(10)
            end
        end)
        return false
    end
    return true
end

function OnDown(key)
    if key == "Mouse4" then
        HID.Press("LCtrl+Z")
        return false
    end
    if key == "Mouse5" then
        HID.Press("LCtrl+LShift+Z")
        return false
    end
    return true
end

Advanced

Auto-clicker with timer

Toggle an auto-clicker with a hotkey. Uses Timer.Every for clean repeating intervals rather than a loop.

-- rebind: name=Auto Clicker

local cfg = UI.Schema({
    cps        = UI.Slider(5,  { min = 1, max = 20, label = "Clicks Per Second" }),
    toggle_key = UI.Keybind("F7", { label = "Toggle" }),
})

local active = false
local clickTimer = nil

function OnDown(key)
    if key == cfg.toggle_key then
        active = not active
        if active then
            clickTimer = Timer.Every(1000 / cfg.cps, function()
                HID.Press("Mouse1", 20)
            end)
            UI.Notify("ON", "info")
        else
            if clickTimer then clickTimer:Cancel() end
            UI.Notify("OFF", "info")
        end
        return false
    end
    return true
end

function OnStop()
    if clickTimer then clickTimer:Cancel() end
end

function OnBlur()
    if active then
        active = false
        if clickTimer then clickTimer:Cancel() end
    end
end

Workflow hub

Mouse4/Mouse5 do different things depending on which app is focused — all from a single script.

-- rebind: name=Workflow Hub

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable" }),
})

local function isProcess(name)
    return System.Window().process:lower():find(name:lower()) ~= nil
end

function OnDown(key)
    if not cfg.enabled then return true end

    if key == "Mouse4" then
        if isProcess("Photoshop") then
            HID.Press("LCtrl+Z")
        elseif isProcess("chrome") or isProcess("firefox") or isProcess("msedge") then
            HID.Press("LCtrl+PageUp")
        elseif isProcess("explorer") then
            HID.Press("LAlt+Left")
        else
            return true
        end
        return false
    end

    if key == "Mouse5" then
        if isProcess("Photoshop") then
            HID.Press("LCtrl+LShift+Z")
        elseif isProcess("chrome") or isProcess("firefox") or isProcess("msedge") then
            HID.Press("LCtrl+PageDown")
        elseif isProcess("explorer") then
            HID.Press("LAlt+Right")
        else
            return true
        end
        return false
    end

    return true
end

HTTP remote control

Control Rebind from any tool that can make HTTP requests — curl, Python, a browser, a home automation system.

-- rebind: name=HTTP Remote
-- rebind: permission=net

local cfg = UI.Schema({
    port = UI.Slider(8080, { min = 1024, max = 65535, label = "Port" }),
})

local server = nil

function OnStart()
    server = Net.Listen(cfg.port, function(req)
        if req.path == "/click" then
            HID.Press("Mouse1")
            return { status = 200, body = "clicked" }
        elseif req.path == "/type" and req.body then
            HID.Type(req.body)
            return { status = 200, body = "typed" }
        elseif req.path == "/press" and req.body then
            HID.Press(req.body)
            return { status = 200, body = "pressed" }
        end
        return { status = 404, body = "not found" }
    end)
    Log.Info("Listening on port " .. cfg.port)
end

function OnStop()
    if server then server:Stop() end
end

Send commands with curl: curl -X POST http://localhost:8080/type -d "Hello World"


Python IPC bridge

Communicate with an external Python process via shared memory. The Python side writes commands; the Rebind script reads and executes them.

-- rebind: name=Python Bridge

local pipe = nil

function OnStart()
    pipe = Pipe.Open("myapp", { size = 65536 })

    Timer.Every(10, function()
        local msg = pipe:Read()
        if msg then
            local data = JSON.Parse(msg)
            if data.action == "type" and data.text then
                HID.Type(data.text, 30)
            elseif data.action == "press" and data.key then
                HID.Press(data.key)
            end
        end
    end)
end

function OnStop()
    if pipe then pipe:Close() end
end

Python side:

import mmap, struct, json

shm = mmap.mmap(-1, 65536, tagname="Local\\Rebind_myapp")
offset = 65536 // 2
data = json.dumps({"action": "type", "text": "Hello from Python!"}).encode()

shm.seek(offset)
shm.write(struct.pack('<Q', 1))
shm.write(struct.pack('<I', len(data)))
shm.write(data)

Accessibility

Tremor smoothing

Filters out small jittery movements and applies exponential smoothing. Configurable threshold and smoothing strength.

-- rebind: name=Steady Hand
-- rebind: mouse_block=true

local cfg = UI.Schema({
    enabled   = UI.Toggle(true),
    smoothing = UI.Slider(50, { min = 0, max = 90, suffix = "%" }),
    threshold = UI.Slider(5,  { min = 1, max = 20, suffix = "px" }),
})

local buffer = { x = 0, y = 0 }

function OnMove(dx, dy)
    if not cfg.enabled then return true end

    local magnitude = math.sqrt(dx * dx + dy * dy)
    if magnitude < cfg.threshold then
        return false
    end

    local s = cfg.smoothing / 100
    buffer.x = buffer.x * s + dx * (1 - s)
    buffer.y = buffer.y * s + dy * (1 - s)

    HID.Move(buffer.x, buffer.y)
    return false
end

function OnBlur()
    buffer.x = 0
    buffer.y = 0
end

Dwell click

Click by hovering the cursor in one spot for a configurable duration. For users who cannot physically click a mouse button.

-- rebind: name=Dwell Click

local cfg = UI.Schema({
    enabled    = UI.Toggle(true),
    dwell_time = UI.Slider(1000, { min = 300, max = 3000, suffix = "ms" }),
    tolerance  = UI.Slider(10,   { min = 5, max = 50, suffix = "px" }),
    click_type = UI.Select("Left Click", { "Left Click", "Right Click", "Double Click" }),
    sound      = UI.Toggle(true, { label = "Audio Feedback" }),
})

local dwellStart = nil
local dwellPos = { x = 0, y = 0 }

function OnTick()
    if not cfg.enabled then dwellStart = nil return end

    local pos = Input.GetMousePos()
    local dx = pos.x - dwellPos.x
    local dy = pos.y - dwellPos.y

    if math.sqrt(dx*dx + dy*dy) > cfg.tolerance then
        dwellPos = pos
        dwellStart = System.Time()
        return
    end

    if not dwellStart then dwellStart = System.Time() return end

    if System.Time() - dwellStart >= cfg.dwell_time then
        if cfg.click_type == "Left Click" then
            HID.Press("Mouse1")
        elseif cfg.click_type == "Right Click" then
            HID.Press("Mouse2")
        elseif cfg.click_type == "Double Click" then
            Run(function()
                HID.Press("Mouse1", 30)
                Sleep(50)
                HID.Press("Mouse1", 30)
            end)
        end
        if cfg.sound then Audio.Beep() end
        dwellStart = nil
    end
end

Where to go from here

These scripts are starting points. The full SDK documentation documents every available function. If you'd rather describe what you want in plain English and have it generated automatically, RebindGPT knows the complete SDK and can write scripts from a description.

The marketplace has community-built scripts for gaming, streaming, productivity, and accessibility — each with a settings panel you can customize without touching code.

Back to all posts