Neovim Plugin

sonny-neovim is an AI code completion plugin for Neovim. Unlike the desktop and VS Code clients, it does not attach to the shared supervisor: it runs its own sonny-daemon and focuses on inline completion rather than agent sessions.

What it does

  • Ghost text suggestions — completions appear inline as you type.
  • Multiple LLM providers — OpenAI, Anthropic, Ollama, Gemini, Groq, Azure, Bedrock.
  • Treesitter integration — uses Neovim’s built-in vim.treesitter to extract functions, types, and variables, plus the exact construct at the cursor (for example return_statement) and its ancestors, injected into the completion for structural awareness.
  • Built-in Neovim feature support — running LSP clients (vim.lsp), diagnostics (vim.diagnostic), quickfix and loclist state, and buffer/version info, injected as an ## Editor Context section.
  • Agent instruction files — reads your repo’s AGENTS.md / CLAUDE.md (provider-aware) and injects them into every completion.
  • Codebase conventions — injects .editorconfig style settings so generated code matches the project.
  • Language best practices — per-language guidance for Go, Python, JS/TS, Rust, Lua and others is baked into completions.
  • LSP integration — gathers document symbols and diagnostics from language servers (gopls, pyright, tsserver, rust-analyzer, clangd, …).
  • Documentation lookup — fetches docs from go doc, pydoc, and more.
  • Linter integration — golangci-lint, ESLint, Pylint, Clippy, and more.
  • Pre-commit support — parses and runs pre-commit hooks.

Requirements

  • Neovim 0.8+
  • Go 1.27+ (for building the daemon)
  • Network access to devnw.dev/llm (the backend module), using your Go credentials in ~/.netrc

Installation

The Neovim integration is commercial software. Install the package provided through your authorized CodePros distribution channel, then ensure the daemon is on your PATH or set daemon_path in setup(). See Licensing and access .

Configuration

require('sonny').setup({
    -- Daemon
    daemon_path = 'sonny-daemon',   -- path to daemon binary
    pack_file = nil,                -- optional: path to a recipe YAML
    request_timeout_s = 300,        -- fail outstanding requests after this long

    -- LLM
    provider = 'openai',
    model = 'gpt-5-mini',

    -- Completion behaviour
    auto_trigger = true,
    trigger_delay_ms = 150,         -- debounce
    trigger_min_chars = 3,
    max_tokens = 256,
    num_suggestions = 1,

    -- Context gathering
    include_related_files = true,
    include_open_buffers = true,
    use_treesitter = true,
    max_related_files = 5,
    max_lines_per_related = 50,
    max_context_lines = 100,
    use_lsp = true,

    -- Editor context
    include_lsp_context = true,     -- running clients + capabilities + folders
    include_diagnostics = true,     -- vim.diagnostic at cursor + buffer counts
    include_quickfix = true,
    include_nvim_context = true,

    disabled_filetypes = {
        'TelescopePrompt', 'neo-tree', 'NvimTree', 'lazy', 'help',
    },

    mcp_servers = {},               -- see lua/sonny/config.lua for examples
    debug = false,
})

max_context_lines is the budget that matters most in practice: it caps the total context lines sent to the model, so raising max_related_files beyond what that budget allows just changes what gets evicted, not how much you send.

Keybindings

KeyModeAction
<Tab>InsertAccept full suggestion
<C-Right>InsertAccept next word
<M-Right>InsertAccept to end of line
<C-]>InsertNext suggestion
<C-[>InsertPrevious suggestion
<Esc>InsertDismiss suggestions
<C-Space>InsertManual trigger
<leader>ccNormalToggle plugin

All are configurable through keymaps, and :SonnyRebindKeys refreshes them from config without restarting Neovim.

Commands

CommandDescription
:SonnyEnableEnable the plugin
:SonnyDisableDisable the plugin
:SonnyToggleToggle the plugin on/off
:SonnyStatusShow plugin status
:SonnyCompleteTrigger completion manually
:SonnyPack <path>Switch recipe
:SonnyProvider <provider> [model]Switch LLM provider
:SonnyModel <model>Switch LLM model
:SonnyDoc [symbol]Look up documentation
:SonnyDocSearch <query>Search documentation
:SonnyLint [output]Run linter (diagnostics/quickfix/loclist)
:SonnyLintFixRun linter with auto-fix
:SonnyLintConfigShow linter configuration
:SonnyPreCommit [action]Pre-commit hooks (info/run/all)
:SonnyEditorConfigShow EditorConfig settings
:SonnyRebindKeysRefresh keybindings from config
:SonnyMCP [status|tools|connect|disconnect] [server]MCP server management
:SonnyMCPCall <server> <tool> [json_args]Call an MCP tool

Lua API

local sonny = require('sonny')

-- Core
sonny.complete()                -- request completion
sonny.accept()                  -- accept current suggestion
sonny.accept_partial('word')    -- accept next word
sonny.accept_partial('line')    -- accept to end of line
sonny.next_suggestion()
sonny.prev_suggestion()
sonny.dismiss()
sonny.has_suggestion()

-- Configuration
sonny.enable(); sonny.disable(); sonny.toggle(); sonny.status()
sonny.set_pack(path)
sonny.set_provider(name, model)
sonny.set_model(name)
sonny.rebind_keys(keymaps)

-- Documentation
sonny.fetch_doc(symbol, callback)
sonny.search_docs(query, callback)
sonny.doc_at_cursor()

-- Linting
sonny.lint(output)
sonny.lint_fix()
sonny.run_linter(opts, callback)
sonny.get_linter_config(opts, callback)
sonny.run_precommit(opts, callback)
sonny.get_editorconfig(opts, callback)

Source of truth

  • sonny-neovim/README.md
  • sonny-neovim/lua/sonny/config.lua (defaults and MCP examples)