# Progressive Disclosure Tooling

> Structure a CLI or tool surface as a progressive-disclosure graph where every subcommand's --help is a self-contained mini-skill, and derive every guidance surface from one typed registry so documentation drift becomes structurally impossible. Use when writing --help text, designing tool help systems, organizing command documentation for agents, or fighting drift between help text, parsers, and skill docs.

- Skill: `amhuppert/progressive-disclosure-tooling` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add amhuppert/progressive-disclosure-tooling`
- Raw SKILL.md: https://api.skillmd.com/api/skills/amhuppert/progressive-disclosure-tooling/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: amhuppert (https://skillmd.com/u/amhuppert)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/amhuppert/progressive-disclosure-tooling

---


# Progressive-Disclosure Tooling

Agents should discover a tool surface pull-based, node by node, instead of front-loading one large document. Make every subcommand a node in a disclosure graph whose `--help` is a self-contained mini-skill, and make every guidance surface — help text, flag allowlists, parser sets, usage, skill-doc references — a derivation from one typed registry. Hand-synced copies of the same facts will drift, and drift in agent-facing docs is worse than absence: it trains distrust.

Help is the instruction side of a larger principle. The data real commands return follows the same pull-based rule — bounded digests with zoom-in handles instead of full dumps (`query-output-disclosure`) — and instruction disclosure is not confined to help: hints, usage errors, and omission lines in real command output are edges of the same graph.

## The tool surface is a disclosure graph

Every subcommand is a node. A node's `--help` is a mini-skill containing:

- **Description** — 1–4 lines of what it does.
- **Usage** — the invocation shapes.
- **Flags** — command-specific flags only; global flags get one pointer line, never repeated per node.
- **≥ 1 example** for every leaf node.
- **Optional domain context** — ≤ 4 lines, only when a domain-model fact genuinely earns its place.
- **Lateral edges** — related commands, each with a one-liner.
- **Outbound edges to skill docs** — "load X when Y", so help routes the agent to deeper documentation exactly when it becomes relevant.

Agents navigate the graph node by node via `--help`, pulling only what the current step needs.

## Terse hubs, rich leaves

- Group nodes render as indexes: their summary, one line per child, plus their own related/skills edges.
- High-traffic nodes (top-level usage, group indexes) stay terse; richness lives at the leaves the agent deliberately navigates to. This keeps the token cost of graph-walking low.
- Resolve help by longest-prefix match on the full positional path, so `tool group verb --help` lands on the leaf, not the group.
- An unknown path under a matched parent fails with a usage error whose hint lists the parent's children — the error itself is a graph edge.

## Examples earn their place

An example that restates the usage line is noise. Examples exist to teach **failure-prone shapes**: range syntaxes, payload file shapes, ordering constraints ("always validate first — exit 2 lists issues one per line"). In one real review of agent tool usage, a range-syntax mistake was the #1 observed friction — that is what the example slot is for.

## One vocabulary across hints, errors, and help

Hints, error messages, and help text share one vocabulary. A hint that names a command must match that command's help node exactly; an error that suggests a flag must use the flag's registered name. Success/error hints form the chain edges of the same graph (`validate` → `create` → `start`; connection errors → `doctor`), so the agent experiences one coherent map, not three dialects.

## Single source of truth: the typed registry

All command metadata lives in typed entries (path, summary, description, usage, flags with kinds, examples, domain context, related edges, skill refs), authored in colocated per-command files and aggregated centrally. The aggregator throws at module init on duplicate paths or a leaf whose parent group node is missing — a malformed registry fails every test run, not at runtime in an agent session.

**Every surface derives from the registry:**

| Derived surface | Instead of |
|---|---|
| Per-command help text | A hand-written help record |
| Per-command flag allowlists | Hand-written arrays at each validation call site |
| The parser's boolean-flag set | A hand-maintained constant |
| Top-level usage | A hand-written usage string |
| Group dispatch (valid verbs, "requires a subcommand" errors) | Hand-listed verbs per group module |
| The generated command reference in the agent-facing skill doc | Manually synced doc sections |

Hand-syncing any of these is a defect. In one real audit, a command accepted three flags its help never documented — the classic drift class. Because the allowlist *is* the registry after derivation, "the command accepts a flag help doesn't show" becomes structurally impossible. Don't build a sync test that compares two hand-written copies; derivation deletes the copy.

Group dispatch should derive a group's valid verbs from the registry's children and throw when its handler map disagrees with the registry — a verb wired into dispatch without an entry, or an entry with no handler, fails loudly.

For structured callers, `--help --json` returns the registry entry itself (summary, usage, flags, examples, related edges, skill refs) rather than a rendered text blob — machine callers should never parse prose, and there is no need to pay for the text twice in the JSON path.

## The add-a-command checklist

When adding or changing a command, subcommand, or flag:

1. Add or update the typed registry entry (summary, description, usage, flags, ≥ 1 example for leaves).
2. Wire flags through the registry — never a literal allowlist at a validation call site.
3. Add related edges both ways: the new node points at siblings, and siblings point back where apt.
4. Add skill-doc refs where a deeper doc materially helps (path contract-tested to exist).
5. Run the registry contract test.
6. Regenerate the derived command reference in the agent-facing skill doc; a check fails if it drifts.

## Documentation drift is a contract-test failure

Make a contract test the definition of "help is correct", not a review duty:

1. Every dispatchable command path has a registry entry.
2. Every leaf entry has ≥ 1 example; every entry has a non-empty summary, description, and usage.
3. Every related-command edge resolves to a registry entry — no dangling graph edges.
4. Every referenced skill-doc path exists on disk.
5. No flag name is declared boolean in one entry and value-taking in another (parser-level constraint).
6. Every top-level entry appears in the generated usage; group nodes list all their children.
7. Dispatch and registry agree — disagreement throws, and the contract test drives every group node through dispatch.

Failure of any assertion is the "help is wrong" signal. Agent-facing documentation rot becomes a red suite instead of a slow trust leak.

## Help never fails

Help is the recovery path — the thing an agent reaches for when something else went wrong. It must:

- Work offline and unauthenticated.
- Return instantly.
- Exit 0, always.

Compile durable content into the binary. Help must describe *this build's* parser — its flags must come from the same build as the flag parser, or help can lie about what the binary accepts. Fully server-rendered help breaks offline recovery and can skew against the binary; fully static help gives up context-awareness. Split it.

## Dynamic context is server-rendered garnish

The server may append a few blocks of current runtime state to help output (running dev servers, current task and iteration counts, existing artifacts). Constrain this hard:

- Fetched best-effort with a short timeout (~500 ms).
- Appended as clearly-marked context blocks after the static content.
- **Any failure — no server, no auth, timeout, non-2xx, schema mismatch — silently omits the blocks.** Static help renders byte-identically, nothing is written to stderr, and the exit code is unchanged. Never train agents to fear `--help`.
- Server-side provider failures are logged server-side; observability never lands in the agent's face.

## High admission bar for dynamic context

Unpredictable help is worse for agents than static help. Every provider adds a dependency to a surface that must stay boring:

- Cap the block count and per-block length (e.g. ≤ 3 blocks of ~10 lines).
- Providers return empty when they have nothing worth saying — absence of context must not render an empty section.
- Providers are strictly read-only.
- Defer new providers until a concrete need is observed in real usage; do not add them speculatively.

## Anti-patterns

- **One giant README as the tool's documentation.** Front-loads tokens the agent doesn't need yet and goes stale as a unit.
- **Hand-synced copies of command facts.** Help, allowlists, parser sets, and skill docs maintained separately will drift; drift trains agents to distrust the docs.
- **Examples that restate usage.** They spend the example slot without teaching anything.
- **Hints naming commands that don't exist.** Author hints next to command definitions so the vocabulary can't skew.
- **Help that depends on the server.** A failed fetch that changes help's exit code or writes to stderr breaks the recovery path.
- **Speculative context providers.** Each one makes help less predictable; add only against observed need.
- **Global flags repeated on every node.** Bloats every leaf; use one pointer line.

## Related skills

- `cli-tools-for-agents` — design a project CLI as the agent tool surface: exit codes, file payloads, jobs, doctor
- `query-output-disclosure` — the data side of disclosure: bounded query output, zoom-in handles, explicit omission
- `agent-feedback-tiers` — hint/reminder/instruction output tiers and the reminder admission rule
- `mechanical-guardrails` — enforce conventions structurally with ratchets, tripwires, contract tests, and derived artifacts
- `earned-guidance-docs` — write agent guidance only when earned by real failures; root contract plus read-on-demand docs

