plugin-jetkvm
| Version | 2026.258.1200 |
| Repo | box/github.com/opencharly/plugin-jetkvm:v2026.267.2212 |
| Plugin | yes — see the plugin reference |
OUT-OF-TREE charly plugin serving the jetkvm IP-KVM verb AND the
kind: jetkvm device entity — a standalone Go module (go.mod +
cmd/serve) that drives a JetKVM device (https://jetkvm.com) without a
browser, over JetKVM’s own WebRTC control plane: local login
(POST /auth/login-local) -> signaling websocket
(/webrtc/signaling/client) -> the “rpc” JSON-RPC 2.0 data channel, the
binary “hidrpc” input channel, and the H.264 video track decoded to a
PNG by ffmpeg. It is served OUT-OF-PROCESS over go-plugin gRPC via the
charly plugin SDK (github.com/opencharly/sdk); charly’s loader fetches
this candy’s repo, go-builds the provider binary on the HOST, and
connects it via LocalTransport, so the device wire lives HERE, out of
charly’s core check surface.
READ-ONLY BY DEFAULT. The device is a physical appliance and is NOT
disposable, so every mutating method (keyboard/pointer input, power and
ATX/DC control, virtual media, USB gadget, config writes, reboot,
firmware update, factory reset) requires the explicit
allow_control: true input; without it a mutating method reports a
skip naming the gate rather than acting. factory-reset additionally
requires it and is never exerciseable from a bed.
The verb’s entire authoring surface lives in this plugin’s own
#JetkvmInput (schema/jetkvm.cue), which the host splices onto the base
and validates every authored jetkvm: step against; the plugin
self-evaluates the shared stdout/stderr/exit_status matchers and the
artifact validators (sdk.VerbVerdict / sdk.RunArtifactValidators), so it
owns the verdict exactly like every other out-of-process verb.
CONSOLE INSTALLER. Beyond raw input, the plugin serves two higher-level
capabilities: the read-only ocr method (capture + tesseract on the
host + assert text — the wait-for-screen primitive), and the mutating
install method, a configurable console-installer DRIVER that connects
ONCE and walks an ordered steps: recipe, OCR-waiting for each
screen-unique anchor before sending its key/type/combo input. The
recipe is generic DATA supplied by a kind: jetkvm device entity, so
one plugin drives any text-console installer with no per-distro code.
The OCR wait is the reason it opens one session: a per-step connection
would pay a fresh WebRTC handshake for every screen.
Client reuse, not reinvention: the WebRTC/HID wire is vendored from LeeroyDing/jetkvm-mcp (MIT) and conallob/mcp-jetkvm (BSD-3) under internal/kvmclient (see third_party/NOTICE) and rides the SAME github.com/pion/webrtc/v4 stack the JetKVM firmware itself uses. The session/artifact/credential plumbing is charly’s own (sdk.VerbVerdict, sdk.LandArtifact, sdk.RequireModifiers), never a second implementation.
Acceptance plan
Section titled “Acceptance plan”This candy’s plan: — the runnable spec charly check executes against a live deployment. check: steps are idempotent probes; run: steps change state.
| Intent | Step |
|---|---|
check |
the plugin ships its self-contained CUE schema and provider entrypoint (the files the host reads over Describe and host-builds) — a deterministic probe that fails if either is missing |
check |
the verb and kind capabilities are declared together, so a jetkvm step dispatches AND a kind jetkvm entity is recognized at parse (a probe that fails if either declaration is dropped) |
check |
the jetkvm verb dispatches through the provider registry and reports its documented no-device skip — proving the out-of-process plugin was host-built, connected, and ran its verdict path (a step that FAILS if the verb is unregistered or the module will not build/serve) |