Agent-First Slug v0.6: A Shape, Not a Sentence

by Agent-First Kit Contributors

afslug's CLI is now compiled from a closed-world registry: one source for argv parsing, typed values, legal combinations, help, and docs/cli.md. clap is gone. The visible payoff is that a constraint which used to live in a help sentence and a runtime check is now a shape the parser enforces and `--help` lists.

The previous release made afslug’s answers structured — help as a result, version as a result, errors routed separately from output. This one makes the question structured too.

It started as a forced move. afdata 0.27.0 deleted help-v1 and the cli-help/cli-help-markdown features that afslug’s help layer was built on, so afslug stopped resolving at all. The small fix was to port the help layer onto whatever replaced it. The change made instead was to move the entire CLI onto afdata’s cli-spec-v1 registry — one declaration that argv parsing, typed values, legal combinations, output contracts, --help, and docs/cli.md are all derived from. clap is dropped.

The constraint that was a sentence

afslug skill install writes the skill into an agent’s skills directory. It takes --agent, which defaults to all, and --skills-dir, which names one directory.

Those two arguments cannot both be meaningful. If the command is fanning out across every agent it knows about, there is no single directory to write to — each agent has its own. --skills-dir only means something when exactly one agent is named.

Under clap that fact lived in two places, neither of them the parser: a sentence in the help text, and a runtime check that ran after the command had already been accepted. An agent reading --help had to notice the sentence, understand it, and comply. Nothing structural stopped it from trying.

Now the command has two shapes, and --help returns both:

$ afslug skill install --help
skill-install-every-agent
  Target every agent that supports the scope
  afslug skill install [--agent all] [--scope <personal|workspace>] [--force] ...

skill-install-one-agent
  Target one named agent; only this shape accepts --skills-dir
  afslug skill install --agent <codex|claude-code|opencode|hermes>
                       [--scope ...] [--skills-dir <DIR>] [--force] ...

The combination that never made sense is not a documented mistake any more. It is absent from the grammar:

$ afslug skill install --agent all --skills-dir /tmp/skills
{"kind":"error","error":{"code":"cli_unregistered_combination",
 "message":"arguments do not match a registered CLI combination",
 "hint":"run `afslug skill install --help` and choose one registered combination"}}

status and uninstall split the same way, for the same reason.

This is the whole argument for a closed world. A CLI that accepts every combination of its flags and then rejects some of them at runtime has two specifications — the one the parser implements and the one the prose describes — and they drift. Registering the legal shapes collapses that into one, and the thing an agent reads before its first attempt is generated from the same source that judges the attempt.

Breaking changes

Stated plainly, because a caller pinning a caret range receives them automatically:

Nothing about slug generation changed. afslug still turns text into a slug with the same charset options and the same output; this release is entirely about how the command is described and parsed.

Getting it

$ brew install agentfirstkit/tap/afslug
$ cargo install agent-first-slug