crabidy/README.md

191 lines
7.9 KiB
Markdown

# crabidy
A client/server music player. A headless gRPC server owns the library,
the play queue, and audio output; a terminal UI connects to it over
localhost (or the network). Media comes from pluggable **providers**,
each mounted as a subtree of one library:
```text
/
├── tidal Tidal streaming (see tidaldy/README.md)
├── youtube YouTube search & playlists (see ytdy/README.md)
├── fs a local music folder (see fsdy/README.md)
├── queues saved play queues (managed by the server)
├── bookmarks link snapshots of library subtrees (`w`)
└── captures downloaded snapshots with local audio (`W`)
```
## Binaries
- `crabidy-server` — the server: providers, queue, playback, gRPC on
`0.0.0.0:50051`. Also serves the web client at that address (see
below).
- `cbd-tui` — the terminal client. Press `?` inside for all key
bindings.
- `cbd` — both in one process: starts the server, waits until it
accepts connections, then runs the TUI. Adopts an already-running
server instead of failing on an occupied port.
- `cbd-web` — the browser client (Leptos/WASM), with the same
functionality as the TUI. Not run directly: it is built to a bundle
and embedded into `crabidy-server` (see
[cbd-web/README.md](cbd-web/README.md)).
## Quick start
The toolchain is managed by [devenv](https://devenv.sh):
```sh
devenv shell # provides rust, yt-dlp, and friends
cargo run -p cbd # server + TUI in one process
```
Or run the halves separately: `cargo run -p crabidy-server` and, in
another terminal, `cargo run -p cbd-tui`.
## Configuration
All configuration lives in `~/.config/crabidy/` (the platform config
directory). Every file is optional; missing providers simply do not
mount. Files are created/rewritten on first start with their defaults
filled in.
| File | Component | Documentation |
| -------------------- | ---------- | -------------------------------------- |
| `tidaly.toml` | Tidal | [tidaldy/README.md](tidaldy/README.md) |
| `ytdy.toml` | YouTube | [ytdy/README.md](ytdy/README.md) |
| `fsdy.toml` | local fs | [fsdy/README.md](fsdy/README.md) |
| `cbd-tui.toml` | `cbd-tui` | below |
| `cbd.toml` | `cbd` | below (same options as `cbd-tui.toml`) |
| `crabidy-server.toml`| server | below (never auto-created) |
The server-managed folders (`queues/`, `bookmarks/`, `captures/`) also
live in `~/.config/crabidy/`; they need no configuration and hold plain
folders of track files in the format documented in
[fsdy/README.md](fsdy/README.md).
### `cbd-tui.toml` and `cbd.toml`
Client configuration. `cbd-tui` (the standalone terminal client) reads
`cbd-tui.toml`; `cbd` (server + TUI in one process) reads its own
`cbd.toml`. They are **separate files with the same options** so the two
can run side by side on one machine — a common setup is `cbd` playing
locally against its in-process server while `cbd-tui` points at a remote
server (e.g. a Raspberry Pi). A shared file would force one to follow
the other's `address`.
```toml
# Where to find the server. Default (both files): localhost, which is
# what cbd's own in-process server listens on. Point cbd-tui.toml at a
# remote server to use it as a remote control.
address = "http://127.0.0.1:50051"
# Credentials, when the server has [auth] configured (see below).
# `user` is the role name; leave both empty against an open server.
# The password is stored in plaintext — keep this file private.
user = ""
password = ""
# Show the frequency-spectrum bars under the track progress. Default true.
spectrum = true
```
Every option is also available as a command-line flag
(`cbd-tui --address ...`, `cbd --address ...`).
### `crabidy-server.toml` — roles and rights
By default the server is open: everyone who can reach the port has
full control. Adding an `[auth]` section turns on HTTP basic auth for
every RPC and hands out *roles* (see `architecture/roles-auth.md`):
- **owner** — everything (the normal user).
- **queue-owner** — anything on the queue and playback, but no
library writes: no bookmarks (`w`), captures (`W`), queue saving,
renames or deletes.
- **queue-appender** — may browse/search and append tracks to the
queue; nothing else.
```toml
[auth]
# One PHC hash per role; omit a role to disable it. Generate with:
# crabidy-server hash-password (reads the password from stdin)
owner = "$argon2id$v=19$m=19456,t=2,p=1$..."
queue_owner = "$argon2id$..."
queue_appender = "$argon2id$..."
```
Clients authenticate with the role name as the basic-auth user (see
`cbd-tui.toml` above). A malformed `crabidy-server.toml` aborts server
startup rather than silently running open. Note that the transport is
plain HTTP/2: fine on a trusted home network, but anything exposed
further needs TLS termination (reverse proxy, VPN) in front.
## Using the library
Navigation is vim-style: `j`/`k` select, `l` enters the selected
folder, `h` goes to the parent, `Tab` switches between library and
queue, `Enter` replaces the queue with the selection. `%` creates a
node where the pane title shows `% to add` (e.g. a search term), `e`
renames, `d` deletes. `/` filters the current pane (library or queue)
live as you type — `Enter` keeps the filter, `Esc` clears it.
- `w` saves the selection as a **bookmark** (links; needs the source
provider to replay) or, in the queue pane, saves the queue.
- `W` **captures** the selection: the subtree is mirrored under
`/captures/<name>` with every track's audio downloaded next to its
metadata — fully local playback afterwards. In the queue pane `W`
captures the current queue directly (no need to save it first).
Tracks that are already local (from `/fs` or another capture) are
copied in rather than re-downloaded, so a queue mixing streamed and
local tracks captures completely. Captures are incremental:
re-capturing the same name resumes and completes it; tracks whose
source genuinely cannot be captured are recorded as *skipped* (red in
the UI, skipped by playback). Download captures can take long;
progress is shown in the library pane. Inside `/captures`, `d` deletes
any
folder or single track *from disk* (audio included) after a `y/N`
confirmation.
Press `?` for the full binding table.
A row of frequency-spectrum bars is drawn under the track progress
while audio plays (the server taps its own output, runs the FFT, and
streams the bars, so it works whether the server is local or remote).
Turn it off with `spectrum = false` in the client config.
## Web client
`crabidy-server` serves a browser client with the same functionality as
the TUI at its own address (`http://<server>:50051/`) — same navigation,
same keys (`j`/`k`/`h`/`l`, `%`, `e`, `d`, `w`, `W`, queue and playback
controls, `?` for help), plus clickable equivalents and a light/dark
theme toggle. It talks gRPC-web to the same service the TUI uses, so it
honors the same `[auth]` roles (it shows a login form when the server
requires credentials).
It is compiled to a WASM bundle and embedded into the server binary,
behind the default-on `web-ui` cargo feature. A plain `cargo build`
needs no WASM toolchain — it embeds a "not built" placeholder page until
you build the bundle:
```sh
devenv shell -- build-web # writes cbd-web/dist
cargo build -p crabidy-server # embeds it
```
Build the server with `--no-default-features` for a headless,
gRPC-only binary. See [cbd-web/README.md](cbd-web/README.md) for the
dev loop and details.
## Logs
`cbd` and `cbd-tui` log to `~/.local/state/crabidy/` (daily files);
`crabidy-server` logs to stderr. Stream URLs and credentials are
redacted from logs by design.
## Development
Design documents live in `architecture/`, per-feature quality gates in
`quality/`, and implementation plans in `plan/`. See `CLAUDE.md` /
`AGENTS.md` for the development workflow and coding rules.