Modes & engines
The CLI has two orthogonal axes — Mode (the data boundary, Cloud vs Local) and Engine (which agent backend runs a turn) — plus permission modes. They compose freely.
The CLI has two orthogonal axes. Mode controls the data boundary; Engine controls which agent backend runs a turn. They are independent and compose — any mode works with any engine.
Mode — the data boundary
| Mode | What it means |
|---|---|
| Cloud (default) | The standard experience: queries and results flow to and from TestRelic Cloud. |
| Local | Nothing is uploaded. Every mutation is approval-gated, and cloud memory is read-only. |
Switch modes either way:
testrelic --mode localOr press Shift+Tab in the interactive UI to toggle the mode for the current session.
When to use Local mode
Local mode is for working against sensitive repos or in environments where you don't want anything written back to the cloud. You can still read cloud memory and context; you just can't change it without an explicit approval.
In Studio, Local mode is per chat
Studio has no app-wide mode switch. Every Studio chat runs in Cloud mode, and Local mode is a
Skill you turn on for one chat: in a Code chat, open the composer's + menu and pick
Skills → Local mode. See Workspace. The
terminal CLI is unchanged: Shift+Tab and --mode local still switch modes there.
Engine — which agent backend runs a turn
The engine decides which agent backend actually executes a turn:
| Engine | Selector |
|---|---|
| CloudAgent | --engine cloud |
| ClaudeCode | --engine claude-code (alias claude) |
| Codex | --engine codex |
| Cursor | --engine cursor (alias cursor-agent) |
| Ollama | --engine ollama |
| (auto-select) | --engine auto |
testrelic --engine claude-codeOr open the picker in the interactive UI:
❯ /engineCloudAgent is the default (auto resolves to it) and needs no local install. ClaudeCode,
Codex, Cursor, and Ollama are local engines — always opt-in, and each runs on
your own auth or model, never silently substituted for the cloud agent. Claude Code drives your
installed claude CLI headless; Codex drives codex exec; Cursor drives its CLI, cursor-agent
(or agent, the name Cursor's installer now leads with); Ollama
talks directly to a local POST /api/chat (default llama3.1 @ localhost:11434, override with
OLLAMA_MODEL / OLLAMA_HOST or config ollamaModel). /engine shows each local engine's
install status; if the CLI it needs is missing or unauthenticated, the turn falls back to
CloudAgent.
To install Cursor's CLI, run irm 'https://cursor.com/install?win32=true' | iex in PowerShell
on Windows, or curl https://cursor.com/install -fsS | bash on macOS and Linux (and inside WSL),
then cursor-agent login. If it's installed somewhere TestRelic doesn't look, set
TESTRELIC_CURSOR_BIN to its path.
$ tr
> /engine
engine: Claude Code — your local Claude Code (runs on your own auth)
> @tests/checkout.spec.ts why does this keep flaking on CI?
✻ TestRelic
⏺ 3 tools · ctrl+o
The last 6 CI runs fail on the same step — waiting on [data-testid="place-order"]before the cart total re-renders. It's a race with the debounced price recalculation, not a selector problem.
I can add a wait on the total text settling before the click. Want me to open a fix?
> /engine codex
engine: Codex — your local OpenAI Codex (runs on your own auth)
> same fix, now open a PR
✻ TestRelic
⏺ 5 tools · ctrl+o
Opened fix/checkout-total-race — waits for the cart total to stop mutating before the place-order click, same MCP Playwright server Claude Code just used. PR #482 is up for review.
The turn header always reads ✻ TestRelic, no matter which engine is running
underneath — switching engines with /engine changes who executes the turn (and the status
chip below the composer), not the identity you're talking to. The same conversation, the same
MCP tools, a different backend.
MCP tools follow you across every engine
Whichever engine you pick, it gets the same MCP server composition — your configured harness
servers (Playwright/Appium/Maestro), any user-added servers, scoped entries, and the injected
testrelic server — not a cut-down set. Each engine receives it through the only channel it
actually has:
| Engine | How it receives MCP servers |
|---|---|
| ClaudeCode | Inline --mcp-config JSON, with an allowlist covering every merged server. |
| Codex | -c mcp_servers.<name>.{command,args,env} TOML dotted-path overrides. |
| Cursor | Mirrored into .cursor/mcp.json (Cursor's only MCP channel) at the root of the workspace's git repository, where Cursor reads it, so a workspace opened on a package folder still gets its servers; merge-preserving anything already there. If that repository is your home folder, nothing is written and the turn says why. --approve-mcps is used for headless approval when the installed cursor-agent supports it. |
| Ollama | The session's MCP host rides directly into TestRelic's own tool loop — host tools are advertised and dispatched the same way as the Cloud engine's client tools. A model that can't take a tools array degrades to a tool-less chat with an in-chat note, rather than failing the turn. |
Cross-app confinement is engine-agnostic: it lives in the server's own command
(tr mcp app-proxy --app <slug>), not in engine-specific config, so a cross-app call is refused
in plain English no matter which engine spawned the entry. The testrelic MCP token is never
written into a repo file — Cursor's .cursor/mcp.json entries that need it are fronted by the
tr mcp app-proxy relay, which resolves the token from ~/.testrelic/token at spawn time.
Tool rules hold on every engine
Codex and Cursor take no tool policy of their own, so Studio's per-tool Auto, Ask and
Off rules reach them through the same tr mcp app-proxy relay: a tool set to Off is
left out of the server's tool list and refused if called anyway, and a tool set to Ask is
refused with a reason, because a headless turn has no one to ask. Claude Code applies the
same rules itself. This holds in Studio, in tr -p and in the terminal UI, and for remote MCP
servers too. Local mode's data boundary still rests on the
MCP capability gate (read-only caps).
Permission mode
Independently of mode and engine, choose how the agent asks before acting:
testrelic --permission-mode plan|default|acceptEdits|bypassPermissions| Value | Behavior |
|---|---|
plan | Plan the work without making changes. |
default | Prompt for confirmation on each gated action. |
acceptEdits | Auto-accept edits while still gating other actions. |
bypassPermissions | Run without confirmation prompts. |
Each local engine maps this onto its own controls: Claude Code disallows its interactive-only
tools so a headless turn never stalls on them; Codex maps to its sandbox flags (plan = read-only,
otherwise full access); Cursor maps to --mode plan (read-only) for plan, adding --trust
when the installed Cursor supports it so a plan turn runs in a folder Cursor hasn't trusted
yet, and --force (the turn has already been approved) otherwise. Ollama runs TestRelic's own built-in tools, which
stay gated by Local mode's standard write/delete/run approval regardless of --permission-mode.
How they compose
Mode and engine are set separately and combine freely — for example, Local mode with the
ClaudeCode engine keeps every mutation approval-gated and nothing uploaded, while running
the turn on Claude Code. Pick the data boundary you need with --mode, the backend you want
with --engine, and the confirmation behavior with --permission-mode.
Next steps
TestRelic CLI authentication
Sign the CLI in through your browser, or save a personal access token for CI and scripts. See which credential a run uses, how the 10-token limit works, and how to point the CLI at a different backend.
Using the CLI as an MCP host
Run local MCP servers from the CLI so the cloud Ask AI agent can call your tools during a turn, with Claude-Code-compatible .mcp.json config.