An optimized, minimalist, and zero-dependency lazy-loader and
vim.packwrapper for Neovim (0.13+).
Resonance.nvim is born out of a desire for extreme performance and simplicity. It strips away the bloat of traditional package managers while keeping the most powerful features: lazy-loading, automatic build hooks, and an elegant UI.
β€οΈSpecial Thanks to: CWorld1.
snacks.nvim or nui.nvim are detected.Event, Cmd, Keys, or FileType.PackChanged events to automatically run make, cargo, or custom Lua functions when a plugin is installed or updated.vim.pack.get() and displays the commits from the installed revision to the resolved target revision.vim.pack and modern vim.system APIs.[!TIP] Please enable UI2 for better experience.
https://github.com/user-attachments/assets/f37b574f-6061-493b-95cb-9e9478616b05
Add this bootstrap snippet to your init.lua. It ensures resonance.nvim is downloaded and prepended to your runtime path on the first run.
-- =====================================================================
-- π΅ Bootstrap Resonance.nvim
-- =====================================================================
-- You can also use the link from codeberg
local plugin_url = 'https://github.com/Imngzx/resonance.nvim'
local pack_path = vim.fn.stdpath('data') .. '/site/pack/core/opt/resonance.nvim'
if not vim.uv.fs_stat(pack_path) then
vim.notify('σ±½ Resonating (Downloading resonance.nvim)...', vim.log.levels.INFO)
vim.system({ 'git', 'clone', '--filter=blob:none', plugin_url, '--branch=main',
pack_path }):wait()
end
vim.opt.rtp:prepend(pack_path)
-- =====================================================================
-- π Configuration
-- =====================================================================
local resonance = require('resonance')
resonance.load({
'https://github.com/Imngzx/resonance.nvim',
version = 'main',
event = 'VimEnter',
keys = {
{ 'n', '<leader>pL', '<cmd>Resonance<cr>', { desc = '[Float] Resonance UI' } },
},
config = function()
resonance.setup({
ui = {
border = 'rounded',
width = 0.65,
height = 0.75,
}
})
end
})
-- NOTE: must put this at the end of your init.lua!
resonance.trigger_verylazy()
Because Resonance.nvim uses Neovim's native C-API (nvim_create_autocmd) under the hood, it supports all native Neovim events out of the box.
You can define events as a string, a table of multiple strings, or a detailed User event table.
Here are the most commonly used native events for lazy-loading plugins:
VimEnter, UIEnterBufReadPre, BufReadPost, BufNewFile, BufEnterInsertEnter, CmdlineEnter, VisualEnterCursorMoved, FocusGained, TextYankPost-- Single event
event = "VimEnter"
-- Multiple events
event = { "BufReadPost", "BufNewFile" }
-- Trigger when entering Insert or Command mode (Great for completion plugins)
event = { "InsertEnter", "CmdlineEnter" }
For ecosystem-specific events (like the famous VeryLazy triggered by resonance.trigger_verylazy()), you must use the strict Neovim native format for User autocmds:
Examples:
-- Trigger on VeryLazy
event = { "User", pattern = "VeryLazy" }
-- Trigger on other custom patterns (e.g. Mason load)
event = { "User", pattern = "MasonLoaded" }
Resonance accepts native vim.pack fields: src, name, version, and data. A source can also be supplied as the first positional value or through the url compatibility alias; Resonance normalizes both to src before calling vim.pack.add().
Each entry needs at least one lazy trigger: event, cmd, keys, or ft.
local resonance = require('resonance')
resonance.load({
{
src = "https://github.com/<author>/<plugin1_name>",
dependencies = "https://github.com/<author>/<plugin2_name>",
build = 'make', -- npm i or others based on plugin's docs
cmd = {'cmd1', 'cmd2'},
keys = {
{ 'n', '<leader>Tg', '<cmd>cmd1<CR>', { desc = 'Open something' } },
{ 'n', '<leader>TL', '<cmd>cmd2<CR>', { desc = 'Do something' } },
},
event = { "BufReadPre", "BufNewFile" },
-- For VeryLazy, use: event = { "User", pattern = "VeryLazy" }
config = function()
local name = require('plugin1_name')
name.setup({
-- Config here...
})
end
},
{ -- another plugin...},
{ -- another plugin...},
})
Resonance provides a clean, zero-hack API to retrieve plugin statistics and exact startup times, heavily inspired by lazy.nvim.
Because Resonance locks the "Time to UI" exactly at the first moment require('resonance').stats() is called, placing this in your dashboard's render function guarantees the most accurate startup time measurement.
stats() APIlocal stats = require("resonance").stats()
-- returns:
-- {
-- count = 37, -- Total number of plugins managed
-- loaded = 20, -- Plugins loaded at startup
-- startuptime = 24.5,-- Startup time in milliseconds (Time to UI)
-- times = { ... } -- Table containing load times for individual plugins
-- }
require("snacks").setup({
dashboard = {
sections = {
{ section = 'header' },
{ section = 'keys', gap = 1, padding = 1 },
function()
local stats = require("resonance").stats()
local ms = string.format("%.2f ms", stats.startuptime)
return {
align = 'center',
text = {
{ "σ± ", hl = "Special" },
{ stats.loaded .. " / " .. stats.count, hl = "Special" },
{ " plugins loaded in ", hl = "Comment" },
{ ms, hl = "Special" },
},
padding = 1,
}
end,
}
}
})
local alpha = require("alpha")
local dashboard = require("alpha.themes.dashboard")
-- ... (your header and buttons configuration) ...
-- Dynamically generate the footer
dashboard.section.footer.val = function()
local stats = require("resonance").stats()
local ms = string.format("%.2f ms", stats.startuptime)
return "σ± " .. stats.loaded .. " / " .. stats.count .. " plugins loaded in " .. ms
end
-- Optional: apply highlight group to footer
dashboard.section.footer.opts.hl = "Comment"
alpha.setup(dashboard.opts)
local starter = require("mini.starter")
starter.setup({
-- ... (your items and hooks) ...
footer = function()
local stats = require("resonance").stats()
local ms = string.format("%.2f ms", stats.startuptime)
return "σ± " .. stats.loaded .. " / " .. stats.count .. " plugins loaded in " .. ms
end
})
[!TIP] If you want a very "honest" startuptime, please add this on top of your init.lua.
-- enable this for a "very" honest startuptime :)
_G.start_time = vim.uv.hrtime()
U : Update all plugins (vim.pack.update()).u : Update the plugin at the cursor (vim.pack.update()).dd: Delete the plugin at the cursor.c : Check out an available branch, commit, or tag.r : Check for pending updates (vim.pack.get() fetches and resolves package revisions).S : Search inside plugins source code (Powered by Snacks.picker / Telescope / Native vimgrep).g : Check Dependency Graph (DAG) and Event Replay.s : Skip plugin update.D : Open plugin directory.q / Esc : Quit.This project is licensed under the MIT License.