# How to Conditionally Enable Plugins in Neovim with Lazy.nvim

> Learn to conditionally enable plugins in Neovim with Lazy.nvim using cond and enabled keys. Optimize your startup by controlling plugin loading based on your needs.

- Repository: [jdhao/nvim-config](https://github.com/jdhao/nvim-config)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Lazy.nvim lets you conditionally enable plugins using the `cond` and `enabled` keys in your plugin specification, where `enabled` filters plugins once at startup and `cond` checks conditions right before loading.**

To keep your Neovim configuration fast and portable, you need to load plugins only when they are actually needed or available. In the **jdhao/nvim-config** repository, conditional plugin activation is implemented using Lazy.nvim's `cond` and `enabled` options to handle different operating systems, external dependencies, and UI contexts.

## Understanding the `cond` and `enabled` Keys

Lazy.nvim processes your plugin list in two stages, giving you fine-grained control over what gets loaded and when.

### The `enabled` Key: Static Startup Filtering

Use **`enabled`** when you want to completely omit a plugin from Neovim's runtime based on conditions that will not change during the session. You can assign a Boolean value or a function that returns `true` or `false`. Lazy.nvim evaluates this once during startup; if the result is `false`, the plugin is discarded entirely and never appears in your `:Lazy` list.

### The `cond` Key: Dynamic Loading Conditions

Use **`cond`** when you want to defer the decision until the plugin is about to load. This key accepts a function that Lazy.nvim evaluates immediately before triggering the plugin (on an `event`, `cmd`, `keys`, or other lazy-loading trigger). Returning `false` aborts the load for that session, but the plugin remains in the manager's index and can be loaded manually later.

## Practical Examples from jdhao/nvim-config

The file [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) demonstrates both approaches for different scenarios.

### Skip UI Plugins When Running Inside Firenvim

When Neovim runs as a browser editor via Firenvim, heavy UI plugins like status lines are unnecessary. The configuration uses `cond` to check `vim.g.started_by_firenvim` at the moment the plugin would load:

```lua
{
  "nvim-lualine/lualine.nvim",
  event = "BufRead",
  cond = function()
    return not vim.g.started_by_firenvim
  end,
  config = function() require("config.lualine") end,
}

```

This pattern appears in [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) (lines 18-21), where a helper function `firenvim_not_active` wraps the same logic.

### Load OS-Specific Plugins Like gx.nvim

The `gx.nvim` plugin opens URLs with the system browser, but the configuration only installs it on Windows or macOS. This uses `enabled` with a function checking global variables set elsewhere in the config:

```lua
{
  "chrishrb/gx.nvim",
  keys = { { "gx", "<cmd>Browse<cr>", mode = { "n", "x" } } },
  enabled = function()
    return vim.g.is_win or vim.g.is_mac
  end,
  config = function() require("config.gx") end,
}

```

You can find this specification in [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) (lines 48-51).

### Require External Dependencies Like ctags

The `vista.vim` plugin provides symbol navigation but requires `ctags` to be present on the system. The configuration uses `enabled` with a utility function to verify the binary exists before adding the plugin to the list:

```lua
{
  "liuchengxu/vista.vim",
  cmd = "Vista",
  enabled = function()
    return utils.executable("ctags")
  end,
  init = function()
    -- plugin configuration...
  end,
}

```

The `utils.executable` function is defined in [`lua/utils.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/utils.lua) and checks the system `PATH` for the executable. This example is located in [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) (lines 75-77).

## How Conditional Loading Works Internally

Lazy.nvim handles conditional plugins in four distinct steps according to the jdhao/nvim-config implementation:

1. **Specification Parsing**: Lazy.nvim reads the `plugin_specs` table from [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua).
2. **Startup Filtering**: For each entry, if `enabled` is present, it evaluates the Boolean or function immediately. When `false`, Lazy.nvim removes the entry from the plugin list entirely.
3. **Pre-load Checks**: If the entry survives, Lazy.nvim evaluates `cond` (if present) immediately before loading the plugin on its designated trigger (e.g., `BufRead`, `CmdlineEnter`).
4. **Load Abortion**: Returning `false` from `cond` prevents the plugin from loading for that session, though it remains available for manual `:Lazy load` commands.

This two-stage filtering ensures that **static conditions** (OS type, missing binaries) skip processing overhead entirely, while **dynamic conditions** (Firenvim detection) allow context-aware loading without polluting your startup time.

## Summary

- Use **`enabled`** in your plugin spec to discard plugins permanently at startup based on static conditions like operating system or missing external tools.
- Use **`cond`** to evaluate dynamic conditions right before a plugin loads, ideal for context-dependent UI components.
- Reference [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) in jdhao/nvim-config for real-world implementations of both patterns.
- Leverage helper functions like `utils.executable` in [`lua/utils.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/utils.lua) to check for system binaries when using `enabled`.
- Remember that `enabled` functions run once during Neovim startup, while `cond` functions run every time the plugin's lazy-loading trigger fires.

## Frequently Asked Questions

### What is the difference between `cond` and `enabled` in Lazy.nvim?

**`enabled`** evaluates once during startup and completely removes the plugin from the internal list if it returns `false`, saving memory and processing time. **`cond`** evaluates immediately before the plugin would load on its specified trigger; returning `false` aborts that specific load attempt but keeps the plugin registered so you can load it manually later.

### Can I use `enabled` to check for external binaries like ctags?

Yes. Define a function for `enabled` that returns the result of a utility check such as `utils.executable("ctags")`, as demonstrated in [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) (lines 75-77). If the binary is missing, Lazy.nvim omits the plugin entirely, preventing configuration errors.

### Where should I define conditional logic for my Neovim plugins?

Place your plugin specifications in a central file like [`lua/plugin_specs.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/plugin_specs.lua) and define `cond` or `enabled` keys directly in each plugin's table. For reusable condition logic, create helper functions in [`lua/utils.lua`](https://github.com/jdhao/nvim-config/blob/main/lua/utils.lua) and reference them in your specs to keep the configuration DRY and maintainable.

### Does `cond` affect Lazy.nvim's startup time optimization?

No. Because `cond` is evaluated only when a plugin's lazy-loading trigger (such as an `event` or `cmd`) fires, it does not impact the initial startup time. However, since `enabled` runs at startup, complex functions there can add milliseconds to launch time; keep those checks lightweight or cache results in global variables.