NeoVim IDE Setup with clangd¶
If you prefer NeoVim over VS Code as your editor for ESP-IDF development, follow this guide to set it up with clangd for C/C++ intelligence.
Why NeoVim + clangd?¶
- clangd is the same language server that powers VS Code's C/C++ extension — fast, accurate code completion, go-to-definition, and diagnostics
- NeoVim is a lightweight, keyboard-driven editor that runs in the terminal — ideal for embedded development where you spend most time in
idf.pyand serial monitors - Works seamlessly inside the Docker dev environment
Step 1 — Install NeoVim¶
Verify the installation:
Step 2 — Install clangd¶
clangd provides code intelligence (completion, diagnostics, go-to-definition) for C/C++.
Step 3 — Configure NeoVim with LazyVim (Recommended)¶
The easiest way to get a full-featured NeoVim setup is using LazyVim, which comes with LSP support out of the box.
# Back up any existing config
mv ~/.config/nvim ~/.config/nvim.bak 2>/dev/null || true
# Clone LazyVim starter
git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git
# Launch NeoVim — plugins will install automatically
nvim
After LazyVim installs, add the clangd LSP config:
mkdir -p ~/.config/nvim/lua/plugins
cat > ~/.config/nvim/lua/plugins/clangd.lua << 'EOF'
return {
{
"neovim/nvim-lspconfig",
opts = {
servers = {
clangd = {
cmd = {
"clangd",
"--background-index",
"--clang-tidy",
"--header-insertion=never",
"--query-driver=/opt/esp/tools/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-elf/bin/xtensa-esp32s3-elf-g++",
},
},
},
},
},
}
EOF
Query driver path
The --query-driver path must match the location of the Xtensa cross-compiler inside your Docker container or local ESP-IDF installation. Run the following to find it:
Step 4 — Generate compile_commands.json for clangd¶
clangd needs a compile_commands.json file to understand your project's include paths and compiler flags. ESP-IDF can generate this automatically.
In your ESP-IDF project directory:
Then symlink it to the project root so clangd can find it:
Automatic symlink
Add this to your project's CMakeLists.txt to auto-create the symlink on every build:
Step 5 — Useful Keybindings (LazyVim)¶
With LazyVim + clangd, these are the key bindings you'll use most:
| Key | Action |
|---|---|
K |
Hover documentation |
gd |
Go to definition |
gr |
Find references |
<leader>ca |
Code actions |
<leader>cr |
Rename symbol |
<leader>cd |
Line diagnostics |
]d / [d |
Next / previous diagnostic |
<C-o> / <C-i> |
Jump back / forward |
Step 6 — Open Your ESP-IDF Project¶
clangd will index the project on first open (may take 30–60 seconds). After that, you'll get:
- Autocompletion for ESP-IDF API functions (
esp_err_t,gpio_config, etc.) - Go-to-definition into ESP-IDF headers
- Inline diagnostics for compiler errors and warnings
- Hover docs for function signatures
If clangd can't find ESP-IDF headers
Make sure compile_commands.json exists in the project root and the --query-driver path in your clangd.lua config points to the correct Xtensa compiler. Restart NeoVim after fixing either of these.
Quick Reference — NeoVim + ESP-IDF Workflow¶
# 1. Build and flash (from a separate terminal or tmux pane)
idf.py build flash monitor
# 2. Edit code (in NeoVim)
nvim main/main.c
# 3. Rebuild after edits
idf.py build
# 4. Use tmux for split workflow
tmux new -s esp
# Split: Ctrl+B % (vertical) or Ctrl+B " (horizontal)
# One pane: nvim | Other pane: idf.py monitor