Your first run
Recording
npx saffron run # everything under features/
npx saffron run features/login.feature # one file
npx saffron run --filter @smoke # by tag
npx saffron run --filter @TC-1,@TC-2 # any of several tags (or repeat --filter)
npx saffron run --headed # watch the browser
If your project already has caches, steps whose exact text matches an
existing recording are seeded: the leading run of known steps replays
zero-AI and the agent records only the novel ones (⚡ 4/6 steps seeded).
The more scenarios you record, the cheaper each new one gets, write
shared steps with identical wording (and the page in the step text, e.g.
"…on the guest information page") to maximize hits. Quoted values may
differ (I enter "admin"… seeds from I enter "bob"…), data-table
steps seed whenever their table keys match, and novel steps can sit
anywhere in the scenario: seeded steps before, between, and after them
all replay free.
No cache exists yet, so the agent executes each scenario in a real browser. Expect real token spend per scenario (typically $0.15–$2.00 depending on length and seeding: the report shows exact numbers, including cache traffic: prompt-cache reads/writes are the dominant cost of agent sessions, and the CLI and report break them out so the small "in+out tokens" figure is never mistaken for the bill). Scenarios finish yellow with a cache proposal each, or red if an assertion genuinely doesn't hold.
Try it on the example suite
If saffron init installed the Saucedemo examples, this is the whole
first run, credentials included (they are the public demo ones):
cp .env.example .env # SAUCE_USER / SAUCE_PASSWORD, resolved at replay only
npx playwright install chromium
npx saffron run --filter @smoke # records "Successful login" and "Add a product to the cart"
Both scenarios come back yellow with verified ✓ proposals (the agent
recorded them, then a zero-AI proof replay confirmed the recordings).
Measured on the real site: 35 AI calls and about $3 of AI usage for the
two, most of it prompt-cache traffic, which the report breaks out
honestly. Open the narratives, then:
npx saffron accept --all
npx saffron run --filter @smoke # green, 0 AI calls, 0 tokens
Now run everything: npx saffron run (a few dollars more: the remaining
scenarios seed most of their steps from what is already recorded). The
login-errors Scenario Outline records once and replays both example rows;
"Recover from a locked-out login" invokes the login StepSet in the middle
of the scenario; the checkout invokes a second set mid-scenario that
carries a data table, recorded as <table:firstName> references. Every
set comes from shared.steps.saffron, so later callers record mostly
seeded. Delete a cache and run again to watch a re-record; edit a table
value and watch it replay free.
Review and accept proposals
npx saffron diff # what the proposals would change, action by action
npx saffron accept # no args: list pending proposals with narratives
npx saffron accept --all # promote every VERIFIED proposal; UNVERIFIED ones are skipped
npx saffron accept --all --include-unverified # promote UNVERIFIED ones too (deliberately)
npx saffron accept <file...> # promote one or more (an UNVERIFIED file is accepted with a warning)
npx saffron reject <file...> # discard: the agent retries next run
Each proposal is stamped by a zero-AI proof replay that ran before it
was filed: verified ✓ means the recording already replayed
deterministically once; UNVERIFIED ✗ means it did not (the listing shows
the reason). accept --all skips UNVERIFIED proposals so a bad recording
never lands by bulk-accepting; accept it by file if you have read it and
still want it, or better, re-record it (§12). A proposal is also stamped
UNVERIFIED when the recording cannot be right on its face, for example a
fill recorded with an empty value on a step that passes a value. If a recording fails its proof
replay, Saffron automatically runs one refinement pass, the agent is told
"the app works, your recording doesn't replay", before stamping. Opt out
with --no-verify or "verifyProposals": false if a scenario has
non-idempotent side effects (verification re-executes it).
Read the narrative and the recorded steps before accepting, the proposal
is the contract every future replay will execute. Then commit
.saffron/cache/ to git like any other reviewed artifact.
Every run after that: free
npx saffron run # cached scenarios replay: 0 AI calls, 0 tokens, ~1-3s each
npx saffron run --no-agent # guarantee zero AI: failures go red instead of healing
npx saffron report # open the latest HTML report
Every run also appends to .saffron/history.jsonl, so reports show deltas
vs the previous run and 20-run sparklines, and the CLI warns about
chronic scenarios (healing repeatedly = re-record it, don't keep
paying) and surfaces recurring failure themes.