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 rest to see what else your input is allowed to do now.
All scripts are written in Luau (the getting started guide introduces the language) and run in the Rebind Engine on your PC. Their output reaches your applications as ordinary 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: min_sdk=3.0.0
-- 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: min_sdk=3.0.0
-- rebind: name=CapsLock to Escape
function OnDown(key)
if key == "CapsLock" then
HID.Down("Escape")
return false
end
return true
end
function OnUp(key)
if key == "CapsLock" then
HID.Up("Escape")
return false
end
return true
end
Mouse side buttons as media controls
Map Mouse4/Mouse5 to previous/next track.
-- rebind: min_sdk=3.2.2
-- rebind: name=Mouse Media Keys
function OnDown(key)
if key == "Mouse4" then
HID.Combo("MediaPrev")
return false
end
if key == "Mouse5" then
HID.Combo("MediaNext")
return false
end
return true
end
HID.Combo presses and releases in one call, so this is a tap however long you
hold the mouse button. That matters for media keys: holding one down auto-repeats
on some hosts, which would skip several tracks instead of one. Combo is native
and does not sleep, so it needs no Run().
Scroll to zoom with a modifier
Hold Right Alt and scroll to zoom. Works in browsers, image viewers, and editors, or whatever else responds to Ctrl+scroll.
-- rebind: min_sdk=3.0.0
-- 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: min_sdk=3.0.0
-- 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"] = function()
local t = os.date("*t")
return string.format("%04d-%02d-%02d", t.year, t.month, t.day)
end,
["/time"] = function()
local t = os.date("*t")
return string.format("%02d:%02d", t.hour, t.min)
end,
}
end
local buffer = ""
function OnDown(key)
if key == cfg.trigger then
for abbr, expansion in pairs(snippets) do
if buffer:sub(-#abbr) == abbr then
if type(expansion) == "function" then expansion = expansion() end
Run(function()
for i = 1, #abbr do
HID.Press("Backspace")
Sleep(20)
end
HID.Type(expansion)
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
HID.Press sleeps between the key down and the key up, so it only works inside a coroutine. Hooks like OnDown are not coroutines. Wrap the press in Run, which starts one and returns immediately. HID.Down, HID.Up, and HID.Type are native and can be called from a hook directly.
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: min_sdk=3.0.0
-- 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
Run(function() HID.Press("LCtrl+PageUp") end)
return false
end
if key == "Mouse5" then
Run(function() HID.Press("LCtrl+PageDown") end)
return false
end
if key == "Mouse3" and Input.IsDown("LAlt") then
Run(function() HID.Press("LCtrl+W") end)
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: min_sdk=3.0.0
-- 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 OnStop()
if held then
HID.Up(cfg.target)
end
end
Precision mouse
Hold middle mouse to slow movement down to a configurable percentage. Useful for image editing, CAD, and other precision work.
-- rebind: min_sdk=3.0.0
-- rebind: name=Precision Mouse
-- rebind: mouse_block=true
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
Intercepting mouse movement (mouse_block=true) requires a Rebind Link.
Photoshop shortcuts
Alt+scroll changes brush size. Mouse4/Mouse5 become undo/redo. Only active when Photoshop is focused.
-- rebind: min_sdk=3.0.0
-- 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
Run(function() HID.Press("LCtrl+Z") end)
return false
end
if key == "Mouse5" then
Run(function() HID.Press("LCtrl+LShift+Z") end)
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: min_sdk=3.0.0
-- 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()
Run(function() HID.Press("Mouse1", 20) end)
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
Workflow hub
Mouse4/Mouse5 do different things depending on which app is focused, all from a single script.
-- rebind: min_sdk=3.0.0
-- 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
local combo
if isProcess("Photoshop") then
combo = "LCtrl+Z"
elseif isProcess("chrome") or isProcess("firefox") or isProcess("msedge") then
combo = "LCtrl+PageUp"
elseif isProcess("explorer") then
combo = "LAlt+Left"
else
return true
end
Run(function() HID.Press(combo) end)
return false
end
if key == "Mouse5" then
local combo
if isProcess("Photoshop") then
combo = "LCtrl+LShift+Z"
elseif isProcess("chrome") or isProcess("firefox") or isProcess("msedge") then
combo = "LCtrl+PageDown"
elseif isProcess("explorer") then
combo = "LAlt+Right"
else
return true
end
Run(function() HID.Press(combo) end)
return false
end
return true
end
HTTP remote control
Control Rebind over HTTP: curl, Python, a browser, a home automation system.
-- rebind: min_sdk=3.0.0
-- 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
Run(function() HID.Press("Mouse1") end)
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
local key = req.body
Run(function() HID.Press(key) end)
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. The Pipe API is Windows only.
-- rebind: min_sdk=3.0.0
-- 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)
elseif data.action == "press" and data.key then
Run(function() HID.Press(data.key) end)
end
end
end)
end
function OnStop()
if pipe then pipe:Close() end
end
Python side. An external peer writes to channel B (offset size / 2); each channel is a 12-byte header (u64 sequence, u32 length) followed by the payload, and the sequence is written last:
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 + 12)
shm.write(data) # payload first
shm.seek(offset + 8)
shm.write(struct.pack('<I', len(data))) # then length
shm.seek(offset)
shm.write(struct.pack('<Q', 1)) # sequence number last
The wire protocol, plus complete Python, Rust, and Node peers, is documented in the Pipe reference.
Accessibility
Tremor smoothing
Filters out small jittery movements and applies exponential smoothing. Configurable threshold and smoothing strength.
-- rebind: min_sdk=3.0.0
-- 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
Intercepting mouse movement (mouse_block=true) requires a Rebind Link.
Dwell click
Click by hovering the cursor in one spot for a configurable duration. For users who cannot physically click a mouse button.
-- rebind: min_sdk=3.0.0
-- 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
Run(function() HID.Press("Mouse1") end)
elseif cfg.click_type == "Right Click" then
Run(function() HID.Press("Mouse2") end)
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 Documentation covers the full SDK. If you'd rather describe what you want in plain English, RebindGPT knows the SDK and writes the script for you.
The in-app marketplace has community-built scripts for gaming, streaming, productivity, and accessibility, each with a settings panel you can customize without touching code.