Neovim suggestions with a Rust retrieval engine.
nsug pairs a Lua Neovim plugin with a Rust server that indexes workspaces,
retrieves relevant code, and builds fill-in-the-middle prompts for local or
remote models.
The Neovim plugin lives in this repository. The Rust backend now lives in the separate server repository during local development and is published as prebuilt release binaries for zero-setup installs.
- Plugin repo:
https://github.com/nesharp/nsug-nvim - Server repo:
https://github.com/nesharp/nsug-server
nsug is currently best treated as an experimental or alpha release.
- Cursor-like ghost text inside Neovim
- Workspace-aware retrieval with tree-sitter chunking
- Hybrid context pipeline: recent files, BM25, symbols, embeddings
- Local adapter with model-family-specific FIM prompt builders
- Optional Cursor-backed adapter for remote completion flow
nsug-nvim/
|- lua/nsug/ Neovim plugin modules
|- doc/nsug.txt Vim help
|- doc/architecture.md Architecture notes
|- doc/fim-completion.md FIM prompt flow
`- doc/reports/ Project reports
../nsug-server/
`- Rust server and retrieval engine
Neovim buffer
|
v
lua/nsug/trigger.lua -> lua/nsug/client.lua
|
v
POST /complete and POST /index
|
v
../nsug-server/src/main.rs
|
+-> WorkspaceManager
| +-> TreeSitterIndexer
| +-> HybridRetriever
| `-> LspManager
|
`-> CompletionService -> adapter -> completion response
| Area | What it does |
|---|---|
| Indexing | Chunks Rust, Python, JavaScript, TypeScript, TSX, and Lua |
| Retrieval | Mixes recent-file context, lexical search, symbol search, and embeddings |
| Prompting | Builds FIM prompts for Gemma, Llama, DeepSeek, Qwen, Mistral, and generic models |
| UX | Shows inline ghost text and accepts completions from Neovim |
| Runtime | Keeps per-workspace data under ~/.nsug by default |
- Install the plugin.
lazy.nvim:
{
"nesharp/nsug-nvim",
config = function()
require("nsug").setup({
server = {
host = "127.0.0.1",
port = 9123,
auto_start = true,
mode = "auto",
},
trigger = {
debounce_ms = 150,
enabled = true,
filetypes = {},
max_lines = 1000,
},
ui = {
highlight_group = "Comment",
accept_key = "<Tab>",
accept_word_key = "<C-]>",
dismiss_key = "<Esc>",
},
cache = {
enabled = true,
ttl_ms = 30000,
},
debug = false,
})
end,
}packer.nvim:
use({
"nesharp/nsug-nvim",
config = function()
require("nsug").setup({
server = {
host = "127.0.0.1",
port = 9123,
auto_start = true,
mode = "auto",
},
})
end,
})- Configure the plugin:
require("nsug").setup({
server = {
host = "127.0.0.1",
port = 9123,
auto_start = true,
mode = "auto",
},
trigger = {
debounce_ms = 150,
enabled = true,
filetypes = {},
max_lines = 1000,
},
ui = {
highlight_group = "Comment",
accept_key = "<Tab>",
accept_word_key = "<C-]>",
dismiss_key = "<Esc>",
},
cache = {
enabled = true,
ttl_ms = 30000,
},
debug = false,
})-
Create
~/.config/nsug/config.jsonfor your model endpoints. -
Open a project and start typing in insert mode.
On first start the plugin downloads the matching nsug-server release binary,
verifies its checksum, caches it under stdpath("data")/nsug/bin/, and then
starts it automatically.
- The plugin is designed for
127.0.0.1by default. Treat remote hosts as less trusted unless you control the network and server. - Completion requests can include the current buffer context, the workspace root, a shortlist of recent files, and the content of other open files from the same workspace.
- If you point
nsugat a remote model endpoint or remote server, your code may leave your machine. - The plugin auto-downloads the server binary in
prodandautomodes, verifies its checksum, and stores it in Neovim's data directory. - Read
SECURITY.mdbefore usingnsugin sensitive or proprietary codebases.
The local adapter reads config from ~/.config/nsug/config.json and falls back
to environment variables when needed.
Example:
{
"data_dir": "~/.nsug",
"llm": {
"api_url": "http://localhost:1234/v1/completions",
"model": "codegemma-7b",
"temperature": 0.2,
"max_new_tokens": 128,
"top_p": 0.9
},
"embedding": {
"api_url": "http://localhost:1234/v1/embeddings",
"model": "text-embedding-nomic-embed-text-v1.5"
}
}Useful env vars:
LLM_API_URLLLM_MODELOPENAI_API_KEYPROMPT_FORMATEMBEDDING_API_URLEMBEDDING_MODELNSUG_DATA_DIR
server.mode = "auto"prefers a local dev binary when one is configured or detected, otherwise it downloads the released server binary automaticallyserver.mode = "prod"always uses the downloaded release binaryserver.mode = "dev"always starts a local binary fromserver.cmdorserver.bin
Example dev setup:
require("nsug").setup({
server = {
mode = "dev",
cmd = { "../nsug-server/target/debug/nsug-server" },
},
})Useful commands:
:NsugInstallServerpreloads the production binary into the local cache:NsugStatusshows the resolved server mode, binary path, and last startup errorcargo run -- --adapter localuses the local retrieval and prompting stackcargo run -- --adapter cursoruses the Cursor adapter pathcargo run -- --cleanclears the local runtime data directory before boot
Server repo:
- GitHub:
https://github.com/nesharp/nsug-server - local path during development:
../nsug-server - release workflow:
https://github.com/nesharp/nsug-server/blob/main/.github/workflows/release-server.yml - CI workflow:
https://github.com/nesharp/nsug-server/blob/main/.github/workflows/ci.yml
Server checks:
cd ../nsug-server
cargo check
cargo test
cargo clippy --all-targets --all-features -- -D warningsLua sync for the local dev config:
cp lua/nsug/*.lua ~/.config/nvim-dev/lua/nsug/Launch the dev Neovim profile:
NVIM_APPNAME=nvim-dev nvimdoc/nsug.txt- Vim helpdoc/architecture.md- component map and request flowdoc/fim-completion.md- model-family prompt behaviordoc/reports/production-readiness.md- project review notesSECURITY.md- supported versions and reporting policyCONTRIBUTING.md- local workflow and contribution rulesCODE_OF_CONDUCT.md- community expectations