UP | HOME

Nixvim Manager (yalms.nvm)

Table of Contents

Nixvim Manager

Nixvim Manager lets you run multiple Neovim configurations on the same machine, each with its own plugins, settings, and keymaps. Each configuration is a self-contained Nixvim instance built with Nix.

You define instances by directory — for example, use one config when working in ~/work and a different one when editing ~/personal projects. The manager picks the right binary automatically based on your current working directory.

It provides:

  • An nv CLI tool to manage instances from the terminal
  • Automatic instance selection based on your current directory
  • Neovim integration for building, rebuilding, and managing instances interactively

Usage Guide

Prerequisites

Installation via Home Manager

This is the recommended installation path. It installs the nv CLI tool and sets up your first instance automatically.

Step 1: Add the flake input

Add YALMS to your flake inputs:

{
  inputs = {
    yalms.url = "github:anomalyco/yalms";
    # ... other inputs
  };
}

Step 2: Import the module

Import the Nixvim Manager Home Manager module:

{
  imports = [
    inputs.yalms.homeManagerModules.nixvim-manager
  ];
}

Step 3: Enable and configure instances

{
  programs.nixvim-manager = {
    enable = true;
    settings = {
      nixvims = {
        default = {
          module = { opts.number = true; };
          dirs = [ "~/projects" ];
        };
      };
    };
  };
}

When you apply this configuration, Home Manager:

  1. Installs the nv CLI tool
  2. Creates instance declarations in $HOME/nixvim/declarations.json
  3. Writes Nix module files to $HOME/nixvim/<name>/nixvim.nix
  4. Runs nv -fnc init to build all instances
  5. Automatically registers the default instance with the YALMS Neovim plugin

Daily Usage with the nv CLI

Once installed, manage your instances from the terminal:

# Build or rebuild all configured instances
nv -fnc init

# Add a new Nixvim instance
nv add myconfig --module '{ opts.number = true; }'

# Rebuild a specific instance
nv build myconfig

# See which Nixvim binary to use for a given directory
nv resolve ~/.config/nvim

After building, each instance produces a nvim binary at ~/.nixvim/<name>/result/bin/nvim.

Configuring Instances

Each instance needs a Nix expression that defines its Neovim configuration. In the Home Manager setup, you provide this as a Nix module:

programs.nixvim-manager.settings.nixvims = {
  myconfig = {
    module = { opts.number = true; opts.relativenumber = true; };
    dirs = [ "~/myproject" ];
  };
};
Option Type Description
module string or lambda Nix expression for the Nixvim module
dirs list of strings Directories this instance serves
link null or string Optional path to symlink the instance binary to

The dirs list controls which directory triggers this instance. When you are in ~/myproject or any subdirectory, nv resolve returns this instance's binary.

Extending the default instance

The Home Manager module creates a builds.default that you can extend in other instances. This lets you share a base configuration:

programs.nixvim-manager.settings.nixvims = {
  myconfig = {
    module = { builds, ... }: builds.default.extend {
      opts.relativenumber = true;
    };
    dirs = [ "~/myconfig" ];
  };
};

You can also use the np argument to import additional Nixvim modules:

module = { builds, np, ... }: builds.default.extend {
  imports = [ np.nixvimModules.langs.svelte ];
  opts.clipboard = "unnamedplus";
};

Quick Setup Without Home Manager

You do not need Home Manager. You can set everything up from inside Neovim:

-- Enable with defaults (stores instances in ~/.nixvim)
require('yalms.nvm').setup(true)

-- Or with a custom directory and instances
require('yalms.nvm').setup({
  dir = vim.fn.stdpath("data") .. "/nvm",
  nixvims = {
    default = {
      name = "Default",
      dirs = { vim.fn.stdpath("config") .. "/nixvim" },
      module = [[
        { opts.number = true }
      ]]
    }
  },
  force_rebuild = false,
})

After calling setup(), access the manager from anywhere in Neovim:

local nvm = require('yalms.nvm').get()

Developer Guide

Programmatic Instance Management

Add a new instance at runtime:

local nvm = require('yalms.nvm').get()

nvm:add({
  name = "myconfig",
  dirs = { "~/.config/nvim" },
  module = [[
    { opts.number = true; opts.relativenumber = true; }
  ]]
}, function(err, nixvim)
  if err then
    print("Error: " .. err)
  else
    print("Added: " .. nixvim.name .. " -> " .. nixvim.link)
  end
end)

Rebuild an instance (defaults to "default"):

nvm:rebuild("myconfig", function(err, nixvim)
  if err then
    print("Build failed: " .. err)
  else
    print("Built successfully: " .. nixvim.status)
  end
end)

Configuration Reference

Option Type Default Description
dir string or function $NIXVIM_MANAGER_DIR or ~/.nixvim Directory for flake files and config
nixvims table {} Instances to register at startup
force_rebuild boolean false Rebuild all instances on load regardless of saved status

Each instance entry requires a name (used as the flake attribute), a dirs array (directories this instance serves, used for automatic binary resolution), and optionally a module (Nix expression written to the instance's nix file).

Automatic Binary Resolution

The manager matches your current directory against each instance's dirs array, picking the longest prefix match. If no match is found, it falls back to the instance with no dirs constraint (the default).

local link = nvm:resolve_link(vim.fn.getcwd())
if link then
  vim.cmd('exec ' .. link .. '/bin/nvim')
end

Events

The manager emits lifecycle events. Register callbacks with on():

Event Fires when
"index" Configuration is first loaded from disk
"ready" Initial load and queued builds are complete
"change" Configuration changes (add, update, remove, build)
"build" A build starts or finishes
"remove" An instance is removed
local nvm = require('yalms.nvm').get()
nvm:on("build", function(e, payload)
  print("Build status for " .. payload.nixvim.name .. ": " .. payload.nixvim.status)
end)

API Reference