# nvim-agentic A Claude Code plugin that turns the user's running Neovim into a first-class collaborator. It assumes two things are already wired up: 1. **`mcp-neovim-server`** reaching the running nvim's RPC socket (default `/run/user/1000/nvim.sock`, created by NixVim's `extraConfigLuaPre` `serverstart` at editor startup). The plugin ships a `.mcp.json` that points the `neovim` MCP server at the `mcp-session-pool` over Streamable-HTTP (`pool.localhost:12010/p/neovim/mcp`); the pool fronts a supervised stdio→HTTP bridge. Tools surface as `vim_*`. 2. **`coder/claudecode.nvim`** loaded inside nvim, with `a*` keymaps wired (toggle, focus, send, accept/deny diff). This plugin doesn't ship those — it depends on them and ties them together with one agent and three skills. ## Connection path ```text Claude Code session └─ .mcp.json → http://pool.localhost:12010/p/neovim/mcp (Streamable-HTTP) └─ mcp-session-pool (:12010, M=1 session pooler, /repin endpoint) └─ nvim-mcp-bridge — supergateway (:12016, --stateful) └─ mcp-neovim-server (stdio child) └─ /run/user/1000/nvim.sock (nvim msgpack-RPC) └─ the running Neovim ``` No MetaMCP in this path: nvim is ephemeral and MetaMCP never re-dials a restarted upstream. The pool *does* re-establish (a fresh `initialize`), so pool→bridge self-heals. Recovery is event-driven — a `systemd.path` watching the nvim socket fires a oneshot that POSTs `/repin` to the pool when the socket (re)appears; no polling. The pool and bridge run on emmett as systemd services under user `oleks`, so the per-user socket is directly reachable. If `vim_*` tools are missing: socket exists? `systemctl status nvim-mcp-bridge`? `http://127.0.0.1:12010/pools/neovim` pinned? session restarted since the wiring landed? ## Layout ```text nvim-agentic/ ├── .claude-plugin/plugin.json # manifest + userConfig (socket, config path) ├── agents/ │ └── companion.md # the nvim-companion agent identity └── skills/ ├── editor-introspect/ # read live state via the vim_* MCP tools ├── editor-act/ # drive nvim safely (open, jump, toggle, run) └── claude-code-handoff/ # delegate buffer edits to the in-editor Claude ``` ## Agent `companion` — answers questions about the *running* nvim ("what's bound to `ff`?", "is lualine actually using catppuccin-mocha?") and acts on it ("open neovim.nix at the lualine block"). It reads the declarative NixVim config as the source-of-truth for *why* things are set up the way they are, and the live editor for *what is actually loaded right now*. ## Skills - **`editor-introspect`** — read-only queries against the live nvim (keymaps, buffers, options, diagnostics, plugins, messages, cursor, selection). - **`editor-act`** — safe driving: open files, jump to definitions, trigger user keymaps, toggle UI. Does **not** edit buffer contents. - **`claude-code-handoff`** — when the work is "change code in this buffer," hand it to the in-editor Claude Code session so the user gets a diff to accept or reject inline. ## Why split it three ways The companion's three jobs have different blast radii: - *Reads* are free; do them eagerly. - *Edits to navigation/UI* are cheap to undo; do them when asked. - *Edits to code* deserve a diff and human review; route them through the inner Claude that already has the right UX for that. The skills enforce that separation so the agent doesn't drift into running `nvim_buf_set_text` directly when it should be sending to the Claude Code split. ## Configuration - **`nvim_socket`** — default `/run/user/1000/nvim.sock`. Where the running nvim listens; must match `NVIM_SOCKET_PATH` in the `nvim-mcp-bridge` service that `mcp-neovim-server` runs under. - **`config_path`** — default `/home/oleks/projects/servers/emmett/nixos/neovim.nix`. The declarative NixVim source the companion cites from. ## License MIT.