SOLWYN

Scripting and CI

The CLI's machine contract — two output formats, schema-bearing JSON, frozen exit codes, and budget gates for CI.

Every command that returns data speaks a stable machine contract: one line of schema-tagged JSON on stdout, and an exit code drawn from a permanently frozen set. Scripts and CI pipelines can depend on both. This page is the contract.

Two formats

Output is either table or json. Those are the only two — there is no plain format.

  • table is the default: human-readable, aligned columns, color when the stream is a terminal.
  • json is the machine format: one compact object per invocation.

Select JSON with any of --json, --format json, the SOLWYN_FORMAT=json environment variable, or format = "json" in your config file. When more than one is present, the flag wins over the environment variable, which wins over config.

Passing --json together with --format table contradicts itself and is a usage error (exit 2). --json with --format json is redundant but accepted.

The JSON envelope

Success is a single line on stdout — a compact JSON object whose first field is always schema:

{"schema":"solwyn.budget-status.v1","project_id":"proj_abc12345","utilization_pct":41.2}

One object per invocation, newline-terminated, never colored. The schema field names the payload's shape and version; the fields after it are that command's data.

Errors are a single line on stderr, using one fixed schema:

{"schema":"solwyn.error.v1","code":"not_found","message":"Project not found.","hint":null,"detail":null}

The error object always carries these fields: code (a stable machine string), message (human-readable), hint (a suggested next step, or null), and detail (structured context, or null). Because data goes to stdout and errors go to stderr, you can redirect and parse the two independently.

Schema names are stable and additive-only. Within a .v1 payload, fields are only ever added — never renamed, retyped, or removed — so a parser written today keeps working. Real success schemas include solwyn.status.v1, solwyn.costs.v1, solwyn.budget-status.v1, solwyn.budget-check.v1, and solwyn.init.v1. The config commands are the exception: they emit plain text and ignore --json, so don't script against JSON from solwyn config get.

Color

Human output is colored only when the stream is a terminal. Disable it with --no-color or by setting the NO_COLOR environment variable — either one turns color off for both stdout and stderr. JSON output is never colored, so it is always safe to pipe.

Exit codes

The CLI's exit codes are permanently frozen across all major versions, so a pipeline can branch on them without pinning a CLI release:

CodeMeaning
0Success
1Generic or API error
2Usage error — bad flags, conflicting options
3Authentication error
4Budget denied
5Not found

Gating a deploy on budget

solwyn budget status --max-utilization 80 prints the project's budget as usual, then exits 4 when utilization is at or above 80 percent. Drop it into a pipeline step to block a deploy while a project sits near its cap — the status still prints, so the job log shows why it stopped.

Terminal
# Fail the job when the project is at or over 80% of its budget.
solwyn budget status --json --max-utilization 80

Guarding un-instrumented spend

When your code makes a provider call that the Solwyn SDK does not already wrap, reserve budget before the call and settle it after:

Terminal
# 1. Reserve before the un-instrumented call.
solwyn budget check --json \
  --provider openai --model gpt-4o --estimated-input-tokens 1200

# 2. Make the call yourself, then settle with the real token counts.
solwyn budget confirm --json \
  --reservation-id "$RID" --call-id "$CALL_ID" \
  --provider openai --model gpt-4o \
  --input-tokens 1180 --output-tokens 320

budget check exits 4 when the reservation is denied — treat that as "do not spend". If the check returns an allowed result with a null reservation, there is nothing to settle, so skip confirm.

Exit 4 has two distinct triggers: a denied budget check, and the budget status --max-utilization gate. Same code, two meanings — read the surrounding output to tell them apart.

Never run this loop around a call the SDK already instruments — that double-counts the spend. See Agent integration for the full rule and solwyn budget for every option.

On this page