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
--jsonmode 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). --jsonis available onbuild,test,status,check,specs,jobs,sync,design,clean,migrate,watch,instructions,init,log,tree,cache, andskill.
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 setsok: falseand exits3.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 legacyskills_workspacealias for this release.emitted_stubs—{module: pyi_path}, present only when.pyistubs were written.stub_warningsappears 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 amagic_modulescan 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
| Code | Meaning |
|---|---|
0 | Success |
2 | Config, discovery, or dependency-cycle error; bad or wrong-state job id |
3 | Generation error |
4 | Pytest/Vitest failure, contract check/reconcile block, stale tree --check, or a daemon job failed/parked during jobs wait |
5 | Timeout while waiting for daemon jobs |
Next: Output Locations.