See inside a run
See inside a run
Why does this task run? What did the run save? Where did the time go? vx answers each in one flag: affected reasons, run JSON, a Graphviz graph, run tags and its own stage table.
Most vx runs are started by coding agents now. So every verb speaks JSON with a shipped schema, a failure keeps its log and the files it names, the run history is a SQLite file, and the docs and a skill come as plain markdown.
A coding agent cannot read a progress bar. It reads stdout, parses it and decides what to do next. If the answer is buried in a frame meant for human eyes, the agent guesses. vx is built so it never has to.
flowchart LR A[agent] -->|vx run --format json| R[result on stdout] A -->|vx last --failed --format json| F[failed output + file:line] A -->|sqlite3 cache.db| H[run history] A -->|llms.txt + SKILL.md| D[how to use vx] style F stroke:#c6f84e,stroke-width:2px
vx run --format json prints one JSON document when the run ends. The
frame and the tasks’ output go to stderr, so a pipe sees only the
result.
$ vx run build --all --format json 2>/dev/null{ "runId": "01a11f0d-014c-700d-a4ad-59e93a00a129", "ok": true, "exitCode": 0, "totalMs": 223.951554, "savedMs": 1270, "tasks": [ { "id": "@demo/api#build", "status": "cache-hit", "exitCode": 0, "durationMs": 3, "hash": "32b3a0bfa973a7a8", "storedDurationMs": 326, ...savedMs is the time the cache saved this run. vx show, vx info,
vx why, vx last and vx cache prune take the same --format json.
Each JSON document has a checked-in JSON Schema, shipped in the package
at node_modules/@vzn/vx/schemas/: summary.json, plan.json,
show.json, info.json, why.json, last.json and cache.json.
Every object closes its key set, so a new field is a schema change, never
a surprise. A test holds each verb’s output to its schema, so stdout
always parses. A refusal under --format json is a JSON line too, with
a stable code an agent can branch on: see
A refusal an agent can read.
When a task fails, an agent wants two things: what it printed and which files it blames. vx saves both, so the agent does not have to scroll a terminal it never saw.
$ vx last --failed --format json | jq '.tasks[] | select(.output != "") | {status, exitCode, output, locations}'{ "status": "failed", "exitCode": 1, "output": "src/index.ts:3:7 - error TS2322: Type string is not assignable to type number\n", "locations": [ { "file": "/work/demo/packages/ui/src/index.ts", "line": 3, "col": 7 } ]}locations lists only files that exist, with absolute paths. Secrets are
masked in the saved output. vx keeps the newest 50 failed runs.
Every task of every run goes into cache.db: time, CPU, peak memory,
status and cache result. No export step, no API. The file is the API.
$ sqlite3 .vx/cache/cache.db " SELECT project, task, status, duration_ms FROM runs WHERE run_id = (SELECT run_id FROM runs ORDER BY id DESC LIMIT 1) ORDER BY duration_ms DESC;"@demo/ui|test|failed|207@demo/ui|build|cache-hit|1llms.txt indexes every docs page
as markdown, and
llms-full.txt is the whole
site in one file. @vzn/vx also ships an agent skill, one SKILL.md
that teaches an agent to run, debug and query vx:
$ mkdir -p .claude/skills/vx$ cp node_modules/@vzn/vx/skills/vx/SKILL.md .claude/skills/vx/For live questions over the Model Context Protocol, see Give your coding agent the build’s memory. The agents guide and machine-readable output have the details.