Skip to content

FAQ

Why Neovim and not Qt Creator / VS Code / CLion?

Nothing stops you using any of them — the environment is editor-neutral underneath. The devshell exports build/compile_commands.json, so any clangd-based IDE (Qt Creator, VS Code + clangd, CLion) gets full C++ intelligence by opening the checkout; pyrightconfig.json does the same for Python. Qt Creator in particular imports the CMake project directly and is an excellent choice for GUI-heavy work and the visual designer.

What Neovim gets you here specifically is the packaged, reproducible experience: nix-vim is a flake input pinned in flake.lock, so every colleague has the same editor to the byte, and the <leader>p menu drives the same qgis-dev tasks the terminal and CI use — no per-machine IDE setup, no config drift, nothing to install. Qt Creator's project files, by contrast, are per-user state we'd have to keep out of the pristine checkout, and its version isn't pinned by our flake.

So: Neovim is the supported, zero-setup default; Qt Creator is a first-class option you can point at the same build tree. If you want it, open CMakeLists.txt in Qt Creator from inside the devshell (so it finds the pinned toolchain) and set the build directory to build/. Just don't let it write project files into tracked upstream paths — qgis-dev doctor will warn you if anything lands where git can see it.

Why embed the sidecar in the checkout instead of keeping it separate?

An external location works (bootstrap uses absolute symlinks then), but the embed keeps the whole project under one folder and, crucially, lets tooling that can only see the current directory tree — sandboxes, some editors — reach it. Because it's a plain nested clone hidden by .git/info/exclude, it costs nothing in isolation. See Bootstrap & isolation.

Why not just use upstream QGIS's own flake / devShell?

We do — as an input. We compose our devshell on top of upstream's packages so we inherit their full dependency set without maintaining a copy, while owning the activation experience (our banner instead of their dev-help). Editing their flake.nix to add our tooling would modify a tracked upstream file — exactly what the isolation rules forbid. See The flake.

Why does the first direnv allow download ~240 MiB of "QGIS"?

Nix must fetch the pinned QGIS source snapshot to evaluate the devshell (it reads upstream's nix/ files). It is copied, not compiled — your build still happens in build/. It's a one-time cost per lockfile pin, cached in the nix store and shared across worktrees. See Troubleshooting.

Why is my first build so slow, and later ones fast?

The first build compiles ~6,000 units cold (hours). Every object lands in a 50 GB shared ccache, so subsequent builds — even after switching branches or worktrees — mostly hit the cache and finish in seconds to minutes. qgis-dev report shows the difference as a log-scaled trend.

Does editing QGIS GUI recompile QGIS core too?

No. Ninja's dependency graph rebuilds only what actually changed and what links against it. Editing a .cpp in qgis_gui recompiles one object and relinks gui + the app; qgis_core is untouched. Editing a widely-included core header is the expensive case (many translation units include it) — inherent to C++, not a tooling limitation. See Build, run & profiles.

Where does the clangd index live, and is it reused?

In <checkout>/.cache/clangd/index/, one shard per file, and yes — it persists and is reused across every session. The first nvim in a fresh checkout spends tens of minutes background-indexing QGIS (you can work meanwhile; the open file is intelligent almost immediately), and every session after that starts fully indexed. Bootstrap excludes .cache/ from git so it never dirties git status. Each worktree indexes once on its own (the index is project-relative). See Editing with Neovim.

What will keep me waiting, and how often?

One-time cost When Roughly
Toolchain download (direnv allow) first activation per machine/pin minutes
Cold QGIS build first qgis-dev build hours (then ccache-warm)
clangd background index first nvim per checkout/worktree tens of minutes, non-blocking

Everything after those is seconds-to-minutes. The Under the Hood section explains why each is one-time.

Can I run several feature branches at once?

Yes — qgis-dev worktree add <branch> creates a sibling worktree, already bootstrapped, sharing the ccache so it builds warm. See Worktrees.

Is any of this OK to submit to upstream QGIS?

The tooling must never reach upstream — three isolation layers enforce that. Your code contributions are welcome upstream provided they are your own human-authored work: QGIS does not accept AI-generated contributions. Read the AI policy before your first patch.

Will this work on macOS / non-NixOS Linux?

It targets NixOS. It may work on any Linux with the Nix package manager and direnv; macOS is untested (the flake declares the Linux systems). The build-tree strategy and qgis-dev are platform-neutral, but some QA tools (perf, GammaRay) are Linux-only.

How do I remove it all cleanly?

./qgis-dev-env/bootstrap.sh --remove . unlinks the overlay, strips the exclude block, and restores a byte-pristine checkout (your PROMPT.log and state are preserved under $XDG_STATE_HOME). Then delete the qgis-dev-env/ folder if you want it gone entirely.

Something's wrong — where do I start?

qgis-dev doctor (or <leader>pv) checks the toolchain, the symlinks and exclude block, the guards, the compile database and Python staging, and isolation across every worktree. Most answers are in Troubleshooting.