README.md

May 16, 2026 · View on GitHub

leanpack.nvim logo

Leanpack.nvim

Latest release Last commit License Stars Issues

A layer on top of Neovim's native vim.pack, adding support for lazy-loading and the widely adopted lazy.nvim-like declarative spec.

Requirements: Neovim 0.12+

Documentation

DocumentDescription
Getting StartedQuick start guide
InstallationDetailed installation options
ConfigurationAll configuration options
Plugin SpecComplete plugin specification reference
Lazy LoadingLazy loading triggers and patterns
CommandsCLI commands reference
APILua API reference
MigratingMigration guide from lazy.nvim

Quick Start

Bootstrap

Add this to the top of your init.lua:

-- Setup leanpack.nvim plugin manager
vim.pack.add({ { src = "https://github.com/ntk148v/leanpack.nvim" } })

-- Setup leanpack with import from lua/plugins/
require("leanpack").setup({
    { import = "plugins" },
    defaults = {
        lazy = true,
    },
    performance = {
        vim_loader = true,
        rtp_prune = true,
    },
})

Create Specs

Create your plugin specs in lua/plugins/:

-- lua/plugins/treesitter.lua
return {
  'nvim-treesitter/nvim-treesitter',
  build = ':TSUpdate',
  config = function()
    require('nvim-treesitter.configs').setup({ highlight = { enable = true } })
  end,
}

Why leanpack.nvim over bare vim.pack?

vim.pack (Neovim 0.12+) is a solid native foundation — leanpack builds on top of it, not around it. Here's what you get:

Featurebare vim.packleanpack.nvim
Spec formatRaw vim.pack.add() callslazy.nvim-compatible declarative spec ('user/repo', opts = {}, config = fn)
Lazy-loadingManual — write your own VimEnter queues and autocmds per pluginBuilt-in triggers: event, cmd, keys, ft, module (require-based)
DependenciesManual orderingAutomatic resolution with topological sort
Build hooksNonebuild = ':TSUpdate' or build = function() ... end
Plugin management UINone:Leanpack floating window with filtering, load/update/delete
Install/UpdateManual vim.pack.add() + restartBackground jobs via headless Neovim, no restart needed
ftdetect sourcingManualAutomatic for lazy-loaded plugins
Config from multiple filesManual require chains{ import = "plugins" } auto-discovers lua/plugins/*.lua

In short: if you're happy writing ~250 lines of helper code (lazyload queues, deep merge, local dev support) around vim.pack for every config, you don't need leanpack. If you want a lazy.nvim-style declarative experience on top of native vim.pack, that's exactly what this is.

Features

  • Native Core: Builds on top of vim.pack — no custom package management, no fork.
  • Lazy-loading: Load plugins on demand via events, commands, keymaps, filetypes, or require().
  • lazy.nvim Compatible: Uses the same declarative spec format you already know.
  • Dependency Management: Automatic resolution and topological loading.
  • Build Hooks: Run commands or Lua functions on install/update.
  • Performance: Built-in vim.loader integration and RTP pruning.

Commands

  • :Leanpack - Open the UI (supports / filtering)
  • :Leanpack sync - Sync all plugins (update + clean)
  • :Leanpack update - Update all or specific plugin
  • :Leanpack clean - Remove unused plugins
  • :Leanpack build! - Run all build hooks
  • :Leanpack load! - Load all pending plugins

See Commands for details.

Configuration

require('leanpack').setup({
  defaults = {
    confirm = true,
  },
  performance = {
    vim_loader = true,
    rtp_prune = true, -- Disable built-in plugins for faster startup
  },
})

See Configuration for more options.

Migrating from lazy.nvim

Most of your lazy.nvim plugin specs will work as-is with leanpack. Key differences are documented in Migrating.

  • version pinning: leanpack's version field supports both semantic versioning (e.g., 1.*) and literal git references (branch/tag/commit).
  • dev mode: Use dev = true with dir = '~/projects/plugin-name' for local development
  • optional: Use optional = true for dependencies that won't block plugin loading
  • module trigger: leanpack automatically supports require()-based lazy loading matching the auto-detected or explicit main module names.

Acknowledgements

  • Inspired by lazy.nvim for the declarative spec design