Skip to main content
Neovim from Scratch uses Packer as its plugin manager. This guide will show you how to add new plugins to your configuration.

Understanding the Plugin System

All plugins are managed in lua/user/plugins.lua. Packer automatically installs itself on first run and syncs plugins whenever you modify this file.

Auto-sync Feature

The configuration includes an autocommand that automatically runs PackerSync whenever you save plugins.lua:
vim.cmd([[
  augroup packer_user_config
    autocmd!
    autocmd BufWritePost plugins.lua source <afile> | PackerSync
  augroup end
]])
This means plugins are installed/updated automatically when you save the file.

Adding a New Plugin

Basic Plugin Installation

To add a new plugin, add a use statement inside the packer.startup function in lua/user/plugins.lua:
return packer.startup(function(use)
  -- Existing plugins...
  
  -- Add your new plugin
  use "author/plugin-name"
end)

Pinning to a Specific Commit

For stability, it’s recommended to pin plugins to specific commits (as done in the base configuration):
use { 
  "author/plugin-name", 
  commit = "abc123def456..." 
}
Example from the codebase:
use { 
  "nvim-lua/plenary.nvim", 
  commit = "4b7e52044bbb84242158d977a50c4cbcd85070c7" 
}

Plugin with Configuration

For plugins that require configuration, create a separate configuration file: Step 1: Add the plugin in lua/user/plugins.lua:
use { "kyazdani42/nvim-tree.lua", commit = "..." }
Step 2: Create lua/user/plugin-name.lua with your configuration:
local status_ok, plugin = pcall(require, "plugin-name")
if not status_ok then
  return
end

plugin.setup({
  -- Your configuration here
})
Step 3: Require it in lua/user/init.lua:
require "user.plugin-name"

Common Plugin Patterns

UI Plugin Example

Here’s how the nvim-tree file explorer is configured:
-- In lua/user/plugins.lua
use { 
  "kyazdani42/nvim-tree.lua", 
  commit = "7282f7de8aedf861fe0162a559fc2b214383c51c" 
}

-- Separate config file: lua/user/nvim-tree.lua
local status_ok, nvim_tree = pcall(require, "nvim-tree")
if not status_ok then
  return
end

nvim_tree.setup({
  -- configuration options
})

Colorscheme Plugin Example

Colorscheme plugins are simple to add:
use { 
  "folke/tokyonight.nvim", 
  commit = "66bfc2e8f754869c7b651f3f47a2ee56ae557764" 
}
use { 
  "lunarvim/darkplus.nvim", 
  commit = "13ef9daad28d3cf6c5e793acfc16ddbf456e1c83" 
}
See Colorschemes for details on activating them.

Completion Plugin Example

The nvim-cmp completion system shows a plugin with multiple dependencies:
-- Main plugin
use { 
  "hrsh7th/nvim-cmp", 
  commit = "b0dff0ec4f2748626aae13f011d1a47071fe9abc" 
}

-- Sources
use { "hrsh7th/cmp-buffer", commit = "..." }
use { "hrsh7th/cmp-path", commit = "..." }
use { "hrsh7th/cmp-nvim-lsp", commit = "..." }
use { "saadparwaiz1/cmp_luasnip", commit = "..." }

Manual Plugin Management

If auto-sync is disabled or you want to manually manage plugins, use these commands:

Packer Commands

  • :PackerSync - Install, update, and clean plugins
  • :PackerInstall - Install missing plugins
  • :PackerUpdate - Update installed plugins
  • :PackerClean - Remove unused plugins
  • :PackerCompile - Recompile the plugin loader
  • :PackerStatus - Show plugin status

Using Which-Key

Press <leader>p to access Packer commands via which-key:
  • <leader>pc - Compile
  • <leader>pi - Install
  • <leader>ps - Sync
  • <leader>pS - Status
  • <leader>pu - Update

Example: Adding a New Plugin

Let’s add the vim-surround plugin: Step 1: Open lua/user/plugins.lua:
nvim ~/.config/nvim/lua/user/plugins.lua
Step 2: Add the plugin in the packer.startup function:
return packer.startup(function(use)
  use { "wbthomason/packer.nvim", commit = "..." }
  -- ... other plugins
  
  -- Add vim-surround
  use "tpope/vim-surround"
  
  -- ... rest of plugins
end)
Step 3: Save the file - Packer will automatically install the plugin! Step 4: Restart Neovim to use the new plugin:
:quitall
nvim

Troubleshooting

Plugin Not Installing

  1. Check the plugin name is correct
  2. Run :PackerSync manually
  3. Check for errors with :PackerStatus
  4. View logs at ~/.cache/nvim/packer.nvim.log

Plugin Errors on Startup

  1. Check the plugin configuration file
  2. Ensure all dependencies are installed
  3. Use the protected call pattern:
local status_ok, plugin = pcall(require, "plugin-name")
if not status_ok then
  return
end

Reset Packer

If you encounter persistent issues:
rm -rf ~/.local/share/nvim/site/pack/packer
rm ~/.config/nvim/plugin/packer_compiled.lua
nvim
:PackerSync

Best Practices

  1. Pin commits for stability in production environments
  2. Use protected calls (pcall) to prevent startup errors
  3. Organize plugins by category (UI, LSP, completion, etc.)
  4. Create separate config files for complex plugins
  5. Comment your plugins to document their purpose
  6. Test new plugins in a branch before committing

Next Steps

Build docs developers (and LLMs) love