Writing KSL

KSL is the Keybind Scripting Language. It reads like JavaScript or Python, with real variables, functions, and control flow — plus keyboard-first constructs like bind and hotstring built into the language. This page covers the fundamentals; every builtin is in the Function Library.

Binds

A bind maps a key or combo to an action:

bind Ctrl+Alt+H => notify("Hello!")

# A multi-line body goes in braces
bind Win+Up => {
    snap_to("max")
    notify("Maximized")
}

Hotstrings

Type an abbreviation, get an expansion:

hotstring "kb"  => "Keybind"
hotstring "sll" => "Stanbren LLC"

Variables and types

Declare with let. Values are numbers, strings, booleans, null, arrays, and maps. String interpolation uses {...}:

let name  = "Ada"
let count = 3
let tags  = ["work", "urgent"]
let user  = { id: 1, name: "Ada" }

notify("Hello {name}, you have {count} items")

Functions

Functions are first-class — name them, or pass them inline as closures:

fn greet(name) {
    return "Hello, {name}"
}

let words = str_split("the quick brown fox", " ")
let long  = arr_filter(words, fn(w) { return str_len(w) > 3 })

Control flow

if count > 0 {
    notify("has items")
} else {
    notify("empty")
}

for word in words {
    notify(word)
}

Error handling

Wrap fallible calls in try/catch:

try {
    let data = file_read("C:/inbox/orders.csv")
} catch (e) {
    notify("Failed: {e.message}")
}

Capabilities

Anything sensitive — the filesystem, network, clipboard, launching processes, AI — is gated behind a capability. A script declares the ones it uses at the top, and Keybind asks your approval once, then remembers it:

#! requires: process, notify

on_load {
    on_interval(5000, fn() {
        if !process_exists("notepad.exe") { run("notepad.exe") }
    })
}

The tokens include filesystem, network, clipboard, process, window, display, notify, store, ai, and more. Declare only what you actually use — the Function Library lists the capability each builtin needs.

Resident scripts

A script that declares on_load, bind, hotstring, or a timer becomes a resident Script Module: it loads once, keeps persistent global state, and reacts to events in the background (great for always-on watchers). A plain per-fire snippet, by contrast, just runs and exits.

> The complete single-file language spec ships with the app and lists every builtin. For the searchable online version, see the Function Library.

We use cookies for analytics to understand how the site is used. Functional cookies (your session) are always on. Privacy Policy.