simforge command keeps the same contract, so a script or an agent can drive it without parsing prose.
stdout: one JSON document
A command prints exactly one JSON document on stdout. JSON is the default;--json asks for it explicitly, and --pretty indents the same document for people. Nothing else is ever written to stdout.
stderr: a structured error
When a command fails it prints one JSON line on stderr:codeis stable: key your handling on it. Never parsereason, which is for people.hintsays what to do next, often the exact command.pathnames the input at fault, anddetailcarries structured context, when there are any.httpStatusandrequestIdare there when the SimForge host refused a request: quote therequestIdto support, which traces the request by it.
login also writes event lines ({"event": …}, never a code) on stderr while it waits: the URL and code a person must approve. runtime install and maps pull write {"event": "distribution.download.progress", "bytes": {"done": …, "total": …}, "percent": …} lines as they download, at each tenth of the archive and at least every 30 seconds. A command that waits on a cloud run (--cloud --wait, runs watch) writes {"event": "run.progress", "runId": …, "status": …, "jobs": [{"kind", "status", "progress", "queue"}], "elapsedSeconds": …, "message": …} when it first reads the run, whenever the run or a job changes, and at least every 30 seconds. Saving a scenario file as a hosted revision (the first --cloud run or dry run of its content) writes {"event": "revision.freeze", "draftId": …, "simulation": …, "elapsedSeconds": …, "message": …} when it starts and each time the host answers that its authoritative simulation (queued or running) is still going.
Exit codes
The command surface as data
simforge --help prints a compact index: every command with a one-line summary. simforge <command> --help prints one command: its arguments and flags with types, allowed values, ranges, defaults, which ones are required or exclude each other, and the global flags it takes. simforge help --json [command] prints the full schema of every command, or of one subtree. An unknown flag is an error (unknown_flag), except after the scenario of render, simulate and preview, whose trailing arguments are runtime options: check those against the command’s help. The same document is published at /docs/cli.json and rendered as the command reference.
A failure on stderr is one simforge.error/v1 line: {code, path?, reason, hint, detail?, httpStatus?, requestId?}. hint says what to do next; for an invalid value it quotes the allowed values or range and names the command’s --help. detail carries structured extras only.
A request the hosted API refuses (an HTTP 4xx answer, such as budget_exceeded or insufficient_scope) exits 2 with the API’s own code; a server failure exits 1.
Common error codes
Codes for a specific area are on its page: sign-in and runtime, cloud.