Scripting the Shorebird CLI
The Shorebird CLI can run without a person at the keyboard, in a CI job, a script, or a coding agent. This page covers how it behaves there, how to get machine-readable output, and how to run destructive commands safely.
Non-interactive mode
Section titled “Non-interactive mode”Shorebird stops asking questions when any of these is true:
- The global
--jsonflag is passed. - stdout or stdin isn’t a terminal, for example when output is piped to a file.
- A CI environment variable is set, such as
CI(with any value),BOT=true, or the variables set by GitHub Actions, Azure Pipelines, Travis, AppVeyor, Cirrus CI, AWS CodeBuild, or Jenkins.
In non-interactive mode, nothing waits for input:
- Some prompts use a default.
shorebird inituses your pubspec name as the app’s display name.shorebird patchwithout--release-versionbuilds the patch with the latest Flutter version to work out which release it belongs to, which can pick the wrong release or Flutter version. - Other prompts fail. When there’s no safe default, the command exits with
an error and a hint, usually naming the flag that provides the answer. For
example,
shorebird patchfails on native code changes unless you pass--allow-native-diffs, andshorebird initfails if you belong to several organizations and don’t pass--organization-id. - Progress spinners become plain lines when stdout isn’t a terminal or
--jsonis passed. Each step printsStarting ...and thenDone ...orFailed ...to stderr.
To keep a job from failing or guessing, pass every input as a flag: the app with
--app-id or --flavor, and the release with --release-version. For
shorebird patch, --release-version=latest targets the most recently updated
release. Authenticate with an API key in the
SHOREBIRD_TOKEN environment variable, since shorebird login needs a browser.
JSON output
Section titled “JSON output”Pass the global --json flag to get one JSON object on stdout instead of
human-readable text. --json also turns on non-interactive mode and removes
color codes.
These commands return structured JSON:
| Group | Commands |
|---|---|
shorebird account | whoami, apps, orgs |
shorebird apps | list, rename, delete, transfer |
shorebird channels | list, create, delete |
shorebird patches | list, info, set-track, rollback, rollforward |
shorebird releases | list, info |
| Other | shorebird doctor, shorebird flutter versions list, shorebird --version |
Other commands, such as shorebird release and shorebird patch, accept
--json and run non-interactively, but still print human-readable logs. Check
their exit code rather than parsing their output.
Success
Section titled “Success”A successful command prints an object with status set to success. The
command’s result is in data, and meta says which CLI version and command
produced it:
The fields inside data depend on the command.
Errors
Section titled “Errors”A failed command prints an object with status set to error and exits with a
non-zero code:
error.code is one of:
| Code | Meaning |
|---|---|
usage_error | Invalid or missing arguments. Exit code 64. |
interactive_prompt_required | The command needed an answer to a prompt. Exit code 64. |
fetch_failed | Shorebird couldn’t retrieve something it needed, such as an app. |
software_error | The command failed unexpectedly. |
process_exit | The command stopped with a non-zero exit code. |
When there’s a way to recover, error.hint says what to do, such as the flag to
add.
Destructive commands
Section titled “Destructive commands”Commands that delete something, shorebird apps delete and
shorebird channels delete, never prompt. Instead, they require
--confirm-name set to the exact name of what you’re deleting:
If the name doesn’t match, nothing is deleted and the command exits with a usage
error. Look the name up first, with shorebird apps list or
shorebird channels list, rather than hard-coding it.
Retrying rollbacks
Section titled “Retrying rollbacks”shorebird patches rollback and shorebird patches rollforward succeed when
the patch is already in the requested state, so a retried job doesn’t fail. Pass
--require-change to make the command exit with a usage error when nothing
changed, if your script needs to know. With --json, the data.changed field
reports the same thing:
See Roll back from the CLI for the command’s options, and What happens when a patch is rolled back? for what it does on devices.