SKILL.md
Neovim config
Use this skill when the task targets a Neovim Lua configuration and the work depends on loading the right checkout, applying plugin-specific wiring truthfully, and validating behavior with the right startup mode.
Use this skill when
- The change touches a Neovim Lua config under
init.lua,lua/,plugin/,after/, orftplugin/. - You are editing or validating plugin management with
vim.pack,lazy.nvim, lockfiles, pinned refs, or plugin bootstrap behavior. - The task involves keymaps, LSP/completion wiring, Blink, Copilot, treesitter, statusline, dashboard, or startup-time behavior.
- A repo checkout or worktree is loading the wrong config, the wrong lockfile, or the wrong plugin state.
- You need Neovim-specific validation rules such as real-TTY startup checks or isolated
XDG_*repros.
Do not use this skill when
- The bug is not specific to a Neovim Lua configuration and needs generic root-cause investigation first. Use
systematic-debugging. - The task is general Lua application code outside a Neovim config surface. Use the repo's normal language workflow or
systematic-debugging. - The main goal is writing or restructuring documentation about the config rather than changing or validating behavior. Use
doc-coauthoring.
Routing boundary
| Situation | Use this skill? | Route instead |
|---|---|---|
| Update plugin specs, keymaps, LSP/completion setup, treesitter, statusline, or startup wiring in a Neovim Lua config | Yes | - |
Validate a worktree checkout, vim.pack migration, or startup regression that depends on loading the right Neovim config |
Yes | - |
| Generic debugging for an app or runtime bug where Neovim config is only incidental | No | systematic-debugging |
| Documentation, onboarding, or explanation work for the config | No | doc-coauthoring |
Inputs to gather
Required before editing
- The real config root and app name (
init.lua, namespace path,NVIM_APPNAME, lockfile location). - The plugin manager in play (
vim.pack,lazy.nvim, or another existing loader) and the exact plugin or runtime seam being changed. - The validation path that matches the symptom: real TTY startup, headless repro, repo formatter/linter, or targeted runtime check.
Helpful if present
- The current pinned repo, branch, tag, or version range for affected plugins.
- The exact startup error,
:messagesoutput, pack review result, or statusline/treesitter symptom. - Whether the repo contains nested
.worktrees/that need to be excluded from repo-wide validators.
Only investigate if encountered
- Blink provider registration state, Copilot client lookup behavior, or
LspAttachreload paths. vim.NILpayloads from decoded JSON.- Extmark index math or Neovim 0.12 capture-list behavior in treesitter queries.
First move
- Identify the config surface, plugin manager, and exact runtime seam the task touches.
- Point
nvimat the target checkout withXDG_CONFIG_HOMEandNVIM_APPNAMEbefore trusting any repro or smoke test. - Choose the smallest truthful validation mode for the symptom: real TTY for UI-sensitive startup, isolated headless repro for scriptable checks, then repo validators only after path scoping is correct.
Workflow
- Confirm the real config root before editing.
- Do not rely on
cdalone; the command must target the intended checkout. - When validating a live
~/.config/<app>checkout, setXDG_CONFIG_HOMEto the parent.configdirectory, not the repo root itself. - Keep the smallest truthful implementation scope; once the wiring is clear, stop extra probing and ship.
- Do not rely on
- Isolate runtime state before reproducing pack or startup behavior.
- For isolated headless repros, isolate
XDG_CONFIG_HOME,XDG_DATA_HOME,XDG_STATE_HOME, andXDG_CACHE_HOMEtogether so synthetic plugins or lockfile entries do not leak into the live config. - When running repo-wide validators, make them ignore nested
.worktrees/**so duplicate checkouts do not poisonselene .orstylua --check ..
- For isolated headless repros, isolate
- Reproduce with the right validation mode for the symptom.
- Use a real TTY for UI-sensitive startup issues such as dashboards, colorschemes, statusline rendering, or first-screen behavior;
nvim --headlesscan miss those states. - For
vim.packmigrations, verify config side effects directly; an installed package or exposed command is not enough to prove the pluginconfigcallback ran.
- Use a real TTY for UI-sensitive startup issues such as dashboards, colorschemes, statusline rendering, or first-screen behavior;
- Implement plugin wiring where the plugin lives, not in a central override maze.
- Prefer plugin-local
main = ...annotations or explicitconfigfunctions over a shared loader override table. - If a plugin keeps causing cascading churn and the user says it is not worth it, remove it cleanly instead of stacking shims.
- Preserve explicit
falsevalues in Lua merges by checking~= nil; do not useand/orternaries for booleans.
- Prefer plugin-local
- Apply plugin-specific rules before assuming the runtime is wrong.
vim.pack: use real upstream repos and verified branches, tags, refs, or version ranges rather than lazy.nvim shorthands; verify the reviewed target ref before trusting pack output.blink.cmp: pin tobranch = "v1"orversion = vim.version.range("^1"), and confirm review or update output is actually comparing against that ref.- Blink + Copilot: reacquire the current attached Copilot client per request; do not cache the client reference.
- Blink provider reloads from
LspAttach: checkblink.cmp.config.sources.providersfirst becauseblink.reload()asserts on unknown providers. - JSON payloads: normalize
vim.NILaftervim.json.decode()before list operations. - Shutdown-time LSP behavior: preload runtime helpers on the LSP setup path instead of assuming
LspAttachwill run at teardown.
- Handle Neovim API edge cases with the runtime's actual index and capture semantics.
- On Neovim 0.12+,
iter_matches()capture slots are lists; unwrap the capture before calling node methods like:range(). vim.ui.progress_status()is already statusline-formatted text; do not double-escape its%markers.- Extmark columns are 0-based and end-exclusive while
string.find()positions are 1-based and inclusive; adjust bracketed status or progress segment ranges accordingly.
- On Neovim 0.12+,
- Re-run the smallest meaningful validation for the touched surface.
- Startup or UI change: open the target checkout in a real TTY and confirm the visual or interactive behavior.
- Headless or scripted change: rerun the repo's existing formatter, linter, or startup smoke checks against the targeted config path.
vim.pack, Blink, or Copilot change: confirm the pinned ref, config callback side effect, and runtime attach or reload behavior that actually motivated the edit.
Outputs
- A Neovim config change or validation plan that targets the correct checkout and runtime paths.
- A plugin-specific fix or diagnosis that respects
vim.pack, Blink, Copilot, treesitter, statusline, or shutdown-time LSP constraints. - A validation result that proves the touched behavior on the right startup mode instead of only on a misleading headless or wrong-checkout path.
Guardrails
- Must not override user keybindings or plugin settings without noting the change.
- Should prefer lazy-loaded plugins when startup performance matters.
- Should verify plugin manager bootstrap before assuming plugin APIs are available.
- Should use the existing plugin manager (lazy.nvim, packer, etc.) rather than introducing a second one.
- May suggest alternative patterns but defer to the user's existing config conventions.
Validation
- Checklist:
- confirm
nvimis loading the intended checkout viaXDG_CONFIG_HOMEandNVIM_APPNAME - use a real TTY for UI-sensitive startup or statusline or dashboard validation
- ignore nested
.worktrees/**before trusting repo-widestyluaorseleneresults - for
vim.pack, verify the config callback side effect or pinned ref behavior, not just package presence - for Blink, Copilot, or LSP changes, verify provider registration, client lookup, or shutdown-time behavior on the real code path you changed
- for treesitter or statusline changes, check capture unwrapping or index conversions against the rendered behavior
- confirm
- Smoke test:
- should trigger: "Fix this Neovim worktree so
vim.packloadsblink.cmpv1 and Copilot completions work again." - should not trigger: "Find the root cause of this failing Lua service test." (→
systematic-debugging)
- should trigger: "Fix this Neovim worktree so
Examples
- "Validate why this Neovim checkout still opens the live config instead of the worktree when I launch
nvim." - "Update my statusline Lua so
vim.ui.progress_status()renders correctly and the extmark highlight range stops clipping the brackets." - "Migrate this plugin spec from
lazy.nvimtovim.pack, pin the right upstream ref, and prove the config callback actually runs."
Reference files
references/runtime-checks.md- compact lookup table for config-targeting,vim.pack, Blink, Copilot, treesitter, and statusline validation checks.