dark-matrix
dark-matrix is an open-source control system for the Framework Laptop 16's dual 9×34 LED Matrix Input Modules, developed by community member heckseven. It is built as a persistent TypeScript/Node.js daemon driving both modules over USB serial, paired with a browser-based web UI called the Deck for configuration, animation editing, HUD presets, audio visualization, video display, and games1. The project is licensed under GPL-3.0-or-later2.
The author notes the code was "written entirely by AI" and openly labels the project as "vibe-coded jank" in its community announcement, while the designs are entirely their own work13.
Background
The Framework Laptop 16 supports hot-swappable LED Matrix Input Modules — 9×34 (306 LED) monochrome displays driven by an RP2040 microcontroller and an IS31FL3741A LED controller, communicating over USB ACM Serial4. dark-matrix was created to consolidate a wide wish-list of matrix capabilities — animations, HUDs, audio reactivity, video, and notifications — into a single daemon and web UI, where two modules are treated as a unified 18×34 canvas where applicable13.
Deck Modes
The Deck is a local web server (default port 7340) opened in the browser. It exposes the following modes1:
| Mode | Description |
|---|---|
| design | Pixel animation editor — draw, animate, push frames to hardware live over WebSocket |
| hud | Named HUD presets — widget layouts per module side; switchable via CLI |
| audio | Real-time audio visualizer — EQ bars, waveform, radial, waterfall, heatmap |
| video | Matrix-rendered video display |
| data | Data-driven display (in progress) |
| runes | Rune/glyph display |
| games | Game of Life and similar generative modes |
| config | Daemon settings — startup, brightness, hardware, notifications, appearance |
The design mode supports undo/redo (50-level history), import of PNG/GIF/.dmx.json projects, export to GIF/PNG, and live preview streaming frames to the physical modules as you draw1.
Notification Sources
The daemon runs a priority-ordered notification queue that preempts the resting HUD state1:
| Source | Trigger | Priority |
|---|---|---|
| Mic switch (FW16 EC) | Physical mic privacy switch toggled ON | High |
| Camera switch (FW16 EC) | Physical camera privacy switch toggled ON | High |
| VM activity | VM started/stopped via libvirt | Medium |
| Claude activity | PostToolUse hook fires (tool use within last 30s) | Low |
CLI Reference
| Command | Description |
|---|---|
init | Guided first-run setup: config, calibrate, report optional deps |
ping | Check if daemon is running; prints version |
status | Show daemon version, uptime, current animation, brightness, module state |
calibrate | Confirm left/right module assignment |
ui [--port <n>] | Launch the Deck UI (default port 7340) |
hud preset <name> | Switch to a named HUD preset |
image <path> | Display any image (PNG/JPEG/GIF), resized to 9×34 |
show-split <left> <right> | Send different images to each module |
scroll <text> | Scroll text across both modules |
animate gif [--dual] <path> | Play a GIF (optionally spanning both modules) |
play [--loop] <path> | Play a .dmx.json project (optionally looping) |
display yeah|runes|0x07|panic | Built-in presets |
release | Release serial port handles (for compatibility with matrix.sh) |
self-update | Fetch latest GitHub release and update in-place |
uninstall [--purge] | Stop service and remove install (and config with --purge) |
Installation
dark-matrix targets Linux and ships a one-line installer that installs to ~/.local/share/dark-matrix/, enables a systemd user service, and writes a dark-matrix wrapper to ~/.local/bin/1:
curl -fsSL https://raw.githubusercontent.com/heckseven/dark-matrix/main/scripts/install.sh | sh
The user must be in the dialout group (or uucp on some distros) for serial access to /dev/ttyACM*1. Optional dependencies include ffmpeg (audio pipeline), wpctl/pw-dump (PipeWire audio source selection and device enumeration), yt-dlp (video download), dbus-monitor (desktop notification watching), and ectool (EC privacy switch detection)1.
After install, open the Deck and run first-run calibration1:
dark-matrix ui # opens the welcome screen on first launch
dark-matrix calibrate # confirms left/right module assignment
Configuration
Config lives at ~/.config/dark-matrix/config.json, generated on first run and hot-reloadable via SIGHUP to the daemon. Modules are referenced by stable by-path symlinks, and brightness can track an ambient light sensor ("sensor" mode) with hysteresis smoothing1.
Technical Details
| Detail | Value |
|---|---|
| Language | TypeScript (99.3%), Shell, C, JavaScript, CSS, HTML1 |
| License | GPL-3.0-or-later2 |
| Platform | Linux (systemd user service) |
| IPC | Unix socket (DARK_MATRIX_SOCKET) |
| Deck | Local HTTP server, default port 7340 |
| Hardware | Two 9×34 LED Matrix modules (RP2040 + IS31FL3741A)4 |
| Pair resolution | 18×34 (612 LEDs) |
| Project format | .dmx.json (column-major base64 pixels) |
| Audio visualizers | EQ bars, waveform, radial, waterfall, heatmap |
| Stars | 21 |
| Created | April 30, 20261 |
| Latest release | v0.1.4 (July 1, 2026)5 |
Releases
| Version | Date | Notes |
|---|---|---|
| v0.1.0 | June 3, 2026 | Initial release5 |
| v0.1.1 | June 6, 2026 | Install, runtime deps, and calibration fixes (PR #1)5 |
| v0.1.2 | June 13, 2026 | — |
| v0.1.3 | June 30, 2026 | — |
| v0.1.4 | July 1, 2026 | Latest release5 |
Related Projects
| Project | Description |
|---|---|
| fw16-led-matrixd | Cross-platform Rust daemon with image rendering and pair mode |
| led-matrix-manager | Qt GUI for LED matrix management |
| fw16-ledvu | PipeWire/CAVA audio visualizer for the LED matrix |
| Dual LED Matrix Audio Visualizer | Stereo frequency bars across both matrix modules |
| FW16 LED Matrix Visualizer | Windows audio visualizer + Pixel Hero animation player |
| fw16-pongwars | Pong Wars game for the FW16 LED Matrix |