CLI overview
Install the flitz CLI and learn the conventions every command shares: global options, output streams, --json, and exit codes.
flitz is the one tool you install. It signs you in, downloads and pins the
Flitz SDK for a project, builds a bundle from that project, publishes it, lists
and manages what your organization has published, and tells you what is set up
and what is not. There are no archive URLs to copy and no PATH juggling required to build
a bundle.
The CLI itself is free to obtain and needs no license. Only the actions behind it are gated: everything that talks to the Flitz service — listing and downloading SDK releases, resolving the loader plugins and their credentials, publishing, listing and managing publishes, tracks, and apps, and managing the API key — checks your organization's license when it runs.
Supported hosts
The CLI ships for linux-x64 and macos-arm64 (Apple Silicon). Other hosts
are not yet supported: on them the installer stops with
flitz: unsupported host: <os> <arch> and points you at the download page.
Install
The one-line installer detects your platform, downloads the matching
pre-compiled binary, verifies its SHA-256, and installs flitz into
${XDG_BIN_HOME:-$HOME/.local/bin}:
curl -fsSL https://download.flitz.dev/install.sh | shIt needs curl or wget, and sha256sum or shasum. When the install
directory is not on your PATH, the script says so. Add it, then confirm the
install:
export PATH="$HOME/.local/bin:$PATH"
flitz --versionThe binary is self-contained. It needs no Dart or Flutter SDK on the machine — it is the bootstrap that installs one.
Prefer to install by hand? The download page at
download.flitz.dev lists each host's binary
with its SHA-256 and a copy-pasteable verify command (sha256sum -c on Linux,
shasum -a 256 -c on macOS). Download, verify, chmod +x, and move it onto
your PATH as flitz.
Update
Re-run the install script. It always installs the newest published CLI.
When a newer CLI exists, the CLI tells you once a day, after your command has
finished, and never in CI or under --json. flitz status reports the same
fact on demand. See Configuration → Update notices
for how to silence it.
The happy path
flitz login # once per machine
cd /path/to/your/flutter/app
flitz sdk use latest # pin an SDK for this project and download it
flitz publish # build a bundle and get a link + QR codeflitz --help prints the same three steps. Run flitz status at any point to
see what is set up and what to do next. For the full walkthrough, including
embedding the loader in your app, see Getting started.
Global options
Every option is accepted before or after the subcommand.
| Option | Effect |
|---|---|
--version | Print only the CLI's own version on stdout and exit 0, whatever else is on the command line. |
-v, --verbose | Add stack traces to errors and stream build-tool output live. One level only; -vv is a usage error. See Verbose output. |
-y, --yes | Answer yes to every confirmation prompt without showing it. See Prompts and --yes. |
--json | Emit the result as one JSON document on stdout. Accepted by ten commands; a usage error elsewhere. See Machine-readable output. |
--no-color | Force plain output, overriding terminal detection, FORCE_COLOR, and config.yaml. |
-h, --help | Help for the CLI or the named command. flitz help <command> is the same as flitz <command> --help. |
Pass dart-defines separated from -D
The CLI spots -v anywhere in a short-option argument. An attached
-DKEY=value that contains a lowercase v turns on verbose error output,
and a second v — in the same value, another define, or a real -v — fails
the command with the one-verbosity-level usage error. Write -D KEY=VALUE
(separated) or --dart-define=KEY=VALUE instead.
Output conventions
Two streams
stdout carries results; stderr carries everything else. A result is the
thing you ran the command to obtain: an SDK path, a plugin version, a JSON
document, the published URLs, a completion script, the version string, the
status report. Progress, timings, spinners, warnings, prompts, errors, and
hints all go to stderr.
So every command works in a pipeline. flitz publish > urls.txt captures the
result block — a blank line and the four labelled links — while the terminal
still shows the progress; flitz sdk path, flitz plugins configure --version-only, and flitz completions zsh each emit exactly their result.
Rich and plain output
There is one switch, rich versus plain, and it governs color, glyphs, and
animation together. Rich output uses color, the Unicode verdict glyphs
(✓ ⚠ ✗ ?), and in-place spinners. Plain output uses no escape sequences at
all: ASCII verdict words ([ok] [warn] [fail] [unknown]) and one appended
line per state change, so a CI log reads as a clean chronological record.
The mode is resolved once per stream, in this order:
--no-color→ plain.NO_COLORset and non-empty → plain (it beatsFORCE_COLOR).FORCE_COLORset and non-empty → rich.config.yamlcolor: always→ rich;color: never→ plain.- Otherwise rich when the stream is a terminal and
TERMis neither unset nordumb; plain otherwise.
Because it is per stream, redirecting stdout does not flatten the progress on stderr.
Verdict markers
Four markers are the CLI's whole visual vocabulary. They prefix status rows,
errors, and warnings alike.
| Verdict | Rich | Plain | Meaning |
|---|---|---|---|
| ok | ✓ | [ok] | Satisfied. |
| advisory | ⚠ | [warn] | Works today; worth attention. Never blocks. |
| blocking | ✗ | [fail] | Prevents building or publishing. |
| unknown | ? | [unknown] | Could not be determined — the service is out of reach, there is no credential to ask with, or the service rejects the stored sign-in. See flitz status. |
Errors and hints
Most failures are one lowercase sentence saying what went wrong, then one
indented → line per next action — usually the command that fixes it:
✗ the pinned SDK <tag> is not installed
→ run `flitz sdk use <tag>`
→ or pass --yesA few usage errors are a single plain line, and argument-parsing errors print the parser's message followed by the command's usage. Either way the exit code is the contract. Compiler output is passed through verbatim, never reformatted. The full contract, the six exit codes, and the bug-report capture are on Exit codes and messages.
Prompts and --yes
A prompt is asked only when stdin and stderr are both terminals. --yes (or
assume_yes: true in config.yaml)
answers every prompt affirmatively without displaying it. There are exactly
six prompts:
| Prompt | Default | Non-interactive without --yes |
|---|---|---|
publish: download the pinned SDK now? | yes | Usage error (exit 1); the hint names flitz sdk use and --yes. |
publish: create app <key>? Asked only when --app or flitz.yaml app: names a key your organization does not have yet. | no | Usage error (exit 1); the hint names --yes. |
sdk use: download the SDK just pinned? | yes | Downloads — you asked for it. |
publishes delete: delete publish <id>? | no | Usage error (exit 1); the hint names --yes. |
apps delete: delete app <key>? | no | Usage error (exit 1); the hint names --yes. |
apikey revoke: revoke the organization key? | no | Usage error (exit 1); the hint names --yes. |
There is no setup wizard. Onboarding is flitz status: it reports what is
missing, and each finding says what to do next.
Machine-readable output (--json)
--json makes a command emit its result as a single JSON object on stdout and
nothing else. Exactly these ten commands accept it:
| Command | Document |
|---|---|
status | cli_version, host, checks[] keyed by stable identifiers, blocking, advisory. |
sdk list | { "sdks": [ { "tag", "installed", "pinned" } ] } |
sdk releases | { "releases": [ { "tag", "installed", "pinned" } ] } |
sdk path | { "tag", "path", "installed" } |
plugins configure | { "version", "target_sdk_tag", "repositories": { "maven", "swift", "cocoapods" } } |
apikey status | { "present", "name", "obfuscated_value", "created_at", "last_used_at" } |
publish | { "id", "page_url", "deeplink", "bundle_url", "app", "track", "track_url" } |
publishes | { "publishes": [ … ] } — the publish history, newest first. |
tracks | { "fallbackTrackKey", "tracks": [ … ] } — an app's tracks, each with its latest publish and "latest" link. |
apps list | { "apps": [ … ] } — your organization's apps, ordered by key. |
Passing --json to any other command is a usage error (exit 1). The contract:
- stdout carries exactly one document — no progress, no warnings, no banner. Everything human-facing goes to stderr or is suppressed, including the ambient update notice.
- On failure the command emits no JSON. It reports the error on stderr and exits non-zero. Check the exit status first; parse stdout only on 0.
- Documents are objects, never bare arrays, and schemas grow additively:
fields are added, never removed or repurposed.
statuskeys its checks on identifiers, not prose. - No document ever contains a plaintext API key, a token, or a signed upload
URL.
apikey status --jsoncarries the obfuscated value only.
sdk path and plugins configure --version-only also print a bare string
without --json: the bare form is what a shell substitution wants, the JSON
form is what a tool wants. --version-only wins over --json: together they
print the bare version.
Commands
| Command | License | Purpose |
|---|---|---|
flitz login | — | Sign in from a browser; stores a credential on this machine. |
flitz logout | — | Remove the stored credential from this machine. |
flitz status | — | Health check of your account, project, plugins, and CLI. Always exits 0. |
flitz sdk install / use / releases | required | Download, pin, and list Flitz SDK releases. |
flitz sdk list / path / remove | — | Local cache reads and deletes; no credential needed, and they work offline. |
flitz publish | required | Build a .flitz bundle from the project and publish it. |
flitz publishes | required | List your organization's publish history, newest first; --app and --track filter it. |
flitz publishes delete <id> | required | Delete one publish. Its links stop working. |
flitz tracks | required | List an app's tracks, each with its latest publish and "latest" link. |
flitz apps list | required | List your organization's apps. |
flitz apps rename / archive / unarchive / delete / restore | required | Rename an app, stop or resume its publishes, delete it, or restore it within 30 days. |
flitz plugins configure / credentials | required | Resolve the loader-plugin version and store the repository credentials. |
flitz apikey create / rotate / revoke / status | required | Manage the organization's single CI API key. |
flitz completions <shell> | — | Print a static completion script for bash, zsh, or fish. |
"Required" means the command needs a credential — an interactive session from
flitz login or the FLITZ_APIKEY environment variable — and the
organization's license must be active. Each licensed command checks the
license as part of its own request, so there is no separate check to run
first. The mutations — apikey create/rotate/revoke, publishes delete,
and every apps subcommand except list — additionally require an interactive
session and refuse an API key.
Members, apps, the API key, billing, and the publish history are also managed in the Flitz portal.
Where the CLI keeps things
| Path | Contents |
|---|---|
~/.config/flitz/credentials.json | Your sign-in credential, mode 0600. Written by login, refreshed automatically, deleted by logout. |
~/.config/flitz/config.yaml | Optional preferences you author; the CLI never writes it. See Configuration. |
~/.cache/flitz/sdk/<tag>/ | The SDK cache, one directory per release tag. |
~/.cache/flitz/update-check.json | Throttle state for the update notice. |
<project>/flitz.yaml | The project's SDK pin, plus optional app:, track:, and schema: publish settings, committed to your repository. See Configuration → flitz.yaml. |
~/.config and ~/.cache follow XDG_CONFIG_HOME and XDG_CACHE_HOME when
those are set to absolute paths. The full list, including the files
flitz plugins credentials --write updates, is in
Configuration → Filesystem locations.
There is no log file: diagnostics are produced on demand by -v and by the
bug-report capture.
flitz status
Start here when anything is unclear: every check and what each verdict means.
flitz publish
Flags, output streams, --json, and the on-demand SDK download.
Exit codes and messages
The six-code contract for scripts, and the bug-report capture.
Troubleshooting
Each failure class mapped to its remedy.