# cmake-tools.nvim: CMake projects driven from Neovim

> CMake Tools is a pure Lua Neovim plugin that adds configure, build, test and debug commands for CMake projects, with kits, variants, compile_commands integration and a choice of executors and runners. It is a fork of neovim-cmake and targets the workflow that vscode-cmake-tools offers in Visual Studio Code.

**Civitasv/cmake-tools.nvim** — CMake integration in Neovim

- Repository: https://github.com/Civitasv/cmake-tools.nvim
- Stars: 562 · Forks: 108
- Language: Lua
- License: GPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/civitasv-cmake-tools-nvim

## The scope is deliberately the vscode extension, in Lua

CMake Tools is described as CMake Tools for Neovim which is written in pure lua, and the goal is stated as offering a comprehensive, convenient and powerful workflow for CMake-based projects in Neovim, comparable to the functionality provided by vscode-cmake-tools for Visual Studio Code. That comparison is the design brief, and it explains the shape of the plugin. The reference implementation is a Visual Studio Code extension, so the feature set mirrors what a VS Code user expects, including the parts that only make sense inside an editor, such as a test picker, a debug configuration and a quickfix window. The repository is a fork, and the credit note is explicit about why. It is a fork from the brilliant neovim-cmake, and since the author changes too much of it, they made a new repository to develop it. The plugin targets Neovim 0.7 or newer and requires plenary, which is the standard Neovim Lua utility library, and it optionally integrates with overseer and toggleterm for task execution. It is GPL-3.0 licensed, the repository is not archived, and the last push was on 2026-10-19, so the work is current.

## Installation is the usual plugin manager incantation

Beyond the two requirements, the installation is described as being like any other Neovim plugin, and the README gives the three common manager forms. With lazy.nvim it is a return statement with the repository name and an empty options table, with packer.nvim it is a use call, and with vim-plug it is a Plug line.

The configuration is done through a setup call on the main module, and the beginning of the default configuration is small enough to read in one screen, which is a good sign for a plugin whose options can otherwise sprawl.

```lua
local osys = require("cmake-tools.osys")
require("cmake-tools").setup {
  cmake_command = "cmake", -- this is used to specify cmake command path
  ctest_command = "ctest", -- this is used to specify ctest command path
  ctest_show_labels = false, -- also show labels in the test picker
  cmake_use_preset = true,
  cmake_regenerate_on_save = true, -- auto generate when save CMakeLists.txt
  cmake_generate_options = { "-DCMAKE_EXPORT_COMPILE_COMMANDS=1" }, -- this will be passed when invoke `CMakeGenerate`
  cmake_build_options = {}, -- this will be passed when invoke `CMakeBuild`
```

The first entries are the paths to the tools themselves, with cmake_command specifying the cmake command path and ctest_command specifying the ctest command path, and then a switch to use a CMake preset, another to auto generate when saving CMakeLists.txt, and the options that are passed when the generate and build commands are invoked. The generate options are where the compile_commands export is enabled by default, and the build options are empty by default so that your own flags are not silently overridden.

## The build directory can be a function, which is how variants work

The configuration block that deserves a close read is cmake_build_directory, because it shows how the plugin handles the CMake concept of a variant, which is a per-configuration build type and generator. The default value is a function rather than a string, and the comment explains that it is used to specify the generate directory for cmake, allows macro expansion, can be a string or a function returning the string, and is relative to the current working directory. The macros it expands are listed in the comment, with a kit placeholder, a kit generator placeholder and a variant placeholder of the form variant:xx, and the body of the function branches on the operating system, returning a Windows style path when osys.iswin32 and a POSIX style path otherwise. That is the whole trick to multi-configuration support, since the build directory has to differ per variant, and the plugin resolves it by calling your function with the current kit and variant in scope rather than making you hardcode a directory. The same macro expansion is available elsewhere in the configuration, and the kits path is separately configurable, with a nil default pointing at a global CMake kits path.

## compile_commands integration has four strategies, and you pick one

The cmake_compile_commands_options block is the part that connects this plugin to the rest of your Neovim setup, since compile_commands.json is what a C++ language server reads. The action option lists the available strategies: soft_link, copy, lsp and none. A soft link automatically makes a soft link from the compile commands file to the target, a copy automatically copies the file to the target, lsp automatically sets the compile commands file location using the language server, and none ignores the option. The target is a path or a function returning a path to a directory, and the comment notes that it is used only if the action is soft_link or copy. That last detail is the practical point, since the lsp action hands the location to the language server rather than moving the file, and the file your server reads is the one CMake wrote. The plugin also has a variants message configuration controlling whether a short message or a long one with a maximum length is shown, and a cmake_dap_configuration block for debug settings that specifies a name, a type of codelldb, a launch request, whether to stop on entry, whether to run in a terminal, and which console to use.

## Executors and runners are pluggable, with four of each

The configuration separates two ideas that are easy to confuse. The executor is where output goes, and the runner is how the task is started. The executor block names a quickfix executor by default, with its own options, and the runner block names a terminal runner by default, again with its own options, and both carry a default_opts table listing the possible values for each type. The four executor options are quickfix, toggleterm, overseer and terminal, and the same four appear as runner options. Each has its own settings, and the comments explain them. The quickfix options cover whether to show the window always or only on error, the position, the size, the encoding, and whether to close the buffer automatically when the execution succeeds. The toggleterm options cover the direction, which can be vertical, horizontal, tab or float, whether to close on exit, whether to auto scroll, and whether the instance is a singleton. The overseer options are passed into the overseer.new_task command, and there is a hook that fires when the task is created, before the task is started, which is where the README shows opening the overseer panel. The terminal options are the most detailed, and they include a warning that the terminal name must be included and must be unique, otherwise the terminals will not work, and that you should not use a simple spacebar or any generic name. That is the kind of operational detail that only appears in a configuration file written by someone who hit the problem.

## Where cmake-tools.nvim is the wrong choice

The first limit is that the plugin is about orchestration, not diagnostics. It does configure, build, test and debug your project, but it does not give you the language intelligence of a C++ language server, and a Neovim setup with a working compile_commands.json and clangd already covers the completion and error reporting side. The second is the dependency chain. Beyond Neovim and plenary you now have cmake and ctest on the path, and optionally overseer and toggleterm, and each of those is a separate thing to install and keep in step. The third is the inheritance of a fork. The credit note is honest about it, the author changed too much of neovim-cmake to keep upstreaming, and the result is a project that will not automatically pick up improvements from neovim-cmake or from vscode-cmake-tools, so features that appear in those projects have to be ported by hand. The fourth is the project state. The repository has no GitHub releases, so there is no version history to pin against, the topics list includes dap-mode alongside the CMake and Neovim tags, and the plugin is GPL-3.0 licensed, which is fine for a personal configuration and something to think about if you plan to ship the plugin inside a proprietary product. The fifth is that the configuration surface is large, as the setup block in the README shows, and the comments are the only documentation for most of it, so a user who does not read the whole file will not know that the build directory can be a function.

## Conclusion

Adopt cmake-tools.nvim if you build C or C++ with CMake in Neovim and want the same command surface the Visual Studio Code extension gives you, without leaving the editor or installing a language server sidecar. Skip it if your project does not use CMake, or if the default Neovim LSP plus a compile_commands.json setup already covers your needs, since the plugin's value is the build and test orchestration rather than diagnostics. Verify first that you have Neovim 0.7 or newer and plenary installed, that your cmake and ctest binaries are on the path the configuration points at, and that the executor and runner you choose are one of the four the plugin supports.

## FAQ

### What does cmake-tools.nvim give a Neovim user?

It offers a workflow for CMake-based projects comparable to vscode-cmake-tools in Visual Studio Code, written in pure Lua. It provides commands to generate, build, run tests through ctest, and debug through a codelldb configuration, with kits, variants, macro expansion in the build directory and compile_commands.json integration.

### How do I install cmake-tools.nvim and what does it need?

It requires Neovim 0.7 or newer and the plenary library, with overseer and toggleterm optional integrations for task execution. You install it like any other Neovim plugin, with lazy.nvim, packer.nvim or vim-plug, and then call require("cmake-tools").setup with your options.

### How does cmake-tools.nvim handle the compile_commands.json file?

The cmake_compile_commands_options block has an action option with four choices, soft_link to link the compile commands file to the target, copy to copy it, lsp to set the compile commands file location using the language server, and none to ignore the option. The target is a path or a function returning one, and it is used only for the soft_link and copy actions.

## Sources

- [Civitasv/cmake-tools.nvim on GitHub](https://github.com/Civitasv/cmake-tools.nvim)
- [Issues](https://github.com/Civitasv/cmake-tools.nvim/issues)
- [License: GPL-3.0](https://github.com/Civitasv/cmake-tools.nvim/blob/master/LICENSE)
- [README](https://github.com/Civitasv/cmake-tools.nvim/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/civitasv-cmake-tools-nvim
