> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stably.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Fix Tests (stably fix)

> Automatically diagnose and fix failing Playwright tests with AI — locally, in CI, or on a schedule

`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.

```bash theme={null}
# Auto-detects the last test run (local or CI)
stably fix

# With explicit run ID
stably fix <runId>
```

<Note>
  For interactive debugging, use the [Interactive Agent](/stably-cli/commands#interactive-agent) instead. `stably fix` is optimized for automated, hands-off repair.
</Note>

<Warning>
  `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 authentication** — `STABLY_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.
</Warning>

## How It Works

<Steps>
  <Step title="Run tests">
    Execute your test suite with `stably test`. The [Stably Reporter](/stably/stably-test-reporter) captures failure context — screenshots, traces, DOM snapshots, and logs.
  </Step>

  <Step title="AI diagnoses each failure">
    `stably fix` analyzes the failure context to determine *why* each test failed and categorizes the issue.
  </Step>

  <Step title="Fixes are applied">
    The AI generates targeted code changes and applies them to your test files.
  </Step>

  <Step title="Review the results">
    View the diagnosis report and applied fixes. In CI, fixes can be committed and pushed automatically.
  </Step>
</Steps>

## Run ID Detection

`stably fix` automatically detects which test run to fix using this fallback chain:

1. **Explicit argument** — `stably fix <runId>`
2. **CI environment** — detected from CI provider variables (GitHub Actions, Azure DevOps, Bitbucket, GitLab, CircleCI, Jenkins, and others via the [`env-ci`](https://github.com/semantic-release/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.

<Tip>
  When tests fail, the [Stably Reporter](/stably/stably-test-reporter) also prints a ready-to-copy `stably fix <runId>` command in the terminal output.
</Tip>

<Info>
  **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>`.
</Info>

## Ad-Hoc Fixing

You don't need CI to use `stably fix`. Run it from your terminal any time against any failed run:

```bash theme={null}
# 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

## Cloud Browser Mode

`stably fix` can run its browser interactions in a Stably-hosted browser:

```bash theme={null}
stably fix --browser=cloud
stably fix <runId> --browser=cloud
```

This is especially useful when:

* your CI runner is minimal and you do not want local browser setup for the fix agent
* a coding agent is running `stably fix` in a container or remote sandbox
* you want the CLI workflow but prefer remote browser execution

Cloud browser mode only changes the browser session used by the agent. The code edits still happen in your local checkout, and `stably fix` still requires a git repository.

<Tip>
  You can make this the default for a shell session or CI job with `STABLY_CLOUD_BROWSER=1`. See [Cloud Browsers for Stably CLI](/stably-cli/cloud-browser).
</Tip>

## 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:

| Category          | What it means                                                             |
| ----------------- | ------------------------------------------------------------------------- |
| **Test Outdated** | The test references selectors or flows that have changed in your app      |
| **Actual Bug**    | The test caught a real bug in your application                            |
| **Unstable**      | The test fails intermittently due to timing or race conditions            |
| **UI Change**     | The UI changed intentionally and the test needs to reflect the new design |
| **Miscellaneous** | Other 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.

<Frame>
  <img src="https://mintcdn.com/stablyai/wqPlyaSGU9yEGzbi/images/stably-fix-automation.png?fit=max&auto=format&n=wqPlyaSGU9yEGzbi&q=85&s=843a986203ebadee67102363e6d4c8f0" alt="Stably fix automation showing real-time agent progress on the web dashboard" width="1897" height="1012" data-path="images/stably-fix-automation.png" />
</Frame>

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: `initializing` → `triage` → `fixing` → `validation` → `complete`

<Info>
  Automation creation is best-effort and non-blocking. If the connection fails, the CLI continues normally — your commands are never interrupted.
</Info>

<Accordion title="Example Output">
  ```bash theme={null}
  $ 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
  ```
</Accordion>

## CI Integration

<Note>
  `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](/stably2/bring-your-own-repo)) 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).
</Note>

<Warning>
  **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.
</Warning>

### 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.

```yaml theme={null}
# .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
```

<Note>
  The fix report is also visible on the Stably dashboard regardless of whether you commit/push — results are always uploaded.
</Note>

### Matrix Pipeline (sharded tests)

When using test sharding, run `stably fix` in a **separate job** that waits for all shards to complete:

```yaml theme={null}
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 }}
```

<Info>
  The `fix` job uses `if: always() && needs.test.result == 'failure'` because GitHub Actions skips dependent jobs when `needs` fail unless `always()` is used.
</Info>

### Background Agent Integration

```bash theme={null}
# 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](/run-tests/run-tests-on-cloud), 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:

```yaml stably.yaml theme={null}
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 — including budget caps, turn limits, and smart skip rules — using the `agent.fix` section in [`stably.yaml`](/core-configuration/stably-md):

```yaml stably.yaml theme={null}
agent:
  fix:
    maxBudgetUsd: 30                   # Cap spending per fix session
    maxTurnsPerIssue: 20               # Move on if a test can't be fixed quickly
    skipAfterConsecutiveUnfixed: 1     # Don't retry persistently broken tests
```

<Tip>
  See [Autofix Cost Controls](/core-configuration/autofix-cost-controls) for the full reference — all options, defaults, recommended settings by use case, and strategies for preventing runaway costs.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Run Tests" icon="play" href="/stably-cli/run-tests">
    Run tests locally or in CI with `stably test`
  </Card>

  <Card title="Test Reporter" icon="chart-line" href="/stably/stably-test-reporter">
    Stream test results and traces to Stably
  </Card>

  <Card title="Scheduled Runs" icon="clock" href="/run-tests/scheduled-runs">
    Configure when your tests run automatically
  </Card>

  <Card title="Alerting" icon="bell" href="/run-tests/alerting">
    Get notified about test failures and fixes
  </Card>
</CardGroup>
