git-cai-cli 0.16.2__tar.gz → 0.17.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 (113) hide show
  1. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/lychee.toml +4 -1
  2. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/PKG-INFO +36 -7
  3. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/README.md +35 -6
  4. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/docs/git-cai.txt +83 -12
  5. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/docs/man/git-cai.1 +183 -14
  6. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/_version.py +3 -3
  7. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/cli/cli.py +10 -1
  8. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/cli/modes.py +3 -2
  9. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/completion.py +9 -3
  10. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/config.py +46 -6
  11. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/doctor.py +5 -4
  12. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/generation.py +3 -3
  13. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/gitutils.py +12 -4
  14. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/init.py +4 -4
  15. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/llm.py +42 -15
  16. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/options.py +25 -8
  17. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/pr.py +3 -3
  18. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/squash.py +7 -8
  19. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/validate.py +27 -1
  20. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/main.py +6 -4
  21. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/PKG-INFO +36 -7
  22. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/SOURCES.txt +1 -0
  23. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/scm_file_list.json +1 -0
  24. git_cai_cli-0.17.1/src/git_cai_cli.egg-info/scm_version.json +8 -0
  25. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_gitutils_integration.py +22 -0
  26. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_modes_integration.py +4 -16
  27. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_completion.py +9 -24
  28. git_cai_cli-0.17.1/tests/unit/test_custom_provider.py +208 -0
  29. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_gitutils.py +12 -12
  30. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_options.py +1 -1
  31. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_squash.py +4 -5
  32. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/uv.lock +88 -88
  33. git_cai_cli-0.16.2/src/git_cai_cli.egg-info/scm_version.json +0 -8
  34. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.caiignore +0 -0
  35. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.gitattributes +0 -0
  36. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/cd/.SRCINFO +0 -0
  37. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/cd/PKGBUILD +0 -0
  38. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/ci/_version.py +0 -0
  39. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/ci/cai_config.ci.yml +0 -0
  40. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/ci/tokens.ci.yml +0 -0
  41. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/workflows/python-tests.yml +0 -0
  42. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/workflows/release.yml +0 -0
  43. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.github/workflows/release_aur.yml +0 -0
  44. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.gitignore +0 -0
  45. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.bandit.yml +0 -0
  46. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.checkov.yml +0 -0
  47. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.flake8 +0 -0
  48. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.ls-lint.yml +0 -0
  49. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.markdownlint.json +0 -0
  50. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.proselintrc.json +0 -0
  51. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.pylintrc +0 -0
  52. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/.yamllint.yml +0 -0
  53. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/check_git_branch_name.sh +0 -0
  54. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.linters/pyrightconfig.json +0 -0
  55. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.markdownlintignore +0 -0
  56. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.mega-linter.yml +0 -0
  57. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.semgrepignore +0 -0
  58. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/.trivyignore +0 -0
  59. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/CLAUDE.md +0 -0
  60. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/LICENSE +0 -0
  61. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/Makefile +0 -0
  62. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/cai_config.yml +0 -0
  63. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/pyproject.toml +0 -0
  64. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/setup.cfg +0 -0
  65. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/__init__.py +0 -0
  66. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/cli/__init__.py +0 -0
  67. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/cli/helptext.py +0 -0
  68. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/__init__.py +0 -0
  69. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/changelog.py +0 -0
  70. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/explain.py +0 -0
  71. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/languages.py +0 -0
  72. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/prompts_fallback.py +0 -0
  73. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/release.py +0 -0
  74. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/secrets.py +0 -0
  75. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/spinner.py +0 -0
  76. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/split.py +0 -0
  77. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli/core/stats.py +0 -0
  78. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/dependency_links.txt +0 -0
  79. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/entry_points.txt +0 -0
  80. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/requires.txt +0 -0
  81. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/src/git_cai_cli.egg-info/top_level.txt +0 -0
  82. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/conftest.py +0 -0
  83. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_cli_integration.py +0 -0
  84. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_config_integration.py +0 -0
  85. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_options_integration.py +0 -0
  86. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_pr_integration.py +0 -0
  87. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/integration/test_squash_integration.py +0 -0
  88. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_amend.py +0 -0
  89. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_branch_context.py +0 -0
  90. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_changelog.py +0 -0
  91. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_classification.py +0 -0
  92. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_cli.py +0 -0
  93. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_config.py +0 -0
  94. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_conventional.py +0 -0
  95. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_doctor.py +0 -0
  96. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_explain.py +0 -0
  97. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_generation.py +0 -0
  98. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_helptext.py +0 -0
  99. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_init.py +0 -0
  100. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_llm.py +0 -0
  101. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_main.py +0 -0
  102. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_modes.py +0 -0
  103. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_pr.py +0 -0
  104. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_print.py +0 -0
  105. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_prompt_loading.py +0 -0
  106. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_release.py +0 -0
  107. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_secrets.py +0 -0
  108. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_set_config.py +0 -0
  109. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_signoff.py +0 -0
  110. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_spinner.py +0 -0
  111. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_split.py +0 -0
  112. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_stats.py +0 -0
  113. {git_cai_cli-0.16.2 → git_cai_cli-0.17.1}/tests/unit/test_validate.py +0 -0
@@ -8,7 +8,10 @@ accept = ["200", "429"]
8
8
 
9
9
  exclude = [
10
10
  "https://megalinter.io/configuration/",
11
- "file:///tmp/lint/dwh/models/logo.png"
11
+ "file:///tmp/lint/dwh/models/logo.png",
12
+ # Example endpoints in the custom provider docs, not browsable pages.
13
+ "^http://localhost",
14
+ "^https://openrouter\\.ai/api/v1$",
12
15
  ]
13
16
 
14
17
  exclude_path = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-cai-cli
3
- Version: 0.16.2
3
+ Version: 0.17.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
@@ -49,6 +49,7 @@ Currently supported providers:
49
49
  - Mistral
50
50
  - DeepSeek
51
51
  - Ollama (local)
52
+ - Any OpenAI compatible API (OpenRouter, Together, Cerebras, LM Studio, vLLM, llama.cpp, LiteLLM, ...) via `base_url`
52
53
 
53
54
  ---
54
55
 
@@ -58,6 +59,7 @@ Currently supported providers:
58
59
  - [pipx](https://pypi.org/project/pipx/)
59
60
  - Either:
60
61
  - Ollama installed and running locally, or
62
+ - A local OpenAI compatible server such as LM Studio or vLLM, or
61
63
  - An API key for at least one of the following providers:
62
64
  - OpenAI
63
65
  - Gemini (free tier available)
@@ -74,7 +76,7 @@ Currently supported providers:
74
76
  - Automatically detects added, modified, and deleted files
75
77
  - Generates meaningful, context-aware commit messages using an LLM
76
78
  - Seamless integration with Git
77
- - Supports multiple LLM providers and models
79
+ - Supports multiple LLM providers and models, plus any OpenAI compatible endpoint
78
80
  - Global configuration with per-repository overrides
79
81
  - Interactive `--init` wizard for first-time setup (provider, token, language, style)
80
82
  - Repository-specific language, style, and model selection
@@ -93,7 +95,7 @@ Currently supported providers:
93
95
  - Optional large-diff guard (`max_diff_bytes`) that truncates oversized diffs before sending
94
96
  - Generation time measurement
95
97
  - Local-only usage analytics (per-provider commits, tokens, latency) with opt-in SQLite storage
96
- - Shell completion for bash, zsh, and fish
98
+ - Shell completion for bash, zsh, and fish (including custom providers from your config)
97
99
  - Local secret scan that blocks the diff before it reaches the provider when likely credentials are detected
98
100
  - Configuration doctor (`--check`) that validates your setup offline, with an optional live provider probe (`--ping`)
99
101
  - Mixed code and documentation diffs are classified by the functional change rather than mislabelled as docs
@@ -188,6 +190,27 @@ Set your preferred LLM in `cai_config.yml` (Groq by default).
188
190
 
189
191
  If you want to use Ollama, install it, set `default: ollama` and configure the `ollama:` block (model/temperature). Ollama is automatically started when used.
190
192
 
193
+ ### Custom OpenAI compatible providers
194
+
195
+ Any service speaking the OpenAI `/chat/completions` API can be added as a provider.
196
+ Pick a name, add a block with `base_url` and `model`, and set `default:` to that name:
197
+
198
+ ```yaml
199
+ default: openrouter
200
+ openrouter:
201
+ base_url: https://openrouter.ai/api/v1
202
+ model: meta-llama/llama-3.3-70b-instruct:free
203
+ lmstudio:
204
+ base_url: http://localhost:1234/v1
205
+ model: qwen2.5-coder
206
+ requires_token: false
207
+ ```
208
+
209
+ The API key goes into `tokens.yml` under the same name (`openrouter: sk-or-...`).
210
+ With `requires_token: false` no key is needed. `/chat/completions` is appended to
211
+ `base_url` unless it is already there. The name works with `-P` / `--provider`
212
+ and shows up in `git cai -l provider` and shell completion.
213
+
191
214
  ### Custom prompts (Markdown)
192
215
 
193
216
  The generated commit message is guided by prompt files.
@@ -247,6 +270,10 @@ git cai -g
247
270
  - `style` – tone or style of the commit message
248
271
  - `emoji` – enable or disable emojis
249
272
  - `load_tokens_from` – path to the file where API tokens are stored
273
+ - `base_url` – per provider block: endpoint of a custom OpenAI compatible provider, or a proxy/gateway for a built in one.
274
+ OpenAI style providers include the version (`https://gateway.example/v1`); `anthropic` and `gemini` take the host without it (`https://gateway.example`)
275
+ - `requires_token` – per provider block: set to `false` for custom providers that need no API key; default `true`
276
+ - `max_output_tokens` – per provider block: cap on the reply length for Anthropic and OpenAI compatible providers; only sent when set
250
277
  - `prompt_file` - path to the file where the prompt for the commit is stored
251
278
  - `squash_prompt_file` - path to the file where the prompt for the squash is stored
252
279
  - `full_files_prompt_file` - path to the prompt used when `-F` / `--full-files` attaches full file contents
@@ -264,7 +291,8 @@ git cai -g
264
291
  No diff content, commit messages, or file paths are stored — only metadata (provider, model, kind, repo name, token counts, latency, settings)
265
292
  - `signoff` – append a `Signed-off-by:` trailer (built from git `user.name` / `user.email`) to every commit message; default `false`
266
293
  - `secret_scan` – scan the outgoing diff for likely secrets and ask before sending; default `true`. Bypass once with `-B` / `--allow-secrets`,
267
- or disable entirely by setting it to `false`. Skipped for tokenless providers (Ollama), where nothing leaves the machine
294
+ or disable entirely by setting it to `false`. Skipped for tokenless providers (Ollama), where nothing leaves the machine.
295
+ Custom providers are always scanned, even with `requires_token: false`, since the diff may leave the machine
268
296
 
269
297
  ---
270
298
 
@@ -286,13 +314,13 @@ In addition to `git cai`, the following options are available:
286
314
  - `-H`, `--set-home` – set a config value in home config (`key=value`), always targets `~/.config/cai/`
287
315
  - `-h`, `--help` – show help and available commands
288
316
  - `-I`, `--init` – interactive setup wizard (writes home config and tokens.yml)
289
- - `-i`, `--install-completion` – install shell completion for bash, zsh, or fish
317
+ - `-i`, `--install-completion` – install shell completion for bash, zsh, or fish. Rerun after upgrading to get custom provider completion
290
318
  - `-k`, `--check` – run configuration diagnostics offline (config source, provider, token, prompts, editor, style)
291
319
  - `-l`, `--list` – list available information. Valid types: `config`, `editor`, `language`, `model`, `path`, `provider`, `style`
292
320
  - `-m`, `--model` – override the model for this invocation (requires `-P`)
293
321
  - `-n`, `--ping` – with `--check`, also send a tiny request to the active provider to confirm reachability
294
322
  - `-o`, `--signoff` / `--no-signoff` – append a `Signed-off-by:` trailer (uses git `user.name` / `user.email`); applies to commit, amend, and squash modes
295
- - `-P`, `--provider` – override the LLM provider for this invocation
323
+ - `-P`, `--provider` – override the LLM provider for this invocation (built in or custom; tab completion lists both)
296
324
  - `-p`, `--generate-prompts` – generate default `commit_prompt.md` and `squash_prompt.md` in the current directory (for customization)
297
325
  - `--print` – print the generated commit message to stdout and exit without committing (commit/amend modes only; mutually exclusive with `-c`)
298
326
  - `-q`, `--sql true|false` – override stats writing for this run (wins over the persisted `stats` config)
@@ -511,7 +539,8 @@ git cai -S secret_scan=false # disable the scan persistently
511
539
 
512
540
  Obvious placeholders (`example`, `dummy`, repeated filler, and similar) are
513
541
  ignored to keep the noise down, and the scan is skipped entirely for tokenless
514
- providers such as Ollama, where nothing leaves the machine. In non-interactive
542
+ providers such as Ollama, where nothing leaves the machine. Custom providers are
543
+ always scanned, even with `requires_token: false`. In non-interactive
515
544
  runs (`-c` / `--crazy`, or no TTY) a detection aborts the send instead of
516
545
  prompting; re-run with `-B` to override.
517
546
 
@@ -20,6 +20,7 @@ Currently supported providers:
20
20
  - Mistral
21
21
  - DeepSeek
22
22
  - Ollama (local)
23
+ - Any OpenAI compatible API (OpenRouter, Together, Cerebras, LM Studio, vLLM, llama.cpp, LiteLLM, ...) via `base_url`
23
24
 
24
25
  ---
25
26
 
@@ -29,6 +30,7 @@ Currently supported providers:
29
30
  - [pipx](https://pypi.org/project/pipx/)
30
31
  - Either:
31
32
  - Ollama installed and running locally, or
33
+ - A local OpenAI compatible server such as LM Studio or vLLM, or
32
34
  - An API key for at least one of the following providers:
33
35
  - OpenAI
34
36
  - Gemini (free tier available)
@@ -45,7 +47,7 @@ Currently supported providers:
45
47
  - Automatically detects added, modified, and deleted files
46
48
  - Generates meaningful, context-aware commit messages using an LLM
47
49
  - Seamless integration with Git
48
- - Supports multiple LLM providers and models
50
+ - Supports multiple LLM providers and models, plus any OpenAI compatible endpoint
49
51
  - Global configuration with per-repository overrides
50
52
  - Interactive `--init` wizard for first-time setup (provider, token, language, style)
51
53
  - Repository-specific language, style, and model selection
@@ -64,7 +66,7 @@ Currently supported providers:
64
66
  - Optional large-diff guard (`max_diff_bytes`) that truncates oversized diffs before sending
65
67
  - Generation time measurement
66
68
  - Local-only usage analytics (per-provider commits, tokens, latency) with opt-in SQLite storage
67
- - Shell completion for bash, zsh, and fish
69
+ - Shell completion for bash, zsh, and fish (including custom providers from your config)
68
70
  - Local secret scan that blocks the diff before it reaches the provider when likely credentials are detected
69
71
  - Configuration doctor (`--check`) that validates your setup offline, with an optional live provider probe (`--ping`)
70
72
  - Mixed code and documentation diffs are classified by the functional change rather than mislabelled as docs
@@ -159,6 +161,27 @@ Set your preferred LLM in `cai_config.yml` (Groq by default).
159
161
 
160
162
  If you want to use Ollama, install it, set `default: ollama` and configure the `ollama:` block (model/temperature). Ollama is automatically started when used.
161
163
 
164
+ ### Custom OpenAI compatible providers
165
+
166
+ Any service speaking the OpenAI `/chat/completions` API can be added as a provider.
167
+ Pick a name, add a block with `base_url` and `model`, and set `default:` to that name:
168
+
169
+ ```yaml
170
+ default: openrouter
171
+ openrouter:
172
+ base_url: https://openrouter.ai/api/v1
173
+ model: meta-llama/llama-3.3-70b-instruct:free
174
+ lmstudio:
175
+ base_url: http://localhost:1234/v1
176
+ model: qwen2.5-coder
177
+ requires_token: false
178
+ ```
179
+
180
+ The API key goes into `tokens.yml` under the same name (`openrouter: sk-or-...`).
181
+ With `requires_token: false` no key is needed. `/chat/completions` is appended to
182
+ `base_url` unless it is already there. The name works with `-P` / `--provider`
183
+ and shows up in `git cai -l provider` and shell completion.
184
+
162
185
  ### Custom prompts (Markdown)
163
186
 
164
187
  The generated commit message is guided by prompt files.
@@ -218,6 +241,10 @@ git cai -g
218
241
  - `style` – tone or style of the commit message
219
242
  - `emoji` – enable or disable emojis
220
243
  - `load_tokens_from` – path to the file where API tokens are stored
244
+ - `base_url` – per provider block: endpoint of a custom OpenAI compatible provider, or a proxy/gateway for a built in one.
245
+ OpenAI style providers include the version (`https://gateway.example/v1`); `anthropic` and `gemini` take the host without it (`https://gateway.example`)
246
+ - `requires_token` – per provider block: set to `false` for custom providers that need no API key; default `true`
247
+ - `max_output_tokens` – per provider block: cap on the reply length for Anthropic and OpenAI compatible providers; only sent when set
221
248
  - `prompt_file` - path to the file where the prompt for the commit is stored
222
249
  - `squash_prompt_file` - path to the file where the prompt for the squash is stored
223
250
  - `full_files_prompt_file` - path to the prompt used when `-F` / `--full-files` attaches full file contents
@@ -235,7 +262,8 @@ git cai -g
235
262
  No diff content, commit messages, or file paths are stored — only metadata (provider, model, kind, repo name, token counts, latency, settings)
236
263
  - `signoff` – append a `Signed-off-by:` trailer (built from git `user.name` / `user.email`) to every commit message; default `false`
237
264
  - `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
265
+ or disable entirely by setting it to `false`. Skipped for tokenless providers (Ollama), where nothing leaves the machine.
266
+ Custom providers are always scanned, even with `requires_token: false`, since the diff may leave the machine
239
267
 
240
268
  ---
241
269
 
@@ -257,13 +285,13 @@ In addition to `git cai`, the following options are available:
257
285
  - `-H`, `--set-home` – set a config value in home config (`key=value`), always targets `~/.config/cai/`
258
286
  - `-h`, `--help` – show help and available commands
259
287
  - `-I`, `--init` – interactive setup wizard (writes home config and tokens.yml)
260
- - `-i`, `--install-completion` – install shell completion for bash, zsh, or fish
288
+ - `-i`, `--install-completion` – install shell completion for bash, zsh, or fish. Rerun after upgrading to get custom provider completion
261
289
  - `-k`, `--check` – run configuration diagnostics offline (config source, provider, token, prompts, editor, style)
262
290
  - `-l`, `--list` – list available information. Valid types: `config`, `editor`, `language`, `model`, `path`, `provider`, `style`
263
291
  - `-m`, `--model` – override the model for this invocation (requires `-P`)
264
292
  - `-n`, `--ping` – with `--check`, also send a tiny request to the active provider to confirm reachability
265
293
  - `-o`, `--signoff` / `--no-signoff` – append a `Signed-off-by:` trailer (uses git `user.name` / `user.email`); applies to commit, amend, and squash modes
266
- - `-P`, `--provider` – override the LLM provider for this invocation
294
+ - `-P`, `--provider` – override the LLM provider for this invocation (built in or custom; tab completion lists both)
267
295
  - `-p`, `--generate-prompts` – generate default `commit_prompt.md` and `squash_prompt.md` in the current directory (for customization)
268
296
  - `--print` – print the generated commit message to stdout and exit without committing (commit/amend modes only; mutually exclusive with `-c`)
269
297
  - `-q`, `--sql true|false` – override stats writing for this run (wins over the persisted `stats` config)
@@ -482,7 +510,8 @@ git cai -S secret_scan=false # disable the scan persistently
482
510
 
483
511
  Obvious placeholders (`example`, `dummy`, repeated filler, and similar) are
484
512
  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
513
+ providers such as Ollama, where nothing leaves the machine. Custom providers are
514
+ always scanned, even with `requires_token: false`. In non-interactive
486
515
  runs (`-c` / `--crazy`, or no TTY) a detection aborts the send instead of
487
516
  prompting; re-run with `-B` to override.
488
517
 
@@ -73,7 +73,8 @@ First run / configuration (manual):
73
73
  - Add at least one API key to `~/.config/cai/tokens.yml` (created as a template if missing).
74
74
  The YAML keys are provider names (for example: `openai`, `anthropic`, `gemini`,
75
75
  `groq`, `xai`, `mistral`, `deepseek`).
76
- If you use `ollama` as provider, no token is required.
76
+ If you use `ollama` as provider, no token is required. Custom providers use
77
+ their own name as key (see below).
77
78
  - In `~/.config/cai/cai_config.yml`, set `default:` to the provider you want and
78
79
  adjust the provider block (model/temperature) as needed.
79
80
 
@@ -89,6 +90,46 @@ Custom prompts (optional):
89
90
  - Generate prompt files in the current directory with `git cai -p`.
90
91
  - Point `prompt_file` / `squash_prompt_file` in `cai_config.yml` to your custom files.
91
92
 
93
+ Custom OpenAI compatible providers (optional):
94
+
95
+ - Any service speaking the OpenAI `/chat/completions` API (OpenRouter, Together,
96
+ Cerebras, GitHub Models, LiteLLM, vLLM, LM Studio, llama.cpp, ...) can be added
97
+ as a provider. Pick a name, add a block with `base_url` and `model`, and set
98
+ `default:` to that name:
99
+
100
+ default: openrouter
101
+ openrouter:
102
+ base_url: https://openrouter.ai/api/v1
103
+ model: meta-llama/llama-3.3-70b-instruct:free
104
+ temperature: 0 # optional
105
+ timeout: 60 # optional
106
+ max_output_tokens: 2048 # optional, cap on the reply length
107
+ lmstudio:
108
+ base_url: http://localhost:1234/v1
109
+ model: qwen2.5-coder
110
+ requires_token: false # optional, default true
111
+
112
+ - `/chat/completions` is appended to `base_url` unless it is already there.
113
+ - The API key goes into `~/.config/cai/tokens.yml` under the same name
114
+ (`openrouter: sk-or-...`). With `requires_token: false` no key is needed and
115
+ no `Authorization` header is sent.
116
+ - The name works with `--provider` (`git cai -P lmstudio`), is listed by
117
+ `git cai -l provider`, and is offered by shell completion.
118
+ - `max_output_tokens` is only sent when set. Useful for local servers whose
119
+ default reply limit truncates commit messages. It is sent as `max_tokens`,
120
+ or as `max_completion_tokens` for the `openai` block.
121
+ - `base_url` also works in the built in blocks to route them through a proxy or
122
+ gateway. Use the same form as the vendor SDKs:
123
+ `openai`, `deepseek`, `groq`, `mistral`, `xai`: include the version,
124
+ e.g. `https://gateway.example/v1` (`/chat/completions` is appended);
125
+ `anthropic`: without version, e.g. `https://gateway.example`
126
+ (`/v1/messages` is appended);
127
+ `gemini`: without version, e.g. `https://gateway.example`
128
+ (`/v1beta/models/<model>:generateContent` is appended).
129
+ `ollama` keeps using the `OLLAMA_HOST` environment variable.
130
+ - The secret scan stays active for custom providers, including local ones.
131
+ Set `secret_scan: false` to disable it.
132
+
92
133
  OPTIONS
93
134
  -------
94
135
  -A, --amend::
@@ -283,7 +324,8 @@ Useful when a working tree contains unrelated staged changes and the commit
283
324
  should focus on a subset of them, or when you want the LLM to concentrate
284
325
  on a specific file.
285
326
  +
286
- Cannot be used with `--list`, `--update`, or `--squash`.
327
+ Only valid in the default commit mode; cannot be used with `--amend`,
328
+ `--list`, `--update`, or `--squash`.
287
329
  +
288
330
  ----
289
331
  git cai -f src/foo.py
@@ -349,7 +391,10 @@ git cai -I
349
391
 
350
392
  -i, --install-completion::
351
393
  Install shell completion for `git cai`. Supports bash, zsh, and fish.
352
- Completions cover all flags and provider names for `--provider`.
394
+ Completions cover all flags and provider names for `--provider`, including
395
+ custom providers from the active config (looked up on each TAB press, so new
396
+ providers show up without reinstalling). Users of an older script need to run
397
+ `git cai -i` once more to get this.
353
398
  +
354
399
  After installation, restart your terminal or source your shell configuration
355
400
  file for the completions to take effect.
@@ -361,8 +406,9 @@ git cai -i
361
406
  -k, --check::
362
407
  Run configuration diagnostics and exit. The check is offline by default: it
363
408
  reports which config is authoritative (repository, home, or built-in), validates
364
- the config keys, confirms the default provider has a model and a
365
- usable token, that the commit/squash/full-files/PR prompts resolve, and that the
409
+ the config keys, confirms the default provider has a model (and shows its
410
+ `base_url` if set) and a usable token (skipped for `ollama` and providers with
411
+ `requires_token: false`), that the commit/squash/full-files/PR prompts resolve, and that the
366
412
  configured editor is on `PATH`. Exits non-zero if any check fails. Add `--ping`
367
413
  to also probe the active provider with a tiny live request.
368
414
  +
@@ -476,11 +522,14 @@ git cai -s --signoff
476
522
  Override the LLM provider for this invocation. The model and temperature
477
523
  from the configuration for that provider are used unless `--model` is also
478
524
  specified. Available providers: `anthropic`, `deepseek`, `gemini`, `groq`,
479
- `mistral`, `ollama`, `openai`, `xai`.
525
+ `mistral`, `ollama`, `openai`, `xai`, plus any custom OpenAI compatible
526
+ provider defined in the active config (see SETUP). Shell completion offers
527
+ both.
480
528
  +
481
529
  ----
482
530
  git cai -P anthropic
483
531
  git cai -P groq -m llama-3.3-70b
532
+ git cai -P openrouter
484
533
  ----
485
534
 
486
535
  -p, --generate-prompts::
@@ -941,7 +990,9 @@ Configuration file paths:
941
990
  provider::
942
991
  List all supported LLM providers. Each provider is shown with its default
943
992
  model and whether an API token is required. Providers that do not require a
944
- token (currently only `ollama`) are marked accordingly.
993
+ token (`ollama`, and custom providers with `requires_token: false`) are
994
+ marked accordingly. Custom OpenAI compatible providers from the active config
995
+ follow in a separate section with their `base_url`.
945
996
  +
946
997
  ----
947
998
  git cai -l provider
@@ -960,6 +1011,11 @@ Supported providers:
960
1011
  ollama model: llama3.1 (no token required)
961
1012
  openai model: gpt-5.4-mini (token required)
962
1013
  xai model: grok-4.3 (token required)
1014
+
1015
+ Custom providers (OpenAI compatible, from config):
1016
+
1017
+ lmstudio model: qwen2.5-coder (no token required) http://localhost:1234/v1
1018
+ openrouter model: meta-llama/llama-3.3-70b-instruct:free (token required) https://openrouter.ai/api/v1
963
1019
  ----
964
1020
 
965
1021
  style::
@@ -1019,7 +1075,8 @@ Available configuration keys:
1019
1075
  credential formats are flagged (private keys, AWS/GitHub/Slack/Google/OpenAI
1020
1076
  keys); obvious placeholders (values containing `example`, `sample`, `dummy`,
1021
1077
  and repeated-character filler) are ignored. Local providers (Ollama) skip the
1022
- scan, since nothing leaves the machine. When you confirm a flagged send in an
1078
+ scan, since nothing leaves the machine. Custom providers are always scanned,
1079
+ even with `requires_token: false`, since the diff may leave the machine. When you confirm a flagged send in an
1023
1080
  interactive commit (a false alarm), git-cai offers, per flagged file, to
1024
1081
  remember the decision: add the file to `.caiignore` (drop it from git-cai
1025
1082
  entirely), add it to `secret_scan_exclude` (keep sending it but skip its
@@ -1073,10 +1130,18 @@ Available configuration keys:
1073
1130
  the middle step).
1074
1131
  - `<provider>.model` -- model name for a specific provider
1075
1132
  - `<provider>.temperature` -- temperature for a specific provider
1076
- - `anthropic.max_tokens` -- upper bound on Anthropic response tokens
1077
- (default `32768`)
1078
- - `ollama.timeout` -- HTTP timeout in seconds for Ollama generation calls
1079
- (default `300`; overrides the global `timeout` for this provider only)
1133
+ - `<provider>.base_url` -- endpoint of a custom OpenAI compatible provider,
1134
+ or a proxy/gateway for a built in one. OpenAI style providers include the
1135
+ version (`https://gateway.example/v1`); `anthropic` and `gemini` take the
1136
+ host without it (`https://gateway.example`). Must be an http(s) URL. Not
1137
+ used by `ollama` (use `OLLAMA_HOST`).
1138
+ - `<provider>.requires_token` -- set to `false` for a custom provider that
1139
+ needs no API key; no `Authorization` header is sent (default `true`)
1140
+ - `<provider>.max_output_tokens` -- upper bound on response tokens. For
1141
+ `anthropic` the default is `32768` (`max_tokens` is still read as a legacy
1142
+ alias). For OpenAI compatible providers it is only sent when set.
1143
+ - `<provider>.timeout` -- HTTP timeout in seconds for one provider,
1144
+ overriding the global `timeout` (`ollama` defaults to `300`)
1080
1145
  - `stats` -- opt in to local-only usage analytics (`true`/`false`,
1081
1146
  default `false`). When enabled, every generation appends one row to
1082
1147
  `~/.local/share/git-cai/stats.db` capturing kind (`commit`, `amend`,
@@ -1234,6 +1299,12 @@ Override the provider for a single invocation:
1234
1299
  git cai -P anthropic
1235
1300
  ----
1236
1301
 
1302
+ Use a custom OpenAI compatible provider defined in the config:
1303
+
1304
+ ----
1305
+ git cai -P lmstudio
1306
+ ----
1307
+
1237
1308
  Override both provider and model:
1238
1309
 
1239
1310
  ----