03 — Editor and LSP

You will spend more hours in your editor than in any other tool. Pick one, configure it once, get out of the way. Two viable choices in 2026 for C: VS Code + clangd (best default) or Neovim + clangd (better if you already live in the terminal). Both are equivalent for C productivity; picking one is a matter of taste.

The one non-negotiable: clangd

clangd is the LLVM-project LSP for C/C++/ObjC. Every serious C editor in 2026 uses it. It requires a compile_commands.json (see below) to give you accurate completion, go-to-definition, warnings, and refactoring.

Why clangd, not ccls or the Microsoft C/C++ extension:

clangd

ccls

Microsoft C/C++ (IntelliSense)

Active development

Very active (LLVM team)

Slower

Active

Speed

Fast

Faster on cold index

Slow on large projects

Accuracy

Excellent

Excellent

Uneven; C is second-class to C++

Cross-editor

Yes (LSP)

Yes (LSP)

VS Code only

Rename symbol

Good

Slightly better

Good

License / vendor

LLVM (Apache 2)

MIT

Microsoft proprietary

Reddit consensus on r/C_Programming across 2023-2025: clangd wins for daily-driver C. ccls holds a small edge on symbol rename but is otherwise superseded.

Never run both clangd and the Microsoft C/C++ extension in VS Code — they fight, and you’ll get double diagnostics. Disable Microsoft’s IntelliSense before enabling clangd.

Generating compile_commands.json

clangd needs this file to know your compile flags. Two options:

With Make: use bear:

brew install bear             # Mac
sudo apt install bear         # Ubuntu
make clean
bear -- make
# Produces compile_commands.json in cwd

With CMake:

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

Or on the command line:

cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
ln -sf build/compile_commands.json .

With Meson / Ninja: Ninja emits it by default in the build directory; symlink it to project root.

Neovim + clangd — for terminal natives

Base plugins:

  • nvim-lspconfig — LSP client configuration

  • williamboman/mason.nvim — LSP installer manager

  • nvim-treesitter/nvim-treesitter — syntax highlighting via tree-sitter

  • hrsh7th/nvim-cmp — completion engine

  • mfussenegger/nvim-dap — debug adapter (gdb/lldb)

  • stevearc/conform.nvim — formatter runner (clang-format)

Mason install:

:MasonInstall clangd clang-format codelldb

lspconfig snippet:

require('lspconfig').clangd.setup {
  cmd = {
    'clangd',
    '--background-index',
    '--clang-tidy',
    '--completion-style=detailed',
    '--header-insertion=iwyu',
  },
}

A starter Neovim config that already assembles all of this: LazyVim or kickstart.nvim. Use one, do not roll your own for at least three months.

What about Cursor / other AI editors?

Cursor (Anysphere) is a VS Code fork with tighter Claude/GPT integration. For C specifically, the honest verdict:

  • Cursor’s inline autocomplete for C is sometimes helpful, sometimes actively wrong (invents size_t semantics, mislabels string ownership).

  • Its “explain this function” feature is genuinely useful for reading unfamiliar codebases.

  • It costs $20/mo. For a learner, this is not obviously worth it; you specifically want to not have completion filling in the answers you’re supposed to figure out.

Recommendation for the first six months of this roadmap: VS Code + clangd, no AI autocomplete. Use Claude/ChatGPT in a separate window for explanation, not integrated in the editor for generation. This is spelled out in 08_ai_assist_for_c.md.

After M6, if you’re shipping C daily, revisit Cursor. It’s fine at that point.

What most people get wrong about editors

They configure for six months and code for six weeks. Rule: your editor is done when you can find-references, go-to-definition, rename-symbol, format-on-save, and set a breakpoint. Any further customization is procrastination in disguise until you have shipped at least 10K lines of C.

Return to README.md · Next: 04_debuggers_and_sanitizers.md