Skip to main content

Overview

stably build turns a prompt file into a Playwright test file with a deterministic, compiler-style workflow.
stably build <input.prompt.md> -o <output.spec.ts>
This is the best fit when you want to keep test intent in source control as markdown, then compile it into executable tests.

Workflow

.prompt.md (source of truth) -> stably build -> .spec.ts -> stably test -> stably fix

When to Use build vs create

CommandBest forInput style
stably create [prompt]One-shot generation and automation from PR/git contextCLI prompt (or no prompt)
stably build <input> -o <output>Repeatable compilation from version-controlled specs.prompt.md file
Use stably create when you want fast generation directly from a prompt or diff context. Use stably build when prompt files are part of your repo and you want predictable rebuild behavior.

Command Reference

stably build <input> -o <output> [options]
Argument/OptionRequiredDescription
<input>YesPrompt file path. Must end with .prompt.md
-o, --output <file>YesOutput .spec.ts file path
--no-cacheNoForce regeneration even if prompt hash is unchanged
-h, --helpNoShow command help

Output Path Behavior

  • If -o points to a file, that file is generated/updated.
  • If -o points to a directory, Stably uses <prompt-name>.spec.ts in that directory.
Example:
stably build prompts/login.prompt.md -o tests/
# -> tests/login.spec.ts

Prompt File Format

Prompt files should describe behavior in business language, not implementation details.
# Login Flow Tests

## Test: Successful login
User navigates to the login page.
User enters valid credentials and submits.
System redirects user to the dashboard.
System shows a personalized welcome message.

## Test: Invalid credentials
User navigates to the login page.
User enters invalid credentials and submits.
System shows an invalid credentials error.
User remains on the login page.

Authoring Guidelines

  • Keep each file self-contained.
  • Focus on user-visible behavior and outcomes.
  • Avoid hardcoding selectors in the prompt.
  • Avoid embedding brittle implementation details unless required.

SDK-Aware Compilation

stably build generates Playwright code with Stably SDK patterns so tests stay resilient as UI changes.
ScenarioTypical SDK methodReference
Stable element targetingaiLocator(...)/stably-sdk/ai-locator
Natural-language visual validationtoMatchScreenshotPrompt(...)/stably-sdk/ai-assertions
Multi-step agent actionsagent.act(...)/stably-sdk/ai-agent-execute

Caching and Build Headers

stably build uses prompt-content hashing to skip unnecessary regeneration. If the existing output contains a matching @prompt-hash, build is skipped.
/**
 * @generated by stably build
 * @prompt-hash sha256:...
 * @prompt-file prompts/login.prompt.md
 * @built-at 2026-02-06T10:30:00.000Z
 */
To force a rebuild:
stably build prompts/login.prompt.md -o tests/login.spec.ts --no-cache

End-to-End Example

1

Create a prompt file

mkdir -p prompts tests
cat > prompts/checkout.prompt.md << 'EOF'
# Checkout tests

## Test: Guest checkout
User adds one item to cart.
User proceeds to checkout.
User completes payment with a valid card.
System confirms the order.
EOF
2

Compile prompt to Playwright test

stably build prompts/checkout.prompt.md -o tests/checkout.spec.ts
Expected output:
Built: tests/checkout.spec.ts
3

Re-run build without changes

stably build prompts/checkout.prompt.md -o tests/checkout.spec.ts
Expected output:
Skipped build: test code is up to date (hash unchanged)
4

Run and fix tests

stably test tests/checkout.spec.ts
stably fix

CI Pattern

# .github/workflows/build-and-test.yml
name: Build and Test Specs

on:
  pull_request:
  push:
    branches: [main]

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npx stably install
      - run: npx stably build prompts/checkout.prompt.md -o tests/checkout.spec.ts
      - run: npx stably test
        env:
          STABLY_API_KEY: ${{ secrets.STABLY_API_KEY }}
          STABLY_PROJECT_ID: ${{ secrets.STABLY_PROJECT_ID }}

Next Steps