Getting started
Link a repository, mint a token, and get a first green test — including how to bring existing Playwright or Cypress specs in without spending AI credits.
There are two different "getting started" paths, and it is worth knowing which one you are on:
- Running Vera itself (self-hosting the control plane, or contributing to it)
— see the
repository README: Docker for Postgres + MinIO,pnpm setup,pnpm dev. - Wiring a repo you're working in to a Vera that already exists — this page. One command, and your editor, your coding agent, and your CI all know which Vera project this repo belongs to.
One minute to a linked repo
npx vera-agent init --url https://your-vera-host --token vera_your_tokenWrite vera-agent, not vera. The published package installs both bins, but
npx vera fetches an unrelated package squatted on that name in 2022 — the short
alias is safe only once vera-agent is already installed, never in an npx
one-liner.
init is idempotent: it reports what changed, and re-running it when nothing has
changed says so instead of touching tracked files.
What one run does:
- Resolves the project. Reads the repo root and
origin, then matches a project this token can see: a GitHub-linked project wins, then a name match (my-app==My App). Two projects with the same name is ambiguous and it asks for--project <id>rather than guessing — linking a repo to the wrong project would silently misdirect every later run and coverage answer. Nothing matches at all? It prints the dashboard link to create one. A token cannot create projects, by design. - Writes
.vera/config.json—{apiUrl, projectId, repoPathPrefix}. Commit it. No credential is in it. - Saves the token to
~/.vera/cli.json—chmod 600, keyed byapiUrl, so one machine can hold credentials for several deployments and a second repo on the same host needs only--url. - Registers the
veraMCP server at the repo root (claude mcp addat local scope — that scope is keyed by the directory a Claude Code session is started from), so a session opened in this repo has the tools. Skipped with--no-mcp; see MCP setup for the other scope and for non-Claude-Code clients. If averaserver is already registered in any scope,initleaves it alone and says so. - Writes the agent-instructions block into whichever instructions file the
repo already uses (
AGENTS.md, elseCLAUDE.md), between<!-- vera:sdlc:begin -->/<!-- vera:sdlc:end -->sentinels. Only the region between the markers is ever rewritten; your prose either side survives.--no-agents-mdskips it.
Flags
| Flag | Meaning |
|---|---|
--url <apiUrl> | Your Vera origin (no trailing slash needed). |
--token <vera_…> | An API token (below). Omit it when one is already stored for that --url. |
--project <id> | Choose the Vera project explicitly — required when the name match is ambiguous, and the way to link a repo whose name doesn't match anything. |
--mcp-scope local|project | Where the MCP registration goes. local (default) → claude mcp add, private to you, carries the real token. project → merges a vera entry into the repo's committed .mcp.json using ${VERA_TOKEN}. |
--no-mcp | Don't register an MCP server. |
--no-agents-md | Don't write the agent-instructions block. |
--import <formats|all> | Convert the E2E suite this repo already has into Vera tests (cypress, playwright, postman, wdio, selenium, testcafe, har, openapi). Deterministic, no AI. See below. |
--no-import | Skip the repo scan for importable suites. |
In a terminal, omitting --url / --token prompts for them. In a script, both
are required (or supplied via a token already stored for that URL).
Three files, and which ones carry a secret
This is the part people get wrong most often.
| File | Committed? | Holds | Written by |
|---|---|---|---|
.vera/config.json | Yes — commit it | apiUrl, projectId, repoPathPrefix. Never a credential; it lands in everyone's checkout. | init |
~/.vera/cli.json | Never | Your vera_… API tokens, keyed by apiUrl. chmod 600. | init |
~/.vera/agent.json | Never | The different vera_agent_… enrollment token used to execute runs locally. chmod 600. | vera-agent login |
The last row is the one that surprises people: init and login write different
files holding different credentials for different surfaces. init's token is a
CI Token (vera_…) for the API and MCP; login's is an agent enrollment
token (vera_agent_…) that lets this machine claim and run work. start, run,
watch and verify all read the enrollment file, so if you only ran init,
verify will tell you the handshake failed — run login too.
With --mcp-scope project, the committed .mcp.json carries the literal string
${VERA_TOKEN}; each developer exports their own token
(export VERA_TOKEN=vera_…). No secret enters the repo either way.
Before that: mint a token
Settings → CI Tokens → name it → Create. Optionally set an expiry, and check org-wide for a shared/unowned token that keeps working after its creator leaves (needs the org-wide token permission; the default is personal, which is what you want for your own machine — audit rows and usage counters then name a human).
The plaintext vera_… token is shown once. Revoking it takes effect
immediately.
Plan note, because the failure is otherwise mysterious. init reads
GET /api/v1/projects, and on cloud /api/v1 requires the Pro api-access
feature. A free cloud workspace gets mcp-basic instead, which covers /api/mcp
only — so the MCP tools work while init refuses with:
Vera token not accepted. It may be revoked, expired, or this workspace may no longer include API access. Check Settings → API tokens, and the workspace plan.
Those three causes are deliberately indistinguishable from the outside, so don't assume "rotate the token" — check the plan too, especially on a recently downgraded workspace where the token is still perfectly valid. Self-hosted and local installs have no billing: every feature is on.
The ritual
init ends by printing this loop, because it is the whole point of installing
anything:
- Change something in the UI.
- Verify it in a real browser as a real role. Not "it compiles" — an actual
run, as a logged-in user, that reports what it observed. From Claude Code with
the plugin:
/vera:verify. Over MCP:run_scenario(unsaved) orrun_test, thenwait_for_run. - Keep the check if it's worth keeping. A scenario you just watched pass is
promoted into a durable test in one call (
save_scenario_as_test) — better than authoring a test blind. Vera returnswarningswhen the steps prove nothing; act on them. - On red, triage before repairing. Decide whether the test is wrong or the
app is wrong.
/vera:fix, orget_failure_details→suggest_fix. A repair that makes a failing test agree with a bug converts a known failure into a silent one, so nothing is applied without your approval.
Before you push, npx vera-agent check maps the diff onto the tests that cover
it and can run exactly that set (--run). Read
change impact before you trust the answer — the joins are
heuristics, and an unmapped file is not a safe one.
Verifying against localhost
A cloud Vera cannot reach http://localhost:3000. Two ways to close that gap,
both requiring an agent enrollment (Settings → Agents → create → copy the
vera_agent_… token):
npx vera-agent login --url https://your-vera-host --token vera_agent_...
# run an ad-hoc check here, now, in this process — seconds, no queue
echo '[{"action":"goto","url":"/orders"},
{"action":"assert","selector":"#total","assertType":"text","value":"42 orders"}]' \
| npx vera-agent verify --project prj_123 --steps - --role admin
# or replay something already saved
npx vera-agent verify --test tst_456It is still a real run: the control plane creates the row, stores the step results and video, and shows it in the project's run feed — local and cloud checks share one history. What runs locally is the browser, not the bookkeeping.
For the standing setup — an environment whose runs always execute on your machine — see the local agent guide.
Bringing existing specs in (no AI credits)
If the repo already has an E2E suite, convert it instead of starting from an
empty project. Eight formats are supported: postman, cypress, playwright,
wdio, selenium, testcafe, har, openapi.
curl -s -X POST https://your-vera-host/api/v1/projects/prj_123/import/cypress \
-H "Authorization: Bearer vera_your_token" \
-H 'content-type: application/json' \
-d '{"files":[{"path":"cypress/e2e/login.cy.ts","content":"…file text…"}]}'Bounds, all of which refuse atomically rather than importing part of a batch:
50 files per request, 5,000,000 characters per file, 16 MiB per body. A 201
returns the created tests, per-format counts, skipped files with reasons,
warnings, and an unresolved count.
Be careful what you quote from that response. Conversion is deterministic and
costs no AI credits, and that is exactly why it is partial: navigation and
interaction map cleanly, but an assertion the converter cannot express is
reported, not converted — it lands in warnings with an unresolved count
and is left out of the test. A Cypress spec whose only assertion was
cy.contains('Welcome back') imports as goto, fill, fill, click: a test that
replays green and proves nothing. So read unresolved before believing a test
count, and add the missing assertions (by hand, or by re-importing with
{"aiFallback": true}, which does spend AI credits on your own key).
Or let init do it
init scans the repo for importable suites and offers what it found:
npx vera-agent init --import all # convert everything it finds
npx vera-agent init --import cypress,har # or name the formats
npx vera-agent init --no-import # skip the scan entirelyWithout --import, an interactive init prints what it found and asks. When
stdin is not a terminal (CI, a piped provisioning script) it imports
nothing and says so, with the flag to opt in — importing writes tests into
someone's workspace, and a script that piped vera-agent init did not consent to
that. The scan honors .gitignore, and aiFallback is never sent from this
path, so a first green costs no AI credits.
This is also the command vera check prints when its impact
map is cold: imported tests carry their own goto URLs, which is exactly what
the route join reads.
Where to go next
- The Vera Claude Code plugin — the skill and the
/vera:*commands, so the procedure isn't re-explained each session. - MCP server — every tool, the auth model, the confirm-to-apply rule.
- The local agent — the full
vera-agentcommand surface, environment run targets, native mobile, troubleshooting. - Change impact (
vera check) — which tests a diff touches, the three joins and what they cannot see,--runand the opt-in--strict. - CI integration — triggering runs from CI with the same
vera_…token; CI-rider for running them on your own runners.