Core commands
Command Reference
Section titled “Command Reference”run402 up [repo-or-path] [--name <name>] [--project <id>] [--manifest <path>] [--dir <path>] [--tier <prototype|hobby|team>] [-y|--yes] [--check|--print-spec|--print-manifest|--plan|--require-plan <id>] [--verify] [--propagation-budget-s <seconds>] [--no-propagation-wait] [--quiet]— SDK-owned recursive app deploy. Validatesrun402.deploy.json/app.json, requires explicit--manifestfor executable.ts/.jsconfigs, ensures missing Cloud prerequisites when approved, resolves/creates/links a project, then applies the manifest. Output includessteps[]; success has no top-levelstatus. Use--checkfor local-only validation,--print-specfor normalizedReleaseSpec,--planfor a gateway-reviewed non-deploying plan, and--require-planfor exact reviewed apply. App HTTP verification reports fresh edge misses aspropagation_pending, waits up to--propagation-budget-s(default 120), and--no-propagation-waitreturns the pending state immediately. Add--verifyto wait for gateway/edge release coherence after the deploy and attachedge_coherence; non-coherence exits 2.run402 up verify [repo-or-path] [--project <id>] [--manifest <path>] [--dir <path>] [--propagation-budget-s <seconds>] [--no-propagation-wait] [--quiet]— rerun manifest HTTP verification (app manifestverify.http[]or deploy-manifest top-levelverify) without deploying, uploading, creating a project, or mutating resources. Use it afterpropagation_pendingor before declaring a consumer copy healthy.
run402 init— set up with x402 (Base Sepolia). Creates allowance, requests faucet, checks tier, lists projects. A blocked or unconfirmed faucet is reported infunding; next actions carry the server cooldown or balance-check recovery instead of recommending immediate deployment. Identity setup can succeed while funding remains blocked.run402 init --api-base <url>— configure the active profile to target a Run402 Core/API base. For Core, this does not create an allowance, request faucet funds, or require a Cloud tier.run402 init mpp— set up with MPP (Tempo Moderato testnet). Same steps, different payment rail.run402 init lightning— the Lightning allowance: the same Base allowance (the x402 fallback) plus a budgeted Lightning wallet the platform mints on Run402’s own Hub (POST /agent/v1/lightning-wallet; custodyrun402_hub, a starter amount funded by the platform). The one-time pairing is stored inallowance.jsonbeside the Base key and never printed;railbecomeslightning, so tier purchases and image generation answer a Lightning challenge first and fall back to x402. The summary carrieslightning: { wallet_id, status, lightning_address, budget_sats, starter_sats, balance_sats, custody, outcome };outcome: "minting"means rerun in a few seconds,"unavailable"means no Hub on this gateway (x402 keeps paying).run402 init <rail> --switch-rail— switch the persisted rail; re-running with the same rail is idempotent.
run402 pay <url> [--method <M>] [--body <json-or-text>] [--max-usd <amount>] [--idempotency-key <key>] [--require-receipt] calls an arbitrary x402-priced HTTP endpoint through the SDK buyer. The request body goes in --body and nowhere else: --json is the CLI-wide output-format flag, takes no value, and is a no-op here because pay always prints JSON. Writing --json '<payload>' does not send the payload — it fails BAD_USAGE with a hint naming --body. The default ceiling is $0.10; --max-usd accepts up to six decimal places and is converted exactly to USD micros. --require-receipt requires a verified wallet-rooted offer before payment and a matching receipt afterward. JSON output is the complete x402-commerce-result.v1 envelope with settlement, movement/replay, delivery, offer, merchant-receipt, signer-relationship, policy, and portable evidence. Unpriced URLs return payment: null. For PAYMENT_INTENT_PENDING on a trusted Run402 host, wait for Retry-After and repeat the identical command with the same payer, request, and key. Never substitute a fresh key. Custom/arbitrary hosts and other funds_moved: "unknown" outcomes remain ambiguous and require reconciliation.
run402 pay https://seller.example/translate --method POST \ --body '{"text":"hello"}' --max-usd 0.05 \ --idempotency-key translation:1 --require-receiptstatus
Section titled “status”run402 status — show full organization state in one shot (wallet, rail, balances, tier, projects, active project). Read-only, JSON output. Includes a wallet: { local_label, server_label, address } object naming the active named wallet (local_label is the local selector, server_label the server-synced display name or null), a top-level rail, and a balances: { on_chain_usd_micros, on_chain_token, prepaid_credit_usd_micros, held_usd_micros } object. The on-chain token tracks the rail (USDC on x402, pathUSD on mpp); prepaid credit is rail-independent. Remote reads carry remote_status entries for tier, billing and projects (available or unavailable, with safe error code/category). projects_source distinguishes server inventory from local_cache. Null remote values after failed reads are unknown, not evidence that initialization or funding is needed.
wallets
Section titled “wallets”Manage multiple named wallets (profiles) on one machine. Keys never leave the machine (non-custodial). The default wallet lives at the config-dir root; named wallets live under {config_dir}/profiles/<name>/.
run402 wallets list— JSON array of{ local_label, server_label, address, address_short, rail, active }. Reads non-secretmeta.json; never loads private keys.run402 wallets current— the resolved active wallet{ name, source, source_detail, address, label, warnings }.source∈ flag|env|binding|config|default.warningssurfaces env-vs-binding conflicts and local-name-vs-server-label drift.run402 wallets new <name> [--mpp | --rail <x402|mpp|lightning>]— create a new named wallet (generates a key).{ name, address, rail, created: true }. Alightningwallet is minted on the platform byrun402 --wallet <name> init lightning.run402 wallets lightning [status|mint|revoke]— the active wallet’s Lightning allowance.statusreads the platform record plus a best-effort balance and remaining budget over NWC ({ rail, lightning: { wallet_id, status, custody, lightning_address, budget_sats, starter_sats, has_pairing, balance_sats, budget_remaining_sats } });mintisinit lightning’s wallet step alone;revokedeletes the sub-wallet on Run402’s Hub, forgets the pairing, and returns the rail to x402. The pairing secret is never printed.run402 wallets use <name>— set the global default wallet (config.jsonactive_wallet).{ name, active: true }.run402 wallets rename <old> <new>— rename a wallet; renamingdefaultmigrates its root files intoprofiles/<new>/.{ from, to, renamed: true }.run402 wallets bind [<name>]— write./.run402.jsonbinding this directory to a wallet (defaults to the active one). Safe to commit (holds only a name).{ wallet, file, bound: true, safe_to_commit: true }.run402 wallets unbind— remove./.run402.json.{ file, unbound }.run402 wallets import <name> --key <path|->— adopt an existing 0x-prefixed 64-hex private key (file path or-for stdin) as a named wallet.{ name, address, imported: true }.run402 wallets rm <name> --yes— delete a wallet and its keys. Requires--yes(agent-first: no interactive prompt). Refuses to removedefault.{ name, removed: true }.- Server-side display label:
new/rename/importpush the wallet’s name to a server-side label (signed by the wallet — proof of control) so the same name shows cross-machine and in the operator console (WEB). Best-effort and on by default;RUN402_WALLET_LABEL_SYNC=0opts out (fully offline wallet ops). The local folder name is the source of truth; the label is a mirror, andwallets currentflags any drift. - Selection for ANY command:
--wallet <name>(alias--profile) >RUN402_WALLET> nearest./.run402.json/.run402.local.json>wallets usedefault >default. A conflicting env + binding errors withWALLET_SELECTION_CONFLICT(resolve via--wallet,unset RUN402_WALLET, orwallets unbind). Selecting a non-existent wallet errors withWALLET_NOT_FOUND.
allowance
Section titled “allowance”run402 allowance <create|status|fund|balance|export>run402 allowance checkout --amount <usd_micros>run402 allowance history [--limit <n>]
Tier and quotas are per organization (not per project) — set is organization-wide, status.pool_usage is the pooled total across every project in the organization. set refetches status after the call and includes it as status_after.
run402 tier statusrun402 tier set <prototype|hobby|team>
credentials
Section titled “credentials”Two surfaces under one command. credentials <verb> acts on PROJECT CREDENTIALS (rows on the gateway); credentials project-keys <verb> acts on the LOCAL key cache on this machine. A project credential (r402_…) is named, listable, expiring and individually revocable, and several may be live per kind at once — that overlap is how you rotate with no downtime. It replaces the derived anon_key/service_key, which come from the platform signing key, never expire, and cannot be revoked one at a time.
Secrets are returned EXACTLY ONCE, from issue, rotate and token. Full JSON goes to stdout so it can be piped (| jq -r .secret); warnings go to stderr. Never write one of these responses to a result cache or tmp file.
run402 credentials status [--project <id>]— am I still on the retiring key? Returnsstate: "legacy"|"rotatable",rotatable_credentials,credentials[], andretirement.gated_on[].retirement.deadlineis ALWAYS null and that is deliberate: retirement is gated on conditions (every tenant migrated, 30 consecutive days of zero legacy-key use, explicit operator approval), never a date — do not plan against one. Needs onlyproject.read, so automation can check its own posture.run402 credentials issue --kind <anon|service> --name <name> [--project <id>] [--expires <iso8601>] [--import]— mint one; secret printed ONCE.--namemust be unique among LIVE credentials; re-using a live name returns409 CREDENTIAL_NAME_TAKEN, and that collision IS the idempotency story (a retried create never silently mints a second credential).--expiresmust be in the future and within one year.--importadditionally writes the minted secret into this machine’s local key cache (what deploys and data-plane commands read) — the cold-restart re-key path in one command per kind instead of issue-then-project-keys import. A first--kind anon --importon a machine with no cached entry still needs a service key first (the same rule asproject-keys import), and that refusal comes BEFORE the mint, so a show-once secret is never burned on a usage error.run402 credentials list [--project <id>] [--include-revoked]— metadata only; never a secret or a secret hash.run402 credentials rotate <credential_id> [--project <id>]— mint a replacement and revoke the old one in one transaction, keeping the name and recordingreplacement_of. New secret printed ONCE. For a rotation with NO downtime window, prefer issuing a second credential, deploying it, then revoking the first; userotatewhen the old secret is already compromised.run402 credentials revoke <credential_id> [--project <id>] [--reason <text>]— immediate, and frees the name for reuse.run402 credentials token [--project <id>] [--kind <anon|service>]— mint a SHORT-LIVED token (defaults toservice). This is the cold-restart recovery path and the ONE credential call an agent can make with no human present: a delegate is accepted. No step-up, because there is nobody to prompt; what it returns expires, so it cannot become a durable root.
Authority split: issue/rotate/revoke require owner membership on the project’s owning org PLUS a fresh step-up, and a delegate can NEVER satisfy them — otherwise a scoped agent credential could escalate itself into a permanent root. Authenticate with a wallet (SIWX) or a control-plane session (run402 operator login --step-up). token is the deliberate exception.
run402 credentials project-keys list— LOCAL CACHE read. Lists cached project-key entries withsource: "local_cache",cache_path,wallet/profile, key presence, prefixes, fingerprints, and timestamps. Never prints full keys.run402 credentials project-keys status --project <id>— LOCAL CACHE read for one project id.configured: falsemeans this selected wallet/profile lacks cached keys; it does not mean the server project is missing.run402 credentials project-keys import --project <id> --service-key-stdin— import a service key from stdin. Optional anon key comes from--anon-key-env <env>.run402 credentials project-keys import --project <id> --service-key-env <env>— import a service key from an environment variable. Do not pass service keys as argv values.run402 credentials project-keys import --project <id> --anon-key-env <env>— anon-only rotation. Import writes the whole cache entry, so the FIRST import for a project must supply a service key; once an entry exists,--anon-key-envalone rotates the anon key and keeps the cached service key. Rotating the anon key therefore never requires exporting the service key with--revealand passing it back through a shell. Passing--anon-key-envwith no cached service key fails withBAD_USAGEnaming that flag.run402 credentials project-keys export --project <id> --reveal— print cached secret key material. Requires--reveal.run402 credentials project-keys remove --project <id>— remove one local cache entry without deleting or changing the server project.
projects
Section titled “projects”run402 projects quoterun402 projects list [--org <id>] [--all]— SERVER read of the named, domain-aware inventory (NOT the local project-key cache). Membership-scoped by default: every project owned by an org your wallet is an active member of, each row{ project_id, name, site_url, custom_domains, org_id, status, active }(activefrom local state).--org <id>filters to one org (authorize-before-reveal: non-member/guessed id -> 403, non-UUID -> 400).--allreads the cross-wallet inventory across every wallet controlling your operator email — runrun402 operator loginfirst for the union, else it falls back to the current wallet’s slice and echoesscope. Barerun402 projects listis the cold-start path (no login needed). Tier/lifecycle live on the organization — userun402 status/run402 tier status.run402 projects rename <id> --name <label>— rename a project (fix an auto-generated name). Needs orgadmin+ (or aproject:writegrant) on the owning org; authorize-before-reveal (unauthorized/guessed id -> 403, never a not-found oracle). Works even if the project isn’t in the local project-key cache. Server-validated name (1-200 chars, no control characters).run402 projects provision [--name <name>] [--org <id>]—--orgprovisions into an EXISTING org (you needdeveloper+ on it); omit for the cold-start path (the wallet’s organization). Tier is org-governed — a client-supplied--tieris ignored when targeting an org. Against a configured Core target, creates a local Core project without Cloud payment and saves it as the active project.run402 projects use <id>— SERVER validation, then stores only the active project id in profile state. It does not require a matching local project-key cache entry.run402 projects current— LOCAL STATE read of the active project pointer with profile-state provenance and validation status.run402 projects get <id>— SERVER read of one project’s authoritative view:{ project_id, public_id, name, org_id, tier, effective_status, organization_lifecycle_state, site_url, custom_domains[], last_deploy, mailbox[], usage{api_calls, storage_bytes, api_calls_limit, storage_bytes_limit}, created_at }. Caller-authed (SIWX/control-plane, no project keys) and works even if the project isn’t in the local project-key cache; authorize-before-reveal (unauthorized/guessed id -> 403, never a not-found oracle). Returns NO keys — userun402 credentials project-keys ...for local credential-cache inspection/export.run402 projects info <id>— moved before public launch. Returns structuredCOMMAND_MOVED; useprojects get <id>for server detail orcredentials project-keys status --project <id>for local cache status.run402 projects sql <id> "<sql>" [--file <path>] [--params '<json_array>']run402 projects rest <id> <table> "<query>"run402 projects keys <id>— moved before public launch. Returns structuredCOMMAND_MOVED; usecredentials project-keys export --project <id> --revealfor cached key material.run402 projects costs <id> [--window <24h|7d|30d|90d>]— admin-only per-project finance: revenue, direct cost, margin, and cost breakdown. Uses the configured allowance wallet for admin auth;RUN402_ADMIN_COOKIE='run402_admin=...'is an optional browser-session override.run402 projects promote-user <id> <email>— promote a user to project_admin rolerun402 projects demote-user <id> <email>— demote a user from project_admin rolerun402 projects <usage|schema> <id>run402 projects delete <id> --confirm— cascade deletes all project resources: Lambda functions, subdomains, S3 site files, deployments, secrets, and published app versions. The schema slot is dropped and recreated. This is irreversible.--confirmis required.run402 projects validate-expose [id] <manifest_json>— validate an auth/expose manifest without applying itrun402 projects validate-expose [id] --file manifest.json [--migration-file setup.sql]— validate file input with optional migration-reference SQLrun402 projects apply-expose <id> <manifest_json>— apply a declarative authorization manifestrun402 projects apply-expose <id> --file manifest.json— apply from a JSON filerun402 projects get-expose <id>— print the current manifest (source: applied | introspected)
Provisioning automatically sets the new project as the active project. Other commands that take <id> default to the active project when omitted.
SQL supports DDL + queries, returns JSON. REST uses PostgREST syntax (select=, eq., order=, limit=).
User auth: password + Google OAuth. See “User Auth” section below.
admin (platform-admin only)
Section titled “admin (platform-admin only)”run402 admin lease-perpetual <organization_id> --enable | --disable— toggle the organization-level escape hatch. When enabled, the organization never advances pastactiveregardless of lease expiry; every project on the organization is pinned. Enabling on a grace-state organization (past_due / frozen / dormant) reactivates inline (reactivated: truein the response).run402 admin archive <project_id> [--reason "..."]— operator moderation. Setsprojects.archived_at = NOW()on a single project; sibling projects on the same organization keep serving. No-op when already archived (returnsnote: "already archived").run402 admin reactivate <project_id>— un-archive a project (flipsarchived_atback to NULL). It does not touch organization-level lifecycle. To reactivate a grace-state organization, runrun402 tier set <tier>(the tier flow runs the lifecycle advance inline) or enablerun402 admin lease-perpetual <org_id> --enable.
All admin subcommands require a platform-admin allowance wallet (or an admin OAuth session). Project owners with a non-admin wallet receive 403 admin_required.
apply, rehearsal, snapshots, branches
Section titled “apply, rehearsal, snapshots, branches”run402 apply --manifest app.json [--project <id>] [--no-rehearse] [--json]— alias forrun402 deploy apply; rehearsal is automatic for a migration-bearing plan against a project with a live release (see “Protecting a live database”),--no-rehearseskips it.run402 deploy rehearse [<plan_id>] [--manifest <path>] [--project <id>] [--teardown keep|on_pass|always] [--json]— ADVANCED: rehearse without committing. With no<plan_id>it discovers the manifest in the current directory the wayupdoes (or takes--manifest), creates a reviewed plan, uploads its bytes, and rehearses it. With a<plan_id>whose bytes were never uploaded (a--plan-only plan), the gateway answers409 REHEARSAL_CONTENT_MISSINGand the CLI uses the manifest to upload and retry; if facts changed since that plan a fresh plan is rehearsed and the result says so underreplanned. Source project data and the original plan stay untouched; a project with no live release rehearses on an empty branch. The result names the plan rehearsed and its bound commit command.run402 snapshots create [project-id] [--json]— capture a manual internal restore point.run402 snapshots list [project-id] [--kind manual|pre_migration|pre_restore|scheduled] [--limit <n>] [--after <cursor>] [--json]— keyset-paginated snapshot list.run402 snapshots get [project-id] <snapshot-id> [--json]— inspect one snapshot and its next actions.run402 snapshots restore [project-id] <snapshot-id> [--include-auth] [--json]— plan a restore and printrestore_plan.confirm.token; no mutation.run402 snapshots restore [project-id] <snapshot-id> --confirm <token> [--include-auth] [--json]— execute the atomic offline-materialize-then-flip restore. Auth users/passkeys are restored only with--include-auth; sessions and tokens are never restored.run402 snapshots delete [project-id] <snapshot-id> [--json]— delete a snapshot and release its CAS references.run402 branches create [project-id] [--from-snapshot <snapshot-id>] [--name <label>] [--email-mode sandbox|off] [--enable-cron] [--ttl-days <1..30>] [--json]— create a contained branch project. Email defaults to sandboxed, scheduled functions default off, and TTL defaults to 7 days. A parent with no live release yields an EMPTY branch (branch_url: null, no cloned release) whose host comes up on its first activation.run402 branches list [project-id] [--json]— list active branches for the parent project.run402 branches renew [project-id] <branch-project-id> [--ttl-days <1..30>] [--json]— extend a branch TTL.run402 branches delete [project-id] <branch-project-id> [--json]— delete a branch project and purge its resources.
deploy
Section titled “deploy”run402 deploy apply --manifest app.json [--project <id>] [--check|--print-spec|--print-manifest|--plan|--require-plan <id>] [--no-rehearse] [--json] [--quiet|--final-only] [--allow-warning <code> ...] [--allow-warnings] [--allow-dirty] [-v|--verbose]— unified apply primitive withassetsslice support; accepts JSON data manifests and explicit executable typed configs through the same--manifestflag. rehearsal against a contained branch is automatic when there is a live release to protect (--no-rehearseskips it);--jsonis accepted as a no-op because success output is always JSON. Against agitvault_policy: requiredproject, the deploy-lane capture applies the SAME dirty-tree rulerepos snapshotdoes: a dirty work tree refusesSNAPSHOT_DIRTY_TREEbefore any capture, and--allow-dirtycaptures it as-is with the samemodified_captured/untracked_captureddisclosure (see therepossection above and Observability). The final result always carries astatsblock;-v/--verbosealso prints a one-line stderr summary.run402 deploy resume <operation_id> [--project <id>] [--quiet]— re-run a stuck operation forwardrun402 deploy promote <release-id> [--project <id>] [--allow-warning <code>] [--allow-warnings]— operator pointer-swap (re-point live release without re-running the apply pipeline)run402 deploy list [--project <id>] [--limit <n>]— list recent deploy operationsrun402 deploy events <operation_id> [--project <id>]— fetch the recorded event stream for an operationrun402 deploy verify <operation_id>|--operation <operation_id> [--project <id>] [--wait] [--timeout <seconds>] [--json]— verify gateway/edge release coherence; exits 2 when a valid report remains not coherentrun402 deploy release get <release_id> [--project <id>] [--site-limit <n>]— fetch release inventoryrun402 deploy release active [--project <id>] [--site-limit <n>]— fetch current-live release inventoryrun402 deploy release diff --from <empty|active|release_id> --to <active|release_id> [--project <id>] [--limit <n>]— diff release targetsrun402 deploy diagnose [--project <id>] <url> [--method GET]— URL-first public deploy diagnosticsrun402 deploy resolve [--project <id>] (--url <url> | --host <host> [--path /x]) [--method GET]— lower-level resolver parity;--urlcannot be combined with--host/--path
Requires active tier and a provisioned project on Run402 Cloud. Against a configured Core target, uses the active Core project and does not require Cloud tier/allowance setup. Deploys to an existing project: runs migrations, applies the authorization manifest (from a manifest.json entry in files[]), deploys functions, deploys static site, and claims subdomain when the target supports that slice. Secret values are write-only: set them with printf %s "$OPENAI_API_KEY" | run402 secrets set <id> OPENAI_API_KEY --stdin or --file <path> before deploy, then use value-free secrets.require in deploy apply manifests. deploy apply stops before upload/commit on confirmation-required warnings unless each warning is covered by repeatable --allow-warning <code> or the broad reviewed --allow-warnings; --require-plan absorbs the warning approval already bound into the reviewed plan and rejects warning flags. The manifest must include project_id, or use --project, RUN402_PROJECT_ID, or an app-local workspace link. Omitting intent fails with UP_PROJECT_REQUIRED; it never falls back to the active project.
Inside GitHub Actions, deploy apply automatically uses OIDC credentials when GITHUB_ACTIONS=true, ACTIONS_ID_TOKEN_REQUEST_URL, and ACTIONS_ID_TOKEN_REQUEST_TOKEN are present. In that mode, project intent comes from --project, RUN402_PROJECT_ID, the app-local workspace link, or the manifest; conflicting selectors are rejected.
run402 live --tables <a,b> [--project <id>] [--cursor <cursor>] [--as anon|service]— stream change hints for live tables as NDJSON (Server-Sent Events under the hood; reconnects on its own)run402 live --tables <a,b> --once [--cursor <cursor>] [--wait <1..25>]— one held read: hints since the cursor, or hold up to--waitseconds for the first one
run402 ci link github [--project <id>] [--manifest <path>] [--repo <owner/repo>] [--branch <name> | --environment <name>] [--repository-id <id>] [--workflow <path>] [--expires-at <iso>] [--route-scope <pattern> ...] [--force]— create a GitHub Actions OIDC deploy binding and write a workflowrun402 ci list [--project <id>]— list CI bindings for a projectrun402 ci revoke <binding_id>— revoke a binding
link github requires a local allowance because it signs the delegation. The generated workflow does not require an allowance file or service key in GitHub; it uses GitHub’s OIDC token with id-token: write. Use repeatable --route-scope only when CI should deploy route declarations; no scopes means no CI route authority.
transfer (unified project transfer — wallet + email + owned-org recipient)
Section titled “transfer (unified project transfer — wallet + email + owned-org recipient)”One noun, three recipient kinds: wallet = two-party SIWX, completed by accept; email = email->org, completed by claim; owned org = --to-org <org_id> immediate same-actor org move. Same /projects/v1/:id/transfers; preview/list/cancel are kind-agnostic; rows carry recipient_kind. Pre-v1.93 /handoffs and --handoff(s) are gone.
run402 transfer init (--to <wallet|email> | --to-org <org_id>) [--project <id>] [--billing-policy migrate] [--message <text>] [--kysigned <record_id>] [--retain-collaborator developer]— owner/admin initiate.--toroutes by kind.--to-org: caller must actively own source+destination org; success completes immediately with accepted result + project keys.--retain-collaborator developer: email recipients only, onlydeveloper, rejected withBAD_FLAGon wallet/org rails; recipient must accept at claim; omit = full severance.--billing-policy/--kysignedwallet-only; email/org reject. Codes:INVALID_RETAIN_ROLE,RETAIN_SUBJECT_REQUIRED.run402 transfer preview <transfer_id>— fetch the preview document (any party; kind-agnostic). Lists custom domains, subdomains, function names, secret NAMES (never values), CI bindings that will be revoked on completion, mailbox summary, billing implications, and — on email transfers — theretain_collaboratoroffer.run402 transfer list [--incoming | --outgoing] [--limit N] [--offset N]—--incoming(default) shows transfers OFFERED TO you;--outgoingshows transfers you initiated. Pending rows are unioned and each entry carriesrecipient_kindandpreview_path.run402 transfer accept <transfer_id>— accept WALLET transfer. Atomically flips ownership, revokes previous owner CI bindings, stampssecrets_rotation_advised. Secret values inherited; response hassecret_names_inherited[], new owneranon_key+service_key; SDK/CLI persist keys and set project active.run402 transfer claim <transfer_id> [--into <organization_id>] [--accept-retained-collaborator]— claim EMAIL transfer into owned org; omit--intoto create new org. Email analog ofaccept.--accept-retained-collaboratoraccepts retained developer offer from preview; omit = severance. Result includesretained_collaborator_principal_id|null, keys persisted + project active. Keys derive fromproject_idand do not rotate; rotate inherited secrets withrun402 secrets set.run402 transfer cancel <transfer_id> [--reason <text>]— cancel a pending transfer of any kind (any authorized party).
Pending transfer: 72h TTL; owner-side mutations return 409 PROJECT_HAS_PENDING_TRANSFER with details.transfer_id + cancel next_actions[]. Data-plane and payment routes keep serving; transfer cancel unblocked. After accept/claim, rotate inherited secrets; secrets_rotation_advised clears after every inherited name is rewritten.
Does not transfer: tier lease (stays with original org; no proration), KMS signers, GitHub repo ownership, on-chain balances. Wallet transfers only support --billing-policy migrate; if recipient lacks active org, accept -> 409 RECIPIENT_ORGANIZATION_NOT_ACTIVE. Email/owned-org always migrate; do not pass --billing-policy.