pikvm-cli
v1.0.1
Published
A Node.js CLI that lets an LLM agent drive a PiKVM device as a single chained command.
Readme
pikvm-cli
A Node.js CLI that lets an LLM agent drive a PiKVM device (mouse, keyboard, screenshots, OCR) as a single chained command. The CLI speaks the PiKVM HTTP and WebSocket protocols so the LLM doesn't have to.
Status: v1 released. See
SPEC.mdfor the full vision andprd/for the unit-of-work breakdown.
Install via npm
npm i -g pikvm-cliOr try without installing:
npx pikvm-cli --helpRequires Node.js 20 or later.
Setup
The recommended setup uses the interactive login wizard:
kvm-cli login
# Prompts:
# PiKVM host URL [https://pikvm.local]: https://jckvm.cantonese.science
# Username: admin
# Password: ••••••••
# Trust self-signed TLS cert? [y/N]: y
# Saved to ~/.pikvm-cli/configAfter login, subsequent commands auto-load the config:
kvm-cli snapshot ./s.jpg
kvm-cli click 500 300
kvm-cli type "hello world"Setup (alternative: env vars)
For CI, headless systems, or agents that pass credentials programmatically:
export KVM_HOST="https://jckvm.cantonese.science" # or your PiKVM
export KVM_USER="your_user"
export KVM_PASSWORD="your_password"
export KVM_INSECURE=1 # if your KVM uses a self-signed certOr pass as CLI flags on each invocation:
kvm-cli --host https://jckvm.local --user admin --password secret --insecure snapshot ./s.pngFlags override env vars. Env vars override defaults (https://pikvm.local, en-us keymap, 10s timeout).
Credential security: Credentials are stored in plaintext in ~/.pikvm-cli/config with mode 0o600 (owner read/write only). On a multi-user system, treat this file like ~/.netrc or ~/.aws/credentials.
OCR dependencies
The ocr verb shells out to Tesseract + Python PIL. Install once:
# Debian/Ubuntu
sudo apt install -y tesseract-ocr python3-pil
# Verify
tesseract --version
python3 -c "from PIL import Image; print('ok')"Quick start
# 1. Take a screenshot and save it locally
kvm-cli snapshot ./screen.jpg
# -> {"ok":true,"path":"./screen.jpg","w":1920,"h":1080}
# 2. Type text into the focused input
kvm-cli type "hello world"
# -> {"ok":true,"n":11}
# 3. Move the mouse and click (packed coord form)
kvm-cli click x960y540
# -> {"ok":true}
# 4. Send a keyboard shortcut (AHK syntax: ^ = Ctrl, + = Shift, ! = Alt, # = Win)
kvm-cli keys "^c"
# -> {"ok":true}
# 5. Chain everything in one command — one login, one connection
kvm-cli snapshot ./a.jpg type "user@host" keys "Tab" type "secret" keys "Return"
# -> {"ok":true,"n":9} (the last verb's result)
# 6. OCR the current screen
kvm-cli ocr --preprocess
# -> {"ok":true,"path":"/tmp/pikvm-cli-xxx.jpg","ocr":"/tmp/pikvm-cli-xxx_ocr.txt","text":"…"}
# 7. OCR a local image file
kvm-cli ocr ./local.png --lang eng --psm 6The move and click verbs also accept positional coords:
kvm-cli click 640 360 right # click (640, 360) with the right mouse buttonVerb reference
| Verb | Args | Effect |
|---|---|---|
| snapshot | <path> | GET /api/streamer/snapshot → write JPEG to <path> |
| type | "<text>" | POST /api/hid/print (paste-as-keys, stable) |
| move | <coords> | Move absolute mouse, no click |
| click | <coords> [button] | Move + click (default left; also right, middle) |
| keys | "<chord>" | Send a key or chord (AHK modifier syntax) |
| ocr | [path] | Snapshot (if path omitted) → run Tesseract OCR → return text |
<coords>: x100y200 (packed, one token) or 100 200 (positional, two tokens). The CLI remaps to int16 internally.
<chord>: AHK-style modifiers ^ + ! # then a key name. Examples: ^c, ^+Tab, !F4, #r, Enter, F5.
Global flags
| Flag | Env var | Default | Notes |
|---|---|---|---|
| --host | KVM_HOST | https://pikvm.local | KVM base URL |
| --user | KVM_USER | (required) | login user |
| --password | KVM_PASSWORD | (required) | login password |
| --insecure | KVM_INSECURE=1 | false | skip TLS verify |
| --timeout | KVM_TIMEOUT | 10 | per-action timeout (sec) |
| --keymap | KVM_KEYMAP | en-us | used by type |
| --human | KVM_HUMAN=1 | false | pretty text output instead of JSON |
| --debug | KVM_DEBUG=1 | false | verbose debug log to stderr |
Management commands
kvm-cli login # Interactive login wizard (or --host/--user/--password flags)
kvm-cli logout # Delete ~/.pikvm-cli/config
kvm-cli whoami # Show effective config and which source each value came from
kvm-cli whoami --json # JSON output (for agents and CI)
kvm-cli doctor # Check system dependencies (Node, tesseract, python3, Pillow)
kvm-cli doctor --json # JSON output for CI
kvm-cli install-skill # Install SKILL.md for AI agents (pi, Claude Code, Cursor, Copilot)
kvm-cli install-skill --dry-run # Show what would be installedkvm-cli whoami
Shows where each config value comes from (helpful for debugging "why is it connecting to the wrong KVM?"):
$ kvm-cli whoami
PiKVM CLI effective configuration
Config file: ~/.pikvm-cli/config
host https://jckvm.cantonese.science (config)
user admin (env)
password *** (config, length=8)
insecure true (flag)
keymap en-us (default)
timeout 10 (default)Output
Default: minimal JSON to stdout. One verb → one line.
{"ok":true}
{"ok":true,"path":"./s.png","w":1920,"h":1080}
{"ok":true,"n":5}
{"ok":true,"path":"./s.png","ocr":"./s_ocr.txt","text":"…"}
{"ok":false,"err":"auth"}Errors are always JSON to stderr, with a stable err code. See src/lib/errors.ts for the full list.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | runtime error (see err field) |
| 2 | bad CLI usage |
| 130 | SIGINT |
For LLM agents
This CLI is designed to be driven by an LLM agent. The SKILL.md file teaches an agent how to use it.
Install the skill for your agent:
kvm-cli install-skillThis creates ~/.pikvm-cli/SKILL.md and symlinks it for detected agents (pi, Claude Code, Cursor, Copilot).
Note: kvm-cli login requires a TTY for password input. Agents typically pass credentials via env vars or --user/--password flags passed by the calling process.
Install from source (for contributors)
git clone https://github.com/chihangc/pikvm-llm-reader.git
cd pikvm-llm-reader
npm install
npm run build
npm link # makes `kvm-cli` available globallyTests
npm test # unit + integration (mock KVM)
npm run test:watch # watch mode
npm run test:cov # with coverage
npm run test:e2e # E2E against the real KVM (requires KVM_E2E=1 + real credentials)Safety
- No destructive actions (ATX power, MSD write, HID reset) are exposed. The CLI is read-only-and-input-only against the host.
- Self-signed certs require an explicit
--insecureflag orKVM_INSECURE=1. - The CLI never writes secrets to disk except via
kvm-cli loginwhich stores them in~/.pikvm-cli/configwith mode0o600.
License
MIT. See LICENSE.
