Set up a local development environment and run the full KVM simulation without hardware.
| Rust | Stable + ESP target | Firmware builds and native simulation binaries |
| uv | Python package manager | All Python execution uses uv with inline script metadata |
| mise | Task runner | Orchestrates all dev/build/test tasks |
| Node.js | v20+ | Astro web UI dev server and site builds |
| QEMU | qemu-system-x86_64 | VM-based full simulation with VNC display |
| socat | Virtual serial pairs | Simulates the UART link between Duo S and ESP32 |
# Arch/Manjaro sudo pacman -S rust uv qemu-full socat nodejs npm # Install mise curl https://mise.run | sh # Clone and enter the project git clone https://gitlab.daringbit.com/josh/kvm-board.git cd kvm-board
The project follows a simulation-first approach. You can run the entire KVM pipeline locally without any hardware, using QEMU as the target machine.
Starts QEMU VM + VNC video + QMP HID injection + KVMD backend + go2rtc WebRTC + Astro dev server. This is the primary development command.
mise run kvmd:dev # Pipeline: # Browser --> KVMD(:8080) --> UART --> HID Bridge --> QMP --> QEMU VM # Browser <-- WebRTC(go2rtc :1984) <-- FFmpeg <-- VNC <-- QEMU VM # # Frontend dev: http://localhost:4321 (Astro with Vite proxy) # Backend: http://localhost:8080 # Video: http://localhost:1984
Runs the full KVM pipeline with production-built frontend. No hot reload.
mise run kvmd:vm
Minimal simulation with virtual serial pair and HID protocol logger. No QEMU, no video.
mise run kvmd:sim
Runs native x86 unit tests for the protocol parser and HID bridge logic. Test vectors are generated from the Python reference implementation.
mise run firmware:test # Regenerate test vectors from Python protocol.py mise run firmware:vectors
8 tests covering packet construction, parsing, checksum validation, and edge cases.
cd software/sim && python -m pytest -v
19 tests covering HID dispatch, ATX control, server routes, and end-to-end WebSocket flows.
cd software/kvmd && python -m pytest -v
The KVM web interface is built with Astro + Tailwind + DaisyUI. During development, Vite proxies API and WebSocket requests to the KVMD backend.
# Development (hot reload) cd software/kvmd/web && npm run dev # Production build cd software/kvmd/web && npm run build
The production build outputs static files that KVMD serves directly. The mise run kvmd:dev command starts both the backend and the Astro dev server together.
kvm-board/ ├── firmware/ │ └── esp32-hid-rs/ Rust ESP32-S3 firmware (TinyUSB HID) │ ├── kvm-protocol/ UART protocol crate (mirrors protocol.py) │ ├── kvm-hid/ USB HID composite device crate │ └── kvm-sim/ Native simulation binaries (kvm-bridge, kvm-sim) ├── software/ │ ├── kvmd/ KVM daemon (Python, aiohttp) │ │ ├── kvmd/ Server, HID dispatch, ATX control │ │ ├── web/ Astro + Tailwind + DaisyUI frontend │ │ └── run_vm.py Entry point for VM simulation mode │ ├── sim/ Shared protocol module + simulation mocks │ │ └── protocol.py UART protocol reference implementation │ └── buildroot/ Duo S Linux image overlay │ └── overlay/ Root filesystem overlay (config, init scripts) ├── hardware/ KiCad 10 project (hierarchical schematics) │ ├── kvm-carrier.kicad_pro │ ├── kvm-carrier.kicad_pcb │ └── *.kicad_sch 7 schematic sheets ├── site/ Project website (this site) ├── docs/ Design specs and plans │ ├── design-aesthetic.md │ └── superpowers/ Feature specs and implementation plans ├── scripts/ Build and automation scripts └── mise.toml Task definitions