13 KiB
Neovim + Nix setup review
Scope: flake.nix, overlays/, modules/, plugin/*.lua, lua/*, ftplugin/*, CI/workflows, and cross-check against the pinned versions in flake.lock (nixpkgs weekly 241313f4).
Pinned package versions (from current lock)
- neovim
0.12.2 - blink-cmp
1.10.2 - codecompanion-nvim
19.13.0 - nvim-treesitter
0.10.0-unstable-2026-04-03(main-branch rewrite) - nvim-treesitter-textobjects
0-unstable-2026-04-07(main-branch rewrite) - copilot-lua
2.0.3 - render-markdown-nvim
8.12.0-unstable-2026-05-07 - zk-nvim
0.4.7-unstable-2026-03-13 - mini.nvim
0.17.0-unstable-2026-05-12 - quarto-nvim
2.1.0 - otter-nvim
2.14.5 - lspconfig
2.9.0
CRITICAL: Treesitter is currently non-functional
Finding
The nixpkgs nvim-treesitter package is the main-branch rewrite — there is no lua/nvim-treesitter/configs.lua. The whole module in plugin/20_startup.lua lines 212-294 is dead code:
local ok_configs, configs = pcall(require, "nvim-treesitter.configs") -- fails
The working tree already removed the fallback vim.treesitter.start() FileType autocmd (the "fixed treesitter" commit deleted it). Net result: no treesitter highlighting, indentexpr, foldexpr, or textobjects are configured.
Impact
- Syntax highlighting falls back to Neovim's regex-only engine.
- All textobject keymaps (
]a,[a,]f,[f,]e/[e,<leader>x/X, lsp_interop<leader>lm) are inert. foldexpr/indentexprbased folding does nothing.
Fix direction
Rewrite plugin/20_startup.lua for main-branch API:
- FileType autocmd →
vim.treesitter.start()(and optionallyindentexpr/foldexpr). require("nvim-treesitter-textobjects").setup({ move = { set_jumps = true } })+ explicit keymaps usingmove.goto_next_start(query, "textobjects")andswap.swap_next(...).- The non-Nix
ensure_installedblock should setopts.ensure_installedBEFORE the filter (line 278 reads it before line 286 defines it).
Also remove duplicate vim.treesitter.language.register("markdown", ...) between plugin/20_startup.lua and plugin/21_datascience.lua.
CodeCompanion version mismatch
Finding
Config targets features absent in 19.13.0 (present only in ≥19.19.0/main):
| Config usage | Present in 19.13? | Present in main (v19.20.0) |
|---|---|---|
interactions.chat.opts.context_management.editing |
No (flat trigger/enabled only) |
Yes |
interactions.chat.opts.context_management.compaction |
No | Yes |
<leader>aC requiring codecompanion.interactions.chat.context_management.compaction |
RUNTIME ERROR | Works |
slash_commands.share (opts.token = ...) |
No (absent from defaults) | Yes |
adapters.acp.codex.defaults.auth_method = "chatgpt" |
Yes | Yes |
interactions.chat.adapter = { name = ..., model = ... } table form |
Yes | Yes |
Risk
On today's lock (19.13.0): /share is inert, compaction-only keymap throws module-not-found, and editing/compaction tuning is silently ignored. On ≥19.19.0/main: everything works.
Decision needed (BLOCKING)
Choose exactly one:
- A — Upgrade the plugin pin (
overlays/plugins.nixfetch tov19.20.0ormain, bump the lock, and keep the current config). Riskiest change but matches what the config is written for. - B — Downgrade config call sites to match
19.13.0: removeslash_commands.share, removeediting/compactionkeys (or collapse to flattrigger: 0.75), remove or gate<leader>aCon "newer" version. - C — Version-gate the config: keep current code, read the installed version at startup and skip the new features when < 19.19.
I recommend A (the config clearly intends to track upstream main-ish behavior; nix flake update already bumped it to 19.18.0 in a prior session and you only reverted because the nightly was still too old — v19.20.0 is now available).
DEAD / DUPLICATE code
plugin/20_startup.lua— the entireconfigs.setup(opts)block is dead (see Treesitter finding above).plugin/10_keymap.lua:nmap_leader('od', '<Cmd>Neogen<CR>', ...)—neogenplugin is not shipped inspecs/plugins.nix. Mapping errors on press.nmap_leader('fp', '<Cmd>Pick projects<CR>', ...)—MiniExtra.pickers.projectsdoesn't exist in mini.extra; would error.nmap_leader('oS', '<Cmd>lua Config.insert_section()<CR>', ...)—Config.insert_sectionis never defined.vim.lsp.buf.definition()is bound togrd; Neovim 0.11+ defaults includegraliases. Cosmetic, but]d/[dexist on modern LSP config and would be more idiomatic.
plugin/23_editor.lua:my_stylerformatter (callsR -s -e styler::...) is defined but never referenced — dead.
plugin/24_completion.lua:providers.cmp_ris defined in the blink source list but never enabled indefaultorper_filetype; inert.BLINK_VERSION = "v1.4.1"— only consulted in the non-Nix install path; nixpkgs is1.10.2. Pin it to current or drop.get_blink_fuzzy_setting().prebuilt_binary = { force_version = BLINK_VERSION }— singular key is wrong; blink option isfuzzy.prebuilt_binaries(plural). Being skipped in-Nix anyway, but still wrong key.
modules/module/specs/plugins.nix—specs.utils-lazyshipsnvim-dap*andnvim-lintbut there is zero config/tooling that references them in this repo.ftplugin/quarto.lua:- Second top-level
require('quarto').setup()with no args runs after21_datascience.lua's setup and resets it to defaults (nolspFeatures, nocodeRunner). - Top-level
require('quarto')at FileType load also crashes if the quarto plugin isn't installed (e.g. cats off and a.qmd/.quartofile is opened): Neovim detectsquartoft natively in 0.10+.
- Second top-level
plugin/00_options.lua:- Lines 146-163: two back-to-back FileType autocmds that both remove
r/ofromformatoptions. The second references an undefinedaugroupvariable (nil → autocmd is global, happens to still work).
- Lines 146-163: two back-to-back FileType autocmds that both remove
STALE / WRONG options
plugin/10_keymap.lualine 174:require("conform").format({ lsp_fallback = true })lsp_fallbackis the deprecated boolean form ofconform.nvim; should belsp_format = "fallback"(the form already used inplugin/23_editor.luaandftplugin/python.lua). In newer conform this may warn or error.ftplugin/quarto.lua:- Sets
<Plug>RDSendLineand R-style keymaps on all quarto buffers, including Python/Julia chunks. This collides with quarto-runner mappings set in21_datascience.lua. Should gate onvim.bo.filetype == "r"(the ftplugin already imports quarto.runner for python, but the R keys leak).
- Sets
.github/dependapot.yml— filename typo. GitHub expectsdependabot.yml; Dependabot won't run..github/workflows/check.yml:nix developwithout a-ccommand just launches an interactive shell. In CI it does nothing useful (or hangs). Replace withnix develop -c echo okor drop.- Path filter
'modules'only matches the root directory itself; should bemodules/**(or'modules/**'). - Changing
plugin/,lua/,overlays/,ftplugin/, etc. does not trigger CI.
flake.nix/.envrcshellHook:export R_LIBS_SITE=$(strings "$(command -v R)" | grep -oP '/nix/store/[^:]+/library' ...)grep -oP(PCRE) is not available in macOS BSD grep. Onaarch64-darwinthis silently fails →R_LIBS_SITEis empty. Either depend onripgrepregex (strings ... | rg -o '...') or usegsed(GNU sed).overlays/plugins.nix—zk-nvimskip list containszk.pickers.fzf_lua; current zk-nvim package likely doesn't load that regardless, but harmless.modules/module/settings/core.nix—config.settings.nvim_lua_envreferenceslp.tiktoken_corebuttiktoken_coreis not incatPkgs.generalor anywhere else in these files. If there's an extra Lua/tiktoken module, fine; otherwise this option is placeholder dead code.modules/module/settings/hosts.nix— hostm(marimo) is defined withenable = falsebut also configured withpackage,argv0,addFlag. Dead block.
PORTABILITY / DARWIN issues
- Shell hook
grep -oP(above) fails on macOS. mkdir -p "$R_LIBS_USER"fine; butcommand -v Ron macOS returns the wrapper; the wrapper path injection still works.
DEAD WEIGHT (shipped but unused)
catPkgs.rincludespkgs.rnvimserver—rnvimserveris needed by R.nvim only when using the socket transport;21_datascience.luaonly uses vim-slime. Acceptable, butrnvimserveradds to build time. Include if you actually use it? Currently not used.specs.utils-lazyshipsnvim-dap,nvim-dap-ui,nvim-dap-virtual-text,nvim-lint— none of these are referenced anywhere inplugin/orlua/. Consider moving them to a devShell-only cat, or drop them..gitignore*.R— prevents tracking any new.Rfiles.tests/test.Ris already committed so it isn't actively harmful, but it's surprising for a repo whose default cats include R..commandcode/dir is listed in.gitignorebut is in the worktree; fine, but worth cleaning up if it's an artifact.
IMPROVEMENTS given updated packages
catPkgs.markdown— addmarksman(it's the LSP used byrender-markdown.nvimwiki links and configured in LSP). Same binary is needed byrender-markdownfor wiki link ISP.vim.lsp.enableservers configured but binaries missing in PATH:marksman(LSP + render-markdown wiki integration).r_ls(new R language server — package name in nixpkgs is likelyr-languageserverorr_ls; currentcatPkgs.rdoesn't ship either).clangd— not required for this data-science setup; either drop or add toexternal.julials— requireLanguageServer.jlinsettings.lang_packages.juliafor it to be useful.
blink.cmpis1.10.2but config pinsBLINK_VERSION = "v1.4.1"for the non-Nix path. Either drop theBLINK_VERSIONconstant (let MiniDeps track HEAD or the tag pinned in flake) or update it tov1.10.2.conform.nvimalready useslsp_format = "fallback"in23_editor.luaandftplugin/python.lua, but10_keymap.luastill calls the deprecatedlsp_fallback = true. Align tolsp_format = "fallback"..github/workflows/check.yml— add path filters forplugin/**,lua/**,overlays/**,ftplugin/**,modules/**.tests/init.luasmoke-test andtests/test.Rare present but not wired intonix flake check. Add a trivial check that runslua tests/init.luavianix-shell -A ....
CONFLICTS
<leader>up(terminal bracketed paste toggle in10_keymap.lua) conflicts withmini.basics.mappings.option_toggle_prefix = "<leader>u"(paste toggle), which is set up later in20_startup.luavianow(). Result: the user's<leader>upmapping gets overwritten. Portable workaround: remap to<leader>tp(terminal namespace) and keep<leader>tbas alternative — both already mapped in 10_keymap.ftplugin/quarto.luaresets quarto-nvim config (killslspFeatures/codeRunnerset in21_datascience.lua) and injects R plug mappings into non-R quarto chunks.
CLEAN summary for implementer
Immediate (not version-dependent)
- Restore treesitter highlighting + textobjects in
plugin/20_startup.luausing main-branch API. - Remove duplicate
vim.treesitter.language.registerin21_datascience.lua. - Fix
plugin/10_keymap.lua: remove/resolveNeogen,Pick projects,Config.insert_sectiondangling mappings. - Replace deprecated
lsp_fallback = truewithlsp_format = "fallback"inplugin/10_keymap.lua. - Gate
ftplugin/quarto.luato not reset config and to not leak R keys into non-R chunks; guard against missingquartoplugin. - Remove duplicate
formatoptionsautocmds (or at least dedupe). - Dedupe
RNVIM_COMPLDIR/TMPDIRsetup (do it in one place). - Rename
.github/dependapot.ymlto.github/dependabot.yml. - Remove or gate dead host
minhosts.nix. - Remove unused
rsplit? no, irrelevant. - Add
marksmantocatPkgs.markdownand remove orphan LSP entries or ship the binaries. - Remove dead
conformformattermy_stylerand dead blinkcmp_rprovider, or wire them up.
Version-dependent (BLOCKED)
- Reset the CodeCompanion version decision: either pin to
v19.20.0(keep config, fixslash_commands.share, drop the<leader>aCcompatibility shim, keepediting/compaction) OR downgrade config to match19.13.0(removeshare, collapsecontext_management).
CI / packaging
- Fix
nix developusage and path filters in.github/workflows/check.yml. - Replace
grep -oPinflake.nixshellHook with portablerg -oor addgnusedtocatPkgs.alwaysand usegsed. - Wire
tests/init.luaintoflake check.
Verification
nix flake checkon bothaarch64-darwinandx86_64-linux.nix build .#packages.<system>.defaultsucceeds (already does).- Start nvim, verify :TSContext works, treesitter highlighting is on, and
]f/[ftextobjects move. - Open a
.qmdfile with cats off → no ftplugin crash. - Confirm
<leader>upstill toggles bracketed paste. - Confirm
:Pick projectsand:NeogenandConfig.insert_sectionno longer error (or are mapped to valid handlers).