Hey everyone!
I'm excited to share kmjs, an open-source TypeScript toolkit I created for programmatically interfacing with Keyboard Maestro, designed for constructing and executing macros entirely in-memory.
It handles all the boilerplate required for constructing each 'virtual' macro's XML, and then running it, and returning the result. Each virtual action has been tested through an automated routine I created, which generates and imports its possible configurations into KM as a real macro, then extracts that, and then compares the expected result with the generated result.
Here's an example of creating a virtual macro and running it:
import { createVirtualNotification, createVirtualPause, runVirtualMacro, } from "kmjs";
// 1. Define your sequence of virtual actions
const actions = [
createVirtualNotification({
title: "Hello from kmjs!",
body: "This is a virtual macro.",
sound: "Glass",
}),
createVirtualPause({ time: 1 }), // Pause for 1 second
createVirtualNotification({
title: "Still here!",
body: "The virtual macro has finished.",
sound: "Ping",
}),
];
// 2. Run the sequence in-memory via KM
runVirtualMacro(actions, "My First Virtual Macro");
Virtual macros can return values, too, of course.
I also built a 'query' framework, which takes KM's tokens and wraps them in a single virtual macro, which then returns the relevant value. For example, getting the current mouse position in JS is now as simple as:
import { getMousePosition } from "kmjs/queries";
const positionString = getMousePosition();
// e.g. "1234,876"*
Beyond the virtual actions/macros, it's packed with various tools and functions that utilise KM, including workflows focused on working with variables and macros that exist in real macros in the GUI. It also includes various JavaScript utilities and tools conceptualised/created by the community, re-packaged as TypeScript functions as a part of this project.
I built this as part of a commercial JS project in which I wanted to use KM for building automated testing routines. Then, of course, as every KM user is too familiar with, the little side project ballooned exponentially into what it is now. As such, not every action has a virtual equivalent (yet). I focused on what would be immediately useful for GUI automation, plus a few extras.
I'd rather not inundate this forum post with everything in kmjs, but I also wanted to highlight the keyboard handling utilities. While creating this, I was bewildered that there are no centralised or complete examples of ready-to-use AppleScript keyboard code mappings. As such, I've built out a complete system for keystroke and keyboard shortcut normalisation (which the virtual actions for keystrokes use). You can input:
- Human-Readable String : Common shortcuts like "Cmd+Shift+S".
- JavaScript event.code String : Web-standard codes like "KeyS" or "Digit1".
- Raw Numeric Key Code : A number representing an AppleScript key code, like 36 for the Return key.
- AppleScript Map : An existing map object like { 256: 1 } (Cmd+S), which is passed through unmodified.
... and produce an object with a single key-value pair that represents a modifier combination and keycode: { [modifierMask]: [keyCode] }. These are then separated out for use in KM actions. I suspect this part of the project might be useful to many people beyond those using KM.
As someone who's benefited enormously from this community, I want to give back with something I hope helps you in your KM-related projects.
Cheers!
(This is my first GitHub / npm project. Please go easy on me - I'd also greatly appreciate any advice about going about hosting and collaborating on repos)!