kvmctl is a Go CLI and MCP server for KVMD-compatible KVM devices such as GLKVM. It provides a verified KVMD REST client plus safe, agent-friendly workflows for device status, screenshots, HID control, target selection, recovery, OCR-assisted actions, and immutable workflows.
Status: live-verified against KVMD 4.82. Read-only API and capability checks were exercised against a real device. Mutating hardware actions remain explicitly gated and were not used during acceptance.
Install the CLI and the companion agent skill:
npx -y @mvanhorn/printing-press-library install kvmctlCLI only:
npx -y @mvanhorn/printing-press-library install kvmctl --cli-onlySkill only:
npx -y @mvanhorn/printing-press-library install kvmctl --skill-onlyFrom the published Printing Press catalog:
go install github.com/mvanhorn/printing-press-library/library/devices/kvmctl/cmd/kvmctl-pp-cli@latest
go install github.com/mvanhorn/printing-press-library/library/devices/kvmctl/cmd/kvmctl-pp-mcp@latestTo build this repository directly:
make build-allDownload the CLI or MCP server archives from the kvmctl releases. Archives are published for macOS, Linux, and Windows on amd64 and arm64 where supported. Verify checksums.txt before installing a downloaded binary.
KVMD credentials are supplied through the environment or the CLI's private credential store. Never commit credentials or put them in a shell history.
export KVMCTL_KVMD_TOKEN="<your-kvmd-token>"
kvmctl-pp-cli doctor --jsonThe persisted form is private to the local user:
printf '%s\n' "$KVMCTL_KVMD_TOKEN" | kvmctl-pp-cli auth set-token
kvmctl-pp-cli doctor --jsonThe token is stored in credentials.toml under the resolved data directory, not in config.toml.
Start with read-only checks:
kvmctl-pp-cli doctor --json
kvmctl-pp-cli capabilities --json
kvmctl-pp-cli info --json
kvmctl-pp-cli hid get-state --jsonUse agent mode when invoking from an automation tool:
kvmctl-pp-cli info --agent
kvmctl-pp-cli semantic capabilities --agentThe live acceptance probe confirmed an authenticated KVMD device, its capabilities, and online keyboard/mouse HID state. The probe did not send keyboard or mouse input.
- Read-only status, capability, screenshot, and inspection commands can run normally.
- Commands that can affect a KVM, host, target, or workflow require explicit confirmation and/or write policy.
--agentselects machine-readable output; it does not imply--yes.- Use
--dry-run --agentbefore an unfamiliar mutating command. - Do not use reboot, target switching, OTG, HID input, or workflow execution against production hardware without identifying the target and reviewing the command's help.
- OCR commands require real image bytes. The CLI never invents screenshots, OCR text, coordinates, or hardware results.
Example dry run:
kvmctl-pp-cli semantic send-key --key Enter --dry-run --agentkvmctl-pp-cli capabilities --json
kvmctl-pp-cli info --json
kvmctl-pp-cli status --json
kvmctl-pp-cli screenshot --output ./screen.jpg
kvmctl-pp-cli hid get-state --jsonkvmctl-pp-cli keyboard --help
kvmctl-pp-cli mouse --help
kvmctl-pp-cli hid send-key --helpThese commands are write operations. Review the help, identify the target, and pass --yes only when the input is intentional.
The semantic surface exposes the Python oracle's operation catalog through stable evidence envelopes. Discover the available operations and their read/write policy at runtime:
kvmctl-pp-cli semantic capabilities --agent
kvmctl-pp-cli semantic snapshot --agent
kvmctl-pp-cli semantic verify --agent
kvmctl-pp-cli semantic host-identity --agentThe MCP server exposes the same structured semantic_dispatch surface for agents.
Use the purpose-built commands for the bounded observe → act → verify loop. They delegate only to the semantic core; they are not a planner and never infer a next UI action.
# Configure a local OCR command. It receives screenshot bytes on stdin.
export KVMCTL_OCR_COMMAND=tesseract
# Default protocol is Tesseract TSV. For a custom structured command, use JSON:
# export KVMCTL_OCR_PROTOCOL=json
kvmctl-pp-cli observe --agent
kvmctl-pp-cli act click-text "Advanced" --observation <observation-id> --yes --agent
kvmctl-pp-cli act press-key F10 --observation <observation-id> --yes --agent
kvmctl-pp-cli verify --expect-text "Save Changes" --agentobserve returns the OCR observation ID. Both actions require that exact --observation value and explicit --yes; the semantic core captures the screen again and refuses a stale, unavailable, ambiguous, or non-matching observation. verify always captures a new observation and checks one exact high-confidence text match. KVMCTL_OCR_PROTOCOL=json selects the strict JSON OCR protocol expected by a custom configured command. These commands have automated HTTP/OCR fixtures only; no live BIOS interaction is claimed.
For MCP, call semantic_dispatch with operation: "observe", "verify-text", "click-text", or "press-key". The tool schema describes the required arguments; mutating operations additionally need arguments.write_enabled: true and the MCP host must permit writes with KVMCTL_WRITE_ENABLED=1.
Workflows are loaded from JSON, listed deterministically, inspected with action values redacted, authorized once, and then executed only against the resolved target and revision.
kvmctl-pp-cli workflow-list --repository ./workflows.json --agent
kvmctl-pp-cli workflow-inspect --repository ./workflows.json --name safe-check --agent
kvmctl-pp-cli workflow-authorize --repository ./workflows.json --name safe-check --target <target> --agent
kvmctl-pp-cli workflow-execute --repository ./workflows.json --name safe-check --target <target> --yes --agentKeep workflow files free of passwords, tokens, private URLs, and machine-specific secrets.
kvmctl-pp-cli machines --help
kvmctl-pp-cli target-switch --help
kvmctl-pp-cli sequence --help
kvmctl-pp-cli workflow --helpThe implementation includes bounded verification, session-integrity checks, target locking, cancellation-safe recovery, and checkpointed host reboot support. Hardware-changing paths remain opt-in.
Every command supports the generated CLI's machine-output flags where applicable:
kvmctl-pp-cli info --json
kvmctl-pp-cli info --agent
kvmctl-pp-cli info --json --select ok,result
kvmctl-pp-cli info --dry-run --agent- JSON goes to stdout; errors go to stderr.
--agentexpands to JSON, compact output, no prompts, and no color.--selectlimits returned fields.--dry-runpreviews a request without sending it.- Exit codes distinguish usage, missing resources, authentication, API, rate-limit, and configuration failures.
Run kvmctl-pp-cli --help and kvmctl-pp-cli <command> --help for the current command tree rather than relying on a copied list.
The CLI separates configuration, durable data, runtime state, and cache files:
| Kind | Contents |
|---|---|
config |
settings, profiles, and config.toml |
data |
credentials.toml, SQLite data, cookies, and auth sidecars |
state |
persisted queries, jobs, journals, and learning state |
cache |
regenerable HTTP/cache files |
Resolution order is the per-kind variable, --home, KVMCTL_HOME, XDG variables, then platform defaults.
export KVMCTL_HOME=/srv/kvmctl
kvmctl-pp-cli doctor --jsonSupported environment variables include:
| Variable | Purpose |
|---|---|
KVMCTL_KVMD_TOKEN |
KVMD API credential |
KVMCTL_HOME |
relocate all local data kinds under one root |
KVMCTL_CONFIG_DIR |
override configuration directory |
KVMCTL_DATA_DIR |
override durable data directory |
KVMCTL_STATE_DIR |
override runtime state directory |
KVMCTL_CACHE_DIR |
override cache directory |
KVMCTL_NO_LEARN |
disable the local learning loop |
KVMCTL_OCR_COMMAND |
local OCR executable; it receives fresh screenshot bytes on stdin |
KVMCTL_OCR_PROTOCOL |
OCR response protocol (tesseract-tsv, default, or strict json) |
KVMCTL_WRITE_ENABLED |
MCP host policy gate; actions additionally require arguments.write_enabled: true |
KVMCTL_LOCK_DIR |
shared directory used to serialize physical device actions (default /tmp/kvmctl-locks) |
For MCP, put these variables in the host's MCP server environment. The MCP binary does not receive CLI flags.
Install and run the MCP server:
go install github.com/mvanhorn/printing-press-library/library/devices/kvmctl/cmd/kvmctl-pp-mcp@latest
kvmctl-pp-mcpExample Claude Desktop configuration:
{
"mcpServers": {
"kvmctl": {
"command": "kvmctl-pp-mcp",
"env": {
"KVMCTL_KVMD_TOKEN": "<your-kvmd-token>"
}
}
}
}The MCP server never receives secrets through committed configuration. Use the host environment or the CLI's private credential store.
Requirements: Go 1.26.6 or newer.
make test
make build-all
go vet ./...
git diff --checkThe release acceptance path additionally runs the official Printing Press validation and live dogfood checks. The live acceptance record is stored under .manuscripts/ and contains only redacted metadata and source fingerprints.
The original Python implementation used for parity comparison is maintained outside this repository and is not required at runtime.
SKILL.md— agent installation and operation protocolAGENTS.md— generated-tree and safety invariantsCHANGELOG.md— maintained by Printing Press release automation- CLI Printing Press
- Printing Press library
Generated by CLI Printing Press.