table of contents.
- introduction.
- prerequisite: generate compile_commands.json.
- installing clangd.
- configuring clangd.
- begin using clangd.
- troubleshooting common issues.
- conclusion.
introduction.
In my previous blog post, I talked about how I spent the first few years of my software development career writing C++ code with this feeling that I was missing something that could take my C++ skills to the next level. For me, that “missing something” was the suite of Clang Tools. Once I discovered and learned to use tools like clang-tidy and clang-format in my workflow, I became a much more efficient C++ developer. However, of all of the Clang Tools, clangd is the tool that has had the most impact on my productivity.
clangd is a language server that integrates with your IDE (or editor of choice) to provide intelligent code completion as you type, catching errors and warnings in real time before you compile. As someone who uses VS Code, I find clangd’s IntelliSense to be faster and more accurate than the IntelliSense bundled in the official Microsoft C/C++ extension for VS Code. clangd offers instant navigation to definitions and declarations with a single keystroke or Ctrl+Click, and it can also quickly find all references to any symbol across your entire project. When you need to rename a variable or refactor code, clangd updates everything automatically for you: declarations, definitions, and all usages are renamed or adjusted as needed. clangd also integrates clang-tidy directly into your editor, surfacing code quality issues, potential bugs, and style violations as you write. Beyond these features, clangd can automatically fix many common problems, suggest or automatically add missing #include directives, and provide hover documentation for any symbol in your code.
In this post, I’ll walk you through setting up clangd in VS Code and show you how you can configure it to work best for you.
prerequisite: generate compile_ commands .json.
Before you can use clangd, you need to generate a compile_commands.json file for your project so that clangd can analyze your code. Without this file, clangd isn’t able to provide accurate IntelliSense or customized warnings and suggestions. For detailed instructions on generating a compile_commands.json file for your project, please check out my previous post: how to generate compile_
installing clangd.
To integrate clangd into your editor of choice, you’ll need to install two things: the clangd language server which runs in the background; and the clangd extension for your editor. clangd extensions are available for many editors, including VS Code, Emacs, Vim, Neovim, Sublime Text, and more.
At a high level, the steps for installing clangd are as follows:
- install the clangd extension for your editor
- install the clangd language server
- disable competing extensions in your editor
The subsections below contain information for performing these steps in VS Code since that is the editor I use, but the process will be similar for other editors.
1: install the clangd extension.
First, install the clangd extension for your editor. In VS Code:
- Go to Extensions
- Search for “clangd”
- Install the official clangd extension by LLVM
2: install the clangd language server.
You have two options for installing the clangd language server:
Option A: download the clangd language server that is suggested by the clangd extension.
Option B: download a specific version of the clangd language server separately.
option a: download the suggested version.
After downloading the clangd extension in VS Code, a popup will appear in VS Code asking if you would like to download the latest clangd language server. If you would like to go this route, simply press the ‘download’ button in the popup to download the language server. Your clangd extension settings in VS Code will be updated to point to the clangd language server binary automatically.
option b: download a specific version separately.
After downloading the clangd extension in VS Code, press ‘no’ in the popup asking if you would like to download the latest clangd language server. Going this route, you will need to install your clangd language server separately. This method is preferred if you would like to have consistent clangd language server versioning across a team and/or the ability to manage your clangd language server version via your OS package manager.
As an example, on Ubuntu/Debian, you can install clangd 18 with the following command:
sudo apt install clangd-18
After installing the clangd language server version of your choosing, you will need to update your VS Code settings to tell the clangd extension where the language server binary is installed on your system. One way to do this is to open the VS Code command palette and type “settings”, then select the option that says Preferences: Open User Settings (JSON). After selecting this option, a JSON file is opened which contains your VS Code user settings. In here, you will add a new JSON key for clangd.path, whose value is a string containing the full file path to the clangd language server binary:
{
"clangd.path": "/usr/bin/clangd-18"
}
Adjust the path according to where your clangd language server binary is installed.
3: disable competing extensions.
At this point, the clangd extension is installed in your editor and it is linked to your clangd language server. The final installation step is to disable any competing extensions in your editor so that clangd works as expected.
In VS Code, the clangd extension will prompt you to disable Microsoft’s C/C++ IntelliSense if that is enabled. You can happily disable it — clangd provides superior functionality anyway. Make sure to also disable any other competing extensions to get the most out of clangd.
configuring clangd.
At this point, you can (and should) configure clangd’s functionality to your liking. This is an important step to follow, because if you skip it, clangd might not give you the suggestions and warnings you care about, and thus you won’t be taking full advantage of the tool. To customize its suggestions and warnings, clangd offers the ability to create your own custom .clangd file with exactly the settings you want to use. This customizability is what sets clangd apart from other tools. You can configure precisely which warnings you care about and which ones you don’t, tailoring the tool to match your project’s needs and/or your personal coding standards. This means you only see diagnostics that matter to you, rather than being overwhelmed with noise from checks that aren’t relevant to your codebase.
For me, the most valuable aspect of clangd is that it reduces my cognitive burden, and this is only possible thanks to the customizability of the tool. As a developer who prioritizes safety, quality, and consistency in my C++ code, clangd gives me confidence that I’m writing good code — or at least what I consider to be good code — without me needing to mentally track every potential issue. Instead of analyzing every line of code for possible problems, I can instead focus on the logic I’m trying to implement while clangd highlights issues in real time. This is incredibly helpful not only when writing my own code, but also while I am reviewing other people’s code in my editor. clangd surfaces potential problems immediately, meaning that I don’t have to scan for all of these issues myself.
You can place a .clangd file in either (or both) of the following locations:
- User-wide: Place
.clangdin your home directory (e.g.~/.clangd) to set defaults for all projects. - Per-project: Place
.clangdin your project root to customize settings for that specific project. These settings will override those from the user-wide.clangdfile.
Below is my personal user-wide .clangd file — the one I use for all of my C++ projects. I have tweaked this file through the years to find a good balance of the features and diagnostics I care about. Feel free to use this as a starting point for creating your own .clangd file:
CompileFlags:
Add: [-Wall, -std=c++17]
InlayHints:
ParameterNames: No
DeducedTypes: No
Designators: No # controls the display of indices in arrays
Diagnostics:
UnusedIncludes: Strict
MissingIncludes: Strict
Includes:
IgnoreHeader: [signal.h, stdio.h]
ClangTidy:
FastCheckFilter: None
Add: [bugprone-*, cert-*, modernize-*, performance-*, misc-unused-*, misc-use-anonymous-namespace, cppcoreguidelines-*]
Remove: [bugprone-easily-swappable-parameters, modernize-use-trailing-return-type, modernize-avoid-bind, cppcoreguidelines-avoid-magic-numbers, cppcoreguidelines-pro-bounds-pointer-arithmetic, cppcoreguidelines-pro-bounds-constant-array-index, cppcoreguidelines-pro-type-union-access, cppcoreguidelines-special-member-functions]
For a complete list of configuration options and descriptions of what each one does, see the clangd configuration documentation.
Finally, after you have decided what your .clangd file will include, you will need to configure your VS Code settings to tell the clangd language server that you are using .clangd files for configuration. This is done by passing the --enable-config argument to the clangd language server. As mentioned before, one way to edit your VS Code settings is to open the VS Code command palette and type “settings”, then select the option that says Preferences: Open User Settings (JSON). After selecting this option, a JSON file is opened which contains your VS Code user settings. In here, you will add a new JSON key for clangd.arguments, whose value is an array of strings containing the arguments that will be passed to the clangd language server. You will need to add the "--enable-config" argument at a minimum, though there are other optional arguments you can provide to tweak the features and behaviour of clangd even further. Below is a JSON snippet showing the arguments I pass to the clangd language server:
{
"clangd.arguments":
[
"--enable-config", // read user and project configuration from '.clangd' files
"--log=verbose", // enable verbose log output
"--pretty", // pretty-print JSON log output
"--background-index", // index project code in the background and persist index on disk
"--clang-tidy", // enable clang-tidy diagnostics
"--header-insertion=iwyu", // insert #include directives according to 'Include What You Use' rules
"--compile-commands-dir=${workspaceFolder}/build/" // the path to the directory where compile_commands.json is located. My projects are always configured to place this file in the build directory
]
}
begin using clangd.
At this point, clangd is installed, configured, and ready to use. I hope you enjoy the benefits of using clangd in your development workflow and that you get as much value out of it as I have. I would encourage you to continue tweaking the clangd configuration to your liking as you use it.
Pro tip: when clangd shows a diagnostic with a lightbulb icon, click on the lightbulb icon to see the available quick fixes. Many of these can be applied automatically, saving you time. E.g.: adding missing #include directives.
troubleshooting common issues.
Even with proper setup, you might encounter some minor issues while using clangd. Below are the most common problems I come across and how to solve them.
When troubleshooting, the clangd log output helps narrow down problems. To open the log output in VS Code:
- Open the Output panel
- Select “clangd” from the dropdown
- Look for error messages or warnings. E.g., you can use Ctrl+F to find “error”
For even more detailed logs, you can enable verbose logging for clangd by adding the --log=verbose clangd argument in your VS Code settings as shown above.
issue: clangd appears frozen or unresponsive.
Symptoms:
- IntelliSense stops working
- No error highlighting is provided for obvious errors
- Suggestions seem outdated
Solution: Restart the clangd language server. In VS Code:
- Open the command palette
- Type “clangd” and select the option that says clangd: Restart language server
This is the first thing to try when clangd seems to be misbehaving.
issue: clangd cannot find headers.
Symptom: Red squiggles under #include directives, “pp_file_not_found” errors.
Possible solutions:
- Make sure that you only have one workspace open per VS Code window
- Verify your
compile_commands.jsonfile is in the expected location for your project - Make sure you’ve opened your project from its root directory
- Try restarting clangd (see above)
issue: incorrect or missing diagnostics.
Symptom: clangd shows errors in code that compiles fine, or misses obvious errors.
Possible solutions:
- Check that your
.clangdfile configuration isn’t suppressing important diagnostics - Add a
CompileFlagssection to your.clangdfile to specify your targeted C++ version. E.g.:CompileFlags: Add: [-std=c++1z]
conclusion.
I hope this guide has helped you to begin working with clangd. Getting started with clangd requires some initial setup time, but the payoff in code quality and developer productivity is absolutely worth it.
The key steps to remember:
- Generate
compile_commands.jsonfor your project - Install the clangd extension in your editor
- Configure clangd with a
.clangdfile to match your project’s needs - Use the “Restart language server” command when things act up
With real-time error detection, intelligent code completion, powerful navigation, and customizable diagnostics, clangd transforms any editor into a world-class C++ development environment. Once you experience the difference, you’ll wonder how you ever wrote C++ code without it.
Until next time!