---
name: tracks
description: Run coding agents (Claude Code, Codex, Cursor) in isolated cloud sandboxes with the Tracks CLI, `tracks` - start a run on a repository, follow what the agent does, send follow-up prompts, check what it cost, or compare agents on scenarios with experiments. Use when the user wants a coding agent to work in a sandbox, to delegate a task to a remote agent, or mentions Tracks.
---

# Tracks

Tracks starts a coding agent on a prompt in a fresh sandbox, optionally on a Git repository, and records everything it does. The `tracks` CLI calls its API; every command prints JSON on stdout.

## Setup

- Install: `npm install --global @alpic-ai/tracks`, or prefix commands with `npx @alpic-ai/tracks` instead of `tracks`.
- `TRACKS_API_KEY` must be set to an API key of the user's organization, starting with `trk_`. If it is not, ask the user for one; never print it.
- `TRACKS_API_URL` points the CLI at another deployment than the default one.
- `tracks health` prints `ok` when the API is reachable.
- `tracks --help`, `tracks runs --help` and `tracks runs <command> --help` list every command and flag.

## Start a run

```sh
tracks runs create "Fix the failing tests and explain the cause" \
  --harness claude-code --model claude-sonnet-5-5 \
  --repository https://github.com/alpic-ai/apps-sdk-template \
  --budget 5
```

- `--harness` is `claude-code`, `claude-desktop` (Cowork, the agent workspace of Anthropic's Claude desktop app, for documents, research and longer tasks, slower to start and costlier per prompt than `claude-code`), `codex`, `codex-app` (the Codex mode of OpenAI's ChatGPT desktop app, with its own browser, computer-use and document tools, slower to start and costlier per prompt than `codex`) or `cursor` (Cursor's CLI); `--model` is a model of that harness's provider, a Cursor model id such as `gpt-5.6-luna-low` for `cursor`.
- `--repository` is cloned without credentials before the agent starts, so it must be public. For a private one, leave it out and clone in `--setup` with a token passed through `-e`: `git clone "https://x-access-token:$GITHUB_TOKEN@github.com/your-org/your-repo" .`
- `-e KEY=VALUE` sets an environment variable in the sandbox; `-e KEY` passes its local value. Repeat for several.
- `--setup "$(cat setup.sh)"` runs a script after checkout, before the prompt, such as installing dependencies; a non-zero exit fails the run. `--teardown` runs one after the run ends. Make both idempotent.
- `--file <path>` uploads a local file and puts it in the sandbox before setup; the prompt tells the agent where. PNG, JPEG, WebP, GIF, PDF, text, Markdown, CSV or JSON, up to 20 MiB each, at most 20 files. Repeat for several.
- `--mcp NAME=URL` gives the agent an MCP server, under that name; repeat for several. See [MCP servers](#mcp-servers) for servers that need the user's account.
- `--budget` caps spend in US dollars, `--time-limit` caps duration in seconds.
- `--idempotency-key <key>` makes a retried `create` return the run already created instead of starting another.

The command returns at once with the run's `id` and status `preparing`.

## MCP servers

The agent reaches its MCP servers through Tracks, never directly: credentials never enter the sandbox, and requests come from the addresses `GET /egress-ips` lists, to allow on a server that filters callers.

A server that needs the user's account (Linear, Notion, GitHub…) needs a connection first, made once and reused by every run:

1. Ask the user to run `tracks connections create <server-url>` themselves: it opens their browser to sign in and consent on that server, waits up to 10 minutes, then prints the connection, `active`.
2. `tracks connections list` shows connections and their `status`: `authorizing`, `unconfirmed`, `active` or `failed`. Only `active` ones are used; a `failed` one needs `tracks connections create` again.
3. Start the run with `--mcp linear=<connection-id>`: the run calls the server as the user who connected it.

A server given by URL is called without credentials. `tracks connections get <id>` shows a connection, `tracks connections delete <id>` deletes it and the access it holds.

## Follow it

A run records two views of the agent's work:

- **Frames** are its raw output: each line the harness printed on stdout or stderr, unchanged, in that harness's own format (Claude Code, Codex and Cursor print different JSON). Use them to debug, or for a detail events leave out.
- **Events** are read from the frames into one format for every harness: `prompt`, `message`, `reasoning`, `tool_started` / `tool_ended`, `subagent_started` / `subagent_ended`, then `stop` when the agent stops. Each event's `frame_seqs` points at the frames it was read from. Prefer events.

Commands:

- `tracks runs follow <id> --events` prints events as they happen, one JSON object per line, until the run ends; without `--events` it prints frames. It exits with code 2 when the run ended before its agent finished: `failed`, `time_limit`, `budget_exceeded` or `canceled`. It can last minutes: run it in the background, or poll `tracks runs get <id>` instead.
- `tracks runs list` lists your runs, most recent first; `--label ticket:ENG-42` keeps those created with `tracks runs create … --label ticket:ENG-42`.
- `tracks runs events <id>` and `tracks runs frames <id>` list what was recorded so far, by page: pass the last `seq` received as `--after`, and `--prompt <index>` to keep one prompt's.

## Read the result

`tracks runs get <id>` shows the run. Its `status` is `preparing`, `working`, `idle` or `ended`. Once ended:

- `end_reason` is `completed`, `idle_timeout`, `time_limit`, `budget_exceeded`, `failed` or `canceled`.
- When `failed`, `failure` says what went wrong and `failure_kind` what kind of thing: `repository_checkout_failed`, `setup_failed`, `browser_not_started`, `sandbox_not_found`, `process_lost`, `sandbox_unavailable`, `agent_stopped` (the agent of a run that accepts no follow-ups stopped with an error) or `unexpected`.
- `completed` means the agent stopped, not that it succeeded: read its last `message` events to judge its work.

`tracks runs usage <id>` shows what the run consumed and cost.

The sandbox is destroyed when the run ends: anything the agent should keep, it must push or send somewhere, for example by asking it in the prompt to open a pull request.

## Several prompts

By default a run ends once its first prompt finishes. To continue the conversation:

1. Create it with `--no-one-shot` (and optionally `--idle-timeout <seconds>`, from 120 to 900).
2. Wait until `tracks runs get <id>` shows `idle`.
3. `tracks runs send-prompt <id> "Now add a regression test"`, optionally with `--model`.
4. `tracks runs end <id>` once done, or it ends by itself after the idle timeout.

`tracks runs cancel <id>` stops a run right away, even mid-prompt.

## Experiments

An experiment gives the same scenarios to several agents in several variants, then judges each run on the scenario's evaluations. Use one to measure how well agents use a product, or to gate a change on a pass rate.

1. `tracks library` lists the repositories, skills, MCP servers and command-line tools an experiment can pick, by id. They are added in the web app.
2. Write the experiment as JSON: `name`, `scenarios` (each with an `id` you choose, a `prompt` and its `evaluations`, yes-or-no `judging_instructions`, and an optional `passing_score` out of 100; without it a run passes only when it passes every evaluation), `agents` (`harness` and `model`), `agent_tools` (agent tool configurations with ids picked from the library; keep one with no agent tools as the baseline), optional `repositories` and `excluded_variants`, and `run_settings` (`repetitions`, `time_limit_seconds`, `budget_usd`, optional `setup`, `teardown`, `variables`). `tracks experiments get <id>` prints one in that shape.
3. `tracks experiments create experiment.json` creates it; `tracks experiments update <id> experiment.json` replaces it whole.
4. `tracks experiments launch <id>` starts a run for every scenario, variant, agent and repetition, at most 500. If it lacks something, the error lists what to fix. With `--wait` it prints progress until no run is pending, then the execution; `--min-pass-rate 80` waits too and exits non-zero below 80%, for CI.
5. `tracks executions get <id>` shows an execution: `pending` while runs have not ended or wait for their evaluation results, and its `pass_rate`. `tracks executions slots <id>` lists its slots, one per scenario, variant, agent and repetition, each with its `run_id`, its `outcome` (`running`, `judging`, `judged` or `not_evaluated`), its `verdict` (`passed` or `failed`), `score` and `evaluation_results`. Read what an agent did with `tracks runs events <run_id>`.

`tracks experiments executions <id>` lists an experiment's executions, latest first; `tracks executions cancel <id>` cancels one.
