178 lines
7.3 KiB
Markdown
178 lines
7.3 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 = ""
|
|
```
|
|
|
|
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. Captures are incremental:
|
|
re-capturing the same name resumes and completes it; tracks whose
|
|
source 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.
|
|
|
|
## 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.
|