clang-tutor: out-of-tree Clang plugins you can read in an afternoon
A collection of out-of-tree Clang plugins for teaching and learning
At a glance
- What is it?
- clang-tutor is a set of self-contained example Clang plugins aimed at developers who want to learn the Clang plugin framework, each one small enough to read, with build scripts, lit tests and CI included. The plugins build against a binary Clang installation rather than a source build, which is the choice that makes the tutorial approachable.
- Who is it for?
- clang-tutor suits a developer who wants to write a Clang tool and would rather start from a working example than from the API documentation, and who is comfortable with C++ and CMake. It is the wrong tool if you need a production linter or refactoring tool, since the examples exist to be read rather than depended on, and the wrong choice if you cannot install a matching Clang and LLVM development package.
- Can I use it commercially?
- Yes. Unlicense is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 32 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the collection is and the three properties it claims
clang-tutor is a collection of out-of-tree Clang plugins for teaching and learning, described as example Clang plugins for C and C++ based on Clang 23. It is a tutorial that targets novice and aspiring Clang developers, and the README lists three key features.
The first is that it is modern, based on the latest version of Clang and updated with every release. The second is that it is complete, including build scripts, lit tests and CI setup. The third is that it is out of tree, which means it builds against a binary Clang installation with no need to build Clang from sources.
That third property is the one that makes the rest practical. Clang is a subproject of llvm-project, and the usual way to write a plugin involves building an entire compiler toolchain first, which for a tutorial is a barrier that stops most people before they write a line of plugin code. Building against an installed Clang removes that step entirely, and the trade is that you are tied to the version of Clang you installed.
The stated goal is to showcase the Clang plugin framework through small, self-contained and testable examples, implemented using idiomatic LLVM. The README also says the source files, apart from the code itself, contain comments that guide you through the implementation, and that the tests highlight the edge cases that are supported and are worth skimming.
The licence field on the repository records Unlicense, and the primary language is C++.
The HelloWorld plugin and what it demonstrates
The HelloWorld plugin is the reference example, and the README explains what it does in a way that teaches the framework rather than just describing the output.
It extracts information from the input translation unit, visiting all C++ record declarations, which means class, struct and union declarations, and counting them. The reminder that a translation unit consists of the input source file and all the header files it includes, directly or indirectly, is the conceptual point.
The output is printed on a file by file basis, separately for every header file that was included, and the plugin visits all declarations including those in header files included by other header files. The README flags that this may lead to some surprising results, and then it shows what that means.
# Expected output
(clang-tutor) file: <source/dir/clang/tutor>/test/HelloWorld-basic.cpp
(clang-tutor) count: 3The build and run sequence is three environment variables and two commands.
# Build the plugin
export Clang_DIR=<installation/dir/of/clang/23>
export CLANG_TUTOR_DIR=<source/dir/clang/tutor>
mkdir build
cd build
cmake -DCT_Clang_INSTALL_DIR=$Clang_DIR $CLANG_TUTOR_DIR/HelloWorld/
make
# Run the plugin
$Clang_DIR/bin/clang -cc1 -load ./libHelloWorld.{so|dylib} -plugin hello-world $CLANG_TUTOR_DIR/test/HelloWorld-basic.cppThe run line is the part that teaches the plugin mechanics. Invoking clang with the -cc1 flag runs the compiler proper rather than the driver, the -load flag loads the shared library, and the -plugin flag names the plugin entry point inside it. The braces in the library name cover the two platforms, a shared object on Linux and a dylib on macOS.
The STL header experiment and what it teaches
The README then uses the plugin to demonstrate the surprising behaviour it warned about, and this is the most instructive part of the tutorial.
The instruction is to run HelloWorld on a header file from the Standard Template Library, and the example is a file that simply includes the vector header.
// file.cpp
#include <vector>Because including a standard library header pulls in a large number of other headers, the output lists an overview of all header files included when using that include, along with the number of C++ records declared in each.
The README then gives the actual observation. There are no explicit declarations in file.cpp and only one header file is included, yet the output on the author's system consists of 37 header files, one of which contains 371 declarations. And the README is careful to add that the actual output depends on the host operating system, the C++ standard library implementation and its version, and that your results are likely to be different.
That last qualification is not a disclaimer, it is the lesson. A translation unit is not a file, and the set of declarations visible to a compiler is a function of the entire include graph, which varies with the standard library implementation. A plugin author who reasons about a translation unit as a file will be surprised, and this example makes that concrete in a handful of lines.
There is also a practical detail in the invocation. When running a plugin on a file that includes standard library headers, the README says it is easier to run it with clang++ rather than clang -cc1.
$Clang_DIR/bin/clang++ -c -Xclang -load -Xclang libHelloWorld.dylib -Xclang -plugin -Xclang hello-world file.cppThe reason is that the include paths needed to locate the standard library headers are added automatically that way, and without them the plugin sees a different, much smaller, set of declarations.
The development environment and the version dependency
The platform support section names the tested configurations as Ubuntu 20.04 and Mac OS X 10.14.6, and the requirements are LLVM 23 and Clang 23, a C++ compiler that supports C++17, and CMake 3.13.4 or higher.
The LLVM point is expanded: since Clang is a subproject within llvm-project, clang-tutor requires development packages for both Clang and LLVM. There are additional requirements for the tests, which the README says are satisfied by installing LLVM 23: lit, the LLVM tool for executing tests, and FileCheck, which the README explains is a lit requirement used to check whether tests generate the expected output.
The installation instructions are per platform. On macOS, Homebrew installs Clang 23 and LLVM 23, and if you already have an older version, brew upgrade llvm does the same job. Once that completes, the required headers, libraries and tools are located under the Homebrew llvm prefix.
On Ubuntu, the instructions target the Jammy Jellyfish release and point at the official apt.llvm.org repository, adding the signing key, the repository for the llvm-toolchain-jammy-23 suite, and then a list of packages that includes the LLVM 23 toolchain, the development packages, the Clang 23 packages and the MLIR libraries.
The version dependency is the thing to take away. The plugin API changes between Clang releases, and a plugin built against one version will not load in another. The README's claim that the collection is updated with every release is the maintainer committing to that work, and it is the reason to read the version numbers before you start rather than discovering the mismatch as a link error.
Where clang-tutor is the wrong choice
The first limitation is that these are examples, not a library. Nothing here is packaged for reuse, the API is the point rather than the code, and the plugin entry points and CMake conventions are written to be read. A team that wants a linter or a refactoring tool needs a different project.
The second is the version coupling, already mentioned. The plugins are pinned to Clang 23, and a team on a different LLVM version cannot use them without porting, which is real work because the plugin API and the AST have both moved between versions.
The third is that the examples are deliberately small, and small examples hide the parts of the framework that matter at scale. There is no coverage here of a plugin that has to be fast, that has to handle a large codebase in memory, or that has to be distributed as a tool to a team. The tutorial teaches the shape of a plugin, and the difficult parts of a real tool are the ones the examples leave out.
The fourth is the platform coverage in practice. The tested configurations are Ubuntu 20.04 and Mac OS X 10.14.6, which are old releases, while the build instructions target a current Clang 23 and a current Ubuntu. A developer on a current distribution will be following an installation guide written against a different one, and the CI badges for Apple Silicon and x86 Ubuntu are the only signal about what is actually exercised.
The fifth is the out-of-tree limitation itself, which cuts both ways. Not building Clang from source is what makes the tutorial approachable, and it also means you cannot experiment with the compiler internals, which is where a lot of interesting plugin work ends up.
How clang-tutor compares with the Clang documentation and with clangd plugins
The comparison with the Clang documentation is the obvious one, and the difference in approach is between reference material and worked examples. The documentation describes the AST, the matcher library, the tooling infrastructure and the plugin interface precisely, and it is written for someone who already knows what they want to build. The tutorial gives you a complete, buildable, testable example of one thing and explains what each part is for, which is a different way of learning the same material.
The second comparison is with the modern alternative to Clang plugins, which is a language server. A language server exposes a smaller and more stable surface than a Clang plugin, and it integrates more directly with the editor. A plugin gives you the full compiler and the full AST, which is what you want for a refactoring or a lint, and the language server gives you a smaller API and better integration with the editor.
The third comparison is with the examples inside the LLVM tree itself. Examples inside the LLVM tree itself exist, but building them as part of LLVM means building the whole project before running anything. The out-of-tree arrangement is what lets a tutorial be cloned and built in a few minutes, which is the whole reason this project exists in this form.
The fourth is with a code generation tool such as a source-to-source refactoring tool. Those tools exist and are more practical for large mechanical changes, and they do not teach you anything about the compiler while doing it.
Licence, project state and what to check before you start
The licence field on the repository records Unlicense, which is a public domain dedication rather than a conventional open source licence, and it is a reasonable choice for teaching examples that people are expected to copy. The README closes by inviting corrections and feedback, which fits a tutorial whose value depends on the examples staying accurate.
The project is not archived and the last push was on 2026-09-21, so the examples are being maintained against the current Clang. The recent releases section says there are no GitHub releases, which is normal for a repository whose artefacts are source examples rather than packaged software.
The repository layout is small and matches the structure the README describes. There is a HelloWorld/ directory holding the reference plugin and its CMakeLists.txt, a test/ directory with the lit tests, an include/ and lib/ directory, a tools/ directory, a top-level CMakeLists.txt, and a .github/ directory with the two CI workflows, one for Apple Silicon and one for x86 Ubuntu.
Four things to check before you start.
That you have Clang 23 and LLVM 23 development packages installed, and that the plugin you build will load into the Clang you run, since the -load and -plugin flags require the ABI to match.
That you have lit and FileCheck available for the tests, since the README ties them to installing LLVM 23 rather than to separate packages.
That you read the comments in the source files, since the README makes the comments part of the teaching and not just documentation.
And that you skim the test directory before changing an example, because the README says the tests show which edge cases are supported, and because lit and FileCheck output matching means a change in behaviour breaks a test in a way that reads as a regression.
Editorial conclusion
clang-tutor suits a developer who wants to write a Clang tool and would rather start from a working example than from the API documentation, and who is comfortable with C++ and CMake. It is the wrong tool if you need a production linter or refactoring tool, since the examples exist to be read rather than depended on, and the wrong choice if you cannot install a matching Clang and LLVM development package. Before you start, install the exact Clang and LLVM version the tutorial targets, because the plugin API changes between releases and the build will not work against a different one.
Frequently asked questions
What is the clang-tutor repository?
It is a collection of self-contained, out-of-tree Clang plugins for C and C++ that doubles as a tutorial for developers new to the Clang plugin framework. The examples are based on Clang 23 and come with build scripts, lit tests and CI setup.
What does the HelloWorld plugin do?
It visits all C++ record declarations, meaning class, struct and union declarations, in the input translation unit and counts them, printing the result separately for every header file that was included, including headers included by other headers.
What do I need to build clang-tutor?
LLVM 23 and Clang 23 development packages, a C++ compiler supporting C++17, and CMake 3.13.4 or higher. For the tests you also need lit and FileCheck, which the README says are satisfied by installing LLVM 23.
Why does building out of tree matter for clang-tutor?
Because it means the plugins build against a binary Clang installation with no need to build Clang from sources, which removes the largest barrier to trying the plugin API. The trade is that the plugin has to match the Clang version it was built for.
How do I run a clang-tutor plugin?
Build it with CMake against the Clang install directory and then load it into the compiler, for example by invoking clang with the -cc1 flag, a -load pointing at the shared library and a -plugin naming the entry point. For a file that includes standard library headers the README suggests clang++ with the -Xclang options so the include paths are added automatically.
What licence does clang-tutor use?
The Unlicense, a public domain dedication, with the terms in the LICENSE file at the root of the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/banach-space-clang-tutor)Was this useful?