Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
fb7fe0d
refactor: centralize URL security policy
steipete Jun 15, 2026
09f9008
refactor: extract Worker deployment foundations
steipete Jun 15, 2026
5f29cf6
refactor: extract Worker database foundation
steipete Jun 15, 2026
691d732
refactor: extract Worker HTTP foundation
steipete Jun 15, 2026
a0d21b8
refactor: extract Worker ingress policy
steipete Jun 15, 2026
2a2c290
refactor: extract Worker authentication
steipete Jun 15, 2026
bee69b5
refactor: extract GitHub authentication
steipete Jun 15, 2026
af3a6fe
refactor: extract interactive session model
steipete Jun 15, 2026
e03c66e
refactor: extract OpenClaw request replay
steipete Jun 15, 2026
a16240f
refactor: extract OpenClaw room repository
steipete Jun 15, 2026
a483268
refactor: extract OpenClaw reservations
steipete Jun 15, 2026
0072cdb
refactor: extract OpenClaw supervision
steipete Jun 15, 2026
9868b87
refactor: extract OpenClaw root stop
steipete Jun 15, 2026
a57c9b9
refactor: extract OpenClaw queries
steipete Jun 15, 2026
670d20f
refactor: extract OpenClaw mutations
steipete Jun 15, 2026
be5bc33
refactor: extract OpenClaw creation
steipete Jun 15, 2026
eb87d1b
refactor: extract session lineage
steipete Jun 15, 2026
ffc5a1c
refactor: extract session creation coordination
steipete Jun 15, 2026
dd1d30f
refactor: extract session reservation persistence
steipete Jun 15, 2026
ba68071
refactor: extract provision completion
steipete Jun 15, 2026
4b68b8b
refactor: centralize session reservations
steipete Jun 15, 2026
635fdc3
refactor: extract session create requests
steipete Jun 15, 2026
5dd8881
refactor: extract session reservation context
steipete Jun 15, 2026
0eb6426
refactor: recover superseded provisions
steipete Jun 15, 2026
1c560fd
refactor: extract session event repository
steipete Jun 15, 2026
770fcde
refactor: centralize shared session policy
steipete Jun 15, 2026
69b770a
refactor: assemble session aggregates
steipete Jun 15, 2026
80e5483
refactor: extract session metadata persistence
steipete Jun 15, 2026
03315ed
refactor: extract session metadata service
steipete Jun 15, 2026
38aa125
refactor: extract session attach service
steipete Jun 15, 2026
f563ff7
refactor: extract session stop routing
steipete Jun 15, 2026
450d7e2
refactor: extract runtime adapter stop service
steipete Jun 15, 2026
46e7150
refactor: centralize session stop persistence
steipete Jun 15, 2026
2597433
refactor: centralize session access policy
steipete Jun 15, 2026
65be3a6
refactor: extract session log archive
steipete Jun 15, 2026
e099451
refactor: extract session presentation policy
steipete Jun 15, 2026
3d3ab8f
refactor: extract terminal finalization
steipete Jun 15, 2026
cd6e8b5
refactor: unify session event append
steipete Jun 15, 2026
242056f
refactor: extract session cleanup service
steipete Jun 15, 2026
162aaa6
refactor: extract session reconciliation
steipete Jun 15, 2026
cc82117
refactor: extract reconciliation scheduler
steipete Jun 15, 2026
23778ac
refactor: share bounded concurrency
steipete Jun 15, 2026
f76c267
refactor: extract agent session authentication
steipete Jun 15, 2026
fb986ed
refactor: extract GitHub Actions registration
steipete Jun 15, 2026
2bfaea1
refactor: extract GitHub Actions work state
steipete Jun 15, 2026
a0b0964
refactor: extract GitHub Actions runner connection
steipete Jun 15, 2026
cb9a5db
refactor: extract terminal route policy
steipete Jun 15, 2026
882cd98
refactor: extract terminal websocket bridge
steipete Jun 15, 2026
33deea7
refactor: extract runtime adapter transport
steipete Jun 15, 2026
1ab0c8e
refactor: remove legacy runtime providers
steipete Jun 15, 2026
9838d40
refactor: remove legacy terminal bridge
steipete Jun 15, 2026
c7a2755
fix: synchronize terminal protocol clients
steipete Jun 15, 2026
1f791bd
refactor: extract provisioning dispatch
steipete Jun 15, 2026
ad2fd72
refactor: extract runtime adapter provisioning
steipete Jun 15, 2026
3b5ee4c
refactor: extract managed sandbox provisioning
steipete Jun 15, 2026
9ae4fc5
refactor: extract standalone sandbox provisioning
steipete Jun 15, 2026
be38bff
refactor: extract auth routes
steipete Jun 15, 2026
19523c0
refactor: extract OpenClaw routes
steipete Jun 15, 2026
1997c54
refactor: unify service session routes
steipete Jun 15, 2026
7005842
refactor: share interactive session routes
steipete Jun 15, 2026
2ed6984
refactor: extract control plane routes
steipete Jun 15, 2026
2f8a734
refactor: extract session ingress routes
steipete Jun 15, 2026
1baa7ce
refactor: isolate scheduled reconciliation
steipete Jun 15, 2026
ffd51f1
refactor: extract app dialogs
steipete Jun 15, 2026
5bfb1f7
refactor: extract app routing and layout
steipete Jun 15, 2026
beeb772
refactor: extract app data lifecycle
steipete Jun 15, 2026
65e0483
refactor: extract app shell components
steipete Jun 15, 2026
378816a
refactor: extract app drawers
steipete Jun 15, 2026
514d136
refactor: extract session workspace
steipete Jun 15, 2026
c6d80fe
refactor: extract app navigation
steipete Jun 15, 2026
5dc9361
refactor: extract app mutations
steipete Jun 15, 2026
eccfc24
refactor: extract app lifecycle hooks
steipete Jun 15, 2026
c9ef836
refactor: remove unsupported provider lifecycle
steipete Jun 15, 2026
e432d9e
refactor: centralize provisioning results
steipete Jun 15, 2026
df08bde
refactor: extract runtime adapter workspaces
steipete Jun 15, 2026
3edd015
refactor: extract terminal hub
steipete Jun 15, 2026
c7dc8c8
refactor: extract session control durable object
steipete Jun 15, 2026
387711b
refactor: centralize sandbox credential policy state
steipete Jun 15, 2026
3a9dbad
refactor: extract sandbox credential cleanup
steipete Jun 15, 2026
3807875
refactor: extract credential policy scanner
steipete Jun 15, 2026
7817248
refactor: extract credential cleanup service
steipete Jun 15, 2026
900b217
refactor: unify credential policy maintenance
steipete Jun 15, 2026
0c92b00
refactor: extract sandbox outbound gateway
steipete Jun 15, 2026
885f8a2
refactor: extract sandbox credential registration
steipete Jun 15, 2026
84803dc
refactor: extract sandbox runtime primitives
steipete Jun 15, 2026
38b0c0c
refactor: extract sandbox runtime bootstrap
steipete Jun 15, 2026
b7a58d1
refactor: extract ssh gateway service
steipete Jun 15, 2026
9d91148
refactor: extract provisioning endpoints
steipete Jun 15, 2026
dd70339
refactor: extract sandbox lifecycle
steipete Jun 15, 2026
71f6227
refactor: remove legacy credential policy migration
steipete Jun 15, 2026
affa751
refactor: extract interactive terminal service
steipete Jun 15, 2026
a564942
refactor: extract desktop access service
steipete Jun 15, 2026
ed910df
refactor: extract sandbox session resources
steipete Jun 15, 2026
5d79a95
refactor: extract card lifecycle
steipete Jun 15, 2026
b127f29
refactor: extract workflow evaluation
steipete Jun 15, 2026
7c929e7
refactor: extract admin configuration
steipete Jun 15, 2026
1abc32b
refactor: extract github reference search
steipete Jun 15, 2026
ba6cca8
refactor: extract runtime adapter release
steipete Jun 15, 2026
879e655
refactor: centralize session creation
steipete Jun 15, 2026
37bb820
refactor: centralize github actions persistence
steipete Jun 15, 2026
cde32a0
refactor: centralize worker persistence
steipete Jun 15, 2026
1306edd
refactor: extract openclaw branch service
steipete Jun 15, 2026
4a3c9fc
refactor: centralize session summary metadata
steipete Jun 15, 2026
bd0426c
refactor: extract github actions stop lifecycle
steipete Jun 15, 2026
6d23fc3
refactor: extract browser session policy
steipete Jun 15, 2026
1a71345
refactor: remove protocol compatibility
steipete Jun 15, 2026
73a5149
fix: keep action dialogs in control
steipete Jun 15, 2026
ef5a021
refactor: integrate upstream terminal capabilities
steipete Jun 15, 2026
fa8c335
refactor: cut terminal protocol to v2
steipete Jun 15, 2026
5ce309f
refactor: extract terminal persistence
steipete Jun 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/deploy-worker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,13 @@ jobs:
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CRABBOX_OPENCLAW_TOKEN: ${{ secrets.CRABBOX_OPENCLAW_TOKEN }}
CRABBOX_EMBED_TICKET_SECRET: ${{ secrets.CRABBOX_EMBED_TICKET_SECRET }}
run: |
set -euo pipefail
if [ -z "${CRABBOX_EMBED_TICKET_SECRET:-}" ]; then
echo "::error::Set CRABBOX_EMBED_TICKET_SECRET before deploying Crabfleet."
exit 1
fi
runtime_token="$(
node -e '
const { createHmac } = require("node:crypto");
Expand All @@ -95,12 +100,15 @@ jobs:
trap 'rm -f "$secrets_file"' EXIT
SECRETS_FILE="$secrets_file" \
CRABBOX_RUNTIME_ADAPTER_TOKEN="$runtime_token" \
CRABBOX_EMBED_TICKET_SECRET="$CRABBOX_EMBED_TICKET_SECRET" \
node -e '
const { writeFileSync } = require("node:fs");
writeFileSync(
process.env.SECRETS_FILE,
JSON.stringify({
CRABBOX_OPENCLAW_TOKEN: process.env.CRABBOX_OPENCLAW_TOKEN,
CRABBOX_EMBED_TICKET_SECRET:
process.env.CRABBOX_EMBED_TICKET_SECRET,
CRABBOX_RUNTIME_ADAPTER_TOKEN:
process.env.CRABBOX_RUNTIME_ADAPTER_TOKEN,
}),
Expand All @@ -127,4 +135,3 @@ jobs:
set -euo pipefail
test "$(curl --fail --silent --show-error --retry 12 --retry-all-errors --retry-delay 5 --max-time 20 https://crabfleet.openclaw.ai/healthz)" = "ok"
test "$(curl --fail --silent --show-error --location --retry 12 --retry-all-errors --retry-delay 5 --max-time 20 --output /dev/null --write-out '%{url_effective}' https://crabfleet.ai/)" = "https://docs.crabfleet.ai/"
test "$(curl --fail --silent --show-error --location --retry 12 --retry-all-errors --retry-delay 5 --max-time 20 --output /dev/null --write-out '%{url_effective}' https://www.crabfleet.ai/)" = "https://docs.crabfleet.ai/"
86 changes: 78 additions & 8 deletions CHANGELOG.md

Large diffs are not rendered by default.

53 changes: 18 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Crabfleet gives OpenClaw maintainers a fleet dashboard where every Codex crabbox
- **Cloudflare Sandbox containers** for standalone interactive Codex CLI workspaces with live PTY attach.
- **Runtime descriptors** for card scheduling evidence and capability display.
- **Versioned lifecycle adapter** for idempotent external workspace creation, bounded status reconciliation, provider-backed deletion, terminal attachment, and authenticated transient desktop connections.
- **Provision endpoint** at `/api/provision/interactive` that can use the built-in Sandbox backend or retain a legacy create-only adapter or ClawFleet integration, with durable ownership and a bearer-authenticated standalone PTY route.
- **Provision endpoint** at `/api/provision/interactive` for durable built-in Sandbox ownership and a bearer-authenticated standalone PTY route.
- **SessionControlDO relay** for one outbound GitHub Actions runner and multiple authenticated Ghostty viewers per action session.
- **R2 session archives** for periodically refreshed interactive-session event NDJSON, transcripts, and summaries, finalized at terminal completion.
- **GitHub API** for OAuth, org/team membership, and issue/PR previews across enabled repos.
Expand Down Expand Up @@ -154,7 +154,7 @@ merge:
### Prerequisites

- Cloudflare account
- `crabfleet.openclaw.ai` route in Cloudflare; legacy OpenClaw app hosts redirect here
- `crabfleet.openclaw.ai` route in Cloudflare
- GitHub OAuth app (optional but recommended)
- Bootstrap token secret

Expand All @@ -164,15 +164,14 @@ Pushes to `main` run `.github/workflows/deploy-worker.yml`, which checks, tests,
deploys the generic product router, applies remote D1 migrations, and deploys the app
Worker. Configure the repository secret `CLOUDFLARE_API_TOKEN` with permissions for
Workers deploys and D1 migrations.
`crabfleet.openclaw.ai` is a Worker Custom Domain declared in the app Wrangler
config. The `crabfleet.ai` product Custom Domains, stale classic-route cleanup,
and `crabd.sh` DNS convergence are handled by
`crabfleet.openclaw.ai` is the only app Worker Custom Domain declared in the app
Wrangler config. The `crabfleet.ai` product Custom Domain and `crabd.sh` DNS
convergence are handled by
`scripts/ensure-cloudflare-domains.mjs`; set `CLOUDFLARE_DNS_API_TOKEN` for
manual deploys and when CI should manage those records. Without that
DNS-scoped repository secret, CI skips domain convergence but still fails the
deploy unless the app health endpoint is reachable and both product hosts resolve
to `docs.crabfleet.ai`. The app Worker keeps the same public-docs redirect as a
defensive fallback, never the authenticated app.
deploy unless the app health endpoint is reachable and `crabfleet.ai` resolves
to `docs.crabfleet.ai`.
The product router source and deploy configuration live in `src/product-router.ts` and
`wrangler.product.jsonc`.

Expand All @@ -184,8 +183,8 @@ CLOUDFLARE_DNS_API_TOKEN=... \
pnpm run deploy
```

`pnpm deploy:product` deploys only the generic product Worker, then converges its
two public Custom Domains and stale classic-route cleanup.
`pnpm deploy:product` deploys only the generic product Worker, then converges
the canonical product Custom Domain.

### Environment Variables

Expand All @@ -204,41 +203,27 @@ The Crabbox namespace cutover intentionally has no old-name compatibility. Exist
- `GITHUB_ORG` – GitHub org for membership check (default: `openclaw`)
- `GITHUB_TOKEN` – GitHub token for all enabled repo issue/PR previews and private repo `CRABBOX.md` refreshes (optional; public/default repo paths work without it)
- `CRABBOX_TOKEN_ENCRYPTION_KEY` – Optional encryption key for per-session GitHub OAuth tokens; defaults to `GITHUB_CLIENT_SECRET`
- `CRABBOX_INTERACTIVE_PROVISION_URL` – Optional adapter endpoint for standalone Codex CLI workspaces
- `CRABBOX_INTERACTIVE_PROVISION_TOKEN` – Optional bearer token sent to the interactive provision endpoint; required when backend URLs below are configured and always required to stop an existing standalone Sandbox
- `CRABBOX_INTERACTIVE_PROVISION_TOKEN` – Required bearer token for the built-in Sandbox provision, PTY, and stop endpoints
- `CRABBOX_STANDALONE_SANDBOX_TTL_SECONDS` – Optional built-in standalone Sandbox lifetime, default `14400`, bounded to 300–86400 seconds
- `CRABBOX_RUNTIME_ADAPTER_URL` – Optional fixed base URL for the versioned workspace lifecycle adapter; mutually exclusive with `CRABBOX_RUNTIME_ADAPTER_URL_TEMPLATE`, takes precedence over the legacy create-only runtime provision URL, and becomes immutable registration identity for each created lifecycle. Nested base paths are preserved; raw query or fragment delimiters are rejected.
- `CRABBOX_RUNTIME_ADAPTER_URL` – Optional fixed base URL for the versioned workspace lifecycle adapter; mutually exclusive with `CRABBOX_RUNTIME_ADAPTER_URL_TEMPLATE` and becomes immutable registration identity for each created lifecycle. Nested base paths are preserved; raw query or fragment delimiters are rejected.
- `CRABBOX_RUNTIME_ADAPTER_URL_TEMPLATE` – Optional profile-routed alternative containing exactly one `{profile}` full path segment. Selected profile IDs must be lowercase DNS labels; the resolved URL is validated and persisted with the same immutable lifecycle fence as a fixed adapter URL.
- `CRABBOX_COORDINATOR_ORIGIN` – Optional public origin corresponding to the `CRABBOX_COORDINATOR` service binding. Matching fixed or profile-routed lifecycle and terminal requests use the binding; other adapter origins use normal outbound fetch.
- `CRABBOX_RUNTIME_ADAPTER_TOKEN` – Required bearer token for the versioned lifecycle adapter; sent only over HTTPS or literal loopback HTTP
- `CRABBOX_RUNTIME_ADAPTER_NAMESPACE` – Required stable tenant namespace when the versioned adapter is enabled; a DNS-safe label of at most 32 characters used in every workspace ID and idempotency key
- `CRABBOX_RUNTIME_ADAPTER_TTL_SECONDS` – Optional requested workspace TTL, default `14400`
- `CRABBOX_RUNTIME_ADAPTER_IDLE_SECONDS` – Optional requested workspace idle timeout, default `1800`
- `CRABBOX_RUNTIME_PROVISION_URL` – Optional generic backend URL used by `/api/provision/interactive`
- `CRABBOX_RUNTIME_PROVISION_TOKEN` – Optional bearer token sent to the generic runtime backend
- `CRABBOX_CLOUDFLARE_RUNNER_URL` – Optional Crabbox Cloudflare container runner URL used by `/api/provision/interactive`
- `CRABBOX_CLOUDFLARE_RUNNER_TOKEN` – Optional bearer token sent to the Cloudflare runner
- `CRABBOX_CLOUDFLARE_RUNNER_INSTANCE_TYPE` – Optional runner instance type, default `standard-4`
- `CRABBOX_CLOUDFLARE_RUNNER_WORKDIR` – Optional base workdir for provisioned sandboxes, default `/workspace/crabbox`
- `CRABBOX_CLOUDFLARE_RUNNER_TTL_SECONDS` – Optional sandbox TTL, default `14400`
- `CRABBOX_CLOUDFLARE_RUNNER_IDLE_SECONDS` – Optional idle timeout, default `1800`
- `CRABBOX_PTY_BRIDGE_URL` – Optional WebSocket PTY bridge URL/template for live Ghostty attach; requires WSS except literal loopback WS and supports `{id}`, `{leaseId}`, `{repo}`, `{branch}`, and `{runtime}`
- `CRABBOX_PTY_BRIDGE_TOKEN` – Optional bearer token sent from Crabfleet to the PTY bridge
- `CRABBOX_CLAWFLEET_URL` – Optional ClawFleet dashboard/API URL used by `/api/provision/interactive` for `crabbox` sessions
- `CRABBOX_CLAWFLEET_TOKEN` – Optional bearer token sent to ClawFleet
- `CRABBOX_CLAWFLEET_PUBLIC_URL` – Optional public ClawFleet URL used when building attach/VNC links
- `CRABBOX_OPENCLAW_TOKEN` – Internal bearer token for OpenClaw service crabbox and GitHub Actions session registration
- `CRABBOX_MULTICODEX_TOKEN` – Optional dedicated bearer token for MultiCodex room supervision
- `CRABBOX_EMBED_TICKET_SECRET` – Crabfleet-only signing key for short-lived terminal embed tickets
- `CRABFLEET_SSH_GATEWAY_TOKEN` / `CRABBOX_SSH_GATEWAY_TOKEN` – Shared bearer token for the Go SSH gateway internal API
- `CRABBOX_EMBED_TICKET_SECRET` – Crabfleet-only signing key for short-lived, session-scoped terminal embed tickets
- `CRABFLEET_SSH_GATEWAY_TOKEN` – Shared bearer token for the Go SSH gateway internal API
- `CRABFLEET_LOCAL_SANDBOX_BACKUPS` – Optional Cloudflare Sandbox checkpoint mode override; defaults to R2 binding uploads, set `0` for SDK presigned R2 uploads
- `CRABFLEET_LABEL` – Optional tenant label shown in the app, default `Crabfleet`
- `CRABFLEET_CANONICAL_URL` – Optional tenant app/API origin, default `https://crabfleet.openclaw.ai`; requires HTTPS except literal loopback HTTP
- `CRABFLEET_PRODUCT_URL` – Optional tenant product/docs origin, default `https://crabfleet.ai`; requires HTTPS except literal loopback HTTP
- `CRABFLEET_SSH_HOST` – Optional SSH command host shown in the app, default `crabd.sh`
- `CRABFLEET_PREFERRED_REPO` – Optional first/default enabled repo, default `openclaw/crabfleet`
- `CRABFLEET_DEFAULT_RUNTIME` – Optional interactive runtime default, `container` or `crabbox`; defaults to `container`
- `CRABFLEET_INTERACTIVE_RUNTIMES` – Optional comma-separated allowlist of interactive runtime choices, `container`, `crabbox`, or both; defaults to `container,crabbox`. A single choice hides the runtime selector and becomes the default unless `CRABFLEET_DEFAULT_RUNTIME` explicitly names it.
- `CRABFLEET_DEFAULT_RUNTIME` – Optional interactive runtime default, `container` or `crabbox`; defaults to `container` when enabled or otherwise the only enabled runtime
- `CRABFLEET_INTERACTIVE_RUNTIMES` – Optional comma-separated allowlist of manual interactive runtimes, `container`, `crabbox`, or both; defaults to `container,crabbox`
- `CRABFLEET_DEFAULT_PROFILE` – Optional opaque runtime-adapter profile, default `default`
- `CRABFLEET_RUNTIME_PROFILES_JSON` – Optional bounded JSON array of generic profile descriptors (`id`, `label`, optional `target`, optional boolean `capabilities`, and optional `codexSsh`) shown to authenticated users when creating Crabbox sessions; when configured, `CRABFLEET_DEFAULT_PROFILE` must name one entry. `codexSsh.aliasTemplate` may use `{providerResourceId}`, `{workspaceId}`, `{sessionId}`, and `{profile}`. Optional `codexSsh.setupCommand` is an argv-like JSON string array: its first item and static items are shell-safe tokens, while any later item may be one complete placeholder. Crabfleet shell-quotes every substituted argument.
- `CRABFLEET_DEV_LOGIN_ENABLED` – Explicit local-only development identity login gate; disabled unless exactly `true`, and still restricted to literal localhost requests
Expand Down Expand Up @@ -316,7 +301,7 @@ wrangler d1 migrations apply DB --local

### SSH Gateway

The Worker exposes an internal SSH onboarding API guarded by `CRABFLEET_SSH_GATEWAY_TOKEN` or `CRABBOX_SSH_GATEWAY_TOKEN`.
The Worker exposes an internal SSH onboarding API guarded by `CRABFLEET_SSH_GATEWAY_TOKEN`.
Run the Go gateway next to a host that can accept raw SSH:

```bash
Expand All @@ -330,7 +315,7 @@ go run ./cmd/crabbox-ssh-gateway
Unknown public keys get a short GitHub OAuth link through `ssh link@host`. Linked keys can
run `whoami`, `list`, `new`, `attach SESSION_ID`, and `delete SESSION_ID`; `new` creates an
interactive Codex session and attaches. Delete confirms runtime release for versioned lifecycle
adapters; legacy create-only and ClawFleet sessions stop locally and may need provider cleanup.
adapters and cleans up built-in Sandbox sessions through their durable ownership records.

Production should expose the gateway at `crabd.sh` as a DNS-only `A` record.
Use `ssh link@crabd.sh` once to connect a GitHub-backed SSH key, then run
Expand Down Expand Up @@ -361,8 +346,6 @@ go run ./cmd/crabfleet restore <session-id> <checkpoint-id>
go run ./cmd/crabfleet doctor
```

`crabfleet stop <session-id>` remains a compatibility alias for `delete`.

### CLI Release

Tagged releases publish `crabfleet` with GoReleaser and dispatch the OpenClaw Homebrew tap updater:
Expand All @@ -385,7 +368,7 @@ curl -fsS https://crabfleet.openclaw.ai/api/openclaw/crabboxes \
-d '{"owner":"@steipete","repo":"openclaw/crabfleet","prompt":"prep the meeting follow-up"}'
```

The created crabbox appears in the fleet grid under the requested owner. Provisioning follows normal interactive-session routing: built-in Sandbox for Container, the versioned adapter for Crabbox, or an intentionally configured legacy path.
The created crabbox appears in the fleet grid under the requested owner. Provisioning follows normal interactive-session routing: built-in Sandbox for Container or the versioned adapter for Crabbox.

### Project Structure

Expand Down
Loading