| name | mise-cookbook-neovim |
| description | End-to-end recipe for a Neovim configuration managed by mise — the vim.env.PATH prepend pattern, LSPs installed via mise (npm:pyright, aqua:gopls, etc.), conform.nvim for formatters, and the mise-managed "editor as a tool" approach. Use when setting up a modern Neovim config that plays nicely with mise-managed projects. |
Cookbook — Neovim config managed by mise
A complete setup where Neovim sees mise-managed tools for every project automatically. The host's mise.toml pins Neovim itself plus the LSPs and formatters; a small init.lua snippet makes Neovim PATH-aware of mise shims; conform.nvim handles formatting.
Who this is for
- Neovim users who want LSPs pinned alongside language runtimes.
- People who already have a Neovim config and want to make it mise-aware.
- "Editor as a tool" advocates — your editor is a dev dependency, not a system install.
Who this isn't for
- VSCode / JetBrains users — see
mise-cookbook-node-nextjs plus mise-vscode-integration / mise-jetbrains-integration instead.
- Pure vim (not Neovim) users — the LSP story differs substantially.
Two layers — global + per-project
There are two mise.toml files in play:
- Global (
~/.config/mise/config.toml) — pins Neovim itself and global LSPs/formatters.
- Per-project — each project's
mise.toml pins its language runtime. Neovim inherits tools via the shims-on-PATH pattern.
The global ~/.config/mise/config.toml
[tools]
"aqua:neovim/neovim" = "0.10"
"npm:pyright" = "latest"
"npm:typescript-language-server" = "latest"
"npm:vscode-langservers-extracted" = "latest"
"aqua:golang/tools/gopls" = "latest"
"aqua:rust-lang/rust-analyzer" = "latest"
"aqua:artempyanykh/marksman" = "latest"
"aqua:LuaLS/lua-language-server" = "latest"
"pipx:ruff" = "latest"
"aqua:mvdan/gofumpt" = "latest"
"npm:prettier" = "latest"
"aqua:JohnnyMorganz/stylua" = "latest"
"aqua:mvdan/sh" = "latest"
"pipx:shellcheck-py" = "latest"
"aqua:BurntSushi/ripgrep" = "latest"
"aqua:sharkdp/fd" = "latest"
"aqua:sharkdp/bat" = "latest"
"aqua:eza-community/eza" = "latest"
The Neovim init.lua snippet
Put this before any plugin loader or LSP config:
local mise_shims = vim.fn.expand("~/.local/share/mise/shims")
if vim.fn.isdirectory(mise_shims) == 1 then
vim.env.PATH = mise_shims .. ":" .. vim.env.PATH
end
That's the only mise-specific piece. Everything else is standard Neovim config.
LSP setup with nvim-lspconfig
local lspconfig = require("lspconfig")
lspconfig.pyright.setup({})
lspconfig.ts_ls.setup({})
lspconfig.gopls.setup({
settings = {
gopls = {
gofumpt = true,
staticcheck = true,
},
},
})
lspconfig.rust_analyzer.setup({
settings = {
["rust-analyzer"] = {
cargo = { features = "all" },
checkOnSave = { command = "clippy" },
},
},
})
lspconfig.marksman.setup({})
lspconfig.lua_ls.setup({
settings = {
Lua = {
workspace = { library = vim.api.nvim_get_runtime_file("", true) },
diagnostics = { globals = { "vim" } },
},
},
})
No cmd = { "/abs/path/to/pyright" } hacks — lspconfig finds each LSP from PATH, and PATH has mise shims prepended.
Formatting via conform.nvim
require("conform").setup({
formatters_by_ft = {
python = { "ruff_format", "ruff_fix" },
go = { "gofumpt" },
javascript = { "prettier" },
typescript = { "prettier" },
javascriptreact = { "prettier" },
typescriptreact = { "prettier" },
json = { "prettier" },
yaml = { "prettier" },
markdown = { "prettier" },
lua = { "stylua" },
},
format_on_save = {
timeout_ms = 500,
lsp_fallback = true,
},
})
conform.nvim also finds formatters via PATH. All are mise-installed.
Linting via nvim-lint
require("lint").linters_by_ft = {
python = { "ruff" },
sh = { "shellcheck" },
bash = { "shellcheck" },
}
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
callback = function() require("lint").try_lint() end,
})
What this gives you
- Project-aware LSPs —
gopls in project A uses the Go pinned by project A's mise.toml. Switch projects, gopls auto-switches Go versions. Zero config.
- Pinned editor tooling — the whole team running the same LSP / formatter versions means no "ruff formatted differently" noise in diffs.
- One install command —
mise install pulls Neovim, all LSPs, all formatters, all linters.
- No mason.nvim — you don't need mason's download layer because mise is the layer. Saves a whole plugin.
First-run walkthrough
curl https://mise.run | sh
eval "$(mise activate zsh)"
vim ~/.config/mise/config.toml
mise install
cd ~/projects/myapp
nvim
Mason.nvim interop (if you want both)
If you already have mason and don't want to rip it out:
local mison_bin = vim.fn.stdpath("data") .. "/mason/bin"
if vim.fn.isdirectory(mison_bin) == 1 then
vim.env.PATH = mise_shims .. ":" .. mison_bin .. ":" .. vim.env.PATH
end
Now mise shims win when a tool is available via both. Slow migration path: move one LSP at a time from mason to mise, uninstall from mason.
Common gotchas
- Launching Neovim via Alfred/Spotlight/Raycast → Desktop launchers skip shell rc. The
vim.env.PATH line in init.lua is essential for this case. Don't skip it.
:checkhealth lsp reports "pyright not found" → PATH isn't set correctly or mise shims are missing pyright. Verify which pyright in a shell, then :echo $PATH inside Neovim.
gopls finds the wrong Go version → gopls uses go version to resolve. mise shims handle this per-project automatically. If you see drift, check mise current go in the project dir.
- Formatter runs but diff looks stale → conform.nvim's
format_on_save is async; if you save-and-quit in one motion, you may beat the formatter. Use :Format then :w.
- Multi-root workspaces → lspconfig picks one root per buffer. That's an lspconfig limitation, not mise's.
TSInstall <lang> needs a C compiler → Treesitter compiles parsers from C. Install aqua:llvm/llvm-project globally or rely on system clang.
- Emacs / Helix users → Same pattern. Set
exec-path/PATH to include mise shims early in init.
See also
mise-neovim-integration — the underlying vim.env.PATH pattern in detail.
mise-ide-activation — cross-IDE overview.
mise-pathing-and-shims — how shims work.
mise-lang-node-packages — why npm: is fine for LSPs.
- mise neovim cookbook:
mise.jdx.dev/mise-cookbook/neovim.html.
- conform.nvim:
github.com/stevearc/conform.nvim.
- nvim-lspconfig:
github.com/neovim/nvim-lspconfig.