Flitzdocs
CLI

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

It 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 --version

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

flitz --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.

OptionEffect
--versionPrint only the CLI's own version on stdout and exit 0, whatever else is on the command line.
-v, --verboseAdd stack traces to errors and stream build-tool output live. One level only; -vv is a usage error. See Verbose output.
-y, --yesAnswer yes to every confirmation prompt without showing it. See Prompts and --yes.
--jsonEmit the result as one JSON document on stdout. Accepted by ten commands; a usage error elsewhere. See Machine-readable output.
--no-colorForce plain output, overriding terminal detection, FORCE_COLOR, and config.yaml.
-h, --helpHelp 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:

  1. --no-color → plain.
  2. NO_COLOR set and non-empty → plain (it beats FORCE_COLOR).
  3. FORCE_COLOR set and non-empty → rich.
  4. config.yaml color: always → rich; color: never → plain.
  5. Otherwise rich when the stream is a terminal and TERM is neither unset nor dumb; 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.

VerdictRichPlainMeaning
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 --yes

A 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:

PromptDefaultNon-interactive without --yes
publish: download the pinned SDK now?yesUsage 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.noUsage error (exit 1); the hint names --yes.
sdk use: download the SDK just pinned?yesDownloads — you asked for it.
publishes delete: delete publish <id>?noUsage error (exit 1); the hint names --yes.
apps delete: delete app <key>?noUsage error (exit 1); the hint names --yes.
apikey revoke: revoke the organization key?noUsage 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:

CommandDocument
statuscli_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. status keys its checks on identifiers, not prose.
  • No document ever contains a plaintext API key, a token, or a signed upload URL. apikey status --json carries 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

CommandLicensePurpose
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 / releasesrequiredDownload, pin, and list Flitz SDK releases.
flitz sdk list / path / remove—Local cache reads and deletes; no credential needed, and they work offline.
flitz publishrequiredBuild a .flitz bundle from the project and publish it.
flitz publishesrequiredList your organization's publish history, newest first; --app and --track filter it.
flitz publishes delete <id>requiredDelete one publish. Its links stop working.
flitz tracksrequiredList an app's tracks, each with its latest publish and "latest" link.
flitz apps listrequiredList your organization's apps.
flitz apps rename / archive / unarchive / delete / restorerequiredRename an app, stop or resume its publishes, delete it, or restore it within 30 days.
flitz plugins configure / credentialsrequiredResolve the loader-plugin version and store the repository credentials.
flitz apikey create / rotate / revoke / statusrequiredManage 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

PathContents
~/.config/flitz/credentials.jsonYour sign-in credential, mode 0600. Written by login, refreshed automatically, deleted by logout.
~/.config/flitz/config.yamlOptional 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.jsonThrottle state for the update notice.
<project>/flitz.yamlThe 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.

On this page