Feature request: embed real Neovim as an opt-in input widget (nvim --embed, msgpack-rpc)

Resolved 💬 3 comments Opened May 16, 2026 by g-i-o-r-g-i-o Closed May 16, 2026

Summary

A small proposal: would it be interesting to offer an opt-in input widget that embeds a real nvim --embed --headless instance in place of the prompt, communicating over msgpack-rpc? Users who don't enable it would not notice it exists; users who do would get actual Neovim — their config, plugins, treesitter, macros, persistent undo — as the place where they compose messages.

The current /vim mode (modal keybindings via the input library) is already nice. This is a different layer: instead of emulating a subset of vim, host vim itself.

Why this might be worth considering

The prompt-toolkit-style vim emulation that every agent CLI converges on (Claude Code, Aider, Codex CLI, Gemini CLI) covers basic motions/operators but stops short of plugins, treesitter, LSP completion, persistent undo, and the user's own keymaps. Embedding nvim closes the emulation gap entirely. To my knowledge, no agent CLI does this today.

How @filename and /command keep working

This is the obvious concern: if nvim grabs every keystroke, the @ file picker and the / slash command menu would stop appearing — that would be a regression and not acceptable. Two complementary mechanisms keep the existing UX unchanged:

1. Intercept-before-nvim for the canonical case. Keystrokes pass through a routing layer before being forwarded to nvim. If the user types @ or / as the first character of an empty buffer (row 1, col 1, insert mode), the host does not forward them: it opens the existing completion overlay above the nvim widget. The user navigates with arrows/Tab/Enter as today; the chosen text is injected into the buffer via nvim_input("@src/foo.ts "). For the 90% flow ("open Claude Code, type @file … or /cmd"), the experience is bit-for-bit identical to today.

2. Native nvim completion source for power users. @filename mid-sentence ("please double-check @src/foo.ts") works by registering Claude Code's file index as a standard Neovim completion source — the same mechanism copilot.vim, nvim-cmp, and blink.cmp use. Slash commands become a :CCSlash ex-command with complete=customlist. Users who already live in nvim get fuzzy completion anywhere in the buffer, which is arguably an upgrade.

| Case | Handled by | UX |
|---|---|---|
| @ or / as first char of empty buffer | host overlay (intercept) | identical to today |
| @file / /cmd mid-sentence | nvim completion source | new capability |
| / in NORMAL mode (vim search) | nvim | what a vim user expects |

The keystroke routing layer is the real design decision — more than the rendering or the RPC bridge. It's also where every project in this space (firenvim's g:firenvim_config, vimgym's input policy) has invested its design time.

Prior art — embedding nvim --embed --headless over msgpack-rpc

No agent CLI does this today, but the pattern — host application embeds Neovim as a sub-process, speaks msgpack-rpc, renders the grid into its own UI — is well-trodden:

  • vimgym — Bubble Tea TUI that embeds Neovim for keybinding exercises. Closest analog to an agent CLI: same family of application (terminal TUI), same pattern (nvim --embed --headless + msgpack-rpc via neovim/go-client). Their phrasing: "Neovim runs in --embed mode, so every command works exactly as expected."
  • grovetools/core/tui/components/nvim — a Bubble Tea component already packaged as a drop-in nvim widget with an 8-method API (Init/Update/View/SetSize/Mode/CursorPosition/OpenFile/Save). Proof the pattern is reusable.
  • firenvim — not a TUI but worth citing: it embeds nvim inside browser <textarea> elements (a more hostile host than a terminal). Their host/guest key routing config (g:firenvim_config, takeover, priority) is the reference for the @ / / problem above.
  • libnvc — C++ msgpack-rpc client; reduces a minimal embed to ~5 lines (spawn + nvim_ui_attach + nvim_input). Useful as a protocol reference.

Around this: neovide, neovim-qt, goneovim — the entire nvim GUI client ecosystem uses the same --embed + msgpack-rpc protocol. It is documented (:help ui.txt) and maintained by the Neovim team.

For Node.js, the official neovim client on npm handles the protocol; the bulk of the work would be a TUI component (Ink) that renders the grid and routes keystrokes.

What stays the same

This proposal is strict-additive. It touches one rectangle of the UI (the input). It does not change:

  • the agent loop, tool use, permission/approval flow
  • slash commands, @ mentions, history, /resume, sessions
  • hooks, MCP, sub-agents, settings, output streaming
  • the behavior for anyone who never enables the mode

A user who doesn't toggle it would not know it exists. A user who does keeps every feature they have today.

What I'd love feedback on

  • Is this directionally something the team would consider, or is the current /vim mode the deliberate ceiling?
  • Are there constraints (rendering, IPC, security model) that would make child_process.spawn nvim a non-starter in the Claude Code TUI architecture?
  • Would a small standalone spike (Node + neovim npm + Ink prototype) be useful as a starting reference, or is this better kept as a design conversation first?

Thanks for the project — it's the agent CLI I use daily, and this proposal is offered in that spirit, not as a critique of what's already there.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗