From 17e4bf9fd359cb297af450b0863cb20335416c14 Mon Sep 17 00:00:00 2001 From: Michel de Graaf Date: Sat, 25 Jul 2026 02:24:58 +0200 Subject: [PATCH] docs(website): lead with the agent-native story `skills install` becomes the featured card on the home page, in the wide slot the grid gives its first entry: one command hands a coding agent the JSON keys of every record, the exit-code meanings, and the --json rule, with nothing to clone because the skill ships inside the binary. The docs page gains a callout and the command in the shell listing. Also catches the site up with the scriptable command surface the last two releases introduced: `get`, `shares add`, `serve`, `room list`, `message send` and `--json` replace the flags and spellings that no longer exist. --- website/index.html | 4 +-- website/src/pages/community.tsx | 17 +++++++---- website/src/pages/docs.tsx | 52 ++++++++++++++++++++++++--------- website/src/pages/home.tsx | 49 +++++++++++++++++++++---------- website/src/pages/install.tsx | 40 +++++++++++++++---------- 5 files changed, 111 insertions(+), 51 deletions(-) diff --git a/website/index.html b/website/index.html index c713b41..f384c80 100644 --- a/website/index.html +++ b/website/index.html @@ -8,7 +8,7 @@ soulseek-rs, a Soulseek client for your terminal @@ -17,7 +17,7 @@ diff --git a/website/src/pages/community.tsx b/website/src/pages/community.tsx index 831b9c3..8092655 100644 --- a/website/src/pages/community.tsx +++ b/website/src/pages/community.tsx @@ -32,8 +32,13 @@ const ALTERNATIVES: readonly Alternative[] = [ links: [{ label: 'Nicotine+', href: LINKS.nicotine }], }, { - question: 'Want to point automation at the network?', - answer: <>slskd does that today. Daemon mode here is unbuilt., + question: 'Want a queue that outlives the command?', + answer: ( + <> + Every command runs one-shot and exits: JSON on stdout, an exit code, nothing left + running. No resident queue to pause, resume, or drive remotely. slskd has that. + + ), links: [{ label: 'slskd', href: LINKS.slskd }], }, ] @@ -45,8 +50,8 @@ const CITIZENSHIP = [ title: 'Share, and share real files', body: ( <> - Point --shared-dir at the collection you actually listen to. Full - albums, honest bitrates, nothing transcoded up from a lossy source and relabelled. + Point shares add at the collection you actually listen to. Full albums, + honest bitrates, nothing transcoded up from a lossy source and relabelled. ), }, @@ -67,8 +72,8 @@ const CITIZENSHIP = [ title: 'Stay online', body: ( <> - Leave it running in a tmux session on the box that is already on. A share that - appears for an hour a week is close to no share at all. + Leave serve --follow running in a tmux session on the box that is + already on. A share that appears for an hour a week is close to no share at all. ), }, diff --git a/website/src/pages/docs.tsx b/website/src/pages/docs.tsx index 65cd3b8..83f696f 100644 --- a/website/src/pages/docs.tsx +++ b/website/src/pages/docs.tsx @@ -15,6 +15,7 @@ import { Terminal } from '@/components/ui/terminal' import { LINKS } from '@/lib/links' const GLOBAL_KEYS: readonly (readonly [string, string])[] = [ + ['s', 'search the network'], ['Space', 'select a result'], ['Enter', 'download / send'], ['b', "browse the owner's files"], @@ -41,7 +42,7 @@ const PANES: readonly { num?: number; title: string; body: string }[] = [ { num: 1, title: 'Searches', - body: 'Your queries and how many results each returned. Type / to search the network; each search keeps its own result set.', + body: 'Your queries and how many results each returned. Press s to search the network; each search keeps its own result set.', }, { num: 2, @@ -153,27 +154,40 @@ export const Docs = () => { eyebrow="4 · from the shell" title="Every command also runs as a one-off." > - Skip the TUI when you’re scripting or mid-task. + Skip the TUI when you’re scripting or mid-task. stdout is data, stderr is + progress, and the exit code is the verdict. "hello there"' }, - { t: 'cmd', text: 'soulseek-rs rooms' }, - { t: 'cm', text: '# list public rooms, busiest first' }, - { t: 'cmd', text: 'soulseek-rs chat "hello room"' }, - { t: 'cmd', text: 'soulseek-rs portmap' }, + { t: 'cmd', text: 'soulseek-rs get "public domain field recordings"' }, + { t: 'cm', text: '# search, pick the best, download it' }, + { t: 'cmd', text: 'soulseek-rs search "netlabel 2004" --min-bitrate 320' }, + { t: 'cmd', text: 'soulseek-rs browse --json' }, + { t: 'cmd', text: 'soulseek-rs room list' }, + { t: 'cm', text: '# public rooms, busiest first' }, + { t: 'cmd', text: 'soulseek-rs room say "hello room"' }, + { t: 'cmd', text: 'soulseek-rs message send "hello there"' }, + { t: 'cmd', text: 'soulseek-rs serve --follow' }, + { t: 'cm', text: '# stay online sharing; every upload as it happens' }, + { t: 'cmd', text: 'soulseek-rs skills install' }, + { t: 'cm', text: '# hand all of the above to your coding agent' }, ]} />

- The subcommands mirror the TUI: search, message,{' '} - browse, rooms, chat, and{' '} - portmap. Pass a room and a message to chat to say - one thing and exit. + The command groups: search, get,{' '} + download, browse, room,{' '} + message, serve, user,{' '} + whoami, shares, config,{' '} + portmap, skills. Records are tab-separated fields, + one per line, or NDJSON with --json. +

+

+ No TTY, no daemon. search --json pipes through jq{' '} + into download --stdin. Every ending has its own exit code: 4 found + nothing, 3 could not reach the server, 6 the transfer died.

portmap tests whether your router will let peers connect back, @@ -185,6 +199,18 @@ export const Docs = () => {

+ +

+ soulseek-rs skills install writes a SKILL.md into + every coding agent on the machine — Claude Code and opencode today,{' '} + --dir for anything else. It carries what --help{' '} + cannot: the JSON keys of every record, what each exit code means, and the + idioms worth reaching for. Run it again after an upgrade to update it, and{' '} + skills uninstall takes it back out. +

+
+
+

If both you and a peer are behind routers with no forwarded port, browsing diff --git a/website/src/pages/home.tsx b/website/src/pages/home.tsx index 5a05030..3090d8b 100644 --- a/website/src/pages/home.tsx +++ b/website/src/pages/home.tsx @@ -20,22 +20,41 @@ const PLATFORMS: readonly { name: OsName; note: string; anchor: string }[] = [ ] const FEATURES = [ + { + glyph: '✦', + color: 'var(--accent-text)', + title: 'Agent native', + cmd: 'soulseek-rs skills install', + body: ( + <> + One command hands your coding agent the whole surface: the JSON keys every record + carries, what each exit code means, and the rule that it always asks for{' '} + --json. The skill ships inside the binary, so there is nothing to + clone and nothing to configure — it finds Claude Code and opencode on its own. + + ), + }, { glyph: '→', color: 'var(--accent-text)', title: 'Search & download', - cmd: 'soulseek-rs "field recordings"', - body: <>Search the network, pick results in the TUI, and queue downloads with pause, resume, and retry., + cmd: 'soulseek-rs get "field recordings"', + body: ( + <> + Queue downloads in the TUI with pause, resume, and retry, or let get{' '} + search, pick the best, and download in one command. + + ), }, { glyph: '↑', color: 'var(--status-success)', title: 'Sharing', - cmd: 'soulseek-rs --shared-dir ~/Music', + cmd: 'soulseek-rs shares add ~/Music', body: ( <> - Point --shared-dir at a directory and your files show up in searches; - peers browse and download them. + Point shares add at a directory and your files show up in searches;{' '} + serve stays online so peers can browse and download them. ), }, @@ -50,14 +69,14 @@ const FEATURES = [ glyph: '#', color: 'var(--status-warning)', title: 'Chat rooms', - cmd: 'soulseek-rs rooms', + cmd: 'soulseek-rs room list', body: <>List, join, and talk in public rooms, several open at once as tabs., }, { glyph: '@', color: 'var(--status-info)', title: 'Private messages', - cmd: 'soulseek-rs message "hi"', + cmd: 'soulseek-rs message send "hi"', body: <>Send and receive PMs, with an inbox and an unread counter in the TUI., }, { @@ -88,11 +107,11 @@ const FEATURES = [ glyph: '▮', color: 'var(--accent-text)', title: 'TUI and CLI', - cmd: 'soulseek-rs', + cmd: 'soulseek-rs search "rjd2" --json', body: ( <> - A full terminal interface, plus scriptable subcommands: search, message, browse, - rooms, chat, portmap. + A full terminal interface, plus scriptable subcommands: stdout is data, stderr is + progress, the exit code is the verdict. ), }, @@ -203,10 +222,10 @@ export const Home = () => {

- Every command runs as a one-off from the shell: search,{' '} - browse, rooms, chat,{' '} - message, portmap. Point cron, a script, or an - agent at them and read the output back. No daemon, no API to stand up.{' '} + Every command runs as a one-off from the shell. Point cron, a script, or an + agent at them and read JSON records back off stdout. No daemon, no API to + stand up — and skills install teaches the agent the surface + for you.{' '} See the commands @@ -243,7 +262,7 @@ export const Home = () => {

get started

- Install it, then press / to search. + Install it, then press s to search.

Needs a Rust toolchain. From there it’s one command, then the TUI opens. diff --git a/website/src/pages/install.tsx b/website/src/pages/install.tsx index 97fd4af..f754cac 100644 --- a/website/src/pages/install.tsx +++ b/website/src/pages/install.tsx @@ -11,7 +11,7 @@ use std::time::Duration; fn main() -> Result<(), Box> { let mut client = Client::new("username", "password"); - client.connect(); + client.connect()?; client.login()?; let results = client.search("public domain field recordings", Duration::from_secs(10))?; @@ -117,8 +117,8 @@ export const Install = () => { ]} />

- Cargo puts the binary on your PATH. Run soulseek-rs and the TUI - opens. + Cargo puts the binary on your PATH. Run soulseek-rs in a terminal + and the TUI opens, in a script or a pipe it wants a subcommand instead.

@@ -205,7 +205,7 @@ export const Install = () => {
Browsing and downloading are peer-to-peer, so at least one side has to accept an - incoming connection. + incoming connection. serve refuses to start with the listener off. @@ -218,13 +218,18 @@ export const Install = () => { yourself.

- The port is your --listener-port (env LISTENER_PORT, - default 2234); it’s renewed automatically and removed on - exit. Pass --disable-listener to turn it off. Check your own - network without launching the client: + The port is your --listener-port (env{' '} + SOULSEEK_LISTENER_PORT, default 2234); it’s + renewed automatically and removed on exit. Pass --no-listener to + turn it off. Check your own network without launching the client:

- +
@@ -288,13 +293,17 @@ export const Install = () => { Your password goes to the OS keychain, never a plain-text file. If you would rather it never be stored at all, have password_cmd shell out to - your own password manager and print it on demand. + your own password manager and print it on demand. For CI and containers,{' '} + --password-stdin reads it off a pipe so it never reaches{' '} + ps or the environment. config.toml is layered: flags beat environment variables, which - beat the file, which beats the defaults. State (searches, downloads, rooms) is - versioned JSON and restores on restart; anything unreadable is set aside as{' '} - .bak instead of being overwritten. + beat the file, which beats the defaults. config get and{' '} + config set read and write that file without opening an editor. + State (searches, downloads, rooms) is versioned JSON and restores on restart; + anything unreadable is set aside as .bak instead of being + overwritten.
@@ -302,14 +311,15 @@ export const Install = () => {
Three things exist on disk: the binary, the config, and the state. Nothing else is - written, and there is no telemetry to opt out of. + written unless you pointed --log-file at a file, and there is no + telemetry to opt out of.