Current Status: Not usable, available for public experimentation.
A linux desktop automation tool providing programmable macros using Bun, a fast JavaScript runtime. It exposes an API to define macro keys, as well as many functions to interact with your system and the various applications I use.
Note - Only available on Linux with X11. It probably isn't possible to support Wayland, but MacOS and Windows could be supported in the future. If you're interested in helping that effort, please reach out.
The demo below is not implemented and is more of a sketch of what I want to achieve
import { kb, ui, Keyboard } from "bhk";
// hotkeys on main keyboard, requires modifier
kb.macro("super + f1", () => {
// `ui` contains live bindings to the current state of your desktop
// .activeWindow is a getter to fetch the active window
// .name is a getter to fetch the name of the active window
console.log(`Macro activated in ${ui.activeWindow.name}`);
// All getters are cached for one tick, meaning a second access will
// not cause a second fetch, and is guaranteed to be the same value.
console.log(`Macro activated in ${ui.activeWindow.proc.exe}`);
// dispatch actions like typing a string
ui.type("Hello world!");
});
// hook into external devices, for example adding an exclusive macro keyboard
// (linux version of Taren's 2nd keyboard stuff)
const kb2 = new Device({ vendor: 0x1b1c, product: 0x1b13 });
kb2.macro("q", () => {
// helper to focus or launch an application
ui.focusOrLaunch("discord");
// same as above but manual
let window = ui.findWindow({ class: "discord" });
if (window) {
window.focus();
} else {
// launch returns a promise to the first window the process creates
window = await ui.launch(["discord"]);
}
});
Any and all of this may be changed at any time.
BunHotKey exposes live bindings to your UI and window state. Unchecked things are not implemented.
ui
:-
activeWindow
->WindowRef
-
hoveredWindow
->WindowRef
-
findWindow(query: FindWindowOptions)
->?WindowRef
-
launch(command: string[])
->Promise<WindowRef>
-
focusOrLaunch(command: string[])
->Promise<WindowRef>
-
mouse
-
pos
->{ x: number, y: number }
-
moveTo(x: number, y: number)
-
moveBy(x: number, y: number)
-
click(button: number)
-
down(button: number)
-
up(button: number)
-
-
i3
:-
async exec(command: string)
-
workspaces
->WorkspaceRef[]
-
workspace(name: string)
->WorkspaceRef
-
on(event, cb)
-
workspace
-
output
-
mode
-
window
-
barconfig_update
-
binding
-
shutdown
-
tick
-
-
blender
-
async execString(python: string)
-
async execFile(path: string)
-
There are a number of "ref" classes which consist of an id
and expose live bindings to them.
WindowRef
(this is designed to be cross-platform)- Properties
-
id
->WindowID
-
name
->string
-
pid
->number
-
proc
->ProcessRef
-
- Bindings
-
size
->{ width: number, height: number }
-
pos
->{ x: number, y: number }
-
x
->number
-
y
->number
-
width
->number
-
height
->number
-
- Methods
-
activate()
-
click(button: number)
-
clickMultiple(button: number, times: number, delay = 1)
-
close()
-
focus()
-
kill()
-
raise()
-
type(text: string, delay = 0)
-
moveMouseRelativeTo(x: number, y: number)
-
- Properties
ProcessRef
- Properties
-
name
->string
-
cmdline
->string
-
cwd
->string
-
exe
->string
-
windows
->WindowRef[]
-
- Methods
-
kill(signal: number)
(defaults to SIGTERM)
-
- Properties
I3WorkspaceRef
(create withi3.workspace(name)
)- Properties
-
name
->string
-
num
->number
-
rect
->{ x: number, y: number, width: number, height: number }
-
urgent
->boolean
-
windows
->WindowRef[]
-
- Bindings
-
focused
->boolean
-
visible
->boolean
-
output
->string
-
- Methods
-
focus()
-
moveToOutput(output: string)
-
- Properties
WIP, JS binding for reading to event devices (/dev/input/event*
)
import { Device } from "bhk";
const device = new Device({
vendor: 0x1b1c,
product: 0x1b3d,
grab: true,
});
device.on("key", (key) => {
console.log(key);
});
Device
-
new Device(opts)
public constructor - Properties
-
type
->string
-
- Bindings
-
grabbed
->boolean
-
- Methods
-
macro(combo: string, cb: Function)
-
- Events
-
key
-
mousemove
-
mousedown
-
mouseup
-
mousewheel
-
-
SpeedEditor
(specific extension for Davinci Resolve Speed Editor)-
new SpeedEditor(opts)
public constructor - Methods
-
macro(combo: string, cb: Function)
-
setLED(led: number, state: boolean)
-
- Events
-
key
-
wheel
-
-
WIP, JS binding for X11's XGrabKey
BunHotKey is developed in Zig and TypeScript. Run bun install
to install dependencies and build the library. Zig is installed through npm.