Contrast was measured, not eyeballed: 41 foreground/background pairs across both themes and the terminal surface, each against the darkest (light) or lightest (dark) surface it actually sits on. Five failed. Links on manila read 3.64:1 and the footer's "No telemetry. Ever." — a claim the site goes out of its way to make — sat at 2.86:1. The accent needed splitting rather than moving. #c1502e clears 4.5:1 as a button fill behind white but only 3.99:1 as an 11px eyebrow on vinyl, so --accent keeps the brand hue for fills and a new --accent-text carries the readable cut. The terminal gets the same treatment dark emulators give their palettes: alarm and oxide brighten inside .tui-content so "Failed" is legible next to its glyph. Reduced motion no longer nukes everything. A blanket 0.01ms also kills the transitions that answer a click, which is feedback rather than movement; looping and travelling animation stops, the rest caps at 80ms. The TUI already skipped its opening run and still does. The hero reserves its box with aspect-ratio from the first paint. It was prerendered at full unscaled height and collapsed once JS measured, moving everything below it by ~145px. Measured shift is now 0. Also: the webfont loads non-blocking (display=swap meant the first frame never waited for it anyway), footer link groups nest under a heading instead of sitting level with page sections, and eight tokens nothing referenced stop shipping.
Soulseek-rs 🦀
Soulseek-rs is a Soulseek library and client built in Rust. Soulseek is a closed-source P2P file-sharing network from the 2000s. It's still used by music enthusiasts around the world to share niche music.
🎥 Demo
Features
- Search & download — search the network, pick results in the TUI, and queue downloads with pause, resume, and retry
- Sharing — point
--shared-dirat a directory and your files show up in searches; peers can browse and download them - Browse — list any user's shared files and download straight from the tree
- Chat rooms — list, join, and talk in public rooms, several open at once
- Private messages — send and receive messages, with an inbox in the TUI
- Firewalled peers — downloads and browsing fall back to server-brokered connections when a peer can't be reached directly
- Automatic port mapping — opens your listen port via UPnP-IGD and
NAT-PMP, with a
portmapsubcommand to test your router - TUI and CLI — a full terminal interface, plus scriptable subcommands
(
search,message,browse,rooms,chat,portmap)
Project Goals
This project is a learning exercise to explore Rust. I've been using Soulseek since the early 2000s, so it's close to my heart, and the Soulseek protocol is a closed-source network protocol that provides a great opportunity to learn about asynchronous and concurrent network programming and reverse engineering
Since it's a learning project, I have a self-imposed restriction not to use external dependencies in the library. This means I can't use any external crates that are not part of the Rust standard library. This is a good challenge to learn how to build complex systems with only the standard library.
In the client crate, external dependencies are allowed for building a rich experience. For me, this is a good balance between learning and practicality.
Planned Features
- Headless mode daemon mode with remote control
Project Structure
This project is organized as a Cargo workspace with two crates:
- soulseek-rs-lib - The core library implementing the Soulseek protocol
- soulseek-rs - A CLI client built on top of the library
This structure allows:
- Other developers to build custom Soulseek clients using
soulseek-rs-lib - Users to install the ready-made client via
cargo install soulseek-rs - Clean separation of concerns between protocol implementation and user interface
Installation
For Users
cargo install soulseek-rs
For Developers
Clone and build from source:
git clone git@github.com:michel/soulseek-rs.git
cd soulseek-rs
cargo build --release
The binary will be available at target/release/soulseek-rs.
For Library Users
To build your own Soulseek client, add to your Cargo.toml:
[dependencies]
soulseek-rs-lib = "6"
Usage
./target/release/soulseek-rs "the weeknd Blinding Lights"
Private messages
Send a private message to another user from the command line:
soulseek-rs message <username> "hello there"
In the interactive TUI:
- press
mto compose — type<recipient> <message>andEnterto send; - press
ito open the inbox popup listing sent and received messages (incoming messages arrive automatically while the TUI is open). Theishortcut shows an unread counter, e.g.i inbox (3).
Chat rooms
From the command line:
soulseek-rs rooms # list public rooms with user counts
soulseek-rs chat <room> # join and print messages for a while
soulseek-rs chat <room> "hello room" # join, say one message, and exit
In the interactive TUI, press c to open the chat-rooms popup:
- the room list is browsable and
/-filterable and shows each room's user count (busiest first); pressEnterto join the highlighted room; - several rooms can be open at once as tabs —
Tab/Shift-Tabswitch between them,xleaves the active room,lreturns to the room list; - in a room, press
Enterto type a message andEnteragain to send; - the room's member list is selectable with
↑/↓; pressbto browse the highlighted user's shared files ormto send them a private message; - unread messages bold a room's tab and add a
room (n)badge, and thec chat (n)shortcut counts unread across all open rooms.
Connectivity (being reachable)
Browsing and downloading are peer-to-peer, so at least one side must accept an incoming connection. When the listener is enabled (the default), the client automatically tries to open its listen port on your router via UPnP-IGD and NAT-PMP, so firewalled peers and the server can connect back to you. This is best-effort: if your router has UPnP/NAT-PMP disabled it's a no-op and you'll see a log line suggesting you forward the port manually.
- The mapped/forwarded port is your
--listener-port(envLISTENER_PORT, default2234); it is renewed automatically and removed on exit. - If auto-mapping can't get that exact port, forward TCP 2234 (or whatever
--listener-portyou chose) to this machine on your router. - Pass
--disable-listenerto turn the listener (and port mapping) off.
Check whether it works on your network without launching the whole client:
soulseek-rs portmap
It tries to open the port via UPnP/NAT-PMP and prints whether your router allowed it (and your external address), then removes the test mapping. If it reports failure, enable UPnP on your router or forward the port manually.
If both you and a peer are behind routers with no forwarded port, browsing that peer can't work — that's a fundamental Soulseek/peer-to-peer limitation, not a bug.
Development
To run the project in development mode with debug output and trace output:
RUST_LOG=trace cargo run
To run the tests:
cargo test
To run the linter:
cargo clippy
To run the formatter:
cargo fmt
End-to-end tests
The soulseek-rs-lib/tests/e2e.rs suite exercises the client against a real
Soulseek server using soulfind, a
local server implementation. The tests are server-optional: they run when a
server is available and otherwise skip (so cargo test stays green everywhere).
They locate a server in this order:
SOULSEEK_TEST_SERVER=host:port— connect to an already-running server, orSOULFIND_BIN=/path/to/soulfind(or asoulfind/bin/soulfindcheckout in a parent directory) — spawn soulfind on an ephemeral port with a throwaway database.
# Build soulfind once (see its BUILDING.md), then:
SOULFIND_BIN=/path/to/soulfind/bin/soulfind \
cargo test -p soulseek-rs-lib --test e2e -- --nocapture
On macOS, soulfind's
SQLITE_CONFIG_SINGLETHREADoptimization is rejected by the system SQLite; building soulfind with that call made non-fatal lets it run locally. It is only a mutex optimization and does not affect the server.
Set SOULSEEK_E2E_REQUIRED=1 to turn a missing server into a hard failure
instead of a skip. Continuous integration sets it so the e2e suite genuinely
runs against a freshly built soulfind rather than silently skipping.
Continuous integration
.github/workflows/ci.yml runs on every push and pull request:
- Format & Clippy —
cargo fmt --all --checkandcargo clippy --workspace --all-targets -- -D warnings. - Test — builds soulfind from source (LDC +
dub build :server), pointsSOULFIND_BINat it, and runscargo test --workspacewithSOULSEEK_E2E_REQUIRED=1, so unit and end-to-end tests both run.
License
This project is licensed under the MIT License — see the LICENSE file for details.
