---
title: CLI
description: The beeuni command line, its auth model, the dev loop, and every command.
---

The `beeuni` command line interface (CLI) controls Beeuni from a terminal — your laptop or a session sandbox. This page shows the everyday dev loop, then lists every stable command and flag.

## Install

```sh
curl -fsSL https://beeuni.ai/install | bash
```

The installer downloads a prebuilt binary for macOS and Linux. Windows is not supported.

| Command | Effect |
| --- | --- |
| `beeuni update` | Re-run the install script and pull the latest binary. |
| `beeuni uninstall [-y\|--yes] [--keep-auth] [--keep-home]` | Remove the binary, the `/usr/local/bin` shim, and the stored token. `--keep-auth` keeps the token. `--keep-home` keeps `~/.beeuni`. |
| `beeuni version` | Print the CLI version. |

## Auth model

Beeuni stores authentication per host, not globally. A host is one Beeuni API endpoint. Use `cloud` to connect to Beeuni.

The config file lives at `~/.config/beeuni/config.json`, mode `0600`. Override its path with `BEEUNI_CONFIG_FILE`.

The CLI follows one hierarchy: host → account → project → session. You sign in to a host, pick an account inside it, pick a project inside that account, and open sessions inside the project. `beeuni hosts login` walks the first three steps in order: it signs you in, picks the account, then sets a default project.

Every token starts with `beeuni_pat_`. A user token, from `beeuni login`, sees every account and project you belong to. A project token is auto-minted for a session sandbox and scoped to one project. See [Token scope](#token-scope).

## The dev loop

This loop assumes the CLI is installed and you ran `beeuni login`. See [Quickstart](/docs/quickstart) for setup.

1. **Link a repo**

    Start a new project, or link an existing repo folder to one.

    To scaffold a new project:

    ```sh
    beeuni init my-app
    cd my-app
    ```

    `beeuni init` creates a project directory with the general-purpose starter. Its
    `beeuni.yaml` declares `beeuni_version: 2` and runs the default runtime
    [harness](/docs/work/harnesses).

    To link an existing cloned repo to a project you already created:

    ```sh
    beeuni projects link <project-id>
    ```

    This command writes `.beeuni/link.json` in the current directory. Beeuni reads this file to find your project on every command run from this folder. If you plan to run `beeuni ship` first, skip this step. It links a new project for you when none exists.

2. **Ship your code**

    ```sh
    beeuni ship
    ```

    `beeuni ship` lints your `beeuni.yaml`, commits local changes, pushes your branch, and prompts for any missing secret or connection. Run it each time you want your local changes on the cloud project. The first run also creates the cloud project and repo if you have not linked one yet.

3. **Run and attach to sessions**

    Start a session with a prompt:

    ```sh
    beeuni sessions new --prompt "Build the login page" --wait
    ```

    Each session runs in its own sandbox, on its own branch. `--wait` blocks until the session is ready.

    Attach to a session from your terminal:

    ```sh
    beeuni connect
    ```

    With no session id, `beeuni connect` (alias: `attach`) opens a session picker
    for the bound project — running sessions attach immediately, stopped ones boot
    first, and `+ New session` starts a fresh sandbox — then lands you in the full
    default runtime TUI attached to that session. Pass an id to skip the picker:
    `beeuni connect <session-id>`.

    The CLI manages the `opencode` binary for you: on first connect it downloads
    the exact version the session's server runs and caches it under
    `~/.beeuni/opencode/<version>/`, so the TUI and server never skew. Set
    `BEEUNI_OPENCODE_BIN` to force your own binary.

    A session on the pi [harness](/docs/work/harnesses) has no default runtime server.
    `beeuni connect` exits 1 for it with the message `This session's runtime does
    not support attaching a terminal client.`

    For a lighter-weight line-based chat instead of the full TUI, run:

    ```sh
    beeuni sessions chat
    ```

    This opens an interactive chat with your most recent session. Add an id to target a specific session: `beeuni sessions chat <id>`.

    For the whole product in your terminal — the session list, the transcript and
    composer, a shell in the sandbox, and the Files, Review, Apps, Customize and
    Account screens — run the experimental terminal client:

    ```sh
    beeuni tui        # or: beeuni t, or beeunit
    beeunit --project <id> --new --terminal   # new session + sandbox shell, one command
    ```

    It signs in with the host you are already on. See [the TUI page](/docs/cli#sessions).

    To open a raw shell in the sandbox, with no agent involved, run:

    ```sh
    beeuni sessions shell
    ```

    List your running sessions at any time:

    ```sh
    beeuni sessions ls
    ```

4. **Review with change requests**

    An agent opens a change request (CR) when its session has commits ready to merge. List, inspect, and merge them from the CLI.

    ```sh
    beeuni cr ls
    beeuni cr diff 1
    beeuni cr merge 1
    ```

    `beeuni cr ls` lists change requests for the linked project. `beeuni cr diff <cr>` shows the unified patch. `beeuni cr merge <cr>` merges it into the project's default branch. Accept a CR number or its full id.

## Reference

### Auth commands

| Command | Effect |
| --- | --- |
| `beeuni login [--host <name>] [--api <url>] [--token <pat>] [--account <slug>] [--no-project]` | Sign in to the active host, or the named one. Opens a browser by default; `--token` signs in headless. `--no-project` skips the default-project pick. |
| `beeuni logout [--host <name>]` | Remove the token for the active host, or the named one. |
| `beeuni whoami [--host <name>] [--json] [--token-only]` | Print the signed-in user and active account. |
| `beeuni token [--host <name>]` | Shortcut for `beeuni whoami --token-only`. |

`beeuni hosts login` / `hosts logout` / `hosts whoami` are the canonical forms. `login` / `logout` / `whoami` are shortcuts that act on the active host.

### Hosts

| Command | Effect |
| --- | --- |
| `beeuni hosts ls [--json]` | List every host and its auth status. |
| `beeuni hosts login [<name>] [--token <pat>] [--api <url>] [--account <slug>] [--no-project]` | Sign in to a host. An unknown name registers the host first. |
| `beeuni hosts logout [<name>]` | Remove the token for a host. |
| `beeuni hosts use <name>` | Switch the active host. |
| `beeuni hosts add <name> --url <url> [--dashboard-url <url>] [--login]` | Register a new host. `--login` signs in right after. |
| `beeuni hosts rm <name> [--force]` | Remove a host. |
| `beeuni hosts info [<name>] [--json]` | Show details for one host. |
| `beeuni hosts current [--json]` | Print the active host name. |

A remote host URL that starts with `http://` is normalized to `https://`. The CLI never sends a token over plain HTTP to a remote host. `localhost` is exempt.

### Accounts

| Command | Effect |
| --- | --- |
| `beeuni accounts ls [--json]` | List the accounts you belong to on the active host. |
| `beeuni accounts use [<slug-or-id>]` | Switch the active account. |
| `beeuni accounts current [--json]` | Print the active account. |
| `beeuni accounts info [<slug-or-id>] [--json]` | Show one account. |

### Members

Who belongs to the account, and at what account role. Roles are `owner`,
`admin`, and `member`. Owners and admins hold implicit Manager on every
project, so `member` is the only role that takes per-project grants.

| Command | Effect |
| --- | --- |
| `beeuni members ls [--json]` | List members, roles, and project counts. |
| `beeuni members invite <email> --role admin\|member [--project <id>:<role>]` | Invite by email. An existing Beeuni user is added immediately; anyone else is mailed an invite link. `--project` is repeatable and applies on accept. Needs `member.invite`. |
| `beeuni members set-role <user\|email> --role owner\|admin\|member` | Change an account role. Needs `member.update`; the `owner` role is owner-only. |
| `beeuni members rm <user\|email> [-y\|--yes]` | Remove a member and revoke their tokens. Needs `member.remove`. |
| `beeuni members super-admin <user\|email> on\|off` | Grant or revoke the super-admin bypass. Needs `member.super_admin.grant`. |
| `beeuni members invites ls [--json]` | List pending invitations you sent. |
| `beeuni members invites cancel <invite-id>` | Cancel one pending invitation. |
| `beeuni members invites resend <invite-id>` | Re-send the email and refresh the 14-day expiry. |

A `<user>` is a user id, or the email of someone already in the account.
Options: `--account <id>`, `--host <name>`, `--json`, `-y`.

### Groups

An account group is a named set of people you grant a role to once. Bind a
group to a scope with `beeuni access grant --group <id> --role <key>`; revoke
with `beeuni access revoke <assignment-id>`.

| Command | Effect |
| --- | --- |
| `beeuni groups ls [--json]` | List groups with member and project counts. |
| `beeuni groups create <name> [--description <t>]` | Create a group. |
| `beeuni groups set <group> [--name <n>] [--description <t>\|--no-description]` | Rename or re-describe a group. |
| `beeuni groups rm <group> [-y\|--yes]` | Delete a group. Its grants go with it. |
| `beeuni groups members <group> [--json]` | List a group's members. |
| `beeuni groups add <group> <user>...` | Add one or more people. |
| `beeuni groups remove <group> <user>` | Remove one person. |
| `beeuni groups projects <group> [--json]` | Which projects the group reaches, and at what role. |

A `<group>` is a group id or its exact name. Reads need `group.read`.
`create`, `set`, and `add` need `group.update` or `group.members.manage`, plus
the enterprise `rbac` entitlement. `rm` and `remove` are cleanup and are never
entitlement-gated.

### Tokens

Non-interactive credentials for the account. Reads need `token.read`. Every
account member may mint and revoke their own personal keys
(`token.personal.create`, `token.personal.revoke`); a personal key acts as you
and never carries more than your own roles. Service accounts and other people's
keys need `token.create` / `token.revoke` (owner and admin).

| Command | Effect |
| --- | --- |
| `beeuni tokens ls [--mine] [--json]` | List the account's personal API keys. `--mine` narrows to the ones you minted. |
| `beeuni tokens new <name> [--expires <when>] [--project <id>]` | Mint a key. The secret prints once. `--project` binds it to one project, which it can never leave. |
| `beeuni tokens rm <token-id> [-y\|--yes]` | Revoke a key immediately. |
| `beeuni tokens apps ls [--json]` | List your connected apps: the apps and MCP clients you approved with Sign in with Beeuni, across every account. |
| `beeuni tokens apps rm <client-id> [-y\|--yes] [--json]` | Revoke a connected app: its tokens stop working at once, and it must ask you again. |
| `beeuni tokens service-accounts ls [--json]` | List service accounts. |
| `beeuni tokens service-accounts new <name> [--description <t>] [--expires <when>]` | Create one. The bearer prints once. |
| `beeuni tokens service-accounts disable <id>` | Disable a service account: it can no longer authorize; delete and re-create to return. |
| `beeuni tokens service-accounts rm <id> [-y\|--yes]` | Delete a service account permanently. |

A personal API key acts as you and dies with your membership. A service
account acts as itself and inherits no access: a new one holds no permissions.
Grant it one with `beeuni access grant --service-account <id> --role <key>`.
`--expires <when>` takes ISO-8601 or a forward span: `30d`, `12h`, `6w`, `1y`.

### Billing

Read the active account's plan, credits, and spend. Read-only: plan changes,
top-ups, and payment methods are dashboard flows.

| Command | Effect |
| --- | --- |
| `beeuni billing status [--json]` | Plan, credits, seats, subscription. |
| `beeuni billing transactions [--limit <n>] [--offset <n>] [--type <a,b>] [--json]` | Credit ledger, newest first. Default page size 50. |
| `beeuni billing transactions --summary\|--breakdown\|--usage [--days <n>]` | Credits in/out, the balance split (expiring/non-expiring/daily), or a credit-usage summary. `--days` is the window for `--summary` and `--usage`; default 30. |
| `beeuni billing costs [--since <iso>] [--until <iso>] [--json]` | Account spend over a window, plus a model breakdown. Default window: 30 days, half-open `[from, to)` UTC. |
| `beeuni billing costs --by project\|session [--sort <k>] [--limit <n>] [--offset <n>] [--csv <file>]` | Roll spend up by project or by session. `--sort` takes `total_desc` (default), `total_asc`, `recent`, or `name_asc` (`--by project` only). `--csv` needs `--by`. |

Filters: `--project <id>`, `--session <id>`, and `--owner <id>` (sessions, with
`--by session`). Options: `--account <id>`, `--host <name>`, `--json`.

### Projects

A command resolves "the project" in this order:

1. The `--project` flag.
2. The `BEEUNI_PROJECT_ID` environment variable.
3. `.beeuni/link.json` in the exact working directory.
4. The global default set by `beeuni projects use`.

| Command | Effect |
| --- | --- |
| `beeuni projects ls [--all] [--query <text>] [--json]` | List projects on the active account. `--all` spans every account you belong to. `--query` (alias `-q`) filters by name, id, or repo. |
| `beeuni projects info [<id>] [--json]` | Show one project. Default: the linked or default project. |
| `beeuni projects use [<id>]` | Set the global default project. Switches the active account if the project lives elsewhere. |
| `beeuni projects unset` | Clear the global default project. |
| `beeuni projects link [<id>]` | Bind the current directory to a project. Writes `.beeuni/link.json`. |
| `beeuni projects unlink` | Remove `.beeuni/link.json`. |
| `beeuni projects open [<id>]` | Open a project's dashboard page in your browser. |
| `beeuni projects clone [<id>] [dir]` | Clone a project's repo through the authenticated Beeuni git proxy. |
| `beeuni projects rm [<id>] [-y\|--yes]` | Delete a project and its Beeuni-managed git repo. Repositories you connected yourself are never touched. |
| `beeuni projects set [<id>] [--name <n>] [--branch <b>] [--manifest <path>] [--json]` | Update one project's settings. Only the fields you pass are written. Passing no field exits `2`. Alias: `update`. |
| `beeuni projects set [<id>] --icon <emoji>\|--no-icon\|--glyph <name>:<color>\|--no-glyph` | Set or remove the project's icon. |
| `beeuni projects rename [<id>] <name>` | Alias for `beeuni projects set --name <name>`. |
| `beeuni projects features [ls] [--json]` | List every feature flag with its key, state, origin, and stability. |
| `beeuni projects features enable\|disable\|reset <flag>` | Set the project override on, off, or clear it so the flag follows the platform default. |
| `beeuni projects cli-tokens ls [--json]` | List the project's CLI tokens. |
| `beeuni projects cli-tokens new [--name <name>] [--expires-at <iso>]` | Mint a project-scoped CLI token. The secret prints once. |
| `beeuni projects cli-tokens rm <token-id> [-y\|--yes]` | Revoke one project CLI token. |
| `beeuni projects upgrade [<id>] [--json]` | Start the agent session that migrates a v1 `beeuni.toml` to a v2 `beeuni.yaml` and opens a change request. |

A project shows one icon, so writing `--icon` clears the glyph and writing
`--glyph` clears the emoji; passing both is refused. Glyph colors: `grey`,
`red`, `orange`, `yellow`, `lime`, `blue`, `purple`, `magenta`. `set` and
`features` need `project.settings.write`. A flag the platform marks
unavailable stays off regardless of the project override.

A project CLI token is bound to one project — the API rejects it everywhere
else. A session sandbox uses its session-bound `BEEUNI_TOKEN`. `cli-tokens ls`
needs project read; `new` and `rm` need
`project.credentials.issue`. A session-bound token can neither mint nor
revoke project tokens (`403`), whether or not the project declares agents. A
project CLI token follows the account's PAT policy: when the account requires
an expiry, pass `--expires-at`; an expiry beyond the maximum lifetime returns
`400`.

`beeuni projects upgrade` needs project write. The default agent refreshes the
marketplace baseline, rewrites the manifest, runs `beeuni validate`, and opens
a change request. It never merges: a human reviews the diff.

### Project scaffold

`beeuni init [project-name] [options]` creates a new project directory. The
starter writes a v2 `beeuni.yaml`, `agents/`, `skills/`, `memory/`, and
`harnesses/opencode/`. The command can wire local coding-tool discovery without
changing the default agent runtime. The command does not write
`.beeuni/link.json`. `beeuni ship` or `beeuni projects link` create that file.

| Flag | Meaning |
| --- | --- |
| `--name <project>` | Project name. |
| `--primary <agent>` | Primary agent. |
| `--agents <csv>` | Local coding-agent integrations to wire up. |
| `--force` | Configure the current directory in place instead of scaffolding a new one. |
| `--overwrite` | Overwrite existing files. |
| `--no-git` | Skip git init. |
| `-y, --yes` | Don't prompt. |

The local coding-tool selection does not change the default agent runtime.

`beeuni init` does not include a marketplace picker. Adding a marketplace skill is an agent import: start a session and ask the agent to bring one in.

### Ship

`beeuni ship` stages, commits, and pushes your current branch to the project's git repo. Run it once to create the project. Run it again any time to sync. Alias: `beeuni deploy`.

Each run:
- Runs the [`beeuni validate`](#manifest-validation) checks: `beeuni.yaml` merged with every file it lists under [`imports:`](/docs/project/manifest#imports), sandbox Dockerfiles, agent wiring, and repository size (skip with `--no-verify`). An error stops the ship. A warning never does.
- Commits any dirty working tree (skip with `--no-commit`).
- Prompts for any missing `env` secret (skip with `--no-env`).
- Pushes the current branch to the same-named remote branch.
- Connects any declared connector that still needs auth (skip with `--no-connect`).

An existing GitHub `origin` links through the Beeuni GitHub App. Any other existing `origin` is registered as-is. No `origin` creates a managed Beeuni git repo.

| Option | Effect |
| --- | --- |
| `--name <project>` | Display name for a new project. |
| `--account <id\|slug>` | Account to create the project under (first ship only). |
| `--origin <managed\|git-url>` | Override the inferred origin choice. |
| `--github-token <pat>` | Link a GitHub origin with this token instead of the GitHub App. |
| `-m, --message <text>` | Commit message. |
| `--no-commit` / `--no-verify` / `--no-env` / `--no-connect` | Skip that step. |
| `-y, --yes` | Don't prompt. |
| `-n, --dry-run` | Print what would happen; change nothing. |
| `--project <id>` / `--host <name>` | Target a non-default project or host. |

### Apps

Apps host static sites, servers, workers and databases. Each App has a stable URL. A release contains its code and configuration; a failed deployment does not replace the active release.

```bash
beeuni apps list
beeuni apps show main
beeuni apps connect main
beeuni apps launch --template convex --slug main
beeuni apps deploy dist --type static --spa
beeuni apps machines main
beeuni apps volumes main
```

Connect applications with `uses` and use the connection examples shown by `beeuni apps connect`. Keep administrative credentials out of client-side code.

Running resources consume account credits. Check Billing and Usage for your balance. Apps do not have a separate monthly budget.

[Apps](/docs/feature-flags/apps)

### Sessions

Each session runs in one sandbox on its own branch.

| Command | Effect |
| --- | --- |
| `beeuni sessions ls [--mine\|--shared\|--automated] [--search <q>] [--label <label>]... [--json]` | List sessions. `--label` is repeatable; a session must carry every given label. A LABELS column appears when any listed session has labels. |
| `beeuni sessions status [--all] [--json]` | Every session and what its agent is doing right now. Aliases: `overview`, `ps`. |
| `beeuni sessions info <id> [--json]` | Detail view: status, branch, agent, sandbox URL. |
| `beeuni sessions new [--prompt "<text>"] [--agent <name>] [--model <id>] [--wait] [--connect] [--json]` | Start a session. `--connect` attaches the default runtime TUI once it is ready (implies `--wait`); on an interactive terminal without it, the CLI asks whether to connect after creation. `--model <id>` overrides the project's default model; a model that runs on an API key or a ChatGPT subscription uses every key you may use for it, and they rotate. `--wait` blocks until it is running (up to ~5 minutes). Use `--secret <id>` or `--no-secrets` to narrow Secret access. These Secret flags require a backend token. Use `--connector <alias>=<authorization-id>` or `--no-connectors` to set Connector access. Use `--require-connector <alias>` to require an authorization before provisioning. Scope flags are repeatable. Use `--context <key>=<value>` for non-secret runtime context. `--label <label>` (repeatable) classifies the session; `--meta <key>=<value>` (repeatable) stores a string in its metadata. |
| `beeuni sessions chat [<id>] [--prompt "<text>"] [--queue \| --steer] [--new] [--agent <name>] [--json]` | Talk to a session's agent. Interactive by default. Alias: `talk`. Top-level `beeuni chat` also works. `--queue` is one-shot only: it stores the prompt in the session's durable inbox and returns as soon as it is stored, instead of handing it to the runtime. `--steer` stores it the same way, and the running turn reads it at its next step without stopping. With no turn running, it starts one. A session that cannot steer runs it as `--queue`. |
| `beeuni sessions connect [<id>] [-- <opencode args>]` | Attach the default runtime TUI to the session's default runtime server. Also available top-level: `beeuni connect` / `beeuni attach`. With no id, opens a session picker (running, stopped-with-restart, or new). The CLI auto-downloads the version-matched `opencode` binary (cache: `~/.beeuni/opencode/<version>/`; override: `BEEUNI_OPENCODE_BIN`). A pi session has no opencode server: the command exits `1` and names `beeuni sessions shell` and `beeuni sessions chat` instead. |
| `beeuni tui [--host <name>] [--project <id>] [--session <id>] [--new] [--agent <name>] [--terminal] [--no-sidebar] [--mouse] [--install] [--uninstall]` | **Experimental.** Open the Beeuni terminal client: sessions, transcript, composer, sandbox shell, Files, Review, Apps, Customize and Account. Aliases `beeuni t` and `beeunit`. `--new` creates a session in the project at boot (`--agent` picks the agent), `--terminal` opens the sandbox shell focused, `--no-sidebar` starts without the sidebar (`Alt+B` toggles it), `--mouse` hands the mouse to the app (off by default so your terminal's selection, copy and link clicks keep working). The TUI is a separate ~80 MB binary; the first run asks, then installs the version-matched `beeuni-tui` into `~/.beeuni/tui/<version>/`; later CLI updates refresh it without asking and reuse an unchanged binary. `--install` does it without a prompt, `--uninstall` removes it. Uses the active host unless `--host` names another; with no host logged in it opens its own login screen. `?` prints every binding. See [/docs/cli#sessions](/docs/cli#sessions). |
| `beeuni sessions shell [<id>] [--new]` | Open a raw interactive terminal in the sandbox, with no agent. Reattaches to the session's existing terminal; `--new` always starts a fresh one. Aliases: `terminal`, `ssh`. |
| `beeuni sessions shell <id> ls [--json]` | List the session's terminals: id, status, command. Needs no TTY. |
| `beeuni sessions shell <id> kill <pty-id>` | Kill one terminal. The ambient shell respawns on the next attach; anything running inside it does not. |
| `beeuni sessions forward <id> --port <sandbox>[:<local>]` | Forward a sandbox port to your machine, VS Code-style, so `http://localhost:3000` an agent printed works in your own browser. `--port` is repeatable; with no local port the same number is used if free, else the next free one; `:0` requests an OS-assigned ephemeral port. HTTP and WebSocket both forward (dev-server hot reload works). Prints one `⇄ localhost:N → sandbox:M` line per forward and stays in the foreground until Ctrl+C. Does not start a stopped session — it prints the `beeuni sessions restart` remedy instead. Alias: `ports`. |
| `beeuni sessions log [<id>] [--limit <n>] [--json]` | Print recent messages, read-only. A running session is read live; a stopped one is read from the transcript saved at the end of every turn, so it is never woken just to be read. The source is noted on stderr, so `--json` output is unchanged. Aliases: `messages`, `history`. |
| `beeuni sessions attachments <id> [--download <attachment-id>\|--all] [--out <dir>] [--json]` | List a session's stored files — what users attached, and copies of the files the agent showed — and download them. Works while the session is stopped: neither the list nor the bytes need its sandbox. Downloads never overwrite; a name already taken becomes `name (1).ext`. |
| `beeuni sessions pending <id> [--json]` | List open tool-permission or question prompts. Alias: `prompts`. |
| `beeuni sessions approve <id> [<req-id>] [--always] [--reject] [--message "<text>"]` | Answer a permission prompt. |
| `beeuni sessions answer <id> [<req-id>] [--option <v>]... [--text "<text>"] [--reject]` | Answer a question prompt. |
| `beeuni sessions digest [--since <7d>] [--json]` | Compact multi-session review. A stopped session's transcript comes from its saved copy and is marked `saved` (and `partial` when that copy does not reach the first message). Aliases: `review`, `summary`. |
| `beeuni sessions scope <id> [scope options] [--json]` | Read or replace Secret and Connector access. Alias: `access`. Use `--secret <id>`, `--no-secrets`, or `--inherit-secrets` for Secrets. Use `--connector <alias>=<authorization-id>` or `--no-connectors` for Connector bindings. Use `--require-connector <alias>` or `--no-required-connectors` for required Connectors. Provided categories replace their current values. Omitted categories remain unchanged. Changes apply to the next prompt. Removed Secret values remain in existing context if the session already read them. |
| `beeuni sessions preview <id> [port] [--port <n>] [--list] [--json]` | Print a clickable preview URL for a sandbox port. Default port: `3000`. `--list` prints the named candidates instead. |
| `beeuni sessions restart <id>` | Restart the session's sandbox. |
| `beeuni sessions rename <id> <name>` | Set a session's name. Pass `""` to clear it. |
| `beeuni sessions update [<id>] [--label <l>]... [--unlabel <l>]... [--clear-labels] [--meta <key>=<value>]... [--unmeta <key>]... [--json]` | Change a session's labels and metadata. `--label` adds, `--unlabel` removes, `--clear-labels` empties the list first; `--meta` sets a string key, `--unmeta` removes a key. Without an id it updates `$BEEUNI_SESSION_ID`, so an agent labels the session it runs in. Alias: `label`. |
| `beeuni sessions rm <id>...` | Stop and delete one or more sessions. |
| `beeuni sessions open <id>` | Open a session's dashboard page in your browser. |
| `beeuni sessions stop <id> [--json]` | Pause a session. The sandbox stops in place and the disk is kept. Alias: `pause`. Needs `project.session.stop`. |
| `beeuni sessions start <id> [--wait] [--json]` | Wake a session: provision a missing sandbox, resume a stopped one, and resolve its runtime. Idempotent. Alias: `wake`. `--wait` blocks until ready (up to ~5 min) and exits `1` if the session ends up failed or stopped. |
| `beeuni sessions warm [--exclude <id>] [--json]` | Pre-create the session you are about to use, so the sandbox is already up. Reuses an existing unused warm session. A warm session stays hidden from `sessions ls` until its first prompt. |
| `beeuni sessions model <id> <model-id> [--json]` | Change the model a session runs, mid-session. A live sandbox is re-pointed and its runtime restarts, which ends the turn running right now; a stopped session stores the value for its next start. A session with no keys selected for the new model's provider gets every key you may use there. |
| `beeuni sessions compact <id> [--json]` | Summarize the conversation so far and continue from the summary. A session whose runtime does not list `session.compact` exits `1` with the reason. |
| `beeuni sessions queue <id> [ls] [--json]` | List the prompts still waiting in the session's durable inbox. |
| `beeuni sessions queue <id> rm <prompt-id>` | Drop one queued prompt. Refused (`409`) once a model step has started answering it. |
| `beeuni sessions queue <id> now <prompt-id>` | Run one queued prompt next: re-queue it ahead of the ordering rule and release the session's hold. |
| `beeuni sessions queue <id> hold\|release` | Hold every queued prompt — what the Stop button writes — or release the hold. |
| `beeuni sessions approvals <id> [ls] [--json]` | List the governed connector calls this session is waiting on a human for. |
| `beeuni sessions approvals <id> approve\|deny <execution-id>` | Let one governed connector call run, or refuse it. The agent is told and continues without it. |
| `beeuni sessions files <id> <subcommand> [--json]` | Read and edit the sandbox's live workspace: `ls [<path>]`, `status`, `find <query>`, `write <path>`, `touch <path>`, `mkdir <path>`, `mv <from> <to>`, `rm <path>`. |
| `beeuni sessions share <id> [--mode private\|project\|members] [--member <id\|email>] [--group <id>] [--show] [--json]` | Set who inside Beeuni can open this session. With no `--mode` it prints the current setting and changes nothing. `--member` and `--group` are repeatable. |
| `beeuni sessions links <id> ls [--json]` | List every public link ever minted on the session, newest first. |
| `beeuni sessions links <id> create [options]` | Mint one public, unauthenticated link onto a preview port or one workspace file. |
| `beeuni sessions links <id> revoke <share-id>` | Kill one public link. |

`sessions queue` needs `project.session.start` — the same permission as sending
a message. A queued prompt survives a closed terminal and is delivered when the
session can take it. Put one there with
`beeuni sessions chat <id> -p "…" --queue`, or steer the running turn with
`--steer`. `sessions queue ls` shows each prompt's `DELIVERY` (`steer`,
`queue` or `interrupt`) and, for a steer prompt that runs as `queue`, the
reason: `unsupported` (the session cannot take messages mid-turn),
`not_prompter` (another member's turn is running) or `turn_ended`.

`sessions approvals` are durable: unlike `sessions pending`, they survive a
sandbox restart. It needs `project.members.manage`, or being the human who
launched the session. An agent may never resolve its own approval.

`sessions attachments` reads the session's private file store, not its
workspace. Files land there at send time, and every file the agent showed lands
there at the end of the turn.

`sessions files` reads the working tree the agent is editing right now, before
anything is committed; `beeuni files` reads the committed repo instead. Paths
resolve under `/workspace` unless they start with `/workspace`, `/tmp`,
`/home`, or `/opt`. The command wakes the sandbox if it is asleep. Options:
`--from <local path>` (`write` reads this file instead of stdin), `--content`
(`find` greps contents with ripgrep instead of filenames), `--limit <N>`
(`find` filename cap), and `-y` to skip the `rm` confirmation.

`sessions share` is owner-governed: the API refuses a project manager who
cannot already read the session. A shared session runs only on provider keys
shared with the whole project: a model that ran on your own keys switches to
the project's keys for that provider, and with none that runs it, the share is
refused (`409 SHARED_SESSION_NEEDS_PROJECT_KEY`).

`sessions links create` options: `--port <n>` (default `3000`; `22`, `8000`,
and the opencode ports are refused), `--path <p>` (default `/`),
`--preview <id>` (a named candidate — `web`, `vite`, `dev-server`, `api-docs` —
instead of `--port`/`--path`), `--file <path>` (share one workspace file
instead of a preview; always read-only), `--mode view\|interactive` (default `view`;
`interactive` allows writes and websockets, and is ignored for `--file`),
`--label <text>`, and `--expires <iso>`. Minting a link needs the session
owner, because the link itself needs no login; listing and revoking also accept
a project manager.

Inside a sandbox, `BEEUNI_SESSION_ID` is your own session's id.

### Change requests

A change request (CR) merges one branch into another on any git host. It is the only way for an agent to land session work on the default branch. See [Change requests](/docs/work/change-requests).

| Command | Effect |
| --- | --- |
| `beeuni cr ls [--status open\|merged\|closed\|all] [--project <id>]` | List CRs. Default: `--status open`. |
| `beeuni cr show <cr> [--project <id>]` | Show one CR, including its merge preview. Alias: `info`. |
| `beeuni cr diff <cr> [--no-color] [--json]` | Print a CR's unified diff. |
| `beeuni cr open --title "<text>" [--description "<text>"] [--head <ref>] [--session <id>] [--base <ref>]` | Open a CR. Aliases: `new`, `create`. Inside a sandbox, `--head` and `--session` default automatically. `--base` defaults to the project's default branch. |
| `beeuni cr merge <cr> [--message "<text>"]` | Merge an open CR. Fast-forward when possible, three-way merge otherwise. |
| `beeuni cr close <cr>` | Close an open CR without merging. |
| `beeuni cr reopen <cr>` | Reopen a closed CR. Merged CRs are terminal. |
| `beeuni cr merge-preview <cr> [--json]` | Report whether the CR can merge, and list every conflicting path. Alias: `preview`. |
| `beeuni cr request-changes <cr> --message "<text>"` | Ask the agent that opened the CR to revise it. Alias: `changes`. |
| `beeuni cr version-diff --from <ver> --into <ver> [--json]` | Summarize one version against another before opening a CR. |

`request-changes` records the note on the CR and delivers it to the originating
session, booting its sandbox if it is asleep. It needs `project.review.act` —
the same leaf the Review Center uses, not `gitops.push`.

`<cr>` accepts a per-project number (`3`) or the full id. Inside a sandbox, the CLI reads its token automatically — no login or link needed.

### Review

The project's review inbox — everything waiting on a human decision: change
requests, connector tool calls a policy gated for approval, and the outputs,
decisions, and batches agents submit for sign-off. Mirrors the dashboard's
Review Center. On for every project; `project.review.read` and
`project.review.act` gate reading and acting.

| Command | Effect |
| --- | --- |
| `beeuni review ls [--segment <s>] [--kind <k>] [--json]` | List inbox items. Default: every segment. |
| `beeuni review show <item-id> [--json]` | Show one item in full. |
| `beeuni review act <item-id> <verdict> [--message <text>]` | Decide one item. `--message` carries the note. |
| `beeuni review bulk <verdict> <id> [<id> …]` | Decide several native items in one call. |
| `beeuni review submit --kind <k> --title <t> [options]` | Submit an output, decision, or batch for review. |

Verdicts: `approve`, `reject`, `changes`, `answer`, `dismiss`. Segments:
`needs_you`, `waiting`, `done`. Kinds: `change`, `approval`, `output`,
`decision`, `batch`.

Where a verdict lands depends on the item id. On `cr:<id>`, `approve` merges
the change, `reject` closes it, and `changes` sends the note back to the agent
that opened it (`--message` required). On `call:<id>`, `approve` lets the tool
call run and `reject` denies it; a connector approval takes no other verdict —
read its arguments first with `beeuni review show`. Every other id goes to the
native act endpoint, which takes every verdict.

`bulk` acts on native ids only. A connector approval needs its own parameter
review and a change request needs its diff in view, so both are reported and
skipped — the same rule as the dashboard's multi-select.

`submit` options: `--kind output\|decision\|batch` (required), `--title <text>`
(required), `--summary <text>`, `--risk none\|low\|medium\|high` (default
`none`), `--detail <json>` (a JSON object), `--agent <name>`, and
`--session <id>` (ignored when it is not this project's session).

Reads need `project.review.read`, verdicts need `project.review.act`, and
`submit` needs `project.review.submit`.

### Secrets

Encrypted values stored on the project. By default a secret injects as a plain environment variable into every session sandbox at boot (environment exposure). Enforced delivery — where the sandbox holds a handle and Beeuni substitutes the real value outside it (egress-enforced exposure, and `beeuni secrets call`) — is experimental. Enable the `secrets_egress` feature flag (Settings → Feature flags) to use it; with the flag off, `beeuni secrets delivery … egress` returns `403` `feature_disabled`. See [Secrets](/docs/project/secrets).

| Command | Effect |
| --- | --- |
| `beeuni secrets ls` | List secrets by identifier and manifest `env` spec, with who can use each value. Marks required-but-missing values. |
| `beeuni secrets set NAME=VALUE ... [--identifier <id>] [--scope runtime\|connector] [--only-me]` | Upsert one or more secrets. `NAME=-` reads the value from stdin. `--scope connector` keeps the value server-side for the connector gateway. `--only-me` makes the new value usable only by you. |
| `beeuni secrets share IDENTIFIER --user <email\|id\|me> --group <id> --agent <name> \| --everyone` | Set who can use the value. People reach it directly or in their own private sessions; an agent in every one of its sessions, triggers included. See [Who can use a secret](/docs/project/secrets#who-can-use-a-secret). |
| `beeuni secrets request NAME ... [--scope runtime\|connector] [--expires <min>]` | Mint a link for a human to enter a value you do not have. |
| `beeuni secrets unset NAME ...` | Remove secrets. |
| `beeuni secrets grant IDENTIFIER --agent <name>` | Let one agent receive this secret: merge the identifier into that agent's `secrets` list in `beeuni.yaml`, adding the agent entry when the manifest omits it. |

`grant` is the fix for a row `ls` reports as undeliverable. It only ever widens
one agent's list; to narrow or replace it, rewrite the whole set with `beeuni
agents scope`. There is no `secrets revoke` — the API has no route that removes
a single identifier from a grant. The first grant on a project with no agents
starts governance: from then on, an agent the manifest does not list receives
no project secrets, and the command says so when it happens.

### Env

| Command | Effect |
| --- | --- |
| `beeuni env pull [--out <path>] [--force]` | Write a `.env` skeleton — names only. Values never leave the cloud. |
| `beeuni env push --from <path>` | Upload every `NAME=VALUE` from a dotenv file as a secret. |

### Agents

Per-agent model settings on the linked project.

| Command | Effect |
| --- | --- |
| `beeuni agents ls [--json]` | Show every agent's pinned model and the fallback default. Alias: `models`. |
| `beeuni agents model <agent> <provider/model>` | Pin an agent to a model. |
| `beeuni agents model <agent> --clear` | Clear the pin — the agent follows the default again. |
| `beeuni agents default <agent>` | Make this the project's default agent. |
| `beeuni agents default --show [--json]` | Print the current default agent. |
| `beeuni agents scope <agent> [--secrets all\|none\|A,B] [--connectors all\|none\|a,b] [--apps all\|none\|a,b] [--require-connector <slug>]` | Replace which secrets, connectors and Beeuni Apps the agent may use. `--apps` takes App slugs and needs a v2 `beeuni.yaml`; the agent also needs `project.app.read`. `--require-connector` is repeatable and must resolve before a session starts. |
| `beeuni agents scope <agent> --show [--json]` | Print the agent's current scope. |
| `beeuni agents config <agent> [--json]` | Print the full agent config block. |
| `beeuni agents config <agent> --file <path>` | Replace the block with a JSON file's contents. `-` reads stdin. |
| `beeuni agents config <agent> --set <key>=<value> ...` | Change single dotted keys, merged in. Repeatable, e.g. `behavior.model=glm-5.3-flash`, `enabled=false`, `connectors=["slack"]`. |

Every scope option replaces; none merge. A `--set` value is parsed as JSON when
it parses, and kept as a string otherwise. Model pins and `scope` apply
instantly, with no `beeuni.yaml` commit; `default` and `config` commit to
`beeuni.yaml` on the project's default branch. `scope` needs
`project.agent.write`, and so do `default` and `config`.

### Tools

The tools this project's sessions get, read from the local `beeuni.yaml` and its
[imports](/docs/project/manifest#imports). Run from the project root. See
[Tools](/docs/project/tools).

| Command | Effect |
| --- | --- |
| `beeuni tools ls [--json]` | List each tool the sessions get: name, kind (`beeuni`, `beeuni (overridden)`, `project`) and source (`beeuni:<name>` or the module path). Also lists the Beeuni tools the project removed. `--json` prints `{ manifest, tools_key, tools, removed }`. |
| `beeuni tools eject <name> [--force]` | Copy the Beeuni tool `<name>` to `tools/<name>.ts` and set `tools.<name>: tools/<name>.ts` in `beeuni.yaml`, in the file that declares it. The changed line ends with `# ejected from beeuni:<name>`; every other comment stays. With no `tools:` key, it also lists the other four Beeuni tools, so the eject removes nothing. Refuses when `tools/<name>.ts` exists or the tool already points at another module, unless `--force`. Refuses a name that is not a Beeuni tool. |

With no `tools:` key, every session gets all five Beeuni tools (`web_search`,
`image_search`, `scrape_webpage`, `memory`, `show`). With a `tools:` key,
sessions get only the Beeuni tools it lists. To remove a Beeuni tool, delete its
line under `tools:`, then run `beeuni validate`. To limit the tools of one agent,
use `agents.<name>.tools`. Exit codes: `0` done, `1` refused (a file exists, a
manifest or import that does not parse), `2` no manifest, an unknown option, or a
name that is not a Beeuni tool.

### Models

Which models the project offers, and which one it starts with. Same surface as
the dashboard's Customize → Models. A project stores only its exceptions to the
catalog default (the newest model of each family). Enablement is display-only:
it decides what pickers offer, never what the gateway serves.

| Command | Effect |
| --- | --- |
| `beeuni models ls [--json]` | List every model you can run: state, origin, how it is paid for (`VIA`: Beeuni, API key, or ChatGPT — your own, shared with you, or shared with the project), provider. |
| `beeuni models enable <model-id>...` | Offer these models. |
| `beeuni models disable <model-id>...` | Stop offering them. The project default refuses with `409` — change the default first. |
| `beeuni models reset` | Drop every exception; back to the catalog default. |
| `beeuni models default [--json]` | Print the default chain (project → account → platform) and what it resolves to. |
| `beeuni models default <model-id> [--account]` | Set the project default, or the account-wide one with `--account`. |
| `beeuni models default --clear [--account]` | Clear the project, or account, default. |

Model ids are gateway wire ids — a bare managed id (`glm-5.3-flash`) or a BYOK
`provider/model`. Copy one from `beeuni models ls --json`. Per-agent pins live
on `beeuni agents model <agent> <model-id>`. Writes need
`project.model.write`.

### Channels

Manages the project's connection to a chat platform. Tokens are stored encrypted in the project's secrets and resolved server-side — they are never injected into the sandbox.

| Command | Effect |
| --- | --- |
| `beeuni channels status [--json]` | Show the current connection. |
| `beeuni channels connect [--wait] [--timeout <sec>]` | Connect in one step: prints an install link. `--wait` polls until the install lands. |
| `beeuni channels connect --manual [--bot-token <token>] [--signing-secret <secret>]` | Bring-your-own-app mode: save a bot token and signing secret directly. |
| `beeuni channels disconnect [--platform slack\|teams]` | Drop the project's connection — the Slack one, or the Teams one with `--platform teams`. |
| `beeuni channels manifest` | Print the app manifest JSON for the bring-your-own-app path. |
| `beeuni channels email status [--json]` | Inbox and delivery mode for one email connector. |
| `beeuni channels email connect [options]` | Create a managed inbox, or attach an existing AgentMail one. |
| `beeuni channels email disconnect` | Drop the inbox connection. |
| `beeuni channels email policy [--allow <email\|@domain>] [--allow-regex <re>] [--allow-all]` | Replace who may email the agent. |
| `beeuni channels bindings [ls] [--json]` | List every bound channel and the agent, model, and join policy it resolves to. |
| `beeuni channels bind <bindingId> [--agent <name>\|--no-agent] [--model <id>\|--no-model] [--policy <p>]` | Change one binding. `--policy` takes `owner_approval`, `owner_only`, or `project_open`. |

`--platform slack|teams` selects the platform; default `slack`. Teams
`connect` prints the Microsoft admin-consent URL; granting tenant-wide consent
publishes the app to your Teams catalog automatically. See [Connectors](/docs/connect/connectors).

The email channel is AgentMail-backed and needs the `agentmail_email` feature
flag. `email connect` options: `--connector <slug>` (default `beeuni_email`),
`--api-key <k>` (bring your own AgentMail key; `-` reads stdin),
`--display-name <n>` (from-name on outgoing mail; default the project name),
`--username <u>` and `--domain <d>` (a new managed inbox), and
`--inbox-id <id>` with `--email <addr>` (attach an existing inbox — both are
required together). `--allow` is repeatable and puts the policy in restricted mode; a
bare value with no `@`, or one with a leading `@`, is read as a domain.
`--allow-all` clears the list and accepts every sender again.

Email and `bind` writes need `project.connector.write`.

### Connectors

Connectors an agent calls as tools. `add`, `rm`, and `policy set` edit the local `beeuni.yaml`; run `beeuni ship` to apply, unless you pass `--apply` to change the cloud project immediately.

| Command | Effect |
| --- | --- |
| `beeuni connectors ls [--json]` | List connectors and their status. |
| `beeuni connectors show <slug> [--json]` | Show one connector's tools. |
| `beeuni connectors add <slug> --provider <p> [options] [--apply]` | Add a connector. |
| `beeuni connectors rm <slug> [--apply]` | Remove a connector. |
| `beeuni connectors rename <slug> <name>` | Set a connector's display name. |
| `beeuni connectors sync` | Reconcile the catalog from the shipped `beeuni.yaml`. |
| `beeuni connectors credential <slug> [value]` | Set a connector's credential. |
| `beeuni connectors connect <slug>` | Start a one-click connect flow. |
| `beeuni connectors link <slug> [--expires <min>]` | Mint a shareable connect link for a human. |
| `beeuni connectors types [--connector <a,b>] [--out <file>]` | Write TypeScript types for every callable action: a `declare module '@beeuni/sdk'` file that types `connectors.callAction(slug, action, args)` args and `output`. Managed connectors publish no output schema, so their result is `unknown`. Without `--out` it prints to stdout. |
| `beeuni connectors accounts <slug> [--default <label\|id>] [--json]` | List the accounts your calls may run as, with the identity each is connected as. `--default` pins one. |
| `beeuni connectors connections ls [--all] [--json]` | List connections with label, `CONNECTED AS`, owner, `WHO CAN USE` (`owner only`, `everyone`, or the grant labels, with `(not you)` when you list it only to manage it), status, and default. |
| `beeuni connectors connections rename <id> <label…>` | Rename a connection. Only the label changes; no re-authorization. |
| `beeuni connectors connections share <id> [--group <id>]… [--user <email\|id>]… [--everyone]` | Share your own private account: it becomes a shared account only they may use (`--everyone`: the whole project). Needs the right to manage the project's connections. |
| `beeuni connectors apps [<query>] [--category <c>] [--cursor <c>] [--limit <n>] [--json]` | Search the managed toolkit catalog — the slugs `add --provider composio --app <slug>` accepts. Alias: `beeuni connectors toolkits`. Add `--pipedream` for the legacy catalog. |
| `beeuni connectors catalog [<query>] [--cursor <c>] [--json]` | Browse the direct-connector catalogue. Needs the `connectors_api_discover` flag. |
| `beeuni connectors catalog show <id> [--json]` | Show one catalogue record's surfaces. |
| `beeuni connectors sensitive <slug> on\|off` | Gate this connector's reads too — every call then needs approval. Applies now. |
| `beeuni connectors owner <slug> project\|user` | Who authorizes: one project connection, or each member's own. Applies now. |
| `beeuni connectors authorize <slug> [--status] [--scope "<a b>"] [--client-id <id>] [--client-secret <s>] [--success-redirect <url>] [--error-redirect <url>] [--json]` | OAuth 2.1 a connector end to end: discover the server's authorization metadata, register Beeuni as a client (RFC 7591) where the server supports it, and print the URL to approve. `--status` reports the result instead. |
| `beeuni connectors authorize <slug> --device` | Same, using the OAuth 2.0 device flow (RFC 8628): print a code and a URL, then poll until it is approved, denied, or expired. |
| `beeuni connectors policy ls [--json]` | Show project-wide execution policy. Alias: `show`. |
| `beeuni connectors policy set --default <risk\|allow_all> [--apply]` | Set the default execution mode in `beeuni.yaml`. `--apply` sets it live instead. |
| `beeuni connectors policy add <match> <allow\|ask\|block> [--condition <k=v>]` | Add a project-wide rule. Applies now. `--condition` narrows it to a matching argument and is repeatable; `k!=v` negates, and `k` is a dot path into the call's arguments. |
| `beeuni connectors policy rm <match>` | Remove a project-wide rule. Applies now. |
| `beeuni connectors policy <slug> ls\|set <match> <allow\|ask\|block>\|rm <match>\|clear` | Manage one connector's tool-call rules. |

`policy ls`, `show`, `set`, `add`, and `rm` are the project-wide surface, so a
connector named after one of those verbs must be addressed as
`policy <slug> ls`. A `<match>` is a tool name, a glob (`send_*`), or a `/regex/`.

`add` options: `--name <label>`, `--provider <pipedream\|mcp\|openapi\|postman\|graphql\|http>`, `--app <slug>`, `--url <url>`, `--transport <http\|sse>`, `--endpoint <url>`, `--base-url <url>`, `--spec <url\|path>`, `--auth-type <none\|bearer\|basic\|custom>`, `--credential shared`.

### Sandboxes

Manages the project's sandbox images. A template defines an image or Dockerfile plus resources; a build produces the snapshot sessions boot from.

| Command | Effect |
| --- | --- |
| `beeuni sandboxes ls [--json]` | List templates and live provider state. |
| `beeuni sandboxes builds [--json]` | Recent build log. |
| `beeuni sandboxes health [--json]` | Primary template readiness. |
| `beeuni sandboxes add <slug> (--image <i>\|--dockerfile <p>) [options]` | Create a custom template and start a build. |
| `beeuni sandboxes update <slug> [options]` | Update a template. |
| `beeuni sandboxes build <slug>` | Trigger a rebuild. |
| `beeuni sandboxes rebuild <slug>` | Force-rebuild: delete the existing snapshot first. |
| `beeuni sandboxes rm <slug>` | Delete a template. |
| `beeuni sandboxes fix` | Start a session seeded with the last failed build log, to repair it. |
| `beeuni sandboxes provider [--json]` | Show the project's sandbox-provider pin and which providers this host offers. |
| `beeuni sandboxes provider <name> [--timeout <sec>]` | Pin every new session to one provider. Where the target needs its snapshot built first, the API answers with a preparation and the command follows it to completion. Default `--timeout`: 600s. |
| `beeuni sandboxes provider --clear` | Drop the pin and follow the platform default. Alias: `--unpin`. |
| `beeuni sandboxes provider status [--json]` | Show the latest provider transition and its history. Alias: `transition`. |

Pinning a provider needs `project.settings.write`.

`add`/`update` options: `--name <label>`, `--cpu <n>`, `--memory <n>` (GiB), `--disk <n>` (GiB).

### Backends

Databases are Apps with persistent volumes. Manage and connect them through Apps.

[Apps](/docs/feature-flags/apps)

### Marketplace

Browse the Beeuni marketplace, and install an item into a project.

| Command | Effect |
| --- | --- |
| `beeuni marketplace search [query]` | Search marketplace items. |
| `beeuni marketplace list` | List marketplace items. |
| `beeuni marketplace show <id-or-name>` | Show one marketplace item. |
| `beeuni marketplace install <id-or-name>` | Start an agent session that imports the item. |

Options: `--query <text>`, `--type <type>`, `--source <source>`, `--host <name>`, `--project <id>`, `--json`.

Install is agent-driven: it starts a project session that clones the item,
reads it, merges what fits, and opens a change request. There is no
deterministic install/update/remove machinery.

### System skills

The Beeuni system skills are the platform's operational reference for both people and agents. They cover sessions, sandboxes, default runtime, connectors, memory, and channels. This public page is the entry point; the authenticated CLI reads the skills from the running host. Use `beeuni system-skills list` to discover the available skills, then `get` the one you need. The API serves them live, so they match the deployed host version. Do not treat a local copy as current.

| Command | Effect |
| --- | --- |
| `beeuni system-skills list` | List the Beeuni system skills. Default subcommand. |
| `beeuni system-skills get <name> [--full]` | Print one skill's current `SKILL.md`. `--full` adds its referenced files. |
| `beeuni system-skills path [name]` | Print a skill's on-disk directory in this project. |

Options: `--host <name>`, `--json`.

`beeuni skills` is a permanent alias for the same command. Sign in to the host first with `beeuni login`; the skills API requires authentication. Use `--host <name>` when working with another host. A public docs page cannot replace these live, host-specific instructions.

This list is always the system skills, never a mix. Optional skills live in the marketplace: `beeuni marketplace list --type skill`. For command syntax, use `beeuni <command> --help`; for the complete platform reference, read `beeuni system-skills get beeuni-system --full`.

### Connector

The in-sandbox agent's interface to every connector. Every call is checked, resolved, and audited server-side; the CLI never holds a third-party credential. Auth: `BEEUNI_TOKEN`. Output is JSON.

| Command | Effect |
| --- | --- |
| `beeuni connectors discover "<intent>"` | Search tools by natural-language intent. |
| `beeuni connectors show <connector>.<action>` | Show an action's input schema. |
| `beeuni connectors call <connector>.<action> '<json-args>'` | Run a tool. A governed call returns its authenticated `approval_url` immediately. The server resumes the session after one approve or deny decision. Pass large args as `@file.json` or `-` (stdin). |
| `beeuni connectors call <connector>.<action> '<json-args>' --reason "<text>"` | Describe what the call does for the human approver when a policy holds it. The approval card shows it as the agent's description next to the arguments. |
| `beeuni connectors call <connector>.<action> @args.json --attach <file>` | Stage a file and append its reference to the action's attachments array. The gateway writes the bytes into the provider's attachment item. `--attach` repeats; `--attach-path <a.b.c>` names the array. See [Attach files](/docs/connect/connectors#attach-files). |
| `beeuni connectors call <connector>.<action> '<json-args>' --out <file>` | Write the full JSON result to `<file>` and print only a summary: `saved_to`, `bytes`, and `shape` (keys, array lengths, `pageInfo`). See [Large results](/docs/connect/connectors#large-results). |
| `beeuni connectors upload <file> --connector <slug>` | Stage one file. Prints `ref`, `{"$beeuni_attachment":"<id>"}`, to place in call args. |
| `beeuni connectors add <slug> --provider pipedream --app <app>` | Add a connector immediately, then connect it. |
| `beeuni connectors rm <slug>` | Remove a connector from the project. |
| `beeuni connectors connect <slug> [--owner me\|project] [--label <name>]` | Mint a connect link for a human. `--label` suggests a name for a new account, for example a second Gmail. |

### Files

Read-only view of the project's git repo. Operates on the default branch unless `--ref` names another branch, tag, or commit.

| Command | Effect |
| --- | --- |
| `beeuni files ls [<path>]` | List files under a path, recursively. The list stops at 1,000 files and says so; narrow it with a path or use `files search`. |
| `beeuni files cat <path>` | Print a file's contents. |
| `beeuni files search <query> [--content]` | Search filenames, or file contents with `--content`. |
| `beeuni files history <path>` | Commit history for one file. |
| `beeuni files branches` | List branches. |
| `beeuni files commits [--path <p>]` | List commits on `--ref`. |
| `beeuni files show <sha>` | Show one commit and its changed files. |
| `beeuni files diff <sha> [--path <p>]` | Print a commit's unified patch. |
| `beeuni files compare <from> <into>` | Summarize the diff between two refs. |
| `beeuni files download -o <out.zip>` | Download the repo, or the `--path` subtree, at `--ref` as a zip. Alias: `archive`. |

Options on every subcommand: `--ref <ref>`, `--path <p>`, `--limit <n>`, `--json`.
`download` also takes `-o, --out <file>`, which is required.

Every subcommand needs `project.file.read`. `download` additionally refuses any
subtree that would include an agent or skill you are scoped out of — a zip
cannot be filtered mid-stream — so archive a narrower `--path` in that case.

### Triggers

A trigger starts a session from a schedule, a webhook, an app event, or a monitor (experimental). `add`, `rm`, `enable`, `disable` edit the local manifest — run `beeuni ship` to apply. `pause`/`resume` flip a separate, server-side switch. See [Triggers](/docs/connect/triggers).

| Command | Effect |
| --- | --- |
| `beeuni triggers ls [--json]` | List triggers and their runtime state. |
| `beeuni triggers add <slug> [options] [--apply]` | Append a trigger to the manifest. `--apply` creates it on the cloud project now instead: it commits to `beeuni.yaml` on `main` and reconciles. |
| `beeuni triggers set <slug> [options]` | Change a live trigger. Only the flags you pass are written. Always applies now — there is no local form. Alias: `update`. |
| `beeuni triggers rm <slug> [--apply]` | Remove a trigger from `beeuni.yaml`, or from the cloud project now with `--apply`. |
| `beeuni triggers info <slug> [--json]` | Show one trigger. |
| `beeuni triggers events --connector <slug> [--json]` | List the events a connector offers, with each event's settings. |
| `beeuni triggers fire <slug>` | Fire a trigger manually and wait for the run outcome: a failed run exits non-zero with its error, and the fired run's fresh session is cleaned up (a run queued into an existing session is left in place). `--wait <dur>` bounds the wait (default `90s`; `0` returns as soon as the fire is accepted). |
| `beeuni triggers enable <slug> [--apply]` / `disable <slug> [--apply]` | Turn one trigger on or off. |
| `beeuni triggers pause` / `resume` | Deactivate or reactivate every trigger on the project, server-side. |

`add` options: `--type <cron\|webhook\|event\|monitor>` (default `cron`), `--prompt <text>` (required), `--agent <name>`, `--cron <expr>` (6-field, e.g. `"0 0 9 * * 1-5"`), `--run-at <iso>` (run once at this instant instead of on a cron), `--timezone <tz>` (default UTC), `--secret-env <NAME>`, `--name <label>`, `--disabled`.

Live-only options — valid on `add --apply`, and on every `set`: `--model <provider/model>`, `--session-mode <fresh\|keyed\|pinned\|reuse>`, `--session-key <tmpl>` (bucket one session per key, e.g. `"{{ body.data.chat_jid }}"`; implies `keyed`), `--session-id <id>` (the session a `pinned` trigger loops; must be this project's session), `--session-access <private\|project\|members>` (default `private`), `--member <uuid>` and `--group <uuid>` (repeatable; each implies `members`), and `--filter <path=value>` (repeatable; every one must match, e.g. `--filter body.type=push`).

`set` takes every live-only option plus `--name`, `--prompt`, `--cron`, `--run-at`, `--timezone`, `--secret-env`, `--agent`, and `--enabled true|false`. `--cron` and `--run-at` are exclusive: setting one clears the other. Monitor fields are add-only.

### Reminders

A reminder re-prompts one session later, once or on repeat. It is stored in the database, not `beeuni.yaml`. Inside a session, `--session` defaults to `$BEEUNI_SESSION_ID`. See [Reminders](/docs/connect/reminders).

| Command | Effect |
| --- | --- |
| `beeuni remind "<text>" [schedule]` | Create a reminder. Same as `beeuni reminders add`. |
| `beeuni reminders add "<text>" [schedule]` | Create a reminder. Prints its id and next fire. |
| `beeuni reminders ls [--json]` | List the session's reminders. |
| `beeuni reminders pause <id>` / `resume <id>` | Turn one reminder off or on. `resume` re-arms from now. |
| `beeuni reminders rm <id>` | Delete a reminder. Aliases: `stop`, `delete`. |

Schedule options: `--in <duration>` or `--at <iso>` (first fire; alone, fire once), `--every <duration>` (repeat, min `5m`), `--cron "<expr>"` with `--timezone <tz>`. Other options: `--name <label>`, `--session <id>` (a unique prefix works), `--project <id>`, `--host <name>`, `--json`.

Event options (`--type event`): `--connector <slug>` and `--event <TYPE>` (both required), `--config key=value` (repeatable, string values), and `--config-json '{...}'` (typed values). `set` accepts the same flags. An event trigger rejects `--cron`, `--run-at`, `--timezone`, `--secret-env`, and the monitor options. The prompt reads `{{ event.data.<field> }}`; see [App event triggers](/docs/connect/triggers#app-event-triggers).

Monitor options (`--type monitor`): `--run <cmd>` (repo-relative command to supervise; required), `--mode <poll\|stream>` (required; `poll` re-runs on `--interval`, `stream` keeps the command alive), `--interval <dur>` (`mode=poll` only, minimum 30s, e.g. `60s`, `5m`), and `--expect-event-within <dur>` (silence watchdog; no event inside the window fires a lifecycle event instead, minimum 5m, e.g. `24h`). A monitor is a repo command the platform runs 24/7, and each stdout line fires the trigger. It is experimental: the platform runs monitors only where the `monitors` feature flag is on.

### Access

The CLI face of the one grant table. Every row is an **assignment**: one
principal, one role, one scope, optionally narrowed to one object. See
[Accounts & access](/docs/accounts#one-access-model) for the model. Account
roles: `owner`, `admin`, `member`. Project roles: `manager`, `member`.

| Command | Effect |
| --- | --- |
| `beeuni access assignments [--project <id>\|--account\|--all] [--json]` | List assignments at one project, at the account, or everywhere. |
| `beeuni access grant --user <id\|email>\|--group <id>\|--service-account <id> --role <key\|id> [opts]` | Create one assignment. Prints the assignment id. |
| `beeuni access revoke <assignment-id>` | Revoke one assignment. |

Grant options: `--project <id>` (default: the linked project), `--account` (the
whole account), `--agent <name>` (narrow the grant to one agent — an object
assignment), `--connection <id>` (narrow the use of one shared connector
account; the first grant limits the account to its grantees, and revoking the
last opens it to the whole project again), `--everyone` (grant to everyone with
access to the project; it holds an `--agent` or a `--connection`, never a
role), and `--expires <iso>` (auto-revoke timestamp). `--principal` filters
a list, and takes `user:<id>`, `group:<id>`, `service_account:<id>`,
`project:<id>`, or `pending:<email>`; a bare id is read as a user. A grant to
everyone lists as `everyone`. An agent's identity is a
`service_account`, so `--service-account <id>` is how you assign a role to an
agent. `--user` accepts an email and resolves it against the account member
directory.

```bash
beeuni access grant --user alice@corp.com --role manager
beeuni access grant --user alice@corp.com --role admin --account
beeuni access grant --group 8f3c… --role member --project 1a2b…
beeuni access grant --user alice@corp.com --agent support-bot
beeuni access grant --everyone --agent support-bot
beeuni access grant --group 8f3c… --connection 2b7e…
beeuni access revoke 4d5e…
```

The project member verbs are a read model over the same assignments:

| Command | Effect |
| --- | --- |
| `beeuni access ls [--json]` | List the people with project access, their account role, and their effective project role. |
| `beeuni access invite <email> --role <r>` | Invite someone to the project. Creates a `pending` assignment. |
| `beeuni access grant <user-id> --role <r>` | Set a user's project role. |
| `beeuni access revoke <user-id>` | Remove a user's project access. |
| `beeuni access pending [--json]` | List pending invitations. |
| `beeuni access resend <invite-id>` | Re-send an invite email and refresh its 14-day expiry. Prints the link too. |
| `beeuni access cancel <invite-id>` | Cancel a pending invitation. |
| `beeuni access requests ls [--json]` | List the pending requests from people asking to join this project. |
| `beeuni access requests approve <req-id> [--role <r>]` | Approve one request, granting the project role. Default role: `member`. |
| `beeuni access requests reject <req-id>` | Reject one request. Alias: `deny`. |

Every verb in the two blocks above needs `project.members.manage`.

A person, a group, or an agent gets roles from Beeuni; an agent additionally
carries Beeuni permissions in `beeuni.yaml`, and a session can only do what both
allow. See [One vocabulary, two bindings](/docs/accounts#one-vocabulary-two-bindings).

### Audit

The audit commands read the centralized reconstruction log. Account and project
lists are newest first. A session timeline is ordered by creation time
(`session_sequence` is set only on rows written before 2026-10, which come
first). `--all` follows every continuation cursor. `ls` lists the last 90 days; `export` reaches back 365 days, and events older than 90 days come from the archive (see [Audit retention](/docs/accounts#retention)). The table shows
each row's title (`EVENT`, for example "Revoked LLM gateway key") next to its
`ACTION` (`gateway.key.revoke`); `--action` filters by action prefix. Every
action and title: [Audit log actions](/docs/audit-actions).

| Command | Effect |
| --- | --- |
| `beeuni audit ls [filters] [--all] [--json]` | List account events. |
| `beeuni audit project <project-id> [filters] [--all] [--json]` | List one project's events. |
| `beeuni audit session <session-id> --project <project-id> [--all] [--json]` | Reconstruct one session in order. |
| `beeuni audit export [filters] --format csv\|jsonl --out <file>` | Resume every export page into one file. |
| `beeuni audit webhooks ls [--json]` | List the account's audit webhooks. |
| `beeuni audit webhooks add --name <n> --url <u> [--action-prefix <p>]` | Create one. The signing secret prints once, and a test delivery fires immediately. `--action-prefix` delivers only actions with that prefix. |
| `beeuni audit webhooks enable <webhook-id>` | Resume delivery. |
| `beeuni audit webhooks disable <webhook-id>` | Pause delivery, keeping the endpoint. |
| `beeuni audit webhooks rm <webhook-id>` | Delete a webhook permanently. |

Audit webhooks stream the trail to a SIEM. Every verb needs `account.write`;
`add` and `enable` also need the enterprise entitlement. `disable` and `rm`
never do.

Filters: `--actor`, `--actor-type`, `--project`, `--session`, `--source`,
`--phase`, `--outcome`, `--action`, `--resource-type`, `--request-id`,
`--correlation-id`, `--query`, `--since`, `--until`, `--cursor`, and `--limit`.
Account lists and exports require `audit.read` and the account's `auditAccess`
entitlement. Project-wide lists require `project.members.manage` because they can
include private-session metadata. Session reconstruction requires
`project.session.read` and visibility of that session.

### Roles

A role is a named set of permissions. System roles (`owner`, `admin`, `member`
at account scope; `manager`, `member` at project scope; plus `agent-user`, the
marker an object assignment carries) are read-only references. Custom roles are
yours to create and edit, and need the enterprise `rbac` entitlement.

| Command | Effect |
| --- | --- |
| `beeuni roles ls [--json]` | List roles, system and custom. |
| `beeuni roles show <role> [--json]` | Show one role's permissions and usage. |
| `beeuni roles permissions <role> [--json]` | List one role's permissions. |
| `beeuni roles create <key> --name <n> [options]` | Create a custom role. |
| `beeuni roles edit <role> [--name <n>] [--desc <t>\|--no-desc]` | Rename or re-describe a custom role. Its key never changes. Needs `role.update`, and refuses a system role. |
| `beeuni roles set-actions <role> --actions a,b` | Replace a custom role's permissions. |
| `beeuni roles rm <role>` | Delete a custom role. |
| `beeuni roles export [--project <id>] [--out <file>] [--format toml\|json]` | Dump roles and assignments to a file. |
| `beeuni roles import <file>` | Apply a roles and assignments file. |

Bind a role to a principal with `beeuni access grant`. The older `beeuni roles
assign` / `unassign` / `assignments` verbs still work and write the same table,
but `beeuni access` is the documented path. `beeuni roles actions` is superseded
by `beeuni permissions ls`.

A custom role only adds permissions. Beeuni has no deny rule, so a role cannot
withhold a permission from a manager.

### Permissions

The permission catalog, as data. One row per leaf action, with the scope it is
decided at, whether it is delegable, and what it implies. Roles are built from
these keys — `beeuni roles create --actions` and `beeuni roles set-actions` take
exactly them. Alias: `beeuni perms`.

| Command | Effect |
| --- | --- |
| `beeuni permissions ls [--scope account\|project] [--area <a>] [--json]` | List the catalog. |
| `beeuni permissions show <action> [--json]` | Show one action in full. |

### Grants

Assigns one project object to a principal — an **object assignment**. Secrets and
connectors live on agents, so assigning an agent to a person grants everything
that agent declares. An agent is closed by default: a member reaches it only when
an assignment names them or one of their groups. `beeuni access grant --agent
<name>` writes the same row.

| Command | Effect |
| --- | --- |
| `beeuni grants ls [--json]` | List object assignments, and which agents can be assigned. |
| `beeuni grants assign <agent-name> --to <who> [--group]` | Assign an agent to a user, or to a group with `--group`. |
| `beeuni grants revoke <grant-id>` | Revoke one object assignment. |

### Manifest validation

| Command | Effect |
| --- | --- |
| `beeuni validate [--file <path>] [--json] [--scopes] [--no-dockerfile-lint]` | Validate the manifest against the canonical schema, lint every sandbox Dockerfile and the agent wiring, and check the repository size. Resolves `beeuni.yaml` first, then `beeuni.toml`. Exit codes: `0` valid (warnings may be present), `1` errors, `2` file missing. `beeuni ship` runs the same checks. |
| `beeuni schema [--version 1\|2] [--url]` | Print the manifest's JSON Schema. `--url` prints the schema URL instead. |

See [Manifest reference](/docs/project/manifest).

#### Repository size

A session builds its [agent config](/docs/work/runtime#where-a-box-gets-the-release) from every file Git tracks at the base commit. A new session takes those files from its own checkout, whatever the size. A running session picks up a base-branch change through the project snapshot, which Beeuni cloud builds up to 512 MiB compressed; above that, the session keeps the config it runs until a new session starts. Every session also downloads every file. `beeuni validate` counts the files Git stores, plus the untracked files `beeuni ship` commits next, and prints a warning when one file is 10 MiB or more or the total is over 512 MiB. A Git LFS file counts as its pointer, because the release holds only the pointer. The warning names the largest files. It never fails the command.

To clear it:
- Move big static assets (video, images, datasets, model weights) to object storage such as S3, R2, or GCS, or a CDN, and download them at runtime.
- Add build output (`dist/`, `out/`) to `.gitignore`.
- For a path that must stay in Git but that no agent reads, add `<path> export-ignore` to `.gitattributes`. The release leaves it out, and so does the check; a directory rule covers everything under it. The agent config dir and `beeuni.yaml` always ship whole.

### Token scope

Every token starts with `beeuni_pat_`. A user token is scoped to every project on your accounts. A project token is scoped to one project and auto-injected into that project's sandboxes. See the full token-family reference at [Session runtime](/docs/work/runtime).

### Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success. |
| `1` | Operation failed. Diagnostics print to stderr. |
| `2` | Bad flag, unknown subcommand, or missing required argument. |
