A proof-of-concept music library manager inspired by beets.
This project is in its very early stages. And I am still learning Rust.
Phase 0: Proof of Concept (In Progress)
The core scaffold is complete. MusicBrainz search integration is working. Currently implementing the remaining auto-tagging workflow components (scoring, track mapping, tag writing).
- TUI interface with ratatui
- Sequential directory scanning with concurrent MusicBrainz searching
- Metadata extraction from MP3, M4A, and FLAC files
- Duration calculation from audio streams (MP3, FLAC, M4A)
- Album clustering based on directory and tags
- Multi-disc album support with proper track sorting
- Interactive cluster detail view with track listings
- Keyboard navigation (j/k, arrows, space, Enter)
- MusicBrainz API client with rate limiting (1 req/sec)
- Concurrent scan/search pipeline with bounded queue
- Basic match result display (artist, title, date, track count)
See ROADMAP.md for the complete development plan.
Immediate next steps (completing auto-tagging workflow):
- Similarity scoring algorithm (0-100% match confidence)
- Track mapping preview showing proposed tag changes
- Manual search implementation (enter custom artist/album query)
- Dry-run tag writing (show what would be written without modifying files)
- Apply functionality (actually write tags to files)
- Proper handling of NoResults and Error cases
The goal is to replicate beets' core auto-tagging experience: scan → auto-search → score matches → prompt → preview changes → apply.
cargo buildScan current directory:
cargo run
# or after building: tuneScan specific directory:
cargo run /path/to/music
# or after building: tune /path/to/musicScanning screen:
Enter- Continue to cluster list (when scan complete)qorCtrl-C- Quit
Cluster list screen:
↑/↓orj/k- Navigate clustersSpaceorEnter- View cluster detailsqorCtrl-C- Quit
Cluster detail screen:
↑/↓orj/k- Navigate tracksEscorh- Back to cluster listqorCtrl-C- Quit
src/
main.rs - Entry point (argument parsing only)
app.rs - Application state machine and event loop
ui.rs - TUI rendering for each state
models.rs - Domain types (AudioFile, AlbumCluster)
codecs.rs - Audio codec enumeration
scanner.rs - Directory scanning and clustering (with rayon parallelism)
scanner/
metadata.rs - Tag extraction by format (MP3, M4A, FLAC)
musicbrainz/
mod.rs - Public API and SearchMessage types
client.rs - Rate-limited MusicBrainz API wrapper
search.rs - Search logic with message passing
Separation of Concerns:
main.rshandles only argument parsing and error reportingapp.rsowns the application lifecycle and event loopterminal.rsencapsulates crossterm setup/teardown- UI rendering is isolated from business logic
Error Handling:
color_eyre::eyre::Resultfor application-level errors- Beautiful error reports with backtraces and suggestions
- Proper cleanup via RAII (terminal restoration happens even on panic)
- Context added to errors for debugging
State Machine:
- Explicit
AppStateenum prevents invalid states - State transitions are centralized in
app.rs - Each state has well-defined entry/exit behavior
Modularity:
- Scanner functionality is split into public API (mod.rs) and implementation details (metadata.rs)
- Future expansion: add
matching/,musicbrainz/modules without changing existing code
- ROADMAP.md - Complete development plan through all phases
- REFACTORING.md - Explanation of architectural decisions
- PATTERNS.md - Rust patterns used in the project
- COLOR_EYRE.md - Error handling with color-eyre
- CLAUDE.md - Project context for Claude Code
- ratatui - TUI framework
- crossterm - Terminal handling (backend for ratatui)
- rayon - Data parallelism for concurrent directory scanning
- musicbrainz_rs - MusicBrainz API wrapper (not yet used)
- tokio - Async runtime (for future MusicBrainz calls)
- id3, mp4ameta, metaflac - Tag reading libraries
- mp3-duration - Calculate MP3 duration from audio stream
- walkdir - Directory traversal
- color-eyre - Error handling with beautiful reports
- strsim - String similarity (for matching algorithm)
Enable backtraces for debugging:
RUST_BACKTRACE=1 cargo run /path/to/music
# or after building: RUST_BACKTRACE=1 tune /path/to/musicThe project follows idiomatic Rust practices:
- Pure functions where possible
- Clear ownership boundaries
- Explicit error handling
- Minimal
unsafecode (currently none)
See PATTERNS.md for detailed explanations of patterns used.
This is a personal learning project, but observations and suggestions are welcome.
When adding features:
- Read the relevant section in ROADMAP.md
- Follow patterns from existing code
- Add tests for new functionality
- Update documentation
To be determined (project is in early stages)