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:
Michel de Graaf
2026-07-25 02:17:11 +02:00
parent 03e8924a6b
commit 95bc18672d
7 changed files with 543 additions and 3 deletions
+6 -3
View File
@@ -1,10 +1,13 @@
//! One-shot commands: everything the binary can do without a terminal.
//!
//! Each command opens a [`Session`], does one job, writes records to stdout
//! and progress to stderr, and returns an exit code through [`CliError`].
//! Each command does one job, writes records to stdout and progress to stderr,
//! and returns an exit code through [`CliError`]. Most open a [`Session`]
//! first; the ones that only read the config file or the local machine are
//! dispatched by `main::run` before any credentials are demanded.
pub mod peer;
pub mod settings;
pub mod skills;
pub mod social;
pub mod transfer;
@@ -193,7 +196,7 @@ pub fn run(ctx: &Ctx, command: Commands) -> CliResult {
// These need no account, so main.rs answers them before asking for
// credentials; the arms exist only to keep the match exhaustive.
Commands::Portmap => portmap(&ctx.out, ctx.settings.listen_port),
Commands::Config(_) | Commands::Shares(_) => {
Commands::Config(_) | Commands::Shares(_) | Commands::Skills(_) => {
Err(CliError::usage("handled without a session; see main::run"))
}
}