Skip to content

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

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

tina4stack merged 3 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.

Ruby specifics

  • serve/start keep -h as --host. Only --help is help there, so serve -h 0.0.0.0 scripts don't break. -p and -d still work.
  • OptionParser commands print the shared usage format, and an OptionParser error the check can't catch (serve --port abc) prints the "Run … --help" line instead of a backtrace.
  • Ruby-only options are kept: migrate --create/--rollback, migrate:rollback --steps, seed --clear, init --template.
  • test reads no arguments, so it's option-checked.
  • ai --all crashed on v3, because ai.rb never loaded Tina4::VERSION. Fixed with one require_relative.
  • Now refused: option abbreviations OptionParser used to accept (--po) and bundled short flags (-dp), the same as Python.
  • Top-level help now reads Usage: tina4ruby <command> [options], the same as the other three (it said COMMAND).
  • Not changed: test runs Tina4's inline tests, not RSpec, so there's no runner to hand arguments to as Python (pytest) and PHP (PHPUnit) do. Wrapping RSpec is a design change for its own PR.

Tests

  • spec/cli_help_flags_spec.rb: 106 examples, running the real exe/tina4ruby in temp projects. 98 of the first 105 fail on unfixed v3, including all 66 help cases. serve -h is checked three ways, including a short-lived real server on -p PORT -h 127.0.0.1 that answers /health.
  • CLI-related specs: 292 examples, 0 failures, 1 pending. spec/cli_spec.rb + the help spec after the wording change: 116 examples, 0 failures.
  • Full suite locally: 6981 examples, 32 failures, 688 pending. All 32 also fail on clean v3: Redis, Valkey, Memcached and Postgres-backed specs that need CI's service containers.
  • Warning: on unfixed v3, lint --help really runs bundle add rubocop. Running the new spec against old code can touch Gemfile.lock.

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. Most handlers never looked for it, so it ran the
command for real: `generate model -h` wrote a model named `-h`, `generate auth
--help` wrote the auth scaffold, `lint --help` ran `bundle add rubocop`,
`migrate:status --help` booted the app. OptionParser commands printed their
own banner; every command now prints one format. `serve` / `start` keep `-h`
as --host, so `-h 127.0.0.1` still works; `--help` is help everywhere.
`help --help` prints the full reference (help is not option-checked).

Each registry entry now declares its options ({name => takes_value}, plus
OptionParser short aliases), and #run checks them before any handler runs:
- an unknown option is refused with a did-you-mean (`--feilds` was silently
  dropped; `queue work --onse` polled forever);
- a value option with no value is refused (`serve --port` raised
  OptionParser::MissingArgument, `--every` was ignored), and an OptionParser
  error such as `--port abc` no longer prints a backtrace;
- `--name=value` works as well as `--name value`.

Also: `generate` refuses a name that starts with `-`; `generate crud
--skip-model` is implemented (`generate model` suggests it); `ai --all` works
(it crashed: ai.rb never loaded Tina4::VERSION) and `ai all` too.

Tests: 106 no-mock cases running the real exe/tina4ruby; the project tree is
hashed before and after each --help run. Ruby port of tina4-python
fix/cli-help-flags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
andrevanzuydam and others added 2 commits October 17, 2026 04:40
`tina4 metrics --fail-on-regression` flagged check_options (cyclomatic
complexity 14; cli.rb offenders 6 -> 7). Split it the way the Python reference
did: check_options walks argv, option_problem(argv, i, accepted, short, label)
judges one argument and returns [message, consumed], option_name reads the
long name from `--name`, `--name=value`, `-p` or `-p7147`, and
unknown_option_message builds the did-you-mean text. Behaviour and messages
are unchanged.

Gate: offenders 277 -> 277, exit 0. spec/cli_help_flags_spec.rb 106/106,
CLI specs 292 examples, 0 failures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
`tina4ruby --help` read `Usage: tina4ruby COMMAND [options]`, and its footer
`Run 'tina4ruby COMMAND --help'`. Python, PHP and Node all say
`Usage: tina4<lang> <command> [options]`; Ruby now matches. spec/cli_spec.rb
and spec/cli_help_flags_spec.rb assert the new text (116 examples, 0
failures); metrics gate exit 0.

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