meta_package_manager.managers.neovim module¶

Managers driven by a headless Neovim process.

None of the three is a standalone binary: each is Lua living inside the editor, so nvim is the CLI mpm executes for all of them and every operation travels as a -c 'lua …' payload. That shared shape is what groups them here, not a shared backend: Lazy and Vim_Pack clone plugins straight from upstream Git into their own trees, while Mason installs ordinary developer tools through whichever ecosystem ships them.

Keying three managers on the same nvim binary is legitimate but needs care, so each one’s version probe answers only for its own component and stays silent on a host that merely has an editor.

meta_package_manager.managers.neovim.LAZY_LOCKFILE = 'vim.fn.stdpath("config") .. "/lazy-lock.json"'¶

Lua expression resolving the lock file lazy.nvim writes after every install or update, which is the inventory mpm reads.

meta_package_manager.managers.neovim.LAZY_ROOT = 'vim.fn.stdpath("data") .. "/lazy/lazy.nvim"'¶

Lua expression resolving lazy.nvim’s own checkout.

lazy.nvim manages itself, and its bootstrap snippet clones it under the lazy directory of Neovim’s data path. That is where a --clean process, which loads none of the user’s configuration, has to look to find it.

meta_package_manager.managers.neovim.MASON_CANDIDATES = ('"/lazy/mason.nvim"', '"/site/pack/*/*/mason.nvim"')¶

Globs, relative to Neovim’s data path, where mason’s own checkout may sit.

mason.nvim is a plugin like any other, so its location is decided by whatever installed it rather than by mason: lazy.nvim clones it under lazy, while the built-in package mechanism and the managers built on it use site/pack. Both are probed because a --clean process loads no configuration and therefore has nothing else to go on.

meta_package_manager.managers.neovim.MASON_ROOT = 'vim.fn.stdpath("data") .. "/mason"'¶

Lua expression resolving mason’s install root.

One directory per machine, holding bin, packages, registries and the rest. It is where a --clean process, loading none of the user’s configuration, has to look: unlike the plugin’s own checkout this path does not move with whichever plugin manager installed mason.

meta_package_manager.managers.neovim.VIM_PACK_PLUGINS = 'vim.pack.get(nil, {info = false})'¶

Lua expression listing every plugin vim.pack manages.

info is turned off on purpose: the extra payload it gathers (the Git branches and tags available for each plugin) costs one Git invocation per plugin and holds nothing mpm reports.

meta_package_manager.managers.neovim.lua_command(body)[source]¶

Wrap a Lua body into the -c argument handed to Neovim.

The trailing os.exit(0) is the success path: it terminates Neovim before the failure gate each manager declares in its own post_args can run.

Return type:

str

meta_package_manager.managers.neovim.lua_string(value)[source]¶

Render value as a Lua string literal.

JSON string syntax is a subset of Lua’s, so json.dumps() quotes and escapes any plugin URL into a valid Lua literal. ensure_ascii is turned off because Lua has no \uXXXX escape: a non-ASCII source must stay verbatim UTF-8.

Return type:

str

meta_package_manager.managers.neovim.vim_pack_resolve(package_id, action)[source]¶

Lua resolving a src URL to its plugin name, then running action.

vim.pack.del() and vim.pack.update() both address plugins by the short name Neovim derives from the source URL, while mpm keys packages on the URL itself. The mapping is looked up in vim.pack.get() output rather than recomputed here, so a plugin whose spec overrides its name still resolves. A URL that matches nothing leaves the loop a no-op, which keeps removing an absent plugin idempotent.

Return type:

str

class meta_package_manager.managers.neovim.Lazy[source]¶

Bases: PackageManager

lazy.nvim is a modern plugin manager for Neovim.

lazy.nvim is a Lua plugin, not a standalone binary: each operation below is a Lua one-liner evaluated by a throw-away Neovim process. Plugins are Git clones under stdpath('data')/lazy, pinned by a lazy-lock.json lock file in stdpath('config') that records the exact commit of each one.

Caution

Neovim is the binary mpm executes, and mpm already wraps Neovim’s built-in Vim_Pack, which legitimately keys on the same nvim. The two are told apart by the version probe: it reports a version only when lazy.nvim’s own checkout is found and its version constant reads back, so a host running Neovim without lazy.nvim leaves this manager unavailable instead of shadowing every editor on every machine.

Note

This manager is deliberately limited to inventorying and updating, the two operations lazy.nvim can carry out with nobody at the keyboard. That is already more than the coarse, whole-category upgrade a tool like topgrade performs for the same plugins, since the inventory comes with it.

Caution

No install and no remove: lazy.nvim materializes exactly the plugin set declared in the user’s own Lua configuration. :Lazy install clones what that configuration already names and :Lazy clean drops what it no longer names, so neither takes a plugin of mpm’s choosing. Installing one would mean mpm editing the user’s init.lua, which is configuration mpm does not own. The two operations are therefore not implemented rather than faked, and mpm auto-skips them.

Note

No outdated: :Lazy check does fetch each remote without touching a working tree, but the pending revisions it computes are only readable through a plugin’s private _.updates field, which lazy.nvim documents no contract for. mpm auto-skips the operation and upgrade --all still works.

Documentation: lazy.folke.io.

Initialize cli_errors list.

name: str = 'Neovim lazy-nvim'¶

Spelled with a dash: manager names are restricted to letters, digits, spaces, apostrophes and dashes, so the lazy.nvim project name cannot be used verbatim.

homepage_url: str | None = 'https://lazy.folke.io'¶

Home page of the project, only used in documentation for reference.

Slug of the brand mark standing for this manager in the documentation.

Names an SVG vendored under docs/assets/managers/, whose provenance and license are recorded in docs/assets/managers/logos.yaml. Inlined at the top of the manager’s page by meta_package_manager._docs; a manager leaving it unset keeps the page’s default package glyph.

Several managers legitimately share one slug, either because they wrap the same upstream (brew and cask) or because the tool has no mark of its own and its ecosystem’s stands in (apt under Debian’s swirl, cargo under Rust’s gear). Documentation-only, like homepage_url: no CLI output reads it.

platforms: frozenset[Platform] | Group | Platform | Iterable[Platform | Group] = frozenset({Platform(id='aix', name='IBM AIX'), Platform(id='almalinux', name='AlmaLinux'), Platform(id='alpine', name='Alpine Linux'), Platform(id='altlinux', name='ALT Linux'), Platform(id='amzn', name='Amazon Linux'), Platform(id='android', name='Android'), Platform(id='arch', name='Arch Linux'), Platform(id='buildroot', name='Buildroot'), Platform(id='cachyos', name='CachyOS'), Platform(id='centos', name='CentOS'), Platform(id='chromeos', name='ChromeOS'), Platform(id='clearlinux', name='Clear Linux OS'), Platform(id='cloudlinux', name='CloudLinux OS'), Platform(id='cygwin', name='Cygwin'), Platform(id='debian', name='Debian'), Platform(id='dragonfly_bsd', name='DragonFly BSD'), Platform(id='endeavouros', name='EndeavourOS'), Platform(id='exherbo', name='Exherbo Linux'), Platform(id='fedora', name='Fedora'), Platform(id='freebsd', name='FreeBSD'), Platform(id='generic_linux', name='Generic Linux'), Platform(id='gentoo', name='Gentoo Linux'), Platform(id='guix', name='Guix System'), Platform(id='haiku', name='Haiku'), Platform(id='hurd', name='GNU/Hurd'), Platform(id='ibm_powerkvm', name='IBM PowerKVM'), Platform(id='illumos', name='illumos'), Platform(id='kali', name='Kali Linux'), Platform(id='kvmibm', name='KVM for IBM z Systems'), Platform(id='linuxmint', name='Linux Mint'), Platform(id='macos', name='macOS'), Platform(id='mageia', name='Mageia'), Platform(id='mandriva', name='Mandriva Linux'), Platform(id='manjaro', name='Manjaro Linux'), Platform(id='midnightbsd', name='MidnightBSD'), Platform(id='netbsd', name='NetBSD'), Platform(id='nixos', name='NixOS'), Platform(id='nobara', name='Nobara'), Platform(id='openbsd', name='OpenBSD'), Platform(id='opensuse', name='openSUSE'), Platform(id='openwrt', name='OpenWrt'), Platform(id='oracle', name='Oracle Linux'), Platform(id='os400', name='IBM i'), Platform(id='parallels', name='Parallels'), Platform(id='pidora', name='Pidora'), Platform(id='pikaos', name='PikaOS'), Platform(id='raspbian', name='Raspbian'), Platform(id='rhel', name='RedHat Enterprise Linux'), Platform(id='rocky', name='Rocky Linux'), Platform(id='scientific', name='Scientific Linux'), Platform(id='slackware', name='Slackware'), Platform(id='sles', name='SUSE Linux Enterprise Server'), Platform(id='slitaz', name='SliTaz GNU/Linux'), Platform(id='solaris', name='Solaris'), Platform(id='sourcemage', name='Source Mage GNU/Linux'), Platform(id='sunos', name='SunOS'), Platform(id='tuxedo', name='Tuxedo OS'), Platform(id='ubuntu', name='Ubuntu'), Platform(id='ultramarine', name='Ultramarine'), Platform(id='void', name='Void Linux'), Platform(id='windows', name='Windows'), Platform(id='wsl1', name='Windows Subsystem for Linux v1'), Platform(id='wsl2', name='Windows Subsystem for Linux v2'), Platform(id='xenserver', name='XenServer')})¶

List of platforms supported by the manager.

Allows for a mishmash of platforms and groups of platforms. Will be normalized into a frozenset of Platform instances at instantiation.

requirement: str | None = '>=11.0.0'¶

Current major series of lazy.nvim.

Both pieces this implementation depends on are older than that: the version constant the probe reads and the wait/show manager options the upgrade passes are present as far back as 10.0.0. The floor is held at the current major anyway, which is the series the implementation was exercised against.

cli_names: tuple[str, ...] = ('nvim',)¶

List of CLI names the package manager is known as.

This list of recognized CLI names is ordered by priority. That way we can influence the search of the right binary.

..hint::

This was helpful in the case of the Python transition from 2.x to 3.x, where multiple versions of the same executable were named python or python3.

By default, this property’s value is derived from the manager’s ID (see the MetaPackageManager.__init__ method above).

pre_args: tuple[str, ...] = ('--headless',)¶
post_args: tuple[str, ...] = ('-c', 'cquit')¶

Failure gate, only reached when the Lua payload raised before reaching its own os.exit(0).

version_cli_options: tuple[str, ...] = ('--clean', '--headless', '-c', 'lua local p = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if (vim.uv or vim.loop).fs_stat(p) then vim.opt.rtp:prepend(p) io.write("lazy.nvim " .. require("lazy.core.config").version) end os.exit(0)')¶

Self-contained probe: version detection skips Lazy.pre_args and Lazy.post_args, so this carries its own --headless and exits on its own.

The checkout is tested before being put on the runtime path, so a Neovim without lazy.nvim prints nothing and exits successfully rather than raising. That silence is what leaves the manager unavailable on a host that merely has an editor installed.

version_regexes: tuple[str, ...] = ('lazy\\.nvim (?P<version>\\S+)',)¶
$ nvim --clean --headless     > -c 'lua local p = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if (vim.uv or vim.loop).fs_stat(p) then vim.opt.rtp:prepend(p) io.write("lazy.nvim " .. require("lazy.core.config").version) end os.exit(0)'
lazy.nvim 11.17.5
property installed: Iterator[Package]¶

Fetch installed packages.

The lock file is read straight off disk by a --clean process, so the inventory costs no plugin loading and cannot be perturbed by the user’s configuration. stdpath() is XDG-derived and --clean does not move it, so the file still resolves.

Packages are keyed on the short name lazy.nvim derives from each plugin’s source, which is what the lock file records. The commit is the Git revision the plugin is checked out at, the only revision lazy.nvim tracks: a plugin follows a branch unless its spec pins a version.

Note

lazy.nvim manages itself, so it appears in its own inventory.

$ nvim --headless --clean \
> -c 'lua local f = io.open(vim.fn.stdpath("config") .. "/lazy-lock.json") if f then io.write(f:read("a")) end os.exit(0)' \
> -c 'cquit'
{
  "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
  "vim-sensible": { "branch": "master", "commit": "0ce2d843d6f588bb0c8c7eec6449171615dc56d9" },
  "z": { "branch": "master", "commit": "d37a763a6a30e1b32766fecc3b8ffd6127f8a0fd" }
}
upgrade_all_cli()[source]¶

Generates the CLI to upgrade all packages.

This is the one operation that lets the user’s configuration load: lazy.nvim only exists once init.lua has bootstrapped it, so --clean is deliberately absent here. wait blocks until every Git task has finished, which is what makes the run usable unattended, and show keeps the interactive floating window from being drawn.

$ nvim --headless \
> -c 'lua require("lazy").update({wait = true, show = false}) os.exit(0)' \
> -c 'cquit'
Return type:

tuple[str, ...]

id: str = 'lazy'¶

Package manager’s ID.

Derived by defaults from the lower-cased class name in which underscores _ are replaced by dashes -.

This ID must be unique among all package manager definitions and lower-case, as they’re used as feature flags for the mpm CLI.

virtual: bool = False¶

Should we expose the package manager to the user?

Virtual package manager are just skeleton classes used to factorize code among managers of the same family.

class meta_package_manager.managers.neovim.Mason[source]¶

Bases: PackageManager

Installer of LSP servers, DAP adapters, linters and formatters for Neovim.

Important

mason is not a plugin manager, which is what separates it from Lazy and Vim_Pack. Those install Lua that runs inside the editor; mason installs ordinary developer tools, the same stylua or rust-analyzer binaries another host might get from Homebrew.

Note

Wrapping it is what makes those tools visible at all. mason redirects every backend it shells out to into the package’s own directory: a local npm install``rather than a global one, a``venv``per package,``cargo install –root .`,``GOBIN``and``GEM_HOME``pointed inside. So a``pyright` installed by mason appears in no other manager’s inventory, and without this wrapper mpm would not see it.

Caution

Reads and writes drive Neovim differently, and deliberately.

The inventory is read by a --clean process straight off mason’s own install tree, costing no plugin loading and immune to whatever the user’s configuration does. Mutations cannot work that way: MasonInstall and its siblings are user commands that exist only once mason is loaded, so those run without --clean and let the configuration supply them. That is mason’s own documented recipe for unattended use.

Note

Every mutating command blocks in headless mode rather than returning while work continues in the background: mason branches on #vim.api.nvim_list_uis() == 0 and runs the transaction synchronously, refusing an unknown package name up front instead of failing silently.

Warning

The install root is assumed to be mason’s default. A configuration moving install_root_dir elsewhere leaves the inventory empty, since finding the override would mean loading the very plugin the read path avoids.

Documentation: mason.nvim.

Initialize cli_errors list.

name: str = 'Neovim mason-nvim'¶

Return package manager’s common name.

Default value is based on class name.

homepage_url: str | None = 'https://github.com/mason-org/mason.nvim'¶

Home page of the project, only used in documentation for reference.

Slug of the brand mark standing for this manager in the documentation.

Names an SVG vendored under docs/assets/managers/, whose provenance and license are recorded in docs/assets/managers/logos.yaml. Inlined at the top of the manager’s page by meta_package_manager._docs; a manager leaving it unset keeps the page’s default package glyph.

Several managers legitimately share one slug, either because they wrap the same upstream (brew and cask) or because the tool has no mark of its own and its ecosystem’s stands in (apt under Debian’s swirl, cargo under Rust’s gear). Documentation-only, like homepage_url: no CLI output reads it.

platforms: frozenset[Platform] | Group | Platform | Iterable[Platform | Group] = frozenset({Platform(id='aix', name='IBM AIX'), Platform(id='almalinux', name='AlmaLinux'), Platform(id='alpine', name='Alpine Linux'), Platform(id='altlinux', name='ALT Linux'), Platform(id='amzn', name='Amazon Linux'), Platform(id='android', name='Android'), Platform(id='arch', name='Arch Linux'), Platform(id='buildroot', name='Buildroot'), Platform(id='cachyos', name='CachyOS'), Platform(id='centos', name='CentOS'), Platform(id='chromeos', name='ChromeOS'), Platform(id='clearlinux', name='Clear Linux OS'), Platform(id='cloudlinux', name='CloudLinux OS'), Platform(id='cygwin', name='Cygwin'), Platform(id='debian', name='Debian'), Platform(id='dragonfly_bsd', name='DragonFly BSD'), Platform(id='endeavouros', name='EndeavourOS'), Platform(id='exherbo', name='Exherbo Linux'), Platform(id='fedora', name='Fedora'), Platform(id='freebsd', name='FreeBSD'), Platform(id='generic_linux', name='Generic Linux'), Platform(id='gentoo', name='Gentoo Linux'), Platform(id='guix', name='Guix System'), Platform(id='haiku', name='Haiku'), Platform(id='hurd', name='GNU/Hurd'), Platform(id='ibm_powerkvm', name='IBM PowerKVM'), Platform(id='illumos', name='illumos'), Platform(id='kali', name='Kali Linux'), Platform(id='kvmibm', name='KVM for IBM z Systems'), Platform(id='linuxmint', name='Linux Mint'), Platform(id='macos', name='macOS'), Platform(id='mageia', name='Mageia'), Platform(id='mandriva', name='Mandriva Linux'), Platform(id='manjaro', name='Manjaro Linux'), Platform(id='midnightbsd', name='MidnightBSD'), Platform(id='netbsd', name='NetBSD'), Platform(id='nixos', name='NixOS'), Platform(id='nobara', name='Nobara'), Platform(id='openbsd', name='OpenBSD'), Platform(id='opensuse', name='openSUSE'), Platform(id='openwrt', name='OpenWrt'), Platform(id='oracle', name='Oracle Linux'), Platform(id='os400', name='IBM i'), Platform(id='parallels', name='Parallels'), Platform(id='pidora', name='Pidora'), Platform(id='pikaos', name='PikaOS'), Platform(id='raspbian', name='Raspbian'), Platform(id='rhel', name='RedHat Enterprise Linux'), Platform(id='rocky', name='Rocky Linux'), Platform(id='scientific', name='Scientific Linux'), Platform(id='slackware', name='Slackware'), Platform(id='sles', name='SUSE Linux Enterprise Server'), Platform(id='slitaz', name='SliTaz GNU/Linux'), Platform(id='solaris', name='Solaris'), Platform(id='sourcemage', name='Source Mage GNU/Linux'), Platform(id='sunos', name='SunOS'), Platform(id='tuxedo', name='Tuxedo OS'), Platform(id='ubuntu', name='Ubuntu'), Platform(id='ultramarine', name='Ultramarine'), Platform(id='void', name='Void Linux'), Platform(id='windows', name='Windows'), Platform(id='wsl1', name='Windows Subsystem for Linux v1'), Platform(id='wsl2', name='Windows Subsystem for Linux v2'), Platform(id='xenserver', name='XenServer')})¶

List of platforms supported by the manager.

Allows for a mishmash of platforms and groups of platforms. Will be normalized into a frozenset of Platform instances at instantiation.

requirement: str | None = '>=2.0.0'¶

The release that reshaped mason’s API into the one described here.

2.0.0 removed the modules backing custom Lua packages, replaced the registry events, and raised the Neovim floor to 0.10.0. It is also the release the project moved to its own organization under, so it is the oldest version worth describing.

Caution

This floors mason, never the receipts it wrote. A host on a current mason still carries receipts from 1.x for anything installed back then, which is why installed() reads both of their shapes.

cli_names: tuple[str, ...] = ('nvim',)¶

List of CLI names the package manager is known as.

This list of recognized CLI names is ordered by priority. That way we can influence the search of the right binary.

..hint::

This was helpful in the case of the Python transition from 2.x to 3.x, where multiple versions of the same executable were named python or python3.

By default, this property’s value is derived from the manager’s ID (see the MetaPackageManager.__init__ method above).

pre_args: tuple[str, ...] = ('--headless',)¶
post_args: tuple[str, ...] = ('-c', 'cquit')¶

Failure gate. Every Lua body exits on its own through lua_command(), and every mutation closes on qall, so reaching this means the command never got that far and the run is an error.

version_cli_options: tuple[str, ...] = ('--clean', '--headless', '-c', 'lua local d = vim.fn.stdpath("data") local c = vim.fn.glob(d .. "/lazy/mason.nvim", true, true) vim.list_extend(c, vim.fn.glob(d .. "/site/pack/*/*/mason.nvim", true, true)) for _, p in ipairs(c) do vim.opt.rtp:prepend(p) local ok, m = pcall(require, "mason.version") if ok then io.write("mason " .. m.VERSION) break end end os.exit(0)')¶

Self-contained probe: version detection skips Mason.pre_args and Mason.post_args, so this carries its own --headless and exits on its own.

Each candidate checkout is put on the runtime path only long enough to try loading mason from it, so a Neovim without mason prints nothing and exits successfully rather than raising. That silence is what leaves the manager unavailable on a host that merely has an editor, which matters here because lazy and vim-pack legitimately key on the same nvim binary.

version_regexes: tuple[str, ...] = ('mason v?(?P<version>\\S+)',)¶

Search the version right after the mason string.

$ nvim --clean --headless \
> -c 'lua local d = vim.fn.stdpath("data") local c = vim.fn.glob(d .. "/lazy/mason.nvim", true, true) vim.list_extend(c, vim.fn.glob(d .. "/site/pack/*/*/mason.nvim", true, true)) for _, p in ipairs(c) do vim.opt.rtp:prepend(p) local ok, m = pcall(require, "mason.version") if ok then io.write("mason " .. m.VERSION) break end end os.exit(0)'
mason v2.3.1

The v is optional in the pattern because it belongs to mason’s own string rather than to the version: it is a tag name reported verbatim.

property installed: Iterator[Package]¶

Fetch installed packages.

mason writes a receipt beside every package it installs, and those receipts are the inventory: a --clean process reads them straight off the tree, so nothing has to be loaded and the user’s configuration cannot perturb the result.

A receipt carries no version field. It records the package’s source as a purl, and the version is the purl’s own version component, which is what mason itself reads back.

Caution

The source sits under source in a 2.0 receipt and under primary_source in every earlier one, exactly as mason’s own reader branches. Both are accepted here: the receipt’s schema version is fixed when the package is installed, so a current mason keeps serving 1.x receipts for anything installed under it, and reading only one shape would silently drop those packages instead of failing.

$ nvim --headless --clean \
> -c 'lua local root = vim.fn.stdpath("data") .. "/mason" .. "/packages" for _, dir in ipairs(vim.fn.glob(root .. "/*", true, true)) do local f = dir .. "/mason-receipt.json" if (vim.uv or vim.loop).fs_stat(f) then local ok, r = pcall(vim.json.decode, table.concat(vim.fn.readfile(f), "\n")) if ok and r and r.name then local s = r.source or r.primary_source io.write(r.name .. "\t" .. ((s and s.id) or "") .. "\n") end end end os.exit(0)' \
> -c 'cquit'
stylua  pkg:github/johnnymorganz/[email protected]
install(package_id, version=None)[source]¶

Install one package.

Runs without --clean so the user’s configuration supplies the MasonInstall command, which mason documents as the way to drive it unattended.

$ nvim --headless -c 'MasonInstall stylua' -c 'qall' -c 'cquit'
Return type:

str

upgrade_one_cli(package_id, version=None)[source]¶

Generates the CLI to upgrade the package provided as parameter.

mason has no upgrade verb of its own: installing a package that is already present fetches whatever the registry currently offers, which is the upgrade.

$ nvim --headless -c 'MasonInstall stylua' -c 'qall' -c 'cquit'
Return type:

tuple[str, ...]

remove(package_id)[source]¶

Removes a package.

$ nvim --headless -c 'MasonUninstall stylua' -c 'qall' -c 'cquit'
Return type:

str

sync()[source]¶

Sync package metadata.

MasonUpdate refreshes the registry index and upgrades nothing, which is exactly this operation. Its own description says so, and its body calls the registry update alone.

$ nvim --headless -c 'MasonUpdate' -c 'qall' -c 'cquit'
Return type:

None

id: str = 'mason'¶

Package manager’s ID.

Derived by defaults from the lower-cased class name in which underscores _ are replaced by dashes -.

This ID must be unique among all package manager definitions and lower-case, as they’re used as feature flags for the mpm CLI.

virtual: bool = False¶

Should we expose the package manager to the user?

Virtual package manager are just skeleton classes used to factorize code among managers of the same family.

class meta_package_manager.managers.neovim.Vim_Pack[source]¶

Bases: PackageManager

Neovim’s built-in plugin manager.

vim.pack is a Lua API shipped in Neovim’s core since 0.12, not a standalone binary: each operation below is a Lua one-liner evaluated by a throw-away Neovim process. Plugins are Git clones under stdpath('data')/site/pack/core/opt, pinned by a nvim-pack-lock.json lock file in stdpath('config').

Note

Every invocation runs --clean, so the user’s init.lua is never sourced. vim.pack.get() reads the lock file rather than the current session, so the inventory stays complete without paying for, nor being perturbed by, a full editor startup. stdpath() is XDG-derived and --clean does not move it, so both the lock file and the plugin directory still resolve.

Caution

Neovim exits 0 even when a -c command raises, which would hide every failure from mpm. Vim_Pack.post_args therefore closes each invocation with -c 'cquit': on success the Lua payload has already called os.exit(0), and on error control falls through to that gate and Neovim exits 1.

Caution

Installing a plugin registers it in the lock file and clones it to disk, but mpm does not edit the user’s init.lua. A plugin installed through mpm is therefore on disk but not loaded by the next editor start until a matching vim.pack.add() call is added to the configuration.

Note

Packages are keyed on their src URL. vim.pack accepts no registry shorthand: Vim_Pack.install() needs a URL while Vim_Pack.remove() and Vim_Pack.upgrade_one_cli() address plugins by the short name Neovim derives from it, so the URL is the only identifier mpm can feed back into every operation. Package ids therefore round-trip through install, remove, upgrade and backup/restore.

Note

No outdated: vim.pack exposes no read-only “list upgradable” call. vim.pack.update() fetches and then either applies the new revisions or renders them into a confirmation buffer, neither of which mpm can consume as a query, so mpm auto-skips the operation and upgrade --all still works.

Initialize cli_errors list.

id: str = 'vim-pack'¶

Package manager’s ID.

Derived by defaults from the lower-cased class name in which underscores _ are replaced by dashes -.

This ID must be unique among all package manager definitions and lower-case, as they’re used as feature flags for the mpm CLI.

virtual: bool = False¶

Should we expose the package manager to the user?

Virtual package manager are just skeleton classes used to factorize code among managers of the same family.

name: str = 'Neovim vim-pack'¶

Spelled with a dash: manager names are restricted to letters, digits, spaces, apostrophes and dashes, so the vim.pack API name cannot be used verbatim.

homepage_url: str | None = 'https://neovim.io/doc/user/pack.html'¶

Home page of the project, only used in documentation for reference.

Slug of the brand mark standing for this manager in the documentation.

Names an SVG vendored under docs/assets/managers/, whose provenance and license are recorded in docs/assets/managers/logos.yaml. Inlined at the top of the manager’s page by meta_package_manager._docs; a manager leaving it unset keeps the page’s default package glyph.

Several managers legitimately share one slug, either because they wrap the same upstream (brew and cask) or because the tool has no mark of its own and its ecosystem’s stands in (apt under Debian’s swirl, cargo under Rust’s gear). Documentation-only, like homepage_url: no CLI output reads it.

platforms: frozenset[Platform] | Group | Platform | Iterable[Platform | Group] = frozenset({Platform(id='aix', name='IBM AIX'), Platform(id='almalinux', name='AlmaLinux'), Platform(id='alpine', name='Alpine Linux'), Platform(id='altlinux', name='ALT Linux'), Platform(id='amzn', name='Amazon Linux'), Platform(id='android', name='Android'), Platform(id='arch', name='Arch Linux'), Platform(id='buildroot', name='Buildroot'), Platform(id='cachyos', name='CachyOS'), Platform(id='centos', name='CentOS'), Platform(id='chromeos', name='ChromeOS'), Platform(id='clearlinux', name='Clear Linux OS'), Platform(id='cloudlinux', name='CloudLinux OS'), Platform(id='cygwin', name='Cygwin'), Platform(id='debian', name='Debian'), Platform(id='dragonfly_bsd', name='DragonFly BSD'), Platform(id='endeavouros', name='EndeavourOS'), Platform(id='exherbo', name='Exherbo Linux'), Platform(id='fedora', name='Fedora'), Platform(id='freebsd', name='FreeBSD'), Platform(id='generic_linux', name='Generic Linux'), Platform(id='gentoo', name='Gentoo Linux'), Platform(id='guix', name='Guix System'), Platform(id='haiku', name='Haiku'), Platform(id='hurd', name='GNU/Hurd'), Platform(id='ibm_powerkvm', name='IBM PowerKVM'), Platform(id='illumos', name='illumos'), Platform(id='kali', name='Kali Linux'), Platform(id='kvmibm', name='KVM for IBM z Systems'), Platform(id='linuxmint', name='Linux Mint'), Platform(id='macos', name='macOS'), Platform(id='mageia', name='Mageia'), Platform(id='mandriva', name='Mandriva Linux'), Platform(id='manjaro', name='Manjaro Linux'), Platform(id='midnightbsd', name='MidnightBSD'), Platform(id='netbsd', name='NetBSD'), Platform(id='nixos', name='NixOS'), Platform(id='nobara', name='Nobara'), Platform(id='openbsd', name='OpenBSD'), Platform(id='opensuse', name='openSUSE'), Platform(id='openwrt', name='OpenWrt'), Platform(id='oracle', name='Oracle Linux'), Platform(id='os400', name='IBM i'), Platform(id='parallels', name='Parallels'), Platform(id='pidora', name='Pidora'), Platform(id='pikaos', name='PikaOS'), Platform(id='raspbian', name='Raspbian'), Platform(id='rhel', name='RedHat Enterprise Linux'), Platform(id='rocky', name='Rocky Linux'), Platform(id='scientific', name='Scientific Linux'), Platform(id='slackware', name='Slackware'), Platform(id='sles', name='SUSE Linux Enterprise Server'), Platform(id='slitaz', name='SliTaz GNU/Linux'), Platform(id='solaris', name='Solaris'), Platform(id='sourcemage', name='Source Mage GNU/Linux'), Platform(id='sunos', name='SunOS'), Platform(id='tuxedo', name='Tuxedo OS'), Platform(id='ubuntu', name='Ubuntu'), Platform(id='ultramarine', name='Ultramarine'), Platform(id='void', name='Void Linux'), Platform(id='windows', name='Windows'), Platform(id='wsl1', name='Windows Subsystem for Linux v1'), Platform(id='wsl2', name='Windows Subsystem for Linux v2'), Platform(id='xenserver', name='XenServer')})¶

List of platforms supported by the manager.

Allows for a mishmash of platforms and groups of platforms. Will be normalized into a frozenset of Platform instances at instantiation.

requirement: str | None = '>=0.12.0'¶

vim.pack landed in Neovim 0.12.

cli_names: tuple[str, ...] = ('nvim',)¶

List of CLI names the package manager is known as.

This list of recognized CLI names is ordered by priority. That way we can influence the search of the right binary.

..hint::

This was helpful in the case of the Python transition from 2.x to 3.x, where multiple versions of the same executable were named python or python3.

By default, this property’s value is derived from the manager’s ID (see the MetaPackageManager.__init__ method above).

pre_args: tuple[str, ...] = ('--clean', '--headless')¶
post_args: tuple[str, ...] = ('-c', 'cquit')¶

Failure gate, only reached when the Lua payload raised before reaching its own os.exit(0).

version_regexes: tuple[str, ...] = ('NVIM\\s+v(?P<version>\\S+)',)¶
$ nvim --version
NVIM v0.12.4
Build type: Release
LuaJIT 2.1.1785763465
property installed: Iterator[Package]¶

Fetch installed packages.

The rev reported for each plugin is the Git commit it is checked out at, which is the only revision vim.pack records: a plugin is pinned to a branch, tag or version range, and the lock file stores the commit that resolved to.

$ nvim --clean --headless \
> -c 'lua io.write(vim.json.encode(vim.pack.get(nil, {info = false}))) os.exit(0)' \
> -c 'cquit'
[{"active":false,"rev":"0ce2d843d6f588bb0c8c7eec6449171615dc56d9","spec":{"name":"vim-sensible","src":"https://github.com/tpope/vim-sensible"},"path":"/home/kev/.local/share/nvim/site/pack/core/opt/vim-sensible"},{"active":false,"rev":"a2e1f2b2e2e5a4c1d0f9b8a7c6d5e4f3a2b1c0d9","spec":{"name":"plenary.nvim","src":"https://github.com/nvim-lua/plenary.nvim"},"path":"/home/kev/.local/share/nvim/site/pack/core/opt/plenary.nvim"}]
install(package_id, version=None)[source]¶

Install one package.

Loading is turned off so the freshly cloned plugin’s own code is not sourced into the throw-away process mpm drives.

$ nvim --clean --headless \
> -c 'lua vim.pack.add({{src = "https://github.com/tpope/vim-sensible"}}, {confirm = false, load = false}) os.exit(0)' \
> -c 'cquit'
Return type:

str

upgrade_all_cli()[source]¶

Generates the CLI to upgrade all packages.

$ nvim --clean --headless \
> -c 'lua vim.pack.update(nil, {force = true}) os.exit(0)' \
> -c 'cquit'
Return type:

tuple[str, ...]

upgrade_one_cli(package_id, version=None)[source]¶

Generates the CLI to upgrade one package.

$ nvim --clean --headless \
> -c 'lua for _, p in ipairs(vim.pack.get(nil, {info = false})) do if p.spec.src == "https://github.com/tpope/vim-sensible" then vim.pack.update({p.spec.name}, {force = true}) end end os.exit(0)' \
> -c 'cquit'
Return type:

tuple[str, ...]

remove(package_id)[source]¶

Remove one package.

$ nvim --clean --headless \
> -c 'lua for _, p in ipairs(vim.pack.get(nil, {info = false})) do if p.spec.src == "https://github.com/tpope/vim-sensible" then vim.pack.del({p.spec.name}, {force = true}) end end os.exit(0)' \
> -c 'cquit'
Return type:

str