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.
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 teamzevcloud login
# add a client team without losing the firstzevcloud login
# see what is configuredzevcloud team list
# deploy to the client team without changing your defaultzevcloud --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 typezevcloud restart 9c4f1e2b-... # recycle the containerzevcloud stop 9c4f1e2b-... # stop, preserve storage and configA 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:
- The config file is locked to
0600so other local users on a shared machine cannot read your API keys. zevcloud config --api-urlrejects plaintext HTTP. API keys never go over the wire in cleartext.- The CLI checks the npm registry once a day for a newer version and prints a small notice when one ships. Set
ZEVCLOUD_DISABLE_UPDATE_CHECK=trueto silence it. zevcloud versionprints installed version, latest known, Node, and platform. Paste it into bug reports.zevcloud helpandzevcloud help <command>both work. Not every user remembers the--helpconvention, and AI agents read the barehelpcommand more reliably.
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/cliIf something behaves wrong, file an issue with zevcloud version output attached and the team will know what to look at.
See you next post.