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) and OPENROUTER_API_KEY (text generation). Only model-driven runs need them. Judgment can also run on the OPENROUTER_API_KEY alone, since OpenRouter serves Jev as ~typesafe/jev-latest: the TypeSafe key wins when both are set, --jev-provider typesafe|openrouter (or JEVITATE_JEV_PROVIDER) pins one, and a pinned provider without its key is refused rather than switched. init skips the TypeSafe key prompt once an OpenRouter key is set; add it later with jevitate ai setup judgment, or choose the route with ai setup judgment --jev-provider openrouter or --jev-provider typesafe. Skip with --skip-keys, or set them later with jevitate ai setup <generation|judgment> (--replace to 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 status shows each key's provider and source and exits 2 on an invalid or unverifiable key. Offline or in CI, use --no-verify and JEVITATE_NO_KEY_VERIFY=1.
  • Agent skills, installed into the coding agents it detects: Claude Code, Codex, Cursor, plus an AGENTS.md fallback. See Agent Skills.
  • MCP. It registers jevitate mcp in .mcp.json, .cursor/mcp.json and ~/.codex/config.toml, and never overwrites an entry you changed without --force.
  • The repo's .jevitate/, at the git root: Journeys, regressions, baselines, an example environments.json, and dated logs/ (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:

ExitOutcome
0clean: finished its budget and found nothing
1defects-found: at least one confirmed defect
2inconclusive / crashed: the run could not do its work, so its silence proves nothing
3 / 4hang (reproduced on replay) / intermittent
5healed-pending-review (0.9.0, Journey runs and check): a self-heal proposed a revision a person must accept
64a usage or input error; nothing ran
Only the origins you authorize. A run visits only the --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.