PRODUCT

The Stratum CLI: designing a tool used by 80,000 teams

A CLI is often the first touch point developers have with your platform, and first impressions compound. Every design decision we made while building the Stratum CLI from scratch — for 80,000 teams across 140 countries — and what we would do differently today.

Stratum CLI

When we shipped the first public version of the Stratum CLI, the most common piece of feedback was blunt: it does too much. Developers want tools that do one thing and compose well with the rest of their shell, not a GUI crammed into a terminal. That feedback shaped every subsequent release.

Design principle 1: nouns and verbs, not actions

Most CLI tools are verb-first: deploy, rollback, restart. We started that way too, and ended up with 60 top-level commands that were impossible to discover. The v2 rewrite adopted a noun-first structure: stratum app deploy, stratum app rollback, stratum db connect, stratum logs tail. Every command now has exactly two segments — resource and action — which means tab-completion alone is enough to learn 80 % of the CLI without reading the docs.

Design principle 2: the output is for humans and machines

Every Stratum CLI command supports three output modes:

  • --format table (default in a TTY): colour-coded, aligned, with status icons — readable in under two seconds.
  • --format json: machine-readable, one object per line (NDJSON) for safe piping into jq or custom scripts.
  • --format quiet: prints only the primary identifier (e.g. the deploy ID) with no decoration — designed for shell scripting where you want to capture and pass on a single value.

The format is detected automatically from whether stdout is a TTY. Scripts that pipe stratum app list into grep always get the quiet format; developers running the command directly get the table. This rule — honour the terminal context — eliminated 90 % of the script-vs-human output complaints.

Design principle 3: errors must be actionable

An error message that says Request failed: 403 is not an error message — it is a bug report waiting to happen. Every Stratum CLI error follows a three-part structure: what went wrong, why it likely happened, and what to do next. Example:

Error: deploy failed — image registry.stratum.io/acme/api:v2.3.1 not found.
Cause: the image tag was pushed to a private registry the service account cannot pull from.
Fix: run stratum registry grant acme/api --service-account deploy-sa to add pull permission, then retry.

Design principle 4: context awareness reduces friction

The CLI reads a .stratum/config.yaml from the project root and infers defaults: the active app, the target environment (staging vs production), and the region. A developer in a repo that has this file can run stratum deploy with no flags at all. Flags are available to override every default, but they are never required for the 80 % case. This is the principle we call sensible defaults, full control.

What we would do differently

  • Ship tab-completion on day one. We added it in v1.4, eight months after launch. It is now the most-used feature. Every developer who onboarded before v1.4 had a worse first week than they needed to.
  • Invest in interactive mode earlier. stratum init --interactive now walks developers through project setup with prompts and sane defaults. It was the most-requested feature for the first year and we kept postponing it for "real" features.
  • Never break flags silently. We renamed --env to --environment in v2.0 without a deprecation warning. The support tickets ran for six months.

Build on the same network

Deploy to 30 regions on the anycast edge — free to start.

Start building free
Stay in the loop

Engineering deep-dives, monthly

Join 40,000 builders getting our best writing on infrastructure, performance, and reliability. No spam, unsubscribe anytime.