Skip to content

CI and AI agent workflows

The CLI behaves the same way on a laptop, in a CI runner, and inside an AI agent’s tool. Three things make that work:

  1. Environment-variable authentication so secrets never have to be written to disk on a shared runner.
  2. Tightly scoped API keys so a leaked credential is bounded by what it can do.
  3. Predictable output in non-interactive contexts (no banners, no prompts, no surprise prompts for --help).

This page covers how to wire each of those up.

Set two environment variables and skip zevcloud login entirely:

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

When ZEVCLOUD_API_KEY is set, the CLI:

  • Uses the env-var key for every request.
  • Never reads from the on-disk credential store.
  • Never writes credentials to disk.
  • Leaves any team configuration the user has set up locally untouched.

ZEVCLOUD_TEAM_ID is the team UUID and pairs with the API key. You can find it in the dashboard URL when viewing the team.

A minimal deploy step in a workflow:

.github/workflows/deploy.yml
name: Deploy to ZevCloud
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g @zevcloud/cli
- name: Deploy
env:
ZEVCLOUD_API_KEY: ${{ secrets.ZEVCLOUD_API_KEY }}
ZEVCLOUD_TEAM_ID: ${{ secrets.ZEVCLOUD_TEAM_ID }}
run: zevcloud deploy ${{ vars.SERVICE_ID }}

A few notes on this pattern:

  • Use secrets.ZEVCLOUD_API_KEY, not vars, for the key. GitHub masks values from secrets in logs but does not mask vars.
  • vars.SERVICE_ID is fine for the service id since it is not sensitive.
  • npm install -g @zevcloud/cli finishes in seconds and installs cleanly without local file writes.

For tool-using agents (Claude Code, agents wrapped around the OpenAI tool API, custom orchestrators), expose zevcloud as a tool and pass the env vars at process start.

The two most useful commands for an agent to call:

  • zevcloud services to discover what is deployed.
  • zevcloud deploy <serviceId> to push a change.

Generate a key with the deploy scope (see below). The agent can deploy and read state but cannot create or destroy services, change billing, or rotate keys. Tighter scope means a leaked key cannot do as much.

The CLI also exposes zevcloud version for diagnostics. An agent that hits an error and includes zevcloud version output in its report gives the maintainers everything they need to reproduce.

Pick the lowest scope that lets the workflow do its job. Scopes are fixed at key creation and cannot be promoted later.

ScopeUse it for
readHealth-check workflows, dashboards that just need to list state.
deployCI pipelines, AI agents. Can deploy, restart/stop, set env vars, verify domains. The right default for non-interactive use.
fullEquivalent to a human admin. Required for creating projects, services, environments, or running terminal commands inside containers. Use sparingly.

The full permission table is at Authentication.

What the CLI suppresses in a non-interactive run

Section titled “What the CLI suppresses in a non-interactive run”

When CI=true is set (most CI providers set this automatically) or when stdout is not a TTY:

  • The postinstall welcome banner is silent.
  • The “is there a newer version?” check is silent.
  • Color output is auto-disabled in environments that do not support ANSI.

To disable these explicitly even outside CI, set ZEVCLOUD_DISABLE_UPDATE_CHECK=true and ZEVCLOUD_DISABLE_POSTINSTALL=true.

API keys are issued and revoked from the dashboard at Settings → API Keys. To rotate:

  1. Generate a new key with the same scope.
  2. Update ZEVCLOUD_API_KEY in your CI secrets to the new value.
  3. Trigger a deploy to confirm the new key works.
  4. Revoke the old key in the dashboard.

The old key keeps working until you revoke it. There is no overlap requirement on our side.

If a single repository deploys to multiple teams (a monorepo serving more than one client, for example), use one set of env vars per job:

.github/workflows/deploy-multi-team.yml
jobs:
deploy-acme:
runs-on: ubuntu-latest
env:
ZEVCLOUD_API_KEY: ${{ secrets.ACME_KEY }}
ZEVCLOUD_TEAM_ID: ${{ vars.ACME_TEAM_ID }}
steps:
- run: npm install -g @zevcloud/cli
- run: zevcloud deploy ${{ vars.ACME_SERVICE_ID }}
deploy-beta:
runs-on: ubuntu-latest
env:
ZEVCLOUD_API_KEY: ${{ secrets.BETA_KEY }}
ZEVCLOUD_TEAM_ID: ${{ vars.BETA_TEAM_ID }}
steps:
- run: npm install -g @zevcloud/cli
- run: zevcloud deploy ${{ vars.BETA_SERVICE_ID }}

Each job uses the team’s own key. The CLI picks up whichever pair of env vars the job exports, with no per-machine state to worry about.