This repository provides a self-contained, reproducible Neovim development environment using Nix Flakes. It packages the Neovim configuration, plugins (managed by Lazy.nvim), and essential language servers/tools into an atomic derivation, allowing for easy installation and predictable behavior across any Nix-enabled system.
The primary goals of this project are:
- Reproducibility: Ensure that running Neovim today is exactly the same as running it a year from now, regardless of changes to system packages or global state.
- Immutability Bypass: Solve the common Nix challenge of running stateful applications (like Neovim with a plugin manager) where writable files (lock files, cache) are expected alongside read-only configuration files.
- Flexible Usage: Support both project-local shell development (
nix develop) and system-wide installation (nix profile add) while maintaining environment isolation. - Local Overrides: Provide an easy mechanism to override the base configuration for specific projects without modifying the flake itself.
Use this method when you want to use the Neovim configuration and all the associated tools (like ripgrep, fd, lua-language-server, deno, etc.) within a specific project directory.
- Add the flake: In your project's
flake.nix, simply addnvim-flakeas an input and reference itsdevShells.defaultoutput. - Enter the shell:
nix develop github:sewakghali/nvim-flake/main
- Start Neovim:
nvim
Use this method to install the custom nvim binary and configuration wrapper system-wide, making it available in your $PATH regardless of your current directory.
# Install the package to your user profile
nix profile install github:sewakghali/nvim-flake#default
# Run Neovim from any directory
nvimThe flake uses custom wrapper logic to handle path resolution and environment setup:
When you enter a directory that contains a sub-directory named ./nvim, the wrapper automatically switches to using the configuration found in that local directory instead of the globally installed flake config.
- Behavior: If
./nvimexists,XDG_CONFIG_HOMEis set to the current directory ($PWD). - Use Case: Quick, project-specific overrides for LSP or plugin configurations without touching your stable global configuration.
When installed globally via nix profile (or when the local override fails), the wrapper employs a copy-on-first-run mechanism to solve the Nix immutability issue:
- Check/Copy: On the first run, the immutable config from the Nix store is copied to a writable user location:
~/.config/nvim-global/nvim. - Config Path: The wrapper sets
XDG_CONFIG_HOMEto the parent directory (~/.config), ensuring Neovim uses this writable copy. - Data Redirection: All mutable data (plugins, cache,
lazy-lock.json) is redirected to a separate, writable path:~/.local/share/nvim-global-data.
This guarantees that plugins can be installed and updated without throwing Permission denied errors.
- Quirk: The very first time you launch
nvimafter a fresh installation (or after clearing your cache), you will likely encounter an error message on startup related to a missing Lua module or plugin. - Cause: This happens because the Lua configuration is loaded before the Lazy plugin manager has finished downloading and installing the dependencies into the
nvim-global-datadirectory. - Solution: Simply exit Neovim and run
nvimagain. The restart allows Neovim to load the plugins that were downloaded during the first session.