diff --git a/README.md b/README.md
index db9eb9d..bf7808b 100644
--- a/README.md
+++ b/README.md
@@ -107,17 +107,66 @@ numbered release. A failed download, checksum, or startup check leaves an
existing binary untouched. Windows archives for both channels are on the
[releases page](https://github.com/michel/soulseek-rs/releases).
-The other stable routes need no installer script:
+Or install it with a package manager. Stable follows the latest release:
```bash
-brew install michel/tap/soulseek-rs # macOS and Linux
-cargo install soulseek-rs # or from crates.io
+# Debian, Ubuntu, Mint (on ARM: arm64 for amd64)
+curl -fsSLO https://github.com/michel/soulseek-rs/releases/latest/download/soulseek-rs-amd64.deb
+sudo apt install ./soulseek-rs-amd64.deb
+
+# Fedora, RHEL (on ARM: aarch64 for x86_64)
+sudo dnf install https://github.com/michel/soulseek-rs/releases/latest/download/soulseek-rs-x86_64.rpm
+
+# Nix
+nix run github:michel/soulseek-rs/master
+
+# Homebrew, on macOS and Linux
+brew install michel/tap/soulseek-rs
+
+# cargo-binstall fetches the release binary and compiles nothing
+cargo binstall soulseek-rs
+
+# From source: Rust 1.91 or newer. Debian 13 and Ubuntu 24.04 default to an older one
+cargo install --locked soulseek-rs
```
+Nightly is the tip of `develop`. The `.deb` and `.rpm` are downloads; Nix,
+Homebrew and cargo build it from source:
+
+```bash
+curl -fsSLO https://github.com/michel/soulseek-rs/releases/download/nightly/soulseek-rs-nightly-amd64.deb
+sudo apt install ./soulseek-rs-nightly-amd64.deb
+
+sudo dnf install https://github.com/michel/soulseek-rs/releases/download/nightly/soulseek-rs-nightly-x86_64.rpm
+
+nix run github:michel/soulseek-rs/develop
+
+brew install --HEAD michel/tap/soulseek-rs
+
+cargo install --locked --git https://github.com/michel/soulseek-rs --branch develop soulseek-rs
+```
+
+A `.deb` or `.rpm` does not update itself. Install the newer file over it. A
+nightly sorts above the release it follows, so going back to stable is a
+downgrade. In a script apt refuses one without `--allow-downgrades`, while dnf
+goes ahead. Both carry the man page and completions for bash, zsh and fish.
+A release download prints the plain number, `19.0.0`. Any Nix build, and a
+nightly download, reads `19.0.0+git202609141144.deb846b`: the last release, the
+commit's time in UTC, and the commit. A Homebrew `--HEAD` build reports
+`HEAD-deb846b`. A `cargo install` from git sets no version, so it prints
+`19.0.0` too.
+
From source, `cargo build --release` leaves the binary at
`target/release/soulseek-rs`. To build your own client on the protocol library,
run `cargo add soulseek-rs-lib`.
+To package it for a distribution: a musl build is static, a glibc build links
+only libc, libm and libgcc_s,
+`soulseek-rs completions print
+ {route.alt}
+
+ Stable is the latest release, or for Nix the
+ {route.note}
+ cargo install --locked soulseek-rs builds from crates.io instead.
+ >
+ ),
+ },
+ {
+ id: 'linux',
+ os: 'Linux',
+ best: 'your package manager',
+ lines: [
+ { t: 'cm', text: '# Debian and Ubuntu; the others are below' },
+ { t: 'cmd', text: `curl -fsSLO ${STABLE_DOWNLOAD}/soulseek-rs-amd64.deb` },
+ { t: 'cmd', text: 'sudo apt install ./soulseek-rs-amd64.deb' },
+ { t: 'cmd', text: 'soulseek-rs' },
+ ],
+ alt: (
+ <>
+ Fedora, Nix, Homebrew and cargo are{' '}
+
+ listed below
+
+ , each with a nightly. Without any of them, the{' '}
+ pc-windows-msvc zip from the{' '}
+ soulseek-rs.exe on your PATH.
+ >
+ ),
+ },
+]
+
+interface LinuxRoute {
+ id: string
+ name: string
+ stable: readonly TermLine[]
+ nightly: readonly TermLine[]
+ note: React.ReactNode
+}
+
+const LINUX_ROUTES: readonly LinuxRoute[] = [
+ {
+ id: 'deb',
+ name: 'Debian, Ubuntu, Mint',
+ stable: [
+ { t: 'cmd', text: `curl -fsSLO ${STABLE_DOWNLOAD}/soulseek-rs-amd64.deb` },
+ { t: 'cmd', text: 'sudo apt install ./soulseek-rs-amd64.deb' },
+ ],
+ nightly: [
+ { t: 'cmd', text: `curl -fsSLO ${NIGHTLY_DOWNLOAD}/soulseek-rs-nightly-amd64.deb` },
+ { t: 'cmd', text: 'sudo apt install ./soulseek-rs-nightly-amd64.deb' },
+ ],
+ note: (
+ <>
+ On ARM, arm64 takes the place of amd64. There is no apt
+ repository behind this, so an update means installing the newer file over the old one.
+ A nightly sorts above the release it follows, so going back to stable is a downgrade,
+ and apt asks before doing it.
+ >
+ ),
+ },
+ {
+ id: 'rpm',
+ name: 'Fedora, RHEL',
+ stable: [{ t: 'cmd', text: `sudo dnf install ${STABLE_DOWNLOAD}/soulseek-rs-x86_64.rpm` }],
+ nightly: [
+ { t: 'cmd', text: `sudo dnf install ${NIGHTLY_DOWNLOAD}/soulseek-rs-nightly-x86_64.rpm` },
+ ],
+ note: (
+ <>
+ On ARM, aarch64 takes the place of x86_64. Run the same
+ command again to update. dnf fetches the file each time, so a newer nightly at the same
+ address is picked up. An older file downgrades without asking.
+ >
+ ),
+ },
+ {
+ id: 'nix',
+ name: 'Nix',
+ stable: [{ t: 'cmd', text: 'nix run github:michel/soulseek-rs/master' }],
+ nightly: [{ t: 'cmd', text: 'nix run github:michel/soulseek-rs/develop' }],
+ note: (
+ <>
+ Both build from source. With no branch at all, Nix takes the repository’s
+ default one, and here that is develop.
+ >
+ ),
+ },
+ {
+ id: 'brew',
+ name: 'Homebrew',
+ stable: [{ t: 'cmd', text: 'brew install michel/tap/soulseek-rs' }],
+ nightly: [{ t: 'cmd', text: 'brew install --HEAD michel/tap/soulseek-rs' }],
+ note: (
+ <>
+ Homebrew installs under /home/linuxbrew, outside the image that a system
+ update replaces on Bazzite and Silverblue. --HEAD compiles{' '}
+ develop with Homebrew’s own Rust.
+ >
+ ),
+ },
+ {
+ id: 'cargo',
+ name: 'cargo',
+ stable: [{ t: 'cmd', text: 'cargo install --locked soulseek-rs' }],
+ nightly: [
+ {
+ t: 'cmd',
+ text: 'cargo install --locked --git https://github.com/michel/soulseek-rs --branch develop soulseek-rs',
+ },
+ ],
+ note: (
+ <>
+ Needs Rust 1.91 or newer. Debian 13 and Ubuntu 24.04 default to an older one, so take
+ the toolchain from cargo binstall soulseek-rs fetches the release binary and compiles nothing.
+ >
+ ),
+ },
+]
+
+export const InstallCards = () => (
+
+ {route.os}
+
+
+ Linux, by distribution
+
+ master branch it was cut
+ from. Nightly is the tip of develop, rebuilt every day. A release download
+ prints the plain number, 19.0.0. Any Nix build, and a nightly download,
+ reads 19.0.0+git202609141144.deb846b: the last release, the
+ commit’s time in UTC, and the commit. A Homebrew --HEAD build
+ reports HEAD-deb846b, and a cargo install from git sets no
+ version, so it prints 19.0.0 too. The .deb and .rpm
+ carry the man page and completions for bash, zsh and fish.
+ cargo install soulseek-rs builds from crates.io instead.
- >
- ),
- },
- {
- id: 'linux',
- os: 'Linux',
- best: 'cargo',
- lines: [
- { t: 'cmd', text: 'cargo install soulseek-rs' },
- { t: 'cmd', text: 'soulseek-rs' },
- ],
- alt: (
- <>
- Homebrew on Linux works the same as on macOS. Without either, the{' '}
- pc-windows-msvc zip from the{' '}
- soulseek-rs.exe on your PATH.
- >
- ),
- },
-]
-
interface PlatformNote {
id: string
name: string
@@ -291,32 +231,12 @@ const Steps = () => (
place.
- Or pick a route per platform. Cargo needs a Rust toolchain from{' '}
- --HEAD also build from source, but bring their own Rust.
- {route.alt} -
-
Every route puts the same binary on your PATH. Run soulseek-rs in
a terminal and the TUI opens, in a script or a pipe it wants a subcommand
@@ -522,11 +442,13 @@ const Config = () => (
)
+// aislop-ignore-file code-quality/duplicate-block -- the two uninstall `lines` arrays repeat the `{ t, text }` shape around different commands. The rule matches punctuation, not logic.
const Uninstall = () => (
--log-file somewhere. No telemetry to opt out of.