A modern, lightweight plugin manager for Neovim with a beautiful UI, intelligent dependency management, and automatic plugin setup.
- 🚀 Fast Installation: Quick plugin installation with progress tracking
- 🎨 Beautiful UI: Modern floating window interface
- đź”— Dependency Management: Automatic dependency resolution
- đź§ą Auto Cleanup: Remove unused plugins automatically
- đź”§ Post-Install Commands: Execute build commands after installation/update
- ⚙️ Auto Setup: Automatically set up plugins from
.config.luafiles - 📦 Import Support: Load plugin configurations from non-standard files using the
importsfield - 🌳 Nested Imports: Support for arbitrary depth nested import structures
If you're using another plugin manager to install Synapse.nvim:
-- Example with any plugin manager
{
"OriginCoderPulse/synapse.nvim",
config = function()
require("synapse").setup({})
end,
}- Clone the repository:
git clone https://github.com/OriginCoderPulse/synapse.nvim.git ~/.config/nvim/lua/synapse- Add to
init.lua:
vim.opt.rtp:prepend("<you_package_path>/synapse.nvim")
require("synapse").setup({}){
method = "https", -- or "ssh"
opts = {
-- Custom plugin installation directory (optional)
package_path = os.getenv("HOME") .. "/.nvim-utils/package",
-- Directory to scan for .config.lua files (optional)
-- Default: vim.fn.stdpath("config")
config_path = vim.fn.stdpath("config"),
-- Performance optimizations
performance = {
reset_packpath = true,
rtp = {
reset = true,
paths = {},
disabled_plugins = {},
},
},
},
-- Import field: Load configurations from non-standard files
-- Supports arbitrary depth nested structures
imports = {
lua = {
test = {
test1 = { "ok" }, -- Loads config_path/lua/test/test1/ok.lua
},
},
},
keys = {
download = "<leader>si",
remove = "<leader>sr",
upgrade = "<leader>su",
},
}| Option | Type | Default | Description |
|---|---|---|---|
method |
string |
"https" |
Git method for cloning repositories. Options: "https" or "ssh" |
opts.package_path |
string |
vim.fn.stdpath("data") .. "/package" |
Directory where plugins will be installed |
opts.config_path |
string |
vim.fn.stdpath("config") |
Directory to scan for .config.lua files (recursive) |
opts.default |
string |
"OriginCoderPulse/synapse.nvim" |
Default plugin repository to install |
opts.ui.style |
string |
"float" |
UI window style. Options: "float", "split" |
opts.performance.reset_packpath |
boolean |
true |
Reset the package path to improve startup time |
opts.performance.rtp.reset |
boolean |
true |
Reset the runtime path to basic paths |
opts.performance.rtp.paths |
string[] |
{} |
Custom paths to include in the runtime path |
opts.performance.rtp.disabled_plugins |
string[] |
{} |
List of plugins to disable |
imports |
table |
nil |
Import configurations from non-standard files |
keys.download |
string |
"<leader>si" |
Keymap to open plugin installation UI |
keys.remove |
string |
"<leader>sr" |
Keymap to open plugin removal UI |
keys.upgrade |
string |
"<leader>su" |
Keymap to open plugin upgrade UI |
The imports field supports arbitrary depth nested structures:
imports = {
lua = {
"config1", -- Loads config_path/lua/config1.lua
test = {
"config2", -- Loads config_path/lua/test/config2.lua
test1 = { "config3" }, -- Loads config_path/lua/test/test1/config3.lua
},
},
}Rules:
- Array elements (numeric keys with string values) are appended directly to the current path
- String keys create subdirectories and continue recursion
- Mixed arrays and string keys in the same table are both processed
Create .config.lua files in your config_path directory (or subdirectories). These files support both plugin installation configuration and automatic setup.
Important: Only files ending with .config.lua will be recognized and automatically processed. For non-standard files, use the imports field in your main configuration.
Each .config.lua file must return a table with the following fields:
| Field | Type | Description | Example |
|---|---|---|---|
repo |
string |
Plugin repository URL in format "username/repository" |
"nvim-lualine/lualine.nvim" |
| Field | Type | Description | Example |
|---|---|---|---|
tag |
string |
Lock plugin to a specific version tag. Takes precedence over branch |
"v1.2.3" |
branch |
string |
Clone a specific branch. Only used if tag is not specified |
"main" |
execute |
string|table |
Commands to run after installation/update | "make" or { "make", "cargo build --release" } |
primary |
string |
Custom plugin name for require(). Use if the actual require name differs from the extracted name |
"custom-name" |
depend |
table |
Plugin dependencies. See dependency format below | See examples |
| Field | Type | Description | Example |
|---|---|---|---|
opts |
table |
Configuration table passed to plugin.setup(opts). Automatically calls plugin.setup(opts) if the plugin has a setup function |
{ option1 = "value1" } |
config |
function |
Manual setup function. Use for custom setup logic. Receives the plugin module as parameter if available | function(plugin) plugin.setup({}) end |
initialization |
function |
Function executed before plugin.setup(). Receives a package wrapper for accessing plugin submodules |
function(package) local install = package({ "install" }) end |
Note: All plugins are loaded immediately on startup. Plugins are automatically added to the runtime path and configured during Neovim initialization.
Dependencies can be specified in two formats:
Simple format:
depend = {
"username/dependency",
}With configuration:
depend = {
{
"username/dependency",
primary = "custom-name", -- Optional
opt = { -- Optional: configuration for dependency
option1 = "value1",
}
}
}-- ~/.config/nvim/lua/pkgs/lualine.config.lua
return {
repo = "nvim-lualine/lualine.nvim",
primary = "lualine",
opts = {
options = {
theme = "auto",
icons_enabled = true,
},
},
}-- ~/.config/nvim/lua/pkgs/autopairs.config.lua
return {
repo = "windwp/nvim-autopairs",
primary = "nvim-autopairs",
config = function(plugin)
plugin.setup({})
-- Additional integration code
end,
}-- ~/.config/nvim/lua/pkgs/tree-sitter.config.lua
return {
repo = "nvim-treesitter/nvim-treesitter",
primary = "nvim-treesitter.configs",
initialization = function(package)
-- Access submodules: package({ "submodule" }) or package.submodule
local install = package({ "install" })
install.prefer_git = true
-- Support for nested structures
local nested = package({ test = { test1 = { "ok" } } })
end,
opts = {
-- Tree-sitter configuration
},
}-- ~/.config/nvim/lua/pkgs/mason.config.lua
return {
repo = "williamboman/mason.nvim",
primary = "mason",
depend = {
{
"williamboman/mason-lspconfig.nvim",
primary = "mason-lspconfig",
opt = {
ensure_installed = { "lua_ls", "pyright" },
automatic_installation = true,
}
},
},
opts = {
-- Mason configuration
},
}-- ~/.config/nvim/lua/pkgs/versioned.config.lua
return {
repo = "username/plugin-name",
tag = "v1.2.3",
opts = {
option1 = "value1",
},
}-- ~/.config/nvim/lua/pkgs/compiled.config.lua
return {
repo = "username/compiled-plugin",
execute = {
"make",
"cargo build --release",
},
opts = {
option1 = "value1",
},
}-- ~/.config/nvim/lua/configs/custom.config.lua
-- Files without a 'repo' field are treated as generic configuration files
return {
config = function()
-- Your custom configuration code
vim.opt.number = true
vim.opt.relativenumber = true
end,
}-- ~/.config/nvim/init.lua
require("synapse").setup({
opts = {
config_path = vim.fn.stdpath("config"),
},
imports = {
lua = {
test = { "config" }, -- Loads ~/.config/nvim/lua/test/config.lua
},
},
})
-- ~/.config/nvim/lua/test/config.lua (not a .config.lua file)
return {
repo = "username/plugin-name",
opts = {
option1 = "value1",
},
}:SynapseDownload: Open plugin installation UI:SynapseRemove: Open plugin removal UI:SynapseUpgrade: Open plugin upgrade UI:SynapseError: Show all error messages
<leader>si: Open plugin installation UI (SynapseDownload)<leader>sr: Open plugin removal UI (SynapseRemove)<leader>su: Open plugin upgrade UI (SynapseUpgrade)
You can customize these keymaps in your configuration:
require("synapse").setup({
keys = {
download = "<leader>pi", -- Custom keymap
remove = "<leader>pr",
upgrade = "<leader>pu",
},
})- Installation: Create
.config.luafiles in yourconfig_pathdirectory, or use theimportsfield to load configurations from non-standard files - Auto-Setup: On Neovim startup, Synapse scans for
.config.luafiles and import files, then automatically:- Adds all installed plugins to the runtime path
- Loads plugin configurations
- Calls
plugin.setup(opts)for plugins withoptsfield - Executes
configfunction for plugins withconfigfield - Applies dependency configurations
- Loading Order:
- All plugins are added to the runtime path first
- Main plugins are set up (non-plugin config files are executed)
- Then dependency configurations are applied
- All plugins are available immediately after startup
Synapse.nvim uses a structured directory layout for plugin management:
- Main plugins:
package_path/plugin-name/plugin-name/ - Dependencies:
package_path/main-plugin-name/depend/dependency-name/ - Shared dependencies:
package_path/public/dependency-name/ - Synapse plugin:
package_path/synapse.nvim/
- Ensure configuration files end with
.config.luaand are inconfig_pathdirectory (supports subdirectories) - For non-standard files, use the
importsfield in your main configuration - Check that files return a table with a
repofield (for plugin configs) or aconfigfunction (for generic configs) - Verify
repofield is not empty for plugin configurations
- Verify the plugin has a
setupfunction if usingoptsformat - Check that
optsis a table type (not a function) - For manual setup, use
configfunction format - Ensure the plugin is properly installed before setup
- Check that the plugin is added to the runtime path
- Verify the plugin is installed in the correct directory structure
- Check that
package_pathis correctly configured - Ensure the plugin name matches the directory name
- Use the
primaryfield if the require name differs from the directory name
- Verify keymaps are not conflicting with other plugins
- Check that the setup function was called correctly
- Try using commands directly:
:SynapseDownload,:SynapseRemove,:SynapseUpgrade
See LICENSE file for details.