Spec Examples
April 8, 2026 ยท View on GitHub
Plugin Spec
return {
'nvim-mini/mini.bracketed',
-- If `opts` or `config = true` is set, the config hook calls
-- `require(MAIN).setup(opts)` by default.
opts = {}, -- calls `require('mini.bracketed').setup({})`
}
return {
'nvim-lualine/lualine.nvim',
opts = { theme = 'tokyonight' },
-- Explicitly define a `config` function hook if you need to run custom logic on plugin load.
-- The resolved `zpack.Plugin` and `opts` table are passed as its arguments:
config = function(_, opts)
vim.opt.showmode = false
require('lualine').setup(opts)
end,
}
Lazy Load on Command
return {
'nvim-tree/nvim-tree.lua',
cmd = { 'NvimTreeToggle', 'NvimTreeFocus' },
opts = {},
}
Lazy Load on Keymap
return {
'folke/flash.nvim',
keys = {
{ 's', function() require('flash').jump() end, mode = { 'n', 'x', 'o' }, desc = 'Flash' },
{ 'S', function() require('flash').treesitter() end, mode = { 'n', 'x', 'o' }, desc = 'Flash Treesitter' },
},
opts = {},
}
Lazy Load on Event
return {
'windwp/nvim-autopairs',
event = 'InsertEnter', -- Also supports 'VeryLazy'
opts = {},
}
Lazy Load on Event with Pattern
-- Inline pattern
return {
'rust-lang/rust.vim',
event = 'BufReadPre *.rs',
}
-- Or using EventSpec for multiple patterns
return {
'polyglot-plugin',
event = {
event = 'BufReadPre',
pattern = { '*.lua', '*.rs' },
},
opts = {},
}
Lazy Load on FileType
Load plugin when opening files of specific types. Automatically re-triggers BufReadPre, BufReadPost, and FileType events to ensure LSP clients and Treesitter attach properly:
return {
'rust-lang/rust.vim',
ft = { 'rust', 'toml' },
}
Conditional Loading
Use enabled to skip vim.pack.add entirely, or cond to conditionally load after calling vim.pack.add:
return {
'project-specific-plugin',
enabled = vim.fn.has('linux') == 1, -- skip installation
cond = function() return vim.fn.filereadable('.project-marker') == 1 end, -- skip loading
opts = {},
}
Build Hook
return {
'nvim-telescope/telescope-fzf-native.nvim',
build = 'make',
}
Dependencies
return {
'nvim-telescope/telescope.nvim',
cmd = 'Telescope',
dependencies = {
'nvim-lua/plenary.nvim',
{ 'nvim-tree/nvim-web-devicons', opts = {} },
},
}
Dependencies are automatically loaded before the parent plugin when the parent's lazy trigger fires.
Version Pinning
vim.pack.add expects version to be string|vim.VersionRange:
return {
'mrcjkb/rustaceanvim',
version = vim.version.range('^6'), -- semver version
-- version = 'main', -- branch
-- version = 'v1.0.0', -- tag
-- version = 'abc123', -- commit
}
See :h vim.pack.Spec, :h vim.version.range(), and :h vim.VersionRange.
Version Pinning for lazy.nvim compatibility
return {
'mrcjkb/rustaceanvim',
sem_version = '^6', -- corresponds to lazy.nvim spec's `version`, auto-wrapped to vim.version.range()
-- branch = 'main',
-- tag = 'v1.0.0',
-- commit = 'abc123',
}
Load Priority
Control plugin load order with priority (higher values load first; default: 50):
-- to load colorscheme early
return {
'folke/tokyonight.nvim',
priority = 1000,
config = function() vim.cmd('colorscheme tokyonight') end,
}
Using Plugin Data in Hooks
All lifecycle hooks (init, config, build, cond) and lazy-loading triggers (event, cmd, keys, ft) can be functions that receive a zpack.Plugin object containing the resolved plugin path and spec:
return {
'some/plugin',
build = function(plugin)
-- plugin.path: absolute path to the plugin directory
-- plugin.spec: the vim.pack.Spec with resolved name, src, version
vim.fn.system({ 'make', '-C', plugin.path })
end,
}
Explicit Main Module
If automatic module detection fails, specify the module explicitly with main:
return {
'some/plugin-with-unusual-structure',
main = 'plugin.core',
opts = {},
}
Multiple Plugins in One File
return {
{ 'nvim-lua/plenary.nvim' },
{ 'nvim-tree/nvim-web-devicons' },
{ 'nvim-lualine/lualine.nvim', opts = { theme = 'auto' } },
{ import = 'plugins.mini' },
}
Real-World Config
For more examples, refer to example config: