# NixOS and other nix users: the desktop front end (Qt Quick) with the engine # it embeds, built and installed the nix way. # # nix-build # ./result/bin/cst-agent-app, run it in place # nix-env -f . -i cst-agent # into the user profile: PATH, menu entry, icon # # The Qt apps hook is what makes the installed binary find Qt's plugins and # QML modules outside a nix-shell (this is also what keeps them out of # nix-collect-garbage's reach). Only the window is installed: the CLI has its # own installer, scripts/bootstrap_linux.sh. { pkgs ? import { } }: let # The version lives in one place: the header the engine and the APK read. vLine = re: let hit = pkgs.lib.findFirst (l: builtins.match "#define ${re} ([0-9]+)" l != null) "" (pkgs.lib.splitString "\n" (builtins.readFile ./include/cst_version.h)); in builtins.head (builtins.match "#define ${re} ([0-9]+)" hit); in pkgs.stdenv.mkDerivation { pname = "cst-agent"; version = "${vLine "CST_VERSION_MAJOR"}.${vLine "CST_VERSION_MINOR"}.${vLine "CST_VERSION_PATCH"}"; # Not the whole checkout: third_party/ (the static curl/mbedTLS/ncurses # sources, the NDK builds), the build directories and the session store are # gigabytes this build never reads -- curl, ncurses and Qt come from nixpkgs. src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".agent" ".cursor" ".gen" ".git" "build-android-arm64-v8a" "build-apk-android" "build-win-tui" "dist" "result" "third_party" ])) ./.; nativeBuildInputs = with pkgs; [ cmake pkg-config qt6.wrapQtAppsHook ]; # qtwayland so a Wayland session gets a native client, qtsvg for the icon # theme: Breeze's icons are SVG, and without the image format plugin the # window falls back to text glyphs. buildInputs = with pkgs; [ qt6.qtbase qt6.qtdeclarative qt6.qtwayland qt6.qtsvg curl curl.dev ncurses ncurses.dev ]; cmakeFlags = [ "-DCST_BUILD_APP=ON" "-DCMAKE_BUILD_TYPE=Release" ]; # The "app" component is the window, its launcher entry and the icon; # app/CMakeLists.txt is the one place that knows where each goes. installPhase = '' runHook preInstall cmake --install . --component app --prefix "$out" runHook postInstall ''; doCheck = true; # One test cannot pass here: tests/test_sandbox.c has the engine run a # sandboxed command and asserts Landlock *denied* the write outside the # workspace, and Landlock does not work inside the nix build sandbox -- the # command succeeds and the assertion trips. The other 40 run; the full set # is `make check` / `ctest` in the dev tree. checkPhase = '' runHook preCheck ctest --output-on-failure -j"$NIX_BUILD_CORES" -E test_sandbox runHook postCheck ''; # The tests write settings, sessions, undo files and a scratch workspace: # give them a home of their own. preCheck = '' export HOME="$TMPDIR/home" export XDG_CONFIG_HOME="$HOME/.config" XDG_CACHE_HOME="$HOME/.cache" export XDG_DATA_HOME="$HOME/.local/share" mkdir -p "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" "$XDG_DATA_HOME" ''; meta = { description = "Local coding agent: Qt Quick front end with the engine in-process"; homepage = "https://git.whcself.xyz/WHC/CST-agent"; platforms = pkgs.lib.platforms.linux; mainProgram = "cst-agent-app"; }; }