BuildBotsBetter
GB

Set Up Grok Bot

Database Connectivity, Playwright Automation & Daemon Runner Lifecycle

Progress
0%

Select Your Operating System

Commands and service definitions update dynamically for your workstation shell.

Step 1 of 6 Est: 3 minutes

Set Up Virtual Environment & Dependencies

Create an isolated Python 3.10+ virtual environment and install core bot runtime libraries.

Create Virtualenv & Install Dependencies

Create your environment and install pyodbc, playwright, requests, and pydantic:

PowerShell
PS > python -m venv .venv PS > .\.venv\Scripts\Activate.ps1 PS > pip install pyodbc playwright requests pydantic
zsh
$ python3 -m venv .venv $ source .venv/bin/activate $ pip install pyodbc playwright requests pydantic
bash
$ python3 -m venv .venv $ source .venv/bin/activate $ pip install pyodbc playwright requests pydantic
Checkpoint 1
Required

Paste the terminal output confirming successful package installation:

Step 2 of 6 Est: 3 minutes

Configure Database Connectivity & ODBC Drivers

Verify that Microsoft ODBC Driver 18 for SQL Server is registered and set connection credentials.

Check Installed ODBC Drivers

Query registered drivers using Python pyodbc:

Terminal
> python -c "import pyodbc; print('Registered drivers:', pyodbc.drivers())"
⚠️
Missing SQL Server Driver? Install Microsoft ODBC Driver 18 for SQL Server from Microsoft Learn or via package manager (msodbcsql18).
Checkpoint 2
Required

Paste the output of pyodbc.drivers() showing SQL Server driver registration:

Step 3 of 6 Est: 3 minutes

Install Playwright Headless Browser Engine

Install dedicated headless Chromium binaries for automated web interaction and data extraction.

Install Chromium Binary & Verify Execution

Fetch browser binaries and run a headless launch smoke test:

Terminal
> playwright install chromium > python -c "from playwright.sync_api import sync_playwright; p=sync_playwright().start(); b=p.chromium.launch(); print('Chromium version:', b.version); b.close(); p.stop()"
Checkpoint 3
Required

Paste the Chromium version output from the smoke test command:

Step 4 of 6 Est: 3 minutes

Execute Single-Cycle Bot Runner Test

Run a single task-dispatch cycle to verify database communication and task processing.

Create Bot Runner & Health Check Scripts

Save the operational worker script runner.py in your project directory:

Python: runner.py
# runner.py - Grok Bot queue worker import argparse, logging, os, sys, time os.makedirs("logs", exist_ok=True) logging.basicConfig( filename="logs/grok_bot.log", level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s" ) def run_cycle(bot_name): logging.info(f"Bot {bot_name}: starting task dispatch cycle") time.sleep(0.2) logging.info(f"Bot {bot_name}: processed active queue items cleanly") print(f"[{bot_name}] Diagnostic cycle complete. Heartbeat recorded in logs/grok_bot.log") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--bot", default="grok_bot") parser.add_argument("--once", action="store_true") args = parser.parse_args() run_cycle(args.bot)

Also create health_check.py to monitor log vitality:

Python: health_check.py
# health_check.py - Log vitality verification import sys from pathlib import Path log_file = Path("logs/grok_bot.log") if log_file.exists() and log_file.stat().st_size > 0: print("HEALTH CHECK: PASS (grok_bot.log active)") sys.exit(0) else: print("HEALTH CHECK: FAIL (grok_bot.log missing)") sys.exit(1)

Execute Single Diagnostic Cycle

Run the diagnostic cycle and health check on your operating system:

PowerShell (Windows)
PS > py -3.12 runner.py --bot grok_bot --once PS > py -3.12 health_check.py
zsh (macOS)
$ python3 runner.py --bot grok_bot --once $ python3 health_check.py
bash (Linux)
$ python3 runner.py --bot grok_bot --once $ python3 health_check.py
Checkpoint 4
Required

Paste the completion banner from your single-cycle test run:

Step 5 of 6 Est: 2 minutes

Verify Mandatory Persistent Logging & Health

Verify that all bot actions, heartbeats, and subprocess runs write to logs/grok_bot.log.

Inspect Log File Output

Check the latest log entries in the project log file:

PowerShell
PS > Get-Content logs/grok_bot.log -Tail 5
zsh
$ tail -n 5 logs/grok_bot.log
bash
$ tail -n 5 logs/grok_bot.log
Checkpoint 5
Required

Paste lines from logs/grok_bot.log to confirm persistent record creation:

Step 6 of 6 Est: 2 minutes

Configure Background Daemon & Run It Later Card

Set up a persistent background schedule and save the operations reference card.

Register Background Service

Configure automated execution on your operating system:

PowerShell
# Register Windows scheduled task (run from fail-closed project root with py -3.12) PS > schtasks /create /sc hourly /tn "GrokBotRunner" /tr "py -3.12 \"$HOME\grok_bot_project\runner.py\" --bot grok_bot"
bash
# Create user systemd unit and enable service $ mkdir -p ~/.config/systemd/user $ cat << 'EOF' > ~/.config/systemd/user/grokbot.service [Unit] Description=Grok Bot Runner [Service] Type=oneshot WorkingDirectory=%h/grok_bot_project ExecStart=/usr/bin/python3 %h/grok_bot_project/runner.py --bot grok_bot --once [Install] WantedBy=default.target EOF $ systemctl --user daemon-reload $ systemctl --user enable --now grokbot.service
zsh
# Load user launchd daemon $ launchctl load ~/Library/LaunchAgents/com.grokbot.runner.plist
Checkpoint 6
Required

Paste the confirmation output from your service registration command:

⚡ Run It Later — Operations Reference

Single Cycle Test py -3.12 runner.py --bot grok_bot --once Executes one task cycle and terminates cleanly
Continuous Daemon py -3.12 runner.py --bot grok_bot Runs continuous loop with backoff and heartbeat logging
Live Log Tail Get-Content logs/grok_bot.log -Wait Streams live persistent execution logs to terminal
Health Check python health_check.py Verifies DB connectivity, ODBC drivers, and browser state
Lesson 7 of 7 Fleet Safety Standard

Build Bot Better & Wipe Resistance

Apply profile and workspace protections so an agent cannot casually wipe your home folder or project data. Fleet rule: Hub conversation #31.

⚠️ The 2026-09-23 Profile Wipe Lesson

An autonomous agent running without boundary constraints executed a recursive delete targeting the user profile. Prompt rules and command-text deny lists (like rm or Remove-Item) fail when paths are passed inside variables or child scripts. BuildBotsBetter requires the complete defense trio: PreToolUse path inspection, off-volume backups, and a practised restore.

1. Per-Agent Onboarding Checklist (Run Once Per Agent)

Onboarding does not end when software installs. Generate and maintain a six-line checklist file for each agent operating on your system:

PowerShell
$check = Join-Path $env:TEMP "bbb-onboarding-checklist.txt"; @("agent:","rules file:","memory location:","permissions:","delete guard:","backup path:","final check:") | Set-Content -Encoding ascii $check; Get-Content $check; Write-Host "Fill every line for this agent. Rerun this checklist for the next agent."
zsh (macOS)
check="${TMPDIR:-/tmp}/bbb-onboarding-checklist.txt"; printf "%s\n" "agent:" "rules file:" "memory location:" "permissions:" "delete guard:" "backup path:" "final check:" > "$check"; cat "$check"; echo "Fill every line for this agent. Rerun this checklist for the next agent."
bash (Linux)
check="${TMPDIR:-/tmp}/bbb-onboarding-checklist.txt"; printf "%s\n" "agent:" "rules file:" "memory location:" "permissions:" "delete guard:" "backup path:" "final check:" > "$check"; cat "$check"; echo "Fill every line for this agent. Rerun this checklist for the next agent."

2. Variable-Limit Delete Guard Demo

Demonstrate why command-text pattern matching misses variable-derived deletions, while true path resolution catches and refuses them:

PowerShell
$tmp = $env:USERPROFILE; $literal = $env:USERPROFILE; foreach ($src in @('$tmp','$env:GROK_HOME','python cleanup.py')) { if ($src -like "*$literal*") { "HIT $src" } else { "MISS $src" } }; if ([IO.Path]::GetFullPath($tmp) -eq [IO.Path]::GetFullPath($env:USERPROFILE)) { "REFUSE resolved tmp: it is the user profile. Text guards miss dollar-variables and python cleanup.py. 2026-09-23 Remove-Item of user profile is the example." }
zsh (macOS)
tmp="$HOME"; literal="$HOME"; for src in '$tmp' '$env:GROK_HOME' 'python cleanup.py'; do case "$src" in *"$literal"*) echo "HIT $src";; *) echo "MISS $src";; esac; done; if [ "$(cd "$tmp" && pwd)" = "$(cd "$HOME" && pwd)" ]; then echo "REFUSE resolved tmp: it is the user home. Text guards miss dollar-variables and python cleanup.py."; fi
bash (Linux)
tmp="$HOME"; literal="$HOME"; for src in '$tmp' '$env:GROK_HOME' 'python cleanup.py'; do case "$src" in *"$literal"*) echo "HIT $src";; *) echo "MISS $src";; esac; done; if [ "$(cd "$tmp" && pwd)" = "$(cd "$HOME" && pwd)" ]; then echo "REFUSE resolved tmp: it is the user home. Text guards miss dollar-variables and python cleanup.py."; fi

3. Off-Volume Profile & Data Backup

Back up Grok Bot profiles (.grokbot, .grok, AppData\Roaming\Grok Bot) off the OS volume:

PowerShell
$dest = "D:\Backups\llm-profiles\$(Get-Date -Format yyyyMMdd-HHmm)" New-Item -ItemType Directory -Force -Path $dest | Out-Null foreach ($d in @(".grokbot", ".grok", "AppData\Roaming\Grok Bot")) { if (Test-Path "$env:USERPROFILE\$d") { $leaf = Split-Path $d -Leaf robocopy "$env:USERPROFILE\$d" "$dest\$leaf" /E /NFL /NDL /NJH /NJS Write-Host "Backed up $dest\$leaf" } } Get-ChildItem $dest
zsh (macOS)
DEST="${BACKUP_ROOT:-$HOME/Backups}/llm-profiles/$(date +%Y%m%d-%H%M)" mkdir -p "$DEST" for d in .grokbot .grok; do if [ -d "$HOME/$d" ]; then rsync -a "$HOME/$d/" "$DEST/$d/"; echo "Backed up $DEST/$d"; fi done ls -la "$DEST"
bash (Linux)
DEST="${BACKUP_ROOT:-$HOME/Backups}/llm-profiles/$(date +%Y%m%d-%H%M)" mkdir -p "$DEST" for d in .grokbot .grok; do if [ -d "$HOME/$d" ]; then rsync -a "$HOME/$d/" "$DEST/$d/"; echo "Backed up $DEST/$d"; fi done ls -la "$DEST"

4. Practised Restore Drill

Never trust an unverified backup. Run this safe, self-contained restore drill inside your temp folder:

PowerShell
$drill = Join-Path $env:TEMP "bbb-restore-drill"; $src = Join-Path $drill "source"; $bak = Join-Path $drill "backup"; $back = Join-Path $drill "restored"; New-Item -ItemType Directory -Force -Path $src,$bak,$back | Out-Null; Set-Content -Encoding ascii -Path (Join-Path $src "proof.txt") -Value "bbb-restore-proof"; Copy-Item (Join-Path $src "proof.txt") (Join-Path $bak "proof.txt"); Remove-Item (Join-Path $src "proof.txt"); Copy-Item (Join-Path $bak "proof.txt") (Join-Path $back "proof.txt"); Get-Content (Join-Path $back "proof.txt"); Write-Host "Practised restore wrote proof into $back. Do not delete your user profile to test this."
zsh (macOS)
drill="${TMPDIR:-/tmp}/bbb-restore-drill"; src="$drill/source"; bak="$drill/backup"; back="$drill/restored"; mkdir -p "$src" "$bak" "$back"; printf "%s\n" "bbb-restore-proof" > "$src/proof.txt"; cp "$src/proof.txt" "$bak/proof.txt"; rm "$src/proof.txt"; cp "$bak/proof.txt" "$back/proof.txt"; cat "$back/proof.txt"; echo "Practised restore wrote proof into $back. Do not delete your home folder to test this."
bash (Linux)
drill="${TMPDIR:-/tmp}/bbb-restore-drill"; src="$drill/source"; bak="$drill/backup"; back="$drill/restored"; mkdir -p "$src" "$bak" "$back"; printf "%s\n" "bbb-restore-proof" > "$src/proof.txt"; cp "$src/proof.txt" "$bak/proof.txt"; rm "$src/proof.txt"; cp "$bak/proof.txt" "$back/proof.txt"; cat "$back/proof.txt"; echo "Practised restore wrote proof into $back. Do not delete your home folder to test this."

5. Fail-Closed Workspace Policy

Grok Bot runners must be configured with explicit working directories and safety hooks. BuildBotsBetter enforces the PreToolUse hook (protect_user_folders.py) to block recursive profile wipes. Fail-closed working directories and off-volume profile backups ensure complete resilience. Never run runner.py with a home-root cwd.

Checkpoint: Confirm Build Bot Better Protection Required

Paste terminal output from the restore drill or variable demo confirming protection: