| name | onboarding |
| description | Deploy your own Open-Inspect instance. Use when the user wants to set up, deploy, or onboard to Open-Inspect. Guides through repository setup, credential collection, Terraform deployment, and verification with user handoffs. |
| user-invocable | true |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion, TodoWrite |
Open-Inspect Deployment Guide
You are guiding the user through deploying their own instance of Open-Inspect. This is a multi-phase
process requiring user interaction for credential collection and external service configuration.
Before Starting
Use TodoWrite to create a checklist tracking these phases:
- Initial setup questions
- Repository setup
- Credential collection (Cloudflare, Vercel, Modal, Anthropic)
- GitHub App creation
- Slack App creation (if enabled)
- Security secrets generation
- Terraform configuration
- Terraform deployment (two phases)
- Post-deployment Slack setup (if enabled)
- Post-deployment GitHub Bot setup (if enabled)
- Web app deployment
- Verification
- CI/CD setup (optional)
Phase 1: Initial Questions
First, generate a random suffix suggestion for the user:
echo "Suggested deployment name: $(openssl rand -hex 3)"
Use AskUserQuestion to gather:
- Directory location - Where to create the project (default: current directory or
~/workplace/open-inspect-{suffix})
- GitHub account - Which account/org hosts the private repo
- Deployment name - A globally unique identifier for URLs (e.g., their GitHub username, company
name, or the random suffix generated above). Explain this creates URLs like
open-inspect-{deployment_name}.vercel.app and must be unique across all Vercel users.
- Slack integration - Yes or No
- GitHub bot integration - Yes or No (automated PR reviews and comment-triggered actions)
- Prerequisites confirmation - Confirm they have accounts on Cloudflare, Vercel, Modal,
Anthropic
Phase 2: Repository Setup
Execute these commands (substitute values from Phase 1):
mkdir -p {directory_path}
gh repo create {github_account}/open-inspect-{name} --private --description "Open-Inspect deployment"
cd {directory_path}
git clone git@github.com:ColeMurray/open-inspect.git .
git remote rename origin upstream
git remote add origin git@github.com:{github_account}/open-inspect-{name}.git
git push -u origin main
npm install
npm run build -w @open-inspect/shared
Phase 3: Credential Collection
Hand off to user for each service. Use AskUserQuestion to collect credentials.
Cloudflare
Tell the user:
- Account ID: Found in dashboard URL or account overview
- Workers Subdomain: Workers & Pages → Overview, bottom-right panel shows
*.YOUR-SUBDOMAIN.workers.dev
- API Token: Create at https://dash.cloudflare.com/profile/api-tokens with template "Edit
Cloudflare Workers" + permissions for Workers KV Storage (Edit), Workers R2 Storage (Edit), D1
(Edit)
R2 Bucket
Check wrangler login status, then create bucket:
wrangler whoami
wrangler r2 bucket create open-inspect-{name}-tf-state
Tell user to create R2 API Token at R2 → Overview → Manage R2 API Tokens with "Object Read & Write"
permission.
Vercel
Modal
Then set the token:
modal token set --token-id {token_id} --token-secret {token_secret}
modal profile current
Anthropic
Phase 4: GitHub App Setup
Guide user through creating a GitHub App (handles both OAuth and repo access):
- Go to https://github.com/settings/apps → "New GitHub App"
- Name:
Open-Inspect-{YourName} (globally unique)
- Homepage URL:
https://open-inspect-{deployment_name}.vercel.app
- Webhook: Uncheck "Active"
- Callback URL (under "Identifying and authorizing users"):
https://open-inspect-{deployment_name}.vercel.app/api/auth/callback/github
- CRITICAL: Must match deployed Vercel URL exactly!
- Repository permissions: Contents (Read & Write), Issues (Read & Write), Pull requests (Read &
Write), Metadata (Read-only)
- Create app, note App ID
- Generate Client Secret, note Client ID and Client Secret
- Generate Private Key (downloads .pem file)
- Install app on account, note Installation ID from URL
After receiving the .pem path, convert to PKCS#8:
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in {pem_path} -out /tmp/github-app-key-pkcs8.pem
cat /tmp/github-app-key-pkcs8.pem
Phase 5: Slack App Setup (If Enabled)
Guide user:
- https://api.slack.com/apps → "Create New App" → "From scratch"
- OAuth & Permissions → Add scopes:
app_mentions:read, chat:write, channels:history,
channels:read, groups:history, groups:read, im:history, im:read, reactions:write
- Install to Workspace, note Bot Token (
xoxb-...)
- Basic Information → note Signing Secret
- App Home and Event Subscriptions configured AFTER deployment (worker must be running for URL
verification)
Phase 6: Generate Security Secrets
echo "token_encryption_key: $(openssl rand -base64 32)"
echo "repo_secrets_encryption_key: $(openssl rand -base64 32)"
echo "internal_callback_secret: $(openssl rand -base64 32)"
echo "nextauth_secret: $(openssl rand -base64 32)"
echo "modal_api_secret: $(openssl rand -hex 32)"
echo "github_webhook_secret: $(openssl rand -hex 32)"
Phase 7: Terraform Configuration
Create terraform/environments/production/backend.tfvars:
access_key = "{r2_access_key}"
secret_key = "{r2_secret_key}"
bucket = "open-inspect-{name}-tf-state"
endpoints = {
s3 = "https://{cloudflare_account_id}.r2.cloudflarestorage.com"
}
Create terraform/environments/production/terraform.tfvars with all collected values. Set:
enable_durable_object_bindings = false
enable_service_bindings = false
If GitHub bot is enabled, also set:
enable_github_bot = true
github_webhook_secret = "{generated_value}"
github_bot_username = "{app-slug}[bot]"
Phase 8: Terraform Deployment (Two-Phase)
Important: Build the workers before running Terraform (Terraform references the built bundles):
npm run build -w @open-inspect/control-plane -w @open-inspect/slack-bot -w @open-inspect/github-bot
Phase 1 (bindings disabled):
cd terraform/environments/production
terraform init -backend-config=backend.tfvars
terraform apply
Phase 2 (after Phase 1 succeeds): Update tfvars to set both bindings to true, then:
terraform apply
Phase 9: Complete Slack Setup (If Enabled)
After Terraform deployment, guide user:
Enable App Home
- App Home → Show Tabs → Enable "Home Tab"
- Save Changes
The App Home provides a settings interface where users can configure their preferred Claude model.
Configure Event Subscriptions
- Event Subscriptions → Enable → Request URL:
https://open-inspect-slack-bot-{deployment_name}.{subdomain}.workers.dev/events
- Wait for "Verified" checkmark
- Subscribe to bot events:
app_home_opened, app_mention, message.im
Configure Interactivity
- Interactivity → Enable → Request URL:
https://open-inspect-slack-bot-{deployment_name}.{subdomain}.workers.dev/interactions
Invite Bot to Channels
- Invite bot to channels:
/invite @BotName
Phase 10: Complete GitHub Bot Setup (If Enabled)
After Terraform deployment, guide user:
Configure Webhook on GitHub App
- Go to GitHub App settings → your app
- Under Webhook: check "Active"
- Webhook URL:
https://open-inspect-github-bot-{deployment_name}.{subdomain}.workers.dev/webhooks/github
- Webhook secret: Enter the
github_webhook_secret value
- Under Subscribe to events, check: Pull requests, Issue comments, Pull request
review comments
- Save changes
Find Bot Username
The bot username is the App's slug with [bot] appended. E.g., if the app is My-Inspect-App, the
bot username is my-inspect-app[bot]. Confirm this matches github_bot_username in
terraform.tfvars.
Usage
- Code Review: Assign the bot as a PR reviewer
- Comment Actions: @mention the bot in a PR comment with instructions
Phase 11: Web App Deployment
npx vercel link --project open-inspect-{deployment_name}
npx vercel --prod
Phase 12: Verification
curl https://open-inspect-control-plane-{deployment_name}.{subdomain}.workers.dev/health
curl https://{workspace}--open-inspect-api-health.modal.run
curl -I https://open-inspect-{deployment_name}.vercel.app
Present deployment summary table. Instruct user to test: visit web app, sign in with GitHub, create
session, send prompt.
Phase 13: CI/CD Setup (Optional)
Ask if user wants GitHub Actions CI/CD. If yes, use gh secret set for all required secrets.
Error Handling
- "redirect_uri is not associated": Callback URL mismatch - update GitHub App settings
- Durable Object errors: Must follow two-phase deployment
- Slack bot not responding: Check Event Subscriptions URL verified, bot invited to channel,
reinstall if scopes changed
- GitHub bot not responding: Check webhook URL, secret,
enable_github_bot = true, and
github_bot_username matches the App's bot login
- Vercel build fails: Terraform configures the monorepo build commands automatically
- "no such file or directory" for dist/index.js: Build workers before Terraform:
npm run build -w @open-inspect/control-plane -w @open-inspect/slack-bot -w @open-inspect/github-bot
- Worker deployment fails: Build shared package first:
npm run build -w @open-inspect/shared
Important Notes
- Track all collected credentials securely throughout the process
- Never log sensitive values
- The callback URL MUST match the actual deployed Vercel URL
- Two-phase Terraform deployment is required due to Cloudflare Durable Object constraints