14 KiB
JetKVM Development Guide
Welcome to JetKVM development! This guide will help you get started quickly, whether you're fixing bugs, adding features, or just exploring the codebase.
Get Started
Prerequisites
- A JetKVM device (for full development)
- Go 1.24.4+ and Node.js 22.15.0
- Git for version control
- SSH access to your JetKVM device
- Audio build dependencies:
- New: The audio system uses a dual-subprocess architecture with CGO, ALSA, and Opus integration. The audio dependencies are automatically installed by the devcontainer or can be manually built using
.devcontainer/install_audio_deps.sh
.
- New: The audio system uses a dual-subprocess architecture with CGO, ALSA, and Opus integration. The audio dependencies are automatically installed by the devcontainer or can be manually built using
Development Environment
Recommended: Development is best done on Linux or macOS.
Apple Silicon (M1/M2/M3) Mac Users
If you are developing on an Apple Silicon Mac, you should use a devcontainer to ensure compatibility with the JetKVM build environment (which targets linux/amd64 and ARM). There are two main options:
- VS Code Dev Containers: Open the project in VS Code and use the built-in Dev Containers support. The configuration in
.devcontainer/devcontainer.json
is set to uselinux/amd64
platform. - Devpod: Devpod is a fast, open-source tool for running devcontainers anywhere. If you use Devpod, go to Settings → Experimental → Additional Environmental Variables and add:
DOCKER_DEFAULT_PLATFORM=linux/amd64
This ensures all builds run in the correct architecture.
- devcontainer CLI: You can also use the devcontainer CLI to launch the devcontainer from the terminal.
Important: If you're switching from an ARM64 devcontainer or updating the platform settings, you'll need to rebuild the devcontainer completely:
- In VS Code: Run "Dev Containers: Rebuild Container" from the command palette
- With devcontainer CLI: Use
devcontainer up --build
This approach ensures compatibility with all shell scripts, build tools, and cross-compilation steps used in the project.
If you're using Windows, we strongly recommend using WSL (Windows Subsystem for Linux) for the best development experience:
This ensures compatibility with shell scripts and build tools used in the project.
Project Setup
-
Clone the repository:
git clone https://github.com/jetkvm/kvm.git cd kvm
-
Check your tools:
go version && node --version
-
Set up the cross-compiler and audio dependencies:
make dev_env # This will install audio dependencies using .devcontainer/install_audio_deps.sh # It will build ALSA/Opus static libs in /opt/jetkvm-audio-libs using the buildkit from /opt/jetkvm-native-buildkit # # **Note:** This is required for the audio subprocess architecture. If you skip this step, builds will not succeed.
-
Find your JetKVM IP address (check your router or device screen)
-
Deploy and test:
./dev_deploy.sh -r 192.168.1.100 # Replace with your device IP
-
Open in browser:
http://192.168.1.100
That's it! You're now running your own development version of JetKVM, with bidirectional audio streaming using the dual-subprocess architecture.
Common Tasks
Modify the UI
cd ui
npm install
./dev_device.sh 192.168.1.100 # Replace with your device IP
Now edit files in ui/src/
and see changes live in your browser!
Modify the backend (including audio)
# Edit Go files (config.go, web.go, internal/audio, etc.)
./dev_deploy.sh -r 192.168.1.100 --skip-ui-build
Run tests
./dev_deploy.sh -r 192.168.1.100 --run-go-tests
View logs
ssh root@192.168.1.100
tail -f /var/log/jetkvm.log
Project Layout
/kvm/
├── main.go # App entry point
├── config.go # Settings & configuration
├── web.go # API endpoints
├── ui/ # React frontend
│ ├── src/routes/ # Pages (login, settings, etc.)
│ └── src/components/ # UI components
├── internal/ # Internal Go packages
│ └── audio/ # Audio Processing Layer (CGO, ALSA, Opus)
│ ├── native/ # CGO / Native code glue layer
│ ├── native/cgo/ # C files for the native library (HDMI, Touchscreen, etc.)
│ ├── native/eez/ # EEZ Studio Project files (for Touchscreen)
│ ├── hidrpc/ # HIDRPC implementation for HID devices (keyboard, mouse, etc.)
│ ├── logging/ # Logging implementation
│ ├── usbgadget/ # USB gadget
│ └── websecurity/ # TLS certificate management
└── resource # netboot iso and other resources
Key files for beginners:
internal/audio/
- [NEW] Dual-subprocess audio architecture (CGO, ALSA, Opus)web.go
- Add new API endpoints hereconfig.go
- Add new settings hereui/src/routes/
- Add new pages hereui/src/components/
- Add new UI components here
Development Modes
Full Development (Recommended)
Best for: Complete feature development
# Deploy everything to your JetKVM device
./dev_deploy.sh -r <YOUR_DEVICE_IP>
Frontend Only
Best for: UI changes without device
cd ui
npm install
./dev_device.sh <YOUR_DEVICE_IP>
Touchscreen Changes
Please click the Build
button in EEZ Studio then run ./dev_deploy.sh -r <YOUR_DEVICE_IP> --skip-ui-build
to deploy the changes to your device. Initial build might take more than 10 minutes as it will also need to fetch and build LVGL and other dependencies.
Quick Backend Changes
Best for: API, backend, or audio logic changes (including audio subprocess architecture)
# Skip frontend build for faster deployment
./dev_deploy.sh -r <YOUR_DEVICE_IP> --skip-ui-build
Debugging Made Easy
Check if everything is working
# Test connection to device
ping 192.168.1.100
# Check if JetKVM is running
ssh root@192.168.1.100 ps aux | grep jetkvm
View live logs
ssh root@192.168.1.100
tail -f /var/log/jetkvm.log
Reset everything (if stuck)
ssh root@192.168.1.100
rm /userdata/kvm_config.json
systemctl restart jetkvm
Testing Your Changes
Manual Testing
- Deploy your changes:
./dev_deploy.sh -r <IP>
- Open browser:
http://<IP>
- Test your feature
- Check logs:
ssh root@<IP> tail -f /var/log/jetkvm.log
Automated Testing
# Run all tests
./dev_deploy.sh -r <IP> --run-go-tests
# Frontend linting
cd ui && npm run lint
Essential Makefile Targets
The project includes several essential Makefile targets for development environment setup, building, and code quality:
Development Environment Setup
# Set up complete development environment (recommended first step)
make dev_env
# This runs build_audio_deps + installs Go tools
# - Uses buildkit from /opt/jetkvm-native-buildkit for cross-compilation
# - Builds ALSA and Opus static libraries for ARM in /opt/jetkvm-audio-libs
# - Installs goimports and other Go development tools
# Build only the audio dependencies
make build_audio_deps
Building
# Build development version with debug symbols
make build_dev
# Builds jetkvm_app with version like 0.4.7-dev20241222
# Requires: make dev_env (for buildkit and audio dependencies)
# Build release version (production)
make build_release
# Builds optimized release version
# Requires: make dev_env and frontend build
# Build test binaries for device testing
make build_dev_test
# Creates device-tests.tar.gz with all test binaries
Code Quality and Linting
# Run both Go and UI linting
make lint
# Run both Go and UI linting with auto-fix
make lint-fix
# Run only Go linting
make lint-go
# Run only Go linting with auto-fix
make lint-go-fix
# Run only UI linting
make lint-ui
# Run only UI linting with auto-fix
make lint-ui-fix
Note: The Go linting targets (lint-go
, lint-go-fix
, and the combined lint
/lint-fix
targets) require audio dependencies. Run make dev_env
first if you haven't already.
Development Deployment Script
The dev_deploy.sh
script is the primary tool for deploying your development changes to a JetKVM device:
# Basic deployment (builds and deploys everything)
./dev_deploy.sh -r 192.168.1.100
# Skip UI build for faster backend-only deployment
./dev_deploy.sh -r 192.168.1.100 --skip-ui-build
# Run Go tests on the device after deployment
./dev_deploy.sh -r 192.168.1.100 --run-go-tests
# Deploy with release build and install
./dev_deploy.sh -r 192.168.1.100 -i
# View all available options
./dev_deploy.sh --help
Key features:
- Automatically builds the Go backend with proper cross-compilation
- Optionally builds the React frontend (unless
--skip-ui-build
) - Deploys binaries to the device via SSH/SCP
- Restarts the JetKVM service
- Can run tests on the device
- Supports custom SSH user and various deployment options
Requirements:
- SSH access to your JetKVM device
make dev_env
must be run first (for buildkit and audio dependencies)- Device IP address or hostname
API Testing
# Test login endpoint
curl -X POST http://<IP>/auth/password-local \
-H "Content-Type: application/json" \
-d '{"password": "test123"}'
Common Issues & Solutions
"Build failed" or "Permission denied"
# Fix permissions
ssh root@<IP> chmod +x /userdata/jetkvm/bin/jetkvm_app_debug
# Clean and rebuild
go clean -modcache
go mod tidy
make build_dev
# If you see errors about missing ALSA/Opus or toolchain, run:
make dev_env # Required for audio subprocess architecture
"Can't connect to device"
# Check network
ping <IP>
# Check SSH
ssh root@<IP> echo "Connection OK"
"Audio not working"
# Make sure you have run:
make dev_env
# # If you see errors about ALSA/Opus, check logs and re-run: make build_audio_deps
"Frontend not updating"
# Clear cache and rebuild
cd ui
npm cache clean --force
rm -rf node_modules
npm install
Next Steps
Adding a New Feature
- Backend: Add API endpoint in
web.go
or extend audio ininternal/audio/
- Config: Add settings in
config.go
- Frontend: Add UI in
ui/src/routes/
- Test: Deploy and test with
./dev_deploy.sh
Code Style
- Go: Follow standard Go conventions
- TypeScript: Use TypeScript for type safety
- React: Keep components small and reusable
- Audio/CGO: Keep C/Go integration minimal, robust, and well-documented. Use zerolog for all logging.
Environment Variables
# Enable debug logging
export LOG_TRACE_SCOPES="jetkvm,cloud,websocket,native,jsonrpc,audio"
# Frontend development
export JETKVM_PROXY_URL="ws://<IP>"
Need Help?
- Check logs first:
ssh root@<IP> tail -f /var/log/jetkvm.log
- Search issues: GitHub Issues
- Ask on Discord: JetKVM Discord
- Read docs: JetKVM Documentation
Contributing
Ready to contribute?
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
Before submitting:
- Code works on device
- Tests pass
- Code follows style guidelines
- Documentation updated (if needed)
Advanced Topics
Performance Profiling
- Enable
Developer Mode
on your JetKVM device - Add a password on the
Access
tab
# Access profiling
curl http://api:$JETKVM_PASSWORD@YOUR_DEVICE_IP/developer/pprof/
Advanced Environment Variables
# Enable trace logging (useful for debugging)
export LOG_TRACE_SCOPES="jetkvm,cloud,websocket,native,jsonrpc,audio"
# For frontend development
export JETKVM_PROXY_URL="ws://<JETKVM_IP>"
# Enable SSL in development
export USE_SSL=true
Configuration Management
The application uses a JSON configuration file stored at /userdata/kvm_config.json
.
Adding New Configuration Options
-
Update the Config struct in
config.go
:type Config struct { // ... existing fields NewFeatureEnabled bool `json:"new_feature_enabled"` }
-
Update the default configuration:
var defaultConfig = &Config{ // ... existing defaults NewFeatureEnabled: false, }
-
Add migration logic if needed for existing installations
LVGL Build
We modified the LVGL code a little bit to remove unused fonts and examples. The patches are generated by
git diff --cached --diff-filter=d > ../internal/native/cgo/lvgl-minify.patch && \
git diff --name-only --diff-filter=D --cached > ../internal/native/cgo/lvgl-minify.del
Happy coding!
For more information, visit the JetKVM Documentation or join our Discord Server.