This guide prepares a macOS or Linux machine to build Cold from source. Cold is a C++20 Qt 6 Widgets desktop editor with optional terminal support through libvterm, optional tree-sitter support, and runtime integrations for tools such as rg, git, Node, and native compilers.
Start with the core build unless you specifically need every optional feature on the first pass.
| Build | Use when | CMake flags |
|---|---|---|
| Core editor | You want the fastest setup and can skip the embedded terminal if libvterm is missing |
-DCMAKE_BUILD_TYPE=Debug |
| Core + terminal | You want the Terminal tab built in | -DCOLD_ENABLE_TERMINAL=ON |
| Core + tree-sitter | You are testing the optional legacy lexical highlighting path | -DCOLD_ENABLE_TREESITTER=ON |
| Release | You want performance closer to a packaged editor | -DCMAKE_BUILD_TYPE=Release |
Important defaults:
COLD_ENABLE_TERMINALdefaults toON, but CMake only compiles terminal sources if it findslibvtermthroughpkg-config.- If
libvtermis missing, CMake prints a warning and builds without the embedded terminal. COLD_ENABLE_TREESITTERdefaults toOFF.- LSP semantic-token highlighting is part of the normal build. The optional tree-sitter path is not required for default syntax colors.
Cold requires:
| Dependency | Minimum / purpose |
|---|---|
| CMake | 3.21+ |
| Qt | 6.4+ with Core, Widgets, Concurrent, Sql, and Network |
| Compiler | C++20 compiler, usually GCC or Clang |
| SQLite | Used through the Qt Sql module |
| pkg-config | Needed for libvterm detection |
Optional but recommended:
| Tool | Purpose |
|---|---|
libvterm |
Embedded Terminal tab |
ripgrep / rg |
Project search |
git |
Git status, diff, stage, and commit UI |
node, npm, tsc, ts-node |
JavaScript and TypeScript run support |
gcc, g++, clang, clang++ |
C and C++ run support |
clang-format |
Local formatting checks |
tree-sitter core library and grammars |
Optional tree-sitter build |
Install the Xcode command line tools if they are not already installed:
xcode-select --installInstall the build dependencies with Homebrew:
brew install qt@6 cmake ninja pkg-config libvterm ripgrep git node llvm coreutilsApple Silicon Homebrew normally installs under /opt/homebrew. Intel Homebrew normally installs under /usr/local.
For Apple Silicon:
export CMAKE_PREFIX_PATH="/opt/homebrew/opt/qt@6"
export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH"For Intel:
export CMAKE_PREFIX_PATH="/usr/local/opt/qt@6"
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"The coreutils path matters for scripts/smoke.sh, because the script calls GNU timeout.
If you use Homebrew LLVM for clang-format, add it to PATH before running lint:
export PATH="$(brew --prefix llvm)/bin:$PATH"Check the required build tools:
cmake --version
c++ --versionCheck optional tools when you need those features:
pkg-config --modversion vterm
timeout --version
rg --version
git --version
node --versionIf Qt command-line tools such as qmake6 are not on PATH, that is usually fine as long as CMAKE_PREFIX_PATH points to qt@6.
Use the section for your distribution. Package names vary most around Qt and LLVM tooling.
sudo dnf install cmake ninja-build gcc gcc-c++ qt6-qtbase-devel pkgconf-pkg-config libvterm-devel ripgrep git nodejs npmFor formatting with the versions expected by the project:
sudo dnf install clang19-tools-extraOptional tree-sitter core:
sudo dnf install tree-sitter-develsudo apt update
sudo apt install cmake ninja-build build-essential qt6-base-dev pkg-config libvterm-dev ripgrep git nodejs npmFor formatting with the versions expected by the project:
sudo apt install clang-format-19Optional tree-sitter core:
sudo apt install libtree-sitter-devsudo pacman -Syu cmake ninja gcc qt6-base pkgconf libvterm ripgrep git nodejs npmFor formatting:
sudo pacman -S clangOptional tree-sitter core:
sudo pacman -S tree-sittersudo zypper install cmake ninja gcc gcc-c++ qt6-base-devel pkgconf-pkg-config libvterm-devel ripgrep git nodejs npmFor formatting:
sudo zypper install clangOptional tree-sitter core:
sudo zypper install tree-sitter-develClone the repository and enter it:
git clone <repo-url> cold
cd coldIf you already have the repository, enter the existing checkout:
cd /path/to/coldUse an out-of-source build directory. Ninja is recommended when installed, but Unix Makefiles also work.
Debug build:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=DebugRelease build:
cmake -S . -B build-release -G Ninja -DCMAKE_BUILD_TYPE=ReleaseTerminal-enabled build:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCOLD_ENABLE_TERMINAL=ONBuild without trying terminal support:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCOLD_ENABLE_TERMINAL=OFFTree-sitter opt-in build:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCOLD_ENABLE_TREESITTER=ONIf CMake cannot find Qt on macOS, pass the prefix explicitly:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6)"If CMake cannot find Qt on Linux, locate the Qt CMake directory:
find /usr -path '*Qt6Config.cmake' 2>/dev/nullThen configure with Qt6_DIR:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DQt6_DIR=/usr/lib/cmake/Qt6Adjust the Qt6_DIR path to the path reported on your system.
Build the configured tree:
cmake --build buildFor Release:
cmake --build build-releaseThe resulting executable is:
build/cold
or:
build-release/cold
Run the Debug binary:
./build/coldRun the Release binary:
./build-release/coldOn Linux desktop sessions, if Qt reports that no platform plugin can initialize, make sure the Qt platform packages for your desktop are installed. On headless systems, use the smoke test instead of opening the GUI.
Run the offscreen smoke test:
./scripts/smoke.sh ./build/coldFor a Release build:
./scripts/smoke.sh ./build-release/coldSmoke success is either:
| Exit code | Meaning |
|---|---|
0 |
The process exited within the smoke window |
124 |
GNU timeout stopped the app after it remained alive in the Qt event loop |
On macOS, if timeout is missing, install coreutils and put the Homebrew gnubin directory on PATH as shown in the macOS setup section.
Install to a local prefix:
cmake --install build --prefix "$HOME/.local"Run the installed binary:
"$HOME/.local/bin/cold"The install rules place:
| Installed item | Destination |
|---|---|
cold |
bin |
src/settings/schema.sql |
share/cold |
resources/lsp/manifest.json |
share/cold/lsp |
| LSP artifact directories | share/cold/lsp/clangd and share/cold/lsp/typescript |
Cold can build without these tools, but features depend on them at runtime.
| Runtime tool | Feature |
|---|---|
rg |
Project search |
git |
Git integration |
node |
JavaScript run |
npm |
TypeScript LSP provisioning path |
tsc |
TypeScript compile fallback |
ts-node |
Direct TypeScript run |
gcc, g++, clang, clang++ |
C and C++ run |
| shell | Embedded terminal process |
Install TypeScript tools globally if you want TypeScript run support outside project-local tooling:
npm install -g typescript ts-nodeIf a tool is not on the default PATH, open Cold and set it in:
File -> Preferences -> Tools
LSP server paths are not configured in the Tools tab. Cold resolves language servers separately.
Cold supports:
| Language group | Server id |
|---|---|
| C / C++ | clangd |
| JavaScript / TypeScript | typescript |
Resolution order:
- Managed cache under the platform data directory.
COLD_LSP_DIR.- Installed
share/cold/lsp. <appDir>/lsp.- Automatic provisioning when
general.lsp_auto_downloadis enabled. PATHfallback only after provisioning fails andCOLD_LSP_ALLOW_PATH=1orCOLD_LSP_PATH_FALLBACK=1.
Default cache locations:
| Platform | Cache path |
|---|---|
| Linux | ~/.local/share/cold/lsp |
| macOS | ~/Library/Application Support/cold/lsp |
For offline development, place server artifacts under a custom directory and point Cold at it:
export COLD_LSP_DIR="/path/to/cold-lsp"Expected shape:
/path/to/cold-lsp/clangd/
/path/to/cold-lsp/typescript/
To allow fallback to language servers already on PATH after provisioning fails:
export COLD_LSP_ALLOW_PATH=1The project lint script checks C++ formatting for files under src using .clang-format.
Format check (default):
./scripts/lint.shExplicit format check:
./scripts/lint.sh --format-onlyCI-like mode (stricter version check and --Werror):
./scripts/lint.sh --ciApply formatting:
./scripts/lint.sh --fix-formatExpected LLVM tooling:
| Tool | Expected version |
|---|---|
clang-format |
LLVM 19 or 18 |
CI uses a Release build-ci tree for the offscreen smoke test. To mirror that layout locally:
cmake -S . -B build-ci -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build-ci
./scripts/lint.sh --ci
./scripts/smoke.sh ./build-ci/coldThe CMake integration also exposes lint targets after configure:
cmake --build build --target cold-format-check
cmake --build build --target cold-lintmacOS fix:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6)"Linux fix:
find /usr -path '*Qt6Config.cmake' 2>/dev/nullThen configure with the matching Qt6_DIR.
Confirm libvterm is visible to pkg-config:
pkg-config --modversion vtermReconfigure after installing libvterm:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCOLD_ENABLE_TERMINAL=ON
cmake --build buildTree-sitter is optional and disabled by default. Enable it explicitly:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCOLD_ENABLE_TREESITTER=ONThe build requires the tree-sitter core library and headers. If system grammar libraries are not found, CMake may fetch the C, C++, and JavaScript grammar sources during configure.
Install GNU coreutils:
brew install coreutilsAdd gnubin to PATH:
export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH"Check whether automatic downloads are enabled in:
File -> Preferences -> General
For offline use, set COLD_LSP_DIR and use the expected server directory shape. For development-only PATH fallback, set:
export COLD_LSP_ALLOW_PATH=1Install the missing runtime tool and make sure it is on PATH. If Cold still cannot find it, configure the absolute path in:
File -> Preferences -> Tools
Remove a build directory and configure again:
rm -rf build
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build buildIf you are changing optional dependencies, a clean configure is often clearer than reusing an old CMake cache.
Before sending a build-related change, run the smallest checks that cover it:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build
./scripts/smoke.sh ./build/cold
./scripts/lint.sh --format-onlyFor release behavior:
cmake -S . -B build-release -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build-release
./scripts/smoke.sh ./build-release/cold