plenary.nvim: the Lua utility library Neovim plugins depend on, and what its archive notice means for you
plenary: full; complete; entire; absolute; unqualified. All the lua functions I don't want to write twice.
At a glance
- What is it?
- plenary.nvim bundles async coroutines, process jobs, path handling, recursive scanning and a busted-style test harness into one Lua dependency. The README now says it is no longer actively maintained and will be archived soon, with critical bugs addressed only until 2026-06-30.
- Who is it for?
- Adopt plenary.nvim if you run a Neovim plugin that requires it, or if you are writing a plugin that needs async coroutines, job control or a busted-style test harness and want a dependency most plugin authors already have. Do not adopt it for new standalone Lua work outside Neovim: the README states the library is useless outside of Neovim, and it is not a general-purpose Lua toolkit.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 174 days ago.
- What is it written in?
- Mainly Lua, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem plenary.nvim solves: the same Lua helpers, rewritten in every plugin
Neovim plugins repeatedly need the same small set of capabilities. Reading a file without blocking the editor. Spawning a process and collecting its stdout. Joining paths without string concatenation bugs. Walking a directory tree. Running tests in a headless Neovim instance. Each plugin author can write these themselves, and many did, which is how the same helper ends up duplicated across dozens of repositories. plenary.nvim exists to be the shared copy: the README describes it as "All the lua functions I don't want to write twice." The name is defined in the same file as "full; complete; entire; absolute; unqualified."
The audience is Neovim plugin authors first and end users second. A user almost never installs plenary.nvim for its own sake. They install it because telescope.nvim, neogit, neo-tree.nvim or vgit.nvim lists it as a dependency, and the README names exactly those four plugins under "Plugins using this." If you are writing Lua that runs inside Neovim and you need coroutine-based I/O or process control, this is the library the surrounding ecosystem already assumes. If you are writing Lua that runs anywhere else, the README is direct: the library "is useless outside of Neovim since it requires Neovim functions."
Inside plenary.nvim: coroutines over libuv, jobs, paths and a test harness
The module list in the README is the architecture. plenary.async is the largest piece: a coroutine layer built on native Lua coroutines and libuv. The README's own example shows the transformation it offers. A raw libuv file read nests four callbacks (fs_open, fs_fstat, fs_read, fs_close) inside each other. The plenary version writes the same sequence as straight-line code, because the async module suspends the coroutine at each call and resumes it when libuv reports back. That is cooperative concurrency, and the README notes it also allows cancellation.
On top of that sit channel primitives. plenary.async.control.channel.oneshot creates a channel that can send data exactly once, with an async receiver and a non-async sender. plenary.async.control.channel.mpsc is a multiple-producer single-consumer channel, demonstrated with two producer coroutines sending values and a loop receiving four of them. plenary.async_lib is the version 1 API, kept "just here for compatibility reasons," and the README tells you to use plenary.async instead.
The remaining modules are narrower. plenary.job wraps system processes: you pass command, args, env and cwd, define optional on_stdout, on_stderr and on_exit callbacks, then call start() or sync(). One detail in the README is easy to miss and will break commands that expect a normal shell: "Each job has an empty environment." plenary.path is explicitly modelled on Python's pathlib. plenary.scandir does recursive directory walks with options for depth and hidden files, plus on_insert and on_exit callbacks, and the README compares it to unix find or fd. plenary.context_manager implements Python's with and open. plenary.test_harness runs busted-style specs in separate Neovim instances. plenary.filetype and plenary.strings round out the list.
Installing plenary.nvim and running a first job
The README gives plugin-manager snippets rather than a standalone installer. With vim-plug the line is a single Plug entry:
Plug 'nvim-lua/plenary.nvim'With packer the equivalent is a use line:
use "nvim-lua/plenary.nvim"The repository also carries a rockspec, plenary.nvim-scm-1.rockspec, and the README links a LuaRocks badge for the module Conni2461/plenary.nvim, so LuaRocks is the other distribution path the project points at. For a lazy.nvim setup the README gives nothing, which is why "plenary nvim lazy" is a phrase people search for; the practical answer is that lazy.nvim loads it as a dependency of whichever plugin declares it, and you add an explicit spec only when something fails to load.
A first real use is plenary.job. The README's example runs ripgrep and prints the exit value and the collected output:
local Job = require'plenary.job'
Job:new({
command = 'rg',
args = { '--files' },
cwd = '/usr/bin',
env = { ['a'] = 'b' },
on_exit = function(j, return_val)
print(return_val)
print(j:result())
end,
}):sync() -- or start()Calling sync() blocks until the process finishes; calling start() returns immediately and lets on_exit fire later. If you swap in a command that depends on PATH or HOME, remember the empty-environment note from the README and pass env explicitly.
The archive notice is the real limitation, not the API
The first substantive block in the README is not documentation. It says the repository "is no longer actively maintained and will be officially archived soon," that critical bugs may still be addressed until 2026-06-30, that no new features will be added, and that ongoing support should not be expected. The last push to the repository was on 2026-04-10. Those two facts together mean the project is in a wind-down, whatever its dependency graph looks like. Any article calling it actively maintained is reading the wrong part of the file.
That changes what a limitation means here. A normal critique would point at missing modules or rough edges. The honest critique is lifecycle: if you file a bug after 2026-06-30, the README has already told you not to expect a response. The code does not stop working when the repository is archived, and the MIT licence means it cannot be taken away, but the queue of fixes closes.
There is a second, smaller limitation in the design itself. The async layer is cooperative, which means a coroutine that never yields stalls everything scheduled around it. The README presents this as a feature ("easy cooperative concurrency and cancellation") and it is, but it is also the constraint: nothing preempts a badly behaved task. And plenary.nvim is the wrong tool for any Lua program outside Neovim, which the README states outright.
Alternatives to plenary.nvim, and where they differ
The closest alternative is writing the helpers yourself, which is what the README implicitly argues against. A plugin that needs one file read does not need a dependency: vim.loop (libuv) is available in Neovim directly, and the README's own before-example shows the callback code that costs you. The difference is scope. Pulling in plenary.nvim gets you async, jobs, paths, scanning, context managers and a test harness in one dependency; writing it yourself gets you exactly the two functions you need with no third party in your plugin's install path. For a plugin that already depends on telescope.nvim, the dependency is present anyway and the calculation changes.
The other real alternative is a different plugin manager or distribution route rather than a different library, which is what the search phrase "plenary.nvim alternative" tends to surface. That is a category error: plenary.nvim is not a plugin manager, it is a library that managers install. If you are choosing between lazy.nvim, packer and vim-plug, plenary.nvim is orthogonal to that decision, and the README shows snippets for two of those three.
Where plenary.nvim genuinely has no drop-in replacement is the test harness. PlenaryBustedDirectory runs *_spec.lua files in separate headless Neovim instances with a minimal runtimepath, and the Makefile in the repository uses exactly that command for its own test target. Reproducing that isolation yourself is more work than the module it replaces.
Running the test harness and keeping the dependency current
For plugin authors, the test harness is the part worth adopting even if you write your own path helpers. The README documents a keymap for running the current spec file in a floating window:
nmap <leader>t <Plug>PlenaryTestFileThat run uses a minimal configuration whose runtimepath contains only plenary.nvim and the current working directory. For a whole directory from the command line, the README gives:
nvim --headless -c "PlenaryBustedDirectory tests/plenary/ {options}"The first argument is the directory, and files matching *_spec.lua are executed in separate Neovim instances. Without a second argument the minimal configuration applies; otherwise the second argument is a Lua option table, whose documented fields include nvim_cmd (defaulting to vim.v.progpath) and init. The repository's own Makefile shows the fuller form, adding minimal_init and sequential:
nvim --headless --noplugin -u scripts/minimal.vim -c "PlenaryBustedDirectory tests/plenary/ {minimal_init = 'tests/minimal_init.vim', sequential = true}"Upgrade cost is low in the ordinary case, because there are no retrieved releases to pin against and the project is winding down: you track the master branch and it stops moving. The licence is MIT, which permits commercial and closed-source use and requires preserving the copyright notice; that is a description of the licence text, not legal advice. The dependency cost is the one that matters. Every plugin that requires plenary.nvim carries it into your configuration, and when the repository is archived, the version you have is the version you keep.
Editorial conclusion
Adopt plenary.nvim if you run a Neovim plugin that requires it, or if you are writing a plugin that needs async coroutines, job control or a busted-style test harness and want a dependency most plugin authors already have. Do not adopt it for new standalone Lua work outside Neovim: the README states the library is useless outside of Neovim, and it is not a general-purpose Lua toolkit. Before you build on it, verify which module your plugin actually calls, since plenary.async_lib is kept only for compatibility and the README directs new code to plenary.async instead. Then read the notice at the top of the README and decide whether a dependency whose critical-bug window ends on 2026-06-30 belongs in your plugin's long-term plan.
Frequently asked questions
How do I install plenary.nvim?
The README gives plugin-manager snippets: Plug 'nvim-lua/plenary.nvim' for vim-plug and use "nvim-lua/plenary.nvim" for packer. The repository also ships a rockspec and links a LuaRocks badge for the module Conni2461/plenary.nvim. There is no standalone installer documented.
What is plenary.nvim?
It is a Lua library for Neovim that collects the functions its author did not want to write twice, described in the README as "full; complete; entire; absolute; unqualified." Its modules cover async coroutines, process jobs, paths, recursive scanning, context managers, filetypes, strings and a busted-style test harness.
What does plenary.nvim do?
It provides shared Lua utilities for Neovim plugins. plenary.async turns libuv callbacks into straight-line coroutine code, plenary.job runs system processes with on_stdout, on_stderr and on_exit callbacks, plenary.path mirrors Python's pathlib, and plenary.scandir does recursive directory walks. The README states the library is useless outside of Neovim.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nvim-lua-plenary-nvim)