SoloAI Tools

Grok Bot on Arch: when Settings won’t click

Stuck on 0.29.0. We needed egress, but Check for Updates / Update was dead in-app, so we couldn’t enable it. The unlock was a terminal upgrade. Run ~/bin/upgrade-grok-bot.sh (general AUR yay -S grok-bot-bin). Our first run was 0.29 → 0.47. The CEO Grok Bot agent in chat wrote / helped with that path.

How-to video (owner cut, first 60s) — same script on a later run when AUR had lagged (0.47 → 0.51):

Grok Bot upgrade script — 0:00–1:00

What was broken

Settings opened. Check for Updates wasn’t usable. We were stuck on an older build while newer ones existed.

Stuck Settings — in-app update path dead

The unlock: terminal upgrade

Note: Arch/Omarchy + yay only; prefers AUR, falls back to official .deb when AUR lags; not Windows/Mac.

Give this to your agent — paste the script (or the download) and tell your Grok Bot / Cursor agent to install or run it on your Arch/Omarchy machine. Readers shouldn’t have to be the sysadmin; the agent can drive it.

What worked right after: the upgrade script. Download: upgrade-grok-bot.sh (save as ~/bin/upgrade-grok-bot.sh, then chmod +x ~/bin/upgrade-grok-bot.sh).

~/bin/upgrade-grok-bot.sh

That script prefers AUR yay -S grok-bot-bin when current enough, and falls back to the official .deb via makepkg when AUR lags (quit the app first; when asked, remove the conflicting grok-bot package; keep ~/.config/Grok Bot). Same idea by hand when AUR is current:

yay -S grok-bot-bin

Our first run was 0.29 → 0.47. After that, the stuck-on-old-version / dead Check for Updates problem was gone. (Older ~/bin/upgrade-grok-bot-047.sh is a thin wrapper that calls upgrade-grok-bot.sh.)

Full script (copy-paste):

#!/usr/bin/env bash
# Upgrade Grok Bot on Arch/Omarchy.
# Prefer AUR grok-bot-bin when it matches Cursor stable.
# If AUR lags, install the official .deb via makepkg (pacman-tracked).
set -euo pipefail

HELPERS="$(cd "$(dirname "$0")" && pwd)/grok-bot-upgrade-helpers"
WORKDIR="${TMPDIR:-/tmp}/grok-bot-upgrade-$$"

ver_ge() {
  # true if $1 >= $2 (x.y.z)
  printf '%sn%sn' "$2" "$1" | sort -V | head -1 | grep -qx "$2"
}

installed_version() {
  if pacman -Q grok-bot-bin >/dev/null 2>&1; then
    pacman -Q grok-bot-bin | awk '{print $2}' | sed 's/-.*//'
  elif pacman -Q grok-bot >/dev/null 2>&1; then
    pacman -Q grok-bot | awk '{print $2}' | sed 's/-.*//'
  else
    echo "0"
  fi
}

aur_version() {
  yay -Si grok-bot-bin 2>/dev/null | awk -F' *: *' '/^Version/{print $2; exit}' | sed 's/-.*//' || true
}

official_meta() {
  python3 - <<'PY'
import json, urllib.request, uuid, re, sys
mid = str(uuid.uuid4())
url = f"https://api2.cursor.sh/updates/api/update/linux-x64/sand/0.1.0/{mid}/stable"
req = urllib.request.Request(url, headers={"User-Agent": "upgrade-grok-bot/1.1"})
with urllib.request.urlopen(req, timeout=30) as r:
    d = json.loads(r.read().decode())
ver = d.get("productVersion") or d.get("version")
u = d.get("url") or ""
m = re.search(r"/([0-9a-f]{40})/", u)
if not ver or not m:
    print("failed to parse official release", ver, u, file=sys.stderr)
    sys.exit(2)
commit = m.group(1)
deb = f"https://downloads.cursor.com/grokbot/stable/{commit}/linux/x64/grok-bot_{ver}_amd64.deb"
print(ver)
print(commit)
print(deb)
PY
}

backup_config() {
  mkdir -p ~/backups
  local stamp=~/backups/"Grok-Bot-config-$(date +%F)"
  if [[ ! -d "$stamp" ]]; then
    cp -a ~/.config/"Grok Bot" "$stamp" || true
  fi
  echo "Config backup: $stamp"
}

quit_app() {
  echo "Quitting Grok Bot (this chat dies if still open)..."
  pkill -TERM -f '/opt/Grok Bot/grok-bot' 2>/dev/null || true
  sleep 2
  if pgrep -af '/opt/Grok Bot/grok-bot' >/dev/null; then
    pkill -KILL -f '/opt/Grok Bot/grok-bot' 2>/dev/null || true
    sleep 1
  fi
  if pgrep -af '/opt/Grok Bot/grok-bot' >/dev/null; then
    echo "Could not stop Grok Bot; abort."
    exit 1
  fi
  echo "grok-bot stopped"
}

install_via_aur() {
  echo "AUR grok-bot-bin is current enough — using yay..."
  yay -S grok-bot-bin --answerclean N --answerdiff N --answeredit N
}

install_via_official() {
  local ver="$1"
  local deb_url="$3"
  echo "AUR lags. Installing official ${ver} from Cursor CDN via makepkg..."
  mkdir -p "$WORKDIR"
  cd "$WORKDIR"
  curl -fL --retry 3 -o "grok-bot_${ver}_amd64.deb" "$deb_url"
  local sum
  sum="$(sha256sum "grok-bot_${ver}_amd64.deb" | awk '{print $1}')"

  if [[ -f "$HELPERS/grok-bot.sh" ]]; then
    cp "$HELPERS/grok-bot.sh" ./grok-bot.sh
  else
    cat > grok-bot.sh << 'EOS'
#!/bin/sh
export FONTCONFIG_NO_CHECK_CACHE_VERSION=1
exec "/opt/Grok Bot/grok-bot" "$@"
EOS
  fi
  chmod +x grok-bot.sh

  cat > PKGBUILD <<PKG
pkgname=grok-bot-bin
pkgver=${ver}
pkgrel=1
pkgdesc='Grok Bot desktop agent (official deb via upgrade-grok-bot.sh)'
arch=('x86_64')
url='https://cursor.com'
license=('LicenseRef-Proprietary')
depends=(gtk3 libnotify nss libxss libxtst xdg-utils at-spi2-core util-linux-libs libsecret hicolor-icon-theme alsa-lib libappindicator)
provides=('sand' 'grok-bot')
conflicts=('sand' 'grok-bot' 'grokbot-linux-port' 'grokbot-linux-port-bin')
replaces=('grok-bot')
options=('!strip' '!debug')
source=(
  "grok-bot_${pkgver}_amd64.deb"
  grok-bot.sh
)
sha256sums=('${sum}' 'SKIP')
noextract=("grok-bot_${pkgver}_amd64.deb")
package() {
  bsdtar -O -xf "grok-bot_${pkgver}_amd64.deb" data.tar.xz | bsdtar -C "${pkgdir}" -xJf -
  local _res="${pkgdir}/opt/Grok Bot/resources"
  if [[ -f "${_res}/apparmor-profile" ]]; then
    install -Dm644 "${_res}/apparmor-profile" "${pkgdir}/etc/apparmor.d/grok-bot"
  fi
  install -Dm755 grok-bot.sh "${pkgdir}/usr/bin/grok-bot"
  ln -sf grok-bot "${pkgdir}/usr/bin/sand"
  if [[ -f "${pkgdir}/usr/share/applications/grok-bot.desktop" ]]; then
    sed -i 's|^Exec=.*|Exec=grok-bot %U|' "${pkgdir}/usr/share/applications/grok-bot.desktop"
  fi
  rm -rf "${pkgdir}/usr/share/doc"
}
PKG

  makepkg -si --noconfirm
  cd /
  rm -rf "$WORKDIR"
}

verify() {
  echo "Verify:"
  pacman -Qi grok-bot-bin 2>/dev/null | rg -i '^(Name|Version)' || true
  ls -l /usr/bin/grok-bot /usr/bin/sand
  test -d ~/.config/"Grok Bot" && echo "config intact"
  echo "Done. Launch with: grok-bot"
}

main() {
  echo "== Grok Bot upgrade (AUR or official when AUR lags) =="
  backup_config

  mapfile -t meta < <(official_meta)
  local official="${meta[0]}"
  local commit="${meta[1]}"
  local deb_url="${meta[2]}"
  local installed aur
  installed="$(installed_version)"
  aur="$(aur_version)"
  echo "Installed: ${installed}"
  echo "AUR:       ${aur:-unknown}"
  echo "Official:  ${official}"

  if ver_ge "$installed" "$official"; then
    echo "Already on official-or-newer (${installed}). Nothing to do."
    exit 0
  fi

  quit_app

  if [[ -n "$aur" ]] && ver_ge "$aur" "$official"; then
    install_via_aur
  else
    echo "AUR (${aur:-none}) behind official ${official}."
    install_via_official "$official" "$commit" "$deb_url"
  fi

  verify
}

# Only run when executed, never when sourced
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  main "$@"
fi

Upgrade path — terminal yay / upgrade script vs dead in-app Update

Separate beat: egress 503 — Update Computer, not Reset

If egress still fails with a 503, that’s a missing tunnel — not the version problem. Hit Update Grok Bot’s Computer. Do not hit Reset Computer for this.

Settings — Update Grok Bot’s Computer

Egress — Update Computer provisions tunnel, not Reset

Harmless terminal noise

You may see grok-bot-tray chatter and Node ExperimentalWarning lines. Leave the terminal open; that noise is harmless for this setup.

Quick checklist

Symptom Try this Don’t
Stuck on an old build (we were on 0.29.0); Check for Updates dead ~/bin/upgrade-grok-bot.sh or yay -S grok-bot-bin (quit app; keep config) Rely on in-app Check for Updates on this build
Egress 503 / tunnel missing Update Grok Bot’s Computer Reset Computer (wrong tool for a missing tunnel)
Tray / Node warnings in terminal Ignore; leave terminal open Panic-wipe config

Optional footnote

One morning we also tried --ozone-platform=x11 when clicks felt flaky. Owner is not convinced that was the fix; the lasting unlock for the stuck version was the upgrade script. Current session can run Wayland. Skip X11 unless you’re chasing a click quirk after you’re already on a current build.