NVIME is a pure Lua Neovim configuration built around Neovim 0.12+, the native vim.pack package manager, built-in LSP, and a compact plugin set.
Install Nix with nix-command and flakes enabled, and Git for cloning. Back up
any existing ~/.config/nvim before installing:
git clone https://github.com/MrZLeo/nvime ~/.config/nvim
cd ~/.config/nvim
nix profile add .
nvimThe default flake.nix output installs Neovim, search tools, language
servers, formatters and the Tree-sitter CLI. Supported systems are
aarch64-darwin, aarch64-linux and x86_64-linux.
Nix manages tools only. Neovim still reads your editable ~/.config/nvim,
and vim.pack manages plugins using nvim-pack-lock.json. Missing plugins and
Blink native libraries may be downloaded on first source-install startup.
If an older executable is still selected, check command -v nvim and your PATH;
installing the flake does not rewrite shell configuration.
External prerequisites are unchanged:
- Git, curl and tar for plugin/parser operations.
- A system C/C++ toolchain for parser compilation and C/C++ projects, such as Xcode Command Line Tools on macOS.
- Rust tooling and
rust-analyzer, for example through rustup, for Rust projects. - A TeX installation providing tools such as
latexmkandlatexindentfor LaTeX. - Project-specific runtimes and dependencies as needed.
Tool versions come from flake.lock. From the checkout:
cd ~/.config/nvim
nix flake update
nix profile list
nix profile upgrade nvimReplace nvim with the actual entry name shown by nix profile list. Updating
the lock alone does not change installed tools; upgrade the profile to apply it.
Lua configuration edits do not need a Nix rebuild. Plugin updates remain separate
via :PackUpdate (confirm updates, then automatically commit the plugin lockfile).
Install Neovim 0.12+ and the tools you need from flake.nix through
your preferred package manager, then clone the configuration and run nvim.
arch-install.sh remains available as an optional Arch helper;
check its package choices against your needs.
Download a matching artifact from the latest release. These packages contain the configuration, plugins and Blink libraries, not Neovim or the LSP/tool collection. Install those separately with Nix or your preferred package manager. Nix itself is not required to use a release bundle.
Tagged releases publish prebuilt artifacts for Linux and macOS:
- Linux x86_64 / ARM64 (glibc):
.tar.gz,.deb,.rpm - macOS Apple Silicon:
.dmg
The .tar.gz and .dmg bundles contain:
install.sh: installs the packaged config and downloaded pluginspayload/config/nvim: the NVIME configpayload/data/nvim/site/pack/core/opt:vim.packplugins and matching Blink native librariesblink-native.json: target platform, upstream releases, revisions and native-file hashes
Installation defaults:
- Config:
${XDG_CONFIG_HOME:-$HOME/.config}/nvim - Data:
${XDG_DATA_HOME:-$HOME/.local/share}/nvim
To install a release bundle from .tar.gz or .dmg:
- Download the matching release artifact for your platform.
- Extract or open it.
- Run the installer:
./install.sh
- Start Neovim:
nvim
Linux package manager artifacts install the same bundle under
/usr/share/nvime and expose nvime-install on PATH. They do not overwrite
user config during apt or dnf installation. The packages recommend Neovim
but do not require the distro package name, because nvime-install checks the
actual nvim binary on PATH.
Debian/Ubuntu:
sudo apt install ./nvime-*.deb
nvime-installFedora/RHEL:
sudo dnf install ./nvime-*.rpm
nvime-installThe installer creates timestamped backups before replacing an existing install.
It also checks that nvim is already installed and that the detected version is
0.12 or newer. Native bundles also require Git and a matching OS/architecture.
Useful installer options:
./install.sh --config-dir /path/to/nvim./install.sh --data-dir /path/to/share/nvim./install.sh --no-backup
Releases download upstream precompiled binaries, not locally compiled Rust
outputs or libraries copied from the Nix store. The plugin checkouts must match
nvim-pack-lock.json; their commits must have matching upstream release tags.
Downloads are verified against GitHub asset SHA-256 digests and, for cmp, the
upstream checksum file.
Files are installed at the plugins' normal lookup locations (.so on Linux,
.dylib on macOS):
blink.cmp/target/release/:libblink_cmp_fuzzylibrary,.sha256andversion.blink.pairs/lib/:libblink_pairs_parserlibrary suffixed with the first seven characters of the locked commit.blink.lib: its checkout is also lock-checked; no standalone binary is fetched.
Plugin Git metadata is retained, but Cargo build caches are excluded. The first
packaged Blink startup needs neither a native download nor a Rust compiler.
Later plugin updates retain the plugins' normal download behavior. Tree-sitter
parsers are not bundled; use :TSSyncParsers when needed.
Plugin specs live in plugin/*.lua and are installed by vim.pack. Pinned revisions are stored in nvim-pack-lock.json.
Example plugin spec:
vim.pack.add({
{
src = "https://github.com/user/repo",
version = vim.version.range("*"),
},
})Useful maintenance commands:
:PackUpdateupdates plugins with the normalvim.packconfirmation buffer: use:writeto apply updates and automatically commitnvim-pack-lock.json, or:quitto cancel without committing. No update means no commit.:lua vim.pack.update()keeps the original behavior without automatic commits.:TSSyncParsersinstalls or updates the Tree-sitter parsers listed in plugin/02-treesitter.lua.
:PackUpdate commits only the config directory's lockfile, even when Neovim's
working directory is another project. Its Git checks and commit ignore inherited
repository-location variables such as GIT_DIR, GIT_WORK_TREE and GIT_INDEX_FILE.
Other staged and unstaged files are left alone. It uses the message
chore(plugins): update lockfile, respects Git hooks and signing settings, and
never pushes. The commit captures the whole current lockfile, including any
earlier unstaged lockfile changes.
Automatic commits require a Git checkout with a tracked lockfile. Detached HEAD,
unresolved conflicts, in-progress merge/rebase/cherry-pick/revert operations and
an already-staged lockfile are refused. If applying updates or committing fails,
review the error and commit the lockfile manually; successful plugin updates are
not rolled back. Release-bundle installs without Git tracking can keep using
:lua vim.pack.update().
| Key Combination | Mode | Description |
|---|---|---|
<C-h/j/k/l> |
Normal | Navigate between windows |
<C-h/j/k/l> |
Terminal | Navigate between windows from terminal |
<C-w>k |
Normal | Split window above |
<C-w>h |
Normal | Split window left |
<C-w>j |
Normal | Split window below |
<C-w>l |
Normal | Split window right |
<BackSpace> |
Normal | Clear search highlighting |
<Space><Space> |
Normal | Save file |
- |
Normal | Open Oil file explorer |
<Leader>ff |
Normal | Find files |
<Leader>fg |
Normal | Live grep |
<Leader>fb |
Normal | List buffers |
<Leader>fh |
Normal | Help tags |
<Leader>o |
Normal | Toggle outline sidebar |
gD |
Normal | Go to declaration |
gd |
Normal | Go to definition (telescope) |
K |
Normal | Show hover information |
gi |
Normal | Go to implementation (telescope) |
gr |
Normal | Find references (telescope) |
<Space>rn |
Normal | Rename symbol |
<Space>f |
Normal | Code action |
<Space>l |
Normal | Show diagnostics (telescope) |
:Outlinetoggles the symbol outline window.:Cleardeletes all hidden loaded buffers.:Spelltoggles spell checking.:PackUpdateupdates plugins and automatically commits only the lockfile after confirmation.:TSSyncParserssyncs the configured Tree-sitter parser set.
LSP configuration is centralized in plugin/zz-lsp.lua.
Current enabled servers:
local lsp_servers = {
"clangd",
"lua_ls",
"tsc",
"ruff",
"ty",
"taplo",
"texlab",
"neocmake",
"nixd",
"rust_analyzer",
}To add or remove a server, update that list and adjust any server-specific settings in the same file.
The flake supplies these servers except rust_analyzer, which remains external.
tsc requires TypeScript 7+; Nix formatting uses nixd with nixfmt, and Lua
formatting uses StyLua.
Current defaults include:
- Telescope-backed definition, implementation, reference, and diagnostics pickers
- Hover and floating diagnostics
- Inlay hints
- Format-on-save, except for filetypes explicitly skipped in plugin/zz-lsp.lua
CI uses nix develop .#ci for tools pinned by flake.lock. Quality checks live
in .github/workflows/checks.yml, reused by releases.
The default Nix tool collection, Lua configuration and vim.pack remain unchanged.
Run the :PackUpdate integration tests with Neovim 0.12+ and Git:
bash scripts/test-pack-update.shThese tests use temporary config/data directories and local plugin repositories; they need no network and do not update your plugins or commit to this checkout.
Run native startup and packaging checks locally with:
nix develop .#ci --command bash scripts/ci-smoke.sh
ARTIFACT_OUTPUT_DIR=/tmp/nvime-artifacts \
nix develop .#ci --command bash scripts/ci-package.shBoth scripts use temporary HOME/XDG directories, not your installed config. Preparation needs network access; final native tests block downloads/builds.
To enable the repository's pre-commit hook, run:
bash scripts/install-git-hooks.shThe hook runs StyLua on staged Lua files. If formatting changes a file, the commit stops so the result can be reviewed and staged before retrying. It also refuses to format partially staged Lua files, preserving unstaged changes.
GitHub Actions builds and publishes release artifacts for tags matching v*.*.*.*.
Release tags follow this format:
v<neovim-major>.<neovim-minor>.<neovim-patch>.<nvime-revision>- Example:
v0.12.5.1
The first three fields match Neovim pinned in flake.lock. The final field is
the NVIME revision for that version and starts at 0.
The release pipeline does three things:
- Runs native smoke tests on
ubuntu-24.04(x86_64),ubuntu-24.04-arm(ARM64), andmacos-15(ARM64), using Nix-provided tools. - Builds artifacts, extracts each, verifies hashes, installs into a fresh HOME, and calls the cmp Rust backend and pairs parser. Missing libraries must fail.
- Publishes the generated packages to the GitHub Release for that tag.
Release jobs cache vim.pack data/cache directories. The plugin cache is keyed by OS, architecture, Neovim version, and
nvim-pack-lock.json, with a same-version fallback so
unchanged plugins can be reused when the lockfile changes.
scripts/ci-blink.py prepares and verifies the
Blink native libraries.
Only initial plugin bootstrapping uses NVIME_SKIP_BLINK_NATIVE=1;
scripts/ci-blink-test.lua blocks runtime downloads
and verifies actual native calls after installing the extracted artifacts.
These tests cover native startup, not every project LSP or parser build.
Releases are triggered in two ways:
- Manually push a tag such as
v0.12.5.1. - Let the monthly scheduled run check
master; on the first day of each month at00:00 UTC, if there are commits since the previous release tag, it creates the next tag automatically and publishes a release from that commit.
To retry a failed release, rerun its existing Actions run. Manual dispatch does not create a release.
Example release flow:
# Preview the next release tag.
bash scripts/create-release-tag.sh --dry-run
# Create an annotated tag locally.
bash scripts/create-release-tag.sh
# Or create and push it in one step, triggering the release workflow.
bash scripts/create-release-tag.sh --pushThe helper resolves Neovim from flake.lock, increments the NVIME revision,
and checks that the working tree is clean and master matches origin/master.
If supplied, --version must match the locked version.
Local helper scripts used by CI:
- scripts/create-release-tag.sh: safely creates the next local or remote release tag
- scripts/ci-prepare-release.sh: resolves the release version and creates scheduled tags
- scripts/ci-smoke.sh: headless startup validation
- scripts/ci-package.sh: bootstraps plugins and builds release artifacts
- scripts/install-bundle.sh: installs a packaged release locally