# Filesystem — /fs The filesystem provider (crate `fsdy`) serves a single local music folder under `/fs`. It does not read audio tags: instead it walks the directory tree and treats small TOML files with a well-known suffix as **serialized track nodes** — each one carries a track's metadata and a reference to the thing that actually plays. Folders become library nodes; `*.cbd-track.toml` files become tracks. Everything else in the tree (other files, hidden entries, symlinks) is ignored. ## Configuration — `~/.config/crabidy/fsdy.toml` The file has a single field: ```toml # Absolute path of the directory exposed under /fs. When unset, the # platform music directory (dirs::audio_dir(), e.g. ~/Music) is used. root = "/home/me/Music" ``` A missing or empty file is fine — the default root is used. A root that does not exist yet is accepted; listing it simply fails until it appears. If neither a configured root nor a platform music directory is available, the provider disables itself with a warning rather than taking the server down. ## The track-file format A file named `.cbd-track.toml` inside the root is a track. The schema is: ```toml # Required. title = "We Will Rock You" # Optional; empty when omitted (web radio streams often have no artist). artist = "Queen" # Optional, in seconds. duration = 122 # Optional. [album] title = "News of the World" release_date = "1977-10-28" # Required: exactly one playable (see below). [playable] file = "../flac/we-will-rock-you.flac" ``` The `[playable]` table must set **exactly one** of five fields: - `file` — a local audio file (see resolution below). - `url` — an `http(s)` URL streamed by the player. - `link` — an absolute crabidy path owned by another provider, e.g. `/tidal/artists/3634161/536243361`. - `store` — the bare name of an entry in the content-addressed store, written by download captures (see [The crabidy store](./store.md)). - `skipped = true` — the track has no playable audio; playback skips it. (`skipped = false` counts as unset.) ```admonish info A file that is not valid TOML, or that sets zero or several playables, is **skipped with a warning** at listing time. It never panics and never poisons its sibling files — the rest of the directory still lists. ``` ### How a `file` playable resolves - An **absolute** path is used as-is. - A **relative** path is joined onto the directory containing the track file, so a whole music folder stays relocatable. Existence is not checked while listing; a dead reference surfaces at play time as the player's normal "cannot open" warning, and playback moves on. ### How a `link` playable resolves When the provider builds a track from a `link` file, it sets the track's path to the **link target**, not to the `/fs` path. From then on the track *is* a track of the target's provider as far as the queue and playback are concerned — the orchestrator's prefix routing does the rest. Links resolve exactly **one hop**: `get_urls_for_track` on an `/fs` path never follows a link, so a link whose target is itself a link file dies at play time with a warning, and cycles cannot recurse. The metadata shown is what the file says, not the target's live metadata. ## Path-to-disk mapping Library paths mirror the directory tree: `/fs///…`, where each segment is the percent-encoded file name (the same encoding search terms use), so names with spaces, `%`, or unicode survive the path scheme. Mapping a path back to disk is a **safe descent**: each segment is decoded and rejected if it is empty, `.`, `..`, or contains a path separator. The joined path is always a pure descent from the root, so a client-supplied path cannot escape the configured folder. Symlinks are skipped during listing, so they cannot lead out of the root either. ## Listing behavior - Directories and track files are each sorted case-insensitively by file name — a deterministic queueing order. Prefix file names with `01`, `02`, … to order an album. - Directories are queueable nodes; queueing one resolves its whole subtree, one chunk per directory. - **Nothing is cached.** Every navigation reads the directory fresh, so edits made with an ordinary file manager appear on the next visit — there is no file watching and no reload step. Creating track files through the library is not supported here; they are made and edited with normal file tools. (Other instances of the same crate — the `/crabidy` saves — do support renaming and deleting; see [The crabidy store](./store.md).)