ADR-0016: Completions and the man page are generated at runtime
- Status: Accepted
- Date: 2026-08-01
- Supersedes / Superseded by: —
Context
Issue #16 wants shell completions (bash/zsh/fish/powershell) and a man
page from the existing clap definitions. clap offers two delivery
routes: generate files at build time (a build.rs running
clap_complete/clap_mangen, artifacts wired into packaging) or
generate on demand from the installed binary (a subcommand).
Decision
Generation happens at runtime, from the installed binary:
margin completions <shell>prints the completion script to stdout — a visible verb, because users run it themselves (margin completions zsh > "$fpath[1]/_margin"or anevalin a shell rc file).margin manprints the roff page to stdout — hidden, because its audience is packagers and the curious (margin man | man -l -); interactive users read--help. Hidden still means stable: it is a CLI verb and carries the same compatibility promise as the rest (ADR-0007).- Both dispatch before config loading. Completions are eval’d from
shell startup files; a typo in
config.tomlmust never break a shell. This ordering is load-bearing and tested. - Output goes through a buffer, and a broken pipe on stdout is success,
not an error —
margin completions zsh | headis normal use, andclap_complete::generatepanics if handed a failing writer directly.
Why not build time:
- Drift-proof. The script always matches the binary that generates it. Pre-built files go stale against whatever version a user actually has installed — the classic completions bug.
- cargo-dist cannot run what it builds. Release artifacts are
cross-compiled; the build host cannot execute an aarch64-linux binary
to harvest its completions. Every packaging route that wants files
(Homebrew’s
generate_completions_from_executable, distro packages) runs the target binary at install time — which is exactly the interface this ADR ships. - Hermetic builds stay simple. No
build.rs, no generated files in the archive layout, nodist generatechurn.
Consequences
- Easier: one code path, zero packaging plumbing,
--help/man/completions can never disagree about the CLI surface. - Harder: completions are not pre-installed by the shell archives; users (or formulas) run one command once. The README documents each shell’s one-liner.
- Committed to: new verbs and flags appear in completions and the man page automatically — no release checklist item exists to forget.
Alternatives considered
build.rs+ cargo-dist artifact wiring: broken by design for cross-compiled targets (see above); adds generated-file drift and build complexity for zero user benefit. Rejected.- A
margin generateumbrella verb (completions + man under one namespace): two flat verbs are simpler, andcompletionsmatches the de-facto convention users already know from other tools. Rejected.