AI-powered commit messages while you review your diff in your favorite editor.
A Neovim plugin that automatically generates commit messages using AI when you
run git commit -v, letting you review your changes while the AI crafts the
perfect commit message.

- 🤖 Automatically generates commit messages using the Pi CLI or Gemini, OpenAI, Anthropic, and GitHub Copilot APIs
when you run
git commit -v - 🎯 Works from terminal or within Neovim (using vim-fugitive)
- 🤝 Non-intrusive - if you start typing, AI suggestions are added as comments instead
- 🔑 Reuses your Pi login or provider API key environment variables for authentication
- ⚙️ Configurable model, temperature, and max tokens
- 🔄 Optional push prompt after successful commits
- ⬇️⬆️ Pull before push to reduce rejections (configurable with args)
- ⌨️ Customizable keymaps for commit buffer
- 📊 Optional spinner and notifications during generation
Using lazy.nvim
{
"aweis89/ai-commit-msg.nvim",
ft="gitcommit",
config=true,
opts= {
-- your configuration options here
},
}{
"tpope/vim-fugitive",
cmd= { "Git" },
keys= {
-- Opens commit in a new tab so quitting doesn't exit Neovim
{ "<leader>gc", "<cmd>tab Git commit -v<cr>", desc="Git commit" },
},
},
{
"aweis89/ai-commit-msg.nvim",
ft="gitcommit",
config=true,
opts= {
-- your configuration options here
},
}Using packer.nvim
use {
"aweis89/ai-commit-msg.nvim",
config=function()
require("ai_commit_msg").setup({
-- your configuration
})
end
}For the Pi provider, install and authenticate the pi CLI:
pi
/loginFor direct API providers, set the corresponding environment variable:
For Gemini (default, best value):
export GEMINI_API_KEY="your-api-key-here"For OpenAI:
export OPENAI_API_KEY="your-api-key-here"For GitHub Copilot:
export COPILOT_TOKEN="your-github-copilot-token-here"For Anthropic:
export ANTHROPIC_API_KEY="your-api-key-here"Configure Neovim as your Git editor:
git config --global core.editor nvimrequire("ai_commit_msg").setup({
-- Enable/disable the pluginenabled=true,
-- AI provider to use ("pi", "gemini", "openai", "anthropic", or "copilot")provider="gemini",
-- Whether to prompt for push after commitauto_push_prompt=true,
-- Pull-before-push behavior (helps avoid rejected pushes)pull_before_push= {
enabled=true, -- run a pull before pushingargs= { "--rebase", "--autostash" }, -- arguments passed to `git pull`
},
-- Show spinner while generatingspinner=true,
-- Show notificationsnotifications=true,
-- Number of surrounding lines to include in git diff (default: 5)context_lines=5,
-- Cost display format ("compact", "verbose", or false to disable)cost_display="compact",
-- Keymaps for commit bufferkeymaps= {
quit="q", -- Set to false to disable
},
-- Provider-specific configurationsproviders= {
openai= {
model="gpt-5-mini",
temperature=0.3,
max_tokens=nil, -- Uses model default-- Used to display cost per commit in notifications (see screenshot above)reasoning_effort="minimal", -- Options: "minimal", "medium", "high" (only applies to reasoning models like gpt-5*)-- Per-model pricing. Add entries for any models you use.pricing= {
["gpt-5-nano"] = {
input_per_million=0.05, -- Cost per million input tokensoutput_per_million=0.40, -- Cost per million output tokens
},
},
system_prompt=nil, -- Override to customize commit message generation instructions
},
anthropic= {
model="claude-3-5-haiku-20241022",
temperature=0.3,
max_tokens=2000, -- Required for Anthropic APIpricing= {
["claude-3-5-haiku-20241022"] = {
input_per_million=0.80, -- Cost per million input tokensoutput_per_million=4.00, -- Cost per million output tokens
},
},
system_prompt=nil, -- Override to customize commit message generation instructions
},
gemini= {
model="gemini-2.5-flash-lite",
temperature=0.3,
max_tokens=4000,
pricing= {
["gemini-2.5-flash-lite"] = {
input_per_million=0.10, -- Cost per million input tokensoutput_per_million=0.40, -- Cost per million output tokens
},
},
},
copilot= {
model="gpt-5-mini",
max_tokens=10000,
reasoning_effort="minimal",
},
pi= {
executable="pi",
-- Omit provider/model to use Pi's configured defaults.cli_provider=nil,
model=nil,
thinking=nil,
args= {}, -- Additional Pi CLI arguments
},
},
})require("ai_commit_msg").setup({
provider="pi",
providers= {
pi= {
-- Optional; omit these to use Pi's configured defaults.cli_provider="github-copilot",
model="gpt-5-mini",
thinking="low",
},
},
})The plugin invokes Pi in non-interactive, ephemeral, tool-free mode, ignores
project-local Pi resources, and sends the staged diff over standard input.
Authentication is handled by your existing Pi login. The effective Pi selection
is appended to stdpath("state") .. "/ai-commit-msg.log" without displaying a
notification.
require("ai_commit_msg").setup({
provider="openai",
})require("ai_commit_msg").setup({
provider="copilot",
providers= {
copilot= {
model="gpt-5-mini",
},
},
})require("ai_commit_msg").setup({
provider="anthropic",
})require("ai_commit_msg").setup({
provider="gemini",
providers= {
gemini= {
model="gemini-2.5-flash-lite",
temperature=0.5,
-- Pricing is resolved by model. Add entries for any models you use.pricing= {
["gemini-2.5-flash-lite"] = {
input_per_million=0.10,
output_per_million=0.40,
},
},
},
},
})require("ai_commit_msg").setup({
providers= {
gemini= {
system_prompt=[[Generate a commit message following Angular commit conventions.Include scope if applicable. Format: type(scope): description]], -- Override system prompt, diff is added as user message
},
},
})The plugin includes default pricing for these models:
- OpenAI:
gpt-5-nano,gpt-5-mini,gpt-4.1-mini,gpt-4.1-nano - Anthropic:
claude-3-5-haiku-20241022 - Gemini:
gemini-2.5-flash-lite,gemini-2.5-flash
All other models: add the correct input/output pricing in your config to ensure accurate costs in notifications. If a model has no pricing entry, cost is simply omitted.
Note on defaults: The plugin's default model choices may change over time to provide the best balance of quality and price. If you want to ensure a specific model is always used, explicitly pin it in your config (for example, providers.gemini.model = "gemini-2.5-flash-lite" or providers.openai.model = "gpt-5-mini").
Note on quality vs cost: Using OpenAI gpt-5-mini or gpt-4.1-mini (faster) generally yields better commit messages than the corresponding nano models, but at a higher cost.
:AiCommitMsg- Manually generate a commit message (prints to messages):AiCommitMsgDisable- Disable automatic commit message generation:AiCommitMsgEnable- Enable automatic commit message generation:AiCommitMsgAllModels- Generate commit messages across all configured provider models for your staged diff; opens a buffer with per-model results, timing, and (when pricing is configured) estimated cost — useful for model selection:AiCommitMsgTestMatrix [diffs_dir] [out_file]- Run a prompt/model matrix against.difffixtures. SetAI_COMMIT_MSG_DRY_RUN=1to only collect prompt sizes without API calls; otherwise writes JSONL lines toout_fileif provided
- Use
:AiCommitMsgAllModelson a representative staged diff to compare output quality, latency, and cost across models. - Once you pick a favorite, pin it in your config under
providers.<name>.modelto lock it in and avoid future default changes. - Example:
require("ai_commit_msg").setup({
provider="openai",
providers= {
openai= {
model="gpt-5-mini", -- pin to a specific model
},
},
})The plugin works seamlessly whether you commit from the terminal or within Neovim:
git add .
git commit -v # Opens Neovim with diff visible, AI generates message while you review:Git add .
:tab Git commit -v" Opens in new tab, AI generates message while you review" or with the keymap: <leader>gcWhen you run
git commit -v(with Neovim as your Git editor), the plugin automatically:- Detects when Git opens the commit message buffer
- Runs
git diff --stagedto get your staged changes - Sends the diff to your configured AI provider's API with your configured prompt
- Inserts the generated message into the commit buffer
- The
-vflag shows the diff below the message, allowing you to review changes during commit generation
If the buffer already has content (e.g., from a commit template), the AI-generated message is added as comments below for reference.
After you save and close the commit buffer, the plugin:
- Checks if the commit was successful (not cancelled or empty)
- If successful and
auto_push_promptis enabled, prompts you to push the commit
Note: This requires Neovim to be your Git editor. Set it with:
git config --global core.editor nvim- Neovim >= 0.7.0
- Pi CLI login or an AI provider API key:
- Pi: Authenticate with
/loginin the Pi CLI - Gemini: Set
GEMINI_API_KEYenvironment variable (default, best value) - OpenAI: Set
OPENAI_API_KEYenvironment variable - Anthropic: Set
ANTHROPIC_API_KEYenvironment variable - GitHub Copilot: Set
COPILOT_TOKENenvironment variable
- Pi: Authenticate with
- Git
- curl (for making API requests)
- The Pi provider shells out to
pi --print; other providers call their APIs directly - Lower temperature values (0.1-0.3) produce more consistent commit messages
- Higher temperature values (0.5-0.8) produce more creative variations
- The default model
gemini-2.5-flash-liteprovides excellent results at a very low cost - For OpenAI's
gpt-5*, the reasoning effort defaults to "minimal" when not specified - Claude 3.5 Haiku is also a solid choice for commit message generation
- If you don't specify
max_tokens, the model will use its default limit - For Anthropic models,
max_tokensis required by the API (defaults to 1000 if not specified) - For more predictable messages, keep
context_linesmodest (default5; usually3-10) to reduce noisy, unchanged context in large diffs - If outputs are too verbose, prefer single-line defaults with a custom
system_promptthat only allows a body for complex or breaking changes
MIT