kvm workstation
The kvm workstation command configures a seat as a whole: what one operator position is allowed to reach, and how it behaves when video is routed to it. Everything else in this section configures one piece of a seat; this is the view of the seat itself.
| Command Type | DisplayNet |
| Minimum Version | 5.0 |
list and show report seats; diagnose explains why one is not working; desk and multiview control what a seat may connect to; follow controls whether routing video to the seat also hands it keyboard and mouse.
Usage
kvm workstation list
kvm workstation show <remote_id>
kvm workstation diagnose <remote_id>
kvm workstation desk add|remove <remote_id> <desk>
kvm workstation desk list <remote_id>
kvm workstation multiview add|remove <remote_id> <config>
kvm workstation multiview list <remote_id>
kvm workstation follow <remote_id> on|off|default
kvm workstation follow default on|off
kvm workstation follow
Subcommands
| Subcommand | Description |
|---|---|
list | One row per seat: the configuration that wins for it, and whether its desk and multiview availability are restricted. Includes seats that have been configured but are not currently powered on. |
show | One seat in full: resolved configuration and its contents, availability lists, follow policy, HID auto-connect, and mouse sensitivity. |
diagnose | Why this seat's keyboard, mouse or control surface is not working, in plain language. Read-only. See Diagnosing a seat. |
desk | Which desks this seat may connect to. See Availability. |
multiview | Which multiview configurations this seat may aim at itself. See Availability. |
follow | Whether routing a source to this seat also gives it keyboard and mouse. See KVM follows video. |
Configuring a seat before it exists
Anything that stores configuration accepts a seat that is not present. An integrator racking a room can set it up from a plan and power it on later; the settings apply the moment the receiver appears. That covers desk, multiview and follow here, and equally kvm streamdeck bind, dial bind, and the kvm config button and dial verbs.
Anything that talks to the hardware still needs the device online: reset, repaint, status, and the diagnostic probes. There is nothing to send a report to otherwise, and they say so:
Device '6cdffb00f077' is not currently present — powered off, or not yet on the network.
This command talks to the hardware, so it needs the device online.
(Configuration commands accept a seat that is not present.)
list includes absent seats with "Present": false so pre-configuration is visible rather than write-only. show reports a seat that has either hardware or stored configuration, and errors only when it has neither.
Name a not-yet-present seat by its device id, not its name
A seat that is present can be named either way. A seat that is not present can only be named by its device id, the 12-hex-digit form, e.g. 6cdffb00f077.
A name is a lookup into the table of discovered devices. While the seat is absent there is nothing to look it up in, so a name cannot be turned into the key a binding is stored under, and a binding stored under the wrong key is accepted, visible in kvm config show, and never fires. Rather than store that, the command is refused:
'TradingDesk1' is not a known device, and is not shaped like a device id.
Use the seat's name while it is on the network, or its 12-hex-digit device id
to configure it before it is powered on.
A device id is stable, so a binding stored under one attaches to the seat the moment it appears.
Diagnosing a seat
kvm workstation diagnose <remote_id>
When someone reports "the keyboard doesn't work at this position", run this first. It is the one command that answers the question. Everything else inspects a single layer and leaves you to join them up.
It is read-only: nothing is re-paired, reset or repainted, so it is safe to run on a live room in the middle of an event. It also works on a seat that is powered off, which is the most common case; the answer is then "this seat is not on the network", not an error.
Read Findings first
Findings is a list of plain-language sentences, and it is the answer. The rest of the response is the evidence behind it, for when you want to check the reasoning or hand it to someone else.
Findings are ordered causes before consequences. A seat that is switched off also has no mouse, no route and no configuration in effect; reporting all four would bury the only one worth reading, so a finding that fully explains the ones below it is the only one shown. Where a command fixes the problem, the finding names it.
Reading the evidence
| Field | What to look at |
|---|---|
Pairing.Paired | Whether the seat's USB extender is actually paired. This is a live state, not "an extender exists". A seat that has dropped keeps its entry. |
Pairing.AutoConnect | If this is false and Paired is false, that is the cause. See kvm hid. |
Devices | What the receiver currently has mounted, with the product name of each. |
Slots | Which mounted device the keyboard and mouse resolve to. -1 means none of that type. |
Slots.Collapsed | Both roles on one device. Normal for a combined keyboard-and-trackpad, and not on its own a fault. |
Routed | false means the seat controls no host, so input has nowhere to go however healthy the rest is. |
Storms | Descriptor-handshake thrashing. See below. |
Events | Recent per-seat history, oldest first, with SecondsAgo relative to the call. |
EventsRecorded | Everything that has happened, including events already aged out of Events. A large number with a short list is a busy seat, not a quiet one. |
Config | The configuration this seat resolves, or null. A seat with none has no macros and a blank control surface. |
A storm is the USB descriptor handshake repeating dozens of times a second. Every occurrence investigated so far has turned out to be a physical fault, most often a failing USB hub, then a marginal cable.
LargestBurst is how big the burst got, and larger bursts have meant longer input outages. Try the keyboard and mouse directly in the receiver, bypassing any hub, before looking at configuration.
This history is kept regardless of the server's logging level, so it is already there when someone finally asks. You do not need to reproduce the fault with logging turned up first.
Per-seat settings
Five settings live on the seat itself rather than in a configuration. They are set by four different commands, but they behave identically.
| Setting | Set it | Reset it |
|---|---|---|
| KVM follows video | kvm workstation follow <rx> on|off | kvm workstation follow <rx> default |
| HID auto-connect | kvm hid enable|disable <rx> | kvm hid clear <rx> |
| Mouse sensitivity | kvm sensitivity <rx> <factor> | kvm sensitivity <rx> default |
| Info-bar branding | kvm streamdeck infobar <rx> on|off | kvm streamdeck infobar <rx> default |
| Deck brightness | kvm streamdeck brightness <rx> <0-100> | kvm streamdeck brightness <rx> default |
Resetting removes the stored value rather than writing the default. The seat then follows any future change to that default, instead of being pinned to whatever it happens to be today. Resetting a seat that has no stored value is a no-op, not an error, so cleaning up after a decommissioned seat never needs a check first.
Each is reported by show with both a value and a HasOverride flag. The flag is the part that matters when you are auditing: a seat set to exactly the default reads identically to one that was never touched, and only the flag tells them apart.
All five accept a seat that is not present, like everything else that stores configuration. A seat carrying only these settings, with no bindings, no availability and no assigned config, still appears in list with "Present": false, so a setting applied ahead of the hardware is visible rather than write-only.
kvm workstation list shows every seat with any stored configuration, including ones whose hardware has never been seen. A row with "Present": false and nothing else configured is usually either a seat that has not been racked yet or an identifier that was mistyped once. show will tell you which settings it carries, and the reset commands above remove them.
Availability
By default every desk connects to every seat, and every multiview configuration is controllable from every seat. Availability narrows that, for a trading desk that should only ever see its own two desks, a lobby seat that should not be able to grab the operations wall.
An empty allow-list means unrestricted, not "nothing allowed". This is what makes the feature safe to add to a running system: no existing seat loses anything until someone deliberately adds a first entry to it. show reports this as "Restricted": false.
Adding the first entry to a seat switches it to restricted, and from then on only what is listed is reachable. Removing the last entry returns it to unrestricted.
An allow-list controls what an operator can aim at a seat. It is not an access-control mechanism and does not stop a multiview that was configured to bring control with it (autoconnectkvm) from doing so. Viewing a multiview at one seat while viewing and controlling it at another is a legitimate setup.
Desks and multiviews are tracked by identity, not by name, so renaming one does not break the seats that reference it, and deleting one removes it from those seats cleanly.
KVM follows video
By default, routing a source to a seat gives it video only. Turn follow on and the same route also hands that seat the source's keyboard and mouse, with no second command and no script.
This seat now drives whatever it displayskvm workstation follow trading_desk_1 on
From then on, any connect to that seat carries control with it, whether it came from a Stream Deck button, the source selector, the Controller, or an API client. They all call connect; nothing else needs to know.
Seat-level scope
Whether a station drives what it displays is a property of the station. A source has no idea who is watching it, and the same source is often on one operator's desk and three overview displays at once.
Default and states
follow ships off, and the system-wide default is settable separately from each seat:
| Command | Effect |
|---|---|
kvm workstation follow default on | The house default for seats that have not been set individually. |
kvm workstation follow <rx> on | off | An override for this seat that always wins over the default. |
kvm workstation follow <rx> default | Removes the override so the seat inherits again. |
A seat set to off stays off when the default is later turned on. That is the difference between explicitly off and not set, and it is why off and default are separate. show reports both the effective answer and whether it was inherited.
kvm workstation follow with no arguments reports the default and every seat that overrides it. Seats that inherit are not listed; only deliberate configuration is.
Overriding one route
Two options on connect override the policy for a single call:
| Option | Effect |
|---|---|
nokvm | Route video only, even on a seat with follow on. |
withkvm | Carry control, even on a seat with follow off. |
Put this on the seat's screen without taking its keyboardconnect hdmi camera_1 trading_desk_1 nokvm
Cases with no effect
A follow is skipped silently, rather than treated as an error, when there is nothing to hand over:
- the source has no USB host of its own (most sources are video and nothing else);
- the destination is a plain display rather than a seat.
withkvm does not change either case. It overrides policy, and no policy can give a keyboard to a device with nowhere to plug one in.
If a follow is attempted and genuinely fails, whether a locked device or a receiver that has gone away, the video route still stands and a kvm_autoconnect_warning notification reports why. A KVM problem never rolls back a route an operator can already see on screen.
Desks
A desk connect routes its monitors and then establishes one MultiDevice session across the desk's controllable monitors. That session is what gives the seat multi-head control, so desk routing deliberately does not trigger per-monitor follows. The desk's own controllable setting remains the single place that rule is applied. See kvm desk.
Split transmitters
Normally a source is its own keyboard and mouse: a DNS transmitter carries the HDMI input and the USB host on the same device, so no configuration is needed and none exists. Where a deployment separates the video transmitter from the USB transmitter, tell DisplayNet which pairs with which using kvm hid source.
Rapid switching
Several routes to one seat in quick succession settle into a single session on the last source routed, rather than walking the seat through every source on the way.
Examples
See every seat at a glancekvm workstation list
Everything about one seatkvm workstation show trading_desk_1
Find out why a seat's keyboard has stopped workingkvm workstation diagnose trading_desk_1
Restrict a seat to two deskskvm workstation desk add trading_desk_1 morning_desk
kvm workstation desk add trading_desk_1 evening_desk
Return a seat to unrestrictedkvm workstation desk remove trading_desk_1 morning_desk
kvm workstation desk remove trading_desk_1 evening_desk
Turn on KVM-follows-video everywhere except the lobbykvm workstation follow default on
kvm workstation follow lobby_display off
Return value
kvm workstation show
kvm workstation show trading_desk_1{
"status": "SUCCESS",
"request_id": null,
"result": {
"kvm_workstation": [
{
"RemoteId": "6cdffb00f077",
"Name": "trading_desk_1",
"Present": true,
"HidRemote": true,
"Config": { "Name": "Global", "Macros": 3, "Buttons": 8, "Dials": 0 },
"Desks": { "Restricted": false, "Allowed": [] },
"Multiviews": { "Restricted": false, "Allowed": [] },
"Follow": { "Enabled": false, "Inherited": true },
"Hid": { "AutoConnect": true, "HasOverride": false },
"Sensitivity": { "Factor": 1.0, "HasOverride": false },
"InfoBar": { "Enabled": true, "HasOverride": false },
"Brightness": { "Value": 100, "HasOverride": false }
}
]
},
"error": null
}
HidRemote reports whether this receiver can actually act on its configuration. A seat can hold macros and buttons without being an HID remote extender, in which case none of them will ever fire, and this field says so.
Every per-seat setting reports its effective value alongside a flag saying whether this seat set it: HasOverride, or Inherited for Follow. See Per-seat settings.
kvm workstation diagnose
A seat whose mouse has stopped working:
kvm workstation diagnose trading_desk_1{
"status": "SUCCESS",
"request_id": null,
"result": {
"kvm_workstation_diagnose": [
{
"RemoteId": "6cdffb00f077",
"Name": "trading_desk_1",
"Present": true,
"Pairing": { "Paired": true, "State": "linked", "AutoConnect": true },
"Devices": [
{ "Index": 1, "Product": "Keychron K10 Pro", "Mouse": false, "Keyboard": true, "ControlSurface": false },
{ "Index": 2, "Product": "Stream Deck XL", "Mouse": false, "Keyboard": false, "ControlSurface": true }
],
"Slots": { "Mouse": -1, "Keyboard": 1, "Collapsed": false },
"Routed": true,
"Storms": { "Count": 3, "LargestBurst": 107, "LastSecondsAgo": 412.6 },
"Events": [
{ "SecondsAgo": 604.1, "Kind": "DeviceSetChanged", "Detail": "0:mouse;1:kb;2:deck" },
{ "SecondsAgo": 412.6, "Kind": "DescriptorStorm", "Detail": "107 answers in 1s" },
{ "SecondsAgo": 411.9, "Kind": "DeviceSetChanged", "Detail": "1:kb;2:deck" }
],
"EventsRecorded": 3,
"Config": "Global",
"Findings": [
"No mouse is resolved for this seat, so pointer input will not be delivered. Check the mouse is plugged into the receiver.",
"The USB descriptor handshake has thrashed 3 times since the engine started (largest burst: 107 in one second), most recently within the last hour. Every occurrence of this investigated so far has been a physical fault — most often a failing USB hub, then a marginal cable. Try the keyboard and mouse directly in the receiver, bypassing any hub.",
"A control surface is attached and a configuration applies to this seat. If its keys are blank or wrong, check the buttons bound for THIS seat with: kvm config show <config>"
]
}
]
},
"error": null
}
The Events list tells the story the findings summarise: the mouse was present, a storm hit, and the device set came back without it.
A healthy seat returns a single finding:
"Findings": [
"No problems found. This seat is paired, has a keyboard and mouse, is routed to a source, and has a configuration in effect."
]
kvm workstation follow
kvm workstation follow{
"status": "SUCCESS",
"request_id": null,
"result": {
"kvm_workstation_follow": [
{
"Default": true,
"DefaultIsSet": true,
"Overrides": [
{
"RemoteId": "6cdffb00f099",
"Name": "lobby_display",
"Present": true,
"Follow": false
}
]
}
]
},
"error": null
}
DefaultIsSet distinguishes a default someone chose from the shipped default of false.
Errors
Error response{
"status": "ERROR",
"request_id": null,
"result": null,
"error": {
"message": "<description>",
"reason": "KVM API ERROR"
}
}
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 |
|---|---|---|
workstation | kvm_workstation | action [args]* |
workstation_desk_add | kvm_workstation_desk_add | remote_id desks |
workstation_desk_clear | kvm_workstation_desk_clear | remote_id |
workstation_desk_list | kvm_workstation_desk_list | remote_id |
workstation_desk_remove | kvm_workstation_desk_remove | remote_id desks |
workstation_follow | kvm_workstation_follow | [target] [value] |
workstation_list | kvm_workstation_list | — |
workstation_multiview_add | kvm_workstation_multiview_add | remote_id configs |
workstation_multiview_clear | kvm_workstation_multiview_clear | remote_id |
workstation_multiview_list | kvm_workstation_multiview_list | remote_id |
workstation_multiview_remove | kvm_workstation_multiview_remove | remote_id configs |
workstation_show | kvm_workstation_show | 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.
Every action except diagnose has a typed operation taking named fields, and a missing or unknown field is rejected before the command runs.
diagnose runs through kvm_workstation, which takes a raw grammar line: action and args, spelled as under Usage above.
See also
connect: the routing command thatfollowattaches to, and wherenokvm/withkvmare givenkvm hid: HID auto-connect, and the split-transmitter overridekvm config: the configuration a seat resolveskvm desk: multi-monitor seats