AI code completions in Neovim, powered by Claude. A self-hosted alternative to Supermaven/Copilot for people with a Claude Max subscription.
You press a key, ghost text streams in, you hit tab. That's it.
Heads up: bonk.nvim is in early development. APIs will change, features may break between commits, and there are rough edges everywhere. If you use it today, pin to a specific commit.
- Neovim >= 0.10.0
- Node.js >= 20
- Claude Code CLI installed and authenticated
- Claude Max subscription (no API keys needed)
{
'username/bonk.nvim',
build = 'cd server && npm install && npm run build',
config = function()
require('bonk').setup()
end,
}git clone https://github.com/username/bonk.nvim ~/.local/share/nvim/site/pack/bonk/start/bonk.nvim
cd ~/.local/share/nvim/site/pack/bonk/start/bonk.nvim/server
npm install && npm run buildThen in your config:
require('bonk').setup()bonk.nvim sets no keybindings by default. Wire them up yourself:
vim.keymap.set('i', '<C-Space>', require('bonk').complete)
vim.keymap.set('i', '<Tab>', require('bonk').accept)
vim.keymap.set('i', '<C-]>', require('bonk').accept_line)
vim.keymap.set('i', '<Esc>', require('bonk').dismiss)| Function | What it does |
|---|---|
complete() |
Trigger a completion at the cursor |
accept() |
Insert the full ghost text into the buffer |
accept_line() |
Insert only the first line of the ghost text |
dismiss() |
Clear ghost text and cancel any in-flight request |
cancel() |
Same as dismiss |
All options with their defaults:
require('bonk').setup({
server = {
path = nil, -- auto-detected from plugin install path
node_binary = 'node', -- path to node executable
log_level = 'warn', -- 'debug' | 'info' | 'warn' | 'error'
idle_timeout = 60, -- seconds before server shuts down with no clients
state_dir = '~/.local/state/bonk/',
},
completion = {
model = 'claude-opus-4-6', -- model for completions
max_tokens = 512, -- max completion length
context_budget = 32768, -- chars of context to send
timeout = 30000, -- ms before request is cancelled
auto_dismiss_on = { -- events that clear ghost text
'InsertLeave',
'BufLeave',
},
},
highlights = {
ghost_text = 'Comment', -- highlight group for ghost text
},
})Ghost text uses the BonkGhost highlight group, linked to Comment by default. Override it in your colorscheme:
vim.api.nvim_set_hl(0, 'BonkGhost', { fg = '#6a6a6a', italic = true })bonk.nvim is a two-process system:
Neovim (Lua) <--HTTP/SSE--> Node.js Server (TypeScript) <--Agent SDK--> Claude
Why two processes? Neovim's Lua runtime is single-threaded. If we called Claude directly from Lua, your editor would freeze while waiting for a response. Instead, the Lua plugin fires off HTTP requests to a local TypeScript server, which handles the async Claude Agent SDK calls and streams results back via Server-Sent Events.
The first Neovim instance spawns the server. Subsequent instances discover it via a lock file at ~/.local/state/bonk/server.lock and reuse the same process. When all Neovim instances disconnect, the server shuts itself down after 60 seconds of idle time.
Inspired by Supermaven's approach. On each completion request, the server assembles context by priority:
- Current file with cursor position (always included)
- Recent edit diffs from the current session (always included)
- Imported/required files resolved from the current file (fill)
- Open buffer contents from other tabs (fill)
- Repo file tree for structural awareness (fill)
Priorities 3-5 are packed greedily until the context budget (default 32K chars) is exhausted.
- You press your trigger keybind
- Lua captures your buffer content, cursor position, and open buffers
- Lua sends a POST to the local server's
/completeendpoint - Server assembles context, calls Claude via the Agent SDK
- Tokens stream back as SSE events
- Lua renders each token as inline ghost text via extmarks
- You accept, accept the first line, or dismiss
bonk.nvim is being built in phases:
- Phase 1: Inline completions -- done. Ghost text streaming, accept/dismiss, context assembly.
- Phase 2: Chat -- a split/float panel for asking questions about your code with conversation history.
Agent mode was considered but intentionally dropped -- Claude Code in a terminal is strictly better for multi-file edits. bonk.nvim focuses on what an editor plugin does best: inline completions and contextual chat.