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

# Agno CLI

> Flags, environment variables, exit codes, and JSON output contracts for every agno CLI command.

The `agno` CLI is published as the `agnoctl` package and ships as a dependency of `agno` 2.7+. Installing either package puts the CLI on your PATH:

| Entry point | Package                  | Notes                                                                 |
| ----------- | ------------------------ | --------------------------------------------------------------------- |
| `agno`      | `agno` >= 2.7, `agnoctl` | Primary command                                                       |
| `agnoctl`   | `agnoctl`                | Same app. Enables `uvx agnoctl <command>` without installing the SDK. |

`agnoctl` requires Python >= 3.9 and depends on `typer`, `rich`, and `httpx` (plus `tomli` on Python \< 3.11). It never imports `agno`.

Running bare `agno` prints the command catalog. `agno --version` prints the CLI version.

## Environment Variables

| Variable           | Read by                                     | Purpose                                                                                     |
| ------------------ | ------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `AGENTOS_URL`      | `connect`, `disconnect`, `status`, `tokens` | AgentOS base URL when `--url` is not passed. Skips the env-file lookup and localhost probe. |
| `AGNO_ADMIN_TOKEN` | `connect`, `disconnect --revoke`, `tokens`  | Admin credential for the service-accounts API. Checked first.                               |
| `OS_SECURITY_KEY`  | `connect`, `disconnect --revoke`, `tokens`  | Admin credential fallback when `AGNO_ADMIN_TOKEN` is unset.                                 |

When neither credential variable is set and the AgentOS enforces authorization, the CLI prompts interactively. In `--json` mode or with a non-TTY stdin it exits with an error instead of prompting.

## Discovery

Commands that talk to an AgentOS resolve its URL in this order: `--url` flag, `AGENTOS_URL` env var, `AGENTOS_URL` read from `.env.production` then `.env` in the current directory, then a probe of `http://localhost:7777`, `:7778`, `:7779`, and `:8000`. Interactive `connect` and `disconnect` runs probe all candidates (including URLs found in existing client configs) and prompt when more than one AgentOS answers; `--json` and non-TTY runs resolve the single highest-priority target.

Each candidate is checked with `GET /health`, then `GET /info`. Servers that report structured discovery fields (`mcp: {enabled, path}` and `auth_mode`) are read directly; older servers are probed with a `POST /mcp` (MCP mounted or not) and an unauthenticated `GET /config` (auth mode by status code). Detected auth modes: `none`, `security_key`, `jwt`, `unknown`.

## Exit Codes

| Code | Meaning                                                                                                                                                   |
| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`  | Success. For `connect`: every selected client connected, was already connected, is configured pending a one-time OAuth sign-in, or received manual steps. |
| `1`  | Error. For `connect`: no client connected.                                                                                                                |
| `2`  | Usage error (unknown command, flag, or argument).                                                                                                         |
| `3`  | Partial success (`connect` and `disconnect`): some clients succeeded, others failed.                                                                      |

## Machine Mode (`--json`)

Every command accepts `--json`:

* stdout carries exactly one JSON document and nothing else.
* Interactive prompts are disabled. Runs that would need one fail with an error.
* Errors emit `{"error": "<message>", "hint": "<optional hint>"}` and exit non-zero.

The document shapes per command are listed below. Two shared objects appear throughout:

```json theme={null}
// OS object
{
  "url": "http://localhost:7777",
  "name": "AgentOS",
  "os_id": "…",
  "version": "2.7.0",
  "mcp": {"enabled": true, "path": "/mcp", "oauth": null},
  "auth_mode": "jwt",
  "discovered_via": "info",
  "url_source": "default",
  "url_source_file": null
}
```

```json theme={null}
// Service-account object (the plaintext token is excluded)
{
  "id": "…",
  "name": "claude-code",
  "principal": "sa:claude-code",
  "token_prefix": "agno_pat_…",
  "scopes": ["agents:run", "teams:run", "workflows:run", "sessions:read", "config:read"],
  "created_at": 1767139200,
  "expires_at": 1774915200,
  "last_used_at": null,
  "revoked_at": null
}
```

`url_source` is `flag`, `env`, `env-file`, `client-config`, or `default`. `url_source_file` names the env file or client configs the URL came from. `mcp.oauth` carries `{authorization_servers, resource}` when `/mcp` is OAuth-protected. `discovered_via` is `info` or `probe`. Timestamps are Unix epoch seconds.

## agno create

```bash theme={null}
agno create <name> [--template <starter>] [--url <repo>] [--json]
```

Scaffolds a project by shallow-cloning a template repository (`git clone --depth 1`, 300s timeout) into `./<name>` and removing its `.git` directory. It requires `git` and fails if the directory already exists. `<name>` must be a single path segment of letters, digits, `-`, and `_`.

| Flag               | Default          | Description                                                                                        |
| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------- |
| `--template`, `-t` | `agentos-docker` | Starter template: `agentos-aws`, `agentos-docker`, `agentos-fly`, `agentos-gcp`, `agentos-railway` |
| `--url`, `-u`      | none             | Clone from a custom template repository URL instead                                                |
| `--json`           | off              | Emit a single JSON document                                                                        |

JSON output:

```json theme={null}
{"path": "/abs/path/my-os", "template": "agentos-docker"}
```

## agno connect

```bash theme={null}
agno connect [OPTIONS]
```

Connects coding agents to a running AgentOS over MCP. It discovers the AgentOS, mints one service account per client, writes each client's MCP config, reads the entry back, and verifies it with a real MCP `initialize` + `tools/list` handshake. The AgentOS must have `mcp_server=True`. When `/mcp` is OAuth-protected, entries are written without tokens, nothing is minted, and each app completes a one-time sign-in; `--pat` opts back into minted tokens.

| Flag              | Default                                                                        | Description                                                                                                                                                                                                                |
| ----------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--url`           | autodiscover                                                                   | AgentOS base URL                                                                                                                                                                                                           |
| `--clients`       | detected, plus `claude-ai`/`chatgpt` steps when the AgentOS is on a public URL | Comma-separated clients: `claude-code`, `claude-desktop`, `codex`, `cursor`; `claude-ai` and `chatgpt` print manual setup steps. Aliases: `claude` (Claude Code), `claude-app` (Claude Desktop), `gpt`/`openai` (ChatGPT). |
| `--name`          | one account per client                                                         | Use one shared service account with this name                                                                                                                                                                              |
| `--scopes`, `-s`  | server's run + read scopes                                                     | Scope to grant (repeatable)                                                                                                                                                                                                |
| `--expires`       | `90d`                                                                          | Token lifetime in days (`90d`, `30`) or `never`                                                                                                                                                                            |
| `--privileged`    | off                                                                            | Required when `--scopes` grants write, delete, admin, or service\_accounts scopes                                                                                                                                          |
| `--pat`           | off                                                                            | Mint service-account tokens even when the MCP endpoint is OAuth-protected (for headless clients)                                                                                                                           |
| `--server-name`   | derived from the AgentOS name, fallback `agentos`                              | MCP server entry name written to client configs. Letters, digits, `-`, `_` only.                                                                                                                                           |
| `--project`       | off                                                                            | Write project-scoped configs (`.mcp.json` / `.cursor/mcp.json`) instead of user-level                                                                                                                                      |
| `--rotate`        | off                                                                            | Rewrite existing entries without asking: revoke and re-mint their accounts, or convert them to OAuth sign-in                                                                                                               |
| `--skip-existing` | off                                                                            | Never touch existing accounts or config entries                                                                                                                                                                            |
| `--allow-http`    | off                                                                            | Permit sending credentials over plaintext HTTP to a non-loopback host                                                                                                                                                      |
| `--yes`, `-y`     | off                                                                            | Trust a remote `AGENTOS_URL` from a `.env` file without prompting                                                                                                                                                          |
| `--json`          | off                                                                            | Emit a single JSON document                                                                                                                                                                                                |

Config locations per client:

| Client           | User scope                                                                                                                              | Project scope (`--project`) |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| `claude-code`    | `~/.claude.json`                                                                                                                        | `<cwd>/.mcp.json`           |
| `claude-desktop` | `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`, Linux: `~/.config/Claude/`) | n/a                         |
| `codex`          | `~/.codex/config.toml`                                                                                                                  | n/a                         |
| `cursor`         | `~/.cursor/mcp.json`                                                                                                                    | `<cwd>/.cursor/mcp.json`    |

Token-bearing config files are written with mode `0600`. The Claude Desktop entry launches the `mcp-remote` stdio bridge via `npx` and passes the token through an `AGNO_AUTH_HEADER` env entry in the config, keeping it out of argv.

Exit codes: `0` all connected, `1` nothing connected, `2` usage error, `3` partial. JSON output:

```json theme={null}
{
  "os": { "…": "OS object" },
  "server_name": "agentos",
  "results": [
    {
      "client": "claude-code",
      "status": "connected",
      "error": null,
      "location": "/Users/you/.claude.json (user scope)",
      "account": { "…": "service-account object" },
      "verify": {"ok": true, "tools": 12, "status_code": 200, "error": null, "oauth_challenge": false}
    }
  ],
  "warning": null,
  "exit_code": 0
}
```

Result `status` values: `connected`, `already-connected`, `needs-login` (OAuth entry written; carries an `instructions` array with the client's sign-in step), `skipped`, `failed`, and `manual` (chat apps; carries `url` and an `instructions` array instead of `location`). Optional result fields: `note`, `rotated` (a different token was replaced; restart the client), `replaced_url` (the entry previously pointed at another AgentOS), `replaced_legacy` (a stale `agno`-named entry was renamed), `replaced_token_entry` (a token-carrying entry was replaced by a tokenless one; the account behind it stays valid), `auto` (chat-app steps surfaced automatically). `warning` is set when the AgentOS accepts unauthenticated MCP requests despite enforcing auth elsewhere (a pre-enforcement agno version).

## agno disconnect

```bash theme={null}
agno disconnect [OPTIONS]
```

Removes the AgentOS MCP entries from client configs. It works offline by default and needs no running AgentOS or admin credential. Without `--server-name`, every entry pointing at the target AgentOS is removed (its live address, or every address discovery would have tried when nothing answers). Entries pointing at any other server are never touched.

| Flag            | Default                                    | Description                                                                      |
| --------------- | ------------------------------------------ | -------------------------------------------------------------------------------- |
| `--url`         | autodiscover                               | AgentOS base URL                                                                 |
| `--clients`     | detected                                   | Comma-separated clients; `claude-ai` and `chatgpt` print manual removal steps    |
| `--server-name` | every entry pointing at the target AgentOS | Remove exactly this entry name                                                   |
| `--name`        | one account per client                     | With `--revoke`: the shared service-account name used at connect time            |
| `--revoke`      | off                                        | Also revoke the matching service accounts (needs the OS and an admin credential) |
| `--allow-http`  | off                                        | Permit sending credentials over plaintext HTTP to a non-loopback host            |
| `--yes`, `-y`   | off                                        | Trust a remote `AGENTOS_URL` from a `.env` file without prompting                |
| `--json`        | off                                        | Emit a single JSON document                                                      |

Result `status` values: `removed` (carries a `removed` array of entry names), `not-found`, `failed`, and `manual` (chat apps). Exit codes: `0` all removed or nothing to remove, `1` every removal failed, `3` partial (including failed revocations). JSON output:

```json theme={null}
{
  "os": { "…": "OS object, or null when no AgentOS answered" },
  "server_name": null,
  "target_urls": ["http://localhost:7777"],
  "results": [
    {"client": "claude-code", "status": "removed", "error": null, "removed": ["agentos"], "location": "/Users/you/.claude.json"}
  ],
  "revocations": [],
  "exit_code": 0
}
```

`revocations` is populated by `--revoke`: `{"account": "<name>", "status": "revoked" | "not-found" | "failed", "error": null}` per account.

## agno status

```bash theme={null}
agno status [--url <url>] [--server-name <name>] [--json]
```

| Flag            | Default                                           | Description                                         |
| --------------- | ------------------------------------------------- | --------------------------------------------------- |
| `--url`         | autodiscover                                      | AgentOS base URL                                    |
| `--server-name` | derived from the AgentOS name, fallback `agentos` | MCP server entry name to look for in client configs |
| `--json`        | off                                               | Emit a single JSON document                         |

JSON output:

```json theme={null}
{
  "os": { "…": "OS object" },
  "clients": [
    {"client": "claude-code", "detected": true, "configured": true, "location": "/Users/you/.claude.json (user scope)"},
    {"client": "codex", "detected": false, "configured": false, "location": null}
  ]
}
```

## agno up / down / restart

```bash theme={null}
agno up [--file <compose>] [--pull] [--dry-run] [--json]
agno down [--file <compose>] [--volumes] [--dry-run] [--json]
agno restart [--file <compose>] [--pull] [--dry-run] [--json]
```

Run `docker compose` against the project's compose file (600s timeout). Without `--file`, the first of `docker-compose.yml`, `docker-compose.yaml`, `compose.yml`, `compose.yaml` found in `./` then `./infra` is used. `up` runs `docker compose up -d --build`; `down` runs `docker compose down`; `restart` runs `down`, waits 2 seconds, then `up`.

| Flag               | Commands        | Description                                            |
| ------------------ | --------------- | ------------------------------------------------------ |
| `--file`, `-f`     | all             | Compose file to use                                    |
| `--pull`, `-p`     | `up`, `restart` | Add `--pull always` to the compose command             |
| `--volumes`, `-v`  | `down`          | Add `--volumes` (removes named volumes, destroys data) |
| `--dry-run`, `-dr` | all             | Print the compose command without running it           |
| `--json`           | all             | Emit a single JSON document                            |

JSON output for `up` and `down`:

```json theme={null}
{"command": ["docker", "compose", "-f", "…", "up", "-d", "--build"], "compose_file": "…", "dry_run": false}
```

`restart` nests both phases:

```json theme={null}
{"down": {"…": "…"}, "up": {"…": "…"}, "compose_file": "…", "dry_run": false}
```

## agno tokens

The `tokens` subcommands are admin operations against the AgentOS service-accounts API. All three accept `--url`, `--json`, `--allow-http`, and `--yes` (trust a remote `AGENTOS_URL` from a `.env` file without prompting), and resolve the admin credential from `AGNO_ADMIN_TOKEN` / `OS_SECURITY_KEY` (or a prompt) when the AgentOS enforces authorization. The CLI refuses to send credentials over plaintext HTTP to a non-loopback host without `--allow-http`.

### agno tokens create

```bash theme={null}
agno tokens create <name> [-s <scope>]... [--expires 90d] [--privileged] [--json]
```

| Flag             | Default                                                                    | Description                                                         |
| ---------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| `--scopes`, `-s` | `agents:run`, `teams:run`, `workflows:run`, `sessions:read`, `config:read` | Scope to grant (repeatable)                                         |
| `--expires`      | `90d`                                                                      | Days until expiry (`90d`, `30`) or `never`                          |
| `--privileged`   | off                                                                        | Required to grant write, delete, admin, or service\_accounts scopes |

`<name>` is a lowercase slug (max 63 chars): `a-z`, `0-9`, `-`, `_`, starting with a letter or digit. A name that already exists is a conflict; revoke it or pick another. The plaintext token appears once in the output and is never retrievable again.

JSON output is the service-account object plus a `token` field:

```json theme={null}
{"id": "…", "name": "ci-runner", "principal": "sa:ci-runner", "scopes": ["…"], "expires_at": 1774915200, "…": "…", "token": "agno_pat_…"}
```

### agno tokens list

```bash theme={null}
agno tokens list [--json]
```

Lists all service accounts, including revoked ones. Only metadata and the token display prefix are returned, never tokens.

```json theme={null}
{"service_accounts": [{"…": "service-account object"}]}
```

### agno tokens revoke

```bash theme={null}
agno tokens revoke <name> [--yes] [--json]
```

| Flag          | Default | Description                                                                 |
| ------------- | ------- | --------------------------------------------------------------------------- |
| `--yes`, `-y` | off     | Skip confirmation prompts (revoking, and trusting a remote `.env`-file URL) |

Revoking is irreversible; the account's tokens stop working on their next request. Interactive runs confirm first. `--yes`, `--json`, and non-TTY runs skip the prompt.

```json theme={null}
{"revoked": {"…": "service-account object with revoked_at set"}}
```

## Developer Resources

* [Agno CLI guides](/agent-os/cli/overview)
* [Service accounts](/agent-os/security/authorization/service-accounts)
* [Scopes](/agent-os/security/authorization/scopes)
