Skip to the content.

kvm-it is a tool a technician uses eight times in a row, hands busy, in front of a machine that might be at a BIOS screen. The UX bar is “never make me think about the tool”.

  1. Zero-step reconnect. Moving the cables to the next machine is the whole workflow. BLE, capture and (later) trust all re-establish themselves; the UI shows state, it does not ask for action.
  2. State is always visible, never ambiguous. One row of colour-coded chips: BLE link, target USB mounted, capture-card signal, input capture on/off. Green is working, amber is in progress, red is broken, grey is idle. Capture-active is unmistakable (red frame + a chip naming the release chord).
  3. Safe by default. Releasing capture, losing focus, reconnecting or quitting sends release-all. The release chord is never forwarded to the target.
  4. Secrets are first-class. Masked, never logged, per-run by default (see security.md). Typing a secret shows progress, never the text.
  5. Anything repeatable is one click (macro buttons, scripts) and anything running is interruptible in one keypress, leaving the target with nothing held down.
  6. Honest feedback. If a command was dropped, the BLE link is degraded, or a script step could not be confirmed, say so plainly — a KVM that silently mistypes a password is worse than none.
  7. Fast to first pixel. Last-used capture device and mode are remembered; the preview appears before the user has found the mouse.

Window layout (0.2.0)

The picture is the window. A single top bar holds everything else:

The window: chips and buttons along the top, the picture filling the rest

The script library, with a script’s preview, variables and the Run / Dry run / Abort buttons; and the run log strip that stays along the bottom after a (dry) run:

The Scripts popup: the script list, a preview of the selected script (steps, typed characters, secrets) and Run, Dry run, Abort The run-log strip along the bottom of the window after a dry run: Script finished, with the steps listed

The pictures on this site are of the real app (0.3.0, Windows 11) with a synthetic demo target in place of a real machine’s screen, so nothing private is ever on show.

Scripting and replay

Goal (from the product owner): bundle replayable scripts, DuckyScript-style, to drive setup flows such as Windows OOBE, installers and BIOS settings.

Design decision

Chosen: a small, structured, declarative script format run by the desktop app (controller side), with a DuckyScript-compatible text importer, plus screen-aware wait steps. Alternatives rejected:

Script file (native, TOML)

name = "Windows 11 OOBE — local account"
format = 1
description = "Region → keyboard → network → local account"

[vars]
wifi_ssid = { prompt = "Wi-Fi SSID" }
wifi_pass = { prompt = "Wi-Fi password", secret = true }   # asked at run time, never saved
user      = { default = "tech" }

[[steps]]
wait_for = { screen = "oobe-region.png", timeout = "90s", threshold = 0.9 }  # closed loop
[[steps]]
key = "ENTER"
[[steps]]
text = ""
[[steps]]
secret_text = ""
[[steps]]
chord = ["CTRL", "SHIFT", "F10"]
[[steps]]
delay = "1s"
[[steps]]
confirm = "Is the desktop showing? Continue?"   # human gate

Step kinds: text, secret_text, key, chord, delay, repeat, wait_for (screen match, or “screen stopped changing for N s”, with timeout), confirm (human gate), comment. Variables via ``. No loops over arbitrary expressions, no shell, no file or network access from scripts.

DuckyScript import

kvm-it script import payload.txt converts the common subset (REM, STRING, STRINGLN, DELAY, DEFAULT_DELAY, ENTER/TAB/arrows, GUI/CTRL/ALT/SHIFT combos, REPEAT) into the native format and lists anything it could not translate rather than guessing. Layout-dependent characters go through the selected keyboard layout abstraction, not the payload’s assumptions.

Run-time UX and safety

Status (0.1.0)

Built and host-tested: native format, variables, text/secret_text/key/chord/delay/repeat/click/ move/confirm, wait_for (reference image or screen-stable), DuckyScript import, dry-run, preview with command warnings, abort-releases-everything. Built-in scripts are templates; none has been run against a real OOBE. Screen matching has only been tested on synthetic frames.

Milestone placement

Native step engine and text/key/chord/delay/repeat land with the macro system (Milestone 10); the screen-aware wait_for/confirm, DuckyScript importer and dry-run follow once video capture (Milestone 7) and the GUI (Milestone 8) exist. Nothing here requires a protocol change: scripts compile to the same key/mouse/release-all messages the live path uses.

Unverified assumptions