git-cai-cli 0.14.1__tar.gz → 0.15.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. git_cai_cli-0.15.1/.caiignore +1 -0
  2. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.gitignore +2 -0
  3. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.pylintrc +4 -4
  4. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/PKG-INFO +60 -10
  5. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/README.md +59 -9
  6. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/docs/git-cai.txt +50 -0
  7. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/docs/man/git-cai.1 +80 -2
  8. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/__init__.py +2 -0
  9. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/_version.py +3 -3
  10. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/cli/cli.py +29 -1
  11. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/cli/helptext.py +7 -0
  12. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/cli/modes.py +7 -3
  13. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/config.py +1 -0
  14. git_cai_cli-0.15.1/src/git_cai_cli/core/doctor.py +195 -0
  15. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/gitutils.py +54 -0
  16. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/llm.py +97 -6
  17. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/options.py +2 -0
  18. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/pr.py +9 -0
  19. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/prompts_fallback.py +2 -2
  20. git_cai_cli-0.15.1/src/git_cai_cli/core/secrets.py +160 -0
  21. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/squash.py +18 -0
  22. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/validate.py +7 -0
  23. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/main.py +48 -17
  24. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli.egg-info/PKG-INFO +60 -10
  25. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli.egg-info/SOURCES.txt +5 -0
  26. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_cli_integration.py +2 -1
  27. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_amend.py +61 -1
  28. git_cai_cli-0.15.1/tests/unit/test_classification.py +81 -0
  29. git_cai_cli-0.15.1/tests/unit/test_doctor.py +117 -0
  30. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_prompt_loading.py +25 -0
  31. git_cai_cli-0.15.1/tests/unit/test_secrets.py +120 -0
  32. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/uv.lock +64 -76
  33. git_cai_cli-0.14.1/.caiignore +0 -5
  34. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.gitattributes +0 -0
  35. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/cd/.SRCINFO +0 -0
  36. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/cd/PKGBUILD +0 -0
  37. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/ci/_version.py +0 -0
  38. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/ci/cai_config.ci.yml +0 -0
  39. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/ci/tokens.ci.yml +0 -0
  40. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/workflows/python-tests.yml +0 -0
  41. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/workflows/release.yml +0 -0
  42. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.github/workflows/release_aur.yml +0 -0
  43. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.bandit.yml +0 -0
  44. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.checkov.yml +0 -0
  45. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.flake8 +0 -0
  46. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.ls-lint.yml +0 -0
  47. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.markdown-link-check.json +0 -0
  48. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.markdownlint.json +0 -0
  49. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.proselintrc +0 -0
  50. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/.yamllint.yml +0 -0
  51. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/check_git_branch_name.sh +0 -0
  52. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/lychee.toml +0 -0
  53. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.linters/pyrightconfig.json +0 -0
  54. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.markdownlintignore +0 -0
  55. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.mega-linter.yml +0 -0
  56. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.semgrepignore +0 -0
  57. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/.trivyignore +0 -0
  58. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/CLAUDE.md +0 -0
  59. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/LICENSE +0 -0
  60. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/Makefile +0 -0
  61. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/cai_config.yml +0 -0
  62. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/pyproject.toml +0 -0
  63. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/setup.cfg +0 -0
  64. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/cli/__init__.py +0 -0
  65. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/__init__.py +0 -0
  66. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/completion.py +0 -0
  67. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/editors.py +0 -0
  68. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/init.py +0 -0
  69. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/languages.py +0 -0
  70. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/spinner.py +0 -0
  71. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli/core/stats.py +0 -0
  72. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli.egg-info/dependency_links.txt +0 -0
  73. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli.egg-info/entry_points.txt +0 -0
  74. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli.egg-info/requires.txt +0 -0
  75. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/src/git_cai_cli.egg-info/top_level.txt +0 -0
  76. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/conftest.py +0 -0
  77. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_config_integration.py +0 -0
  78. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_gitutils_integration.py +0 -0
  79. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_modes_integration.py +0 -0
  80. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_options_integration.py +0 -0
  81. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_pr_integration.py +0 -0
  82. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/integration/test_squash_integration.py +0 -0
  83. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_branch_context.py +0 -0
  84. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_cli.py +0 -0
  85. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_completion.py +0 -0
  86. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_config.py +0 -0
  87. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_conventional.py +0 -0
  88. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_gitutils.py +0 -0
  89. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_helptext.py +0 -0
  90. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_init.py +0 -0
  91. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_llm.py +0 -0
  92. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_main.py +0 -0
  93. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_modes.py +0 -0
  94. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_options.py +0 -0
  95. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_pr.py +0 -0
  96. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_print.py +0 -0
  97. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_set_config.py +0 -0
  98. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_signoff.py +0 -0
  99. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_spinner.py +0 -0
  100. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_squash.py +0 -0
  101. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_stats.py +0 -0
  102. {git_cai_cli-0.14.1 → git_cai_cli-0.15.1}/tests/unit/test_validate.py +0 -0
@@ -0,0 +1 @@
1
+ tests/unit/test_secrets.py
@@ -7,6 +7,8 @@ src/git_cai_cli.egg-info/
7
7
  megalinter-reports/
8
8
  __pycache__/
9
9
  .ruff_cache/
10
+ .pytest_cache/
11
+ .mypy_cache/
10
12
  .venv/
11
13
 
12
14
  # files
@@ -7,7 +7,7 @@ persistent=yes # Save data between runs (improves inference cac
7
7
  unsafe-load-any-extension=no # Prevent loading arbitrary C extensions for safety
8
8
 
9
9
  ignore=venv,build,dist,__pycache__,tests # Ignore common generated/virtual dirs
10
- ignore-paths=.*[\\/](\.venv|\.mypy_cache|\.pytest_cache|build|dist|docs)([\\/].*)?$
10
+ ignore-paths=.*[\\/](\.venv|\.mypy_cache|\.pytest_cache|build|dist|docs)([\\/].*)?$,.*[\\/]_version\.py$
11
11
 
12
12
  ignore-patterns=^\.#,^__init__\.py$ # Ignore editor lockfiles (e.g., Emacs)
13
13
 
@@ -66,12 +66,12 @@ check-protected-access-in-special-methods=no
66
66
  # Don’t warn about protected attr access in dunder methods
67
67
 
68
68
  [DESIGN]
69
- max-args=25 # Max arguments per function
69
+ max-args=30 # Max arguments per function
70
70
  max-attributes=12 # Max attributes per class
71
71
  max-branches=30 # Max branches per function
72
- max-locals=70 # Max locals per function
72
+ max-locals=80 # Max locals per function
73
73
  max-returns=10 # Max return statements per function
74
- max-statements=120 # Max total statements per function
74
+ max-statements=130 # Max total statements per function
75
75
  max-public-methods=20 # Max public methods per class
76
76
  min-public-methods=1 # Min public methods per class
77
77
  max-nested-blocks=15 # Max nesting depth
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-cai-cli
3
- Version: 0.14.1
3
+ Version: 0.15.1
4
4
  Summary: Use LLM to create git commit messages
5
5
  Author-email: Thorsten Foltz <thorsten.foltz@live.com>
6
6
  License-Expression: MIT
@@ -79,7 +79,7 @@ Currently supported providers:
79
79
  - Global configuration with per-repository overrides
80
80
  - Interactive `--init` wizard for first-time setup (provider, token, language, style)
81
81
  - Repository-specific language, style, and model selection
82
- - Amend the last commit message with a regenerated one
82
+ - Amend mode refines the existing commit message instead of regenerating it from scratch, preserving trailers and intent
83
83
  - Conventional Commits format support
84
84
  - `Signed-off-by:` (DCO) trailer support via `--signoff`
85
85
  - `--print` mode that emits the generated message to stdout for scripting
@@ -95,6 +95,9 @@ Currently supported providers:
95
95
  - Generation time measurement
96
96
  - Local-only usage analytics (per-provider commits, tokens, latency) with opt-in SQLite storage
97
97
  - Shell completion for bash, zsh, and fish
98
+ - Local secret scan that blocks the diff before it reaches the provider when likely credentials are detected
99
+ - Configuration doctor (`--check`) that validates your setup offline, with an optional live provider probe (`--ping`)
100
+ - Mixed code and documentation diffs are classified by the functional change rather than mislabelled as docs
98
101
 
99
102
  ---
100
103
 
@@ -261,6 +264,8 @@ git cai -g
261
264
  - `stats` – opt in to local-only usage analytics (per-run row in a SQLite DB at `~/.local/share/git-cai/stats.db`); default `false`.
262
265
  No diff content, commit messages, or file paths are stored — only metadata (provider, model, kind, repo name, token counts, latency, settings)
263
266
  - `signoff` – append a `Signed-off-by:` trailer (built from git `user.name` / `user.email`) to every commit message; default `false`
267
+ - `secret_scan` – scan the outgoing diff for likely secrets and ask before sending; default `true`. Bypass once with `-B` / `--allow-secrets`,
268
+ or disable entirely by setting it to `false`. Skipped for tokenless providers (Ollama), where nothing leaves the machine
264
269
 
265
270
  ---
266
271
 
@@ -268,13 +273,14 @@ No diff content, commit messages, or file paths are stored — only metadata (pr
268
273
 
269
274
  In addition to `git cai`, the following options are available:
270
275
 
271
- - `-A`, `--amend` – regenerate and amend the last commit message
276
+ - `-A`, `--amend` – refine the last commit message against its diff and amend it (preserves trailers and original intent)
272
277
  - `-a`, `--all` – stage all tracked modified and deleted files
278
+ - `-B`, `--allow-secrets` – bypass the local secret scan and send the diff even if a likely secret is detected
273
279
  - `-b`, `--branch` – include current branch name as context for the LLM
274
280
  - `-C`, `--conventional` – use Conventional Commits format (`type(scope): description`)
275
281
  - `-c`, `--crazy` – Trust the LLM and commit without checking
276
282
  - `-d`, `--debug` – enable debug logging
277
- - `-e`, `--temperature` `TEMPERATURE` – override the active provider's sampling temperature for this invocation (provider-scoped, like `-m`)
283
+ - `-E`, `--temperature` `TEMPERATURE` – override the active provider's sampling temperature for this invocation (provider scoped, like `-m`)
278
284
  - `-F`, `--full-files` – attach the full contents of affected files alongside the diff (uses `full_files_prompt.md`)
279
285
  - `-f`, `--files` `PATH` – limit the diff (and full-file content, if enabled) to PATH; repeat for multiple files
280
286
  - `-g`, `--generate-config` – generate the default `cai_config.yml` in the current directory
@@ -282,8 +288,10 @@ In addition to `git cai`, the following options are available:
282
288
  - `-h`, `--help` – show help and available commands
283
289
  - `-I`, `--init` – interactive setup wizard (writes home config and tokens.yml)
284
290
  - `-i`, `--install-completion` – install shell completion for bash, zsh, or fish
291
+ - `-k`, `--check` – run configuration diagnostics offline (config source, provider, token, prompts, editor, style)
285
292
  - `-l`, `--list` – list available information. Valid types: `config`, `editor`, `language`, `model`, `path`, `provider`, `style`
286
293
  - `-m`, `--model` – override the model for this invocation (requires `-P`)
294
+ - `-n`, `--ping` – with `--check`, also send a tiny request to the active provider to confirm reachability
287
295
  - `-o`, `--signoff` / `--no-signoff` – append a `Signed-off-by:` trailer (uses git `user.name` / `user.email`); applies to commit, amend, and squash modes
288
296
  - `-P`, `--provider` – override the LLM provider for this invocation
289
297
  - `-p`, `--generate-prompts` – generate default `commit_prompt.md` and `squash_prompt.md` in the current directory (for customization)
@@ -297,9 +305,9 @@ In addition to `git cai`, the following options are available:
297
305
  - `--base` `BRANCH` – explicit base branch for `--PR` (overrides auto-detection: `origin/HEAD` → `main` → `master`)
298
306
  - `-S`, `--set` – set a config value (`key=value`) in repo config (requires existing repo config)
299
307
  - `-s`, `--squash` `[N|HASH]` – squash commits on the current branch and summarize them. Without argument: squash all since branch checkout. With a number: squash the last N commits. With a commit hash: squash up to and including that commit
300
- - `--style` `STYLE` – override the commit message style for this invocation (e.g. `funny`, `neutral`, `none`); validated against the supported styles
301
- - `--language` `CODE` – override the commit message language for this invocation (e.g. `de`, `fr`, `none`); validated against supported codes
302
- - `--emoji` / `--no-emoji` – override emoji usage for this invocation (use `--no-emoji` to disable when config enables it)
308
+ - `-y`, `--style` `STYLE` – override the commit message style for this invocation (e.g. `funny`, `neutral`, `none`); validated against the supported styles
309
+ - `-L`, `--language` `CODE` – override the commit message language for this invocation (e.g. `de`, `fr`, `none`); validated against supported codes
310
+ - `-e`, `--emoji` / `--no-emoji` – override emoji usage for this invocation (use `--no-emoji` to disable when config enables it)
303
311
  - `-T`, `--timeout` `SECONDS` – HTTP timeout for this invocation (overrides config)
304
312
  - `-t`, `--time` – measure and log commit message generation time
305
313
  - `-u`, `--update` – check for updates
@@ -310,14 +318,17 @@ In addition to `git cai`, the following options are available:
310
318
 
311
319
  ### Amend
312
320
 
313
- To regenerate the last commit message and amend it:
321
+ To refine the last commit message and amend it:
314
322
 
315
323
  ```sh
316
324
  git cai -A
317
325
  ```
318
326
 
319
- This reads the diff from the most recent commit, sends it to the LLM, and opens the editor for review.
320
- Use with `-c` to amend immediately without the editor: `git cai -A -c`.
327
+ This reads the diff from the most recent commit and sends both the diff and the
328
+ existing message to the LLM, which improves the wording while keeping the
329
+ original intent and any trailers (issue IDs, `Co-authored-by`). The result opens
330
+ in the editor for review. Use with `-c` to amend immediately without the editor:
331
+ `git cai -A -c`.
321
332
 
322
333
  ### Conventional Commits
323
334
 
@@ -466,6 +477,45 @@ git cai -H language=de
466
477
  git cai -H emoji=false
467
478
  ```
468
479
 
480
+ ### Configuration check (doctor)
481
+
482
+ `-k` / `--check` runs a set of offline diagnostics so you can confirm cai is
483
+ set up correctly without contacting any provider. It reports the authoritative
484
+ config source, validates the config keys, checks the active provider block, the
485
+ token and `tokens.yml` permissions, prompt resolution, the editor on your PATH,
486
+ and the configured style.
487
+
488
+ ```sh
489
+ git cai -k # offline diagnostics only
490
+ git cai --check # long form
491
+ git cai -k -n # also probe the provider for reachability
492
+ git cai --check --ping # long form
493
+ ```
494
+
495
+ Add `-n` / `--ping` to send one tiny synthetic diff to the active provider and
496
+ confirm it is reachable (this consumes a minimal request). The command exits
497
+ non-zero if any check fails, so it works in scripts and CI.
498
+
499
+ ### Secret scanning
500
+
501
+ Before any diff leaves your machine, cai scans it for likely credentials
502
+ (private keys, AWS, OpenAI, GitHub, Slack, and Google keys). When something is
503
+ found, the location is shown as `path:line` with a masked value and you are
504
+ asked to confirm before anything is sent.
505
+
506
+ ```sh
507
+ git cai # scan runs automatically, prompts on a hit
508
+ git cai -B # bypass the scan for this run
509
+ git cai --allow-secrets # long form
510
+ git cai -S secret_scan=false # disable the scan persistently
511
+ ```
512
+
513
+ Obvious placeholders (`example`, `dummy`, repeated filler, and similar) are
514
+ ignored to keep the noise down, and the scan is skipped entirely for tokenless
515
+ providers such as Ollama, where nothing leaves the machine. In non-interactive
516
+ runs (`-c` / `--crazy`, or no TTY) a detection aborts the send instead of
517
+ prompting; re-run with `-B` to override.
518
+
469
519
  ---
470
520
 
471
521
  ## License
@@ -49,7 +49,7 @@ Currently supported providers:
49
49
  - Global configuration with per-repository overrides
50
50
  - Interactive `--init` wizard for first-time setup (provider, token, language, style)
51
51
  - Repository-specific language, style, and model selection
52
- - Amend the last commit message with a regenerated one
52
+ - Amend mode refines the existing commit message instead of regenerating it from scratch, preserving trailers and intent
53
53
  - Conventional Commits format support
54
54
  - `Signed-off-by:` (DCO) trailer support via `--signoff`
55
55
  - `--print` mode that emits the generated message to stdout for scripting
@@ -65,6 +65,9 @@ Currently supported providers:
65
65
  - Generation time measurement
66
66
  - Local-only usage analytics (per-provider commits, tokens, latency) with opt-in SQLite storage
67
67
  - Shell completion for bash, zsh, and fish
68
+ - Local secret scan that blocks the diff before it reaches the provider when likely credentials are detected
69
+ - Configuration doctor (`--check`) that validates your setup offline, with an optional live provider probe (`--ping`)
70
+ - Mixed code and documentation diffs are classified by the functional change rather than mislabelled as docs
68
71
 
69
72
  ---
70
73
 
@@ -231,6 +234,8 @@ git cai -g
231
234
  - `stats` – opt in to local-only usage analytics (per-run row in a SQLite DB at `~/.local/share/git-cai/stats.db`); default `false`.
232
235
  No diff content, commit messages, or file paths are stored — only metadata (provider, model, kind, repo name, token counts, latency, settings)
233
236
  - `signoff` – append a `Signed-off-by:` trailer (built from git `user.name` / `user.email`) to every commit message; default `false`
237
+ - `secret_scan` – scan the outgoing diff for likely secrets and ask before sending; default `true`. Bypass once with `-B` / `--allow-secrets`,
238
+ or disable entirely by setting it to `false`. Skipped for tokenless providers (Ollama), where nothing leaves the machine
234
239
 
235
240
  ---
236
241
 
@@ -238,13 +243,14 @@ No diff content, commit messages, or file paths are stored — only metadata (pr
238
243
 
239
244
  In addition to `git cai`, the following options are available:
240
245
 
241
- - `-A`, `--amend` – regenerate and amend the last commit message
246
+ - `-A`, `--amend` – refine the last commit message against its diff and amend it (preserves trailers and original intent)
242
247
  - `-a`, `--all` – stage all tracked modified and deleted files
248
+ - `-B`, `--allow-secrets` – bypass the local secret scan and send the diff even if a likely secret is detected
243
249
  - `-b`, `--branch` – include current branch name as context for the LLM
244
250
  - `-C`, `--conventional` – use Conventional Commits format (`type(scope): description`)
245
251
  - `-c`, `--crazy` – Trust the LLM and commit without checking
246
252
  - `-d`, `--debug` – enable debug logging
247
- - `-e`, `--temperature` `TEMPERATURE` – override the active provider's sampling temperature for this invocation (provider-scoped, like `-m`)
253
+ - `-E`, `--temperature` `TEMPERATURE` – override the active provider's sampling temperature for this invocation (provider scoped, like `-m`)
248
254
  - `-F`, `--full-files` – attach the full contents of affected files alongside the diff (uses `full_files_prompt.md`)
249
255
  - `-f`, `--files` `PATH` – limit the diff (and full-file content, if enabled) to PATH; repeat for multiple files
250
256
  - `-g`, `--generate-config` – generate the default `cai_config.yml` in the current directory
@@ -252,8 +258,10 @@ In addition to `git cai`, the following options are available:
252
258
  - `-h`, `--help` – show help and available commands
253
259
  - `-I`, `--init` – interactive setup wizard (writes home config and tokens.yml)
254
260
  - `-i`, `--install-completion` – install shell completion for bash, zsh, or fish
261
+ - `-k`, `--check` – run configuration diagnostics offline (config source, provider, token, prompts, editor, style)
255
262
  - `-l`, `--list` – list available information. Valid types: `config`, `editor`, `language`, `model`, `path`, `provider`, `style`
256
263
  - `-m`, `--model` – override the model for this invocation (requires `-P`)
264
+ - `-n`, `--ping` – with `--check`, also send a tiny request to the active provider to confirm reachability
257
265
  - `-o`, `--signoff` / `--no-signoff` – append a `Signed-off-by:` trailer (uses git `user.name` / `user.email`); applies to commit, amend, and squash modes
258
266
  - `-P`, `--provider` – override the LLM provider for this invocation
259
267
  - `-p`, `--generate-prompts` – generate default `commit_prompt.md` and `squash_prompt.md` in the current directory (for customization)
@@ -267,9 +275,9 @@ In addition to `git cai`, the following options are available:
267
275
  - `--base` `BRANCH` – explicit base branch for `--PR` (overrides auto-detection: `origin/HEAD` → `main` → `master`)
268
276
  - `-S`, `--set` – set a config value (`key=value`) in repo config (requires existing repo config)
269
277
  - `-s`, `--squash` `[N|HASH]` – squash commits on the current branch and summarize them. Without argument: squash all since branch checkout. With a number: squash the last N commits. With a commit hash: squash up to and including that commit
270
- - `--style` `STYLE` – override the commit message style for this invocation (e.g. `funny`, `neutral`, `none`); validated against the supported styles
271
- - `--language` `CODE` – override the commit message language for this invocation (e.g. `de`, `fr`, `none`); validated against supported codes
272
- - `--emoji` / `--no-emoji` – override emoji usage for this invocation (use `--no-emoji` to disable when config enables it)
278
+ - `-y`, `--style` `STYLE` – override the commit message style for this invocation (e.g. `funny`, `neutral`, `none`); validated against the supported styles
279
+ - `-L`, `--language` `CODE` – override the commit message language for this invocation (e.g. `de`, `fr`, `none`); validated against supported codes
280
+ - `-e`, `--emoji` / `--no-emoji` – override emoji usage for this invocation (use `--no-emoji` to disable when config enables it)
273
281
  - `-T`, `--timeout` `SECONDS` – HTTP timeout for this invocation (overrides config)
274
282
  - `-t`, `--time` – measure and log commit message generation time
275
283
  - `-u`, `--update` – check for updates
@@ -280,14 +288,17 @@ In addition to `git cai`, the following options are available:
280
288
 
281
289
  ### Amend
282
290
 
283
- To regenerate the last commit message and amend it:
291
+ To refine the last commit message and amend it:
284
292
 
285
293
  ```sh
286
294
  git cai -A
287
295
  ```
288
296
 
289
- This reads the diff from the most recent commit, sends it to the LLM, and opens the editor for review.
290
- Use with `-c` to amend immediately without the editor: `git cai -A -c`.
297
+ This reads the diff from the most recent commit and sends both the diff and the
298
+ existing message to the LLM, which improves the wording while keeping the
299
+ original intent and any trailers (issue IDs, `Co-authored-by`). The result opens
300
+ in the editor for review. Use with `-c` to amend immediately without the editor:
301
+ `git cai -A -c`.
291
302
 
292
303
  ### Conventional Commits
293
304
 
@@ -436,6 +447,45 @@ git cai -H language=de
436
447
  git cai -H emoji=false
437
448
  ```
438
449
 
450
+ ### Configuration check (doctor)
451
+
452
+ `-k` / `--check` runs a set of offline diagnostics so you can confirm cai is
453
+ set up correctly without contacting any provider. It reports the authoritative
454
+ config source, validates the config keys, checks the active provider block, the
455
+ token and `tokens.yml` permissions, prompt resolution, the editor on your PATH,
456
+ and the configured style.
457
+
458
+ ```sh
459
+ git cai -k # offline diagnostics only
460
+ git cai --check # long form
461
+ git cai -k -n # also probe the provider for reachability
462
+ git cai --check --ping # long form
463
+ ```
464
+
465
+ Add `-n` / `--ping` to send one tiny synthetic diff to the active provider and
466
+ confirm it is reachable (this consumes a minimal request). The command exits
467
+ non-zero if any check fails, so it works in scripts and CI.
468
+
469
+ ### Secret scanning
470
+
471
+ Before any diff leaves your machine, cai scans it for likely credentials
472
+ (private keys, AWS, OpenAI, GitHub, Slack, and Google keys). When something is
473
+ found, the location is shown as `path:line` with a masked value and you are
474
+ asked to confirm before anything is sent.
475
+
476
+ ```sh
477
+ git cai # scan runs automatically, prompts on a hit
478
+ git cai -B # bypass the scan for this run
479
+ git cai --allow-secrets # long form
480
+ git cai -S secret_scan=false # disable the scan persistently
481
+ ```
482
+
483
+ Obvious placeholders (`example`, `dummy`, repeated filler, and similar) are
484
+ ignored to keep the noise down, and the scan is skipped entirely for tokenless
485
+ providers such as Ollama, where nothing leaves the machine. In non-interactive
486
+ runs (`-c` / `--crazy`, or no TTY) a detection aborts the send instead of
487
+ prompting; re-run with `-B` to override.
488
+
439
489
  ---
440
490
 
441
491
  ## License
@@ -12,6 +12,7 @@ SYNOPSIS
12
12
  [verse]
13
13
  `git cai` [-A | --amend] [-a | --all] [-C | --conventional]
14
14
  [-b | --branch] [-c | --crazy] [-d | --debug]
15
+ [-B | --allow-secrets] [-k | --check] [-n | --ping]
15
16
  [-e TEMPERATURE | --temperature TEMPERATURE]
16
17
  [-F | --full-files | --no-full-files] [-f PATH | --files PATH]
17
18
  [-g | --generate-config]
@@ -93,6 +94,10 @@ so you can review or adjust the message before amending. This is useful when
93
94
  the original commit message was poorly worded or when you want the LLM to
94
95
  produce a better summary.
95
96
  +
97
+ git-cai also sends the existing commit message to the LLM, so it refines and
98
+ improves the current wording instead of starting over, preserving issue
99
+ references and trailers such as `Co-authored-by`.
100
+ +
96
101
  Combine with `-c` to skip the editor and amend immediately.
97
102
  +
98
103
  Cannot be combined with `--squash` or `--list`.
@@ -113,6 +118,18 @@ Cannot be combined with `--list`, `--update`, or `--squash`.
113
118
  git cai -a
114
119
  ----
115
120
 
121
+ -B, --allow-secrets::
122
+ Bypass the local secret scan for this invocation and send the diff to the LLM
123
+ even if a likely secret (API key, token, private key) is detected. By default
124
+ git-cai scans the exact content it is about to send and blocks on a match; use
125
+ this flag in non-interactive contexts where you have confirmed the match is a
126
+ false positive. See also the `secret_scan` config key.
127
+ +
128
+ ----
129
+ git cai -B
130
+ git cai -A --allow-secrets
131
+ ----
132
+
116
133
  -b, --branch / --no-branch::
117
134
  Include the current Git branch name as context when generating the commit
118
135
  message. The LLM uses the branch name to better understand the intent and
@@ -306,6 +323,31 @@ file for the completions to take effect.
306
323
  git cai -i
307
324
  ----
308
325
 
326
+ -k, --check::
327
+ Run configuration diagnostics and exit. The check is offline by default: it
328
+ reports which config is authoritative (repository, home, or built-in), validates
329
+ the config keys, confirms the default provider has a model/temperature and a
330
+ usable token, that the commit/squash/full-files/PR prompts resolve, and that the
331
+ configured editor is on `PATH`. Exits non-zero if any check fails. Add `--ping`
332
+ to also probe the active provider with a tiny live request.
333
+ +
334
+ Cannot be combined with other mode flags (`--amend`, `--squash`, `--PR`,
335
+ `--list`, `--stats`, `--init`, `--update`).
336
+ +
337
+ ----
338
+ git cai --check
339
+ git cai --check --ping
340
+ ----
341
+
342
+ -n, --ping::
343
+ Only meaningful together with `--check`. After the offline checks, send one
344
+ small request to the active provider and report whether it is reachable and how
345
+ long it took. Useful to confirm an API key and network path end to end.
346
+ +
347
+ ----
348
+ git cai --check --ping
349
+ ----
350
+
309
351
  -l, --list [config|editor|language|model|path|provider|style]::
310
352
  List information about a specific category. Provide one of the supported
311
353
  list types as the next argument. Without an argument, a help text is shown
@@ -865,6 +907,14 @@ Available configuration keys:
865
907
  - `emoji` -- enable or disable emojis in commit messages (`true`/`false`)
866
908
  - `branch_context` -- include current branch name as LLM context (`true`/`false`)
867
909
  - `conventional` -- use Conventional Commits format (`true`/`false`)
910
+ - `secret_scan` -- scan the diff (and any full-file contents) for likely
911
+ secrets before sending to the LLM (`true`/`false`, default `true`). On a
912
+ match the send is blocked and you are asked to confirm (or pass
913
+ `--allow-secrets`); each finding reports the file and line. Only distinctive
914
+ credential formats are flagged (private keys, AWS/GitHub/Slack/Google/OpenAI
915
+ keys); obvious placeholders (values containing `example`, `sample`, `dummy`,
916
+ and repeated-character filler) are ignored. Local providers (Ollama) skip the
917
+ scan, since nothing leaves the machine.
868
918
  - `load_tokens_from` -- path to the tokens file
869
919
  - `prompt_file` -- path to the commit prompt Markdown file
870
920
  - `squash_prompt_file` -- path to the squash prompt Markdown file
@@ -2,12 +2,12 @@
2
2
  .\" Title: git-cai
3
3
  .\" Author: Thorsten Foltz
4
4
  .\" Generator: Asciidoctor 2.0.26
5
- .\" Date: 2026-06-04
5
+ .\" Date: 2026-06-19
6
6
  .\" Manual: \ \&
7
7
  .\" Source: \ \&
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "GIT\-CAI" "1" "2026-06-04" "\ \&" "\ \&"
10
+ .TH "GIT\-CAI" "1" "2026-06-19" "\ \&" "\ \&"
11
11
  .ie \n(.g .ds Aq \(aq
12
12
  .el .ds Aq '
13
13
  .ss \n[.ss] 0
@@ -34,6 +34,7 @@ git-cai \- AI\-powered commit message generator
34
34
  .nf
35
35
  \f(CRgit cai\fP [\-A | \-\-amend] [\-a | \-\-all] [\-C | \-\-conventional]
36
36
  [\-b | \-\-branch] [\-c | \-\-crazy] [\-d | \-\-debug]
37
+ [\-B | \-\-allow\-secrets] [\-k | \-\-check] [\-n | \-\-ping]
37
38
  [\-e TEMPERATURE | \-\-temperature TEMPERATURE]
38
39
  [\-F | \-\-full\-files | \-\-no\-full\-files] [\-f PATH | \-\-files PATH]
39
40
  [\-g | \-\-generate\-config]
@@ -219,6 +220,10 @@ so you can review or adjust the message before amending. This is useful when
219
220
  the original commit message was poorly worded or when you want the LLM to
220
221
  produce a better summary.
221
222
  .sp
223
+ git\-cai also sends the existing commit message to the LLM, so it refines and
224
+ improves the current wording instead of starting over, preserving issue
225
+ references and trailers such as \f(CRCo\-authored\-by\fP.
226
+ .sp
222
227
  Combine with \f(CR\-c\fP to skip the editor and amend immediately.
223
228
  .sp
224
229
  Cannot be combined with \f(CR\-\-squash\fP or \f(CR\-\-list\fP.
@@ -250,6 +255,24 @@ git cai \-a
250
255
  .if n .RE
251
256
  .RE
252
257
  .sp
258
+ \-B, \-\-allow\-secrets
259
+ .RS 4
260
+ Bypass the local secret scan for this invocation and send the diff to the LLM
261
+ even if a likely secret (API key, token, private key) is detected. By default
262
+ git\-cai scans the exact content it is about to send and blocks on a match; use
263
+ this flag in non\-interactive contexts where you have confirmed the match is a
264
+ false positive. See also the \f(CRsecret_scan\fP config key.
265
+ .sp
266
+ .if n .RS 4
267
+ .nf
268
+ .fam C
269
+ git cai \-B
270
+ git cai \-A \-\-allow\-secrets
271
+ .fam
272
+ .fi
273
+ .if n .RE
274
+ .RE
275
+ .sp
253
276
  \-b, \-\-branch / \-\-no\-branch
254
277
  .RS 4
255
278
  Include the current Git branch name as context when generating the commit
@@ -527,6 +550,43 @@ git cai \-i
527
550
  .if n .RE
528
551
  .RE
529
552
  .sp
553
+ \-k, \-\-check
554
+ .RS 4
555
+ Run configuration diagnostics and exit. The check is offline by default: it
556
+ reports which config is authoritative (repository, home, or built\-in), validates
557
+ the config keys, confirms the default provider has a model/temperature and a
558
+ usable token, that the commit/squash/full\-files/PR prompts resolve, and that the
559
+ configured editor is on \f(CRPATH\fP. Exits non\-zero if any check fails. Add \f(CR\-\-ping\fP
560
+ to also probe the active provider with a tiny live request.
561
+ .sp
562
+ Cannot be combined with other mode flags (\f(CR\-\-amend\fP, \f(CR\-\-squash\fP, \f(CR\-\-PR\fP,
563
+ \f(CR\-\-list\fP, \f(CR\-\-stats\fP, \f(CR\-\-init\fP, \f(CR\-\-update\fP).
564
+ .sp
565
+ .if n .RS 4
566
+ .nf
567
+ .fam C
568
+ git cai \-\-check
569
+ git cai \-\-check \-\-ping
570
+ .fam
571
+ .fi
572
+ .if n .RE
573
+ .RE
574
+ .sp
575
+ \-n, \-\-ping
576
+ .RS 4
577
+ Only meaningful together with \f(CR\-\-check\fP. After the offline checks, send one
578
+ small request to the active provider and report whether it is reachable and how
579
+ long it took. Useful to confirm an API key and network path end to end.
580
+ .sp
581
+ .if n .RS 4
582
+ .nf
583
+ .fam C
584
+ git cai \-\-check \-\-ping
585
+ .fam
586
+ .fi
587
+ .if n .RE
588
+ .RE
589
+ .sp
530
590
  \-l, \-\-list [config|editor|language|model|path|provider|style]
531
591
  .RS 4
532
592
  List information about a specific category. Provide one of the supported
@@ -1389,6 +1449,24 @@ Available configuration keys:
1389
1449
  . sp -1
1390
1450
  . IP \(bu 2.3
1391
1451
  .\}
1452
+ \f(CRsecret_scan\fP \(em scan the diff (and any full\-file contents) for likely
1453
+ secrets before sending to the LLM (\f(CRtrue\fP/\f(CRfalse\fP, default \f(CRtrue\fP). On a
1454
+ match the send is blocked and you are asked to confirm (or pass
1455
+ \f(CR\-\-allow\-secrets\fP); each finding reports the file and line. Only distinctive
1456
+ credential formats are flagged (private keys, AWS/GitHub/Slack/Google/OpenAI
1457
+ keys); obvious placeholders (values containing \f(CRexample\fP, \f(CRsample\fP, \f(CRdummy\fP,
1458
+ and repeated\-character filler) are ignored. Local providers (Ollama) skip the
1459
+ scan, since nothing leaves the machine.
1460
+ .RE
1461
+ .sp
1462
+ .RS 4
1463
+ .ie n \{\
1464
+ \h'-04'\(bu\h'+03'\c
1465
+ .\}
1466
+ .el \{\
1467
+ . sp -1
1468
+ . IP \(bu 2.3
1469
+ .\}
1392
1470
  \f(CRload_tokens_from\fP \(em path to the tokens file
1393
1471
  .RE
1394
1472
  .sp
@@ -1,3 +1,5 @@
1
+ """git-cai-cli: AI-powered git commit message generator."""
2
+
1
3
  from ._version import __version__
2
4
 
3
5
  __all__ = ["__version__"]
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.14.1'
22
- __version_tuple__ = version_tuple = (0, 14, 1)
21
+ __version__ = version = '0.15.1'
22
+ __version_tuple__ = version_tuple = (0, 15, 1)
23
23
 
24
- __commit_id__ = commit_id = 'gbd1b6f7b7'
24
+ __commit_id__ = commit_id = 'g00cc1e8ad'
@@ -181,25 +181,46 @@ def callback( # pylint: disable=too-many-arguments,too-many-positional-argument
181
181
  ),
182
182
  temperature: float = typer.Option(
183
183
  None,
184
- "-e",
184
+ "-E",
185
185
  "--temperature",
186
186
  help="Override the active provider's sampling temperature for this invocation.",
187
187
  ),
188
188
  style: str = typer.Option(
189
189
  None,
190
+ "-y",
190
191
  "--style",
191
192
  help="Override the commit message style for this invocation (e.g. funny, neutral, none).",
192
193
  ),
193
194
  language: str = typer.Option(
194
195
  None,
196
+ "-L",
195
197
  "--language",
196
198
  help="Override the commit message language code for this invocation (e.g. de, fr, none).",
197
199
  ),
198
200
  emoji: bool | None = typer.Option(
199
201
  None,
202
+ "-e",
200
203
  "--emoji/--no-emoji",
201
204
  help="Override emoji usage for this invocation. Use --no-emoji to disable when config enables it.",
202
205
  ),
206
+ check: bool = typer.Option(
207
+ False,
208
+ "-k",
209
+ "--check",
210
+ help="Run configuration diagnostics (offline). Add --ping for a live provider probe.",
211
+ ),
212
+ ping: bool = typer.Option(
213
+ False,
214
+ "-n",
215
+ "--ping",
216
+ help="With --check, also send a tiny request to the active provider to confirm reachability.",
217
+ ),
218
+ allow_secrets: bool = typer.Option(
219
+ False,
220
+ "-B",
221
+ "--allow-secrets",
222
+ help="Bypass the local secret scan and send the diff even if a likely secret is detected.",
223
+ ),
203
224
  ):
204
225
  """
205
226
  CLI entry point for git-cai-cli.
@@ -221,6 +242,7 @@ def callback( # pylint: disable=too-many-arguments,too-many-positional-argument
221
242
 
222
243
  mode = resolve_mode(
223
244
  amend=amend,
245
+ check=check,
224
246
  init=init,
225
247
  list_flag=list_flag,
226
248
  pr=pr,
@@ -229,6 +251,10 @@ def callback( # pylint: disable=too-many-arguments,too-many-positional-argument
229
251
  update=update,
230
252
  )
231
253
 
254
+ if ping and not check:
255
+ typer.echo("Error: --ping is only valid together with --check.", err=True)
256
+ raise typer.Exit(code=1)
257
+
232
258
  sql_override: bool | None = None
233
259
  if sql is not None:
234
260
  normalized = sql.strip().lower()
@@ -336,6 +362,8 @@ def callback( # pylint: disable=too-many-arguments,too-many-positional-argument
336
362
  style_override=style,
337
363
  language_override=language,
338
364
  emoji_override=emoji,
365
+ live_check=ping,
366
+ allow_secrets=allow_secrets,
339
367
  )
340
368
 
341
369
 
@@ -17,10 +17,13 @@ Usage:
17
17
  Flags:
18
18
  -A, --amend Regenerate and amend the last commit message
19
19
  -a, --all Stage all modified and deleted files that are already tracked by Git
20
+ -B, --allow-secrets Bypass the local secret scan and send even if a secret is detected
20
21
  -b, --branch Include current branch name as context for the LLM
21
22
  -C, --conventional Use Conventional Commits format (type(scope): description)
22
23
  -c, --crazy Commit immediately without opening editor (trust LLM output)
23
24
  -d, --debug Enable debug logging
25
+ -E, --temperature FLOAT Override the active provider's sampling temperature for this invocation
26
+ -e, --emoji Toggle emoji prefixes (use --no-emoji to disable)
24
27
  -F, --full-files Send the full contents of affected files alongside the diff
25
28
  -f, --files PATH Limit the diff (and full files) to PATH; repeat the flag for multiple files
26
29
  -g, --generate-config Generate default cai_config.yml in the current directory
@@ -28,9 +31,12 @@ Flags:
28
31
  -h, --help Show this help message or opens manual
29
32
  -I, --init Interactive setup wizard (writes home config and tokens.yml)
30
33
  -i, --install-completion Install shell completion for git-cai
34
+ -k, --check Run configuration diagnostics (offline; add --ping for a live probe)
35
+ -L, --language CODE Override the commit message language (e.g. de, fr, none)
31
36
  -l, --list [TYPE] List information. TYPE: config, editor, language,
32
37
  model, path, provider, style
33
38
  -m, --model NAME Override model for this invocation (requires --provider)
39
+ -n, --ping With --check, probe the active provider for reachability
34
40
  -o, --signoff Append a `Signed-off-by:` trailer (git user.name / user.email)
35
41
  -P, --provider NAME Override LLM provider for this invocation
36
42
  -p, --generate-prompts Generate default commit/squash/full_files/pr prompt files
@@ -48,6 +54,7 @@ Flags:
48
54
  -u, --update Check for updates
49
55
  -v, --version Show installed version
50
56
  -x, --context TEXT Provide extra context for the LLM (e.g. ticket number, reason)
57
+ -y, --style NAME Override the commit message style (e.g. funny, neutral, none)
51
58
  -z, --stats Show local-only usage analytics (commits, tokens, latency)
52
59
  --since YYYY-MM-DD Filter --stats to events on or after this date
53
60
  --json Render --stats output as JSON instead of text