Define observable CLI behavior: argument handling, summaries, error UI, and output writing.
- CLI runner:
codeclone/cli.py:main,codeclone/cli.py:_main_impl - Parser:
codeclone/_cli_args.py:build_parser - Summary renderer:
codeclone/_cli_summary.py:_print_summary - Path validation:
codeclone/_cli_paths.py:_validate_output_path - Message catalog:
codeclone/ui_messages.py
CLI modes:
- Normal mode
- Gating mode (
--ci,--fail-on-new,--fail-threshold>=0) - Update mode (
--update-baseline)
Summary metrics:
- files found/analyzed/cache hits/skipped
- structural counters: analyzed lines/functions/methods/classes
- function/block/segment groups
- suppressed segment groups
- dead-code active/suppressed status in metrics line
- new vs baseline
Refs:
codeclone/_cli_summary.py:_print_summarycodeclone/ui_messages.py:fmt_summary_files
- Help output includes canonical exit-code section and project links.
- Reporting flag UX uses explicit pairs (
--no-progress/--progress,--no-color/--color) and avoids generated double-negation aliases. --open-html-reportis a local UX action layered on top of--html; it does not implicitly enable HTML output.--timestamped-report-pathsonly rewrites default report paths requested via bare report flags; explicit FILE values stay unchanged.- Changed-scope clone review uses:
--changed-only--diff-against GIT_REF--paths-from-git-diff GIT_REFTypical usage:codeclone . --changed-only --diff-against maincodeclone . --paths-from-git-diff HEAD~1
- Contract errors are prefixed by
CONTRACT ERROR:. - Gating failures are prefixed by
GATING FAILURE:. - Internal errors use
fmt_internal_errorwith optional debug details. - Runtime footer uses explicit wording:
Pipeline done in <seconds>s. This metric is CLI pipeline time and does not include external launcher/startup overhead (for exampleuv run). - Dead-code metric line is stateful and deterministic:
N found (M suppressed)when active dead-code items exist✔ cleanwhen both active and suppressed are zero✔ clean (M suppressed)when active is zero but suppressed > 0
Refs:
codeclone/contracts.py:cli_help_epilogcodeclone/ui_messages.py:fmt_contract_errorcodeclone/ui_messages.py:fmt_internal_error
- Report writes (
--html/--json/--md/--sarif/--text) are path-validated and write failures are contract errors. - Bare reporting flags write to default deterministic paths under
.cache/codeclone/. --open-html-reportrequires--html; invalid combination is a contract error.--timestamped-report-pathsrequires at least one requested report output; invalid combination is a contract error.--changed-onlyrequires either--diff-againstor--paths-from-git-diff.--diff-againstrequires--changed-only.--diff-againstand--paths-from-git-diffare mutually exclusive.- Browser-open failure after a successful HTML write is warning-only and does not change the process exit code.
- Baseline update write failure is contract error.
- In gating mode, unreadable source files are contract errors with higher priority than clone gating failure.
- Changed-scope flags do not create a second canonical report: they project clone summary/threshold decisions over the changed-files subset after the normal full analysis completes.
Refs:
codeclone/cli.py:_write_report_outputcodeclone/cli.py:_main_impl
| Condition | User-facing category | Exit |
|---|---|---|
| Invalid CLI flag | contract | 2 |
| Invalid output extension/path | contract | 2 |
--open-html-report without --html |
contract | 2 |
--timestamped-report-paths without reports |
contract | 2 |
--changed-only without diff source |
contract | 2 |
--diff-against without --changed-only |
contract | 2 |
--diff-against + --paths-from-git-diff |
contract | 2 |
| Baseline untrusted in CI/gating | contract | 2 |
| Unreadable source in CI/gating | contract | 2 |
New clones with --fail-on-new |
gating | 3 |
| Threshold exceeded | gating | 3 |
| Unexpected exception | internal | 5 |
- Summary metric ordering is fixed.
- Compact summary mode (
--quiet) is fixed-format text. - Help epilog is generated from static constants.
git diff --name-onlyinput is normalized to sorted repo-relative paths before changed-scope projection is applied.
Refs:
codeclone/_cli_summary.py:_print_summarycodeclone/contracts.py:EXIT_CODE_DESCRIPTIONS
tests/test_cli_unit.py::test_cli_help_text_consistencytests/test_cli_unit.py::test_argument_parser_contract_error_marker_for_invalid_argstests/test_cli_inprocess.py::test_cli_summary_format_stabletests/test_cli_inprocess.py::test_cli_unreadable_source_fails_in_ci_with_contract_errortests/test_cli_inprocess.py::test_cli_contract_error_priority_over_gating_failure_for_unreadable_source
- Rich styling details are not part of machine-facing CLI contract.
- Warning phrasing may evolve if category markers and exit semantics stay stable.