Skip to main content

CLI overview

This page is the front door to the platformctl reference. You will learn what the CLI covers, how to install it, how it decides which endpoint to call and which credential to send, where its config file lives, and how it behaves when things go wrong.

What platformctl is

platformctl is the command-line tool for the Crusoe AI Platform. It is one self-contained program written in Go — no runtime, no plugins. It packages a folder of agent code, uploads it, waits for the platform to build and start it, and then lets you chat with the agent, read its logs, set its secrets, and delete it.

It also administers the rest of the platform. Serverless container services, pub/sub topics and subscriptions, memory stores, vector indexes and the points inside them, MCP servers, the project secret store, projects, organizations, platform users, project membership, service accounts, API keys, invitations, quota, and the audit trail all have commands. That is 35 command groups and, not counting the shell completion generators, 196 commands.

Almost everything the web console can do, platformctl can do in a scriptable form — including the one flow you might expect to be browser-only. A new account is issued a temporary password, and until you replace it every management call is refused. You can clear that from the terminal with platformctl change-password; you never have to open the console just to start working. (That is different from platformctl users reset-password, which is an administrator issuing someone else a fresh temporary password.)

Where a specific operation in a group is still console-only, the page documenting that group says so.

Command groups

platformctl --help prints this list. It is the map of the whole surface — every command lives under one of these.

GroupWhat it covers
agentsA deployed agent's life after deploy: revisions and traffic pinning, scaling and resource config, the memory policy and what the agent remembers about each user (agents memory), its operator-written knowledge (agents knowledge), plain environment variables, source files, sessions, end users, live spec, runtime signals, which secret keys are set, redeploy, and the embeddable chat widget.
auditThe project's audit trail, newest first, one page per run (--limit, --page-token). Every project member can read it.
change-passwordReplace the password of the account you are signed in as. A new account is issued a temporary one, and every management call is refused until it is replaced — so this is usually the first command you run.
completionShell completion scripts for bash, zsh, fish, and powershell.
configThe CLI's own persisted settings: the saved default project, and where the config file lives.
crusoe-cloud (alias cc)The project's Crusoe Cloud connection: connect, show, disconnect, and browse the buckets, container-registry repositories, and managed inference models it reaches. Connecting is a prerequisite for deploying — every image the platform builds is pushed to a repository in your own Crusoe Cloud registry.
deleteDelete an agent or a function.
demoWalk the golden path end to end against the bundled research-buddy example.
deployPackage a directory of agent code and deploy it (ADK, LangGraph, or CrewAI).
functionsDeploy a function directory (Python, Node.js, Go, or Ruby).
gatewayPublishing to the internet: publish puts an agent, service, function or MCP server at an address you can hand out, and endpoint, key and domain manage what happens after — API keys, IP allow lists, rate limits, and your own domains. Nothing is reachable from outside the project until you publish it.
iamWho holds a role on this project: members, service-account grants, and recorded break-glass access.
inferenceThe platform's hosted models: models lists the catalog, embed turns text into vectors, rerank scores documents against a query.
invitationsInvite an email address that has no account yet; list, revoke, preview, and accept.
invokeSend a message to an agent and print its response.
keysYour own API keys — create (the secret is printed once), list, revoke.
listList the agents and functions deployed in the project.
loginSign in and cache a session token for management commands.
logoutDiscard the cached session token.
logsPrint an agent's logs: the running instance's buffer, --follow to tail it, or --history for persisted logs that survive scale-to-zero.
mcpHosted, scale-to-zero MCP tool servers: their tools, the immutable version built by each publish, rollback, and yank/unyank.
memorizeWrite a session's conversation into an agent's long-term memory.
memorystoreMemory store instances: create, inspect, delete, rotate the credential, and read a live stats snapshot.
orgsOrganizations and their members. Not project-scoped, so --project is ignored here.
platformThe platform's own limits and defaults — container sizes, timeout ceilings, the embedding width your indexes must use. Read these rather than hardcoding them.
profileThe platform-wide default model credential that agents inherit. Write-only, platform admin only.
projectsCreate, list, inspect, rename, and delete projects.
pubsubTopics and subscriptions, publishing and pulling messages, direct broker connection details, per-topic usage counters, and the storage quota.
quotaThe project's limits and how much of each is in use, read from the accounting that actually enforces them.
secretsTwo different things: the versioned project secret store (put, list, show, versions, reveal, delete, issue-token), and an agent's own environment secrets (secrets set).
searchFind a resource by name across every project you can see, when you know what a thing is called but not where it lives.
serverlessScale-to-zero container services: create, update, delete, revisions, traffic splits, logs, metrics, spec, and triggers that fire on a schedule, a topic, or a bucket.
service-accountsThe project's machine principals and their API keys. Project admin only — and never usable with a service account's own credential.
statusAn agent's full status.
usersPlatform-wide user accounts: create, list, change role, reset password, delete.
vectordbVector indexes and the points in them: create, update, delete, upsert, query, scroll, delete points, and direct-access credentials.
whoamiThe identity the CLI is authenticating as, and which credential it used.

A few commands deliberately refuse a value flag. platformctl secrets put has no --value; it reads from --value-file or stdin. platformctl crusoe-cloud connect has no --secret-key; it reads from --secret-key-file or stdin. That is a design choice, not an oversight: a flag value lands in your shell history, is visible in the process table for as long as the command runs, and is captured by any shell tracing or audit rule watching argv. A file or a pipe is none of those things.

Install

From the repository root:

( cd cli/platformctl && go build -o ../../bin/platformctl . )
export PATH="$PWD/bin:$PATH"
platformctl --help

The install guide walks through this step by step.

Shell completion

Tab completion means your shell finishes command and flag names for you when you press Tab. platformctl generates the script for it, for four shells: bash, zsh, fish, and powershell.

platformctl completion --help

You should see:

Generate the autocompletion script for platformctl for the specified shell.
See each sub-command's help for details on how to use the generated script.

Usage:
platformctl completion [command]

Available Commands:
bash Generate the autocompletion script for bash
fish Generate the autocompletion script for fish
powershell Generate the autocompletion script for powershell
zsh Generate the autocompletion script for zsh

To turn it on for the shell you are in right now — a good way to try it before committing:

source <(platformctl completion bash) # bash
source <(platformctl completion zsh) # zsh
platformctl completion fish | source # fish

To keep it after you close the terminal, write the script where your shell looks for completions. Run the line for your shell once, then start a new shell:

ShellRun once
bash (Linux)platformctl completion bash > /etc/bash_completion.d/platformctl
bash (macOS)platformctl completion bash > $(brew --prefix)/etc/bash_completion.d/platformctl
zsh (Linux)platformctl completion zsh > "${fpath[1]}/_platformctl"
zsh (macOS)platformctl completion zsh > $(brew --prefix)/share/zsh/site-functions/_platformctl
fishplatformctl completion fish > ~/.config/fish/completions/platformctl.fish
powershellAdd the output of platformctl completion powershell to your PowerShell profile

Bash needs the bash-completion package installed. Zsh needs completion enabled — if it is not already, run echo "autoload -U compinit; compinit" >> ~/.zshrc once.

Each subcommand also takes --no-descriptions, which drops the short help text that would otherwise appear next to each suggestion. platformctl completion zsh --help prints the same instructions for your shell at any time.

How the CLI reaches the platform

The CLI talks to the public API at https://api.codyhill.dev unless you tell it otherwise. Nothing needs configuring for that to work.

The CLI talks to two families of endpoints:

Control plane (most commands). The endpoint is resolved in this order:

  1. The --api flag.
  2. The $CAI_API environment variable.
  3. The public API, https://api.codyhill.dev. This is the default and needs no setup.

There is a fourth, opt-in route: give either the flag or the variable the literal value port-forward and the CLI opens a short-lived private tunnel into the platform instead. That is break-glass for administrators — it needs privileged access to the platform's internals — and it never happens by itself. If the tunnel cannot be opened, you get:

port-forward failed (pass --api <url> or set CAI_API to a URL instead): ...

The fix is almost always to stop asking for the tunnel: unset the variable and let the default take over.

Service groups (serverless, pubsub, memorystore, vectordb). These four command groups deliberately do not take their base URL from --api. Each has its own environment variable, and each falls back to $CAI_API and then to the public API when that variable is unset — one hostname serves all of them, so in normal use you set none:

Command groupEnv override
platformctl serverlessCAI_SERVERLESS_API
platformctl pubsubCAI_PUBSUB_API
platformctl memorystoreCAI_MEMORYSTORE_API
platformctl vectordbCAI_VECTORDB_API

--api is still used indirectly by these four groups: if --project is a slug or short name rather than a UUID, the CLI resolves it to a UUID through the core platform API, reached via --api, $CAI_API, or the public default. Pass the project's UUID to skip that call entirely.

Global flags

Every command accepts these flags. One of them — -o — is accepted everywhere but honored only by the commands that print a resource; the rule and the exceptions are in output formats and scripting below.

FlagDefaultWhat it does
--api <url>$CAI_API, else https://api.codyhill.devBase URL of the core platform API. The four service groups above do not take their base URL from it, but still use it to resolve a slug or short-name --project to a UUID.
--project <ref>$CAI_PROJECT, else the saved default, else the server picks your single/default projectWhich project to scope requests to. Accepts a project's slug, short id, or full UUID.
-o, --output <format>tableOutput format: table, json (pretty-printed), or yaml. Validated on every command, ignored by some — see below.
--jsonoffHidden legacy flag: emits one compact JSON line as the last line of stdout. Kept for existing scripts; use -o json instead.

Project resolution, most specific first: --project flag, then $CAI_PROJECT, then the default saved by platformctl config set-project, then empty (the server chooses). Note that $CAI_PROJECT beats the saved config default — the same convention as gcloud, aws, and az.

What that reference costs you depends on which of three families the command belongs to:

FamilyCommandsHow the project travelsCost of a slug or short name
Agent routesdeploy, functions deploy, list, status, invoke, memorize, logs, delete, secrets set, and the agents group?project=<ref> on the request; the server resolves itNothing — slug, short id, and UUID all cost the same
Project-scoped control-plane routesmcp, iam, audit, quota, service-accounts, projects get/update/delete, invitations (except preview and accept), and the project secret store — every secrets subcommand except setThe project's UUID as a path segmentOne GET /v1/projects lookup, made on the connection the command already opened. A UUID skips it.
The four service groupsserverless, pubsub, memorystore, vectordbThe project's UUID as a path segment, on a different base URLOne lookup against the control plane, over a second connection. Pass a UUID in CI to avoid it.

The first family can fall back to "the server chooses". The other two cannot — they need a project named somewhere, and with none set they fail before sending anything:

this command needs a project: pass --project, set $CAI_PROJECT, or run 'platformctl config set-project' (use the id or slug shown by 'platformctl projects list')

Some groups are not project-scoped at all, and the CLI deliberately sends no project reference on their requests: orgs sits above projects, users and profile are platform-wide, and keys manages your credentials rather than a project's. invitations preview and invitations accept also send none — the token is the credential. For all of these, --project and $CAI_PROJECT are ignored.

Output formats and scripting

  • -o table (default): human-readable columns.
  • -o json: the full object(s), pretty-printed.
  • -o yaml: the same, as YAML.
  • --json (hidden, legacy): one compact JSON line as the last stdout line — the contract the platform's own e2e scripts rely on.

An invalid format fails with:

invalid --output "xml": want table, json, or yaml

Which commands honor -o

-o is checked once, centrally, before any command runs — so a bad value is rejected everywhere. A good value, though, only changes the output of the commands that print a resource. The rest print a fixed human sentence and ignore the flag entirely.

The rule: if a command returns an object or a list, -o works. If it prints a confirmation sentence or streams raw text, -o is ignored.

That makes it honored across nearly the whole surface: deploy, functions deploy, list, status, invoke, logs --history, config get-project, config view, and the read, create, and update verbs of every group — agents, audit, iam, invitations, keys, mcp, memorystore, orgs, profile, projects, pubsub, quota, secrets, serverless, service-accounts, users, vectordb. (agents spec and serverless spec count as resource commands: their default output is the YAML document, and -o json/-o yaml return the envelope around it.)

Ignored by these:

CommandWhat it prints instead
login, logout, whoamiA plain identity or session sentence
demoThe narrated golden-path walkthrough
memorize, secrets set, config set-projectA one-line confirmation
Every delete, revoke, and remove verb, in every group — delete, mcp delete, mcp tools delete, serverless delete, serverless triggers delete, vectordb delete, memorystore delete, pubsub topics delete, pubsub subscriptions delete, secrets delete, projects delete, users delete, orgs delete, orgs members remove, iam members remove, iam service-accounts remove, service-accounts delete, service-accounts keys revoke, keys revoke, invitations revoke, agents sessions delete, agents files delete, agents embed disableA one-line confirmation such as deleted my-agent, exit 0
logs (default) and logs --followRaw log text

Note the split inside logs: --history reads stored log records and can render them as JSON or YAML, while the default and --follow modes stream raw log text, which has no object shape to convert.

No error tells you the flag did nothing

platformctl whoami -o json prints prose, not JSON, and exits 0. A pipeline like platformctl whoami -o json | jq -r .email fails inside jq, not in the CLI. When scripting, only parse output from a command the rule above says is honored.

Here is the difference, on one command from each side:

platformctl status research-buddy -o json | jq -r .state
platformctl whoami -o json

You should see:

ready
you@example.com role=admin (credential: cached login (/Users/you/Library/Application Support/crusoe-ai/token))

The second line is the plain-text whoami output, unchanged by -o json. To script identity checks today, read the same values from the API instead — see API authentication.

Exit behavior and errors

  • Commands exit 0 on success and non-zero on any failure, with the error printed to stderr.
  • Any 4xx or 5xx from the API is wrapped as:
workload-api returned <code>: <body>
  • On a 401 or 403, the CLI also tells you which credential it tried:
workload-api returned 401: ... [platformctl credential: none; run `platformctl login` or set $CAI_TOKEN]

The credential source shown is one of: none, $CAI_TOKEN, cached login (<path>), or $CAI_USER/$CAI_PASSWORD.

Credential resolution

Every request carries at most one credential, sent as Authorization: Bearer <credential>. The CLI picks it in this order, most specific first:

  1. $CAI_TOKEN — any bearer credential: a session token, or an API key in the format cai_<keyid>_<secret>. Create one with platformctl keys create for yourself, or platformctl service-accounts keys create for a machine principal; the console has the same under Security → API keys. Either way the secret is printed once and only a hash is kept.
  2. The cached login token written by platformctl login, stored at <UserConfigDir>/crusoe-ai/token (macOS: ~/Library/Application Support/crusoe-ai/token; fallback: $TMPDIR/crusoe-ai-token), owner-only permissions. Tokens last 12 hours; a token expiring within 30 seconds is treated as absent and the CLI falls through to the next source.
  3. $CAI_USER + $CAI_PASSWORD — the CLI logs in on the spot via POST /v1/auth/login. It caches nothing, and on failure it falls through instead of erroring.

Finding nothing is not an error. Invoking a deployed agent needs no credential by default (the "data plane" is open). Management commands — deploy, list, status, logs, secrets, delete — return a 401 annotated with the credential source that was tried. See API authentication for the full model.

The config file

platformctl config set-project saves your default project to:

<UserConfigDir>/crusoe-ai/config.json

The file has 0600 permissions (only you can read it) and contains {"default_project":"..."}. Remember: $CAI_PROJECT still overrides it. See the config commands for details.

Timeouts

OperationTimeout
Any API request5 minutes (deliberately generous for cold starts)
Deploy upload request2 minutes
Deploy readiness pollingevery 2 seconds, up to 5 minutes
Opening the CLI's own connection15 seconds
logs --follownone — tails until you stop it

How it compares

platformctlAWS CLIgcloudaz
InstallBuild from source ()Prebuilt installers and packagesPrebuilt installersPrebuilt installers
Sign inplatformctl login, $CAI_TOKEN API keysAccess keys, SSOBrowser OAuth flowBrowser OAuth flow
Outputtable, json, yamljson, text, tabledefault, json, yaml, morejson, table, tsv, more
CoverageThe whole platform: agents, functions, four data services, MCP servers, secrets, and platform administrationHundreds of servicesHundreds of servicesHundreds of services

Summary: the big clouds' CLIs cover far more services and ship signed binaries. platformctl covers one platform and is built from source during the — no prebuilt binaries and no package manager. What it does cover, it now covers end to end: deploy to invoke in two commands, and every administration area the console exposes.

In this section

  • Agents and functionsdeploy, functions deploy, list, status, invoke, memorize, secrets set, logs, delete, demo, and the agents group: revisions, traffic, config, env, files, sessions, users, metrics, spec.
  • Data and messagingserverless, pubsub, memorystore, vectordb, end to end: create, update, and delete as well as read.
  • MCP and secrets — MCP servers and the project secret store.
  • Platform and authlogin, logout, whoami, config, projects, orgs, users, iam, invitations, service-accounts, keys, profile, quota, audit.
  • Gateway and inferencegateway (publish, endpoints, keys, domains) and inference (models, embed, rerank), plus platform, search and change-password.