Development Setup
Development environment setup, build processes, and workflows for HelixScreen.
Quick Start
Section titled “Quick Start”# Install dependencies (see platform-specific below)npm install && make venv-setup
# Build and runmake -j./build/bin/helix-screen --test -vv # Mock printer + DEBUG logsDevelopment Environment
Section titled “Development Environment”macOS (Homebrew)
Section titled “macOS (Homebrew)”brew install cmake bear imagemagick python3 node shellcheck bats-corenpm install # lv_font_conv and lv_img_convmake venv-setup # Python venv with pypng/lz4Minimum: macOS 10.15 (Catalina) for CoreWLAN/CoreLocation WiFi APIs.
Debian/Ubuntu
Section titled “Debian/Ubuntu”sudo apt install cmake bear imagemagick python3 python3-venv clang make npm \ shellcheck bats libnl-3-dev libnl-genl-3-dev libssl-devnpm install && make venv-setupFedora/RHEL
Section titled “Fedora/RHEL”sudo dnf install cmake bear ImageMagick python3 clang make npm \ ShellCheck bats libnl3-devel openssl-develnpm install && make venv-setupDependencies
Section titled “Dependencies”| Category | Components | Notes |
|---|---|---|
| Required | clang, cmake 3.16+, make, python3, node/npm | Core build tools |
| Auto-built | SDL2, spdlog, libhv | Built from submodules if not system-installed |
| Always submodule | lvgl | Project-specific patches required |
| Optional | bear, imagemagick, shellcheck, bats-core | IDE support, screenshots, shell linting/testing |
make check-deps # Check what's missingmake install-deps # Auto-install (interactive)Build System
Section titled “Build System”Core Commands
Section titled “Core Commands”make -j # Parallel incremental build (recommended)make build # Clean parallel build with progress/timingmake clean && make -j # Full rebuild (only when needed)make V=1 # Verbose mode (shows full commands)make compile_commands # Generate compile_commands.json for IDE/LSPRunning the Application
Section titled “Running the Application”./build/bin/helix-screen # Production mode./build/bin/helix-screen --test # Full mock mode (no hardware)./build/bin/helix-screen --test --real-wifi # Mix real WiFi + mock printer./build/bin/helix-screen --dark # Force dark theme./build/bin/helix-screen --light # Force light theme./build/bin/helix-screen -d 1 -s small # Display 1, small sizeTest Mode Flags
Section titled “Test Mode Flags”| Flag | Effect |
|---|---|
--test | Enable test mode (required for mocks) |
--real-wifi | Use real WiFi instead of mock |
--real-ethernet | Use real Ethernet instead of mock |
--real-moonraker | Connect to real printer |
--real-files | Use real printer files |
Test mode keyboard shortcuts: S=screenshot, P=test prompt, N=test notification, Q/Esc=quit
Wizard Flags
Section titled “Wizard Flags”| Flag | Effect |
|---|---|
-w, --wizard | Force the first-run configuration wizard |
--wizard-step <step> | Jump to a specific wizard step (0-12) for testing |
--wizard is destructive to wizard-managed config — it is meant to fully re-run setup, not just re-open it. On startup with --wizard, the app clears all wizard-managed state in settings.json so a stale or wrong install-time seed is recoverable:
- Clears the preset marker via
Config::clear_preset()(erases the top-level"preset"key). Becausehas_preset()is then false, the re-run becomes a full wizard — the identify and hardware pages reappear instead of being skipped. - Clears the active printer’s
moonraker_host(set to""), so the connection step is re-entered. - Clears the cached hardware snapshot and the wizard’s heater/sensor/fan/LED/filament-sensor selections, so stale hardware choices don’t trigger false hardware-health warnings.
This is the recovery path when an install-time auto-seed (see INSTALLER.md) picked the wrong printer: re-run with --wizard to drop the seed and reconfigure from scratch.
Printer Detection (--detect-printer)
Section titled “Printer Detection (--detect-printer)”A headless one-shot that queries a running Moonraker over its REST API, runs the same detection logic the wizard uses, prints a JSON verdict to stdout, and exits. No UI is started. Useful for debugging which preset a given printer matches, or for scripting install-time detection.
| Flag | Argument | Default | Effect |
|---|---|---|---|
--detect-printer | (none) | — | Run headless detection, print JSON, exit |
--host <addr> | host/IP | 127.0.0.1 | Moonraker host to query |
--port <n> | 1-65535 | 7125 | Moonraker port to query |
# Detect the local printer./build/bin/helix-screen --detect-printer
# Detect a printer on another host./build/bin/helix-screen --detect-printer --host 192.168.1.74 --port 7125Internally it does three REST GETs against http://HOST:PORT (3-second timeout each):
/printer/objects/list, /printer/info (hostname), and
/printer/objects/query?configfile=settings (kinematics + build volume from the
stepper_x/y/z config). The resulting hardware profile is fed to
PrinterDetector::auto_detect().
Exit codes: 0 on success (verdict printed). 1 if Moonraker’s object list is
unavailable at the given host/port (a warning is logged; no JSON is printed).
JSON output shape — one compact line, terminated by a newline:
{"model":"Creality K1 Max","preset":"k1_max","confidence":92,"runner_up_preset":"qidi_q2","runner_up_confidence":43}| Key | Type | Meaning |
|---|---|---|
model | string | Human-readable detected printer name (PrinterDetectionResult::type_name) |
preset | string or null | Platform preset id for the match; null when the result has no preset |
confidence | integer (0-100) | Detection confidence for the top match |
runner_up_preset | string or null | Preset id of the second-place candidate; null when there is none |
runner_up_confidence | integer (0-100) | Confidence score of the runner-up |
When there is no credible second candidate, the runner-up fields collapse:
{"model":"FlashForge AD5M","preset":"ad5m","confidence":88,"runner_up_preset":null,"runner_up_confidence":0}The installer’s Tier-2 detection (see INSTALLER.md) parses exactly this
output and applies its confidence gate to confidence and the
confidence - runner_up_confidence margin.
For cross-compilation, patches, and advanced options, see BUILD_SYSTEM.md.
Logging
Section titled “Logging”Verbosity Levels
Section titled “Verbosity Levels”| Level | Flag | Use For |
|---|---|---|
| WARN | (default) | Errors and warnings only |
| INFO | -v | User-visible milestones |
| DEBUG | -vv | Troubleshooting, summaries |
| TRACE | -vvv | Per-item loops, wire protocol |
Log Destinations
Section titled “Log Destinations”./build/bin/helix-screen --log-dest=console # Console (default on macOS)./build/bin/helix-screen --log-dest=journal # systemd journal (Linux)./build/bin/helix-screen --log-dest=file --log-file=/tmp/helix.logViewing logs on Linux:
journalctl -t helix -f # systemdtail -f /var/log/helix-screen.log # fileCode Usage
Section titled “Code Usage”ALWAYS use spdlog - never printf/cout/LV_LOG_*:
spdlog::info("[ComponentName] Message: {}", value);spdlog::debug("[Theme] Registered {} items", count);spdlog submodule: Uses fmt-11.2.0 branch. Initialize with git submodule update --init --recursive.
Configuration
Section titled “Configuration”Config File Pattern
Section titled “Config File Pattern”cp config/settings.json.template config/settings.json # First-time setupconfig/settings.json- User settings (git-ignored)config/settings.json.template- Defaults (versioned)
Never commit user config. Legacy root location auto-migrates.
Config Structure
Section titled “Config Structure”{ "printer": { "heaters": { "bed": "heater_bed", "hotend": "extruder" }, "temp_sensors": { "bed": "heater_bed", "hotend": "extruder" }, "fans": { "part": "fan", "hotend": "heater_fan hotend_fan" } }}Naming: Container keys plural (heaters), role keys singular (bed).
DPI & Hardware Profiles
Section titled “DPI & Hardware Profiles”LVGL scales UI based on DPI. Default: 160 (reference, no scaling).
./build/bin/helix-screen --dpi 170 # 7" @ 1024x600 (BTT Pad 7)./build/bin/helix-screen --dpi 187 # 5" @ 800x480./build/bin/helix-screen --dpi 201 # 4.3" @ 720x480 (AD5M)| Hardware | Resolution | DPI |
|---|---|---|
| Reference | — | 160 |
| 7” LCD | 1024×600 | 170 |
| 5” LCD | 800×480 | 187 |
| AD5M | 720×480 | 201 |
Multi-Display (macOS)
Section titled “Multi-Display (macOS)”./build/bin/helix-screen --display 1 # Secondary display./build/bin/helix-screen -d 1 -s small # Combined optionsUses SDL_GetDisplayBounds() for proper positioning on multi-monitor setups.
Screenshots
Section titled “Screenshots”# Interactive: Press 'S' in running UI
# Automated:./scripts/screenshot.sh helix-screen output-name [panel] [options]./scripts/screenshot.sh helix-screen home-screen home./scripts/screenshot.sh helix-screen motion motion -s small
# Environment overrides:HELIX_SCREENSHOT_DISPLAY=0 ./scripts/screenshot.sh helix-screen test homeHELIX_SCREENSHOT_OPEN=1 ./scripts/screenshot.sh helix-screen review homeOutput: /tmp/ui-screenshot-[name].png
Icon & Font Workflow
Section titled “Icon & Font Workflow”python3 scripts/generate-icon-consts.py # After editing include/ui_fonts.hmake icon # Generate platform iconsSee BUILD_SYSTEM.md for complete font generation details.
IDE Setup
Section titled “IDE Setup”make compile_commands # Generates compile_commands.json (requires bear)VS Code: C/C++ extension + clangd extension Vim/Neovim: Configure clangd LSP client CLion: Import as Makefile project
Daily Workflow
Section titled “Daily Workflow”- Edit code in
src/orinclude/ - Edit XML in
ui_xml/— no rebuild needed (use hot reload or just relaunch) - Build with
make -j(only when C++ changes) - Test with
./build/bin/helix-screen --test -vv [panel] - Screenshot with S key or
./scripts/screenshot.sh - Commit working incremental changes
XML vs C++ Changes
Section titled “XML vs C++ Changes”| Change Type | Location | Rebuild? | Hot Reload? |
|---|---|---|---|
| Layout, styling, colors | ui_xml/*.xml | No | Yes — auto-detected |
| Logic, bindings, handlers | src/*.cpp, include/*.h | Yes (make -j) | No |
| Theme colors | config/themes/*.json | No — just restart | No |
| Translations | config/strings/*.yaml | Yes (code generation step) | No |
XML Hot Reload
Section titled “XML Hot Reload”For the fastest UI iteration, use hot reload — edit XML, save, see updates without restarting:
HELIX_HOT_RELOAD=1 ./build/bin/helix-screen --test -vvWhen enabled, a background thread watches all XML files for changes and re-registers modified components automatically. After a file changes, navigate away from the panel and back to see the new layout. See HELIX_HOT_RELOAD for details and limitations.
UI Development
Section titled “UI Development”For layout work, styling fixes, and alternate screen layouts, the UI Contributor Guide is the primary reference. It covers breakpoints, design tokens, pre-themed widgets, layout overrides, and what needs work.
Key points for UI contributors:
- XML layouts load at runtime — no rebuild needed for layout/styling changes. Use
HELIX_HOT_RELOAD=1for live editing without restarting - Design tokens are mandatory — use
#space_md,#card_bg,<text_body>instead of hardcoded values - 5 breakpoint tiers based on screen height: tiny (≤390px), small (391–460px), medium (461–550px), large (551–700px), xlarge (>700px)
- Layout overrides let you provide alternate XML for ultrawide, portrait, or tiny screens without touching the standard layouts
- Test at multiple sizes with
-s WIDTHxHEIGHT:Terminal window ./build/bin/helix-screen --test -vv -s 480x320 # Tiny./build/bin/helix-screen --test -vv -s 800x480 # Standard./build/bin/helix-screen --test -vv -s 1920x480 --layout ultrawide
Where UI files live
Section titled “Where UI files live”| Path | Contents |
|---|---|
ui_xml/ | All XML layouts (~170 files) |
ui_xml/components/ | Reusable XML components |
ui_xml/ultrawide/ | Ultrawide layout overrides |
ui_xml/globals.xml | Design tokens and global variables (shared, never override) |
config/themes/ | Theme JSON files (color palettes) |
Worktrees
Section titled “Worktrees”For major feature work, use git worktrees to isolate your changes:
scripts/setup-worktree.sh feature/my-branch # Creates in .worktrees/This creates a worktree with symlinked dependencies and a ready-to-build environment. Worktrees keep main clean while you experiment.
macOS WiFi Permission
Section titled “macOS WiFi Permission”Real WiFi scanning requires Location Services (network SSIDs reveal location).
Easiest: System Settings → Privacy & Security → Location Services → Enable Terminal
Without permission, app falls back to mock WiFi. Check with:
./build/bin/helix-screen --wizard -vv 2>&1 | grep -i "location\|wifi"Troubleshooting
Section titled “Troubleshooting”make check-deps # Check missing dependenciesmake install-deps # Auto-installmake clean && make V=1 # Verbose rebuildSDL2 not found: brew install sdl2 (macOS) or sudo apt install libsdl2-dev (Linux)
For complete troubleshooting, see BUILD_SYSTEM.md.
Contributing
Section titled “Contributing”First-Time Setup
Section titled “First-Time Setup”make setup # Configures pre-commit hook + commit templateThe pre-commit hook auto-formats code (clang-format) and runs quality checks.
Code Standards
Section titled “Code Standards”Class-based architecture required for all new code:
// ✅ CORRECT: Class-based panelclass MotionPanel : public PanelBase {public: explicit MotionPanel(lv_obj_t* parent); void show() override;};
// ❌ AVOID: Function-based (legacy)void ui_panel_motion_init(lv_obj_t* parent);Naming conventions:
- Functions/variables:
snake_case(ui_panel_home_init,temp_target) - XML files:
kebab-case(nozzle-temp-panel.xml) - Constants:
UPPER_SNAKE_CASE(MAX_TEMP)
Critical patterns:
// Widget lookup: use names, not indiceslv_obj_t* label = lv_obj_find_by_name(panel, "temp_display"); // ✅lv_obj_t* label = lv_obj_get_child(panel, 3); // ❌
// LVGL API: public onlylv_obj_get_x(); // ✅ Public_lv_obj_mark_dirty(); // ❌ Private (underscore prefix)Copyright headers (all new files):
// Copyright 2025 356C LLCCommit Messages
Section titled “Commit Messages”type(scope): description
Optional detailed explanation.Types: feat, fix, docs, style, refactor, test, chore
Examples:
feat(ui): add temperature control overlay panelfix(build): resolve SDL2 linking on macOS Sequoiadocs(readme): update build instructionsPull Requests
Section titled “Pull Requests”Before submitting:
- Rebase on latest
main - Test build and runtime
- Update docs if patterns changed
- Add screenshots for UI changes
PR description includes:
- What changed (summary)
- Why (context/problem solved)
- How to test
- Screenshots (if visual)
- Breaking changes (if any)
Code Review Focus
Section titled “Code Review Focus”- Architecture compliance (XML/Subject patterns)
- Error handling (logging, null checks)
- Performance (no blocking in UI thread)
- Documentation updated
Installer Scripts
Section titled “Installer Scripts”The installation system is modular for maintainability and BusyBox compatibility.
Structure
Section titled “Structure”scripts/├── install.sh # Auto-generated for curl|sh (user-facing)├── install-dev.sh # Modular version (requires lib/installer/)├── uninstall.sh # Standalone uninstaller├── lib/installer/ # Shared modules│ ├── common.sh # Logging, colors, error handling│ ├── platform.sh # Platform/firmware detection│ ├── permissions.sh # Root/sudo handling│ ├── requirements.sh # Pre-flight checks│ ├── forgex.sh # ForgeX-specific functions│ ├── competing_uis.sh # Stop GuppyScreen, KlipperScreen, etc.│ ├── release.sh # Download and extract│ ├── service.sh # Systemd/SysV service management│ └── uninstall.sh # Uninstall/clean functions└── bundle-installer.sh # Generate install.sh from modulesBusyBox Compatibility
Section titled “BusyBox Compatibility”All modules use POSIX #!/bin/sh (not bash) for AD5M’s BusyBox environment:
[ ]instead of[[ ]]command -v X >/dev/null 2>&1instead of&>- No arrays (use space-separated strings)
ps -efinstead ofps aux
Generating Bundled Installer
Section titled “Generating Bundled Installer”./scripts/bundle-installer.sh -o ./scripts/install.shThe bundled version inlines all modules for curl|sh usage.
Testing Installers
Section titled “Testing Installers”./scripts/install-dev.sh --help # Test modular version (from repo)./scripts/install.sh --help # Test bundled version (for users)./scripts/uninstall.sh --help # Test uninstallersh -n scripts/install.sh # Check POSIX syntaxRelated Documentation
Section titled “Related Documentation”- README.md - Documentation index
- UI Contributor Guide - Start here for UI/layout work
- BUILD_SYSTEM.md - Complete build reference
- ARCHITECTURE.md - System design
- LVGL9_XML_GUIDE.md - XML syntax reference
- DEVELOPER_QUICK_REFERENCE.md - Common patterns
- TESTING.md - Test infrastructure and Catch2 usage
- LOGGING.md - Log levels and when to use each