CLI overview
Run Agentiqa from the terminal with the agentiqa CLI — explore a URL or run saved test plans, locally or in CI.
The agentiqa CLI runs the same agent as the apps, headless. It has two sides:
- Explore & author —
agentiqa exploreproposes what to test, and theplanverbs (plan list/get/save) plusruns getlet you and your coding agent curate, save, and read back test plans. This is the interactive agent-authoring loop.agentiqa project listshows which projects those verbs can work in — see Choosing a project. - Run & gate —
agentiqa runreplays saved plans and returns deterministic pass/fail. This is the command you wire into CI.
Plus login, logout, and whoami. See the generated
CLI reference for every command and flag.
Install
The CLI ships on npm and needs Node.js 18+ (Node 20 recommended). There is
nothing to install ahead of time — npx -y fetches it on first use:
npx -y agentiqa@latest whoamiOn Ubuntu CI, the distro's default apt-get install nodejs can be too old — use
actions/setup-node@v4 or NodeSource to get Node 20+.
explore vs run
-
agentiqa explore "<prompt>"— the agent explores a URL, proposes what to test, and reports findings. It also returns a draft plan you can curate and save (see the authoring loop). Great for ad-hoc QA.npx -y agentiqa@latest explore "Find bugs on the signup page" --url https://example.com -
agentiqa run— replays your saved test plans and returns deterministic pass/fail. This is the command you wire into CI. With a service key it runs on the hosted engine by default — no--engineflag needed:# Run all plans in the service key's project (hosted engine, by default) AGENTIQA_SERVICE_KEY=sk_... npx -y agentiqa@latest run
To save, read, and revise plans by id from your coding agent — the full explore → review → save → run → read loop — see Agent skill.
Where the engine runs
agentiqa run picks its engine automatically, and you can override it:
- Hosted (default with a service key). An authenticated
agentiqa run(AGENTIQA_SERVICE_KEYset) now defaults to Agentiqa's env-matched cloud engine (engine.agentiqa.com) — so CI needs no--engine. No Chromium on your machine, and the run persists to your account (run link, server-side video). The service key alone authenticates; a short-lived engine credential is minted automatically. - Embedded / in-process (
--embedded). Forces an execution engine inside the CLI process instead: it downloads Chromium on first use and drives the browser on your machine, so it can reach local targets (includinglocalhost) and run offline. Embedded runs execute locally and do not persist to your account (no run link or server-side video). - Explicit (
--engine <url>). Pins a specific engine URL; overrides the default and--embedded.
To test a localhost target, use --embedded (or point --engine at a reachable
engine).
Choosing a project
plan, runs, and labels operate inside one project. agentiqa project list
shows every project the logged-in account can reach — the ones it owns and the
ones a teammate shared with its organization — with an explicit access marker:
npx -y agentiqa@latest project listID NAME TARGET URL ACCESS
proj_7q1x8k2m0 web https://app.example.com owner
proj_mr26brft0 acme-app https://acme.example shared · orgThen pick one, once, per machine:
npx -y agentiqa@latest project use acme-app # by id or by unique name
npx -y agentiqa@latest project current # what the next command will use
npx -y agentiqa@latest project use --clear # forget the remembered projectproject use with a name that does not match exits 2 with
error.code: "project_not_found" and candidates: [{ id, name }] in the envelope,
so a script can pick from that response without a second list. project current --json adds name, the rung it came from (source: flag, env, stored,
single-project, service-key, none) and valid — false when the remembered
project is no longer accessible, which is the answer to "why does every command
suddenly 404?". project list --archived includes soft-deleted projects — it needs the
server-side archived listing, so against a control plane that does not have it yet
the command exits 3 archived_listing_unsupported instead of reporting a live-only
list as complete.
The project is resolved in this order, first match winning:
--project <id|name>on the command.AGENTIQA_PROJECT_IDin the environment.- The project remembered by
agentiqa project use. - The only project the account can access, when there is exactly one.
- On an interactive terminal, a prompt that lists the projects and remembers your
choice. In CI (or with
--json, or piped stdin) there is no prompt — the command fails immediately with the list of options, so a job never hangs.
Several terminals or coding-agent sessions at once? Don't use project use there. It stores one selection for the whole machine (in ~/.agentiqa/config.json), so a session that runs it switches the project for every other shell on that machine. Pin the project per session instead, with export AGENTIQA_PROJECT_ID=proj_… (an exact project name also works) or --project on each command. project current --json then reports source: "env" (or "flag"), so each session can confirm where its commands will land.
AGENTIQA_SERVICE_KEY overrides all of the above: a service key is scoped to one
project by construction. Only a project's owner can mint a service key — but
you do not need one: a logged-in member can run a shared project directly with
project use / --project / AGENTIQA_PROJECT_ID.
Project memory, credentials, and permissions
Inspect your effective permissions before changing a shared project:
npx -y agentiqa@latest project permissions --project myapp-staging --json| Resource | Who can change it? |
|---|---|
| Project name, URL, sharing and browser-profile persistence | Project owner |
| Project memory | Project owner; shared-project members can read it |
| Personal credentials | Each member can manage their own credentials on an accessible project |
| Shared credential pool | Project owner or org admin, with an active Company organization; non-owner admins need the project shared with the org |
An org admin does not automatically own teammates' projects. permissions
reports separate capabilities for settings, memory, personal credentials and the
pool. Model, viewport, headless and max-actions defaults currently live in the UI's
local session configuration; they are not persistent server-backed project
settings that the CLI can update.
Memory
npx -y agentiqa@latest project memory list --project myapp-staging --json
npx -y agentiqa@latest project memory add --project myapp-staging --file ./qa-context.txt --category auth --json
npx -y agentiqa@latest project memory update mem_ID --project myapp-staging --text "Use the staging sign-in page" --json
npx -y agentiqa@latest project memory pin mem_ID --project myapp-staging --jsonUse archive to exclude an item from default recall, restore to bring it back,
and unpin to remove its pinned status. list --include-archived includes archived
items. --file - reads text from stdin; --text and --file are mutually
exclusive. An omitted category is preserved on update.
Personal credentials and shared pools
# Pipe from your secret manager or a protected local file; secrets never go on argv.
npx -y agentiqa@latest project credentials add --project myapp-staging --name tester --login qa@example.com --secret-stdin < ./qa-password.txt
npx -y agentiqa@latest project credentials update cred_ID --project myapp-staging --secret-stdin < ./rotated-password.txt
npx -y agentiqa@latest project credentials list --project myapp-staging --json
# An authorized project owner or org admin provisions a shared login/password pair.
npx -y agentiqa@latest project pool add --project myapp-staging --name tester --login shared@example.com --secret-stdin < ./shared-password.txt
npx -y agentiqa@latest project pool list --project myapp-staging --json
npx -y agentiqa@latest project pool release cred_ID --project myapp-staging --jsonAGENTIQA_CREDENTIAL_SECRET is an alternative to --secret-stdin. Stdin removes
one trailing newline. Personal credential updates preserve omitted names, logins
and secrets; an explicit empty --login "" clears the distinct login. Pool
update always requires a replacement secret because the pool list never returns
passwords. pool release force-releases a slot held by a run or chat; it is
restricted to pool administrators.
Secrets are redacted in text and JSON output. Only credentials list --reveal
prints your personal plaintext secrets; it never reveals pool passwords or
another user's credentials.
Removing an item
Removal requires an exact item id, an explicit project id, and --yes:
npx -y agentiqa@latest project memory remove mem_ID --project proj_ID --yes --json
npx -y agentiqa@latest project credentials remove cred_ID --project proj_ID --yes --json
npx -y agentiqa@latest project pool remove cred_ID --project proj_ID --yes --if-exists --jsonA name or remembered project is insufficient for removal. Without --yes the
command exits 2 with confirmation_required. --if-exists succeeds with
found: false when the item is absent from the selected project/account. Pool
removal also clears that account's active lease.
Resource commands use the existing login or the service key's pinned project.
JSON successes return items for lists, item for saved/curated items, and the
resolved target. Exit 2 means usage, permission or conflict; exit 3 means a
network/server failure or invalid response. Useful denial codes are owner_only,
pool_admin_required, pooled_credential, item_not_found, and
CREDENTIAL_CONFLICT. Resource flags are validated so an unsupported option is
reported instead of silently ignored.
Creating and editing a project
A project can be created and retargeted entirely from the CLI — useful when a coding agent is setting up testing inside a repo, or when CI needs a project per environment.
# Create. The name defaults to the URL's host label (`app.example.com` → `example`).
npx -y agentiqa@latest project create --url https://staging.myapp.dev --name myapp-staging --json
# Idempotent create: a name collision returns the EXISTING project with
# `created: false` and exit 0, so a retried CI job never mints a twin.
npx -y agentiqa@latest project create --url https://staging.myapp.dev --name myapp-staging --if-not-exists --json
# Inspect: the entity plus `isOwner`, `sharedVia`, `archived` and `activeRuns`.
npx -y agentiqa@latest project get myapp-staging --json
# Retarget after a preview deploy. Omitted fields are PRESERVED;
# `--clear-url` stores an explicit empty default URL.
npx -y agentiqa@latest project update myapp-staging --url https://pr-123.preview.app --jsonNotes:
- Names are unique per owner, case-insensitively. A collision is exit 2 with
error.code: "name_conflict"andexisting: { id, name }in the envelope — never a silent rename. Pass--if-not-existsto accept the existing project instead. updateis a patch. Only the flags you pass change;--urland--clear-urlare mutually exclusive.--expected-updated-at <iso>makes the write fail withstale_writerather than overwrite a concurrent edit.- Editing project settings is owner-only. On a project shared with you,
updateexits 2owner_onlywithout issuing a write. AGENTIQA_SERVICE_KEYcannot create a project — a key is scoped to the one project it was minted for.project createunder a key exits 2service_key_cannot_createand issues no request; runagentiqa logininstead.- Every project verb reports its target.
--jsoncarriestarget: { apiBase, env, projectId, name }(envisprod,staging, orcustom (<host>)), and text mode prints one[agentiqa] target: …line on stderr before acting — so "which control plane am I on?" is never implicit.
A shared project's saved plans are readable, and a plan with a sign-in step resolves its credential by name: your own credential is used when you have one stored under that name in Project Settings → Project credentials, and otherwise a free shared account of that name, provisioned for the team by an admin. A personal credential's secret stays yours — nobody else can see it. When neither exists, the run is refused before it starts, naming the credential to add. See Team projects.
Selecting which plans run
agentiqa run operates on the project resolved above — the service key's project
when one is set, otherwise the project you picked. With no selector it runs
every non-deleted plan; narrow it with:
--plan-id tp_…— run a single saved plan.--label-ids a,b,c— run every plan tagged with any of those labels (comma-separatedlbl_…ids, OR match).
--plan-id overrides --label-ids when both are given, and a selector that
matches no plans is a configuration error (nonzero exit) — a run that tests
nothing is never a pass.
Parallel vs sequential
--mode controls how the selected plans execute. Each plan always runs as an
independent engine session with its own browser, so plans never share cookies
or state — --mode only changes ordering and concurrency.
--mode sequential(default) — plans run one at a time. Run memory is threaded from each plan into the next, and a transient per-plan engine disconnect is retried on a fresh session, up to three attempts total.--mode parallel— plans run through a bounded worker pool to shrink wall-clock time. By default, up to four plans run concurrently and remaining plans start as workers become available. Each plan gets the same engine-disconnect recovery as sequential mode: it is retried on a fresh session, up to three attempts total.
Parallel has one deliberate caveat:
- No run-memory threading — a plan that consumes an earlier plan's saved run memory has no upstream memory in parallel and is reported as dependency-blocked. Run dependent chains sequentially.
Prefer sequential when plans depend on each other; prefer parallel for an independent regression suite where bounded concurrency shortens wall-clock time. Both modes apply the same per-plan engine-disconnect retry.
Authentication
Interactive use: agentiqa login (opens a browser). That is enough for every
command — run included, against a project's saved plans — with no service key;
see Choosing a project for how the project is picked. You
may run any project you can reach: your own, and any project shared with your
organization.
Unattended use (CI): set AGENTIQA_SERVICE_KEY to a project-scoped service key —
see CLI Service Keys. A service key needs no
browser and no interactive step, which is what makes it the right credential for
an unattended job; it also overrides the project selection, since it is scoped to
one project by construction.
In CI
For running the CLI in GitHub Actions, prefer the GitHub Action; for the exit-code contract and JSON envelope you parse, see CI Integration.