A Neovim plugin that enables seamless integration with Google's Gemini CLI IDE mode.
- π Real-time Context Awareness: Automatically shares your current file, cursor position, and selection with Gemini CLI
- πͺ Floating Window Support: Toggle chat in a native Neovim floating window or a traditional side split
- π Native Diff Support: Review and apply AI-suggested code changes directly in Neovim with side-by-side diff view
- β¨οΈ Flexible Acceptance: Accept diffs via
:win Neovim or through Gemini CLI prompts - π Standard MCP Protocol: Built on the Model Context Protocol over HTTP
- π Secure: Token-based authentication for all communications
- π Workspace Discovery: Connect from any terminal, not just Neovim's
:terminal
This plugin integrates Neovim with Gemini CLI using the Model Context Protocol (MCP). It consists of:
- Neovim Lua Plugin: Monitors your editing activity and manages the diff UI
- Golang MCP Server: Bridges communication between Neovim and Gemini CLI
For detailed architecture information, see docs/architecture.md.
- Neovim >= 0.9.0
- Go >= 1.21
- Gemini CLI
Using lazy.nvim
{
'ndsl6211/nvim-gemini-cli',
build = 'cd server && go build -o ../bin/gemini-mcp-server',
config = function()
require('gemini-cli').setup({
-- Auto-setup default keymaps (<leader>gc, <leader>gs, <leader>gf, <leader>ga)
setup_keymaps = true,
-- Set to true to accept diffs with :w in the diff window
allow_w_to_accept = true,
})
end,
}Using packer.nvim
use {
'ndsl6211/nvim-gemini-cli',
run = 'cd server && go build -o ../bin/gemini-mcp-server',
config = function()
require('gemini-cli').setup()
end
}-
Clone the repository:
git clone https://github.com/ndsl6211/nvim-gemini-cli.git ~/.config/nvim/pack/plugins/start/nvim-gemini-cli -
Build the MCP server:
cd ~/.config/nvim/pack/plugins/start/nvim-gemini-cli/server go build -o ../bin/gemini-mcp-server
-
Add to your
init.lua:require('gemini-cli').setup()
The plugin provides customizable keymaps via <Plug> mappings and Lua functions.
If setup_keymaps = true (default), the following mappings are created:
<leader>gc: Toggle Gemini Chat terminal (Split)<leader>gf: Toggle Gemini Chat terminal (Float)<leader>ga: Send current file or selection to Gemini (Send/Append)<leader>gs: Show Gemini Status
You can manually map keys to the provided <Plug> mappings or Lua functions:
Using Lua Functions (Telescope Style):
-- Normal mode mapping
vim.keymap.set('n', '<leader>ff', function() require('gemini-cli.terminal').toggle() end)Using <Plug> Mappings:
-- This will automatically override the default <leader>gc
vim.keymap.set('n', '<C-g>', '<Plug>(GeminiChat)')Available <Plug> mappings:
<Plug>(GeminiChat)<Plug>(GeminiChatFloat)<Plug>(GeminiSend)<Plug>(GeminiStatus)<Plug>(GeminiRestart)<Plug>(GeminiStop)
Full configuration options with their default values:
require('gemini-cli').setup({
-- Auto-start server when Neovim starts
auto_start = true,
-- Log level: 'debug', 'info', 'warn', 'error'
log_level = 'info',
-- Debounce time for context updates (ms)
context_debounce_ms = 50,
-- Maximum number of open files to track
max_open_files = 10,
-- Allow :w in diff window to automatically accept and save changes
-- If true, pressing :w in the diff buffer accepts the suggestions.
allow_w_to_accept = true,
-- Automatically setup default keymaps (<leader>gc, <leader>gs)
setup_keymaps = true,
-- Focus Gemini terminal when opened via command/keymap (default: true)
focus_on_open = true,
-- Focus Gemini terminal when automatically opened by GeminiSend (default: false)
focus_on_send = false,
})Controls how you accept diff changes:
true(default): Pressing:win the diff window automatically applies changes to the original file, saves it to disk, and notifies Gemini CLI.false::win the diff buffer only updates the buffer state without saving to disk or notifying the server. You must accept changes via the Gemini CLI prompt.
Choose based on your workflow:
- Set to
falseif you want explicit control via CLI - Set to
truefor a streamlined Neovim-centric workflow
Controls whether the Gemini terminal window gains focus when it is opened via :GeminiChat or the <leader>gc/<leader>gf keymaps.
true(default): Focus moves to the terminal immediately and entersInsertmode.false: The terminal opens but your cursor stay in the current buffer.
Controls whether the Gemini terminal window gains focus when it is automatically opened by a context send command (:GeminiSend or <leader>ga).
true: Focus moves to the terminal.false(default): Focus stays in your code, allows you to send multiple references conveniently.
For a detailed explanation of the discovery mechanism, context sharing, and diff implementation, see docs/how-it-works.md.
For information on building from source, running tests, and contributing, see docs/development.md.
For common issues and solutions, see docs/troubleshooting.md.
For detailed documentation, see the docs/ directory:
- How It Works - Discovery mechanism, context sharing, and diff implementation
- Development Guide - Building, testing, and contributing
- Troubleshooting - Common issues and solutions
- Architecture - Detailed system architecture
- Neovim Communication - RPC protocol details
- Gemini Communication - HTTP/MCP protocol details
Contributions are welcome! Please see docs/development.md for:
- Development setup and workflow
- Building from source
- Running tests
- Code style guidelines
- How to submit pull requests
This plugin's implementation is inspired by claudecode.nvim and follows the Gemini CLI IDE Companion Specification.