Repository navigation
fix(cli): --help prints usage; unknown options are refused - #159
Merged
Merged
Conversation
`--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`,
`init --help` scaffolded a project called `--help`, `migrate:create -h` wrote
a migration named `-h`.
Each registry entry now declares its options ({name: takesValue}), 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` became `true`,
`--every` was ignored);
- `--name=value` works as well as `--name value`;
- `help` is not checked: `help --help` / `help -h` print the reference.
Also:
- `generate` refuses a name that starts with `-`;
- `ai --all` installs into the project (it installed into a folder named `--all`);
- `migrate:create --fields x` keeps the value with its option;
- `generate crud <Name> --skip-model` scaffolds CRUD around an existing model.
Port of the tina4-python fix on fix/cli-help-flags. Tests:
test/cliHelpFlags.test.ts, 90 no-mock cases against the built dist/bin.js; the
project tree is hashed before and after each --help run. On unfixed v3, 137 of
its first 213 assertions fail.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
This was referenced Oct 17, 2026
…rics gate `tina4 metrics --fail-on-regression` flagged the new code: checkOptions had cyclomatic complexity 16 (bin.ts worst CC 7 -> 16) and util.ts's parseFlags pushed the file under the maintainability floor (worst CC 6 -> 8). Same behaviour, smaller pieces, mirroring the Python reference: - checkOptions only walks the arguments; optionProblem(args, i, accepted, label) -> [message | null, consumed] judges one, with splitOption, isAccepted and hasValueAfter as one-line helpers; unknownOptionMessage builds the did-you-mean text. - editDistance fills its table through distanceCell. - main hands a registered command to runCommand (help flag, option check, handler). - parseFlags walks; readFlag stores one `--flag` and says how many arguments it used. Gate: exit 0, offenders 395 -> 395, bin.ts worst CC 7 -> 7, util.ts 6 -> 6. test/cliHelpFlags.test.ts 214 passed, typecheck clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
CodeQL (js/file-system-race) flagged the help-flags test's snapshot helper:
it stat'ed a path, then read it, leaving a window for the file to change.
readdirSync({ withFileTypes: true }) brings the type with the listing, so
there is no separate stat. Same snapshot output; 214 passed, typecheck clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andre van Zuydam <andrevanzuydam@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
--helpand-hnow 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, andai --allworks.This came from
tina4 generate model --help, which made a model called--help. Thetina4client 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
generate model --help--help(four files)lint --help/migrate --helpgenerate model Product --feilds name:stringUnknown option --feilds for "generate model". Did you mean --fields?exit 1generate model Product --fieldsOption --fields for "generate model" needs a value: --fields <value>exit 1--fields=price:float--fields price:floatgenerate crud Product --skip-model(the hintgenerate modelprints)help --helpHow 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--helprun never reaches code that writes. Delegated commands (doctor,setup,deploy) are untouched, because thetina4client answers those.Node specifics
ai --allinstalled into a folder named--all. It took--allas the project root; the root is now the first non-option argument, or..migrate:create <desc> --fields xfoldedxinto the description. The value now stays with its option.serveaccepts--productioneven though it doesn't read it, because the Dockerfileinitcreates runsserve --production. Node has no--hostand nostartalias.--json/--dry-runapply to every generator, because they all write through the same helpers.testtakes a single[file]and forwards nothing, so it's option-checked.ailine no longer mentions--force, which nothing read.Tests
test/cliHelpFlags.test.ts: 90 cases (214 checks) against the builtpackages/cli/dist/bin.js, each child with a temp HOME and a PATH holding only node. On unfixed v3, 137 of the first 213 checks fail, and 39 of the 62 help runs wrote to the project.npm test(local, no service containers): 9914 passed, 32 failed, 288 skipped. The failing files need MongoDB, Redis/Valkey, Memcached, GreenMail or the nativetina4binary, and each fails the same way on clean v3.Plan:
plan/cli-help-and-options.md.Parity PRs
tina4client (Termux/iSH,servesetsTINA4_PORT): Install, run and self-update tina4 on Termux (Android) and iSH (iOS) tina4#91🤖 Generated with Claude Code