kvm macro
A macro binds a key combination to an action. The combination is detected on the remote station's keyboard and never forwarded to the controlled PC. Macros are stored persistently and survive server restarts.
A macro lives inside a seat configuration, and is created, removed, enabled, and disabled there with kvm config macro. The kvm macro command itself is read-only: it reports what exists and what a given seat will actually fire.
| Command Type | DisplayNet |
| Minimum Version | 5.0 |
Usage
kvm macro list [<remote_device>]
Authoring, in kvm config:
kvm config macro add <config> <name> <trigger> <builtin|command|script|sendkeys> <action...>
kvm config macro remove <config> <name>
kvm config macro enable <config> <name>
kvm config macro disable <config> <name>
They addressed a macro by a scope and a bare name rather than by its configuration, which made two things impossible to get right:
kvm macro define <name> <remote_device>created a configuration for that receiver and assigned it. Since a seat resolves to exactly one configuration and that configuration replaces the less specific one entirely, the new one, holding one macro and no buttons, took the seat's Stream Deck dark the instant it was created.- A macro name was a global handle, so
kvm macro delete <name>searched every configuration. That in turn forcedkvm config cloneto rename the macros it copied, since two of them could not share a name.
define → config macro add, delete → config macro remove. Running an old verb returns an error naming its replacement.
Macro scope
Not on the macro, but on its configuration. A configuration assigned to global applies at every station; one assigned to an rx scope applies at that seat.
Resolution is whole-configuration replacement, not a per-trigger merge
Each seat resolves to exactly one configuration (rx > global), and that configuration supplies all of the seat's macros. The less-specific one is not layered underneath it. So the moment a seat has its own configuration assigned, none of the Global macros apply there anymore, not just the ones sharing a trigger. Give a seat its own configuration and it must carry the complete set that seat needs. kvm config clone is the quick way to start from the global set. See kvm config.
Names and triggers are unique within a configuration, not globally. Two configurations may each hold a macro called openrun, and cloning a configuration copies names verbatim.
Action types
| Type | Action argument | Effect |
|---|---|---|
builtin | focus_next, focus_prev, focus <window>, lock_toggle, lock_on, lock_off, fullscreen_toggle, fullscreen_on, fullscreen_off | Runs the corresponding kvm focus / kvm lock / kvm fullscreen operation on the session that fired the macro |
command | Any DisplayNet API command | Runs the command with the same validation and authority as a connected client |
script | The name of an existing preset script | Runs the script (see preset) |
sendkeys | A keystroke sequence, e.g. ctrl+alt+f1 or gui+r, type:notepad, enter | Types the sequence into the host the seat is currently controlling (see kvm sendkeys) |
A script action must name a script that already exists; the add is rejected otherwise.
Arguments
| Argument | Description |
|---|---|
config | The configuration that will own the macro. kvm config list shows them; kvm workstation show <remote_device> shows which one a seat resolves. |
name | The macro name, unique within its configuration (case-insensitive). |
remote_device | A remote HID extender, used to filter kvm macro list to what that seat actually fires. |
trigger | A key combination string. See trigger. |
trigger
A key combination string: one or more modifiers plus exactly one non-modifier key, joined with +. Matching is side-agnostic: left and right modifiers are equivalent (ctrl matches either Ctrl key, and lctrl/rctrl are accepted as aliases).
| Element | Accepted names |
|---|---|
| Modifiers | ctrl, shift, alt, gui (aliases: control, win, cmd, and l/r side prefixes) |
| Letters / digits | a to z, 0 to 9 |
| Function keys | f1 to f12 |
| Navigation | up, down, left, right, home, end, pageup, pagedown, insert, delete |
| Other | enter, esc, tab, space, backspace, minus, equals, printscreen, scrolllock, pause, numlock, kp0 to kp9 |
| Raw escape | 0xNN, any USB HID usage code in hex |
Examples: ctrl+alt+1, ctrl+shift+f5, gui+0x52.
When a trigger fires, the controlled PC does not see the combination. The chord is swallowed and the modifier keys are released cleanly on the PC side.
Examples
Add a hotkey that every station getskvm config macro add Global wallcycle ctrl+alt+n builtin focus_next
Add one that runs a preset scriptkvm config macro add Global camerascript ctrl+alt+c script CameraPreset1
Give one seat its own macros, starting from the global setkvm config clone Global ControlRoom_seat
kvm config assign ControlRoom_seat rx ControlRoom
kvm config macro add ControlRoom_seat night ctrl+alt+f9 command preset apply NightShift
Turn a macro off without deleting itkvm config macro disable Global wallcycle
List what a station will actually firekvm macro list ControlRoom
command actionType the API command as plain words after command, as in the night example above. Do not wrap the whole command in quotes. A quoted command "preset apply NightShift" collapses to the single token preset_apply_NightShift; the macro is accepted and the break surfaces only when it fires. A multi-word name inside the command still needs its quotes so it stays one token: command connect HDMI "Front Lobby" ControlRoom.
Return value
kvm macro list
With no argument, every macro that exists, labelled with the configuration that owns it. With a <remote_device>, the seat's effective set, read from the same compiled result the engine fires from, so it cannot drift from behaviour.
kvm macro list{
"status": "SUCCESS",
"request_id": null,
"result": {
"macro_list": [
{
"Name": "wallcycle",
"Config": "Global",
"TriggerDisplay": "ctrl+alt+n",
"ActionType": "builtin",
"ActionPayload": "focus_next",
"Enabled": true
}
]
},
"error": null
}
TriggerDisplay is the macro's trigger as the same human-readable string used to define it, such as ctrl+alt+n. It uses the exact vocabulary the trigger argument accepts, so what a macro reports is what recreates it.
Config replaced the former Scope / Source pair in 5.0. Those described a per-macro scope, but resolution has always been per-configuration, and once every macro is configuration-owned, every row would have reported global regardless of where its configuration was actually assigned.
Macro subcommands
add, remove, enable and disable all return the same envelope.
kvm config macro add Global wallcycle ctrl+alt+n builtin focus_next{
"status": "SUCCESS",
"request_id": null,
"result": null,
"error": null
}
Errors
Error response{
"status": "ERROR",
"request_id": null,
"result": null,
"error": {
"message": "<description>",
"reason": "KVM API ERROR"
}
}
Common error conditions:
- Invalid trigger string, action type, or built-in name (
config macro add) - Macro name already used in that configuration, or its trigger already bound there (
config macro add) - Script not found (
config macro add ... script) - Configuration not found, or no macro of that name in it (
config macro remove/enable/disable) - Enabling a macro whose trigger is already bound by another enabled macro in the same configuration (
config macro enable) - A removed
kvm macroverb was used. The message names itskvm config macroreplacement
Notifications
macro_update
Sent after every kvm config macro add, remove, enable, or disable, carrying the current macro names and enabled flags so clients can keep a macro editor live.
macro_update notification{
"status": "DN_NOTIFICATION",
"request_id": null,
"error": null,
"result": {
"macro_update": [
{ "Name": "wallcycle", "Enabled": true },
{ "Name": "night", "Enabled": false }
]
}
}
macro_error
Sent when a fired macro fails to execute, for example a command macro whose target device is locked, or a fullscreen_toggle on a session that is not MultiView. A failing macro never disturbs keyboard/mouse forwarding.
macro_error notification{
"status": "DN_NOTIFICATION",
"request_id": null,
"error": null,
"result": {
"macro_error": [
{
"Macro": "night",
"Remote": "6cdffb00387f",
"Action": "preset apply NightShift",
"Message": "Cannot apply preset: device DisplayWall-1 is locked"
}
]
}
}
REST API
| Endpoint type | DisplayNet API command |
|---|---|
| Address | POST /api/displaynet/<operation>, or name the operation in the body of a POST /api/displaynet. See Sending commands. |
| Role | User |
| Subcommand | Operation | Parameters |
|---|---|---|
macro | kvm_macro | action [args]* |
macro_list | kvm_macro_list | [remote_id] |
A parameter in brackets is optional. A parameter marked * takes the remainder of the command line as one string. Pass the text exactly as you would type it on the TCI interface.
kvm_macro_list takes remote_id as a named field for one seat's effective set, or no fields for every defined macro. Authoring runs through the kvm config typed operations.
kvm_macro takes a raw grammar line instead: action and args, spelled as under Usage above.
See also
kvm config: where macros are authored, and the configuration model they resolve throughkvm: core KVM session commands, includingkvm sendkeyspreset: preset scripts runnable fromscriptmacros