BuildBotsBetter
SQL

Set Up SQL Server Express

Database Engine, sqlcmd CLI, BOTS Schema & Network Configuration

Progress
0%

Select Your Operating System

Instructions and database connection strings adjust dynamically for your shell.

Step 1 of 6 Est: 4 minutes

Install SQL Server Express Database Engine

Install Microsoft's lightweight relational database engine or launch the official container.

Install Database Service

Install the database engine on your system:

PowerShell
# Install SQL Server 2022 Express via winget PS > winget install Microsoft.SQLServer.2022.Express PS > Get-Service MSSQL$SQLEXPRESS
zsh
# Run official Microsoft SQL Server container on port 1433 (use --platform linux/amd64 on Apple Silicon) $ docker run --platform linux/amd64 -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=YourStrong@Password123" -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest $ docker ps --filter "name=sqlserver"
bash
# Run official Microsoft SQL Server container on port 1433 $ docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=YourStrong@Password123" -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest $ docker ps --filter "name=sqlserver"
Checkpoint 1
Required

Paste the service status showing MSSQL$SQLEXPRESS is Running (or Docker container status):

Step 2 of 6 Est: 2 minutes

Install sqlcmd Command-Line Utilities

Install Microsoft's command-line query utility to execute T-SQL statements directly from your terminal.

Install sqlcmd Package

Install the modern cross-platform sqlcmd utility:

PowerShell
PS > winget install Microsoft.SqlCmd PS > sqlcmd -?
zsh
$ brew install sqlcmd $ sqlcmd -?
bash
# Add Microsoft package repository for Ubuntu and install mssql-tools18 $ curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg $ curl -fsSL https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list $ sudo apt-get update && sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18 unixodbc-dev $ echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc $ sqlcmd -?
Checkpoint 2
Required

Paste the header line from sqlcmd -? to confirm utility availability:

Step 3 of 6 Est: 3 minutes

Connect & Test Server Health (@@VERSION)

Authenticate to your local instance and verify server version and encryption trust flags.

Query Server Version

Connect and query version information. Note the -C flag to trust self-signed development certificates:

PowerShell
PS > sqlcmd -S localhost\SQLEXPRESS -E -C -Q "SELECT @@VERSION;"
zsh
$ sqlcmd -S localhost -U sa -P 'YourStrong@Password123' -C -Q "SELECT @@VERSION;"
bash
$ sqlcmd -S localhost -U sa -P 'YourStrong@Password123' -C -Q "SELECT @@VERSION;"
💡
Why the -C flag? ODBC Driver 18 mandates encryption by default. For local development environments with self-signed SSL certificates, -C instructs the client to trust the server certificate and avoids Error 08001.
Checkpoint 3
Required

Paste the Microsoft SQL Server ... output from SELECT @@VERSION;:

Step 4 of 6 Est: 2 minutes

Create BOTS Database for Agent Coordination

Provision the dedicated database used by BuildBotsBetter multi-agent conversation hubs and tasks.

Create Database & Verify Catalog

Execute idempotent T-SQL commands to create the BOTS database:

PowerShell
PS > sqlcmd -S localhost\SQLEXPRESS -E -C -Q "IF NOT EXISTS(SELECT * FROM sys.databases WHERE name='BOTS') CREATE DATABASE BOTS; SELECT name FROM sys.databases WHERE name='BOTS';"
zsh
$ sqlcmd -S localhost -U sa -P 'YourStrong@Password123' -C -Q "IF NOT EXISTS(SELECT * FROM sys.databases WHERE name='BOTS') CREATE DATABASE BOTS; SELECT name FROM sys.databases WHERE name='BOTS';"
bash
$ sqlcmd -S localhost -U sa -P 'YourStrong@Password123' -C -Q "IF NOT EXISTS(SELECT * FROM sys.databases WHERE name='BOTS') CREATE DATABASE BOTS; SELECT name FROM sys.databases WHERE name='BOTS';"
Checkpoint 4
Required

Paste the query output confirming that the BOTS database exists:

Step 5 of 6 Est: 3 minutes

Configure Dedicated Bot User & Permissions

Create a least-privileged SQL Server login and map it to a user in the BOTS database.

Create Dedicated Bot Account

Create a bot login and assign reader/writer database roles:

PowerShell
PS > sqlcmd -S localhost\SQLEXPRESS -E -C -Q " IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'bot_user') CREATE LOGIN bot_user WITH PASSWORD = 'StrongBotPassword@2026'; USE BOTS; IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = 'bot_user') CREATE USER bot_user FOR LOGIN bot_user; ALTER ROLE db_datareader ADD MEMBER bot_user; ALTER ROLE db_datawriter ADD MEMBER bot_user; SELECT 'bot_user configured successfully' AS status; "
zsh
$ sqlcmd -S localhost -U sa -P 'YourStrong@Password123' -C -Q " IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'bot_user') CREATE LOGIN bot_user WITH PASSWORD = 'StrongBotPassword@2026'; USE BOTS; IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = 'bot_user') CREATE USER bot_user FOR LOGIN bot_user; ALTER ROLE db_datareader ADD MEMBER bot_user; ALTER ROLE db_datawriter ADD MEMBER bot_user; SELECT 'bot_user configured successfully' AS status; "
bash
$ sqlcmd -S localhost -U sa -P 'YourStrong@Password123' -C -Q " IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'bot_user') CREATE LOGIN bot_user WITH PASSWORD = 'StrongBotPassword@2026'; USE BOTS; IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = 'bot_user') CREATE USER bot_user FOR LOGIN bot_user; ALTER ROLE db_datareader ADD MEMBER bot_user; ALTER ROLE db_datawriter ADD MEMBER bot_user; SELECT 'bot_user configured successfully' AS status; "
Checkpoint 5
Required

Paste the confirmation output verifying bot user provisioning:

Step 6 of 6 Est: 2 minutes

Connection Strings & Operations Reference

Review standard connection strings for Python pyodbc and save the operations reference card.

Standard Application Connection String

Configure your Python scripts with ODBC Driver 18 encryption flags:

Python pyodbc string
conn_str = ( "DRIVER={ODBC Driver 18 for SQL Server};" "SERVER=localhost\\SQLEXPRESS;" "DATABASE=BOTS;" "UID=bot_user;" "PWD=StrongBotPassword@2026;" "TrustServerCertificate=yes;" )
Checkpoint 6
Required

Paste your connection string template or driver string below to confirm format:

⚡ Run It Later — SQL Operations Reference

Connect via sqlcmd sqlcmd -S localhost\SQLEXPRESS -E -C Connects using Windows Authentication with certificate trust
List Databases SELECT name FROM sys.databases; Inspects all active databases in instance catalog
Service Restart Restart-Service MSSQL$SQLEXPRESS Restarts SQL Server Express after networking configuration
ODBC 18 Flag TrustServerCertificate=yes; Required in client connection strings to avoid 08001 error
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 SQL Server databases to a dedicated backup volume using native SQL backup commands:

PowerShell
$dest = "D:\Backups\sql\$(Get-Date -Format yyyyMMdd)" if (!(Test-Path "D:\Backups\sql")) { New-Item -ItemType Directory -Force -Path "D:\Backups\sql" | Out-Null } New-Item -ItemType Directory -Force -Path $dest | Out-Null sqlcmd -S localhost\SQLEXPRESS -E -C -Q "BACKUP DATABASE [BOTS] TO DISK = N'$dest\BOTS.bak' WITH INIT, COMPRESSION" Get-ChildItem $dest
zsh (macOS)
DEST="${BACKUP_ROOT:-$HOME/Backups}/sql/$(date +%Y%m%d)" mkdir -p "$DEST" docker exec -i sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong@Password123" -C -Q "BACKUP DATABASE [BOTS] TO DISK = N'/var/opt/mssql/data/BOTS.bak' WITH INIT, COMPRESSION" docker cp sqlserver:/var/opt/mssql/data/BOTS.bak "$DEST/BOTS.bak" ls -la "$DEST"
bash (Linux)
DEST="${BACKUP_ROOT:-$HOME/Backups}/sql/$(date +%Y%m%d)" mkdir -p "$DEST" docker exec -i sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong@Password123" -C -Q "BACKUP DATABASE [BOTS] TO DISK = N'/var/opt/mssql/data/BOTS.bak' WITH INIT, COMPRESSION" docker cp sqlserver:/var/opt/mssql/data/BOTS.bak "$DEST/BOTS.bak" ls -la "$DEST"

4. Practised Restore Drill

Never trust an unverified backup. Run this safe, self-contained RESTORE verifyonly and scratch restore drill:

PowerShell
$dest = "D:\Backups\sql\$(Get-Date -Format yyyyMMdd)" sqlcmd -S localhost\SQLEXPRESS -E -C -Q "RESTORE verifyonly FROM DISK = N'$dest\BOTS.bak'" sqlcmd -S localhost\SQLEXPRESS -E -C -Q "RESTORE DATABASE [BOTS_SCRATCH] FROM DISK = N'$dest\BOTS.bak' WITH MOVE 'BOTS' TO '$env:TEMP\BOTS_SCRATCH.mdf', MOVE 'BOTS_log' TO '$env:TEMP\BOTS_SCRATCH_log.ldf', REPLACE; DROP DATABASE [BOTS_SCRATCH];" Write-Host "bbb-restore-proof: Database [BOTS] backup verified and restored to scratch successfully."
zsh (macOS)
DEST="${BACKUP_ROOT:-$HOME/Backups}/sql/$(date +%Y%m%d)" docker exec -i sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong@Password123" -C -Q "RESTORE verifyonly FROM DISK = N'/var/opt/mssql/data/BOTS.bak'" docker exec -i sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong@Password123" -C -Q "RESTORE DATABASE [BOTS_SCRATCH] FROM DISK = N'/var/opt/mssql/data/BOTS.bak' WITH MOVE 'BOTS' TO '/var/opt/mssql/data/BOTS_SCRATCH.mdf', MOVE 'BOTS_log' TO '/var/opt/mssql/data/BOTS_SCRATCH_log.ldf', REPLACE; DROP DATABASE [BOTS_SCRATCH];" echo "bbb-restore-proof: Database [BOTS] backup verified and restored to scratch successfully."
bash (Linux)
DEST="${BACKUP_ROOT:-$HOME/Backups}/sql/$(date +%Y%m%d)" docker exec -i sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong@Password123" -C -Q "RESTORE verifyonly FROM DISK = N'/var/opt/mssql/data/BOTS.bak'" docker exec -i sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong@Password123" -C -Q "RESTORE DATABASE [BOTS_SCRATCH] FROM DISK = N'/var/opt/mssql/data/BOTS.bak' WITH MOVE 'BOTS' TO '/var/opt/mssql/data/BOTS_SCRATCH.mdf', MOVE 'BOTS_log' TO '/var/opt/mssql/data/BOTS_SCRATCH_log.ldf', REPLACE; DROP DATABASE [BOTS_SCRATCH];" echo "bbb-restore-proof: Database [BOTS] backup verified and restored to scratch successfully."

5. Fail-Closed Workspace Policy

Always store SQL backups on a separate physical volume or drive. Never run automated database maintenance agents or data cleaning jobs from the user root folder.

Checkpoint: Confirm Build Bot Better Protection Required

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