Home / Alt manpages / clangd-20(1)

  • clangd-20(1)
  • User command
  • linux

Make clangd 20 Useful in a C++ Project

You will finish with clangd 20 checking a C++ file using the right compilation flags, a repeatable way to diagnose missing project configuration, and a small set of settings that improve editor feedback without making the whole machine configuration noisy. The examples use Ubuntu clangd version 20.1.8, from package clangd-20 version 1:20.1.8~++20250804090239+87f0227cb601-1~exp1~20250804210352.139.

Allow about twenty minutes. You need a shell, clangd 20 and a C++ project. An editor plugin normally starts clangd for you, so this guide uses the command line for checks rather than pretending that clangd is a standalone compiler. The examples read project files and write no configuration until you choose to add it.

1. Confirm the installed binary

Start with a read-only version check. This does not need elevated privileges:

$ command -v clangd-20
/usr/bin/clangd-20
$ clangd-20 --version
Ubuntu clangd version 20.1.8 (++20250804090239+87f0227cb601-1~exp1~20250804210352.139)
Features: linux+grpc
Platform: x86_64-pc-linux-gnu

The executable is a language server. An editor plugin speaks the Language Server Protocol to it over standard input and output. Running clangd-20 in a terminal without an LSP client is not an interactive source checker. Use --check when you want a direct, one-file diagnostic.

Checkpoint

If command -v finds another clangd first, either use that deliberately or call /usr/bin/clangd-20 in your editor's configuration. Do not debug one binary while the editor launches another.

2. Check one file without starting an editor session

Make a harmless test file in a temporary directory, or substitute a real source path. The --check option parses one file in isolation and does not act as a language server:

$ clangd-20 --check=/path/to/project/src/main.cc 2>clangd-check.log
$ grep -E 'Testing on source file|All checks completed|error' clangd-check.log
I[...] Testing on source file /path/to/project/src/main.cc
I[...] All checks completed, 0 errors

The timestamps and process details vary. The useful success signal is All checks completed, 0 errors and a zero exit status. The log goes to standard error, which is why the example redirects it. If the command reports a missing compilation database, it can still use a generic fallback command. That is useful for a smoke test, but it is not proof that your project is being parsed with its real include paths and language flags.

Remove a temporary log when you have finished reviewing it. There is no project state to undo in this step; clangd only read the source and any configuration it found.

3. Give clangd the project's compilation database

For reliable C++ results, make compile_commands.json available. clangd looks for it in the current directory and in parent directories of the source file. You can also point it at a directory explicitly:

$ clangd-20 --compile-commands-dir=/path/to/project/build \
    --check=/path/to/project/src/main.cc 2>clangd-check.log
$ grep -E 'compile command|All checks completed|error' clangd-check.log
I[...] Compile command from CDB is: [...] /path/to/project/src/main.cc
I[...] All checks completed, 0 errors

Replace both placeholders with real paths. The option expects the directory containing the database, not the JSON file itself. When an editor plugin launches clangd, put this option in that plugin's server arguments if the normal directory search cannot find the build tree.

A compilation database is generated by your build system. For example, configure your project in the way its build documentation specifies, then check that the file exists:

$ test -r /path/to/project/build/compile_commands.json && \
    echo 'compilation database is readable'
compilation database is readable

Do not hand-edit a generated database as a first response to diagnostics. Fix the build configuration that produced it, regenerate it, and rerun the check. That keeps the editor view aligned with the command used to build the program.

4. Add project settings only when the project needs them

clangd 20 reads a project .clangd YAML file when configuration is enabled. It also reads a user config.yaml under $XDG_CONFIG_HOME, normally ~/.config/clangd/config.yaml on Linux. The project file travels with the repository; the user file affects your own projects and is a poor place for a repository-specific include path.

Use a minimal project file for settings that belong to the project, such as enabling clang-tidy:

Diagnostics:
  ClangTidy:
    Add: [readability-*, performance-*]

This example is a configuration fragment, not a complete build description. Keep the file under version control only if the project agrees on that policy, and check the configuration against the clangd documentation before adding more keys. If a new setting makes diagnostics unusable, remove that setting or restore the previous committed version. Do not use sudo to edit a project file.

To test whether configuration is the source of a problem, run the same --check command from the project and then from a clean copy or with the project file temporarily moved aside. Save the original first if it is not tracked. This is a reversible diagnostic; do not delete a configuration file you may need to recover.

5. Tune the common editor annoyances

Most projects do not need every clangd flag. Three options have clear boundaries:

  • --background-index asks clangd to index project code in the background and persist the index. It can use noticeable disk, CPU and memory, so enable it when cross-file navigation is worth that cost.
  • --clang-tidy enables clang-tidy diagnostics. Use the project's agreed checks where possible; otherwise, extra warnings can obscure compiler errors.
  • --fallback-style=none chooses the clang-format style used when no .clang-format file exists. This example is useful when you do not want clangd inventing formatting, but it does not replace the project's real format file.

Set these in the editor's clangd arguments rather than exporting a global setting for every project. clangd also accepts flags in CLANGD_FLAGS, but that environment variable is easy to forget and can make two editor sessions behave differently.

For a slow or noisy session, use a bounded worker count such as -j 2, or use --log=info while investigating. --log=verbose is useful for a short diagnostic capture, not as a permanent default. A log can contain file paths and build details, so treat it as project information before sharing it.

6. Allow a compiler driver only when it is trusted

The --query-driver option gives clangd a comma-separated list of globs for GCC-compatible drivers that it may execute to discover system include paths. This is a security-sensitive boundary: only allow compiler drivers that you trust and expect on the machine.

$ clangd-20 --query-driver=/usr/bin/g++-*,/usr/bin/clang++-* \
    --check=/path/to/project/src/main.cc 2>clangd-check.log

Do not copy a broad wildcard from an untrusted project, and do not allow a driver path inside a writable source tree merely to silence an include warning. If the project uses a custom toolchain, establish who owns that executable, what it runs, and how it is updated before adding its path. Removing the option from the editor arguments is the undo step.

7. Read failures in the right order

When completion or diagnostics look wrong, check the layers in this order:

  1. Confirm the editor launched clangd-20, not a different version.
  2. Run --check on the affected file and capture standard error.
  3. Look for a compilation command from the database. A generic fallback means the project flags were not found.
  4. Check the source file's path, language mode, include directories and defines in the compilation database.
  5. Only then investigate clangd options, clang-tidy checks or the editor plugin.

Do not solve a missing header by adding random system directories to a user-wide config. That can hide a broken build and make another project parse incorrectly. Fix the compilation database or the build command, then rerun the same verification.

Done means

  • clangd-20 --version reports the installed 20.1.8 binary you intended to use.
  • --check completes with zero errors on a representative source file.
  • The check uses the project's compilation database, or you have recorded why the fallback is acceptable.
  • Project settings are minimal, reversible and stored at the correct scope.
  • Background indexing, diagnostics and logging are enabled only where their resource and privacy costs are understood.
  • Any --query-driver entry names a trusted compiler driver rather than an arbitrary writable path.