Guidelines for AI agents (Claude, GPT, Copilot, etc.) working with this codebase.
codecompanion-gitcommit.nvim is a Neovim plugin extension for CodeCompanion that provides:
- AI-powered Git commit message generation following Conventional Commits
- Comprehensive Git workflow tools (
@{git_read},@{git_edit},@{git_bot}) - AI-powered release notes generation
- Multi-language support for commit messages
- Smart buffer integration for gitcommit filetype
- Requires CodeCompanion v18.0+
- Lua 5.1+ / LuaJIT
- Neovim 0.9+
- Multi-platform (Linux, macOS, WSL, Native Windows)
codecompanion-gitcommit.nvim/
├── lua/codecompanion/_extensions/gitcommit/
│ ├── init.lua # Main entry point, extension setup, exports
│ ├── config.lua # Default configuration options
│ ├── git.lua # Core Git operations (diff, commit, repository detection)
│ ├── generator.lua # LLM-based commit message generation
│ ├── buffer.lua # Gitcommit buffer integration & auto-generation
│ ├── ui.lua # Floating window UI for commit message display
│ ├── langs.lua # Multi-language support for commit messages
│ ├── types.lua # Type definitions (LuaLS annotations)
│ ├── prompts/
│ │ └── release_notes.lua # Prompts for AI release notes generation
│ └── tools/
│ ├── git.lua # GitTool class - low-level git operations
│ ├── git_read.lua # Read-only git operations tool schema
│ ├── git_edit.lua # Write-access git operations tool schema
│ ├── ai_release_notes.lua # AI-powered release notes tool
│ └── validation.lua # Parameter validation utilities
├── doc/
│ └── codecompanion-gitcommit.txt # Vim help documentation
├── scripts/
│ └── download_codecompanion.ps1 # Development script
└── .github/workflows/
└── stylua-check.yml # CI for code formatting
init.lua (entry point)
├── config.lua
├── git.lua ──────────────────┐
├── generator.lua │
├── buffer.lua ───────────────┼── git.lua (core)
├── ui.lua │
├── langs.lua │
└── tools/ │
├── git.lua ──────────────┘
├── git_read.lua ─────────┬── tools/git.lua
├── git_edit.lua ─────────┤
├── ai_release_notes.lua ─┴── prompts/release_notes.lua
└── validation.lua
The main module that:
- Sets up the extension with CodeCompanion
- Registers tools (
git_read,git_edit,ai_release_notes) and tool groups (git_bot) - Creates Vim commands (
:CodeCompanionGitCommit,:CCGitCommit) - Adds slash commands (
/gitcommit) - Exposes programmatic API via
exports
Chat Config Access:
-- v18+ uses interactions
if codecompanion_config.interactions and codecompanion_config.interactions.chat then
return codecompanion_config.interactions.chat
endHandles:
- Repository detection (
is_repository()) - Diff retrieval with file filtering (
get_staged_diff(),get_contextual_diff()) - Amend detection (
is_amending()) - Commit history retrieval (
get_commit_history()) - Glob pattern matching for file exclusion
Important: This module maintains its own config state set via Git.setup().
LLM integration for commit message generation:
- Supports both HTTP and ACP (Anthropic Claude Protocol) adapters
- Handles streaming responses
- Cleans markdown code blocks from LLM output
- Creates structured prompts with commit history context
CodeCompanion tool implementations following the tool schema pattern:
| Tool | File | Purpose |
|---|---|---|
git_read |
git_read.lua |
16 read-only operations (status, log, diff, etc.) |
git_edit |
git_edit.lua |
20 write operations (stage, commit, push, etc.) |
| ai_release_notes | ai_release_notes.lua | AI-powered release notes from commit history |
Tool Schema Structure:
Tool.schema = {
type = "function",
["function"] = {
name = "tool_name",
parameters = { ... },
strict = true, -- Enforce strict parameter validation
},
}
Tool.system_prompt = [[...]] -- LLM context
Tool.cmds = { function(self, args) ... end } -- Execution
Tool.handlers = { setup, on_exit }
Tool.output = { prompt, success, error, rejected }
Tool.opts = { require_approval_before } -- Tool optionsCentralized parameter validation with consistent error formatting:
require_string(),optional_string()require_array(),optional_integer(),optional_boolean()require_enum(),first_error()
- Formatter: StyLua (config in
stylua.toml) - Line width: 120 characters
- Indentation: 2 spaces
- Quotes: Double quotes for strings
- Modules:
PascalCasefor classes (GitTool,Generator) - Functions:
snake_case(get_staged_diff,format_git_response) - Private functions: Prefix with
_(Git._filter_diff,Buffer._setup_gitcommit_keymap) - Constants:
UPPER_SNAKE_CASE(TOOL_NAME,VALID_OPERATIONS)
Use LuaLS (lua-language-server) annotations:
---@class ClassName
---@field field_name type Description
---@param param_name type Description
---@return type description
function Module.function_name(param_name)local ok, result = pcall(function()
-- risky operation
end)
if not ok then
return false, "Error: " .. tostring(result)
end
return resultlocal success, output = pcall(vim.fn.system, cmd)
if not success or vim.v.shell_error ~= 0 then
return false, output or "Command failed"
end
return true, outputThis extension requires CodeCompanion v18.0+. The codebase uses:
interactions.chatfor chat configurationrequire_approval_beforefor tool approval
Tool Options Pattern:
Tool.opts = {
require_approval_before = function(_self, _tools) return true end,
}- Add operation to
VALID_OPERATIONSingit_read.lua - Add to schema
enumarray - Add to
system_promptdocumentation table - Implement handler in
GitTool(tools/git.lua) - Add case in
GitRead.cmdsfunction - Add to help text
Same pattern as read operations, but in git_edit.lua. Remember:
- Edit operations require approval (
require_approval_before = true) - Add appropriate parameter validation
- Handle async operations if needed (see
push_async)
- Create
tools/new_tool.luafollowing existing pattern - Register in
init.lua→setup_tools() - Add schema, system_prompt, cmds, handlers, output, opts
- Add to tool group if needed (
git_bot)
mise run deps # Install test dependencies (mini.nvim)
mise run test # Run all unit tests
mise run test:file file=tests/test_validation.lua # Run specific test file
mise run lint # Check code formatting with stylua
mise run fmt # Format code with stylua
mise run doc # Download latest CodeCompanion documentationstylua --check . # Check formatting (used in CI)
stylua . # Auto-fix formatting
# Or via mise:
mise run lint # Check formatting
mise run fmt # Auto-fix formattingThe extension must be loaded through CodeCompanion:
require("codecompanion").setup({
extensions = {
gitcommit = {
callback = "codecompanion._extensions.gitcommit",
opts = { ... }
}
}
})- Use
vim.notify()for user-facing messages - Use
vim.inspect()for debugging complex data structures - Check
vim.v.shell_errorafter shell commands - Use
pcall()to catch Lua errors gracefully
local function format_git_response(tool_name, success, output, empty_msg)
local user_msg, llm_msg
local tag = "git" .. tool_name:gsub("^%l", string.upper) .. "Tool"
if success then
user_msg = string.format("✓ Git %s:\n```\n%s\n```", tool_name, output)
llm_msg = string.format("<%s>success:\n%s</%s>", tag, output, tag)
else
user_msg = string.format("✗ Git %s failed: %s", tool_name, output)
llm_msg = string.format("<%s>fail: %s</%s>", tag, output, tag)
end
return user_msg, llm_msg
endvim.fn.jobstart(cmd, {
on_stdout = function(_, data) ... end,
on_stderr = function(_, data) ... end,
on_exit = function(_, code)
if code == 0 then
callback({ status = "success", data = output })
else
callback({ status = "error", data = error_output })
end
end,
})local normalize_output = require("codecompanion._extensions.gitcommit.tools.output").normalize_output
local output = normalize_output(stdout)
local errors = normalize_output(stderr, "Unknown error")local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
vim.api.nvim_buf_set_lines(bufnr, start, end_, false, new_lines)
vim.api.nvim_win_set_cursor(0, { row, col })- Read operations (
git_read): No approval required - Write operations (
git_edit): Require user approval - Force push: Extra warning, explicitly dangerous
- Input escaping: Always use
vim.fn.shellescape()for shell commands - Path validation: Validate file paths before operations
local gitcommit = require("codecompanion._extensions.gitcommit")
-- Generate commit message
gitcommit.exports.generate("English", function(result, error) end)
-- Check repository status
gitcommit.exports.is_git_repo()
-- Git operations
gitcommit.exports.git_tool.status()
gitcommit.exports.git_tool.stage({"file.lua"})
gitcommit.exports.git_tool.generate_release_notes("v1.0", "v1.1", "markdown")- Always run
stylua --check .after making changes to ensure StyLua compliance - Always run
stylua .after modifying code to auto-format - Use v18+ patterns when modifying tool options (use
require_approval_before) - Use validation.lua for all parameter validation in tools
- Follow existing patterns - this codebase is consistent; match the style
- Test with actual CodeCompanion - the extension requires the parent plugin
- Error messages should be user-friendly - use icons (✓, ✗, ℹ) for visual feedback 8 Document new features in both code (annotations) and help file
- Update this file (AGENTS.md) with any new patterns or guidelines you introduce