> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kugelaudio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy from your terminal

> Sign in with curb login, send your provider keys with curb secrets push, and ship your agent with curb deploy. Every flag, the upload limits and the errors you can fix.

Three commands take an agent project on your machine to a live hosted agent: sign in,
send your keys, deploy. Run them from the project's root directory.

```bash
npx curb login
npx curb secrets push
npx curb deploy
```

No project yet? Start with the [quickstart](/hosted-agents/quickstart).

## curb login

Opens the KugelAudio sign-in page in your browser and waits up to five minutes for you
to confirm. The terminal prints the sign-in link too, so on a machine without a browser
you can open it anywhere that can reach `127.0.0.1` on that machine.

| Flag | Meaning |
|---|---|
| `--url <web>` | Sign in to another KugelAudio app URL (default `https://www.kugelaudio.com`). Later logins remember it. |
| `--no-open` | Print the sign-in link without opening a browser. `CURB_NO_OPEN=1` does the same. |

The session is stored in `~/.config/curb/credentials.json` (or under
`$XDG_CONFIG_HOME/curb/`), readable only by you, and renews itself when it expires.
`npx curb logout` signs this machine out and deletes the file.

## curb secrets push

Sets every variable in the project's `.env` on the agent: your provider keys such as
`ANTHROPIC_API_KEY`, and the keys your own tools use. Values are write-only: the command
prints names, never values, and nothing can read them back. New calls use the new
values, so you do not need to deploy again.

| Flag | Meaning |
|---|---|
| `--file <path>` | Read another file instead of `.env`. |
| `--agent <id>` | Push to this agent, and link the project to it. |

The command skips empty values and these names:

- `KUGELAUDIO_API_KEY` and `KUGELAUDIO_API_BASE`: KugelAudio provides them to every
  hosted agent.
- `LIVEKIT_URL`, `LIVEKIT_API_KEY` and `LIVEKIT_API_SECRET`: hosted calls do not need
  them. Keep them in `.env` for running the agent locally with `npm run dev`.

You can also set variables in the dashboard, on the agent's **Variables** page.

## curb deploy

Packs the project, uploads it, builds it, and makes it the agent's live version:

```text
Packed 42 files (180.3 KiB unpacked, 51.2 KiB compressed).
Uploaded.
Revision rev_...
  build running
  build succeeded
  deployment candidate
  deployment active
Live. Try it in the playground: https://www.kugelaudio.com/dashboard/.../playground
```

A new version goes live only after it builds and starts. Until then the previous version
keeps answering calls.

| Flag | Meaning |
|---|---|
| `--agent <id>` | Deploy to this agent, and link the project to it. |
| `--no-activate` | Build the new version and check that it starts, but keep the live version serving. |

### Which agent

The first `deploy` or `secrets push` in a project asks which of your agents to use, or
creates a new one, and saves the choice in `.curb/link.json`. Later runs reuse it.
Delete `.curb/link.json` to choose again.

Without a terminal (CI, a coding agent), a first run in an account with exactly one
project and no agent creates the agent, named after the directory. Any other first run
needs `--agent <id>`, and the error lists the ids to choose from.

### What is uploaded

The project directory, except `node_modules/`, `.git/`, `.curb/`, `.data/`,
`.mcp-auth/`, a top-level `dist/`, and every `.env` and `.env.*` file. Your keys never
leave your machine with the source; `curb secrets push` sends them separately.

The lockfile is uploaded with the source, so keep it in the project. These limits are
checked before anything is uploaded:

| Limit | Value |
|---|---|
| Compressed archive | 50 MiB |
| Unpacked | 200 MiB |
| Files | 10,000 |
| Single file | 50 MiB |
| Directory depth | 8 |

Symlinks are kept when they point inside the project and refused when they point
outside it.

## What your agent can reach

Each call runs in its own sandbox, and its outbound traffic leaves through KugelAudio's
egress proxy:

| Traffic | Allowed |
|---|---|
| HTTPS to a public address on port 443 | Yes |
| HTTP to a public address on port 80 | Yes |
| Any other port, a private address, or a direct TCP connection (Postgres, MySQL, Redis, SMTP) | No |

Every call has `HTTPS_PROXY`, `HTTP_PROXY` and `NODE_USE_ENV_PROXY=1` set, so Node's
built-in `fetch`, `http` and `https` use the proxy with no code change. A library with
its own network client must be configured to use `HTTPS_PROXY`.

To read or write a database during a call, use its HTTPS API, for example the Supabase
client or a serverless driver that talks HTTP, instead of a TCP driver such as `pg`.

Each call can send and receive up to 50 Mbit/s.

## Errors you can fix

| Message starts with | What to do |
|---|---|
| `You are not signed in` or `Your KugelAudio session expired` | Run `npx curb login`. |
| `Your plan does not include ...` | Upgrade your organization's plan in the dashboard, then run the command again. |
| `Uploading source is not enabled for this organisation` | Push the project to GitHub and [connect the repository](/hosted-agents/github). |
| `Build ... failed` | Open the agent's **Deployments** page in the dashboard and read the build log. |

Any other refusal prints its HTTP status, error code and correlation id. Quote the
correlation id when you contact support. Set `DEBUG=1` for a stack trace.

## Next steps

<CardGroup cols={2}>
  <Card title="Deploy on git push" icon="github" href="/hosted-agents/github">
    Let every push to a branch ship the agent
  </Card>
  <Card title="Web widget" icon="globe" href="/hosted-agents/web-widget">
    Put a talk button on your website
  </Card>
</CardGroup>
