It's like mopidy but good.
Go to file
Test User 4e59e50943 Gate the gRPC surface behind basic-auth roles
crabidy-server.toml gains an [auth] section with one argon2 PHC hash
per role: owner (everything), queue-owner (queue and playback, no
library writes), queue-appender (browse, search, and Append only).
Enforcement is a single fail-closed tower layer in front of the tonic
service — unknown methods require owner, a malformed config aborts
startup, and a missing one keeps the server open as before. Successful
credentials are cached so argon2 runs once, failures re-verify at full
cost and stay indistinguishable. crabidy-server hash-password turns a
stdin password into the config hash; cbd-tui sends the header from new
user/password options.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 20:47:06 +02:00
.gitea Clean up a bit 2023-06-13 10:12:26 +02:00
architecture Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
audio-player Refetch mutable library listings and redact stream URLs from logs 2026-07-21 18:37:10 +02:00
cbd Bundle server and TUI into a single cbd binary 2026-07-21 14:15:47 +02:00
cbd-tui Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
crabidy-core Delete captures from disk at any depth, behind a confirmation 2026-07-21 20:34:03 +02:00
crabidy-server Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
fsdy Delete captures from disk at any depth, behind a confirmation 2026-07-21 20:34:03 +02:00
plan Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
quality Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
tidaldy Delete captures from disk at any depth, behind a confirmation 2026-07-21 20:34:03 +02:00
ytdy Delete captures from disk at any depth, behind a confirmation 2026-07-21 20:34:03 +02:00
.editorconfig Add cross compile release flow 2023-06-12 09:38:19 +02:00
.gitignore Add devenv-based dev environment and README 2026-07-19 21:29:23 +02:00
Cargo.lock Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
Cargo.toml Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
Cross.toml Generate x86_64 target 2023-06-12 18:21:58 +02:00
README.md Gate the gRPC surface behind basic-auth roles 2026-07-21 20:47:06 +02:00
aarch64-unknown-linux-gnu-Dockerfile Try to add release files 2023-06-12 18:06:00 +02:00
armv7-unknown-linux-gnueabihf-Dockerfile Try to add release files 2023-06-12 18:06:00 +02:00
devenv-rust.nix Add devenv-based dev environment and README 2026-07-19 21:29:23 +02:00
devenv.lock Add devenv-based dev environment and README 2026-07-19 21:29:23 +02:00
devenv.nix Fetch streams in bounded windows and restore yt-dlp for stream URLs 2026-07-21 18:18:40 +02:00
devenv.yaml Add devenv-based dev environment and README 2026-07-19 21:29:23 +02:00
rust-toolchain.toml Add devenv-based dev environment and README 2026-07-19 21:29:23 +02:00
x86_64-unknown-linux-gnu-Dockerfile Generate x86_64 target 2023-06-12 18:21:58 +02:00

README.md

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:

/
├── 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.
  • 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.

Quick start

The toolchain is managed by devenv:

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
ytdy.toml YouTube ytdy/README.md
fsdy.toml local fs fsdy/README.md
cbd-tui.toml TUI / cbd below
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.

cbd-tui.toml

Configuration of the TUI (and the TUI half of cbd):

# Where to find the server. Default shown.
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 ...).

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.
[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.

  • 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.

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.