Getting Started
Install, run jevitate init once, and point it at the app you already have running
locally. The first run needs no API keys.
Prerequisites
- Node.js 22+ (required since 0.10.0; Node 20 is end-of-life)
- Your app running somewhere Jevitate can reach, e.g. a dev server on
http://localhost:3000. - No display needed: every run is headless by default. Chromium only.
1. Install
npm install -g @jevitate/cli
npx playwright install chromium # on a fresh Linux box: npx playwright install --with-deps chromium jevitate --version prints the version with the commit and git tree hash it was built from (0.15.0). Releases are published from GitHub Actions through npm trusted publishing, with a provenance attestation. A merge to staging publishes the tested build as the next dist-tag; pushing the vX.Y.Z tag moves latest to that same build.
2. Set up with jevitate init
cd your-app # the repo of the app you want to test
jevitate init --dry-run # optional: show what it would install and register
jevitate init One command does the setup:
- Keys. At a terminal it asks for the ones it is missing:
TYPESAFE_API_KEY(Jev, the judgment model) andOPENROUTER_API_KEY(text generation). Only model-driven runs need them. Judgment can also run on theOPENROUTER_API_KEYalone, since OpenRouter serves Jev as~typesafe/jev-latest: the TypeSafe key wins when both are set,--jev-provider typesafe|openrouter(orJEVITATE_JEV_PROVIDER) pins one, and a pinned provider without its key is refused rather than switched.initskips the TypeSafe key prompt once an OpenRouter key is set; add it later withjevitate ai setup judgment, or choose the route withai setup judgment --jev-provider openrouteror--jev-provider typesafe. Skip with--skip-keys, or set them later withjevitate ai setup <generation|judgment>(--replaceto rotate one). Without a terminal (CI, a coding agent) it never prompts; it reports which keys are missing. Each key is checked live with its provider (a non-billable call);jevitate ai statusshows each key's provider and source and exits 2 on an invalid or unverifiable key. Offline or in CI, use--no-verifyandJEVITATE_NO_KEY_VERIFY=1. - Agent skills, installed into the coding agents it detects: Claude Code, Codex,
Cursor, plus an
AGENTS.mdfallback. See Agent Skills. - MCP. It registers
jevitate mcpin.mcp.json,.cursor/mcp.jsonand~/.codex/config.toml, and never overwrites an entry you changed without--force. - The repo's
.jevitate/, at the git root: Journeys, regressions, baselines, an exampleenvironments.json, and datedlogs/(git-ignored, pruned after 14 days, newest 50 kept). Secrets and sessions live in~/.jevitate/, never in the repo.
3. First run: try to break a form (no keys)
jevitate explore --strategy adversarial --url http://localhost:3000/settings --fake-ai
The adversarial mission plans its misuse in code: double submits, empty, boundary, long, unicode
and invalid values, reloads mid-edit, acting while a save is pending. --fake-ai swaps
its advisory model calls for deterministic stand-ins; nothing it reports depends on them.
It prints a short summary: the outcome, each defect with its fingerprint, where the result file
is, and a next: line. The full result, its Recording and ready-to-file issue drafts go
under .jevitate/logs/<date>/. Add --json for the
{v, ok, data} envelope. The exit code is the outcome:
| Exit | Outcome |
|---|---|
0 | clean: finished its budget and found nothing |
1 | defects-found: at least one confirmed defect |
2 | inconclusive / crashed: the run could not do its work, so its silence proves nothing |
3 / 4 | hang (reproduced on replay) / intermittent |
5 | healed-pending-review (0.9.0, Journey runs and check): a self-heal proposed a revision a person must accept |
64 | a usage or input error; nothing ran |
--url's origin.
--allow <origin> (repeatable) replaces that default, so include the app's own
origin too (since 0.13.0 a blocked write prints the full --allow list to set, start origin included, and
E_UNAUTHORIZED_EXPLORE_TARGET says the start URL's origin must be in it; the list stays exact).
Logged-in app? Add --storage-state auth.json
(Targeting Real Apps).
4. With keys: ask a question, or reach a goal
# Find out: no --success; the answer must be grounded in text the run saw. Read-only by default.
jevitate explore --url http://localhost:3000/pricing \
--goal "find out which plans are offered and report their prices" --real
# Reach a goal: code decides it with independent checks, not the model's "done"
jevitate explore --url http://localhost:3000/profile --goal "set the last name to Litmus and save" \
--success 'requestMade:PUT /api/profile' \
--success 'reloadThen:valueEquals:[data-testid=last-name]|Litmus' --real
Jev picks what to try next among the controls code found; code decides the outcome. A goal run
reports missionOutcome (it sets the exit code) and its own goalOutcome
(succeeded, failed, exhausted, blocked).
Model-driven runs need --real (or --fake-ai for a pipeline smoke) and
report their cost under usage. Every strategy is on
Testing Modes.
5. Keep it: a Journey
jevitate explore-author-journey --url http://localhost:3000 \
--goal "add a product to the cart and reach checkout" --success urlIncludes:/checkout \
--id checkout --name "Checkout" --real
jevitate journey promote checkout # the human approval gate
jevitate journey run checkout # deterministic replay, no model in the loop A Journey is a typed, deterministic replay. It is written unpromoted; promotion is always a human act. See Journeys for recording by demonstration, intent, self-heal, sharing and load tests.
6. Run it anywhere, and demo it
Name the places your app runs in .jevitate/environments.json (init writes an example once; it is committed, so never put a secret in it):
{
"local": { "baseUrl": "http://localhost:3000" },
"staging": { "baseUrl": "https://staging.example.com" }
} jevitate journey run checkout --env staging
jevitate journey demo checkout --env staging --video demos/checkout.webm --guide demos/checkout.md
Journeys know no host: --env picks where they run. journey demo writes a
captioned WebM, .vtt subtitles and a Markdown guide. See
Demos & Environments.
7. Verify fixes and gate CI
jevitate verify-fix --result <run>.result.json --fingerprint <fp> # fixed? 3 fresh replays
jevitate check --suite ci/jevitate-suite.json # the CI gate: JUnit, SARIF, report verify-fix passes only if the defect is absent on every replay. regression
capture commits a failure as a regression, and check runs a suite within a
budget. See Regression & CI.
Hand it to your coding agent
After init, your agent can already use Jevitate, through the skills or the MCP
server. A prompt to paste for each runtime is on the homepage; the tool
list is on MCP & CLI.
Try the demo app
The repository's example app has a planted bug: a form that says "Saved" while the server returns HTTP 500. The 2-minute walkthrough finds it, reproduces it 3/3, commits a regression and verifies the fix, with no API keys.
Building from source
git clone https://github.com/matt-cochran/jevitate
cd jevitate && pnpm install && pnpm -r build
pnpm --filter @jevitate/cli run bundle
alias jevitate="node $PWD/packages/cli/dist/bin.js" Every command and flag: docs/cli.md.