# CLI reference

> Every `zavu` command — what it does, its flags, and a copy-pasteable example.

## CLI reference

The Zavu CLI ships as the [`zavudev`](https://www.npmjs.com/package/zavudev) npm
package. Run it with `npx zavudev <cmd>` — nothing to install — or install it
globally (`npm i -g zavudev`) and call the shorter `zavu` binary. This reference
uses the `npx zavudev` form throughout.

It auto-discovers the function you're in via `.zavu/config.json`, so most
commands "just work" from inside the function directory.

```sh
npx zavudev --help              # full command tree
npx zavudev <cmd> --help        # per-command flags
```

## Auth

### `npx zavudev login`

Opens the browser to `/cli-auth`, lets you pick the project, saves the API key
to `~/.zavu/credentials.json` (chmod 0600).

| Flag | Description |
|---|---|
| `--api-key <key>` | Skip the browser flow and save a provided key directly. |
| `--base-url <url>` | Override the API base URL (default `https://api.zavu.dev`). |
| `--dashboard <url>` | Override the dashboard URL (default `https://dashboard.zavu.dev`). |
| `--no-browser` | Don't open the browser, just print the URL. |
| `--show` | Print the credentials path + current login state, then exit. |

Environment overrides: `ZAVU_DASHBOARD_URL`, `ZAVU_API_URL`.

### `npx zavudev whoami`

Shows the project, team, mode, and the last 4 chars of your API key.

```sh
npx zavudev whoami
npx zavudev whoami --json    # machine-readable
```

### `npx zavudev logout`

Clears `~/.zavu/credentials.json`. The API key stays active server-side — revoke
it from the dashboard if needed.

## Functions

### `npx zavudev fn init`

Scaffold a new function locally **and** register it in your Zavu project.

| Flag | Description |
|---|---|
| `--template <id>` | Template to scaffold from (`blank`, `restaurant-booking`). |
| `--name <name>` | Display name for the function. |
| `--slug <slug>` | URL slug. Max **23 chars**, lowercase + digits + hyphens. |
| `--dir <path>` | Output directory (default `./<slug>`). |
| `-y, --yes` | Accept defaults, no prompts. |

```sh
npx zavudev fn init --template restaurant-booking -y
npx zavudev fn init --name "Order Bot" --slug bella -y
```

> **Note:**
> If the slug is already taken, the CLI auto-bumps (`bella-2`, `bella-3`, …) up
> to 25 attempts. The directory it creates matches the final slug.

### `npx zavudev fn push`

Fast-sync the local source + dependencies to the function's **draft**. Does
NOT trigger a build. Useful for "save my progress" or to keep the dashboard
editor showing the latest code.

```sh
npx zavudev fn push                     # uses index.ts
npx zavudev fn push --source bot.ts     # custom entrypoint
npx zavudev fn push --no-deps           # skip package.json upload
```

### `npx zavudev fn deploy` (alias: `npx zavudev deploy`)

Bundle, upload, publish. Reads `index.ts` + `package.json` from cwd and posts
to `/v1/functions/:id/deploy`. Polls until status=active.

| Flag | Description |
|---|---|
| `--source <file>` | Source file to use (default `index.ts`). |
| `--update-runtime` | Upgrade this function to the latest runtime layer. Default: keep the pinned version. See [Runtime](https://www.zavu.dev/docs/guides/functions/runtime). |
| `--arch <arch>` | `arm64` (default) or `x86_64`. x86 invocations cost 1.25× units. Override of `package.json` `zavu.architecture` field. See [Runtime → CPU architecture](https://www.zavu.dev/docs/guides/functions/runtime#cpu-architecture). |

Output after success includes:
- Public URL (if `httpEnabled: true`).
- Agents and tools synced (`+ created`, `~ updated`, `= unchanged`, `- removed`).
- Warnings (collisions, validation issues).

### Calling a function over HTTP

With `httpEnabled`, a function answers on its public URL. What it accepts
depends on what the function declares.

A function whose default export is `defineFunction` receives the POST body as
the event. A function that only declares `defineAgent` and `defineTool` has no
handler for a bare request and answers `404 {"error":"no_handler"}` — to reach
one of its tools, name it and pass its arguments under `arguments`:

```sh
curl -X POST https://fn.zavu.dev/{projectId}/{slug} \
  -H 'content-type: application/json' \
  -d '{"tool":"get_order_status","arguments":{"orderId":"ORD-4417"}}'
```

The key is `arguments`. `args`, `input`, and `parameters` are accepted by the
dispatcher and then reach your handler empty, which surfaces as a
`tool_error` about a property of `undefined` rather than as a clear rejection.

A project compiled from the [eve layout](https://www.zavu.dev/docs/guides/functions/deploy-eve-project)
declares no HTTP handler at all, so enabling HTTP on one produces a URL that
404s for every request. Use `npx zavudev invoke --tool <name>` there.

### `npx zavudev fn delete` (alias: `npx zavudev fn rm`)

Permanently destroy a function and cascade everything it owns. **Always asks
for confirmation** — you must type the slug back to proceed.

```sh
npx zavudev fn delete                # uses .zavu/config.json (the cwd)
npx zavudev fn delete fn_abc123      # by id, from anywhere
```

Cascade:
- The deployed function + its logs (async cleanup).
- Triggers, secrets, deployment history.
- Managed agents + tools created via `defineAgent` / `defineTool`.
- Auto-provisioned API key is revoked.

Manual agents/tools (created via dashboard or `npx zavudev agents create`) are
**not** touched.

### `npx zavudev fn invoke`

Run the function locally with a synthetic event. Same TypeScript, same handler,
but no cloud round-trip.

```sh
npx zavudev fn invoke --event message.inbound \
  --data '{"from":"+14155551234","text":"hola"}'

# Call one tool handler directly, without an event:
npx zavudev fn invoke --tool lookup_order --args '{"orderId":"ORD-001"}'

<Note>
`fn invoke` runs your code with [Bun](https://bun.sh). Every other command runs
under plain Node.
</Note>
npx zavudev fn invoke --event message.inbound --json '{"from":"+1...","text":"…"}'
```

### `npx zavudev fn logs`

Stream CloudWatch logs for the deployed function.

| Flag | Description |
|---|---|
| `-t, --tail` | Keep polling for new events (adaptive backoff). |
| `--since <duration>` | Show events newer than this (`5m`, `1h`, `2d`). Default `30m`. |
| `--filter <pattern>` | CloudWatch filter pattern. |
| `--limit <n>` | Max events per page (default 100). |

```sh
npx zavudev fn logs                      # last 30 min, exit
npx zavudev fn logs --tail               # follow
npx zavudev fn logs --since 2h --filter "ERROR"
```

> **Tip:**
> `--tail` starts polling every 3s and backs off to 30s when idle. Activity
> resets to 3s. Ctrl-C exits cleanly and aborts the in-flight request.

## Triggers

Functions can subscribe to Zavu events. The `defineAgent`/`defineTool` path
covers most agent use cases automatically; use triggers for raw events
(`message.inbound`, `broadcast.status_changed`, etc).

```sh
npx zavudev fn triggers events                                       # list event types
npx zavudev fn triggers list                                         # current triggers
npx zavudev fn triggers add --events message.inbound                 # any sender
npx zavudev fn triggers add --events message.inbound --senders snd_abc,snd_xyz
npx zavudev fn triggers add --events message.inbound --senders any   # explicit "all"
npx zavudev fn triggers toggle <triggerId>                           # pause
npx zavudev fn triggers toggle <triggerId> --off                     # alias for above
npx zavudev fn triggers rm <triggerId>
```

The cartesian product applies: `--events A,B --senders X,Y` creates 4 triggers
(2 events × 2 senders).

## Secrets

Per-function environment variables. Encrypted at rest. Plaintext **never**
leaves the server after `set` — `list` only shows the last 4 chars.

```sh
npx zavudev fn secrets list
npx zavudev fn secrets set OPENAI_API_KEY sk-…       # inline
npx zavudev fn secrets set KEY --from-file ./key.txt # from a file
cat key.txt | npx zavudev fn secrets set KEY -       # stdin (safest)
npx zavudev fn secrets unset OLD_KEY                 # alias: npx zavudev fn secrets rm
```

| Constraint | Limit |
|---|---|
| Key format | `[A-Z_][A-Z0-9_]*` (uppercase env-var style) |
| Reserved prefixes | `AWS_`, `LAMBDA_`, `_HANDLER`, `_X_AMZN` (system-reserved) |
| Value size | 4096 chars |
| Total secrets per function | 50 |

Changes take effect on the **next** `npx zavudev deploy`. `list` shows `synced: no`
for secrets that haven't been deployed yet.

## Messages

Wraps the SDK's messages resource.

```sh
npx zavudev messages send --to +56912345678 --text "Hello"
npx zavudev messages send --to user@example.com --channel email --subject "Hi" --text "Hey"
npx zavudev messages list --limit 20
npx zavudev messages list --status delivered --to +14155551234
npx zavudev messages get <messageId>
```

## Other API mirrors

The CLI mirrors the full REST API — every resource has its own subcommand.
Defaults are sane (pagination 20, JSON output via `--json` flag).

| Group | Commands |
|---|---|
| `senders` | list, get, create, update, delete, rotate-secret |
| `contacts` | list, get, create, delete, by-phone, add-channel, remove-channel, merge |
| `templates` | list, get, create, submit, delete |
| `broadcasts` | list, get, create, add-contacts, send, cancel, progress, delete |
| `phone-numbers` | list, get, search, requirements, buy, update, delete |
| `invitations` | list, get, create, cancel |
| `agents` | get/create/update/delete + flows + tools + knowledge-bases |
| `addresses` | list, get, create, delete |
| `documents` | list, get, delete, upload-url |
| `exports` | list, get, create |
| `urls` | list, get, submit |
| `sub-accounts` | list, get, create, update, delete, balance, api-keys |
| `10dlc` | brands `{list/create/submit/sync/…}` + campaigns + assign |
| `introspect` | phone |
| `balance` / `plan` / `usage` | singletons |

Every command supports `--help`. Examples:

```sh
npx zavudev senders list
npx zavudev agents get --sender snd_abc
npx zavudev broadcasts send brd_xyz --at 2026-12-25T10:00:00Z
npx zavudev 10dlc brands create --file brand.json
```

## Agents (detailed)

When a function declares an agent with `defineAgent`, the agent is created on
the sender and managed by the function. These commands let you inspect that
state — handy for debugging an agent that isn't responding.

### `npx zavudev agents get`

```sh
npx zavudev agents get --sender <senderId>
```

Returns the full agent config: `enabled`, `provider`, `model`, `systemPrompt`,
`triggerOnChannels`, `triggerOnMessageTypes`, stats. If `managedByFunctionId`
is set, this agent is the live mirror of your `defineAgent` declaration.

### `npx zavudev agents executions list`

```sh
npx zavudev agents executions list --sender <senderId>
npx zavudev agents executions list --sender <senderId> --status error
npx zavudev agents executions list --sender <senderId> --json
```

Lists the most recent agent runs. Failed executions are surfaced with their
`errorMessage` truncated below the table. Use `--json` to get the full
payload for parsing.

### `npx zavudev agents executions get`

```sh
npx zavudev agents executions get <executionId> --sender <senderId>
```

Full detail of one execution: `errorCode`, `errorMessage`, `responseText`,
tokens, cost, latency, and the inbound/response message IDs. Use this when
you spot an `error` row in the list and want to know exactly what failed.

### `npx zavudev agents tools list`

```sh
npx zavudev agents tools list --sender <senderId>
```

Lists the tools attached to the agent. After `npx zavudev deploy`, the tools you
declared via `defineTool` should appear here with `managedByFunctionId` set.

### `npx zavudev agents flows list`

```sh
npx zavudev agents flows list --sender <senderId>
```

Lists the conversational flows attached to the agent.

## Environment variables

The CLI respects:

| Var | Effect |
|---|---|
| `ZAVU_DASHBOARD_URL` | Default for `--dashboard`. Useful for local dev (`http://localhost:3000`). |
| `ZAVU_API_URL` | Default for `--base-url`. The dashboard reports its own API URL on login, so this is rarely needed. |
| `ZAVUDEV_API_KEY` | Used as the API key instead of `~/.zavu/credentials.json`. Lets CI, a container, or a coding agent authenticate with no interactive `npx zavudev login` and no writable home. |
| `ZAVUDEV_API_BASE_URL` | Overrides the API host. Only needed to point at a non-production deployment. |
| `ZAVU_NO_ANIMATE` | Disables the scramble animation in success output. |
| `CI` | Same as `ZAVU_NO_ANIMATE` (auto-detected). |

## Exit codes

- `0` — success
- `1` — error (invalid args, server rejection, network)
- `130` — Ctrl-C (SIGINT)
