Source: https://docs.cumuluslabs.io/sdk-cli
Content version: b5cf27bd

# Cumulus CLI

The `cumulus` CLI takes an agent from local definition to a published version. It saves the reviewed plan and checkpoints so later commands can detect source changes, concurrent Studio edits and interrupted work.

Use the CLI from your pinned project installation: `./node_modules/.bin/cumulus`. Compile TypeScript first. The [tutorial](/docs/sdk-tutorial) supplies a stable `cumulus/project.mjs` entrypoint that exports `{ project, bindings }` from the compiled code.

## Validate locally

From the tutorial project:

```bash
npm run build
./node_modules/.bin/cumulus validate --project cumulus/project.mjs --agent service_guide
```

Validation composes the definition and checks it against the packaged API schema. It makes no API requests. Because the CLI imports your project, that project's bindings may still require environment values. Successful local validation is followed by server validation when publishing.

`--project` defaults to `cumulus/project.js`. `--agent` selects an agent key; omit it only when the project has one agent. The CLI selects at most one integration per agent. Use the authoring library when you need to choose integrations explicitly.

## Review and apply a plan

Set `CUMULUS_API_URL` to the API origin for your development workspace and inject its `CUMULUS_API_KEY`. Then preview:

```bash
./node_modules/.bin/cumulus preview --project cumulus/project.mjs --agent service_guide
```

Preview reads remote state, saves `preview.json` and prints the effective tenant, draft revision and proposed changes. Review those values before applying:

```bash
./node_modules/.bin/cumulus apply --project cumulus/project.mjs --agent service_guide
```

Apply consumes that saved plan. If you changed the source after preview, preview again. If someone changed the remote draft, follow [the Studio backport workflow](/docs/sdk-lifecycle#backport-a-studio-change) instead of overwriting their work.

## Publish, then change routing deliberately

Create a test-only publication first:

```bash
./node_modules/.bin/cumulus publish --project cumulus/project.mjs --agent service_guide
```

This saves an immutable publication in the receipt without advancing the ordinary head. Use the runtime library with `test: true` to test that version. A phone test still places a real call.

When you are ready to advance the ordinary callable version, publish with `--live`:

```bash
./node_modules/.bin/cumulus publish --project cumulus/project.mjs --agent service_guide --live
```

This creates a new ordinary publication from the unchanged draft; it does not convert the earlier test-only version. If the draft or head changed in the meantime, resolve that conflict before publishing.

Publishing does not assign phone numbers. After checking the deployed tool endpoints and reviewing the intended dedicated number, assign the integration's routes:

```bash
./node_modules/.bin/cumulus route --project cumulus/project.mjs --agent service_guide
```

Route requires the receipt's publication to be the current head. Inspect every returned assignment; multiple number updates are separate operations. Carrier/trunk configuration remains part of workspace setup.

## Place a call

The CLI call path uses the saved publication and creates an ordinary phone request. Use an ordinary publication from `publish --live`; promoting a test-only publication does not change its classification.

The destination below is fictional. Replace it with an authorized test recipient and review the request before running:

```bash
./node_modules/.bin/cumulus call --project cumulus/project.mjs --agent service_guide \
  --to +12025550123 --confirm-real-call
```

The CLI saves `call-command.json` before sending and writes admission to `call-result.json`. Repeating this command reuses the saved request and idempotency key. It refuses a different recipient while that command exists. To intend a new call, deliberately archive the earlier command and result before preparing another.

Use [the runtime library](/docs/sdk-runtime) for `test: true`, dynamic variables, metadata or an explicit `from`. Fetch transcript, effects, recording and analysis separately after admission.

## Keep recovery files across builds

State lives beside the selected entrypoint:

```text
cumulus/.cumulus/<effective-tenant>/<project-key>/<agent-key>/
  preview.json
  receipt.json
  studio-backport.json
  call-command.json
  call-result.json
```

The location is derived from the entrypoint: selecting `dist/project.js` puts state under `dist/.cumulus`. Deleting `dist` would delete it. The tutorial's stable `cumulus/project.mjs` avoids that problem.

Ignore `.cumulus` directories in version control. Keep their private contents and backups: they can contain prompts, endpoint configuration and call recipients. The CLI writes state with mode 0600 and an atomic rename. Receipts help recover intent; they are not a substitute for checking current remote state.

## Command reference

| Command | Result |
| --- | --- |
| `validate` | Local definition validation. |
| `preview` | Saved remote comparison and proposed edits. |
| `apply` | Applied reviewed plan and saved receipt. |
| `publish` | Server-validated test-only publication; `--live` also advances the ordinary head. |
| `promote` | Selects the receipt publication as head; preserves its test/live classification. |
| `route` | Assigns configured imported numbers after checking the head. |
| `export` | Saves the canonical public draft as `studio-backport.json` for review. |
| `status` | Reads the agent summary. |
| `call` | Sends one saved phone command; requires `--to` and `--confirm-real-call`. |

After exporting and manually backporting a Studio edit, preview with `--adopt-reviewed-revision <number>` for exactly the revision you reviewed. See [recovery](/docs/sdk-lifecycle).

Remote CLI commands require `CUMULUS_API_URL` and `CUMULUS_API_KEY`. In library code, pass `baseUrl` explicitly; the root client's optional environment default is `CUMULUS_BASE_URL`. The CLI does not provision hosting, install package credentials or inject secret values into your server.
