Scripting and CI
The CLI keeps result data on stdout and progress or diagnostics on stderr. Scripts can capture a value or pipe JSON without scraping human-facing status messages.
JSON output
Add --json to a data-producing command:
j17 whoami --json
j17 instance list --json
j17 key list --json
j17 spec deploy --json
For example, with jq:
instance_id="$(j17 instance list --json | jq -r '.[] | select(.name == "my-app") | .id')"
raw_key="$(j17 key create ci --scope deploy --env test --json | jq -r '.raw_key')"
Action-only commands such as logout, use, and successful local spec validate have no result body, so --json produces no stdout on success.
Non-interactive authentication
For an ephemeral job, provide a control-plane bearer token without writing credentials:
J17_TOKEN="$CONTROL_PLANE_TOKEN" \
j17 instance list --json
J17_TOKEN is used only by that process. It is neither persisted nor refreshed.
For a persistent runner, use a dedicated profile and run the browser-assisted login once:
J17_PROFILE=ci j17 login --no-browser
J17_PROFILE=ci j17 use my-app --env staging
Confirm destructive commands explicitly
Non-interactive input defaults to "no." Pass --yes only where the pipeline has already made the decision:
j17 key revoke "$KEY_ID" --yes
j17 spec deploy --instance my-app --env prod --yes
--force is never accepted for production spec deployment, even with --yes.
Exit codes
The CLI uses stable exit codes so automation does not need to parse error strings:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Generic local or transport failure |
2 |
Invalid usage, unknown flag, missing argument, or declined confirmation |
3 |
Login required or HTTP 401 |
4 |
Forbidden (HTTP 403) |
5 |
Validation/not-found failure, including HTTP 404 or 422 |
6 |
Conflict (HTTP 409) |
7 |
Other HTTP client error |
8 |
Server error (HTTP 5xx) |
Errors are written to stderr. Server errors include the request ID when one is returned; include that ID when contacting support.
if output="$(j17 spec deploy --instance my-app --env staging --json)"; then
printf '%s\n' "$output"
else
status=$?
echo "deploy failed with exit code $status" >&2
exit "$status"
fi
Environment isolation
Use explicit profile and target variables in CI rather than depending on a developer's default selection:
export J17_PROFILE=ci
export J17_CONTROL_URL=https://console.j17.dev
j17 spec deploy ./j17.spec.json \
--instance "$J17_INSTANCE" \
--env staging \
--json
For API-key creation and spec deployment, the CLI refuses to invent an environment. If neither --env nor the active profile contains one, the command exits with code 2 before making a request.