diff --git a/README.md b/README.md
index ba9a3bc..7a40df8 100644
--- a/README.md
+++ b/README.md
@@ -1,72 +1,153 @@
-# decks
-
-Local-first AI library assistant for Rekordbox DJs โ audit, clean, and
-re-cue a music library with a Claude agent that can only act through
-reviewable staged changes.
-
-**Status:** MVP in progress. Core desktop workflows and the local MCP
-tooling work; real-library validation and a first tagged release (v0.1.0)
-remain.
-
-
-
-## The problem
+
decks
+
+An AI assistant that cleans up a DJ's music library โ and can't change anything you haven't approved
+
+
+ DJs keep thousands of tracks in Rekordbox, but fixing messy titles, missing cue points,
+ duplicates, and broken file paths happens one track at a time. decks audits the whole library,
+ lets a Claude agent propose fixes in bulk, and stages every change for review before it's written.
+
+
+
+ ๐ Run locally ยท
+ ๐บ Roadmap ยท
+ ๐ Feature-parity matrix
+
+
+
+
+
+
+
+
+
+
+
+ ๐ฆ Rust core, ~20 crates ยท
+ ๐ฅ๏ธ Tauri 2 desktop app ยท
+ ๐ Same tools exposed as an MCP server and a CLI ยท
+ ๐ก No telemetry
+
+
+
+
+
+> [!NOTE]
+> **Status: MVP in progress.** Core desktop workflows and the local MCP tooling
+> work; real-library validation and a first tagged release (v0.1.0) remain.
+
+---
+
+### Menu
+
+- [Features](#-features)
+- [The problem](#-the-problem)
+- [How it works](#-how-it-works)
+- [Run it locally](#-run-it-locally)
+- [Scope and non-goals](#-scope-and-non-goals)
+- [Tradeoffs](#-tradeoffs)
+- [Known limitations](#-known-limitations-and-failure-modes)
+- [What I'd do next](#-what-id-do-next)
+- [Stack](#-stack)
+
+---
+
+## โจ Features
+
+- **Library audits** โ tracks with no cues, tracks in no playlist, inconsistent artist and title formatting
+- **Audio duplicate detection** and **broken-path relocation**
+- **Smart Fixes and Cleanup** that propose changes across thousands of tracks at once
+- **A Claude agent in the app** that can see only what you've shown it and can only act through reviewable changes
+- **Every edit is staged** โ `Proposed โ Accepted/Rejected โ Exported/Applied`, previewable as a diff
+- **Safe write-back** through Rekordbox XML export, or an opt-in direct sync with an automatic backup
+- **One tool service, three surfaces** โ the in-app chat, an MCP server for any MCP host, and a CLI
+- **Everything on your machine** โ no telemetry; the Anthropic key lives in the OS keychain
+
+---
+
+## ๐งฉ The problem
Rekordbox is built for performing, not for library hygiene. Normalizing
artist and title formatting across thousands of tracks, finding tracks with
no cues or no playlist, spotting audio duplicates, and relocating broken
file paths are all one-track-at-a-time chores in its UI. The paid benchmark
for this job is Lexicon DJ; decks is working toward Lexicon parity within
-Rekordbox (the parity matrix in `docs/lexicon/PARITY.md` drives the
-roadmap) as a local-first desktop app with an agent attached โ one that can
-see only what you've shown it and can only write through staged,
+Rekordbox (the parity matrix in [`docs/lexicon/PARITY.md`](docs/lexicon/PARITY.md)
+drives the roadmap) as a local-first desktop app with an agent attached โ one
+that can see only what you've shown it and can only write through staged,
reversible changes.
-## How it works
+---
+
+## ๐ง How it works
+
+```mermaid
+flowchart LR
+ UI[React UI
Tauri 2] -->|typed IPC| T[Rust tool service]
+ C[Claude chat panel] --> T
+ M[MCP server
decks mcp] --> T
+ L[CLI
decks tools call] --> T
+ T -->|read-only| R[(Rekordbox master.db
SQLCipher + ANLZ)]
+ T --> S[Staged changes
Proposed โ Accepted]
+ S -->|default| X[Rekordbox XML export]
+ S -.->|opt-in Sync,
WriteGuard + backup| R
+```
-- A Tauri 2 desktop app: React/TypeScript frontend over a Rust workspace
+- **A Tauri 2 desktop app:** React/TypeScript frontend over a Rust workspace
(~20 crates, one per bounded concern), with typed IPC between them.
-- `crates/rekordbox-db` opens Rekordbox 7's SQLCipher `master.db` directly,
- read-only, and parses the native ANLZ files (beat grids, color
- waveforms). Audio features, waveform peaks, fingerprints, and chat
- history live in a local SQLite (WAL) cache.
-- Every mutation โ from the agent, Smart Fixes, Cleanup, or the Duplicates
- view โ is a staged change: `Proposed โ Accepted/Rejected โ
+- **Reads Rekordbox directly.** `crates/rekordbox-db` opens Rekordbox 7's
+ SQLCipher `master.db`, read-only, and parses the native ANLZ files (beat
+ grids, color waveforms). Audio features, waveform peaks, fingerprints, and
+ chat history live in a local SQLite (WAL) cache.
+- **Every mutation is a staged change** โ from the agent, Smart Fixes,
+ Cleanup, or the Duplicates view: `Proposed โ Accepted/Rejected โ
Exported/Applied`, previewable as a diff. The default egress is
- round-trip-tested Rekordbox XML export; an opt-in Sync flow writes
- directly to `master.db` under a `WriteGuard`.
-- The same Rust tool service backs three surfaces at once: the in-app
- Claude chat panel, an MCP server (`decks mcp` / `decks mcp-http`) usable
- from any MCP host on your existing subscription, and a `decks tools call`
- CLI.
-- Everything runs on your machine. No telemetry; enrichment APIs
- (MusicBrainz, opt-in Discogs) only fire if enabled, through a local
- cache. The Anthropic key lives in the OS keychain.
-
-## Running it
-
-Requires Rust stable, Node 20+, pnpm 9+, and a Rekordbox 7 library
-(`master.db`) to point at.
-
- git clone https://github.com/cole-hackman/decks
- cd decks
- ./scripts/dev.sh
-
-Tests run against synthetic fixture libraries in `fixtures/` โ no real
+ round-trip-tested Rekordbox XML export; an opt-in Sync flow writes directly
+ to `master.db` under a `WriteGuard`.
+- **One tool service, three surfaces:** the in-app Claude chat panel, an MCP
+ server (`decks mcp` / `decks mcp-http`) usable from any MCP host on your
+ existing subscription, and a `decks tools call` CLI.
+- **Everything runs on your machine.** No telemetry; enrichment APIs
+ (MusicBrainz, opt-in Discogs) only fire if enabled, through a local cache.
+
+---
+
+## ๐ Run it locally
+
+Requirements:
+
+- [Rust stable](https://www.rust-lang.org/tools/install)
+- [Node 20+](https://nodejs.org/) and [pnpm 9+](https://pnpm.io/)
+- A Rekordbox 7 library (`master.db`) to point at
+
+```bash
+git clone https://github.com/cole-hackman/decks
+cd decks
+./scripts/dev.sh
+```
+
+**Tests** run against synthetic fixture libraries in `fixtures/` โ no real
library needed:
- cargo test --workspace
- pnpm test && pnpm typecheck && pnpm lint
- pnpm e2e # Playwright
- ./scripts/real-library-smoke.sh # data-layer smoke vs a real master.db copy
+```bash
+cargo test --workspace
+pnpm test && pnpm typecheck && pnpm lint
+pnpm e2e # Playwright
+./scripts/real-library-smoke.sh # data-layer smoke vs a real master.db copy
+```
+
+---
-## Scope and non-goals
+## ๐ฏ Scope and non-goals
**In scope:** Rekordbox 7, deep โ browsing, auditing, smart fixes,
duplicates, relocation, cues, smartlists, staged edits back to the
@@ -80,7 +161,9 @@ library.
- Silent fixes. Playlist duplicate entries are surfaced, not auto-removed;
every change is staged for review.
-## Tradeoffs
+---
+
+## ๐ Tradeoffs
**Staged changes everywhere, direct writes almost nowhere.** The founding
invariant was "never mutate `master.db`" โ all edits stage into a
@@ -101,7 +184,9 @@ to it. The cost: the system WebView differs per OS (Safari, WebView2,
WebKitGTK), so rendering must be verified on each platform instead of once
in a bundled Chromium.
-## Known limitations and failure modes
+---
+
+## ๐ง Known limitations and failure modes
- It has not been validated against a real library at scale yet โ that's
the line between here and v0.1.0. Synthetic fixtures cover the test
@@ -121,16 +206,34 @@ in a bundled Chromium.
- No telemetry cuts both ways: nothing phones home, and nothing tells me
what broke on someone else's machine.
-## What I'd do next
+---
+
+## ๐งญ What I'd do next
-1. Real-library validation and the v0.1.0 release โ the smoke harness
+1. **Real-library validation and the v0.1.0 release** โ the smoke harness
exists; it needs to be run in anger against large libraries.
-2. Work down the Lexicon parity matrix (`docs/lexicon/PARITY.md`) โ one
- epic per branch, already queued in `docs/ROADMAP.md`.
-3. Put Linux in the CI matrix and get e2e running in CI, so the
+2. **Work down the Lexicon parity matrix** ([`docs/lexicon/PARITY.md`](docs/lexicon/PARITY.md))
+ โ one epic per branch, already queued in [`docs/ROADMAP.md`](docs/ROADMAP.md).
+3. **Put Linux in the CI matrix and get e2e running in CI,** so the
three-WebView cost of the Tauri decision is actually paid down.
-## Stack
+---
+
+## ๐งฑ Stack
+
+| Layer | Technology |
+|---|---|
+| Desktop shell | Tauri 2 |
+| Core | Rust (~20-crate workspace) ยท SQLite / SQLCipher |
+| Frontend | React ยท TypeScript ยท Vite ยท Tailwind |
+| AI | Claude (in-app chat) ยท MCP server |
+| CI | GitHub Actions โ Rust fmt, clippy and tests on macOS and Windows; frontend typecheck, lint and vitest |
+
+## ๐ License
+
+GPL-3.0-or-later โ see [LICENSE](LICENSE) and [NOTICE](NOTICE).
+
+decks is not affiliated with or endorsed by AlphaTheta / Pioneer DJ (Rekordbox)
+or Lexicon DJ.
-Tauri 2 ยท Rust ยท React ยท TypeScript ยท Vite ยท Tailwind ยท SQLite/SQLCipher ยท
-GPL-3.0-or-later
+Built by [Cole Hackman](https://colehackman.com).