From cd4168880345a36be78933a15479742cc99958bd Mon Sep 17 00:00:00 2001 From: Michel de Graaf Date: Sat, 25 Jul 2026 02:27:47 +0200 Subject: [PATCH] docs(website): explain what the skill unlocks, and document config.toml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The agent-native copy described what the skill contains rather than what it buys you. A new home-page section shows the shape of the request that becomes possible — describe the outcome, let the agent write the pipeline — and names the specific knowledge --help cannot carry: which JSON keys a record has, that exit 4 means widen the query, that a remote path goes back byte-identical, that --follow never returns. The install page gains a reference for all nine config.toml settings with their defaults and an example file, next to the paths that were already there. The list is the one `config set` accepts, checked against FileConfig::KEYS. --- website/src/pages/docs.tsx | 13 +++- website/src/pages/home.tsx | 55 +++++++++++++- website/src/pages/install.tsx | 134 ++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 7 deletions(-) diff --git a/website/src/pages/docs.tsx b/website/src/pages/docs.tsx index 83f696f..0e602fe 100644 --- a/website/src/pages/docs.tsx +++ b/website/src/pages/docs.tsx @@ -203,9 +203,16 @@ 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{' '} + --dir for anything else. After it lands you describe the + outcome instead of the pipeline: “mirror that peer’s FLAC + folder”, “watch this room for an hour and save anything + mentioning the label”. +

+

+ It carries what --help cannot: the JSON keys of every record, + that exit 4 means widen the query rather than retry it, that remote paths go + back byte-identical, and that --follow never returns so an agent + passes --duration. Run it again after an upgrade to update it;{' '} skills uninstall takes it back out.

diff --git a/website/src/pages/home.tsx b/website/src/pages/home.tsx index 3090d8b..49f3492 100644 --- a/website/src/pages/home.tsx +++ b/website/src/pages/home.tsx @@ -27,10 +27,10 @@ const FEATURES = [ 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. + Run it once and asking beats scripting: your agent knows the record shapes, the + exit codes, and the filters, so “find the 1998 pressing, lossless only” + becomes a pipeline it writes itself. No MCP server, no wrapper — the skill ships + inside the binary and finds Claude Code and opencode on its own. ), }, @@ -257,6 +257,53 @@ export const Home = () => { +
+ + A CLI an agent can drive is not the same as a CLI an agent knows how to drive. + skills install closes that gap in one command. + + + + +

+ --help lists flags. It cannot say which JSON keys a record + carries, that exit 4 means widen the query rather than retry it, that a + remote path is backslash-separated and has to go back byte-identical, or + that --follow never returns and an agent wants{' '} + --duration instead. An agent without that guesses, and guessing + against someone else’s file server is how you get a hung job. +

+

+ The skill is that missing half. Once it lands, the interesting requests stop + being pipelines you write: mirror a peer’s FLAC folder overnight, watch + a room and save anything that mentions a label, check whether a user is worth + queueing behind before committing to a 2 GB transfer. +

+

+ It stays a CLI — no daemon, no MCP server, no API key. Upgrading the binary + upgrades the skill; run skills install again to take it.{' '} + + See the commands + +

+
+
+
+
diff --git a/website/src/pages/install.tsx b/website/src/pages/install.tsx index f754cac..5af1672 100644 --- a/website/src/pages/install.tsx +++ b/website/src/pages/install.tsx @@ -67,6 +67,98 @@ const PLATFORMS: readonly PlatformNote[] = [ }, ] +interface Setting { + key: string + fallback: string + body: React.ReactNode +} + +const SETTINGS: readonly Setting[] = [ + { + key: 'username', + fallback: 'unset', + body: <>Your Soulseek account name. The TUI writes it here after a first login., + }, + { + key: 'server', + fallback: 'server.slsknet.org:2416', + body: <>The server to log in to, as host:port., + }, + { + key: 'listener_port', + fallback: '2234', + body: ( + <> + The TCP port peers connect back on. Forward it, or let portmap ask + your router. + + ), + }, + { + key: 'disable_listener', + fallback: 'false', + body: ( + <> + true refuses incoming peer connections. You can still download from + reachable peers, but firewalled ones can no longer reach you. + + ), + }, + { + key: 'download_dir', + fallback: 'the Downloads path above', + body: <>Where finished transfers land., + }, + { + key: 'shared_dirs', + fallback: 'the download folder', + body: ( + <> + Folders offered to the network, as a list. An explicitly empty list shares + nothing. shared_dir is the older single-folder spelling and still + reads; shares add writes the list form. + + ), + }, + { + key: 'max_concurrent_downloads', + fallback: '5', + body: <>Transfers allowed to run at once. The rest queue., + }, + { + key: 'search_timeout', + fallback: '10', + body: ( + <> + Seconds a search collects replies before reporting. Results trickle in from + separate peers, so a short window finds less. + + ), + }, + { + key: 'password_cmd', + fallback: 'unset', + body: ( + <> + A shell command whose stdout is the password, used when the keychain has none. + The password itself never belongs in this file. + + ), + }, +] + +const CONFIG_EXAMPLE: TermLine[] = [ + 'username = "your-name"', + 'download_dir = "~/Music/Soulseek"', + 'shared_dirs = ["~/Music/Soulseek", "~/Music/Library"]', + 'max_concurrent_downloads = 3', + 'search_timeout = 15', + 'listener_port = 2234', + '', + '# never store the password itself; shell out for it instead', + 'password_cmd = "pass show soulseek"', +].map((text) => ({ t: 'code' as const, text })) + interface StepProps { n: number title: string @@ -308,6 +400,48 @@ export const Install = () => {
+
+ + Every one has a working default, so an empty file — or no file — is valid. Flags + beat environment variables, which beat this file, which beats the defaults.{' '} + config list prints the effective value of each. + + +
+ {SETTINGS.map((setting) => ( +
+
+ + {setting.key} + + + {setting.fallback} + +
+

+ {setting.body} +

+
+ ))} +
+
+ + +

+ config path prints the file in use, config get{' '} + reads one setting and config set writes one. Unknown keys are + rejected rather than silently ignored, so a typo fails loudly instead of + quietly doing nothing. --no-config ignores the file entirely + and --config FILE points at another one. +

+
+
+
+
+
Three things exist on disk: the binary, the config, and the state. Nothing else is