ZevCloud ZevCloud Blog

Blog

How we designed the ZevCloud CLI

Three design choices behind the ZevCloud CLI: every team you belong to in one place, deploy commands that route by service type, and auth that skips the credentials file.

DAN DAN 5 min read
A terminal window showing zevcloud login and a cross-team deploy with a "Deployed acme-corp/api" badge, next to a "Three design choices" panel listing multi-team in one place, deploy by service type, and no file on disk. ZevCloud mark in the top-left, "Engineering · CLI design" tag in the top-right.

A CLI is a small surface, but the design choices show up the moment you use it for real work. Most deploy CLIs I have used quietly assume a single team, a single service type, and a credentials file you can leave on your laptop. None of those are universally true, and each assumption costs the user time when it breaks.

When we built the ZevCloud CLI, we made three different choices. Each one came from work we were doing on our own dashboard, where the assumptions in older tools kept getting in the way.

Developers belong to multiple teams

API keys on ZevCloud are scoped to a team, which is the right call. A key should not have ambient authority across an entire org. The mistake most CLIs make is also assuming the install belongs to one team. It does not. A developer is a person, not a tenant. Someone who freelances on the side and ships at a day job is one person who needs two different team contexts. Forcing them to log out and log back in to switch is friction with no security benefit.

The ZevCloud CLI keeps every team you belong to in one place. zevcloud login adds a team. zevcloud team switch changes the active default. --team <name> overrides for a single command without touching the default at all.

# add personal team
zevcloud login
# add a client team without losing the first
zevcloud login
# see what is configured
zevcloud team list
# deploy to the client team without changing your default
zevcloud --team acme-corp deploy 9c4f1e2b-...

In practice the per-command override is what gets used most. Switching contexts mid-shell is rare. Running one specific command against a non-default team is constant.

A deploy command that knows what type of service it is

ZevCloud has four service types: web apps, WordPress sites, databases, and static sites. They have very different lifecycles. A web app gets rebuilt from a Git pipeline. A WordPress site is provisioned once, and after that files are pushed via SFTP or wp-admin. A database has no concept of a build. A static site is files plus a small container.

A deploy command that pretends these are all the same will fail in unhelpful ways. Run it against a database and most CLIs return an error that does not tell the user what to do instead.

The ZevCloud CLI looks at the service type first and routes correctly. For a web app it triggers a fresh build. For a WordPress site that has not been provisioned yet, it provisions. For a running WordPress site, it tells you the site is already live and points you at restart instead. For a database, it suggests restart or stop.

zevcloud deploy 9c4f1e2b-... # works for any service type
zevcloud restart 9c4f1e2b-... # recycle the container
zevcloud stop 9c4f1e2b-... # stop, preserve storage and config

A CLI should make it impossible for the user to be wrong about the obvious thing.

Authentication that does not require a file on disk

In CI runners and AI agent workflows, the worst thing a CLI can do is force you to write secrets to a file on a shared host. Most CLIs do this anyway, and you end up with zevcloud login running against a tty that is not actually a tty, or a shell script that prints your API key to the build log when it fails.

Two environment variables bypass the credential store entirely:

export ZEVCLOUD_API_KEY=sk_live_...
export ZEVCLOUD_TEAM_ID=<team-id>
zevcloud deploy <serviceId>

When ZEVCLOUD_API_KEY is set, the CLI uses it for every command and never reads or writes the on-disk credential store. GitHub Actions and similar runners are the obvious fit. Claude Code or any tool-using agent is the second fit. Same flow on a laptop and in a runner means one less failure mode to debug.

A few smaller details

The choices above shape what the CLI can do. A few smaller decisions shape how it feels:

Where the CLI fits

The dashboard at zevcloud.net is where most things start: you create a project, link a Git repo, pick a plan, watch a deploy run. The CLI is for the work that comes after. It is the surface where you push fixes, restart things, set env vars, tail logs, and deploy across teams without context-switching out of the terminal you were already in.

The full reference is at docs.zevcloud.net/cli. Install with:

npm install -g @zevcloud/cli

If something behaves wrong, file an issue with zevcloud version output attached and the team will know what to look at.

See you next post.

← All posts