diff --git a/CLAUDE.md b/CLAUDE.md
index 9c56b8c..1dfb673 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -2,162 +2,98 @@
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+Halo is a 2-deck DJ app for macOS with an integrated lighting console (Art-Net output driven by per-track cues
+and a live programmer). `ROADMAP.md` is the authoritative description of the architecture and feature plan —
+read it before designing anything non-trivial.
+
## Common Commands
-### Building and Running
- **Build**: `cargo build --release`
-- **Run with Art-Net broadcast**: `cargo run --release -- --source-ip `
-- **Run with unicast and MIDI**: `cargo run --release -- --source-ip 192.168.1.100 --dest-ip 192.168.1.200 --enable-midi`
-- **Run with multi-destination setup**: `cargo run --release -- --source-ip 192.168.1.100 --lighting-dest-ip 192.168.1.200 --pixel-dest-ip 192.168.1.201`
-- **Load a show file**: `cargo run --release -- --source-ip --show-file shows/Jasons40th.json`
-
-### CLI Arguments
-- `--source-ip ` - Art-Net source IP address (required)
-- `--dest-ip ` - Single destination IP (legacy, optional)
-- `--lighting-dest-ip ` - Lighting fixtures destination IP (multi-destination)
-- `--pixel-dest-ip ` - Pixel fixtures destination IP (multi-destination)
-- `--lighting-universe ` - Universe for lighting fixtures (default: 1)
-- `--pixel-start-universe ` - Starting universe for pixel fixtures (default: 2)
-- `--artnet-port ` - Art-Net port (default: 6454)
-- `--broadcast` - Force broadcast mode
-- `--enable-midi` - Enable MIDI support
-- `--show-file ` - Path to show JSON file
-
-See `docs/multi-destination-artnet.md` for detailed multi-destination Art-Net setup.
-
-### Development Tools
+- **Run**: `cargo run --release` (optionally pass an audio file path as the only positional arg to load it on launch)
- **Check compilation**: `cargo check --workspace --all-targets`
-- **Format code**: `cargo +nightly fmt --all` (requires nightly toolchain for unstable formatting options)
-- **Lint**: `cargo clippy --workspace --all-targets --all-features -- -D warnings`
+- **Format code**: `cargo +nightly fmt --all` (nightly required — `rustfmt.toml` uses unstable options)
- **Test**: `cargo test --workspace`
-- **Install nightly toolchain**: `rustup toolchain install nightly` (required for formatting only)
+- **Lint**: `cargo clippy --workspace --all-targets` (currently not enforced in CI)
+- **macOS app bundle**: `cargo bundle --release` (requires `cargo-bundle`)
+
+There are no CLI flags. Art-Net destination, audio device, and other settings are configured in-app and
+persisted (see Persistence below). Logging is controlled with `RUST_LOG`.
+
+### Toolchain
-### Toolchain Requirements
-- **Stable Rust**: Used for building, testing, and linting (MSRV: 1.90.0)
-- **Nightly Rust**: Required only for formatting due to unstable options in `rustfmt.toml`
+- **Stable Rust** for building/testing (CI pins 1.90.0); **nightly** only for formatting.
+- The `timestretch` crate is a **path dependency on a sibling clone**: `../timestretch-rs` next to this repo
+ (from `crates/halo`, `path = "../../../timestretch-rs"`). CI checks out `robmorgan/timestretch-rs` to that
+ location. Builds fail without it.
## Architecture Overview
-Halo is a real-time lighting console built with Rust, designed for solo performers. It uses a multi-crate workspace architecture with async/tokio runtime:
-
-### Core Crates
-- **`halo-core`**: Core lighting engine with async module system, DMX output, cue system, effects engine, pixel engine, and MIDI integration
-- **`halo-fixtures`**: Fixture library and management system
-- **`halo-ui`**: egui-based UI components and interface
-- **`halo`**: CLI application and main entry point (uses `#[tokio::main]` async runtime)
-
-### Key Systems
-
-#### Lighting Console (`halo-core/src/console.rs`)
-- Central `LightingConsole` struct manages all lighting operations
-- Uses async `ModuleManager` to coordinate separate modules (`DmxModule`, `AudioModule`, `MidiModule`, `SmpteModule`)
-- Channel-based communication using `ConsoleCommand` and `ConsoleEvent` via tokio `mpsc`
-- Handles fixture patching, cue management, and MIDI integration
-- Supports multi-destination Art-Net routing for different fixture types
-
-#### Cue System (`halo-core/src/cue/`)
-- `CueManager` handles playback state and timecode synchronization
-- Supports both internal and external SMPTE timecode
-- `CueList` contains sequences of `Cue` objects with static values and effects
-- Audio playback synchronization with Ableton Link
-
-#### Effect Engine (`halo-core/src/effect/`)
-- Mathematical effect generators: sine, sawtooth, square waves
-- Beat-synchronized effects using rhythm detection
-- Effect distribution across multiple fixtures with customizable parameters
-
-#### MIDI Integration (`halo-core/src/midi/`)
-- MPK49 controller support for live performance
-- `MidiOverride` system for real-time control during shows
-- Actions include static values and cue triggering
-
-#### Module System (`halo-core/src/modules/`)
-- `ModuleManager` coordinates all async modules in separate tokio tasks
-- Each module implements `AsyncModule` trait with `initialize()`, `run()`, and `shutdown()` methods
-- Inter-module communication via `ModuleEvent` (DMX output, audio commands, timecode sync, MIDI input)
-- Status/error reporting via `ModuleMessage` back to manager
-- **DmxModule**: Real-time DMX output at 44Hz with multi-destination Art-Net routing
-- **AudioModule**: Audio file playback in dedicated OS thread (not tokio task) using `rodio` and `symphonia`
-- **MidiModule**: MIDI input handling and event forwarding
-- **SmpteModule**: SMPTE timecode synchronization for external timecode sources
-
-#### Pixel Engine (`halo-core/src/pixel/`)
-- `PixelEngine` manages all pixel bar fixtures with per-universe routing
-- Pixel effects: `Chase`, `Wave`, `Strobe`, `ColorCycle`
-- `PixelEffectScope` controls effect application: `Bar` (uniform) or `Individual` (per-pixel)
-- Beat-synchronized effects using rhythm detection
-- Supports effect distribution across multiple fixtures (All, Step, Wave)
-- Renders RGB data per universe for pixel bar fixtures
-
-#### Configuration System (`halo-core/src/config.rs`)
-- `ConfigManager` handles persistent configuration in `config.json` (repository root)
-- `Settings` structure stores audio device, MIDI device, DMX settings, and fixture library preferences
-- Configuration loaded at startup; CLI arguments override saved settings
-- Settings UI panel allows runtime configuration changes
-- Version-aware configuration with migration support
-
-#### UI Architecture (`halo-ui/src/`)
-- `HaloApp` is the main egui application with tabbed interface
-- Separate panels: Dashboard, Programmer, Cue Editor, Patch Panel, Show Manager
-- Real-time fixture grid visualization and control
-- Timeline view for cue sequencing
-
-### Network Configuration
-- Multi-destination Art-Net architecture via `NetworkConfig` (`artnet/network_config.rs`)
-- Multiple `ArtNetDestination` entries with independent broadcast/unicast modes
-- Universe routing via `HashMap` maps universes to destination indices
-- Common setup: Universe 1 for lighting fixtures, Universes 2+ for pixel fixtures
-- CLI supports separate `--lighting-dest-ip` and `--pixel-dest-ip` for easy multi-destination setup
-- Legacy `--dest-ip` still supported for single-destination backward compatibility
-- Art-Net output on port 6454 (configurable via `--artnet-port`)
-
-### Show File Format
-- JSON-based show files in `shows/` directory
-- Contains cue lists with timing, effects, pixel effects, and fixture assignments
-- Includes audio file paths for synchronized playback
-- Loadable at runtime via `--show-file` parameter
-- Managed through UI Show Manager with save/load functionality
-
-## Development Notes
-
-### Repository Conventions
-
-#### Rust Crates
-- Crate names are prefixed with `halo-`. For example, the `core` folder's crate is named `halo-core`
-- When using `format!` and you can inline variables into `{}`, always do that
-- Never use `unsafe` blocks or functions in any code
-
-#### Code Formatting
-After making any changes to Rust code, always run:
-```bash
-cargo +nightly fmt --all
-```
-
-### macOS Platform Requirement
-- Development and execution require macOS due to system-specific audio and MIDI dependencies
-- Uses Core Audio frameworks through `rodio` and `midir` crates
-
-### Async Architecture
-- Built on tokio async runtime with async/await throughout the codebase
-- Module system uses async tasks for concurrent operation
-- Channel-based communication between UI and console (`tokio::sync::mpsc`)
-- AudioModule uses dedicated OS thread (not async task) for real-time audio playback
-
-### Configuration Management
-- `config.json` file in repository root stores persistent settings
-- Auto-created with defaults on first run if not present
-- CLI arguments override configuration file settings
-- Editable through Settings panel in UI
-
-### Fixture Patching
-- Fixtures are defined in the fixture library with channel layouts
-- Traditional lighting fixtures typically on Universe 1
-- Pixel bar fixtures on Universes 2+ with per-universe routing
-- DMX addressing starts from specified universe and channel
-
-### Performance Considerations
-- DMX module outputs at 44Hz for smooth lighting output
-- Async module architecture allows concurrent operation of DMX, audio, MIDI, and timecode
-- UI runs on main thread with egui's native event loop and repaint system
-- Channel-based communication between UI and console for thread-safe operation
-- Audio playback in dedicated OS thread for consistent timing
\ No newline at end of file
+Two workspace crates:
+
+- **`crates/halo`** — the application: UI (egui/eframe, wgpu backend), audio engine, decks, mixer DSP, track
+ library, analysis workers, and the DMX engine thread.
+- **`crates/halo-light`** — UI-free, audio-free lighting domain library: fixtures, cues, programmer resolution,
+ DMX rendering, Art-Net transport.
+
+### Threading model (no tokio)
+
+Plain threads + channels/atomics, mirroring the `timestretch` controller/processor/source split:
+
+- **UI thread** — egui at ~30 fps while playing. Talks to audio via atomics and the engine's wait-free control
+ mailbox; a mutex only guards cold UI state.
+- **Feed/control thread per deck** — keeps the engine's source ring fed, handles warm-start seeks and gapless
+ loop wraps (`JumpMap` re-anchor), publishes the playhead.
+- **Audio callback thread (cpal)** — owns both `EngineProcessor`s and the whole mixer chain
+ (engine → trim → EQ → filter → fader → crossfader → master → limiter). Must stay **allocation-free and
+ lock-free**; parameters arrive via atomics and are smoothed per block.
+- **Worker threads** (`std::thread` + `mpsc`, drained per frame by the UI) — library import, track analysis.
+- **DMX engine thread** — 44 Hz tick: reads deck playheads from atomics, `resolve()` → `render()` → Art-Net send.
+
+### Key modules — `crates/halo/src`
+
+- `main.rs` — eframe/wgpu entry point; positional file arg; `env_logger`.
+- `app.rs` — `HaloApp`: views (Prepare/Perform), deck UI, mixer UI, rig ownership, PATCH tab, settings window.
+- `deck.rs` — `Deck`: one `timestretch::Engine` per deck, feed thread, seeks, loops, EOF, playhead.
+- `audio.rs` — cpal stream setup and the audio callback owning the mixer chain.
+- `dsp.rs` — `IsolatorEq` (LR4 crossover, full-kill), `DjFilter` (RBJ biquad LP/HP), `Limiter`.
+- `state.rs` — shared atomics (`DeckShared`, `MixerShared`), scrub state, meters, CPU load.
+- `scrub.rs` — audible scrub: varispeed voice with momentum glide/settle, engine↔voice crossfade.
+- `waveform/` — 3-band RGB peaks pyramid, overview strip, zoomed beat-grid view, trigger-lane strips + cue editor.
+- `decoder.rs` — symphonia decode (mp3/flac/ogg/wav) to interleaved stereo `f32`.
+- `worker.rs` — background import/analysis workers (own DB connections).
+- `library.rs` — SQLite (rusqlite, bundled): `tracks`, `playlists`, `playlist_tracks`, `lighting_cues`, `settings`.
+- `dmx.rs` — `spawn_dmx_engine`, the 44 Hz Art-Net output thread (has an end-to-end UDP test).
+- `programmer_ui.rs` — lighting programmer surface (fixture grid, five parameter views, effect panels).
+- `show.rs` — `simulate_show()`: deterministic demo cue generator, not real authored content.
+- `fader.rs` / `knob.rs` — custom egui widgets.
+
+### Key modules — `crates/halo-light/src`
+
+- `fixture.rs` — `Rig`, grid/selection types, `default_rig()`.
+- `fixture_library.rs` — `FixtureProfile`/`Channel`/`ChannelType`, hardcoded profile registry, patching.
+- `cues.rs` — `CueSet` (runtime, non-overlapping per lane) + `CueFile` (persisted JSON, seconds).
+- `programmer.rs` — `resolve()`: **the single merge point** (programmer override > track cues > off).
+- `output.rs` — pure `render()`: resolved lanes + params → per-universe `[u8; 512]` DMX frames.
+- `artnet.rs` — synchronous Art-Net over `std::net::UdpSocket` (broadcast/unicast, multi-destination).
+
+### Persistence
+
+- **eframe persistence** (`PERSIST_KEY = "halo"`) — UI/mixer state: trims, keylock, pitch range, quantize,
+ gated mode, audition volume, device/buffer, sort order.
+- **Library DB `settings` table** — Art-Net config and rig patch.
+- There is no config file; `config.json` in old branches/history is from the pre-pivot console.
+
+## Conventions
+
+- Crate names are prefixed with `halo-` (the `halo-light` crate lives in `crates/halo-light`).
+- **Never use `unsafe`** blocks or functions in any code.
+- When using `format!` (and friends) and a variable can be inlined into `{}`, always inline it.
+- **No tokio** — concurrency is plain threads + `mpsc` + atomics. Don't reintroduce async scaffolding.
+- The audio callback must never allocate, lock, or panic.
+- `programmer::resolve()` stays the single merge point for lighting state; `output::render()` stays pure.
+- After changing Rust code, always run `cargo +nightly fmt --all`.
+
+## CI
+
+`.github/workflows/rust.yml` runs on macOS arm64 and Linux x86_64: checks out `timestretch-rs` as a sibling,
+then `cargo +nightly fmt --check`, `cargo build`, `cargo test` on stable 1.90.0.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1195e20..f9c32f6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -7,13 +7,18 @@
## ⏩ Quick‑Start
### 1. Fork, clone & branch
+
+Halo depends on the [`timestretch`](https://github.com/robmorgan/timestretch-rs) crate by local path, so clone
+`timestretch-rs` alongside your halo clone:
+
```bash
git clone https://github.com//halo.git
+git clone https://github.com/robmorgan/timestretch-rs.git
cd halo
git checkout -b feat/
```
-### 2. Compile fast (uses stable toolchain from rust-toolchain.toml)
+### 2. Compile fast (uses stable toolchain)
```bash
cargo check --workspace --all-targets
```
@@ -49,21 +54,21 @@ git push origin feat/
## Project Layout
-| Crate | Role |
-| ------------------- | -------------------------------------------------------- |
-| **`halo-core`** | Core lighting engine. |
-| **`halo-fixtures`** | Fixture library and management. |
-| **`halo`** | CLI and main entrypoint |
-| **`halo-ui`** | UI Components and Interface. |
+| Crate | Role |
+| ----------------- | ----------------------------------------------------------------------------------------- |
+| **`halo`** | The application: UI, decks, audio engine, mixer DSP, track library, DMX engine thread. |
+| **`halo-light`** | UI-free lighting domain library: fixtures, cues, programmer resolution, Art-Net output. |
-All crates live in one Cargo **workspace**, so `cargo ` from the repo root affects everything.
+All crates live in one Cargo **workspace**, so `cargo ` from the repo root affects everything. The
+[`timestretch`](https://github.com/robmorgan/timestretch-rs) engine is a path dependency expected at
+`../timestretch-rs`, next to this repository.
-----
## Dev Environment
* **Platform**: Development and execution require **macOS**.
- * **Rust (Build/Test)**: **Stable** toolchain, MSRV pinned in `rust-toolchain.toml` (currently *1.90.0*). Install via [rustup.rs][rustup.rs]. This is used by default for `cargo build`, `cargo check`, `cargo test`, etc.
+ * **Rust (Build/Test)**: **Stable** toolchain (CI runs *1.90.0*). Install via [rustup.rs][rustup.rs]. This is used by default for `cargo build`, `cargo check`, `cargo test`, etc.
* **Rust (Format)**: **Nightly** toolchain is required *only* for formatting (`cargo fmt`) due to unstable options used in our `rustfmt.toml` configuration.
* Install via: `rustup toolchain install nightly`
* **Rust Components**: `rustfmt`, `clippy` – install via `rustup component add rustfmt clippy`. Make sure these components are available for *both* your default stable toolchain and the nightly toolchain.
@@ -107,7 +112,7 @@ All crates live in one Cargo **workspace**, so `cargo ` from the repo root
1. Sync with `main`; rebase preferred.
2. Ensure your code is formatted correctly with `cargo +nightly fmt --all`.
-3. Ensure CI is green (build, fmt check, clippy, tests on macOS using appropriate toolchains).
+3. Ensure CI is green (fmt check, build, and tests on macOS arm64 and Linux x86_64).
4. Fill out the PR template; explain *why* + *how*.
5. Respond to review comments promptly – we’re friendly, promise!
6. Maintainers will *Squash & Merge* (unless history is already clean).
diff --git a/README.md b/README.md
index 48b224a..5f4b67c 100644
--- a/README.md
+++ b/README.md
@@ -6,114 +6,113 @@
- Lighting console bringing advanced features to solo performances.
+ A two-deck DJ app with a built-in lighting console.
## About
-⭕️ Halo is a real-time lighting console, designed to bring modern, immersive experiences into the hands of solo
-performers. Traditional consoles are typically deployed at front of house (FOH) and require a dedicated lighting
-designer. On the other hand, software designed for solo performers is often limited in features and is difficult to
-operate during a live show. Halo bridges this gap through a combination of pre-defined cues, beat-synchronized
-effects, and live improvisation through MIDI overrides. This enables performers to elevate their shows with immersive
-lighting that responds to their performance.
+**⭕️ Halo is a DJ app with a built-in lighting console, designed for solo performers who want to deliver immersive
+live shows.**
+
+Mix across two decks while Halo drives the lighting rig in sync with your set. Lighting cues can be prepared per track,
+then shaped and overridden live from a console-style programmer—so one performer can control the music, the lights, and
+the energy of the room from a single app, without relying on a dedicated lighting operator.
+
+Halo is designed to integrate seamlessly with the Ableton Push 2, providing hands-on real-time control and visual
+feedback without forcing you to perform through a mouse and keyboard.
+
+Built for macOS in Rust, Halo uses the [`timestretch`](https://github.com/robmorgan/timestretch-rs) engine for
+real-time tempo and pitch control.
-
+
> [!WARNING]
> This project is still in heavy development and unsuitable for production use (even though I'm using it for shows).
-
## Features
-* **Intuitive UI.** Featuring a Dashboard, Programmer, Cue Editor, Patch Panel, Show Manager, and Settings panels.
-* **Show File System.** Save and load complete shows with cues, effects, and fixture assignments.
-* **Programmer.** Control lighting fixtures using a professional programmer interface with real-time feedback.
-* **Cue System.** Create, save, and recall lighting scenes using cue lists with timecode synchronization.
-* **Effect Engine.** Beat synchronized effects engine with sine, sawtooth and square patterns plus customizable parameters.
-* **Pixel Engine.** Dedicated pixel engine for displaying various effects and colors on pixel bar fixtures.
-* **Multi-destination Art-Net.** Route different fixture types (traditional lighting, pixels) to separate Art-Net nodes.
-* **Audio Playback.** Integrated audio file playback synchronized with cues and Ableton Link.
-* **SMPTE Timecode.** Both internal and external timecode synchronization for precise show timing and automation.
-* **MIDI Integration.** Control your show with MIDI devices (currently supports Akai MPK49) with override system.
-* **Configuration System.** Persistent settings with UI-based configuration panel for audio, MIDI, and DMX preferences.
-* **Fixture Library.** Built-in support for various lighting fixtures with extensible fixture definitions.
-* **Async Module Architecture.** Separate modules for DMX (44Hz output), Audio, MIDI, and Timecode running concurrently.
+### DJ
+
+* **Dual decks** powered by one `timestretch` engine each: warm-start seeks, gapless loop wrap, and keylocked
+ tempo control.
+* **Full mixer chain** per deck: trim → 3-band isolator EQ (full-kill) → resonant LP/HP filter → channel fader,
+ into a constant-power crossfader, master fader, and soft limiter.
+* **CDJ-style transport**: play/pause and cue (set while paused, hold to preview, release to return).
+* **Hot cues** — 8 per deck, with Normal and Gated modes and optional quantize to the beat grid.
+* **Loops** — manual in/out, 4-beat quantized autoloop, and halve/double controls from 1/16 up to 16 beats.
+* **Tempo & sync** — tempo slider with ±8/±16/±50% ranges, keylock, pitch-bend nudges, and one-button sync that
+ locks BPM and beat phase to a master deck.
+* **Audible scrub** with momentum — grab the waveform and hear it, like dragging a platter.
+* **Rich waveforms** — 3-band RGB overview strip and a zoomed, centered-playhead view with beat/bar marks,
+ rendered from background track analysis.
+* **Track library** — SQLite-backed browser with playlists, search, sortable columns (BPM, key, duration, …),
+ folder import, and background analysis. BPM comes from analysis; musical key is read from file tags.
+* **Prepare & Perform views** — audition tracks on an independent third channel and edit cues in Prepare, then
+ play the show in Perform.
+* **Meters everywhere** — per-deck and master levels plus an audio-callback CPU meter.
+
+### Lighting
+
+* **Per-track cue lanes** (Lighting / Pixels / FX) under the waveforms, edited directly and persisted in the
+ library alongside the track.
+* **Console-style programmer** — fixture grid, group selects, and Intensity/Color/Position/Beam/Pixel FX views
+ with beat-synced effects; latch or flash overrides sit above track cues, with STORE-from-live.
+* **Real fixture engine** — a default rig patched from real fixture profiles, editable live in the PATCH tab
+ (profile, universe, address, grid position) and persisted to the library.
+* **Art-Net output** — a dedicated 44 Hz engine thread resolves cues + programmer state into per-universe DMX
+ frames and sends them over Art-Net (broadcast or unicast to a node), independent of the UI.
+
+See [ROADMAP.md](ROADMAP.md) for the full feature arc and what's next.
## Requirements
-* **macOS** (required for Core Audio and MIDI dependencies)
-* **Rust toolchain** (cargo, rustc) - MSRV: 1.90.0
-* **Network interface for Art-Net output** (e.g., [Enttec ODE MK2](https://support.enttec.com/support/solutions/articles/101000438016-ode-mk2-70405-70406-))
-* **Optional:** MIDI controller (e.g., Akai MPK49, Novation Launch Control XL)
-* **Optional:** Ableton Link compatible device/software for beat synchronization
+* **macOS 12+** (Core Audio via cpal; the UI uses the wgpu backend)
+* **Rust toolchain** (stable for building/testing; nightly only for `cargo +nightly fmt`)
+* **[`timestretch-rs`](https://github.com/robmorgan/timestretch-rs)** cloned alongside this repo (path dependency)
+* **Optional:** an Art-Net node and DMX fixtures for the lighting rig
## Installation
+Halo depends on the `timestretch` crate by local path, so clone the two repos side by side:
+
```bash
git clone https://github.com/robmorgan/halo.git
+git clone https://github.com/robmorgan/timestretch-rs.git
cd halo
cargo build --release
```
-## Usage
-
-### Basic Usage
-
-Start with Art-Net broadcast mode:
+To build a macOS app bundle (`Halo.app`):
```bash
-cargo run --release -- --source-ip
+cargo install cargo-bundle
+cargo bundle --release
```
-Load a show file:
+## Usage
```bash
-cargo run --release -- --source-ip --show-file shows/myshow.json
+cargo run --release
```
-### Multi-Destination Setup
-
-Route lighting and pixel fixtures to separate Art-Net nodes:
+Load tracks through the in-app library or file dialog, or pass a file directly to load it on launch:
```bash
-cargo run --release -- --source-ip 192.168.1.100 \
- --lighting-dest-ip 192.168.1.200 \
- --pixel-dest-ip 192.168.1.201 \
- --enable-midi
+cargo run --release -- path/to/track.mp3
```
-See [docs/multi-destination-artnet.md](docs/multi-destination-artnet.md) for detailed multi-destination configuration.
-
-### Command Line Options
-
-```bash
-USAGE:
- halo [OPTIONS]
-
-OPTIONS:
- --source-ip Art-Net source IP address (required)
- --dest-ip Single destination IP (legacy, optional)
- --lighting-dest-ip Lighting fixtures destination IP
- --pixel-dest-ip Pixel fixtures destination IP
- --lighting-universe Universe for lighting fixtures (default: 1)
- --pixel-start-universe Starting universe for pixel fixtures (default: 2)
- --artnet-port Art-Net port (default: 6454)
- --broadcast Force broadcast mode
- -m, --enable-midi Enable MIDI support
- --show-file Path to show JSON file
-```
+* **Prepare view** — import folders into the library, build playlists, audition tracks, and edit per-track
+ lighting cues.
+* **Perform view** — two decks, mixer, and the lighting programmer.
+* **Art-Net** — configure broadcast or unicast-to-node output in the in-app settings window; the choice is
+ persisted with the library.
+* **Logs** — set `RUST_LOG=debug` (or another filter) when launching from a terminal.
## Documentation
-For detailed documentation, see the [docs/](docs/) directory:
-
-* [Architecture Overview](docs/architecture.md) - System design and component structure
-* [CLI Reference](docs/cli-reference.md) - Complete command-line interface documentation
-* [Multi-Destination Art-Net](docs/multi-destination-artnet.md) - Setting up multiple Art-Net destinations
-* [Troubleshooting Guide](docs/troubleshooting.md) - Common issues and solutions
+* [ROADMAP.md](ROADMAP.md) — architecture overview, phased feature plan, and current status.
## License
diff --git a/TODO.md b/TODO.md
deleted file mode 100644
index 189ddb1..0000000
--- a/TODO.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# TODO
-
-## Input
-
-- [x] Use [crossterm](https://github.com/crossterm-rs/crossterm) for instant keyboard input.
-- [ ] OSC
-
-## UI
-
-- [ ] Programmer
- - [ ] Audio Playback
-
-## Engine
-
-- [ ] Cues
- - [ ] Cue Master
- - [ ] Cue Lists
-- [ ] Presets (gobos, position, color)
-- [ ] Color
- - [ ] Interpolated Fades (note: your cheap PARs cant blend colors)
-- [ ] Fixtures
- - [ ] Groups
diff --git a/_docs/screenshot.png b/_docs/screenshot.png
new file mode 100644
index 0000000..abe7105
Binary files /dev/null and b/_docs/screenshot.png differ
diff --git a/config.json b/config.json
deleted file mode 100644
index 7146a83..0000000
--- a/config.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "version": "0.1.0",
- "settings": {
- "target_fps": 60,
- "enable_autosave": false,
- "autosave_interval_secs": 300,
- "audio_device": "Default",
- "audio_buffer_size": 512,
- "audio_sample_rate": 48000,
- "midi_enabled": false,
- "midi_device": "None",
- "midi_channel": 1,
- "dmx_enabled": true,
- "dmx_broadcast": false,
- "dmx_source_ip": "192.168.1.100",
- "dmx_dest_ip": "192.168.1.200",
- "dmx_port": 6454,
- "wled_enabled": false,
- "wled_ip": "192.168.1.50",
- "pixel_engine_enabled": true,
- "pixel_engine_fps": 44.0,
- "pixel_universe_mapping": {},
- "enable_pan_tilt_limits": true
- },
- "created_at": "2025-10-13T02:53:54.682044+00:00",
- "modified_at": "2025-10-13T02:53:54.682105+00:00"
-}
diff --git a/config.template.json b/config.template.json
deleted file mode 100644
index 3973c21..0000000
--- a/config.template.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "version": "0.1.0",
- "settings": {
- "target_fps": 60,
- "enable_autosave": false,
- "autosave_interval_secs": 300,
- "audio_device": "Default",
- "audio_buffer_size": 512,
- "audio_sample_rate": 48000,
- "midi_enabled": false,
- "midi_device": "None",
- "midi_channel": 1,
- "dmx_enabled": true,
- "dmx_broadcast": false,
- "dmx_source_ip": "192.168.1.100",
- "dmx_dest_ip": "192.168.1.200",
- "dmx_port": 6454,
- "wled_enabled": false,
- "wled_ip": "192.168.1.50"
- },
- "created_at": "2025-01-13T10:00:00Z",
- "modified_at": "2025-01-13T10:00:00Z"
-}
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index 5d40c07..3cca57f 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,32 +1,8 @@
# Halo Documentation
-This directory contains comprehensive documentation for the Halo lighting console.
+Current documentation lives in [ROADMAP.md](../ROADMAP.md) at the repository root — it covers the architecture,
+the phased feature plan, and current status. See the top-level [README](../README.md) for build and usage
+instructions.
-## Table of Contents
-
-- [Multi-Destination Art-Net Setup](multi-destination-artnet.md) - Configure separate outputs for lighting and pixel fixtures
-- [CLI Reference](cli-reference.md) - Complete command-line interface documentation
-- [Architecture](architecture.md) - Technical architecture and implementation details
-- [Examples](examples.md) - Common usage scenarios and configurations
-- [Troubleshooting](troubleshooting.md) - Common issues and solutions
-
-## Quick Start
-
-For the most common use case of separating lighting and pixel outputs:
-
-```bash
-cargo run --release -- \
- --source-ip 192.168.1.100 \
- --lighting-dest-ip 192.168.1.200 \
- --pixel-dest-ip 192.168.1.201
-```
-
-This sends:
-- **Lighting fixtures** (universe 1) → `192.168.1.200` (e.g., Enttec Ode MK2)
-- **Pixel fixtures** (universes 2+) → `192.168.1.201` (e.g., Enttec Octo MK2)
-
-## Getting Help
-
-- Run `halo --help` for CLI usage
-- Check [troubleshooting.md](troubleshooting.md) for common issues
-- See [CLAUDE.md](../CLAUDE.md) for development commands and architecture overview
\ No newline at end of file
+The [legacy/](legacy/) directory contains documentation for the pre-pivot Halo lighting console (the old
+tokio-based Art-Net console). It no longer describes this codebase and is kept for reference only.
diff --git a/docs/legacy/README.md b/docs/legacy/README.md
new file mode 100644
index 0000000..5d40c07
--- /dev/null
+++ b/docs/legacy/README.md
@@ -0,0 +1,32 @@
+# Halo Documentation
+
+This directory contains comprehensive documentation for the Halo lighting console.
+
+## Table of Contents
+
+- [Multi-Destination Art-Net Setup](multi-destination-artnet.md) - Configure separate outputs for lighting and pixel fixtures
+- [CLI Reference](cli-reference.md) - Complete command-line interface documentation
+- [Architecture](architecture.md) - Technical architecture and implementation details
+- [Examples](examples.md) - Common usage scenarios and configurations
+- [Troubleshooting](troubleshooting.md) - Common issues and solutions
+
+## Quick Start
+
+For the most common use case of separating lighting and pixel outputs:
+
+```bash
+cargo run --release -- \
+ --source-ip 192.168.1.100 \
+ --lighting-dest-ip 192.168.1.200 \
+ --pixel-dest-ip 192.168.1.201
+```
+
+This sends:
+- **Lighting fixtures** (universe 1) → `192.168.1.200` (e.g., Enttec Ode MK2)
+- **Pixel fixtures** (universes 2+) → `192.168.1.201` (e.g., Enttec Octo MK2)
+
+## Getting Help
+
+- Run `halo --help` for CLI usage
+- Check [troubleshooting.md](troubleshooting.md) for common issues
+- See [CLAUDE.md](../CLAUDE.md) for development commands and architecture overview
\ No newline at end of file
diff --git a/docs/architecture.md b/docs/legacy/architecture.md
similarity index 100%
rename from docs/architecture.md
rename to docs/legacy/architecture.md
diff --git a/docs/cli-reference.md b/docs/legacy/cli-reference.md
similarity index 100%
rename from docs/cli-reference.md
rename to docs/legacy/cli-reference.md
diff --git a/docs/examples.md b/docs/legacy/examples.md
similarity index 100%
rename from docs/examples.md
rename to docs/legacy/examples.md
diff --git a/docs/multi-destination-artnet.md b/docs/legacy/multi-destination-artnet.md
similarity index 100%
rename from docs/multi-destination-artnet.md
rename to docs/legacy/multi-destination-artnet.md
diff --git a/docs/presets.md b/docs/legacy/presets.md
similarity index 100%
rename from docs/presets.md
rename to docs/legacy/presets.md
diff --git a/docs/troubleshooting.md b/docs/legacy/troubleshooting.md
similarity index 100%
rename from docs/troubleshooting.md
rename to docs/legacy/troubleshooting.md
diff --git a/start-capture.sh b/start-capture.sh
deleted file mode 100755
index fc4f027..0000000
--- a/start-capture.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-echo "Starting Halo for Capture..."
-#cargo run --release -- --source-ip 127.0.0.1 --lighting-dest-ip 127.0.0.1 --pixel-dest-ip 127.0.0.1 --show-file shows/Guys40th.json
-cargo run -- --source-ip 127.0.0.1 --lighting-dest-ip 127.0.0.1 --pixel-dest-ip 127.0.0.1 --broadcast --show-file shows/Jasons40th.json
diff --git a/start.sh b/start.sh
deleted file mode 100755
index a1f5f0b..0000000
--- a/start.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-echo "Starting Halo..."
-#cargo run -- --source-ip 10.143.62.113 --show-file shows/Guys40th.json
-#cargo run -- --source-ip 127.0.0.1 --dest-ip 10.8.45.80 --show-file shows/Guys40th.json
-#cargo run -- --source-ip 127.0.0.1 --dest-ip 10.8.45.80 --show-file shows/Guys40th.json
-#
-
-# doesn't work when capture is running so use this (for broadcast):
-#cargo run -- --source-ip 10.8.45.1 --show-file shows/Guys40th.json
-
-# unicast - using local IP address
-#cargo run -- --source-ip 192.168.1.131 --dest-ip 192.168.1.131 --show-file shows/Guys40th.json
-
-#cargo run -- --source-ip 192.168.1.131 --dest-ip 192.168.1.131 --show-file shows/Guys40th.json
-#cargo run -- --source-ip 10.8.45.1 --dest-ip 10.8.45.80 --show-file shows/Guys40th.json
-
-cargo run -- --source-ip 10.8.45.1 --lighting-dest-ip 10.8.45.80 --pixel-dest-ip 10.8.45.90 --pixel-start-universe 1 --show-file shows/Jasons40th.json