Development
Setup and checks
uv sync # install with dev dependencies
uv run bester-ytm # run the TUI from the working tree
uv run pytest -q # tests (fast: no network, no mpv, no sleeps)
uv run pytest -q --cov=bester_ytm --cov-report=term # coverage report
# CI enforces the 80% gate (--cov-fail-under=80 in .github/workflows/ci.yml)
uv run ruff check . # lint
uv run mypy src # type check
CI runs the same lint, type check, and coverage gate on every push and pull request, on Python 3.11 and 3.13. Contribution rules live in CONTRIBUTING.md.
Releasing
Bump the version in pyproject.toml and src/bester_ytm/__init__.py, add a
## [X.Y.Z] section to CHANGELOG.md, commit, and push a vX.Y.Z tag. The
Release workflow fails unless tag, both version strings, and the changelog
section agree; it then re-runs all checks and publishes the GitHub release
with notes extracted from the changelog.
Layout and conventions
src/bester_ytm/
├── cli.py, cli_play.py, cli_config.py Typer commands (thin; no API logic)
├── tui.py + tui_*.py Textual app shell and action mixins
├── playback.py PlaybackController: queue, history, mpv
├── transitions.py, deck.py, fader.py dual-deck crossfade engine
├── playback_status.py, transition_settings.py shared dataclasses
├── mpv_ipc.py mpv JSON IPC transport
├── ytm_client.py + ytm_*.py YouTube Music access: facade over
│ session, search, library, models
├── auth.py, config.py, config_options.py logins, paths, config.toml
├── playlist_plan.py, playlist_builder.py, playlist_create.py, resolver.py
├── stores.py, search_query.py, similar.py
└── intelligence/ AI providers (heuristic, codex, openai, anthropic)
- UI layers (
cli*,tui*) never call ytmusicapi or spawn mpv directly; they go throughytm_client.pyandplayback.py. - Modules stay under ~300 lines, functions under ~30, full type hints.
- Errors are raised as
ConfigError/PlaybackError/YTMClientErrorwith actionable messages. - Tests fake mpv at the
subprocess.Popen/ IPC seams and inject clocks; the whole suite must stay under ~15 seconds.
See Architecture for the dual-deck engine design and its invariants, and Manual Testing for the credentialed, audio-producing checks that unit tests intentionally skip.
Documentation
This site is built with MkDocs Material:
uv sync --group docs
uv run mkdocs serve # live preview at http://127.0.0.1:8000
It deploys to GitHub Pages automatically on every push to main.