JSON & Automation
The CLI is built to be scripted. Pass --json for machine-readable output, drive it from CI with a token, and discover any command’s schema at runtime.
The other reader of this output is an AI coding agent — deploying from Claude Code shows the JSON log commands it runs to check a deploy.
--json everywhere
Add --json to any command for structured output. The CLI also switches to JSON automatically when stdout isn’t a TTY.
lizard ps --json
lizard secrets list --json
lizard metrics --jsonStreaming commands
For streaming commands (lizard up without --detach), --json emits one JSON object per line:
{ "event": "log", "line": "Step 1/8 : FROM node:20" }
{ "event": "log", "line": "..." }
{ "event": "deployed", "status": "running", "url": "https://app.onlizard.com" }The build stream ends with done or error. After done, lizard up without --ci emits a final deployed, failed, or deploying event with status. Only deployed carries url (which may be null). After error no final event follows, and the command exits 1.
logs --json is a snapshot, not a stream
lizard logs --json returns the last 200 lines (override with --tail N, max 1000) and exits. Don’t wait on it expecting more output. For a specific incident, use --restart latest or --restart <id>.
Errors
In JSON mode a failed command prints one error object on stdout and exits with a nonzero code (see the table under CI / headless usage):
{
"error": {
"code": "ERROR",
"status": null,
"message": "Project \"my-projet\" not found.",
"body": null
}
}code is the API’s error code, a CLI code such as NOT_AUTHENTICATED or PROJECT_DELETED, or ERROR for a generic failure; flag mistakes give codes like commander.unknownOption. status is the HTTP status, or null when the CLI failed before the API answered. body holds the API’s response, or null.
With no sign-in, commands fail with NOT_AUTHENTICATED and exit 2. Outside CI, body.login holds sign-in links (authUrl, authUrls) and an instruction: an agent can give the user the link, then run the command again.
Schema discovery
Dump any command’s exact arguments, options, and exit codes:
lizard --help --json # whole tree + global flags + exit codes
lizard service set --help --json # one commandThe response shape is { cli, version, agents, command: { arguments, options, subcommands }, globalOptions, exitCodes }. Because it’s generated from your installed binary, it always matches your version — prefer it over hard-coding flags.
CI / headless usage
Authenticate with a token and link the project explicitly. Otherwise headless up deploys into your account’s default project:
# Set LIZARD_TOKEN through your CI secret store.
lizard init --name my-project
lizard up --ci --service api --detach # creates api on the first runCheck exit codes to branch your pipeline:
| Code | Meaning |
|---|---|
0 | success |
1 | generic error |
2 | auth — token missing/expired |
3 | not found: the API has nothing with that ID |
4 | timeout |
5 | cancelled |
A project or service name that matches nothing exits 1. lizard run, lizard sandbox exec and lizard sandbox ssh exit with the command’s own code (127 when run can’t find the command).
--wait makes redeploy wait for the build and for the new deploy to become ready. Without it, JSON mode exits 0 as soon as Lizard accepts the build request.
if lizard redeploy --service api --wait --json; then
echo "Deploy succeeded"
else
status=$?
echo "Deploy failed with code $status" >&2
lizard logs --build --json || true
exit "$status"
fiUpdated