Provider-agnostic prompt/styling toolkit for LLM-powered git workflow tools (commit messages, MR descriptions)
Project description
git-ai
LLM-powered git workflow tools. Generate commit messages and PR titles using explicit auth methods and model IDs from the CLI, Lazygit, and other git environments that expose normal Git state.
Install
npm install -g @waxmard/git-ai
Or clone and symlink for local development:
make install # symlinks to ~/.local/bin and ~/.local/lib; edits are live
make uninstall
Prerequisites
At least one auth method must be available:
| Auth Method | Runtime | Auth |
|---|---|---|
vertex |
Gemini CLI | Google ADC / Vertex credentials |
gemini-api |
Gemini CLI | GEMINI_API_KEY or system keychain |
claude-code |
Claude Code CLI | Claude Code CLI session |
anthropic-api |
curl + python3 |
ANTHROPIC_API_KEY |
codex |
Codex CLI | Codex CLI session |
openai-api |
curl + python3 |
OPENAI_API_KEY |
anthropic-api and openai-api require curl and python3, both standard on macOS and most Linux systems.
Gemini API auth
git-ai tries these in order until one succeeds:
GEMINI_API_KEYenvironment variable- System keychain — store the key as
gemini-api-key:- macOS:
security add-generic-password -s gemini-api-key -a "$USER" -w YOUR_KEY - GNOME / libsecret:
secret-tool store --label="Gemini API Key" service gemini-api-key - pass:
pass insert gemini-api-key - KDE Wallet:
kwallet-query kdewallet -w gemini-api-key
- macOS:
- Google Application Default Credentials (ADC):
gcloud auth application-default login- or set
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Commands
Both git-ai and aigit work identically — use whichever you prefer.
commit
Generate a commit message from staged changes.
git-ai commit [auth-method] [model-id]
- Reads
git diff --stagedand produces a Conventional Commits message - Includes a description body for non-trivial changes
- No default auth method on a fresh repo; choose one explicitly
- Non-
vertexauth methods default to a lightweight model whenmodel-idis omitted vertexalways requires an explicit model ID- Pass
lastas the provider to reuse the previously generated message
pr
Generate a PR title and body from the current branch.
git-ai pr [auth-method] [model-id] [--base <branch>] [--fresh] [--from-sha <commit>]
git-ai mr [...] # alias for pr
- Reads the commit log and diff against the base branch
- Produces a Conventional Commits title + markdown body with a
### Test Plansection - Auto-detects the base branch from the remote default (falls back to
main) - Use
--baseto override (e.g.--base dev) - Saves the generated output per current-branch/base-branch pair under
.git/pr-cache/; subsequent runs with the same pair refine the previous result automatically - Use
--freshto ignore the saved output and regenerate from scratch - Use
--from-shato override the saved HEAD and regenerate only from commits after a specific prior generated commit - No default auth method on a fresh repo; choose one explicitly
- Non-
vertexauth methods default to a stronger model whenmodel-idis omitted vertexalways requires an explicit model ID
options
List every auth-method / model combo as a flat pipe-delimited list, LRU-sorted. Primary input for the fzf-based Lazygit integration; also useful for custom pickers.
git-ai options [commit|pr]
- Emits one
provider:model|<label>line per selectable combo - For
commit, also emitslast|reuse saved messagewhen a saved message exists - Most-recent picks (from
.git/{tool}-choice-history) float to the top; remaining combos follow in default order git-ai commit <provider:model>andgit-ai pr <provider:model>accept the emitted value directly
providers / models
List available auth methods and models, ordered by last-used. Kept for scripting and as a fallback when options isn't a fit.
last is only a commit provider option; PR refinement reuses cached prior output automatically.
git-ai providers [commit|pr]
git-ai models <auth-method> [commit|pr]
Python library
git-ai is also distributed as a Python package (waxmard-git-ai) so other tools can reuse the same commit-message and MR-description generation without shelling out.
pip install waxmard-git-ai
# or: uv add waxmard-git-ai
The Python package is provider-agnostic: it owns prompt assembly, diff-stat derivation, fence-stripping, and cache management, but not the LLM call. Consumers pass a generate: Callable[[str, str], str] that takes (system_prompt, user_input) and returns raw model text. Bring your own Claude / Gemini / OpenAI / anything.
generate_mr_description handles both repo-mode and data-mode through one entry point and returns an MrDescription(text, diff) — text is the full PR, diff is a marker-style rendering of what changed vs. existing_pr (or None when there's no prior PR or the output matches it).
Bring-your-own provider — example with the Google Gemini SDK:
from google import genai
from google.genai import types
from git_ai import generate_mr_description
client = genai.Client()
def generate(system_prompt: str, user_input: str) -> str:
resp = client.models.generate_content(
model="gemini-3.1-pro-preview",
contents=user_input,
config=types.GenerateContentConfig(system_instruction=system_prompt),
)
return resp.text or ""
Swap the body for anthropic, openai, vertexai, or any other SDK — git_ai never imports them.
Repo-mode (reads staged diff / base..HEAD from a local checkout):
from git_ai import generate_commit_message, generate_mr_description
msg = generate_commit_message(".", generate=generate)
pr = generate_mr_description(".", base_branch="main", generate=generate)
pr = generate_mr_description(".", base_branch="main", fresh=True, generate=generate)
pr = generate_mr_description(
".",
base_branch="main",
existing_pr=existing_pr_text,
previous_head_sha=last_generated_head_sha,
generate=generate,
)
print(pr.text) # full PR (title line + body)
print(pr.diff or "") # marker-style delta vs existing_pr, if any
Data-mode (no local checkout required — pass raw diff strings, e.g. fetched from the GitHub/GitLab API):
from git_ai import (
format_commit_log,
generate_commit_message_from_diff,
generate_mr_description,
)
commit_msg = generate_commit_message_from_diff(diff_text, generate=generate)
log = format_commit_log((c.title, c.message) for c in mr_commits)
pr = generate_mr_description(
diff=diff_text,
commit_log=log,
existing_pr=current_pr_body or None,
generate=generate,
)
# pr.text -> full updated PR to post as title + description
# pr.diff -> compact "what changed since last PR" markers, or None
diff_stat and release_context are optional — when omitted, the diff-stat is derived from the diff and a generic "no release tags found" context is used. Model selection, retries, auth, and error handling are the consumer's responsibility (inside generate).
Repo-mode uses the same incremental PR efficiency path as the CLI: it reuses .git/pr-cache/ automatically, returns the cached PR unchanged when HEAD has not advanced, and narrows generation to commits after the last generated HEAD when possible. Pass fresh=True to disable that behavior for one call, or previous_head_sha= to override the cached incremental base explicitly.
Data-mode is stateless by design. To get the same efficiency in remote consumers, persist the prior PR text and prior generated head SHA yourself, fetch only the incremental diff/log since that SHA from your SCM, then call generate_mr_description(diff=..., existing_pr=..., generate=...).
Narrowing the picker list
By default git-ai options enumerates every supported provider/model combo. Most users only have access to a couple. To restrict the picker to just the providers and models you actually use, drop a config file at $XDG_CONFIG_HOME/git-ai/options.conf (usually ~/.config/git-ai/options.conf):
[claude-code]
claude-haiku-4-5-20251001
claude-sonnet-4-6
[codex]
gpt-5.4-mini
# Empty section hides this provider entirely
[vertex]
[provider]headers must be one of:vertex,gemini-api,claude-code,anthropic-api,codex,openai-api. Unknown headers are silently dropped.- Model IDs under a header are passed through to the provider verbatim, so you can list future model IDs (e.g. a newly released
claude-sonnet-5-0) without waiting for a git-ai release. - Delete the file to restore the full shipped catalog.
- See
examples/options.conffor a starter.
Terminal picker
Running git-ai commit or git-ai pr without a provider argument launches an inline fzf picker over the same provider/model combos Lazygit uses. History entries float to the top. Pass provider or provider:model to skip the picker. Flags still parse, so git-ai pr --base staging opens the picker then runs against the chosen base.
Set GIT_AI_NO_FZF=1 (or pipe stdout) to disable the picker for scripting. If fzf isn't installed, the tools fall back to the last saved choice.
Lazygit integration
Requires fzf on your PATH. Add the following under customCommands: in ~/.config/lazygit/config.yml:
customCommands:
- key: "<c-g>"
description: "AI commit message (git-ai + fzf)"
context: "files"
command: |
choice=$(git-ai options commit | fzf --delimiter='|' --with-nth=2 --no-sort --tiebreak=index --prompt='git-ai> ') || exit 0
git commit -m "$(git-ai commit "${choice%%|*}")" --edit
output: terminal
Pressing <c-g> in the files panel opens an fzf picker showing every auth+model combo (plus reuse saved message when available). Typeahead narrows instantly; Enter commits with the generated message. Selections float to the top of the list on subsequent invocations.
Compatibility
git-ai does not depend on a specific terminal UI. It works in the CLI, in Lazygit, and in similar git environments as long as Git exposes the required repository state:
git-ai commitneeds staged changes (git diff --staged)git-ai prneeds commits and diff data relative to a base branch
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file waxmard_git_ai-4.1.3.tar.gz.
File metadata
- Download URL: waxmard_git_ai-4.1.3.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c12099ce577d50842c2965372a25bd9271f685f062ca7ca9cfdb8a2692d6dee7
|
|
| MD5 |
b5dd85df0a9a3fe38f2c3445c1036685
|
|
| BLAKE2b-256 |
47c1cb5dcf4f7bf9b699a3f7e7f77175a6c68f9b4dd98c6bc85469f33458f154
|
Provenance
The following attestation bundles were made for waxmard_git_ai-4.1.3.tar.gz:
Publisher:
pypi-publish.yml on Waxmard/git-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waxmard_git_ai-4.1.3.tar.gz -
Subject digest:
c12099ce577d50842c2965372a25bd9271f685f062ca7ca9cfdb8a2692d6dee7 - Sigstore transparency entry: 1358967495
- Sigstore integration time:
-
Permalink:
Waxmard/git-ai@371e2bbcf2e8288beb37e983674dd6005fda4692 -
Branch / Tag:
refs/tags/v4.1.3 - Owner: https://github.com/Waxmard
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@371e2bbcf2e8288beb37e983674dd6005fda4692 -
Trigger Event:
push
-
Statement type:
File details
Details for the file waxmard_git_ai-4.1.3-py3-none-any.whl.
File metadata
- Download URL: waxmard_git_ai-4.1.3-py3-none-any.whl
- Upload date:
- Size: 24.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f7f7d2b36336f73944b6be72bbdaf380f82981ad11dd23cc75b7091dc83efe8
|
|
| MD5 |
2d2cf618a49345db7d726e7730baac8d
|
|
| BLAKE2b-256 |
64b604cc63cb091e0e67e84809296297477f74a15ec590e738fe3cc76ada290b
|
Provenance
The following attestation bundles were made for waxmard_git_ai-4.1.3-py3-none-any.whl:
Publisher:
pypi-publish.yml on Waxmard/git-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waxmard_git_ai-4.1.3-py3-none-any.whl -
Subject digest:
0f7f7d2b36336f73944b6be72bbdaf380f82981ad11dd23cc75b7091dc83efe8 - Sigstore transparency entry: 1358967523
- Sigstore integration time:
-
Permalink:
Waxmard/git-ai@371e2bbcf2e8288beb37e983674dd6005fda4692 -
Branch / Tag:
refs/tags/v4.1.3 - Owner: https://github.com/Waxmard
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@371e2bbcf2e8288beb37e983674dd6005fda4692 -
Trigger Event:
push
-
Statement type: