2026-07-02 Neovim 0.12 Config Fixes and lua_ls Split-Root
What I set out to do
Started as a plain question — what shipped in Neovim 0.11 → 0.12.3 — but I’m already running 0.12.3, so it turned into auditing my nvim config against the 0.12 breaking changes, then fixing whatever :checkhealth flagged, wiring up the dap_repl parser, and finally root-causing the recurring “undefined global vim” diagnostics.
What I actually did
- Real latent bug from 0.12 in
nvim/lua/plugins/treesitter.lua:vim.treesitter.get_parser()now returnsnilinstead of throwing when there’s no parser, soif pcall(get_parser, buf)was truthy even for parser-less buffers and wrongly setindentexpr. Guarded on the returned parser. Confirmed the exact behavior headless (ok=true, parser=nil). nvim-debug/functions/state.lua:vim.lsp.get_active_clients()→get_clients()(deprecated since 0.10), plus a--[[@as string]]cast on thefinddir/findfileresult passed tofnamemodify.- Cleared a 171MB
~/.local/state/nvim/lsp.logthat was tripping the size warning. dap_replparser: on nvim-treesitter’smainbranch it isn’t a normal grammar — thenvim-dap-repl-highlightsplugin registers it via aUser TSUpdateautocmd, so the fix is aconfigfn runningsetup()thenrequire('nvim-treesitter').install({'dap_repl'}). It wouldn’t compile inside the running nvim:tree-sitter buildfailed witherror: tool 'clang' not foundbecause that nvim was launched without the nixclang-wrapperon PATH (/usr/bin/clang→ xcrun → no CLT). Compiled it via a headless nvim from a proper shell instead; the.solands in the shared parser dir.- The “undefined global
vim” mystery: two lua_ls instances with different roots. One roots at~/.configand loads~/.config/.luarc.json(clean — this is the instance themcp-neovim-servertools drive). The other roots at~/.config/nvim(pinned bynvim/.luacheckrc) and never reads the parent.luarc.json, so it flagsvim. Crucially, the diagnostics Claude surfaces come from the claudecode.nvim instance (:51676), a different nvim than the MCP one — sovim.diagnostic.get()looked clean while Claude’s feed showed errors. Proven from~/.cache/lua-language-server/log/file_*.log(rootUri + “Load config from .luarc.json” counts).
What was striking
- The
get_parserchange is a nasty silent one — no error, no warning, just wrong indentation on files without a parser. - Two editors, two language servers, two roots: the “phantom” diagnostics weren’t phantom at all, just from a workspace root I wasn’t querying.
.luarc.jsondeployed to the XDG root only happened to work whenever lua_ls rooted at~/.config; the.luacheckrcmarker quietly created a second root where it didn’t.
Resolution
Fixed the lua_ls split-root in nix/home-manager/modules/neovim.nix: DRY let luarcJson = … deployed to both ~/.config/.luarc.json and ~/.config/nvim/.luarc.json (library paths are absolute, so it works at either root). hm switch + verified headless: an nvim rooted at ~/.config/nvim now reports 0 undefined-global. Shipped as four atomic commits (3b50bdb, 841fa7b, 93666f4, e0e1f0c), all pre-commit hooks green.
Related
- Auto-memory: lua_ls split-root
.luarc.jsondual-deploy; nvim parser builds needing nix clang on PATH. - 2026-06-29 Home Manager News Feature Triage — prior Neovim/HM upkeep session.