DEV Community

Cover image for Built for the agent at the keyboard
VX
VX

Posted on Originally published at vznjs.github.io

Built for the agent at the keyboard

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.

diagram

The result on stdout, the logs on stderr

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,
      ...
Enter fullscreen mode Exit fullscreen mode

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.

Every shape has a schema

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.

A failure keeps its log and its files

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
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

locations lists only files that exist, with absolute paths. Secrets are
masked in the saved output. vx keeps the newest 50 failed runs.

The history is a SQLite file

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|1
Enter fullscreen mode Exit fullscreen mode

Docs and a skill, as markdown

llms.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/
Enter fullscreen mode Exit fullscreen mode

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.


Originally published on the vx blog. vx is an MIT task runner and build cache for JS monorepos: vznjs.github.io/vx ยท GitHub.

Written with AI assistance.

Top comments (0)