CLI ReferenceJSON & Automation

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 --json

Streaming 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 command

The 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 run

Check exit codes to branch your pipeline:

CodeMeaning
0success
1generic error
2auth — token missing/expired
3not found: the API has nothing with that ID
4timeout
5cancelled

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"
fi

Updated