docspack v1.5.0
Documentation

Documenting a command-line interface

To document a command-line tool so an agent can run it correctly, describe it in a cmdspec file and package that. `docspack build --cmdspec` writes one chunk per command, each saying how to run it and what running it does.

To document a command-line tool so an agent can run it correctly, describe it in a file — the way an HTTP API is described in OpenAPI — and package that. docspack build --cmdspec reads the description and writes one chunk per command, each saying how to run that command and what running it does:

bash
npx docspack build --cmdspec ./cmdspec.yaml --name @acme/docspack --pkg-version 1.4.0

Combine it with --from, and with --openapi, to publish prose, an API and a CLI in one package, or put it in the docspack key of the package’s package.json:

json
{
  "docspack": {
    "from": "./docs",
    "cmdspec": "./cmdspec.yaml"
  }
}

The file is cmdspec, an open format for describing a command line. docspack reads two others as well, converting them: a Usage spec (KDL), which many Rust, Go and Python CLIs can export, and an OpenCLI document.

A Node CLI built with commander, citty or yargs need not be described by hand. @docspack/cmdspec/emit reads the program and writes the document — fromCommander(program), await fromCitty(command), await fromYargs(() => buildProgram(), { version }) — with every command, option and argument the program parses. What a framework does not know, add to the result: effects, exit statuses, outputs, examples.

What one chunk contains

Everything needed to run the command, in the shape of a help page, with what help pages leave out spelled in words: the types and defaults of its inputs, where a value can come from, what the command changes, what it prints and what its exit statuses mean. The command’s own prose comes first, where a question is matched against it. Shortened, the chunk for docspack ask:

text
docspack ask <question>... [options]
  Answer from the local index — the command to give an agent
  <question>...  words are joined with spaces
  -p, --package <s>  only packages whose name contains this text
  --limit <n>  maximum chunks to return (integer; at least 1; default 3)
  also accepts: --store <path>, --cwd <dir>, --json, -q, --quiet
  effects: read; idempotent
  stdout: text/markdown, the answer; application/json, the chunks and their scores with --json
  exit: 0 success; 1 the command failed; 2 the command was used wrongly; 3 nothing matched, and a docs package is installed but not indexed
  $ docspack ask "how do I verify a webhook signature"

effects is the line an agent most needs and a help page never has: whether running the command reads, writes, deletes, talks to the network or runs other programs. A command that does not state its effects says effects: not stated, never nothing, so an agent cannot mistake silence for safety.

The package also gets an overview chunk: the program’s prose, the options every command accepts with what they do, and one line per command — or the top-level commands only, for a CLI too large to list in one answer.

Asking for one command

A command path is a key, not a phrase. Ranked as prose, git remote add matches every chunk that mentions remotes; named in a question, it pins its chunk ahead of anything the ranker found:

bash
docspack ask "git remote add origin https://example.com/repo.git"
docspack ask "what does git remote rm do"     # an alias reaches its command

The longest path the question names wins, so the first question gets git remote add, not git remote as well. Paths match exactly, as typed: command names are case-sensitive.

A CLI you depend on can describe itself

docspack describes its own this way — docspack --cmdspec prints the document its parser and its --help are generated from, and its reference is rendered from the same file — and any package can do the same.

A package that ships a CLI can name its cmdspec document in its own package.json:

json
{
  "name": "acme",
  "version": "4.2.0",
  "bin": { "acme": "./bin/acme.js" },
  "cmdspec": "./cmdspec.json"
}

docspack sync then indexes that CLI for exactly the version installed, beside its type declarations, and docspack ask answers from it — ranked like documentation, and pinned when a question names a command. A description of a different version than the one installed is reported and skipped, never indexed: it would answer with a command line the installed program does not accept.

What build checks

An invalid description stops the build, listing every problem. One that is valid but answers worse is built, with a warning for each gap: commands without a summary, without an example, without stated effects, or a CLI that says nothing about its exit statuses. docspack doctor runs the same checks against the file docspack.cmdspec names, so CI catches a description that drifts after the payload was built.

npx @docspack/cmdspec validate ./cmdspec.yaml checks a description on its own, and npx @docspack/cmdspec convert turns a Usage or OpenCLI document into cmdspec.

The same ranking docspack search uses, over the same 15 documents.