Jaunt
Reference

JSON Output

The --json envelope for each command, for agents and CI.

Pass --json to a command and it prints a single JSON object on stdout instead of human progress. This is the interface for CI annotations, agents, and any tooling that shells out to Jaunt. The payloads below are trimmed from real runs.

Conventions

  • Every envelope carries a "command" field naming the command and an "ok" boolean.
  • Errors go to stderr as a human-readable line. In --json mode Jaunt also writes a machine envelope to stdout: {"command": ..., "ok": false, "error": "..."}. So a non-zero exit can still leave parseable JSON on stdout.
  • Progress bars are suppressed. To keep a progress display while parsing JSON, use --progress plain (progress on stderr, JSON on stdout).
  • --json is available on build, test, status, check, specs, jobs, sync, design, clean, migrate, watch, instructions, init, log, tree, cache, and skill.

Version-1 Python projects keep these envelopes byte-for-byte. Version-2 workspaces add "schema_version": 2, qualify top-level IDs (py:demo.specs, ts:src/slug/index), and repeat language-local values under targets.py and targets.ts. TypeScript errors use a structured {code, message, diagnostics} record; version-1 errors remain strings.

{
  "schema_version": 2,
  "command": "build",
  "ok": true,
  "generated": ["ts:src/slug/index"],
  "skipped": ["py:demo.models"],
  "refrozen": [],
  "failed": {},
  "targets": {
    "py": {"generated": [], "skipped": ["demo.models"], "refrozen": [], "failed": {}},
    "ts": {"generated": ["src/slug/index"], "skipped": [], "refrozen": [], "failed": {}}
  }
}

build

{
  "command": "build",
  "ok": true,
  "generated": ["demo.specs"],
  "skipped": [],
  "refrozen": [],
  "failed": {},
  "cost": {
    "api_calls": 1,
    "cache_hits": 0,
    "prompt_tokens": 79687,
    "cached_prompt_tokens": 61952,
    "completion_tokens": 557,
    "total_tokens": 80244,
    "estimated_cost_usd": 0.16383
  },
  "cache": { "hits": 0, "misses": 1 },
  "context_stats": {
    "demo.specs": {
      "preamble": { "chars": 2790, "est_tokens": 697 },
      "module_contract": { "chars": 7, "est_tokens": 1 },
      "repo_map": { "chars": 131, "est_tokens": 32 }
    }
  },
  "emitted_stubs": {
    "demo.specs": "/path/to/src/demo/specs.pyi"
  }
}
  • generated, skipped, refrozen — modules built, left fresh, and re-frozen by the semantic gate without a rebuild.
  • failed{module: reason}; a non-empty map sets ok: false and exits 3.
  • context_stats — per-module char/token estimates for each prompt block (preamble, system, module_contract, deps, package_context, repo_map, blueprint, skills_workspace_seeded). Trimmed above. The seeded-skills block also carries the legacy skills_workspace alias for this release.
  • emitted_stubs{module: pyi_path}, present only when .pyi stubs were written. stub_warnings appears only when a hand-authored stub was skipped.
  • needs_deps — present only when a module inlined logic for an undeclared dependency: {module: [marker, ...]}. Declare those deps to reuse the code.
  • advisories — present only when Codex flagged a logical issue while implementing: {module: [note, ...]}. Advisories never touch digests or exit codes.
  • newly_governed — present only when a magic_module scan governed a symbol that has no artifact yet: {module: [symbol, ...]}. Those modules build on the next run.

status

{
  "command": "status",
  "ok": true,
  "stale": ["demo.specs"],
  "stale_changes": { "demo.specs": "structural" },
  "fresh": [],
  "digests": { "demo.specs": "9c39cc26…f656d76a" },
  "orphans": [],
  "contracts": [],
  "contract_review": [],
  "tree": { "added": 1, "removed": 0, "restaled": 0 }
}

stale_changes classifies why each stale module changed — "structural", "prose", "fingerprint", or "re-stamp" when the next build resolves the module through the free re-stamp path (text output renders this value as re-stamp: free). orphans lists generated artifacts whose spec no longer exists. tree reports repo-map drift, or is null when the tree is in sync.

A TypeScript status also reports unbuilt and invalid artifacts plus structured diagnostics:

{
  "schema_version": 2,
  "command": "status",
  "ok": true,
  "fresh": [],
  "stale": ["ts:src/slug/index"],
  "stale_changes": {"ts:src/slug/index": "structural"},
  "unbuilt": ["ts:src/new/index"],
  "invalid": {
    "ts:src/bad/index": [
      {"code": "JAUNT_TS_INVALID", "message": "artifact hash does not match", "severity": "error"}
    ]
  },
  "diagnostics": [],
  "targets": {
    "ts": {
      "fresh": [],
      "stale": {"src/slug/index": "structural"},
      "unbuilt": ["src/new/index"],
      "invalid": {
        "src/bad/index": [
          {"code": "JAUNT_TS_INVALID", "message": "artifact hash does not match", "severity": "error"}
        ]
      },
      "orphans": []
    }
  }
}

check

{
  "command": "check",
  "ok": true,
  "blocked": [],
  "checked": [],
  "orphans": [],
  "magic": {
    "fresh": ["demo.specs"],
    "stale": {},
    "unbuilt": [],
    "orphans": []
  }
}

blocked/checked cover contract batteries. Orphaned artifacts are split by kind: contract-battery orphans are listed at the top-level orphans key (present whenever contracts are in scope), while generated-module, stub, and sidecar orphans are listed under magic.orphans (present whenever magic is in scope). A combined jaunt check emits both keys; --contracts-only emits only the top-level orphans, and --magic-only emits only magic.orphans. Any blocking drift — including an orphan of either kind — sets ok: false and exits 4. Before the first build the same project reports "unbuilt": ["demo.specs"] and exits 4.

In a version-2 TypeScript payload, magic is partitioned as magic.ts and includes invalid; targets.ts.magic repeats the same language-local state. Structured diagnostics remain available at the top level.

specs

{
  "command": "specs",
  "ok": true,
  "specs": [
    {
      "ref": "demo.specs:add",
      "module": "demo.specs",
      "qualname": "add",
      "source_file": "/path/to/src/demo/specs.py"
    }
  ],
  "dependency_graph": { "demo.specs:add": [] }
}

TypeScript specs adds the resolved projects, package owners, and static routes. The same spec list, routes, and dependency graph are repeated under targets.ts.

test

{
  "command": "test",
  "ok": true,
  "exit_code": 0,
  "refrozen": [],
  "generation_failed": {}
}

For Python, exit_code is pytest's exit code. A TypeScript payload instead carries the protected runner report under vitest at both the top level and targets.ts. ok is true only when the target runner passed and no generation failed. A generation failure exits 3; a pytest or Vitest failure exits 4.

sync

TypeScript sync is model-free. It lists each deterministic boundary artifact it wrote and repeats the same paths under targets.ts:

{
  "schema_version": 2,
  "command": "sync",
  "ok": true,
  "mirrors": ["src/slug/__generated__/index.api.ts"],
  "placeholders": ["src/slug/__generated__/index.ts"],
  "created_facades": ["src/slug/index.ts"],
  "failed": {},
  "targets": {
    "ts": {
      "mirrors": ["src/slug/__generated__/index.api.ts"],
      "placeholders": ["src/slug/__generated__/index.ts"],
      "created_facades": ["src/slug/index.ts"],
      "failed": {}
    }
  }
}

design

design returns a declaration-only patch. The default records but does not apply the proposal; a later --apply returns the same target with applied: true and makes no second model call.

{
  "schema_version": 2,
  "command": "design",
  "ok": true,
  "target": "ts:src/store/index#TokenStore",
  "patch": "*** Begin Patch\n\n*** End Patch",
  "applied": false,
  "diagnostics": [],
  "usage": {"api_calls": 1},
  "targets": {
    "ts": {"target": "src/store/index#TokenStore", "applied": false}
  }
}

jobs

{
  "command": "jobs",
  "ok": true,
  "jobs": [],
  "would_rebuild": { "demo.specs": "structural" }
}

jobs lists daemon job records; would_rebuild previews the modules the next build would regenerate and why.

clean

{
  "command": "clean",
  "ok": true,
  "dry_run": true,
  "would_remove": [
    "/path/to/src/demo/__generated__",
    "/path/to/src/demo/specs.pyi"
  ]
}

Without --dry-run, would_remove becomes removed.

migrate

{
  "command": "migrate",
  "ok": true,
  "applied": false,
  "actions": [
    {
      "migration": "legacy-stub-body",
      "path": "src/demo/specs.py",
      "module": "demo.specs",
      "symbol": "parse_email",
      "kind": "rewrite-stub-body",
      "classification": "re-stamp",
      "description": "demo.specs.parse_email: raise RuntimeError('spec stub') -> ... [re-stamp (free)]"
    }
  ]
}

applied is false in the default plan-only mode and true under --apply. Each entry in actions describes one planned or applied change; classification is re-stamp for an already-governed spec or newly-governs for a legacy body that would newly govern a symbol. Neither mode calls the model.

For jaunt migrate --language ts, the plan is worker-validated and includes its input-bound digest and any work that cannot be completed mechanically:

{
  "schema_version": 2,
  "command": "migrate",
  "ok": true,
  "language": "ts",
  "applied": false,
  "plan_digest": "sha256:…",
  "blocked": false,
  "actions": [
    {
      "migration": "typescript-artifacts-v1",
      "module_id": "ts:src/slug/index",
      "path": "src/slug/__generated__/index.api.ts",
      "kind": "api-mirror",
      "classification": "deterministic-rewrite",
      "description": "[deterministic-rewrite] repair API mirror: src/slug/__generated__/index.api.ts"
    }
  ],
  "diagnostics": [],
  "requires_rebuild": []
}

Possible TypeScript classifications are deterministic-rewrite, free-restamp, model-rebuild, and manual-intervention. A dry-run with a manual item still has ok: true because the analysis succeeded; an attempted apply returns ok: false, writes nothing, and includes an error. Successful applies also include applied_paths.

instructions

{
  "command": "instructions",
  "ok": true,
  "text": "# Jaunt — agent primer\n…",
  "project": {
    "root": "/path/to/project",
    "paths": { "source_roots": ["src"], "test_roots": ["tests"], "generated_dir": "__generated__" },
    "engine": "codex",
    "model": "gpt-5.6-sol",
    "reasoning_effort": "low",
    "semantic_gate": { "enabled": true, "model": "gpt-5.6-luna" },
    "repo_map": true,
    "freshness": { "total": 1, "fresh": 0, "stale": 1, "stale_modules": ["demo.specs"] }
  }
}

text is the full primer as one string. project is the live snapshot, or null when no jaunt.toml exists.

watch

watch emits one envelope per rebuild cycle (a watch envelope) rather than nested build or test documents.

Exit codes

CodeMeaning
0Success
2Config, discovery, or dependency-cycle error; bad or wrong-state job id
3Generation error
4Pytest/Vitest failure, contract check/reconcile block, stale tree --check, or a daemon job failed/parked during jobs wait
5Timeout while waiting for daemon jobs

Next: Output Locations.

On this page