Reference

API Reference

API Reference

Crabfleet exposes same-origin REST APIs and terminal WebSocket APIs from the Worker. Browser clients keep app state in D1-backed REST calls and attach to live Codex terminals through the multiplex terminal hub.

#Auth

Session cookie: crabbox_session

  • GitHub OAuth: /login/github
  • Bootstrap token: POST /api/login/token
  • Logout: POST /api/logout

GitHub sessions last 15 minutes. Bootstrap sessions last 1 hour. API JSON responses use cache-control: no-store.

#Public Endpoints

#GET /healthz

Returns:

ok

#GET /api/auth

Returns available login methods without requiring a session.

{
  "auth": {
    "github": true,
    "token": true
  },
  "deployment": {
    "label": "Crabfleet",
    "canonicalUrl": "https://crabfleet.openclaw.ai",
    "productUrl": "https://crabfleet.ai",
    "sshHost": "crabd.sh"
  }
}

The unauthenticated response exposes branding and SSH connection fields only. Preferred repository, default runtime, adapter profile, and other routing configuration are returned after authentication through /api/state.

#POST /api/login/token

{
  "token": "bootstrap-token"
}

Returns the bootstrap owner user and sets crabbox_session.

#GET /login/github

Starts GitHub OAuth with read:user read:org repo.

When GITHUB_REDIRECT_URI is configured, that validated HTTPS callback is authoritative for both authorization and token exchange. Login and SSH-link requests received on another origin redirect to the configured origin before any host-only state cookie is created, preserving the pending SSH code through callback. Without the binding, Crabfleet uses the request-origin callback; insecure non-loopback HTTP origins are rejected.

#GET /auth/github/callback

Completes OAuth, verifies active org membership, applies the allowlist, stores the user, and redirects to /app.

With GITHUB_REDIRECT_URI configured, callback requests whose origin or path does not exactly match the configured callback are rejected before token exchange.

#Session Endpoints

#POST /api/logout

Deletes the session and clears the cookie.

#GET /api/session

Returns current user and enabled auth methods.

#GET /api/state

Returns app state:

{
  "user": {},
  "auth": {},
  "org": "OpenClaw",
  "cap": 20,
  "retention": "30",
  "merge": "guarded",
  "allow": [],
  "repos": ["openclaw/crabfleet", "openclaw/crabbox"],
  "workflows": [],
  "cards": []
}

Owner-only fields:

  • allow
  • workflows

Every card may include:

  • changes: changed file summary; list responses omit diff patches
  • run: active run attempt, including selectionReason and capabilities
  • logs: last 80 events

#GitHub Lookup

#GET /api/github/refs?number=76552

Maintainer+. Searches enabled repos for issue/PR number matches.

{
  "matches": [
    {
      "repo": "openclaw/crabfleet",
      "number": 76552,
      "title": "Fix runtime policy",
      "source": "Issue",
      "state": "open",
      "url": "https://github.com/openclaw/crabfleet/issues/76552",
      "author": "octocat",
      "updatedAt": "2026-05-17T10:00:00Z",
      "body": "..."
    }
  ]
}

With GITHUB_TOKEN, lookup runs across all enabled repos. Without it, lookup falls back to the preferred repo.

#Cards

#POST /api/cards

Maintainer+. Creates a card.

{
  "prompt": "Implement allowlisted admin workflow",
  "repo": "openclaw/crabfleet",
  "source": "Prompt",
  "runtime": "auto",
  "policy": ""
}

Fields:

  • prompt: required, max 4000 chars.
  • repo: required, enabled repo.
  • title: optional, max 140 chars; derived from prompt if blank.
  • source: optional Prompt, Issue, or PR.
  • runtime: optional auto, container, or crabbox.
  • policy: optional. Blank, default, or repo_default uses a valid repo workflow policy, then open_pr.

Invalid explicit merge policies return 400.

#POST /api/cards/:id/actions

Actions:

  • start: maintainer, claim run or pulse active run.
  • pulse: maintainer, same as start for active runs.
  • advance: maintainer, move to next lane.
  • attach: viewer, fetch current card/logs.
  • watch: viewer, record watch event.
  • takeover: maintainer, requires active run and capabilities.takeover.
  • stall: maintainer, mark active run stalled and move to Human Review.

Response:

{
  "card": {}
}

Takeover errors:

  • 400 no active run to take over
  • 400 runtime does not support takeover

#GET /api/cards/:id/runs

Returns all run attempts for a card, newest first.

{
  "runs": [
    {
      "id": "CY-101-R1",
      "cardId": "CY-101",
      "attempt": 1,
      "runtime": "container",
      "status": "running",
      "controlIntent": null,
      "leaseId": null,
      "attachUrl": null,
      "vncUrl": null,
      "selectionReason": "default container runtime",
      "capabilities": {
        "terminal": true,
        "takeover": false,
        "vnc": false,
        "desktop": false,
        "logs": true,
        "artifacts": true
      },
      "operator": null,
      "lastHeartbeatAt": 1779000000000,
      "startedAt": 1779000000000,
      "endedAt": null,
      "createdAt": 1779000000000,
      "updatedAt": 1779000000000,
      "error": null
    }
  ]
}

#Interactive Sessions

#GET /api/shared-sessions/:id?token=:token

Public read-only endpoint for a generated session share link. Returns the shared interactive session, D1 event scrollback, and sharedReadOnly: true. Invalid, disabled, or rotated tokens return 404.

{
  "session": {
    "id": "IS-105",
    "sharedReadOnly": true,
    "canControl": false,
    "logs": []
  }
}

#POST /api/provision/interactive

Provision hook used by CRABBOX_INTERACTIVE_PROVISION_URL. It accepts the same session request payload as the external adapter contract and returns normalized provision status.

Auth:

  • If CRABBOX_INTERACTIVE_PROVISION_TOKEN is set, callers must send Authorization: Bearer <token>.
  • The token is required when CRABBOX_RUNTIME_ADAPTER_URL, CRABBOX_RUNTIME_PROVISION_URL, CRABBOX_CLOUDFLARE_RUNNER_URL, or CRABBOX_CLAWFLEET_URL is configured; backend-enabled deployments fail closed without it.

Backends:

  • Versioned lifecycle adapters are deliberately excluded from this stateless hook. Create those workspaces through POST /api/interactive-sessions, which durably records ownership before calling the adapter.
  • Direct built-in Sandbox calls without a managed interactive-session row acquire a durable standalone ownership fence before credential-policy registration. Standalone IDs cannot use the case-insensitive IS-<number> managed-session namespace. Retries with the same ID must match the original immutable request; abandoned claims and failed provisions enter the same generation-fenced cleanup path as managed sessions.
  • A request whose ID already belongs to a managed interactive session is rejected unless every immutable request field matches that row and the call wins an exact session-version ownership claim before allocating a Sandbox. Completion commits through the immutable lease, claim, agent-token, and status ownership fence while monotonically advancing the session version, so an intervening metadata edit does not discard the non-replayable result.
  • CRABBOX_RUNTIME_PROVISION_URL: forwards the session payload to a legacy create-only runtime adapter.
  • CRABBOX_CLOUDFLARE_RUNNER_URL: creates a Crabbox Cloudflare container sandbox and returns its lease reference.
  • CRABBOX_CLAWFLEET_URL: creates a ClawFleet OpenClaw instance and returns console/noVNC links.
  • ClawFleet handles crabbox sessions only; use CRABBOX_RUNTIME_PROVISION_URL or CRABBOX_CLOUDFLARE_RUNNER_URL for container sessions.
  • If neither backend is configured, returns pending_adapter with a message that the route is live.

For a successful direct built-in Sandbox provision, attachUrl is an absolute wss:// URL under /api/provision/interactive/:id/pty, and expiresAt is bounded by CRABBOX_STANDALONE_SANDBOX_TTL_SECONDS (default four hours, maximum one day). Connect with the same Authorization: Bearer <CRABBOX_INTERACTIVE_PROVISION_TOKEN> header used for provisioning. The Worker validates the unexpired standalone owner and exact active credential-policy generation, strips the bearer before opening the Sandbox terminal, proxies the WebSocket while periodically revalidating that ownership, and closes both peers after stop, expiry, or policy revocation. It never routes the connection through interactive_sessions. POST /api/provision/interactive/:id/stop always requires that configured bearer, even if runtime backend bindings were removed after creation, and atomically moves the exact owner plus every matching policy into durable cleanup; expiry follows the same path from cron and PTY access, and cleanup terminates the Sandbox terminal execution session before deleting its owner row.

#Versioned runtime adapter

Crabfleet authenticates every adapter request with Authorization: Bearer CRABBOX_RUNTIME_ADAPTER_TOKEN. Adapter URLs must use HTTPS, except literal loopback HTTP for same-host deployments. The original base URL may include a nested path, whose semantics are preserved, but any raw ? or # delimiter is rejected even when its query or fragment is empty. Authenticated adapter requests reject redirects so the bearer token cannot cross origins. The canonical control-plane base URL is persisted with the lifecycle registration before create. Replay, inspect, desktop connection, and delete fail closed unless the current configured URL exactly matches that registered identity, so a configuration change cannot redirect an existing workspace ID or turn a 404 from another origin into release proof.

  • POST /v1/workspaces: idempotent create. Crabfleet persists the deterministic adapter identity, TTL, idle timeout, requested capabilities, and exact serialized create payload before the request, then sends the same namespaced DNS-safe lowercase id and Idempotency-Key, plus repo, branch, runtime, opaque profile, command, prompt, ownership/lineage, and lifecycle settings. A definitive non-2xx response is read once, sanitized, and durably recorded as the failure reason before provider release begins. After an ambiguous result, a bounded reconciliation pass retries only that immutable payload and key when inspect returns 404; later edits to session metadata do not alter it.
  • GET /v1/workspaces/:id: inspect current status, capabilities, terminal URL, expiry, and provider resource identity. Status-only responses preserve previously stored capabilities and expiry; explicit null clears those fields. Active external sessions are reconciled in bounded batches; state responses wait only for a short foreground budget while remaining work continues in the Worker background.
  • DELETE /v1/workspaces/:id: stop/release. Crabfleet enters stopping before calling the adapter and marks the session stopped only after 204, 404, or a valid exact-ID terminal response confirms release; malformed successful bodies remain stopping. Plain-text and malformed-JSON responses are read once and sanitized before their evidence is retained. An explicit stop whose ownership claim loses returns success only when the exact workspace is already stopping or terminal; otherwise it returns a lifecycle conflict.
  • POST /v1/workspaces/:id/connections/desktop: mint a current transient desktop URL. expiresAt is optional; when present it must be in the future and no more than 15 minutes away. Accepted HTTPS URLs are treated as opaque signed connection material and redirected byte-for-byte without URL normalization. After minting, Crabfleet re-reads the exact current session status, control grant, capabilities, and registered adapter identity before redirecting; a concurrent stop, revocation, capability withdrawal, or lifecycle replacement discards the URL and denies access.

CRABBOX_RUNTIME_ADAPTER_NAMESPACE is required and must remain stable for the deployment. It prevents workspace and idempotency collisions when an adapter serves more than one Crabfleet tenant. The adapter workspace id is an immutable lifecycle route key and remains separate from an opaque providerResourceId; the provider identity is never interpreted as a legacy lease or sandbox ID. Create, inspect, and stop responses must echo the byte-exact requested DNS-safe id; whitespace normalization is not accepted. Responses use status, id, optional providerResourceId, attachUrl, capabilities, expiresAt, and message. Only a literal null clears a previously stored expiry; a malformed non-null timestamp invalidates the response. A terminal URL implies terminal capability only when the response omits a terminal capability; an explicit terminal: false wins. Supported status values include provisioning, ready, stopping, stopped, expired, and failed. Create-only legacy adapters cannot return stopping, because they do not own a later reconciliation lifecycle.

Every create, inspect, delete, and desktop response body is consumed through one 64 KiB bounded stream reader before JSON or text parsing. Declared or chunked oversized bodies are cancelled and fail safely: ambiguous create remains reconcilable, delete remains pending, inspect retries later, and desktop access is denied.

Adapter messages are untrusted display text. Crabfleet removes raw and slash-escaped HTTP/WebSocket connection URLs directly from arbitrary message/detail text; Bearer and Basic credentials; authorization, cookie, and API-key headers; and sensitive assignments such as quoted JSON, colon fields, token, ticket, access_token, passwords, signatures, and secrets before replacing opaque provider identifiers and storing text in lastEvent, events, terminal failure evidence, or archives. For non-successful or malformed responses, opaque providerResourceId, provider_resource_id, leaseId, and lease_id values are collected from body, workspace, and error envelopes before redaction. Sanitizing credential structure first prevents an identifier such as token from hiding token=secret.

An adapter-reported failed workspace is not locally terminal until Crabfleet calls DELETE and confirms release. Crabfleet durably clears create ambiguity and records the requested failed terminal state and original failure reason before awaiting DELETE, so reconciliation cannot replay the create or replace useful failure evidence with a generic release message. Asynchronous or uncertain release remains stopping; reconciliation records failed only after the workspace is gone. A stop racing an ambiguous create also remains stopping: every reconciliation pass uses a dedicated replay path fenced to the exact stopping row, pending marker, registered control plane, immutable payload, settings, and session version, then issues DELETE before recording the requested terminal state. Generic provisioning cannot restage that row. After confirmed release, Crabfleet re-reads and compare-and-swaps the current ambiguity marker and terminal intent: a cleared marker terminalizes immediately, while a still-pending create remains stopping. A valid exact-ID create response, including provisioning, or a definitive create rejection resolves that ambiguity.

#GET /api/terminal/ws

Viewer+, or public shared-link token for read-only sessions. Same-origin multiplex WebSocket endpoint used by the Ghostty WASM session grid. One browser socket can subscribe to multiple interactive sessions, receive PTY output frames, resize terminals, and send input only when the current user has control.

The wire format is a compact binary frame:

u16 magic 0x5943
u8 version 1
u8 message_type
u32 session_id_length
utf8 session_id
u32 payload_length
payload bytes

Supported browser actions:

  • Subscribe: attach to a session with output/snapshot/event flags and optional initial cols/rows.
  • Unsubscribe: detach one session without closing the hub.
  • Input / Key: send terminal bytes when control is granted.
  • Resize: forward terminal dimensions to the upstream PTY.
  • Stop: close the upstream subscription.
  • Ping: keepalive, answered with Pong.

Server messages include Welcome, Output, Event, Error, ControlRevoked, and Pong. Shared-link viewers can subscribe and scroll output, but input frames are rejected unless an owner/maintainer grants writable control. Subscriptions require the current terminal capability; withdrawing it prevents new attaches, closes existing terminal sockets on the next authorization check, suppresses raw attach URLs and attachable state from app, API, fleet, CLI, and SSH responses, and removes Fleet terminal/SSH affordances. Recurring and per-input authorization use short-lived D1 snapshots only; throttled subscription reconciliation runs independently and never blocks an input frame on provider I/O.

#POST /api/interactive-sessions/:id/clipboard

Viewer+ with writable terminal control. Uploads a browser clipboard image/file body into the controlled Cloudflare Sandbox workspace and returns { path, name, mediaType, byteCount }. The browser then pastes the returned path into the PTY. Max body size: 10 MiB. Non-Sandbox PTY backends do not expose file paste.

#GET /api/interactive-sessions/:id/vnc

Viewer+ with writable session control. For runtime-v1, Crabfleet authenticates the browser session, asks the adapter to mint a current desktop connection, validates its HTTPS URL and optional bounded expiry, and issues a no-store redirect. Versioned-adapter desktop URLs are never persisted in D1 or returned by fleet state. API and CLI session views expose an absolute canonical Crabfleet browser URL for this cookie-authenticated route; the SSH gateway does not mint or receive the underlying adapter URL. Legacy adapters retain their existing validated absolute VNC URL behavior for browser and CLI clients.

#GET /api/interactive-sessions/:id/pty

Viewer+. Legacy single-session WebSocket endpoint. Crabfleet authenticates the browser session, verifies the interactive session is still attachable, verifies terminal control, then proxies PTY bytes to the configured runner. Owners and maintainers have control by default; other viewers require an approved control request.

Target resolution:

  • CRABBOX_PTY_BRIDGE_URL: explicit bridge WebSocket URL/template. Templates support {id}, {leaseId}, {repo}, {branch}, and {runtime}. Crabfleet appends sessionId, leaseId, repo, branch, runtime, and command query parameters.
  • Provider terminal connection: if the provision adapter returned a wss:// URL, or literal loopback ws:// URL, Crabfleet retains it server-side and proxies to it unchanged, including its path and signed query string.
  • CRABBOX_CLOUDFLARE_RUNNER_URL: for cloudflare:<sandbox> leases, Crabfleet proxies to /v1/sandboxes/:sandbox/pty on the runner.

Both multiplex and legacy direct PTY routes append terminal cols and rows only to configured bridge and Cloudflare runner endpoints, never to an adapter attachUrl. Crabfleet authenticates versioned-adapter terminal upgrades with CRABBOX_RUNTIME_ADAPTER_TOKEN only when the terminal shares the persisted and currently configured adapter origin; adapter URLs never carry reusable shell credentials. If CRABBOX_PTY_BRIDGE_TOKEN or CRABBOX_CLOUDFLARE_RUNNER_TOKEN is set, Crabfleet sends it as a bearer token only to the upstream bridge/runner. The browser never receives upstream credentials.

#POST /api/openclaw/action-sessions

Internal OpenClaw service endpoint authenticated with Authorization: Bearer CRABBOX_OPENCLAW_TOKEN. Registers or resumes one durable github_actions session per workKey. Re-registration returns the same logical session and rotates its scoped agent token.

See GitHub Actions Sessions for the complete integration lifecycle and operational invariants.

Request:

{
  "workKey": "openclaw/crabfleet:pr:42",
  "workKind": "pr_repair",
  "repo": "openclaw/crabfleet",
  "branch": "fix/pr-42",
  "sourceUrl": "https://github.com/openclaw/crabfleet/pull/42",
  "runUrl": "https://github.com/openclaw/crabfleet/actions/runs/123",
  "purpose": "repair PR 42",
  "summary": "starting repair"
}

Response:

{
  "session": {},
  "agentToken": "rotated-session-token",
  "runnerPtyUrl": "wss://crabfleet.openclaw.ai/api/agent/interactive-sessions/IS-123/runner-pty?agentToken=...",
  "browserUrl": "https://crabfleet.openclaw.ai/app/sessions/IS-123"
}

runnerPtyUrl is directly usable with Node's global WebSocket; no custom headers are required. The query credential is session-scoped, rotates on registration, is stored only as a hash, and is not exposed through viewer/session APIs.

#GET /api/agent/interactive-sessions/:id/runner-pty

WebSocket endpoint for the outbound GitHub Actions runner. Authentication uses the scoped agentToken query parameter embedded in runnerPtyUrl. The runner sends raw terminal output bytes and receives raw viewer input bytes. One runner is current; a reconnect replaces the previous runner while browser viewers remain attached.

#POST /api/agent/interactive-sessions/:id/work-state

Agent-authenticated heartbeat and state update. Use Authorization: Bearer <agentToken>.

{
  "state": "running",
  "phase": "fixing_tests",
  "summary": "two tests fixed; checking CI",
  "codexThreadId": "thread-id",
  "codexTurnId": "turn-id",
  "completionReason": null
}

Every call updates lastHeartbeatAt. Active states are registered and running; phase keeps active steps distinguishable. Terminal states are completed, blocked, failed, and canceled.

#POST /api/interactive-sessions

Maintainer+. Creates a standalone Codex CLI workspace request.

{
  "repo": "openclaw/crabfleet",
  "branch": "main",
  "runtime": "container",
  "profile": "default",
  "command": "codex",
  "prompt": "Investigate flaky release CI",
  "parentSessionId": "IS-100",
  "rootSessionId": "IS-100",
  "purpose": "debug release CI",
  "summary": "checking the release workflow"
}

Fields:

  • repo: required, enabled repo.
  • branch: optional, default main.
  • runtime: optional crabbox or container; omission uses CRABFLEET_DEFAULT_RUNTIME, which defaults to container.
  • profile: optional opaque adapter profile, defaulted by CRABFLEET_DEFAULT_PROFILE.
  • github_actions is service-created through /api/openclaw/action-sessions and is not accepted by this endpoint.
  • command: optional, default codex.
  • prompt: optional initial context note.
  • parentSessionId: optional parent session for supervision trees.
  • rootSessionId: optional root session; inferred from the parent when present.
  • purpose: optional short mission label.
  • summary: optional list/closeout summary.

If CRABBOX_RUNTIME_ADAPTER_URL is configured, the Worker creates and reconciles the versioned adapter workspace and records its lifecycle identity, status, capabilities, expiry, and terminal connection. Otherwise CRABBOX_INTERACTIVE_PROVISION_URL retains the legacy create-only behavior. Without an adapter the session is stored as pending_adapter.

Session responses include ptyAvailable, the authenticated Worker's authoritative answer for whether the current terminal capability, lifecycle state, and configured Sandbox/bridge/runner route can resolve a PTY connection. A controllable runtime-v1 session exposes only the Worker-owned /api/interactive-sessions/:id/pty route in attachUrl; the signed provider connection remains server-side even for owners and controllers.

Built-in Sandbox sessions receive CRABFLEET_SESSION_ID, CRABFLEET_PARENT_SESSION_ID, CRABFLEET_ROOT_SESSION_ID, CRABFLEET_AGENT_TOKEN, and CRABFLEET_API_URL. The managed provision hook rotates a fresh agent token in the same durable claim that owns provisioning, then injects that exact token into the Sandbox. The agent token can call the /api/agent/* endpoints below for same-owner session discovery, child creation, transcripts, and summary updates.

#GET /api/interactive-sessions/:id/transcript

Viewer+. Returns the Markdown transcript from R2 when archived, or a D1 event-log transcript fallback.

#POST /api/interactive-sessions/:id/summary

Viewer+ with owner/maintainer access. Updates purpose and/or summary.

{
  "purpose": "review sibling fix",
  "summary": "waiting on CI"
}

#POST /api/interactive-sessions/:id/actions

Actions:

  • attach: viewer with control, mark seen/attached and return the session.
  • share_link: owner/maintainer, enable or rotate a public read-only share URL; response includes shareUrl once.
  • disable_share: owner/maintainer, disable the share URL and clear pending/granted control.
  • request_control: viewer, request writable terminal control.
  • approve_control: owner/maintainer, grant pending requester 30 minutes of writable terminal control.
  • deny_control: owner/maintainer, clear a pending control request.
  • revoke_control: owner/maintainer, revoke active delegated control.
  • enable_multiplayer: session creator, prefix submitted terminal prompts with the actor.
  • disable_multiplayer: session creator, stop prefixing submitted terminal prompts with the actor.
  • stop: owner/maintainer, stop the provider workspace first, then mark stopped; asynchronous releases remain stopping until reconciliation confirms completion.

Response:

{
  "session": {},
  "shareUrl": "https://crabfleet.openclaw.ai/app/sessions/IS-105?token=..."
}

#SSH Gateway

The Go gateway terminates raw SSH and calls Worker APIs with Authorization: Bearer CRABBOX_SSH_GATEWAY_TOKEN. These endpoints are not browser APIs.

  • POST /api/ssh/auth: checks a public-key fingerprint. Unknown keys receive a short /ssh/link/:code GitHub OAuth URL only when the gateway is in explicit link mode, e.g. ssh link@host.
  • GET /api/ssh/state: returns the same board/session state for the linked SSH user.
  • POST /api/ssh/interactive-sessions: creates an interactive Codex session for the linked SSH user.
  • GET /api/ssh/interactive-sessions/:id/logs: returns the D1 event stream plus R2 archive metadata for a visible crabbox session.
  • GET /api/ssh/interactive-sessions/:id/transcript: returns the Markdown transcript.
  • POST /api/ssh/interactive-sessions/:id/summary: updates purpose and/or summary.
  • GET /api/ssh/interactive-sessions/:id/pty: WebSocket PTY attach for the gateway, scoped by linked key fingerprint.

#Agent Session API

Crabfleet-issued session agents use Authorization: Bearer <CRABFLEET_AGENT_TOKEN> plus X-Crabfleet-Session-ID: <CRABFLEET_SESSION_ID>. These endpoints mirror the SSH lifecycle subset without requiring an SSH key inside the sandbox.

  • GET /api/agent/state: returns app/fleet state plus { agent: { sessionId, rootSessionId } }.
  • POST /api/agent/interactive-sessions: creates a child session owned by the same user and linked under the current agent session.
  • GET /api/agent/interactive-sessions/:id: reads a visible same-owner session.
  • GET /api/agent/interactive-sessions/:id/logs: returns event logs.
  • GET /api/agent/interactive-sessions/:id/transcript: returns the Markdown transcript.
  • POST /api/agent/interactive-sessions/:id/summary: updates purpose and/or summary.
  • GET /api/agent/interactive-sessions/:id/pty: WebSocket PTY attach/input for same-owner steering; the CLI uses this for crabfleet message.

#OpenClaw Service

Internal automation uses Authorization: Bearer CRABBOX_OPENCLAW_TOKEN.

#POST /api/openclaw/crabboxes

Creates a repo-ready crabbox for an operator, e.g. from a Discord meeting handoff.

{
  "owner": "@steipete",
  "repo": "openclaw/crabfleet",
  "branch": "main",
  "runtime": "crabbox",
  "command": "codex --yolo",
  "prompt": "prep the meeting follow-up"
}

Response:

{
  "session": {
    "id": "IS-105",
    "owner": "@steipete",
    "runtime": "crabbox",
    "vncUrl": "https://..."
  }
}

#Admin

Owner role required.

#POST /api/admin/allow

{
  "value": "@openclaw/maintainer",
  "role": "maintainer"
}

Values can be @login, @org/team, or email. Returns full state.

#DELETE /api/admin/allow/:value

Removes an allowlist entry. :value is URL encoded.

#POST /api/admin/repos

{
  "repo": "openclaw/crabfleet"
}

Enables a repo. Returns full state.

#DELETE /api/admin/repos/:repo

Disables a repo by setting enabled = 0.

#PUT /api/admin/policy

{
  "cap": 20,
  "retention": "30",
  "merge": "guarded"
}

Fields:

  • cap: 1-200.
  • retention: 14, 30, or 60.
  • merge: guarded, disabled, or maintainers.

#POST /api/admin/workflows/evaluate

Fetches and evaluates CRABBOX.md for an enabled repo. Private repos require deployment GITHUB_TOKEN access; the logged-in user's OAuth token is not used for this fetch.

{
  "repo": "openclaw/crabfleet"
}

Returns full state. Owner state includes workflow summaries with:

  • repo
  • status: ok, missing, invalid, or error
  • sourcePath
  • sourceSha
  • config
  • error
  • evaluatedAt
  • updatedAt

The stored prompt body is not returned in state summaries.

#GET /api/fleet

Returns the redacted fleet registry for the signed-in viewer.

Includes:

  • canonicalUrl
  • productUrl
  • registryAvailable
  • egress
  • totals
  • sessions

Secrets, ciphertext, and token values are never returned.

#Static Routes

  • / and /app: app shell.
  • /docs, /docs/, /docs/spec, /docs/spec/: generated docs page, or Markdown when Accept includes text/markdown.
  • /docs/spec.md: Markdown spec.
  • /docs/spec-v2, /docs/spec-v2/: generated v2 spec page, or Markdown when Accept includes text/markdown.
  • /docs/spec-v2.md: Markdown v2 spec.
  • /crabbox-logo.png: logo.
  • /vendor/ghostty-web.js: local Ghostty WASM bundle.

#Error Shape

{
  "error": "message"
}

Common statuses:

  • 400: invalid input or unsupported action.
  • 401: missing/expired session.
  • 403: insufficient role, repo blocked, or no longer allowlisted.
  • 404: missing card or route.
  • 503: GitHub dependency unavailable or rate limited.