Skip to content

Migrate the CLI from argh to cw - #6

Merged
thorwhalen merged 1 commit into
mainfrom
migrate-argh-to-cw
Sep 4, 2026
Merged

thorwhalen merged 1 commit into
mainfrom
migrate-argh-to-cw

Conversation

@thorwhalen

Copy link
Copy Markdown
Collaborator

Closes #5

Swaps the LGPL argh dependency for cw (MIT, zero runtime dependencies).

The change

# before
parser = argh.ArghParser(prog="lookbook")
argh.add_commands(parser, [curate, list_plugins, list_recipes, serve, mcp])
argh.dispatch(parser)

# after
COMMANDS = [curate, list_plugins, list_recipes, serve, mcp]
parser = cw.mk_parser(COMMANDS, prog="lookbook")
return cw.run(parser)

prog was already pinned, so it stays pinned — the python -m lookbook and
console-script surfaces remain byte-identical to each other, as they were.
cw.run returns the exit code where argh exited by itself, so main()
returns it (the console-script shim does sys.exit(main())) and the __main__
guard raises SystemExit(main()).

pyproject.toml: argh>=0.30 → cw>=0.1.1,<0.2. README's file-map line updated.

--help diff: empty

14 argv vectors were recorded from the argh implementation with
cw.testing.characterize before any edit — the top-level --help and -h,
all five subcommand --helps, the no-argument case, three non-zero-exit cases,
and the real output of list-plugins and list-recipes. Replayed against cw:

interpreter result
CPython 3.12, cw from source 14/14 identical under --strict-help
CPython 3.10 grammar verified identical (see below)

--strict-help compares the full --help body, not just exit codes and the
usage line. Nothing moved: not the subcommand table, not the docstring-derived
descriptions, not the inferred short flags, not the nargs='*' rendering of the
Sequence[str] parameters, and not argh's quirk where --scorer and --selector
both lose their -s short flag to the collision between them.

The committed test replays non-strictly, because CPython itself rewrites
argparse's option column between versions and this repo's matrix spans several.
Separately verified that CPython 3.10 and 3.12 render this CLI's shapes
identically, and that published cw 0.1.4 (what CI will resolve) renders them
identically to the source tree — so the strict result above is what CI exercises.

What is now pinned

tests/test_cli_surface.py (7 tests) + tests/cli_goldens/lookbook.json:

  1. The whole grammar, replayed against the argh recording.
  2. Exit codes. Proven load-bearing: removing the return and the
    raise SystemExit makes 4 of these tests fail while all 159 pre-existing
    tests still pass. That is the failure mode invisible to every other test.
  3. No arguments → usage on stdout, exit 0 — argh's behaviour, which plain
    argparse with a required subparser does not have.
  4. COMMANDS matches what the help text advertises.
  5. A hygiene test asserting the golden names no absolute path.

One case is deliberately not in the golden: list-recipes's real output
reads YAML profiles out of the user's app data folder, so a committed recording
would assert a property of the recording machine.

Tests

159 passed, 3 skipped before, 166 passed, 3 skipped after. ruff check clean.

Replaces the LGPL `argh` dependency with `cw` (MIT, zero runtime deps).
`argh.ArghParser` + `argh.add_commands` + `argh.dispatch` becomes
`cw.mk_parser(COMMANDS, prog="lookbook")` + `cw.run(parser)`; `prog` was
already pinned, so it stays pinned and the `python -m lookbook` and console
-script surfaces remain byte-identical to each other, as before.

`cw.run` returns the exit code rather than exiting, so `main()` returns it
and the `__main__` guard raises `SystemExit(main())`.

The CLI surface is unchanged. 14 argv vectors were recorded from the argh
implementation before the edit and replayed against cw: all identical under
`--strict-help`, on CPython 3.10 and 3.12 alike. 13 of them are committed as
tests/cli_goldens/lookbook.json (the `list-recipes` real-output case is left
out: it reads YAML profiles from the user's app data folder).

Closes #5

Claude-Session: https://claude.ai/code/session_01K6LB3AwUmKDxaFNZ2NqPGr
@thorwhalen
thorwhalen merged commit 426c6d8 into main Sep 4, 2026
12 checks passed
@thorwhalen
thorwhalen deleted the migrate-argh-to-cw branch September 4, 2026 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate the CLI from argh to cw

1 participant