Background Agent and CI Setup
This feature is in beta. We are actively developing background agent and CI support. If you’d like to get started using Ranger with a background agent, reach out to us and we’ll help you set it up.
This guide covers running Ranger in hosted environments, including background agents running on isolated VMs, and CI workflows (GitHub Actions, GitLab CI, etc.). The same steps apply regardless of the platform - anywhere you can run Node.js and a headless browser.
Ranger works with any coding agent that can execute bash commands — Claude Code, OpenCode, Codex, or any other agent with shell access.
A Note on Auth
Section titled “A Note on Auth”The challenge for running in non-tty environments is authentication. The verification usually needs to happen in a logged-in context, which is where human intervention usually comes into play. We have two approaches to make this work.
One-Time CI Profile Creation
Section titled “One-Time CI Profile Creation”The first option is to manually login to the app once, save the session state, and encrypt it so that it can be committed and used in different environments.
This works well in situations where sessions are long-lived or a bot bypassing auth is not possible.
Login Instructions
Section titled “Login Instructions”The second option is to give Ranger “login instructions” that it can use to construct its own auth state. This is a very flexible and open-ended option but may take more customization to set up.
Some options that users have configured with login instructions include using a username and password or hitting a specific endpoint to obtain a token to include in an auth header. The options here are fairly unlimited
Overview
Section titled “Overview”The setup has two parts: a one-time local setup (creating a CI profile and committing it), and the hosted environment itself (installing tools, activating the profile, and running your coding agent with Ranger).
Option A: One-Time CI Profile Creation (configure locally)
Section titled “Option A: One-Time CI Profile Creation (configure locally)”1. Create a CI profile
Section titled “1. Create a CI profile”Run this on your local machine, from your project root. Here we name the profile preview - you can use any name, but the rest of this guide assumes preview.
ranger profile add preview --ciThis will open a browser pointed at your app’s URL. Log in to the environment that the hosted agent will verify against (e.g. your staging or preview deployment). The browser session cookies are captured and encrypted — these are the exact cookies Ranger will use to authenticate in the hosted environment, so they must be valid for the target URL.
The encrypted auth state is saved to .ranger/ci/preview/:
.ranger/ci/preview/ settings.json # baseUrl and browser config auth.json.enc # encrypted auth state (safe to commit)Dynamic base URLs
Section titled “Dynamic base URLs”If your deployment URL changes per environment (e.g. Vercel preview URLs, Heroku review apps), you can use ${VAR_NAME} syntax in your profile’s baseUrl. Ranger resolves environment variables at runtime.
When running ranger profile add preview --ci, enter the URL of a representative deployment (e.g. your current staging URL). This is needed so you can log in and capture valid auth cookies. After the profile is created, update the baseUrl to use a variable:
Note: The cookies captured during login must be valid for all target deployments. If your staging and preview environments use different auth providers or cookie domains, the captured cookies won’t work across them.
ranger profile config set preview baseUrl '${PREVIEW_URL}'The auth cookies captured during setup will still be used — only the URL changes at runtime. This works as long as the cookies are valid across deployments (e.g. same domain, shared auth provider).
At runtime, Ranger replaces ${PREVIEW_URL} with the value of that environment variable:
export PREVIEW_URL=https://my-app-pr-123.vercel.appThis works for any settings value, not just baseUrl. For example, you can use env vars in custom headers:
ranger profile config set preview header.Authorization '${AUTH_TOKEN}'2. Commit the profile to version control
Section titled “2. Commit the profile to version control”git add .ranger/ci/git commit -m "Add Ranger CI profile"If you use encrypted auth, auth.json.enc can only be decrypted at runtime using your Ranger API token, so it’s safe to store in git.
Option B: loginInstructions (no saved session)
Section titled “Option B: loginInstructions (no saved session)”If your app uses short-lived cookies/tokens or a custom auth bootstrap endpoint, configure loginInstructions instead of relying on a long-lived encrypted browser session.
Create the CI profile without capturing login state:
ranger profile add preview --skip-authThen set login instructions that Ranger will run before every verification:
ranger profile config set preview loginInstructions 'Navigate to ${PREVIEW_URL}/api/debug-auth?email=${TEST_USER_EMAIL} to obtain a session token.'loginInstructions supports environment variables and works with any auth mechanism (debug endpoints, token injection, API-key bootstrap, etc.).
2. Make secrets available to the environment
Section titled “2. Make secrets available to the environment”Your environment needs this secret:
| Secret | Description |
|---|---|
RANGER_CLI_TOKEN | Your Ranger API token (rngr_...). Used for CLI auth and decrypting the encrypted auth state. |
You’ll also need an API key for whatever coding agent you use (e.g. ANTHROPIC_API_KEY for Claude Code). If your loginInstructions references environment variables, provide those as well. How you provide these depends on your platform - GitHub repo secrets, GitLab CI variables, environment variables in a VM, etc.
Environment Setup Steps
Section titled “Environment Setup Steps”These are the steps your environment needs to run, in order. The commands below are plain bash — adapt them to your platform’s syntax.
1. Check out the repository
Section titled “1. Check out the repository”Clone with full git history (needed if you want to generate diffs):
git clone --depth=0 <repo>2. Install Node.js
Section titled “2. Install Node.js”Ranger CLI requires Node.js 20+.
3. Install project dependencies
Section titled “3. Install project dependencies”npm install4. Install a virtual display (Linux only)
Section titled “4. Install a virtual display (Linux only)”Ranger runs a headless Chromium browser. On Linux environments without a display server, you need Xvfb:
apt-get install -y xvfbXvfb :99 -screen 0 1920x1080x24 &export DISPLAY=:99Not needed on macOS or environments with a display server.
5. Install your coding agent and Ranger CLI
Section titled “5. Install your coding agent and Ranger CLI”Install Ranger CLI globally, along with whatever coding agent you’re using:
npm install -g @ranger-testing/ranger-cli
# Plus your coding agent, e.g.:npm install -g @anthropic-ai/claude-code6. Authenticate and install Chromium
Section titled “6. Authenticate and install Chromium”Pass your Ranger API token to the setup command. In non-interactive mode, this authenticates and installs the Playwright Chromium browser:
export RANGER_CLI_TOKEN=<your-token>ranger setup $RANGER_CLI_TOKEN7. Activate the CI profile
Section titled “7. Activate the CI profile”Tell Ranger to use the CI profile you committed in the one-time setup:
ranger profile use previewIf the profile includes auth.json.enc, Ranger decrypts it at runtime using RANGER_CLI_TOKEN. If the profile uses loginInstructions, Ranger follows those instructions before each verification run.
8. Install Ranger skills
Section titled “8. Install Ranger skills”Install the Ranger skill files that teach your coding agent how to create feature reviews and run verifications:
ranger skillupThis places skill markdown files in .claude/skills/ (compatible with any agent that reads skill files from the project directory).
9. Configure your coding agent’s permissions
Section titled “9. Configure your coding agent’s permissions”Your coding agent needs permission to run bash commands (for ranger, gh, git, etc.) and read files. How you configure this depends on your agent.
Claude Code example — write .claude/settings.local.json:
{ "permissions": { "allow": ["Bash(*)", "Read(*)", "Glob(*)", "Grep(*)"], "deny": [] }}Other agents may need equivalent configuration, or may not require it at all.
10. Run your coding agent with Ranger
Section titled “10. Run your coding agent with Ranger”Invoke your coding agent in non-interactive mode with a prompt that tells it to use the Ranger skill. The skill files teach the agent how to create feature reviews, write scenarios, and run browser verification.
Here are two possible use cases:
CI workflow: Bug bash a PR’s changes
Section titled “CI workflow: Bug bash a PR’s changes”Trigger on every pull request. The agent reads the diff, creates scenarios based on what changed, and verifies them in the browser. Results get posted as a PR comment.
claude --print "Look at the git diff for this branch against main. \ Use the /ranger skill to create a feature review from the UI changes \ and verify each scenario. Post results as a PR comment using gh."Background agent: Build and verify a feature
Section titled “Background agent: Build and verify a feature”Give a coding agent a feature task and let it implement the code, then verify its own work in the browser before reporting back.
claude --print "Read the task requirements and document a plan in docs/feature/{feature-name}.md. \ Implement the feature in the codebase, referencing the original task for context. \ Commit changes and push to the current branch. \ Use the Ranger skill to authenticate against the current environment and verify the feature works end-to-end in the browser."Updating the Encrypted Profile
Section titled “Updating the Encrypted Profile”When your app’s auth expires or login flow changes, update the profile locally:
ranger profile update previewThen commit the updated .ranger/ci/preview/auth.json.enc.
If you use loginInstructions, update the instruction text instead:
ranger profile config set preview loginInstructions "<updated instructions>"Limitations
Section titled “Limitations”- Encrypted auth state doesn’t auto-refresh. The encrypted
auth.json.encis a snapshot of browser cookies/session from when you ranranger profile add. If your app’s sessions expire, you’ll need to re-runranger profile update previewlocally and commit the updated file, or switch tologinInstructions. loginInstructionsmust stay valid. If the bootstrap endpoint, login flow, or required env vars change, updateloginInstructionsin the profile settings.- One profile per environment. Each CI profile is tied to a single base URL and auth config. If you need to verify against multiple environments (e.g. staging and production), create separate profiles (
ranger profile add staging --ci,ranger profile add production --ci).
Troubleshooting
Section titled “Troubleshooting””No CI profiles found”
Section titled “”No CI profiles found””Make sure .ranger/ci/preview/ is committed to git with both settings.json and auth.json.enc.
”Failed to verify encrypted auth”
Section titled “”Failed to verify encrypted auth””The RANGER_CLI_TOKEN must belong to the same organization as the token used when the profile was created.
Coding agent blocks commands
Section titled “Coding agent blocks commands”Some agents sandbox tool calls by default. Make sure your agent has permission to run bash commands before invoking it. For Claude Code, this means writing .claude/settings.local.json (see step 9).
Browser fails to launch
Section titled “Browser fails to launch”On Linux, make sure Xvfb is running and DISPLAY is set before the agent starts. Chromium needs a display server even in headless mode on some configurations.
Vercel preview environments return 401/403
Section titled “Vercel preview environments return 401/403”Vercel’s Deployment Protection blocks automated access to preview URLs by default. To bypass it, generate a protection bypass token in your Vercel project settings and add it as a custom header on the profile:
ranger profile config set preview header.x-vercel-protection-bypass '<your-bypass-token>'See Vercel’s bypass automation docs for how to generate the token.
Example: GitHub Actions Workflow
Section titled “Example: GitHub Actions Workflow”A complete workflow using Claude Code. Copy to .github/workflows/ranger-pr-verify.yaml.
Required secrets (Settings > Secrets and variables > Actions):
RANGER_CLI_TOKEN— Your Ranger API tokenANTHROPIC_API_KEY— Anthropic API key for Claude Code
name: Ranger PR Verification
on: pull_request: types: [opened, synchronize, reopened] workflow_dispatch: inputs: pr_number: description: 'PR number to verify (optional, uses current branch if empty)' required: false type: string
env: HUSKY: 0
jobs: verify: name: Ranger PR Verification runs-on: ubuntu-latest permissions: contents: read pull-requests: write
steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20'
- name: Install dependencies run: npm install
- name: Install system dependencies run: | sudo apt-get update sudo apt-get install -y xvfb
- name: Install Claude Code and Ranger CLI run: npm install -g @anthropic-ai/claude-code @ranger-testing/ranger-cli
- name: Setup Ranger CLI env: RANGER_CLI_TOKEN: ${{ secrets.RANGER_CLI_TOKEN }} run: ranger setup ${{ secrets.RANGER_CLI_TOKEN }}
- name: Activate CI profile run: ranger profile use preview
- name: Install Ranger skills env: RANGER_CLI_TOKEN: ${{ secrets.RANGER_CLI_TOKEN }} run: ranger skillup
- name: Configure Claude Code permissions run: | mkdir -p .claude cat > .claude/settings.local.json << 'EOF' { "permissions": { "allow": [ "Bash(*)", "Read(*)", "Glob(*)", "Grep(*)" ], "deny": [] } } EOF
- name: Run Ranger verification env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} RANGER_CLI_TOKEN: ${{ secrets.RANGER_CLI_TOKEN }} DISPLAY: ':99' GH_TOKEN: ${{ github.token }} run: | Xvfb :99 -screen 0 1920x1080x24 & export DISPLAY=:99 sleep 2
claude --print "Look at the git diff for this branch against main. Use the /ranger skill to create a feature review from the changes and verify each scenario. Post results as a PR comment using gh." timeout-minutes: 30