English | 简体中文
AI-powered Git CLI that analyzes your staged and unstaged changes, splits them into atomic commits, and generates conventional commit messages via LLMs. It also surfaces co-change relations for agents — which files habitually change together, plus the commits that explain why — all-language, offline, and with no API key.
Homebrew (macOS/Linux):
brew install GitAgentHQ/brew/git-agentGo install:
go install github.com/gitagenthq/git-agent@latestPre-built binaries: download from the releases page.
Install the git-agent skill to enable AI agents to commit on your behalf:
npx skills add https://github.com/GitAgentHQ/git-agent-cli --skill using-git-agentThe skill is a discovery stub — the full usage guide ships in the binary:
git-agent skills get core prints the main guide (triggers, workflows, flags,
exit codes) and git-agent skills get cli prints the complete command
reference, always matching the installed version.
# Initialize git-agent in your repository
git-agent init
# Stage changes, then generate and create commits
git-agent commitInitialize git-agent in the current repository. With no flags, runs the full setup wizard: generates .gitignore, generates commit scopes from git history, and writes .git-agent/config.yml with scopes and hook: [conventional].
git-agent init # full wizard (gitignore + scopes + conventional hook)
git-agent init --scope # generate scopes only
git-agent init --gitignore # generate .gitignore only
git-agent init --hook conventional # install conventional commit validator
git-agent init --hook empty # install empty placeholder hook
git-agent init --hook /path/to/script # install a custom hook script
git-agent init --force # overwrite existing config/hook/.gitignore
git-agent init --max-commits 50 # limit commits analyzed for scope generation
git-agent init --local --scope # write scopes to .git-agent/config.local.yml| Flag | Description |
|---|---|
--scope |
Generate scopes via AI |
--gitignore |
Generate .gitignore via AI |
--hook |
Hook to configure: conventional, empty, or a file path (repeatable) |
--force |
Overwrite existing config/.gitignore |
--max-commits |
Max commits to analyze for scope generation (default: 200) |
--local |
Write config to .git-agent/config.local.yml (requires an action flag) |
--user |
Write config to ~/.config/git-agent/config.yml (requires an action flag) |
The graph database (.git-agent/graph.db) is generated at runtime by commit,
related, and status commands. It must never be committed — if it is, every
run re-modifies it and produces a stream of chore: update graph database file
commits (the "infinite recreation" loop).
git-agent defends this invariant automatically, with no init required:
git-agent initwrites.git-agent/graph.db(+*.db-shm/*.db-wal/*.db-journaland.git-agent/config.local.yml) into the committed.gitignore, and runsgit rm --cachedon any already-trackedgraph.dbso the rule can take effect.- Runtime defence: every command that opens the graph DB (
commit,related,status) writes the mandatory ignore rules to.git/info/exclude(local, untracked, invisible togit diff) and untracksgraph.dbif a prior commit tracked it — e.g. a repo cloned from a fork that committed it. This breaks the loop even wheninithas not run.
Verify when in doubt:
git ls-files .git-agent/graph.db # must print nothing (untracked)
git check-ignore .git-agent/graph.db # prints the path, exit 0 (ignored)Reads staged and unstaged changes, splits them into atomic groups, generates a commit message for each group, and commits them in sequence.
git-agent commit # commit all changes
git-agent commit --dry-run # print messages without committing
git-agent commit --no-stage # commit already-staged changes only
git-agent commit --amend # regenerate and amend the last commit
git-agent commit --intent "fix auth bug" # provide a context hint to the LLM
git-agent commit --co-author "Name <email>" # add a co-author trailer
git-agent commit --trailer "Fixes: #123" # add an arbitrary git trailer
git-agent commit --no-attribution # omit the default Git Agent trailer
git-agent commit -o json # structured result (titles, SHAs, hook outcome)With -o json, commit prints a single object: dry_run, commits[] (each
{title, message, files, sha, hook_outcome}), committed_count, and
final_sha. hook_outcome is passed or skipped. Otherwise output is
human-readable text.
Manage git-agent configuration.
git-agent config show # display resolved provider config (API key masked)
git-agent config get <key> # show resolved value and source scope for a key
git-agent config set <key> <value> # write a config value to the appropriate scope
git-agent config set --user api-key sk-xxx # write to user scope
git-agent config set --project hook empty # write to project scope
git-agent config set --local max-diff-lines 1000 # write to local scope
git-agent config set --local max-diff-bytes 524288 # raise the byte cap (e.g., 512 KiB for direct endpoints)
git-agent config set --local max-plan-files 300 # raise the planner file-list cap before it collapses to directory summariesconfig set and config get accept both snake_case and kebab-case keys (e.g., api-key and api_key are equivalent).
| Scope flag | Config file | Purpose |
|---|---|---|
--user |
~/.config/git-agent/config.yml |
Provider keys and Cloudflare AI Gateway ID |
--project |
.git-agent/config.yml |
Shared, checked into git |
--local |
.git-agent/config.local.yml |
Personal override, gitignored |
When no scope flag is given, provider keys default to --user and all others to --project.
Generate shell completion scripts for git-agent.
git-agent completion bash # bash completions
git-agent completion zsh # zsh completions
git-agent completion fish # fish completions
git-agent completion powershell # PowerShell completionsTo load completions for each session, run once:
# bash (macOS)
git-agent completion bash > $(brew --prefix)/etc/bash_completion.d/git-agent
# zsh
git-agent completion zsh > "${fpath[1]}/_git-agent"
# fish
git-agent completion fish > ~/.config/fish/completions/git-agent.fishPrint the build version.
Show the files that historically change together with the given seeds (co-change coupling), mined from git history. Seeds are file paths, a directory, or — with no arguments — your current working-tree changes ("what else usually changes with my edits?"). A file coupled to several seeds ranks highest.
In JSON output, each related file carries a commits array of
{sha, subject, ts} — the commits that link it to a seed, i.e. the evidence
for why the two files are coupled. Use --tests to keep only related test
files, a fast "which tests should I run after this change?".
Language-agnostic (it reads git history, not source parsing), offline (no LLM, no API key), and auto-indexed on first run.
git-agent related # "what else changes with my edits?"
git-agent related application/commit_service.go # co-change from a specific file
git-agent related src/ # co-change from a directory
git-agent related application/commit_service.go --tests # related test files only
git-agent related application/commit_service.go -o json # adds the linking `commits` array| Flag | Default | Description |
|---|---|---|
--depth |
1 | Transitive co-change depth |
--top |
20 | Max results |
--min-count |
2 | Minimum co-change count to include |
--tests |
false | Keep only related test files |
--reindex |
false | Force a full re-index before querying |
-o, --output |
auto | Output format: auto, json, text (JSON when piped, text on a TTY) |
related is the temporal complement to a code-search tool, not a replacement.
Grep, Glob, and editor "find references" locate files by their current
content and symbols (spatial). related locates them by how they have
changed together (temporal). Many real couplings are invisible to a symbol
search:
- In
gin, over half ofcontext.go's top co-change partners (tree.go,errors.go,binding/*,render/*) carry no textual link to theContextsymbol — grep cannot surface them. - In
flask,app.pyco-changes withCHANGES.rst(85 commits) anddocs/templating.rst; grep alone never tells you to update the changelog and docs when you editapp.py.
The JSON commits array adds the intent behind each coupling, which static
search cannot. A practical loop: related <file> (blast radius + the commits
explaining why) → grep/read those files (exact code) → related <file> --tests
(which tests to run). It is offline and answers in milliseconds, so an agent
can call it on every multi-file change.
Co-change is an aggregate signal: accurate for consistent couplings (an
implementation and its test), softer for feature-spanning or sweeping commits.
Read the commits subjects to tell a real coupling from incidental noise.
Report code-graph index health and row counts: commits, files, authors, co-change pairs, the last indexed commit, and database size. Offline (no LLM, no API key).
git-agent status # index health + row counts
git-agent status -o json # structured output
git-agent related <file> # auto-indexes git history on first runOptional. Points to any OpenAI-compatible endpoint:
base_url: https://api.openai.com/v1
api_key: sk-...
model: gpt-4oOfficial release binaries point at a free shared gateway by default, so no
configuration is required — just run git-agent commit. Your requests are
routed through a Cloudflare Worker that holds the upstream credential
server-side (never in the binary) and rate-limits anonymous free usage.
To opt out and use your own endpoint, set base_url (and optionally api_key
/ model) — any user config overrides the built-in gateway URL.
Examples for other providers:
# Bring your own key — Cloudflare AI Gateway + Workers AI
base_url: https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT_ID/ai/v1
api_key: YOUR_CLOUDFLARE_API_TOKEN
model: "@cf/zai-org/glm-4.7-flash"
cloudflare_ai_gateway_id: YOUR_GATEWAY_ID # use "default" for the default gatewayWhen you bring your own key, git-agent routes requests through that endpoint
directly; for Cloudflare, cloudflare_ai_gateway_id opts into the gateway,
disables prompt/response payload storage while retaining metadata, and leaves
retries to the CLI so retry layers cannot multiply.
# Local Ollama
base_url: http://localhost:11434/v1
model: llama3Generated by git-agent init. Defines commit scopes and hook configuration. Also reads .git-agent/project.yml for backward compatibility:
scopes:
- api
- core
- auth
- infra
hook:
- conventionalConfigured via --hook during init or updated later with git-agent config set hook <value>:
| Hook | Description |
|---|---|
conventional |
Validates Conventional Commits format (Go-native) |
empty |
Placeholder that always passes |
<file path> |
Go validation + shell script at that path |
Custom hooks receive a JSON payload on stdin (diff, commitMessage, intent, stagedFiles, config) and should exit 0 to allow or non-zero to block. On block, git-agent retries up to 3 times before exiting with code 2.
| Flag | Description |
|---|---|
--dry-run |
Print commit messages without committing |
--no-stage |
Skip auto-staging; commit only already-staged changes |
--amend |
Regenerate and amend the most recent commit (no planning or hooks) |
--intent |
Describe the intent of the change |
--co-author |
Add a co-author trailer (repeatable) |
--trailer |
Add an arbitrary git trailer, format Key: Value (repeatable) |
--no-attribution |
Omit the default Git Agent co-author trailer |
--max-diff-lines |
Maximum diff lines sent to the model (default: 0, no line limit; a byte cap always applies) |
--max-diff-bytes |
Maximum diff bytes sent to the model (default: 0, falls back to the built-in ~384 KiB cap; pass a positive value to override) |
--max-plan-files |
Maximum file paths listed individually in the planner prompt before collapsing to directory summaries (default: 0, falls back to the built-in cap of 150) |
-o, --output |
Output format: text (default), json, or auto (JSON when piped) |
| Flag | Description |
|---|---|
--api-key |
API key for the AI provider |
--model |
Model to use for generation |
--base-url |
Base URL for the AI provider |
-v, --verbose |
Enable verbose output |
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error — no changes, API failure, missing config |
| 2 | Hook blocked — pre-commit hook returned non-zero after retries |
| 3 | Retired/unused (no longer emitted) |
| 4 | Retired/unused — formerly Event Log chain integrity; the Event Log subsystem has been removed (no longer emitted) |
See CHANGELOG.md for release history.