cli: align with Typer's bundled agent skill - #15
Merged
Conversation
Reviewed src/icebergsca/cli/main.py against the typer skill shipped at typer/.agents/skills/typer/SKILL.md. The explicit Typer app, Annotated declarations and absence of Click-era settings already matched; these are the gaps. - --scope and --ecosystem took a single comma-separated string, so their help showed <str> and listed no choices, unlike --format and unlike --exclude in the same command. They now take a repeatable list and advertise their members in the metavar. Comma-separated values still parse, so every documented invocation is unchanged. - The sbom docstring used RST double backticks, which the default Rich markup mode renders literally. Uses Rich markup instead. - rich_markup_mode is now stated rather than inferred, so help output does not change shape with what else is installed. - sbom's -v/-q had no help text; the cache sub-app had no no_args_is_help, so a bare `icebergsca cache` errored where a bare `icebergsca` helps. - Floor typer at 0.26, the release that vendored Click. Below it, an unrelated Click upgrade governs parsing and exit codes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJSEXcpbfSLbYqHc2t2WY2
No deployments to keep compatible, so the comma-separated form goes and the options become plain list[Scope] and list[EcosystemId]. Typer derives the choices metavar, validates the values and rejects a bad one as a usage error by itself, which is exactly what _parse_enum_option and _choices_metavar were reimplementing — both are now gone, along with the EnumT TypeVar. Help output and exit codes are unchanged. Docs and the bundled skill now show the repeated form. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJSEXcpbfSLbYqHc2t2WY2
test_enum_choices_are_listed_in_help passed locally and failed on all four CI Pythons. Rich counts GitHub Actions as a terminal, so help output is bare off CI and styled on it — and it styles each choice in a metavar separately, putting escape codes between every value: <\x1b[1;33mpypi\x1b[0m|\x1b[1;33mnpm\x1b[0m|... so the plain substring is never present there. Strips the codes first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJSEXcpbfSLbYqHc2t2WY2
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.
Reviewed
src/icebergsca/cli/main.pyagainst the agent skill Typer ships attyper/.agents/skills/typer/SKILL.md(typer 0.27.0), and closed the gaps.Already aligned
Explicit
typer.Typer()app rather thantyper.run;Annotatedthroughout, with no old-style= typer.Option(...)defaults ordefault=...ellipsis;no_args_is_helpon the root app;list[str]for the repeatable--exclude; a boolean flag pair onsbom; an eager--versioncallback. None of the Click-era settings the skill calls out (expose_value,shell_complete,show_choices,errors,prompt_required,is_flag,flag_value,allow_from_autoenv) appear anywhere insrc/, and nothing imports Click.--scopeand--ecosystemare now Typer enum listsThey took a single comma-separated
strand hand-rolled the splitting and enum validation, so--helprendered<str>and advertised no choices — inconsistent with--format, which Typer converts natively, and with--excludein the same command, already a list. The skill's "CLI options with multiple values" section is explicit that a multi-value option is a list.They are now
list[Scope] | Noneandlist[EcosystemId] | None. Typer derives the metavar, validates each value, and rejects a bad one as a usage error on its own, so_parse_enum_option,_choices_metavarand theEnumTTypeVar are all gone — 42 lines out, 8 in.Breaking:
--scope runtime,devis now a usage error; use--scope runtime --scope dev. Taken on the basis that there are no deployments to keep compatible. Exit codes and the rest of the help output are unchanged.Other fixes
sbomdocstring used RST double backticks, which the default Rich markup mode renders literally in--help. Now uses[bold], per the skill's Rich section.rich_markup_modeis stated on the app rather than inferred, so help output does not change shape with what else is installed.sbom's-v/-qhad no help text, unlike the same flags onscan.cachesub-app lackedno_args_is_help, so a bareicebergsca cacheerrored with exit 2 while a bareicebergscaprinted help.typerat 0.26, the release that vendored Click. Below that, an unrelated Click upgrade in the same environment governs this CLI's parsing and exit codes — andExitCode.USAGE = 2is justified in its own docstring by Click's reservation of that code. The lock already resolved to 0.27.Docs
README.md,website/docs/cli.md,website/docs/ecosystems.mdand the bundled.agents/skills/icebergsca/SKILL.mdnow show the repeated form, per the CLAUDE.md rule that a skill describing flags that no longer exist is worse than none.Verification
ruff check,ruff format --check,mypyandpytestall pass — 386 tests, up from 384. Addedtest_scope_flag_is_repeatableandtest_enum_choices_are_listed_in_help, the latter asserting the choices reach--helpso a future switch back to a bare<str>metavar fails loudly.Dogfooded
icebergsca scan . --ecosystem pypi --scope runtime --scope build --format json— 50 dependencies, correct scope union.