grok-bot-flake

August 14, 2026 · View on GitHub

Nix flake for Grok Bot, xAI's desktop agent, on Linux. It repackages the official amd64 .deb — there is no source build.

Note

Grok Bot is proprietary (meta.license = unfree). This flake is not affiliated with xAI or Cursor.

Quick start

Run it once, without installing:

nix run github:jordangarrison/grok-bot-flake

This works, but sand:// login-redirect links will not route back to the app until the package is properly installed — see Getting sand:// links to work.

Add it to your Nix config

Flake input

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    grok-bot = {
      url = "github:jordangarrison/grok-bot-flake";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };
}

NixOS

{ inputs, pkgs, ... }:
{
  environment.systemPackages = [
    inputs.grok-bot.packages.${pkgs.system}.default
  ];
}

Home Manager

{ inputs, pkgs, ... }:
{
  home.packages = [
    inputs.grok-bot.packages.${pkgs.system}.default
  ];
}

Overlay (if you prefer pkgs.grok-bot)

nixpkgs.overlays = [ inputs.grok-bot.overlays.default ];
environment.systemPackages = [ pkgs.grok-bot ];

The flake's own packages output already allows unfree for you. The overlay deliberately does not — it uses your nixpkgs config, so you need allowUnfree (or an allowUnfreePredicate matching grok-bot) when consuming it that way.

Imperative install

nix profile install github:jordangarrison/grok-bot-flake

What you get

  • grok-bot — the app, wrapped for NixOS (patchelf'd, GApps-wrapped, Wayland-aware).
  • sand — a compatibility alias for the same binary. Older upstream releases used that executable name, and the app still registers the sand:// URL scheme used by existing login flows.
  • share/applications/grok-bot.desktop + icon, so launchers and URL-scheme routing can find the app.

Wayland is opt-in through the usual NixOS variable: with NIXOS_OZONE_WL=1 set (and a Wayland session), the wrapper adds --ozone-platform-hint=auto and Wayland window decorations. Otherwise it runs under XWayland/X11.

Login redirects open sand://... URLs. For your desktop environment to route those to Grok Bot, two things must hold:

  1. grok-bot.desktop must be on XDG_DATA_DIRS — true automatically once the package is installed via NixOS, Home Manager, or nix profile install. A bare nix run does not do this.

  2. The scheme must map to the app. The app registers itself on first launch (the wrapper sets CHROME_DESKTOP=grok-bot.desktop so Electron registers the right desktop id). To set it manually:

    xdg-mime default grok-bot.desktop x-scheme-handler/sand
    

Verify with:

xdg-mime query default x-scheme-handler/sand   # → grok-bot.desktop

Empty output means the desktop file isn't visible (see 1). The desktop id stays grok-bot.desktop across rebuilds even though the store path in Exec= changes, so the association survives upgrades.

Packaging notes

Upstream ships its own Electron 42 build, and the bundled native modules (better-sqlite3, tree-sitter, and others) are compiled against it. This flake keeps that Electron instead of swapping in pkgs.electron_42 — no ABI risk, and the result matches what upstream tests.

The build unpacks the .deb, runs autoPatchelfHook over the binaries and .node modules, and wraps the launcher with wrapGAppsHook3.

Differences from the .deb:

  • chrome-sandbox is removed. It only works setuid root, which the Nix store cannot express. Chromium falls back to the user-namespace sandbox, which NixOS enables by default. If your kernel disables unprivileged user namespaces, the app will not start — re-enable them rather than running with --no-sandbox.

  • --no-sandbox is added. Upstream's custom Electron build crash-loops every sandbox: true renderer — notably the <webview> that shows your agent's box screen — with FATAL:platform_shared_memory_region_posix.cc (/dev/shm ... No such process). Traced with strace: the renderer is forked from the sandboxed zygote (chroot'd into a dead /proc/<tid>/fdinfo, which is where the odd ESRCH comes from) and then tries to create /dev/shm shared memory directly. Stock Chromium brokers that allocation through the browser process; upstream's build never installs the broker hooks for webview renderers, so the crash is environment-independent — the same signature is reported for .deb-class Electron apps on stock Ubuntu (electron#30758, open-webui/desktop#157). A stock nixpkgs electron_42 runs the identical sandboxed renderer fine.

    The flag costs nothing that works today: upstream already launches its main renderer with --no-sandbox --no-zygote, its GPU process with --no-sandbox, and every utility process with --service-sandbox-type=none. The webview was the only process that got a real sandbox, and it only ever crashed. The flag will be removed when upstream fixes their sandboxed-renderer shared-memory path.

  • The AppArmor profile is not installed. It is Ubuntu-specific and refers to /opt paths that do not exist here.

Updating

./update.sh

Reads the current stable version from upstream's update feed and rewrites the download namespace, version, buildId, and hash in package.nix. It also checks that the downloaded artifact is the expected sand/grok-bot amd64 package and that its embedded version matches the feed before changing anything.

One wrinkle: upstream's Linux update feed is empty — linux-x64 answers HTTP 204 for every version, and the in-app updater has no Linux branch at all (it falls through to darwin-arm64). The download namespace and build id are shared across platforms, so the script reads them from the darwin-arm64 feed, rebuilds the conventional Linux .deb URL, downloads it, and validates its metadata. If upstream changes that Linux URL convention, the update fails safely instead of committing an unverified package. This also means in-app self-update does not work on Linux — re-run ./update.sh and rebuild instead.

A daily GitHub Actions workflow runs the updater, refreshes flake.lock, builds the package, and commits verified changes to main. The workflow can also be run manually from the Actions tab.

To pin an exact build, pass its URL:

./update.sh https://downloads.cursor.com/<product>/stable/<buildId>/linux/x64/Grok_Bot_<version>.deb

Provenance

The .deb is served from downloads.cursor.com, and its control file lists SpaceXAI <hi@cursor.com> as vendor with Homepage: https://cursor.com. Upstream renamed the Debian package from sand to grok-bot in 0.19.0 while retaining sand as a provided compatibility name. The app is built on Cursor's release infrastructure. That is expected, not a mis-download.