Repository navigation
docs/cli.md: a flag-level CLI reference for an agent, GENERATED from every shipped tool's --help, with a hygiene test that fails when the committed file drifts from what the generator produces #97
Description
Lane: openreposhape-2 (openRepoShape-2)
What was asked
Brett Heap, in session, 2026-09-10/11: "do we have documentation designed for
an AI to understand what our CLI can do and how to use it?"
The answer was no. AGENTS.md is PROCEDURE-first — it tells an assistant which
act to perform, in what order, and what it must not do — and README.md is the
standard itself. Neither is a flag-by-flag reference, and the only place the
current flags exist is in each tool's own --help, which an agent can only read
by running eleven commands and remembering the output. The README's one
concession is a sentence pointing at openRepoShape --help and setup.sh --help; that covers two of the seventeen entry points.
Brett's ruling: "add the docs/cli.md".
What this adds
docs/cli.md: a flag-level CLI reference, for an agent, generated from
every shipped tool's own --help output. Not hand-written, because a
hand-written flag list is a second copy of the flags that starts drifting the
day after it is written — the same argument this repository already makes about
a hand-edited pin.
scripts/render-cli-reference.py
Python 3 standard library. Runs each tool's --help (and each subcommand's)
from the repository root, captures stdout and stderr, and renders the whole
document:
- a header stating the file is GENERATED, by which script, and which test keeps
it honest; - a one-paragraph orientation for an agent, and a table giving what each tool is
FOR in one line — the only prose in the document, and it lives INSIDE the
generator, not in the output; - one section per tool, the help verbatim in a fenced block, subcommands nested;
- two groups: Run from a checkout of the standard and Shipped into every
project (copied, digest-pinned) — the second group's files are placed at
scripts/<name>.pyin a scaffolded project or a family holder and are run
from THERE, which the reference has to say or an agent will try to run them
here.
Determinism, because a generated file compared byte-for-byte flaps
otherwise: the child environment pins COLUMNS, forces UTF-8, and clears the
locale and colour variables; every line is stripped of trailing whitespace;
CRLF is folded to LF; and the usage: block is re-wrapped by this script from
its own collapsed tokens rather than left as argparse wrapped it — Python 3.14's
argparse breaks family.py bump's usage line in a different place from 3.12's,
and nothing but the line breaks differs, so collapsing and re-wrapping is
lossless and version-proof. Rule 1 is asserted directly: no host-absolute path
may land in the file.
tests/test_cli_reference.py
- regenerates into a temporary path and asserts byte-equality with the committed
docs/cli.md, printing a unified diff and the exact regeneration command on
failure; - asserts the header line, so the "do not edit" sentence cannot be lost;
- asserts that every shipped tool has a section, with the list DERIVED from
the repository rather than written down twice — so a tool added tomorrow and
forgotten here fails a test rather than going unlisted.
Windows. setup.sh and openRepoShape are bash, and the windows job has no
bash it can use (tests/conftest.py::WINDOWS_SKIP says why). The byte-equality
test is WINDOWS_SKIPped and the ubuntu and macOS jobs — the two platforms that
have a bash — carry it. The other assertions, and a per-tool check that every
PYTHON tool's help is the text the committed file carries, run everywhere,
Windows included, so that job still fails on real drift in fifteen of the
seventeen entries.
Everything else
AGENTS.md: ONE short paragraph pointing atdocs/cli.mdas the flag-level
reference and saying it is generated — never hand-edited.README.md:docs/cli.mdand the generator in the Layout block, and the
sentence that already points a reader at two--helptexts now points at the
file that has all of them.- Both line caps raised, with a dated docstring entry naming this issue.
templates/is untouched:git diff --stat origin/main -- templates/is
empty. Nothing here ships into a project.- No new README
##heading, soREADME_HEADING_TO_HANDBOOK_IDdoes not move;
the handbook'sREADME.md blob <hash>is re-cut because README.md changed.
Activity
brettheap commentedon Sep 11, 2026
CLAIMED — lane openreposhape-2 (openRepoShape-2), session 8fa66b30-4cf5-4b80-b40c-ac3640cf45ab, 2026-09-11T02:16Z, for the whole of this issue, branch
docs/cli-reference.Worktree
openRepoShape-worktrees/cli-referenceofforigin/mainat3d46ab5; the shared checkout is another live session's and is not touched.Sibling search before claiming:
gh issue list --state openandgh pr list --state openboth empty;--search "cli reference"across all states returns only #59 (the preflight), which is unrelated. Nothing to serialise behind.Reads before authoring, in full:
AGENTS.md(400 lines — AT its cap) andREADME.md(1324 — AT its cap), so both move with a dated docstring entry naming docs/cli.md: a flag-level CLI reference for an agent, GENERATED from every shipped tool's --help, with a hygiene test that fails when the committed file drifts from what the generator produces #97.tests/test_repo_hygiene.py(1479), for the guards this change has to stay inside:test_no_committed_file_names_a_host_absolute_path(tree-wide, so the generated file is bound by it),test_the_handbook_follows_the_readmes_outline(no new README##heading, and the footer'sREADME.md blob <hash>re-cut because README.md changes),test_every_naming_families_count_matches_the_policy(tree-wide over.md/.html, so the generated file must not carry the phrase),test_the_windows_commands_name_files_that_exist(single-match unpacks ofInvoke-WebRequestandpy <file>in README.md and AGENTS.md — neither may gain a second), andtest_the_materializers_account_for_every_template_file(nothing undertemplates/moves).tests/conftest.py(REPO,SCAFFOLD,WINDOWS_SKIPand the reason it exists) and.github/workflows/tests.yml(ubuntu / windows / macOS).--help, and every subcommand's:setup.sh,openRepoShape,setup-project.py,scaffold-project.py,adopt-project.py+plan/check/execute,update-shape.py+check/apply,shape-doctor.py,bootstrap,scripts/bump-leg.py,scripts/family.py+init/add/bump/remove/siblings,scripts/validate-repository-naming.py, and the six project-side copies undertemplates/*/scripts/.Two facts found by reading that shape the design, both recorded here before any of it is written:
sys.path.insert(0, <its own directory>)and thenfrom repo_shape import …;repo_shape.pyis beside them only in a materialized project. The generator runs them withscripts/onPYTHONPATH, which the inserted directory still shadows, so nothing about the files changes.COLUMNS=80 python3.12andCOLUMNS=80 python3.14agree on all twenty-two help texts exceptfamily.py bump, where 3.14 keeps--to COMMITtogether and 3.12 breaks it. CI pinspython-version: '3.x', so a byte-equality test written naively is red the day the runner moves. The generator therefore re-wraps theusage:block itself from the collapsed tokens — the tokens are identical, only the breaks differ — and pinsCOLUMNS, UTF-8 and the locale in the child environment.Merge origin/main: `docs/cli.md` regenerated for `--placement-plan`, …
docs/handbook.html, tests/test_repo_hygiene.py: re-pin the handbook t…
templates/workspace-root: the <user>-wip template (lane protocol Amen…