Skip to content

fix(cli): --help prints usage; unknown options are refused - #238

Merged
tina4stack merged 2 commits into
v3from
fix/cli-help-flags
Oct 19, 2026
Merged

tina4stack merged 2 commits into
v3from
fix/cli-help-flags

Conversation

@andrevanzuydam

@andrevanzuydam andrevanzuydam commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

--help and -h now print a command's usage and change nothing, in every framework CLI. Unknown options are refused with a did-you-mean, value options need a value, and ai --all works.

This came from tina4 generate model --help, which made a model called --help. The tina4 client forwards these commands verbatim, so each framework CLI needed the fix. Python is the reference, and the other three are ports with equivalent no-mock tests.

What a user will see

Typed Before After
generate model --help a model named --help (four files) the generator's usage, exit 0, nothing written
lint --help / migrate --help lint ran (and installed its linter) / migrations ran usage, exit 0
generate model Product --feilds name:string model made without the fields, exit 0 Unknown option --feilds for "generate model". Did you mean --fields? exit 1
generate model Product --fields crash or silently ignored Option --fields for "generate model" needs a value: --fields <value> exit 1
--fields=price:float not understood everywhere same as --fields price:float
generate crud Product --skip-model (the hint generate model prints) option didn't exist CRUD around the existing model
help --help n/a the full reference

How it works: each command and generator in the CLI's registry declares the options it accepts (name -> takes a value). The help and option checks run before any handler, so a refused or --help run never reaches code that writes. Delegated commands (doctor, setup, deploy) are untouched, because the tina4 client answers those.

Python specifics (reference)

  • test isn't option-checked: its arguments go to pytest (test -q -k one still works).
  • Before this, --fields with no value crashed with AttributeError: 'bool' object has no attribute 'strip', and ai --all opened the menu because the code checked for the bare word all.

Tests

  • tests/test_cli_help_flags.py: 96 cases. Each runs the real tina4python entrypoint as a subprocess in a temp project, and every --help run hashes the project tree before and after. All 78 original help cases fail on unfixed v3.
  • tests/test_cli*.py: 250 passed, 1 skipped.
  • Full suite (macOS, CPython 3.14, no service containers):
Run Passed Failed Skipped
this branch 6184 2 938
unfixed v3 6091 3 938

No failure is new. Firebird connect-timeout and server libcrypto fail on both runs. v3's third failure is test_cli_serve_debug_env, which flakes on a real server boot (it failed once in seven runs on the branch too).

Plan: plan/cli-help-and-options.md.

Parity PRs

🤖 Generated with Claude Code

`--help` / `-h` after any command now prints that command's usage and exits 0
without touching the project. Handlers never looked for it, so it ran the
command for real: `generate model --help` wrote a model named `--help`,
`lint --help` installed ruff, `migrate --help` created app.db.

Each registry entry now declares its options ({name: takes_value}), and main()
checks them before any handler runs:
- an unknown option is refused with a did-you-mean (`--feilds` was silently
  dropped and the model came out without its fields);
- a value option with no value is refused (`--fields` crashed with a
  traceback, `--every` was ignored);
- `--name=value` works as well as `--name value`;
- `test` is not checked: its arguments belong to pytest.

Also:
- `generate` refuses a name that starts with `-`;
- `ai --all` installs every context file as its help says (it opened the menu);
- `help --help` prints the reference (`help` is not option-checked);
- `generate crud <Name> --skip-model` works. `generate model` has always
  suggested it, but no generator had the option.

Tests: 96 no-mock subprocess cases; the project tree is hashed before and
after each --help run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
The regression gate flagged _check_options at cyclomatic complexity 13.
Same behaviour and messages, in three small functions: _check_options walks
the arguments, _option_problem judges one, _unknown_option_message builds the
did-you-mean text. `tina4 metrics --path tina4_python --fail-on-regression`
passes; tests/test_cli_help_flags.py and test_cli_generate*: 185 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
@tina4stack
tina4stack merged commit 2ef5140 into v3 Oct 19, 2026
14 checks passed
@tina4stack
tina4stack deleted the fix/cli-help-flags branch October 19, 2026 06:22
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.

2 participants