feat(cli): ship the agent skill inside the binary
A `cargo install` leaves a binary and nothing else, so there is no file on disk for a coding agent to read. `skills install` writes an embedded SKILL.md into every agent found on the machine — Claude Code and opencode today, any other via --dir — and installing over an older copy is what updating means. The skill carries what --help cannot: the JSON keys of every record, what each exit code means, and the rule that an agent always passes --json. A unit test walks the clap command tree and holds SKILL.md to a documented entry for every command, so a new subcommand fails the build until it is written up.
This commit is contained in:
@@ -26,6 +26,7 @@ Examples:
|
||||
soulseek-rs room listen lobby --follow stream room chat
|
||||
soulseek-rs serve --follow --json share files, stream upload events
|
||||
soulseek-rs user someuser is this peer online and worth it
|
||||
soulseek-rs skills install teach your coding agent this CLI
|
||||
|
||||
Exit codes:
|
||||
0 success 2 usage/config 3 connect or login 4 no results
|
||||
@@ -193,6 +194,32 @@ pub enum Commands {
|
||||
|
||||
/// Check whether the router opens the listen port (UPnP/NAT-PMP)
|
||||
Portmap,
|
||||
|
||||
/// Teach a local coding agent this command surface
|
||||
#[command(subcommand)]
|
||||
Skills(SkillsCommand),
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum SkillsCommand {
|
||||
/// Write the skill into every agent found on this machine, replacing an
|
||||
/// older copy
|
||||
Install(SkillsArgs),
|
||||
|
||||
/// Remove the skill again
|
||||
Uninstall(SkillsArgs),
|
||||
|
||||
/// Show where the skill goes and what is there now
|
||||
List(SkillsArgs),
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct SkillsArgs {
|
||||
/// Skills directory to use instead of the agents found on this machine;
|
||||
/// repeat for several. Use `--dir .claude/skills` to commit the skill
|
||||
/// alongside a project
|
||||
#[arg(long, value_name = "PATH", action = ArgAction::Append)]
|
||||
pub dir: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
@@ -588,6 +615,24 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skills_dir_repeats_into_a_list() {
|
||||
let cli = parse(&[
|
||||
"soulseek-rs",
|
||||
"skills",
|
||||
"install",
|
||||
"--dir",
|
||||
"/a",
|
||||
"--dir",
|
||||
"/b",
|
||||
]);
|
||||
let Some(Commands::Skills(SkillsCommand::Install(args))) = cli.command
|
||||
else {
|
||||
panic!("expected skills install");
|
||||
};
|
||||
assert_eq!(args.dir, [PathBuf::from("/a"), PathBuf::from("/b")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_defaults_to_picking_the_best_result() {
|
||||
let cli = parse(&["soulseek-rs", "get", "query"]);
|
||||
|
||||
Reference in New Issue
Block a user