Skip to main content
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 pointPackageNotes
agnoagno >= 2.7, agnoctlPrimary command
agnoctlagnoctlSame 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

VariableRead byPurpose
AGENTOS_URLconnect, disconnect, status, tokensAgentOS base URL when --url is not passed. Skips the env-file lookup and localhost probe.
AGNO_ADMIN_TOKENconnect, disconnect --revoke, tokensAdmin credential for the service-accounts API. Checked first.
OS_SECURITY_KEYconnect, disconnect --revoke, tokensAdmin 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

CodeMeaning
0Success. For connect: every selected client connected, was already connected, is configured pending a one-time OAuth sign-in, or received manual steps.
1Error. For connect: no client connected.
2Usage error (unknown command, flag, or argument).
3Partial 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:
// 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
}
// 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

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 _.
FlagDefaultDescription
--template, -tagentos-dockerStarter template: agentos-aws, agentos-docker, agentos-fly, agentos-gcp, agentos-railway
--url, -unoneClone from a custom template repository URL instead
--jsonoffEmit a single JSON document
JSON output:
{"path": "/abs/path/my-os", "template": "agentos-docker"}

agno connect

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.
FlagDefaultDescription
--urlautodiscoverAgentOS base URL
--clientsdetected, plus claude-ai/chatgpt steps when the AgentOS is on a public URLComma-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).
--nameone account per clientUse one shared service account with this name
--scopes, -sserver’s run + read scopesScope to grant (repeatable)
--expires90dToken lifetime in days (90d, 30) or never
--privilegedoffRequired when --scopes grants write, delete, admin, or service_accounts scopes
--patoffMint service-account tokens even when the MCP endpoint is OAuth-protected (for headless clients)
--server-namederived from the AgentOS name, fallback agentosMCP server entry name written to client configs. Letters, digits, -, _ only.
--projectoffWrite project-scoped configs (.mcp.json / .cursor/mcp.json) instead of user-level
--rotateoffRewrite existing entries without asking: revoke and re-mint their accounts, or convert them to OAuth sign-in
--skip-existingoffNever touch existing accounts or config entries
--allow-httpoffPermit sending credentials over plaintext HTTP to a non-loopback host
--yes, -yoffTrust a remote AGENTOS_URL from a .env file without prompting
--jsonoffEmit a single JSON document
Config locations per client:
ClientUser scopeProject scope (--project)
claude-code~/.claude.json<cwd>/.mcp.json
claude-desktopclaude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\, Linux: ~/.config/Claude/)n/a
codex~/.codex/config.tomln/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:
{
  "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

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.
FlagDefaultDescription
--urlautodiscoverAgentOS base URL
--clientsdetectedComma-separated clients; claude-ai and chatgpt print manual removal steps
--server-nameevery entry pointing at the target AgentOSRemove exactly this entry name
--nameone account per clientWith --revoke: the shared service-account name used at connect time
--revokeoffAlso revoke the matching service accounts (needs the OS and an admin credential)
--allow-httpoffPermit sending credentials over plaintext HTTP to a non-loopback host
--yes, -yoffTrust a remote AGENTOS_URL from a .env file without prompting
--jsonoffEmit 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:
{
  "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

agno status [--url <url>] [--server-name <name>] [--json]
FlagDefaultDescription
--urlautodiscoverAgentOS base URL
--server-namederived from the AgentOS name, fallback agentosMCP server entry name to look for in client configs
--jsonoffEmit a single JSON document
JSON output:
{
  "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

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.
FlagCommandsDescription
--file, -fallCompose file to use
--pull, -pup, restartAdd --pull always to the compose command
--volumes, -vdownAdd --volumes (removes named volumes, destroys data)
--dry-run, -drallPrint the compose command without running it
--jsonallEmit a single JSON document
JSON output for up and down:
{"command": ["docker", "compose", "-f", "…", "up", "-d", "--build"], "compose_file": "…", "dry_run": false}
restart nests both phases:
{"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

agno tokens create <name> [-s <scope>]... [--expires 90d] [--privileged] [--json]
FlagDefaultDescription
--scopes, -sagents:run, teams:run, workflows:run, sessions:read, config:readScope to grant (repeatable)
--expires90dDays until expiry (90d, 30) or never
--privilegedoffRequired 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:
{"id": "…", "name": "ci-runner", "principal": "sa:ci-runner", "scopes": ["…"], "expires_at": 1774915200, "…": "…", "token": "agno_pat_…"}

agno tokens list

agno tokens list [--json]
Lists all service accounts, including revoked ones. Only metadata and the token display prefix are returned, never tokens.
{"service_accounts": [{"…": "service-account object"}]}

agno tokens revoke

agno tokens revoke <name> [--yes] [--json]
FlagDefaultDescription
--yes, -yoffSkip 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.
{"revoked": {"…": "service-account object with revoked_at set"}}

Developer Resources