Neovim config for remote machines
This is my Neovim configuration, published so that I, or an agent working on my behalf, can put it on any machine I SSH into with one command. The config is frozen: the lockfile is the contract, and the files here are byte-for-byte what I run locally.
curl -fsSL https://www.mfserna.dev/nvim/install.sh | sh
If nvim is missing or older than 0.11, add
--install-nvim and the script fetches the official release
tarball into ~/.local/opt/nvim (no sudo, no package
manager):
curl -fsSL https://www.mfserna.dev/nvim/install.sh | sh -s -- --install-nvim
For a machine with no git or no outbound network beyond this download, install the plugin-free variant instead:
curl -fsSL https://www.mfserna.dev/nvim/install.sh | sh -s -- --minimal
Files
/nvim/install.sh: POSIXshinstaller. Idempotent; backs up any config it replaces./nvim/init.lua: the full config. Bootstraps lazy.nvim and declares every plugin, LSP server, keymap, and option./nvim/lazy-lock.json: pinned plugin commits. The installer runsLazy! restore, notsync, so you get exactly these./nvim/syntax/baml.vim: fallback highlighting for BAML files until the LSP attaches./nvim/init.min.lua: the--minimalvariant. Same options and keymaps, built-in colorscheme, netrw instead of a tree plugin,:find/:grepinstead of Telescope, and native LSP completion for any server already onPATH.
Requirements
Hard requirements for the full config: nvim 0.11 or newer
(the config uses vim.lsp.config,
vim.lsp.enable, and vim.uv), git
(lazy.nvim clones plugins), and curl or wget
for the download. The minimal variant needs only nvim
0.11+ and curl or wget.
Optional tools, and what each unlocks:
ccandmake: compiletelescope-fzf-nativeand LuaSnip's jsregexp. Without them Telescope falls back to its Lua sorter.tree-sitterCLI plus a C compiler: nvim-treesitter'smainbranch installs the C, C++, CMake, and Make parsers through it. Without it, highlighting comes from regex syntax files and LSP semantic tokens.rg(ripgrep): Telescopelive_grepand the minimal config's:grep.node,cargo,go,java,python3: toolchains for the language servers Mason installs. Servers whose toolchain is absent simply fail to install in:Masonand the rest keep working.
The installer prints which optional tools it found so you can decide whether the machine needs more.
What the installer does
- Checks for
nvim≥ 0.11. With--install-nvim, downloads thestabletarball for the detected OS and architecture from the Neovim GitHub releases into~/.local/opt/nvimand links~/.local/bin/nvim. It prints a note if that directory is not onPATH. - Downloads
init.lua,lazy-lock.json, andsyntax/baml.vim(or justinit.min.luawith--minimal) into a temporary directory. - If
$XDG_CONFIG_HOME/nvim(default~/.config/nvim) exists and itsinit.luadiffers, moves it tonvim.bak.<timestamp>. If it already matches, it refreshes in place with no backup. It never deletes anything. - Copies the files into place.
- Runs
nvim --headless "+Lazy! restore" +qato install the pinned plugins, then counts the directories in$XDG_DATA_HOME/nvim/lazyagainst the lockfile. Skip this with--no-sync. - Reports optional tooling.
--dry-run prints every step without writing. The script
writes only to the config directory, Neovim's data directory, and,
with --install-nvim, ~/.local/opt/nvim and
~/.local/bin/nvim.
Language servers are installed by Mason on the first interactive
launch, not by the installer, because mason-lspconfig
installs them asynchronously and a headless +qa would cut
that short. Open nvim once and let :Mason
finish, or run :MasonInstall for a specific server.
Verify
nvim --headless +checkhealth +qa
nvim --headless "+Lazy! check" +qa
Both should exit 0. To check that a remote machine is on the published config rather than a drifted copy:
curl -fsSL https://www.mfserna.dev/nvim/init.lua | diff - ~/.config/nvim/init.lua
curl -fsSL https://www.mfserna.dev/nvim/lazy-lock.json | diff - ~/.config/nvim/lazy-lock.json
No output means no drift.
Manual install
For a machine where piping to sh is not acceptable, the files are plain static downloads:
mkdir -p ~/.config/nvim/syntax
curl -fsSL https://www.mfserna.dev/nvim/init.lua -o ~/.config/nvim/init.lua
curl -fsSL https://www.mfserna.dev/nvim/lazy-lock.json -o ~/.config/nvim/lazy-lock.json
curl -fsSL https://www.mfserna.dev/nvim/syntax/baml.vim -o ~/.config/nvim/syntax/baml.vim
nvim --headless "+Lazy! restore" +qa
What is in the config
Gruvbox, lualine, bufferline, nvim-tree, Telescope with fzf-native,
nvim-cmp with LuaSnip and friendly-snippets, gitsigns, toggleterm,
which-key, Comment.nvim, indent-blankline, and nvim-autopairs. LSP goes
through nvim-lspconfig and Mason, with rustaceanvim and crates.nvim for
Rust, nvim-jdtls for Java, clangd flags for C and C++, and a hand-wired
BAML server. Leader is space; <leader>f finds,
<leader>g is git, <leader>l is
LSP, <leader>r is Rust,
<leader>c shells out to the Cursor CLI, and
Ctrl-\ toggles a terminal. Tabs are four spaces, folds
come from treesitter and start open, diagnostics show in a float on
hover rather than as virtual text, and search highlighting clears
itself when the cursor leaves the match.