Skip to main content
stably fix is a headless command that automatically diagnoses test failures and applies AI-generated fixes. Designed for unattended execution, it’s ideal for self-healing CI pipelines, background maintenance agents, and automated test repair workflows.
# Auto-detects the last test run (local or CI)
stably fix

# With explicit run ID
stably fix <runId>
For interactive debugging, use the Interactive Agent instead. stably fix is optimized for automated, hands-off repair.
stably fix must run:
  • Inside a git repository/worktree — required so stably fix can track and apply changes
  • Usually from the same place you run stably test — for monorepos or non-standard layouts, use --cwd or --config
  • With authenticationSTABLY_API_KEY and STABLY_PROJECT_ID (via env vars or stably login)
  • With your test env vars — fix re-runs tests to validate fixes, so it needs the same variables (e.g., BASE_URL, test credentials). Use --env <name> to load a named environment from Stably.

How It Works

1

Run tests

Execute your test suite with stably test. The Stably Reporter captures failure context — screenshots, traces, DOM snapshots, and logs.
2

AI diagnoses each failure

stably fix analyzes the failure context to determine why each test failed and categorizes the issue.
3

Fixes are applied

The AI generates targeted code changes and applies them to your test files.
4

Review the results

View the diagnosis report and applied fixes. In CI, fixes can be committed and pushed automatically.

Run ID Detection

stably fix automatically detects which test run to fix using this fallback chain:
  1. Explicit argumentstably fix <runId>
  2. CI environment — detected from CI provider variables (GitHub Actions, Azure DevOps, Bitbucket, GitLab, CircleCI, Jenkins, and others via the env-ci library)
  3. Last local run — read from .stably/last-run.json (written automatically by stably test)
In most cases, just run stably test followed by stably fix — no run ID needed.
When tests fail, the Stably Reporter also prints a ready-to-copy stably fix <runId> command in the terminal output.
Using CLI with web portal tests: The CLI works with web portal projects — set STABLY_PROJECT_ID to the project ID from your dashboard. The CLI has access to all tests, run history, and environments for that project. You can fix cloud runs locally: copy the run ID from the dashboard, run stably fix <runId>.

Ad-Hoc Fixing

You don’t need CI to use stably fix. Run it from your terminal any time against any failed run:
# Fix failures from any run — local, CI, or cloud
stably fix <runId>
  • Works with any run ID: local runs, CI runs, or cloud runs
  • Fixes are applied to your working tree — review with git diff, commit when satisfied
  • Useful for debugging specific failures or testing autofix before wiring into CI
  • The fix report is also uploaded to the Stably dashboard for monitoring

Environment Files and Secrets

stably fix does not read, edit, or search .env files (including .env.local, .env.production, and other .env* variants).
  • Use --env <name> to load a named environment from Stably.
  • Use --env-file <path> when you explicitly want to provide local environment variables at command startup.
  • If a failure is caused by missing or invalid environment configuration, the fix agent reports which variables are required instead of modifying secret files.

Diagnosis Categories

Each failure is categorized to help you understand at a glance whether it needs attention or has already been addressed:
CategoryWhat it means
Test OutdatedThe test references selectors or flows that have changed in your app
Actual BugThe test caught a real bug in your application
UnstableThe test fails intermittently due to timing or race conditions
UI ChangeThe UI changed intentionally and the test needs to reflect the new design
MiscellaneousOther issues that don’t fit the categories above

Monitoring Fix Sessions

When stably fix runs, it automatically creates an automation — a real-time view of the agent’s progress visible on the Stably web dashboard. This is especially useful in CI pipelines, Docker containers, and other non-interactive environments where you can’t see the terminal.
Stably fix automation showing real-time agent progress on the web dashboard
From the dashboard you can:
  • Watch progress live — see the current phase, activity log, and files being fixed
  • Send messages to the agent — provide guidance or corrections while the agent works, even in CI
  • View the final report — when complete, the automation shows a summary with links to the autoheal report
Fix automations track these phases: initializingtriagefixingvalidationcomplete
Automation creation is best-effort and non-blocking. If the connection fails, the CLI continues normally — your commands are never interrupted.
$ stably fix run_abc123

Analyzing 3 failures...

checkout.spec.ts > complete purchase
  Issue: Selector '.checkout-button' not found
  Fix: Updated to '[data-testid="checkout-btn"]'
 Fixed

login.spec.ts > invalid credentials
  Issue: Error message assertion failed
  Fix: Updated expected text to match new design
 Fixed

Summary: 2 auto-fixed, 1 requires manual review

CI Integration

stably fix applies changes to local files on the CI runner. CI runners are ephemeral — the file changes are lost when the job ends. However, results are always uploaded to the Stably dashboard, so you can review diffs and create a PR from there (if your repo is connected) without any extra CI steps.If you prefer to commit directly from CI, add git commit/push/PR steps to your workflow (shown in the examples below).
Run fix once, not per shard. stably fix must run on a single machine after all test shards complete. It groups failures by root cause — running per-shard misses cross-test patterns and may cause conflicts.

Simple Pipeline (no matrix)

The recommended pattern runs tests in a parallel matrix and uses a separate fix job that triggers only when tests fail. This ensures stably fix runs once after all test results are collected.
# .github/workflows/self-healing-tests.yml
name: Self-Healing Tests

on:
  push:
    branches:
      - main
  schedule:
    - cron: '0 */3 * * *'
  workflow_dispatch:

env:
  CI_BUILD_ID: stably-${{ github.run_id }}-${{ github.run_attempt }}

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 120
    strategy:
      fail-fast: false
      matrix:
        project:
          - 'e2e:smoke'
          - 'e2e:checkout'
          - 'e2e:login'
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install chromium --with-deps

      - name: Run Stably tests
        env:
          STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }}
          STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }}
          BASE_URL: ${{ vars.BASE_URL }}
        run: npx stably test --project=${{ matrix.project }}

  fix:
    needs: test
    if: always() && needs.test.result == 'failure'
    runs-on: ubuntu-latest
    timeout-minutes: 120
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install chromium --with-deps

      - name: Run Stably Fix
        env:
          STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }}
          STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }}
          # Same env vars your tests need:
          BASE_URL: ${{ vars.BASE_URL }}
        run: npx stably fix

      # Option 1: Open a PR with the fixes (recommended)
      - name: Create fix PR
        if: steps.test.outcome == 'failure'
        run: |
          git config user.name "stably-bot"
          git config user.email "bot@stably.ai"
          branch="stably-fix/$(date +%Y%m%d-%H%M%S)"
          git checkout -b "$branch"
          git add tests/
          git commit -m "fix: auto-repair failing tests" || exit 0
          git push origin "$branch"
          gh pr create --title "fix: auto-repair failing tests" \
            --body "Automated test fixes from Stably" --head "$branch"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # Option 2: Push fixes directly to the branch instead
      # - name: Commit fixes
      #   if: steps.test.outcome == 'failure'
      #   run: |
      #     git config user.name "stably-bot"
      #     git config user.email "bot@stably.ai"
      #     git add tests/
      #     git commit -m "fix: auto-repair failing tests" || exit 0
      #     git push
The fix report is also visible on the Stably dashboard regardless of whether you commit/push — results are always uploaded.

Matrix Pipeline (sharded tests)

When using test sharding, run stably fix in a separate job that waits for all shards to complete:
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci && npx stably install

      - name: Run tests
        env:
          STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }}
          STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }}
          BASE_URL: ${{ vars.BASE_URL }}
        run: npx stably test --shard=${{ matrix.shard }}/${{ strategy.job-total }}

  fix:
    needs: test
    if: always() && needs.test.result == 'failure'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci && npx stably install

      - name: Auto-fix failures
        env:
          STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }}
          STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }}
          # Same env vars your tests need:
          BASE_URL: ${{ vars.BASE_URL }}
        run: npx stably fix

      - name: Create fix PR
        run: |
          git config user.name "stably-bot"
          git config user.email "bot@stably.ai"
          branch="stably-fix/$(date +%Y%m%d-%H%M%S)"
          git checkout -b "$branch"
          git add tests/
          git commit -m "fix: auto-repair failing tests" || exit 0
          git push origin "$branch"
          gh pr create --title "fix: auto-repair failing tests" \
            --body "Automated test fixes from Stably" --head "$branch"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The fix job uses if: always() && needs.test.result == 'failure' because GitHub Actions skips dependent jobs when needs fail unless always() is used.

Background Agent Integration

# Called by AI coding agents for autonomous test maintenance
# Chain test execution with automatic repair

stably test || stably fix

# Full pipeline: test → fix → verify
stably test || (stably fix && stably test)

Autofix on Scheduled Runs

When running tests on Stably Cloud Runner, you can enable autofix to run automatically after each scheduled run — no CLI invocation needed.

Enabling Autofix

From the Dashboard: When creating or editing a scheduled test run, toggle “Auto-fix failing tests”. In stably.yaml: Add autofix: true to any schedule definition:
stably.yaml
schedules:
  nightly-regression:
    cron: "0 2 * * *"
    stablyTestArgs: "--project regression"
    autofix: true
You can enable autofix on some schedules and leave it off on others — it’s configured per schedule.

Viewing Results

After autofix completes, results appear in your test runs table under the “Diagnosis & Fix” column:
  • In Progress — autofix is still running
  • Diagnosed — analysis is complete, with issue counts by category
  • Review fix — click to see the full report and code changes
  • No fix available — the issue was identified but couldn’t be automatically repaired
Click “Review fix” to open the detailed report, which includes:
  • Each failing test with its diagnosis
  • The code changes that were applied
  • A link to the generated pull request (if your repo is connected to GitHub)

Configuration

Fine-tune how the fix agent behaves using the agent.fix section in stably.yaml:
stably.yaml
agent:
  fix:
    maxBudgetUsd: 100                  # Override default $50 limit
    maxTurnsPerIssue: 30               # Max turns per issue (default: 50)
    maxParallelWorkers: 3              # Max concurrent agents for fixing issues (default: 2)
    skipAfterConsecutiveUnfixed: 3     # Skip tests unfixed 3+ consecutive runs
    rules: |                           # Custom instructions for the fix agent
      Prefer data-testid selectors over CSS selectors.
      Always add comments explaining selector changes.
OptionTypeDescription
maxBudgetUsdnumberMaximum spend in USD per fix session (default: 50)
maxTurnsPerIssuenumberMaximum AI turns per issue (default: 50)
maxParallelWorkersnumberNumber of issues to fix in parallel (default: 2)
skipAfterConsecutiveUnfixednumberSkip tests that have failed to fix this many times in a row — saves AI costs on persistently broken tests
rulesstringCustom instructions appended to the agent’s system prompt (e.g., selector preferences, coding conventions). Use YAML `` for multi-line rules

Next Steps

Run Tests

Run tests locally or in CI with stably test

Test Reporter

Stream test results and traces to Stably

Scheduled Runs

Configure when your tests run automatically

Alerting

Get notified about test failures and fixes