Coming from Keyboard Maestro
How Keyboard Maestro's groups, triggers, actions, conditions, variables and tokens map to Switchboard, and how to import your library.
Keyboard Maestro: Macro Groups, Palettes, Tokens, Variables, Engine, Editor, kmmacros
Most of what you know carries over: a macro still has triggers, optional conditions and a list of actions. This page maps the words, then covers importing your library.
The same ideas, different words #
| Keyboard Maestro | Switchboard |
|---|---|
| Macro Group | Group, with a scope: everywhere, only in some apps, or everywhere except some apps |
| Palette (a group shown as a palette) | A layer: the group's hotkey, then a bare key, with the keys listed on screen. The palette hotkey, ⌥Space by default, still lists every macro. |
| Triggers | When |
| Conditions on the macro | Only if |
| Actions | Do: a list of Steps |
| If Then Else, Switch, Repeat, While, For Each | if and repeat steps, with nested steps |
| Local_ and Instance_ variables | Run-local variables: just a name |
| Global variables | shared. variables that persist between runs |
%Variable%name%, %Calculate%…% | {{ name }} and {{ expression }} |
| Keyboard Maestro Engine and Editor | Switchboard Engine runs macros in the background. The Switchboard app is where you edit. |
| One big library file | One JSON file per macro, in the Library folder |
Groups and scope #
A group is a folder of macros with an on/off switch and a scope. The scope is everywhere, or a list of apps with an only in these or everywhere except these choice. If two groups want the same key, the app-scoped one wins over the everywhere one.
Variables #
A Keyboard Maestro variable named Local_count or Instance_count becomes count, local to the run. A global such as Counter becomes shared.counter. Names that are already plain identifiers keep their names. Names with spaces or punctuation become lower snake case.
- Set greeting to “Hello”
- Show “{{ greeting }}, world”
Tokens #
Text fields use {{ }} for anything that changes. Inside the braces you write an expression, so %Calculate% is just arithmetic.
| Keyboard Maestro | Switchboard |
|---|---|
%Variable%name% | {{ name }} (or {{ shared.name }} for a global) |
%SystemClipboard%, %CurrentClipboard% | {{ clipboard }} |
%FrontWindowName% | {{ frontWindowTitle }} |
%Application%1% | {{ frontAppName }} |
%TriggerValue% | {{ triggerValue }} |
%ICUDateTime%format% | {{ date("format") }} |
%Calculate%1+2% | {{ (1+2) }} |
%ExecutingMacro% | The macro's name, written out as plain text |
(2 + 3) * 420Tokens with no equivalent, such as %MouseLocation% or %FinderSelections%, stay as plain text in the imported macro, and the review flags them.
Triggers #
| Keyboard Maestro trigger | Switchboard trigger |
|---|---|
| Hot Key (pressed, repeating) | Hotkey |
| Typed String | typed |
| Application launches, quits, activates, deactivates | app |
| Time of day | time |
| Cron | time with a cron schedule |
| Repeat while (every N, between times) | periodic plus an Only if time window |
| Wake, Sleep, Unlock, Idle | wake, sleep, unlock, idle |
| Folder | file |
| USB device | device |
| Wireless network | network |
| None. Keyboard Maestro can't see notifications. | App notification: any app's notification, matched on app, title and body |
| Public web trigger | url |
| A variable counter and an If, to do something only the first time today | A tick: Limits on the trigger, "at most 1 per day". See Limits on any trigger. |
| A variable with a timestamp, to rate-limit a trigger | Limits, Cooldown |
| A counter variable and a modulo test, to act every nth time | Limits, "Every 3rd time" |
| A timestamp variable, to catch a double press or a double copy | Limits, "Twice within 2 s" ({{ trigger.burst }}) |
| Subroutine | None. The macro's parameters become its inputs, and you call it with a Run Macro step. See Functions. |
A hotkey that fires on release or hold has no Switchboard equivalent. That macro imports disabled.
A Typed String trigger with an Insert Text action is a snippet: it imports in the snippet shape and shows in the snippet editor (see Snippets), and the %|% token in the text, where Keyboard Maestro puts the caret, becomes {{cursor}}.
- Press ⌥⌘K
- Show “Hello from Switchboard”
Actions to steps #
A representative selection. The full list is in the step reference.
| Keyboard Maestro action | Switchboard step |
|---|---|
| Insert Text by Typing | Type text |
| Insert Text by Pasting | clipboard set, pressKeys Command-V, then restore the clipboard |
| Simulate Keystroke | Press keys |
| Pause | waitFor |
| Activate a Specific Application | activate |
| Open URL, Open File | openURL, openFile |
| Select Menu Item | menu |
| Manipulate a Window | window |
| Set Clipboard to Text | clipboard |
| Display Text in a Window / Briefly | notify / hud |
| Notification | notify |
| Speak Text | speak |
| Execute Shell Script, AppleScript, JXA, Swift | shell, appleScript, jxa, swiftScript |
| Execute a Shortcut | runShortcut |
| Execute a Macro | runMacro |
| Set Variable to Text / Calculation | variable |
| If Then Else, Switch | if |
| Repeat, While, For Each | repeat |
| Cancel, Break from Loop, Return | cancel, break, return |
| Comment | Dropped |
Some actions have no step: Safari Control, Prompt for Snippet, Show Palette of Macros, Named Clipboards and Bring All Windows Forward. They import as an "unsupported" placeholder step that keeps the original action's data so you can rebuild it.
Conditions #
| Keyboard Maestro condition | Switchboard |
|---|---|
| Application active, not active | frontApp, with negate for "not" |
| Front window title contains, is, matches | windowTitle |
| Variable (is, contains, greater than…) | variable |
| Path exists | fileExists |
| Modifiers down | modifierDown |
| Script succeeds, fails, or output matches | script |
| Screen image | Imported where possible; check the note |
"Key is down" and menu-item-state conditions have no equivalent.
Import your library #
Open File › Import… (it is also offered on first launch) or use the command line. The importer reads a .kmmacros export, or your live Keyboard Maestro library.
switchboard import ~/Desktop/MyMacros.kmmacros --dry
switchboard import --km-library --dry
switchboard import ~/Desktop/MyMacros.kmmacros
switchboard import ~/Desktop/MyMacros.kmmacros --take-over
--dryprints the review as JSON and writes nothing.--km-libraryreads your live Keyboard Maestro library instead of a file.--take-overkeeps each macro's on/off state from Keyboard Maestro.
Importing the same library twice replaces macros by id; it doesn't duplicate them.
Nothing fires twice #
Until you take over, everything imports disabled. Keyboard Maestro still owns your hotkeys, and two apps answering the same key would fire twice.
When you are ready:
Quit Keyboard Maestro.
Import again with Take over Keyboard Maestro's hotkeys switched on (or
--take-over).
With take over, groups and macros keep the state they had in Keyboard Maestro. A macro that has anything unsupported still imports disabled, with a note.
Reading the review #
Before anything is added, the review sheet lists every group and macro with a badge:
| Badge | Meaning |
|---|---|
| Ready | Everything mapped with nothing to check. |
| Needs a look | It imported, but something was guessed, for example a repeat interval read as seconds, a weekday bit mask, or a USB device id. Open the notes. |
| Not supported | Part of it cannot run in Switchboard yet. The macro imports disabled, with a placeholder step where the action was. |
Each macro's notes name the step they refer to. The Show control filters to the ones that need a look. Pictures used by image steps are saved beside the macro.
Tidying an import #
An import is a literal translation: a variable called KMVAR_Local_Result, a 0.5-second Pause where a wait belongs, the same four steps pasted into a dozen macros. Tidy up with AI (Macro menu, ⌥⌘I) cleans one macro up. It never runs on its own, and nothing is saved until you have read the changes and pressed Apply, which is one Undo. History records what it did ("Tidied: renamed 4 variables, folded 2 waits").
The plain rules go first:
Names. Variables that are not lower camel case become readable (
my_file_pathbecomesmyFilePath), in every step and condition that uses them. A name that a script, a shell command or a piece of text still uses is left alone, and the change list says why.Waits. A fixed pause right before a click, field or button becomes a wait for that element, up to the same time. Two waits in a row become one.
Unused variables. A variable that is set and never read anywhere, scripts included, is dropped. When in doubt it stays.
Calls. Steps that match a whole macro you already have become a call to it. Steps that only almost match are listed as a suggestion, not changed.
Then the model gives steps short labels, suggests a name and a description, and may answer an import note when the macro itself shows the answer. It cannot change what any step does: a check compares every step's type and settings before and after, and refuses the proposal if one differs.