Skip to content

CLI reference

The public CLI source and releases live at github.com/opencloud-ai/cli. OpenCloud skills pin an exact release instead of installing a moving branch.

Install

The current release is v3.10.3 and requires Node.js 22 and npm 10 or newer:

bash
curl -fsSL https://docs.opencloud.ai/install.sh | bash
opencloud --cli-version

The installer downloads the pinned GitHub release, verifies its published SHA-256 checksum, and keeps the versioned package in the user data directory. It creates opencloud in a writable binary directory already on PATH when possible, otherwise in ~/.local/bin; in that case, follow the printed PATH instruction once.

Run commands from any directory:

bash
opencloud <command>

The CLI searches parent directories for the nearest .opencloud/app.json workspace binding or passwordless-onboarding session. Run opencloud doctor for redacted identity, credential-backend, endpoint, CLI, and platform-version diagnostics; it never prints a credential.

Account login and workspace connection

text
login [--force] [--no-browser]
auth status
auth logout
logout
app list
app create --name <name> [--visibility <public|private>]
app get <app-id>
app connect <app-id>

opencloud login uses the API at https://api.opencloud.ai unless --api-url or OPENCLOUD_API_URL selects another OpenCloud installation. The CLI discovers the authorization server, creates a ten-minute browser approval request, prints the approval URL, and opens it when possible. Use --no-browser to print the URL without opening it.

The browser flow is:

  1. OpenCloud checks the browser session. If needed, the user signs in or registers with a one-time email link or a password. New accounts still confirm their email address before signing in.
  2. OpenCloud shows the CLI name, requested account scope, expiry, and an explicit Allow/Deny choice. A GET or link scanner cannot approve the request.
  3. The CLI polls the token endpoint until the user decides. There is no localhost listener, redirect callback, copied code, or pasted secret.
  4. Approval issues a 15-minute API access token and a rotating 30-day refresh token. Refresh-token reuse revokes the complete login family.

The account login is reusable by new Codex or Claude Code sessions running as the same OS user. Secrets are stored in the OS credential store under service ai.opencloud.cli. When no usable keyring exists, the CLI falls back to mode-0600 files in:

  • Linux: $XDG_CONFIG_HOME/opencloud/credentials, normally ~/.config/opencloud/credentials;
  • macOS: ~/Library/Application Support/OpenCloud/credentials; or
  • Windows: %APPDATA%\OpenCloud\credentials.

File names are derived identifiers; do not inspect, copy, upload, or commit their contents.

The account token is intentionally unable to build or deploy. It may list, read, and create apps and connect a workspace. To work on another app:

bash
opencloud auth status
opencloud app list
cd /path/to/the-other-app
opencloud app connect "$APP_ID"
opencloud doctor

app connect writes a non-secret, ignored .opencloud/app.json binding and stores a separate 24-hour app-scoped credential in the protected per-user backend. Build, deploy, secret, and operation commands use that workspace credential. The CLI automatically reconnects through the account login as the credential nears expiry.

opencloud logout and opencloud auth logout revoke the refresh family, all linked workspace credentials remotely, and the local account credential. They also remove the current workspace's cached credential and any onboarding session at the resolved session path. Cached credentials for other workspace bindings are unusable after remote revocation and are replaced when those workspaces reconnect. Non-secret app bindings remain so a later opencloud login and opencloud app connect "$APP_ID" can reconnect them. Use opencloud login --force to replace a stored login that cannot be refreshed.

Exact-app owner Agent sessions

AI SDK Codex harness v3 receives a protected session through OPENCLOUD_SESSION_FILE and an assigned app ID from OpenCloud. That session is already connected and delegates human-owner-equivalent authority for the exact app. The Agent runs opencloud doctor and opencloud app get "$APP_ID", then uses ordinary public CLI commands directly. It does not run browser login, create another app, call app connect, or inspect the session file.

The delegation permits every app-owned command, including deployment, production data and File mutations, rollback, restore, secret and access changes, archive, and deletion. No additional Agent-specific approval is required merely because a same-app operation is destructive or affects production. This does not bypass validation, deployment locks, idempotency, quotas, or immutable artifacts, and an explicit user constraint such as “do not deploy” still applies.

The credential cannot operate another app, create apps, change account preferences or billing, authorize or reveal account-owned provider credentials, administer OpenCloud, or access the host and shared infrastructure. Account connection and consent remain human account actions. The Agent may bind or unbind an existing app-account integration only through the typed app-scoped API; calling-user bindings remain the calling user's authority. AI SDK harness v1/v2 and ordinary human CLI credentials retain their existing authority and approval rules.

Nested deployments, backups, operations, credentials, Files, bindings, grants, and other resources resolve to their parent app before authorization. A foreign identifier is denied exactly like a nonexistent one; the Agent must not probe or infer cross-app existence.

The exact-app owner CLI surface covers every implemented owner capability:

  • supported app lifecycle and configuration, including visibility, restart, archive, unarchive, and deletion;
  • drafts and source files, isolated development and captured effects, validation, verification, deployment, operations, rollback, artifact inspection, and inactive-deployment cleanup;
  • production table and managed-File inspection and mutation;
  • secret metadata, generation, secure set/replace, entry links, and deletion;
  • backup inspection, creation, schedule, and restore;
  • production Function invocation, cron, jobs, queues, and app email through their supported typed surfaces;
  • logs, metrics, usage, visitors, alerts, Agent Feed, verification, and operation evidence;
  • members, grants, app credentials, and app-scoped access tokens; and
  • app integration listing, binding, configuration, typed use, and unbinding.

This list does not create raw administrative bypasses where the app runtime is the product contract. Enqueue through a declared Function; send email and use provider integrations through their typed Function clients. Creating or authorizing an account-owned provider connection, managing a calling_user binding, reading a raw provider credential, or transferring ownership where the platform does not support transfer remains outside the exact-app session.

Passwordless email onboarding

Agents can use passwordless onboarding to create a new identity and first app in one flow. Existing accounts should use opencloud login and opencloud app connect.

For a new app, no copied connection pack, owner UUID, or hand-picked domain is required:

bash
opencloud onboard \
  --email person@example.com \
  --name "Family tasks" \
  --visibility private

The API allocates <title>-<six random characters>.opencloud.ai atomically.

  • A new email receives organisation_setup_required with no project or credential. OpenCloud sends a project-aware confirmation email that expires after 24 hours. The owner confirms it, then explicitly sets up their company or accepts its invitation through the launch page.

  • Existing emails also approve the project request. After confirmation and company setup, resume the same retained request:

    bash
    opencloud onboard-complete

CLI 3.10.0 retains the pending completion secret for this state. Its next-step message mentions email confirmation; complete company setup on launchUrl too before resuming. Repeating onboard-complete while setup is pending keeps the same request and does not create an app.

The command returns a non-secret launchUrl. Give it to the owner as the primary link while confirmation or deployment is pending; it opens the project after the email review creates the browser session and the deployment is ready.

The CLI writes the short-lived credential or pending completion secret to .opencloud/session.json, creates .opencloud/.gitignore, and applies file mode 0600. The CLI automatically uses this file for later commands. Never print, inspect, copy, or commit it. Override its location only when necessary with OPENCLOUD_SESSION_FILE or --session-file.

Non-default OpenCloud installations can provide OPENCLOUD_API_URL and OPENCLOUD_TOKEN. OPENCLOUD_EDGE_URL is an optional transport adapter for non-browser CLI requests.

Structured output, idempotency, and operation recovery

Every successful command emits one stable machine-readable JSON document. Starting with the owner-parity v3.6.0 release, failures also emit structured, redacted JSON and exit non-zero. Clients should read the documented fields instead of scraping prose, retain request and operation IDs for diagnosis, and never persist credential or secret values.

Use one stable idempotency key for one intended mutation. An exact-app owner Agent must pass it through every mutating command's --idempotency-key <key> option; CLI 3.10.3 rejects a missing key before creating a journal entry or sending a request. Reuse the same key after a timeout, disconnect, or lost response. Do not generate a second key for an ambiguous response. A materially changed request after a diagnosed failure is a new intended effect and gets a new key. An artifact digest may identify the input but does not identify the complete intent.

Operation-starting commands follow the durable operation by default with bounded polling. They accept --no-follow, --interval <seconds>, and --timeout <seconds> where documented. A wait timeout exits non-zero but does not assert that the server-side operation failed. Record the operation ID and recover terminal truth without repeating the mutation:

bash
opencloud operation get "$OPERATION_ID" --follow \
  --interval 2 --timeout 300
opencloud operation list "$APP_ID" --limit 50

A terminal failed or cancelled operation exits non-zero and preserves typed, actionable diagnostics. Successful app deletion returns its terminal result before revoking the app-owner session. For a bounded receipt window, that revoked session may read only the exact succeeded deletion operation; it cannot list operations or access any other app resource.

Owner-parity command contract

The owner-parity command tree below is the contract for public CLI v3.10.3. The current pinned public CLI is v3.10.3; its published checksum, packaged tests, and control-plane compatibility evidence are verified. Do not invent equivalent syntax or bypass the CLI with raw requests. Report a missing CLI surface as a product limitation. Harness v3 uses this CLI with its exact-app owner session in the additive app-owner runtime.

CLI 3.8.0 adds production Web Push history list/detail and paginated operations. Hosted runtimes can route app request through the installation's OPENCLOUD_PUBLIC_EDGE_HOST bridge when the public address cannot loop back. The route changes address resolution only; the canonical HTTP Host, TLS server name, certificate verification, and same-origin path restrictions remain active.

CLI 3.10.3 requires explicit idempotency keys for app-owner Agent mutations. It also retains schema-3 route validation and bundling, SDK 2.3.0 Function routes, and exact-app custom-domain management, and keeps an operation's polling authenticated when its exact-app runtime credential rotates, while rejecting changes to the original authority. operation list keeps its array output unless --page, --cursor, --type, or --state is supplied. Page output contains asOf, operations, and nextCursor; continue with the same app, filters, and limit. Operation states are queued, running, succeeded, failed, and cancelled.

app notifications list returns retained production history with messages and nextCursor. It accepts queued, no_subscribers, accepted, partial, and failed statuses, a recipient user ID, and ISO date-time bounds spanning at most 30 days. get includes the retained payload and delivery attempts. Provider acceptance does not prove that a user saw a notification. These reads require app read access and preserve exact-app Agent authorization.

In the command lists below, operation options mean:

text
[--idempotency-key <key>] [--no-follow]
[--interval <seconds>] [--timeout <seconds>]

Lifecycle and access:

text
app restart <app-id> [operation options]
app archive <app-id> [operation options]
app unarchive <app-id> [operation options]
app delete <app-id> [operation options]
app members <app-id>
app access list <app-id>
app access add <app-id> --email <email> --role <builder|app_user> [operation options]
app access grant <app-id> <user-id> [operation options]
app access revoke <app-id> <user-id> [operation options]
app access builder-add <app-id> <user-id> [operation options]
app access builder-remove <app-id> <user-id> [operation options]
app access-token list <app-id>
app access-token create <app-id> --name <name> [--expires-in-days <days>] [--idempotency-key <key>]
app access-token request <app-id> --name <name> [--expires-in-days <days>]
app access-token revoke <app-id> <token-id> [--idempotency-key <key>]
app credential-create <app-id> --name <name> --token-file <path> \
  [--expires-in-hours <1..168>] [--scopes <comma-separated>] \
  --idempotency-key <key>

Access-token creation returns a one-time reveal link rather than token material to the Agent. credential-create refuses to overwrite its required token-file path, creates it with mode 0600, and returns only credential metadata plus the absolute file path in JSON. An Agent must never open, echo, trace, or report that file. If an ambiguous response leaves no token file, rerun the exact same request with the same idempotency key; the server replays the same one-time credential. If the file exists, do not overwrite it; inspect credential metadata with credential-list. The exact-app owner session normally needs no second credential. Account login and provider-connection authorization are not part of these commands.

Server-side drafts:

text
draft create <app-id> [--name <name>] [--empty]
draft list <app-id>
draft get <app-id> <draft-id>
draft files <app-id> <draft-id>
draft read <app-id> <draft-id> --path <path> [--path <path>]...
draft apply <app-id> <draft-id> --expected-revision <revision> --changes-file <path>
draft diff <app-id> <draft-id>
draft validate <app-id> <draft-id> [--legacy-version <version>]
draft deploy <app-id> <draft-id> [operation options]
draft discard <app-id> <draft-id> [--idempotency-key <key>]

Production data, Functions, and managed Files:

text
data tables <app-id>
data list <app-id> <table> [--limit <number>] [--cursor <cursor>]
data get <app-id> <table> <row-id>
data create <app-id> <table> [--values <json>|--values-file <path>] [operation options]
data create-many <app-id> <table> [--values <json>|--values-file <path>] [operation options]
data update <app-id> <table> <row-id> [--values <json>|--values-file <path>] [operation options]
data delete <app-id> <table> <row-id> [operation options]
function invoke <app-id> <function-name> [--input <json>|--input-file <path>] [operation options]
file list <app-id> [--limit <number>] [--cursor <cursor>]
file get <app-id> <file-id>
file download <app-id> <file-id> --output <path> [--force]
file upload <app-id> <path> [--name <name>] [--content-type <type>] [operation options]
file replace <app-id> <file-id> <path> [--name <name>] [--content-type <type>] [operation options]
file delete <app-id> <file-id> [operation options]

Production table mutations, Function invocations, and File uploads, replacements, and deletions are durable operations. File uploads and replacements stream bytes rather than placing them in JSON. Recover their terminal operation normally, then verify the resulting state with file list or file get. Queue enqueue/redrive is not a raw owner command: invoke a declared production Function that uses the typed queue client. The same rule applies to production email sending and typed provider execution.

Operations, deployment cleanup, legacy email capture, and visitors:

text
operation get <operation-id> [--follow] [--interval <seconds>] [--timeout <seconds>]
operation list <app-id> [--limit <number>]
operation list <app-id> --page [--cursor <cursor>] [--limit <1..200>] [--type <type>] [--state <state>]
app notifications list <app-id> [--cursor <cursor>] [--limit <1..200>] [--user-id <uuid>] [--status <status>] [--from <timestamp>] [--to <timestamp>]
app notifications get <app-id> <message-id>
deployment delete <app-id> <deployment-id> [--idempotency-key <key>]
app email capture-get <app-id> <message-id>
visitors <app-id>

App integrations and direct secret replacement:

text
integration list <app-id>
integration bind <app-id> <integration-name> --connection-id <uuid> \
  [--resource-id <id>] [--label <label>] [--trigger-mode <mode>] \
  [--idempotency-key <key>]
integration unbind <app-id> <integration-name> <binding-id> \
  [--idempotency-key <key>]
secret set <app-id> <name> [--idempotency-key <key>]

secret set accepts the value only on standard input and never echoes it. secret configure remains the one-time human entry-link flow. Integration commands can manage only app-account bindings that the exact owner may use; integration list returns declarations, current bindings, and eligibleConnections. Each declared account: app slot includes at most 50 safe eligible records containing only id, accountLabel, active status, and createdAt. It does not expose the general account connection catalog, allow connection creation or management, reveal raw credentials or undeclared providers, include calling_user connections, or cross into another owner's connections.

App

text
app list
app create --name <name> [--visibility <public|private>]
app get <app-id>
app connect <app-id>
app sdk-inspect <app-id>
app origin <app-id>
app domain get <app-id>
app domain add <app-id> <hostname> [--idempotency-key <key>]
app domain check <app-id> [--idempotency-key <key>]
app domain remove <app-id> [--idempotency-key <key>]
app email list <app-id> [--cursor <cursor>] [--limit <number>] [--alias <alias>] [--direction <inbound|outbound>] [--from <iso>] [--to <iso>]
app email get <app-id> <message-id>
app request <app-id> [path]
app verify <app-id>
app configure <app-id>
app credential-list <app-id>
app credential-create <app-id>
app credential-revoke <app-id> <credential-id>

app verify starts and follows the authoritative server-side release gate. CLI v3 intentionally provides no partial local verification substitute.

App credential commands are owner-only and exact-app scoped. Creation requires a new --token-file plus a stable --idempotency-key, writes the one-time credential at mode 0600, and emits only safe metadata. Revoke only the intended credential ID.

Public CLI v3.10.3 includes app access-token listing, reveal-link creation, owner-approval requests, and revocation. It never prints or stores the runtime secret. Account connection and consent remain outside the exact-app Agent boundary.

Development sessions

text
app dev start <directory>
app dev sync <directory>
app dev status [directory]
app dev request <directory> [path] [--method GET|HEAD]
app dev data <directory> <table> <create|createMany|updateById|deleteById> [--values <json>] [--id <id>]
app dev email list [directory] [--limit <number>]
app dev email get <directory> <message-id>
app dev email inject <directory> --to <alias> --from <address.test> [--from-name <name>] [--subject <subject>] [--text <text>|--text-file <path>] [--html <html>|--html-file <path>] [--reply-to <address.test>] [--header <header>]... [--attachment <path>]...
app dev notifications list [directory] [--limit <number>]
app dev invoke <directory> <function-name> [--body <json>]
app dev requests [directory] [--limit <number>]
app dev receipts [directory] [--limit <number>]
app dev evidence [directory]
app dev verify [directory] [--idempotency-key <key>] [--parallelism <number>] [--interval <seconds>] [--timeout <seconds>]
app dev promote [directory] [--idempotency-key <key>]
app dev stop [directory]

start and sync use the canonical bundler, synchronize changed and deleted draft files with optimistic guards, and reject a local/server artifact digest mismatch. Local .opencloud/dev.json stores only IDs and hashes.

For human review, start returns session.browserPreviewUrl and status returns the same value as top-level browserPreviewUrl. Give that URL to an owner or builder: it opens the isolated revision in the clearly marked Development preview — Not live window with Full size, Tablet, Mobile, and Reload tools. Keep the raw previewUrl for CLI/agent inspection; opening it directly in a normal browser may return AUTH_REQUIRED.

The preview has a separate database schema and supports isolated Auth, managed Files, Functions, and background jobs. It cannot access production data, owner-configured secrets, Realtime, runtime telemetry, or cron; generated secrets receive only synthetic development values. Dev Functions remain dormant until invoke or a deliberate preview interaction; an enqueue wakes its declared queue consumer in the same isolated namespace. requests returns correlated, redacted outcomes. data exposes only SDK-shaped table actions and keeps REST paths and methods internal. Dev email sends are captured instead of delivered; the email commands inspect those captures or inject bounded .test messages into the active revision. Dev Web Push sends are also captured rather than delivered; notifications list inspects their visible payload, resolved icon, and click path. verify issues a receipt for the exact active revision. promote refuses any changed, stale, or unverified candidate, then follows deployment, verifies production, prints the live URL, and stops dev. Read the development guide before invoking Functions with possible external side effects.

For app dev verify, --timeout controls the verification HTTP request and the receipt reconciliation wait in seconds (default 900, range 1–1800). If a request is interrupted, verification may still be running on the server. Rerun the same command to reconcile existing evidence before another attempt.

Bundle and deployment

text
init <directory> [--app-id <uuid>] --version <version>
artifact-check <directory> [--expect-app-id <uuid>] [--max-files <count>]
validate <directory> [--write-archive <path>]
deploy <directory> --idempotency-key <key>
operation get <operation-id> --follow
deployment list <app-id>
deployment get <app-id> <deployment-id>
deployment rollback <app-id> <deployment-id>

init infers the app ID from the connected workspace binding, or from a passwordless-onboarding session when one is present. CLI 3.10.3 creates a versionless schema-3 manifest by default. --version deliberately creates a legacy schema-2 source; keep an existing value stable across updates. The publisher allocates the actual deployment version in the database.

Cron diagnostics

text
cron history <app-id>
cron invoke <app-id> <cron-name>

Background-job diagnostics

text
jobs list <app-id> [--cursor <cursor>] [--limit <number>] [--queue <name>] [--state <state>] [--from <iso>] [--to <iso>]
jobs get <app-id> <job-id>

jobs list returns current depth, retained outcome totals, per-queue policy and rollups, and cursor-paginated history. from and to are inclusive ISO 8601 creation times. jobs get returns safe execution metadata for one job. Neither command exposes payloads, idempotency keys, or enqueuing-user IDs, and neither can cancel or redrive work.

Secrets and observability

The installed v3.10.3 release provides:

text
secret rotate <app-id> <name>
secret configure <app-id> <name>
secret set <app-id> <name>
secret list <app-id>
secret delete <app-id> <name>
logs <app-id>
metrics <app-id>
usage <app-id>

Declare each secret in opencloud.yaml as generated, required, or optional. OpenCloud provisions generated values automatically; use secret rotate only for an intentional rotation. Use secret configure when the owner must supply a required or optional value through the one-time browser page. secret set reads the value only from standard input; it never accepts a secret as an argument or returns one in JSON.

CLI v3.10.3 also provides:

text
agent-feed <app-id> [--since <iso>]
alert-rule list <app-id>
alert-rule put <app-id> <rule-id> --name <name> --metric <metric> \
  --aggregation <sum|rate|latest|min|max|avg> \
  --operator <gt|gte|lt|lte|eq> --threshold <number> \
  --window <5m|15m|1h|24h>
alert-rule delete <app-id> <rule-id>

Use agent-feed for routine agent monitoring. Raw logs and metrics remain diagnostic surfaces. Alert rules can reference only metrics declared by the active deployment and do not accept PromQL or LogQL. Put durable app-owned rules in observability.alertRules so they activate with the release. alert-rule put creates an immediate operational rule or override; a same-ID override takes precedence over the manifest rule until it is deleted. alert-rule delete removes only an operational definition; a same-ID manifest rule then becomes effective again. The control-plane response identifies each origin as manifest or operational_override.

Backup

text
backup create <app-id>
backup list <app-id>
backup schedule <app-id> <daily|weekly|none>
backup restore <app-id> <backup-id>

Rollback and restore are destructive recovery actions. Do not use them as routine deployment tests. An exact-app owner Agent may choose either for its assigned app without another operation-specific approval and must inspect the terminal operation and resulting state. Ordinary human-directed sessions and legacy or narrower Agent credentials still require the user to authorize that exact destructive action.

Self-hosted infrastructure for agent-built applications.