Neovim plugin for lup — AI-powered code summarisation and semantic lookup.
When you open a file, lup silently summarises it in the background. When you select a term or symbol, lup searches your project's indexed summaries and shows you where it's used and what it means — without leaving your editor.
- Neovim 0.9+
- The
lupbinary installed and available on$PATH→ github.com/wingitman/lup - An OpenAI-compatible API server running locally or in the cloud (e.g. Ollama, LM Studio, OpenAI)
{
"wingitman/lup.nvim",
event = "BufReadPost",
config = function()
require("lup").setup()
end,
}use {
"wingitman/lup.nvim",
config = function()
require("lup").setup()
end,
}Plug 'wingitman/lup.nvim'Then in your init.lua:
require("lup").setup()- Install the
lupbinary (see lup releases):
# Build from source (requires Go)
git clone https://github.com/wingitman/lup
cd lup
go build -o ~/.local/bin/lup ./cmd/lup- Configure your LLM endpoint in
~/.config/lup/config.toml(see lup.toml.example):
[llm]
base_url = "http://localhost:11434/v1" # Ollama
chat_model = "qwen2.5-coder:7b"
embed_model = "nomic-embed-text"-
Add lup.nvim to your Neovim config (see full config below).
-
Open any
.go,.py,.js,.ts,.jsx, or.tsxfile — lup will summarise it in the background automatically. -
Select a word or phrase in visual mode and press
<leader>luto look it up across your indexed project.
require("lup").setup({
-- Path to the lup binary. Defaults to "lup" (assumes $PATH).
bin = "lup",
-- Automatically summarise files in the background when opened.
-- Only runs for supported file types: .go .py .js .ts .jsx .tsx
auto_summarise = true,
-- Keymap to trigger a lookup.
-- Normal mode: looks up the word under the cursor.
-- Visual mode: looks up the selected text.
-- Set to false to disable and manage keymaps yourself.
lookup_keymap = "<leader>lu",
-- Floating window border style.
-- Valid values: "none", "single", "double", "rounded", "solid", "shadow"
border = "rounded",
-- Floating window transparency (0 = opaque, 100 = fully transparent).
winblend = 0,
-- Number of RAG results to show in the lookup float.
-- 0 = defer to top_k in lup's own config.toml (recommended).
top_k = 0,
})| Command | Description |
|---|---|
:LupSummarise |
Summarise the current file in the background |
:LupSummariseForce |
Force re-summarise even if already done |
:LupLookup [text] |
Look up text (defaults to visual selection) |
:LupIndex |
Re-embed all stored summaries into the vector index |
:LupStatus |
Show all summarised files for the current project |
| Mode | Key | Action |
|---|---|---|
| Normal | <leader>lu |
Look up word under cursor |
| Visual | <leader>lu |
Look up selected text |
The lookup float closes with q, <Esc>, <Enter>, or by moving focus away.
open file
└─ lup summarise <file> (background job, no editor interruption)
└─ tree-sitter extracts functions/classes
└─ LLM generates summary JSON
└─ stored in .lup/summaries/
└─ embedded and indexed in .lup/index.db
select text → <leader>lu
└─ lup lookup --json "<text>"
└─ LLM embeds the query text
└─ sqlite-vec nearest-neighbour search over .lup/index.db
└─ top results hydrated from .lup/summaries/
└─ displayed in a floating window
The lup binary does all the heavy work as a subprocess. lup.nvim is a thin wrapper — it never loads a model or does any computation inside Neovim.
lup stores its data in a .lup/ directory at your project root:
.lup/
├── summaries/ ← JSON summaries (safe to commit)
├── index.db ← vector index (exclude from git, cheap to rebuild)
└── config.toml ← optional per-project config overrides
Add to your project's .gitignore:
.lup/index.db
.lup/index.db-shm
.lup/index.db-wal
Override these in your colorscheme to customise the float appearance:
| Group | Default link | Used for |
|---|---|---|
LupNormal |
NormalFloat |
Float background |
LupBorder |
FloatBorder |
Float border |
LupTitle |
Title |
Float title bar |
LupDim |
Comment |
Metadata / distance scores |
MIT