No description
  • Rust 82.1%
  • Just 14.2%
  • Dockerfile 3.7%
Find a file
2026-05-14 10:00:27 +02:00
src Remove --by-id in favour of --source-id 2026-05-14 08:52:53 +02:00
.containerignore Add Containerfile for minimal Alpine-based image 2026-05-14 09:14:01 +02:00
.env.sample Add Justfile and .env.sample 2026-05-14 08:35:26 +02:00
.gitignore Ignore .claude/ directory 2026-05-14 09:05:04 +02:00
Cargo.lock Release 1.0.0 2026-05-14 09:02:18 +02:00
Cargo.toml Release 1.0.0 2026-05-14 09:02:18 +02:00
Containerfile Add Containerfile for minimal Alpine-based image 2026-05-14 09:14:01 +02:00
Justfile Add Containerfile for minimal Alpine-based image 2026-05-14 09:14:01 +02:00
README.md Document absence of tests and rationale 2026-05-14 10:00:27 +02:00
subsonic-shuffler.container Fix Quadlet .container file 2026-05-14 09:38:36 +02:00

Disclaimer: This project is completely AI generated.

subsonic-shuffler

A command-line tool that shuffles a Subsonic / OpenSubsonic playlist. It can shuffle a playlist in-place or write the shuffled result to a different playlist.

Requirements

  • Rust toolchain (edition 2021, MSRV 1.85)
  • just (optional, for the convenience recipes)
  • A Subsonic-compatible server (Navidrome, Gonic, etc.)

Configuration

Credentials are read from environment variables:

Variable Description
SUBSONIC_URL Server base URL
SUBSONIC_USER Username
SUBSONIC_PASSWORD Password

Copy .env.sample to .env and fill in your values. The just recipes load .env automatically.

cp .env.sample .env
$EDITOR .env

Usage

subsonic-shuffler [OPTIONS] [PLAYLIST]

Source options

The source playlist can be specified as a positional argument (by name) or via a flag:

Option Description
PLAYLIST Source playlist name (positional)
--source <NAME> Source playlist by name
--source-id <ID> Source playlist by ID

If multiple playlists share the same name, the tool errors and lists each one with its ID so you can switch to --source-id.

Destination options

If no destination option is given, the source playlist is shuffled in-place.

Option Description
(none) Shuffle the source playlist in-place
--create <NAME> Create a new playlist; fails if a playlist with that name already exists
--output <NAME> Write to a playlist by name; creates it if missing, overwrites if it exists
--output-id <ID> Overwrite an existing playlist by ID

--create, --output, and --output-id are mutually exclusive.

Examples

Shuffle a playlist in-place:

subsonic-shuffler "My Playlist"
subsonic-shuffler --source "My Playlist"
subsonic-shuffler --source-id 42

Create a new shuffled copy (fails if Shuffle Queue already exists):

subsonic-shuffler "My Playlist" --create "Shuffle Queue"

Write the shuffled result to an existing-or-new playlist:

subsonic-shuffler "My Playlist" --output "Shuffle Queue"

Overwrite a specific playlist by ID:

subsonic-shuffler "My Playlist" --output-id 99

Just recipes

just shuffle "My Playlist"                        # in-place by name
just shuffle-id 42                                # in-place by ID
just shuffle-create "My Playlist" "Shuffle Queue" # create new (fails if exists)
just shuffle-output "My Playlist" "Shuffle Queue" # create or overwrite by name
just shuffle-output-id "My Playlist" 99           # overwrite by ID
just build                                        # release build

Container

Pre-built images for x86_64 are published to the Forgejo registry:

forgejo.victorsavu.eu/victor/subsonic-shuffler:latest
forgejo.victorsavu.eu/victor/subsonic-shuffler:1.0.0

Pass credentials as environment variables and append arguments after the image name:

podman run --rm \
  -e SUBSONIC_URL=https://your-server.example.com \
  -e SUBSONIC_USER=your-username \
  -e SUBSONIC_PASSWORD=your-password \
  forgejo.victorsavu.eu/victor/subsonic-shuffler:latest \
  "My Playlist"

Any option that works with the binary works the same way:

podman run --rm \
  -e SUBSONIC_URL=... -e SUBSONIC_USER=... -e SUBSONIC_PASSWORD=... \
  forgejo.victorsavu.eu/victor/subsonic-shuffler:latest \
  --source "My Library" --output "Shuffle Queue"

Testing

This project has no unit tests. All meaningful logic is Subsonic API calls, so unit tests would require mocking the entire client and verify nothing real. Meaningful test coverage would require an integration test against a live server (e.g. a local Navidrome instance in a container), which is significant setup for a tool of this size.

Building

cargo build --release
# binary at target/release/subsonic-shuffler

To build and push the container image:

just image-build 1.0.0
just image-push 1.0.0