DEV Community

Piotr Stachowski
Piotr Stachowski

Posted on

AI Commit: Crafting an Automated Git Commit Message Generator for Neovim

A deep dive into how I built the ai_commit plugin for Neovim (nvim) using asynchronous system subprocesses, specialized prompt engineering, and external LLM APIs with zero heavy language wrappers.

Introduction & Repository

Writing meaningful, informative, and standardized git commit messages is one of those daily disciplines that keeps codebases healthy—but it's also a point of constant friction. Developers often write rushed commits like fix issue, wip, or refactor some stuff to move on quickly, which turns the git history into an uninformative timeline.

While there are many CLI utilities and heavy node-based wrappers that solve this problem externally, doing so requires switching context away from your editor. As an avid Neovim user, I wanted a solution integrated directly into my editing workspace.

The plugin is fully open-source and easy to integrate:
👉 Official GitHub Repository: https://github.com/klusekP/ai_commit

The goal was clear: select or stage files, type a simple Neovim command (like :AICommit), and let Neovim automatically request an intelligent, conventional-commit-formatted message based on the actual code diff and inject it right into Neovim's active commit buffer.

1. Core Plugin Architecture

To build a native Neovim plugin, we need to balance performance with user experience. A naive synchronous HTTP request would freeze Neovim completely during the network round-trip, resulting in a laggy editor.

Therefore, ai_commit uses a fully asynchronous subprocess model. Here is the operational pipeline:

  • Change Detection: The plugin verifies if there are staged changes by spawning git diff --staged --name-only as an asynchronous background job.
  • Diff Ingestion: If changes are staged, it executes git diff --staged to harvest the precise code additions and deletions.
  • Payload Construction: It bundles the raw diff with a highly tailored system prompt, ensuring the LLM formats the response strictly following the Conventional Commits specification.
  • Asynchronous Dispatch: Rather than relying on a heavy Python, Node, or Rust binary, Neovim spawns a non-blocking curl process in the background.
  • Buffer Injection: Once curl exits with a successful response, Neovim processes the JSON, extracts the commit message, and populates either the active commit buffer or opens a floating menu for user review.

2. Technical Prerequisites & Dependencies

One of the core design goals of ai_commit was minimal bloat. To install and run the plugin, only a handful of ubiquitous system dependencies are required:

  • Neovim (v0.8.0 or newer): Required for modern Lua APIs, job control spawning, and floating buffer manipulation.
  • Git CLI: The system must have git installed in the system PATH, as the plugin runs subprocesses to retrieve diff metadata.
  • curl (System Utility): The plugin issues direct network requests using the standard curl command-line tool. This avoids needing external Lua HTTP socket libraries.
  • Plenary.nvim (Optional but Standard): Used for elegant asynchronous job coordination and cleaner network requests. Most Neovim users already have Plenary as a dependency for Telescope.
  • API Access Token: A valid API key for your chosen provider (such as OpenAI, Anthropic, Gemini, or a locally hosted Ollama instance running llama3).

3. Complete Installation & Configuration Guide

Integrating ai_commit into your Neovim configuration is simple and supports standard modern package managers.

Installation via lazy.nvim

Add this plugin declaration block directly to your plugins directory:

-- Neovim Plugin Integration using lazy.nvim
return {
  "klusekP/ai_commit",
  dependencies = { "nvim-lua/plenary.nvim" }, -- optional helper library
  config = function()
    require("ai_commit").setup({
      provider = "openai",          -- Options: "openai" | "gemini" | "ollama"
      model = "gpt-4o-mini",        -- Model alias to invoke
      prompt_language = "en",       -- Output language: "en" (English) or "pl" (Polish)
      temperature = 0.2,            -- Generative creativity scale
      key_maps = {
        generate = "<leader>ca",    -- Custom keymap to trigger generation
      }
    })
  end
}
Enter fullscreen mode Exit fullscreen mode

4. Provider Setup & Custom Prompts

The plugin is highly versatile and lets you leverage cloud APIs or locally run LLMs with ease.

  • Authentication: The plugin reads your API tokens directly from your environment variables, keeping your secrets out of your public dotfile repository (e.g., loads $OPENAI_API_KEY or $GEMINI_API_KEY).
  • Ollama (Local Offline Mode): Set provider = "ollama" and configure your local address (usually http://localhost:11434) to run completely offline without an internet connection.
  • Polish Language Output: Setting prompt_language = "pl" forces the system prompt to instruct the model to write clean, polish conventional commits, which is rare in other standard tools.

5. Command API & Keybindings

Once configured, the plugin exposes clean, native command-line bindings:

  • :AICommit - Triggers the asynchronous diff capture, calls the LLM, and populates the current buffer with the conventional commit message.
  • Keymaps configured under key_maps.generate (such as <leader>ca) let you execute this workflow instantly with simple keystrokes.

This ensures a rapid cycle where you stage changes with your preferred git UI (like fugitive or neogit), open your commit message editor, hit your keymap, and immediately commit your changes.

Conclusion

By bypassing heavy external runtimes and leveraging Neovim's built-in asynchronous job control coupled with direct API endpoints, ai_commit provides a lightning-fast, zero-bloat workflow that keeps your git timeline pristine and readable.

Check out the repository, install it today, and start generating professional, structured commit messages in your preferred language!

🔗 Star the project on GitHub: https://github.com/klusekP/ai_commit

Top comments (4)

Collapse
 
hari_haran_144973263df174 profile image
Hari Haran

How do you handle large git diffs that exceed the LLM's context window while still generating accurate commit messages?

Collapse
 
kluchol1922 profile image
Piotr Stachowski • Edited

Just yesterday, I generated a commit message for a change set containing around 305 small modifications. I did not have issues with the accuracy or structure of the response, since that largely depends on how the prompt and diff-processing strategy are configured.

However, when using a local model-mlx-community/Qwen2.5-Coder-14B-Instruct-4bit—the generation time was noticeably longer than for smaller diffs. For very large changes, I would split the diff into logical chunks, summarize each chunk separately, and then generate the final commit message from those summaries rather than passing the entire raw diff at once.

In the future, I also plan to extend the plugin with project-specific skills that provide architectural, domain, and repository context. This should allow the model to understand the purpose of the changes more accurately and generate more precise commit messages without relying only on the diff itself.

Collapse
 
hari_haran_144973263df174 profile image
Hari Haran

I like the idea of project-specific skills. Do you think they'll have a bigger impact on commit quality than simply using a larger model?

Thread Thread
 
kluchol1922 profile image
Piotr Stachowski

I think project-specific skills will have a bigger impact. A larger model can better summarize a diff, but it still lacks project context.