ESP32.nvim provides an ESP-IDF workflow for Neovim and LazyVim: build, flash, monitor, configure, select targets, and use Espressif's clangd without leaving the editor.
- 🛠️ Run ESP-IDF build, flash, monitor, menuconfig, clean, and reconfigure tasks
- 🔌 Select serial ports on macOS and Linux and reuse the last selection
- 🎯 Select any target supported by the active ESP-IDF installation
- 🧠 Detect Espressif's
clangdand configure it for the project - 🔎 Detect missing or GCC-generated compilation databases
- 🔄 Restart project clangd clients after reconfigure and target changes
- 📋 Inspect the active environment, clangd command, and build database with
:ESPInfo
- Neovim 0.11 or newer
- An activated ESP-IDF environment
- Espressif's
esp-clangtool (optional in ESP-IDF, required for this LSP workflow) - snacks.nvim (installed automatically by lazy.nvim)
ESP-IDF Installation Manager is the recommended upstream installer. See ESP-IDF setup for EIM, manual installation, activation, and clang toolchain details.
ESP32.nvim is an ESP-IDF clang workflow. Espressif still describes parts of the clang toolchain as under development, so some projects or components that build with GCC may not yet build with clang. See project compatibility.
{
"Aietes/esp32.nvim",
}With lazy.nvim's standard package support, the repository's lazy.lua spec:
- installs the required
snacks.nvimdependency - calls
require("esp32").setup()withbuild_dir = "build.clang" - provides the default keymaps
- adds the ESP32 which-key group when which-key.nvim is already installed
It does not configure clangd; complete step 2 below.
For native vim.pack and other plugin managers, see
Installation methods.
⚠️ Attention: Installing ESP32.nvim does not configure clangd automatically. Complete the LSP setup below to enable completion, diagnostics, hover, and go-to-definition.
Choose the setup that matches your configuration.
For LazyVim:
{
"neovim/nvim-lspconfig",
opts = function(_, opts)
opts.servers = opts.servers or {}
opts.servers.clangd = require("esp32").lsp_config()
end,
}For plain Neovim 0.11+:
vim.lsp.config("clangd", require("esp32").lsp_config())
vim.lsp.enable("clangd")If you do not use lazy.nvim, install and configure snacks.nvim, then call
require("esp32").setup() before enabling the LSP.
See LSP configuration for clangd detection, nested project roots, non-ESP C/C++ projects, and advanced toolchains.
Activate the intended ESP-IDF version before launching Neovim:
source ~/.espressif/tools/activate_idf_vX.Y.Z.sh
cd /path/to/your/project
nvimReplace vX.Y.Z with the installed version name. Use the activation script
generated for your shell. Windows users should launch or source the
EIM-generated PowerShell environment.
Alternatively, a project-local Nix/direnv setup can
activate an existing ESP-IDF installation automatically whenever you enter the
project directory, so Neovim inherits the environment without a manual
source step.
Open a C or C++ file and run:
:ESPReconfigureThis creates the configured build directory (default: build.clang) with
IDF_TOOLCHAIN=clang, then restarts clangd so it reads the new database.
:ESPInfoIt should report an Espressif clangd, a clang-generated
compile_commands.json, a working idf.py, and a populated IDF_PATH.
If not, follow the troubleshooting guide.
Override the packaged defaults in your plugin spec:
{
"Aietes/esp32.nvim",
opts = {
build_dir = "build.clang",
clangd_args = {},
idf_cmd = nil,
},
}| Option | Default | Purpose |
|---|---|---|
build_dir |
"build.clang" |
Project-relative ESP-IDF build directory and clangd compilation database |
clangd_args |
{} |
Extra arguments appended to the generated clangd command |
idf_cmd |
nil |
idf.py executable or argv override, such as { "mise", "exec", "--", "idf.py" } |
For cross-toolchain include problems, read
Query-driver before adding a broad
--query-driver=** rule.
All esp32.nvim terminal windows (build, flash, monitor, reconfigure,
set-target) share the esp32_terminal
snacks window style.
By default they open as a float of 60% × 70% with a border that follows
vim.o.winborder (rounded if unset). Size, position and border set in your
snacks styles.terminal config are inherited. Adjust anything specifically
for esp32.nvim — including any other
window option —
in your snacks.nvim config:
{
"folke/snacks.nvim",
opts = {
styles = {
esp32_terminal = {
width = 0.9,
height = 0.5,
border = "double",
position = "bottom",
},
},
},
}A borderless window (border = "none") cannot display a floating window
title, so the title is shown in the winbar instead.
The user commands are always available:
| Command | Action |
|---|---|
:ESPBuild |
Build with the configured build directory |
:ESPReconfigure |
Regenerate the clang build database and restart clangd |
:ESPInfo |
Show project, toolchain, and LSP diagnostics |
:ESPSetTarget |
Pick a supported chip target and regenerate the project |
The packaged lazy.nvim spec adds:
| Key | Action |
|---|---|
<leader>Rb |
Build |
<leader>RM / <leader>Rm |
Pick a port and monitor / monitor with the remembered port |
<leader>RF / <leader>Rf |
Pick a port and flash / flash with the remembered port |
<leader>Rc |
Open menuconfig |
<leader>RC |
Clean |
<leader>Rr |
Reconfigure |
<leader>Ri |
Show project info |
<leader>Rt |
Set target |
Override a key through your own lazy.nvim spec:
{
"Aietes/esp32.nvim",
keys = {
{
"<leader>em",
function()
require("esp32").pick("monitor")
end,
desc = "ESP32: Pick & Monitor",
},
},
}Commands open in a floating terminal. Press Ctrl + ] to stop the process and
close it. Pressing q hides a monitor terminal without stopping it, so the same
command can reattach later.
:ESPSetTargetfollowsidf.py set-target: it clears the build directory, regeneratessdkconfig, and saves the previous configuration assdkconfig.old.
- ESP-IDF setup — installation, activation, esp-clang, and project compatibility
- Installation methods — lazy.nvim, native vim.pack, and other managers
- LSP configuration — integration, detection, roots, compilation databases, and query-driver
- Commands and Lua API — custom mappings, remembered ports, and terminal behavior
- Troubleshooting — symptom-based checks for the most common setup failures
- Nix and direnv — project-local activation of an existing ESP-IDF installation
MIT License © 2026 Aietes