Run Claude Code inside an isolated OpenShell sandbox using the published image:
ghcr.io/openrind/openrind-shell/sandbox:just-bash
No local source checkout or JavaScript toolchain is required for the normal user flow. Contributor workflows live in BUILD.md.
- Docker is running.
- The
openshellCLI is installed. curlis available for creating the optional Openrind Gateway presign.ANTHROPIC_API_KEYis set in the shell where you runopenshell.DATABASE_URLpoints at an external PostgreSQL (Supabase, Neon, etc.). Openrind Shell has no embedded database — workspaces always live in PostgreSQL.
If you keep credentials in .env, load them first:
set -a
source .env
set +aFor Supabase, use the pooler connection string from Project Settings -> Database -> Connection pooler. It looks like:
postgresql://postgres.PROJECT:PASSWORD@aws-0-REGION.pooler.supabase.com:6543/postgres
Sensitive home credentials and config such as .ssh, .aws, .git-credentials, .npmrc, and keyrings are intentionally not persisted.
export ANTHROPIC_API_KEY='sk-ant-...'
export DATABASE_URL='postgresql://...'
# Compatibility with .env files that use POSTGRES_URL.
export DATABASE_URL="${DATABASE_URL:-${POSTGRES_URL:-}}"
printf '%s' "$DATABASE_URL" > /tmp/openrind-shell-db-url
chmod 600 /tmp/openrind-shell-db-url
openshell gateway start
openshell sandbox create --tty \
--from ghcr.io/openrind/openrind-shell/sandbox:just-bash \
--upload /tmp/openrind-shell-db-url:/sandbox/db-url \
--provider claude --auto-providers \
-- openrind-shell
rm -f /tmp/openrind-shell-db-urlThe first Claude Code launch may ask you to choose a theme, accept the security notice, trust /sandbox, and confirm API usage billing. After that, Claude opens with HOME=/home/agent inside the sandbox.
Openrind Shell reads /sandbox/db-url, creates the _openrind schema, runs migrations, restores the persisted workspace into /home/agent, syncs changes during runtime, and does a final flush on shutdown. In Supabase, switch the Table Editor schema selector to _openrind to inspect the rows.
Reuse the same sandbox name on every machine, and point it at the same DATABASE_URL. Openrind Shell uses the OpenShell sandbox ID as the workspace ID, so --name openrind-shell-claude is what makes the same PostgreSQL-backed home restore after deletion or from another host.
Do not pass the database URL through an OpenShell generic provider. PostgreSQL is raw TCP, so the credential must be delivered by --upload.
Openrind Gateway is optional. It routes Claude Code API calls through a presigned proxy URL for token and cost metering.
export ANTHROPIC_API_KEY='sk-ant-...'
export OPENRIND_GATEWAY_API_KEY='sk-st-...'
OPENRIND_SHELL_INPUT="$(mktemp -d)"
curl -fsS https://app.openrind.com/v1/presign \
-H "Authorization: Bearer $OPENRIND_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "anthropic",
"client_api_key": "'"$ANTHROPIC_API_KEY"'",
"path": ["/v1/messages"],
"expires_in": -1,
"max_uses": -1,
"cost_limit": 10000000,
"metadata": { "source": "openrind-shell-sandbox", "client": "claude-code", "labels": ["openrind-shell", "claude-code"] }
}' \
> "$OPENRIND_SHELL_INPUT/presign.json"
# Optional: combine PostgreSQL persistence in the same upload.
export DATABASE_URL="${DATABASE_URL:-${POSTGRES_URL:-}}"
if [ -n "${DATABASE_URL:-}" ]; then
printf '%s' "$DATABASE_URL" > "$OPENRIND_SHELL_INPUT/db-url"
fi
chmod -R go-rwx "$OPENRIND_SHELL_INPUT"
openshell provider create --name openrind-gateway --type generic \
--credential "OPENRIND_GATEWAY_API_KEY=$OPENRIND_GATEWAY_API_KEY" \
|| openshell provider update openrind-gateway \
--credential "OPENRIND_GATEWAY_API_KEY=$OPENRIND_GATEWAY_API_KEY"
openshell sandbox create --tty \
--from ghcr.io/openrind/openrind-shell/sandbox:just-bash \
--upload "$OPENRIND_SHELL_INPUT:/sandbox/openrind-shell-input" \
--provider claude --auto-providers \
-- openrind-shell
rm -rf "$OPENRIND_SHELL_INPUT"Create the presign on the host. Inside OpenShell, provider secrets are placeholders; they work for HTTP headers but not as JSON body values for Openrind Gateway's client_api_key.
OpenClaw is an alternative AI coding agent that runs in the same image. The openclaw provider is what signals the sandbox to launch OpenClaw instead of Claude Code.
Create the provider once (this is the only one-time step — the provider persists in your OpenShell gateway):
openshell provider create --name openclaw --type generic \
--credential "OPENRIND_SHELL_AGENT=openclaw" \
|| openshell provider update openclaw \
--credential "OPENRIND_SHELL_AGENT=openclaw"OpenClaw uses the same _openrind schema as Claude Code. Both ANTHROPIC_API_KEY and DATABASE_URL must be delivered as uploaded files — OpenShell provider credentials arrive as opaque placeholders that OpenClaw's gateway cannot resolve, and PostgreSQL is raw TCP that needs the literal connection string.
export ANTHROPIC_API_KEY='sk-ant-...'
export DATABASE_URL='postgresql://...'
export DATABASE_URL="${DATABASE_URL:-${POSTGRES_URL:-}}"
OPENRIND_SHELL_INPUT="$(mktemp -d)"
printf '%s' "$ANTHROPIC_API_KEY" > "$OPENRIND_SHELL_INPUT/anthropic-api-key"
printf '%s' "$DATABASE_URL" > "$OPENRIND_SHELL_INPUT/db-url"
chmod -R go-rwx "$OPENRIND_SHELL_INPUT"
openshell gateway start
openshell sandbox create --tty --name openrind-shell-openclaw \
--from ghcr.io/openrind/openrind-shell/sandbox:just-bash \
--upload "$OPENRIND_SHELL_INPUT:/sandbox/openrind-shell-input" \
--provider openclaw --auto-providers \
-- openrind-shell
rm -rf "$OPENRIND_SHELL_INPUT"setup.sh reads /sandbox/openrind-shell-input/anthropic-api-key, writes it into ~/.openclaw/openclaw.json, starts the openclaw gateway on ws://127.0.0.1:18789, waits for /readyz, then launches the OpenClaw TUI. Reuse --name openrind-shell-openclaw on every machine and point it at the same DATABASE_URL so the PostgreSQL-backed home restores after deletion or on another host.
If Claude Code launches instead of OpenClaw, the
openclawprovider was not created or was not passed. Run theopenshell provider createcommand above (one-time) and ensure you pass--provider openclawin the sandbox create command.
Note: For Openrind Gateway cost tracking on OpenClaw, see Add Openrind Gateway Tracking for OpenClaw.
Openrind Gateway is optional. It routes OpenClaw's Anthropic API calls through a presigned proxy URL so token spend, COGS, and revenue land in your Openrind Gateway vendor portfolio under the openclaw label.
export ANTHROPIC_API_KEY='sk-ant-...'
export OPENRIND_GATEWAY_API_KEY='sk-st-...'
export DATABASE_URL='postgresql://...'
export DATABASE_URL="${DATABASE_URL:-${POSTGRES_URL:-}}"
OPENRIND_SHELL_INPUT="$(mktemp -d)"
curl -fsS https://app.openrind.com/v1/presign \
-H "Authorization: Bearer $OPENRIND_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "anthropic",
"client_api_key": "'"$ANTHROPIC_API_KEY"'",
"path": ["/v1/messages"],
"expires_in": -1,
"max_uses": -1,
"cost_limit": 10000000,
"metadata": { "source": "openrind-shell-sandbox", "client": "openclaw", "labels": ["openrind-shell", "openclaw"] }
}' \
> "$OPENRIND_SHELL_INPUT/presign.json"
printf '%s' "$ANTHROPIC_API_KEY" > "$OPENRIND_SHELL_INPUT/anthropic-api-key"
printf '%s' "$DATABASE_URL" > "$OPENRIND_SHELL_INPUT/db-url"
chmod -R go-rwx "$OPENRIND_SHELL_INPUT"
openshell provider create --name openclaw --type generic \
--credential "OPENRIND_SHELL_AGENT=openclaw" \
|| openshell provider update openclaw \
--credential "OPENRIND_SHELL_AGENT=openclaw"
openshell sandbox create --tty --name openrind-shell-openclaw-openrind-gateway \
--from ghcr.io/openrind/openrind-shell/sandbox:just-bash \
--upload "$OPENRIND_SHELL_INPUT:/sandbox/openrind-shell-input" \
--provider openclaw --auto-providers \
-- openrind-shell
rm -rf "$OPENRIND_SHELL_INPUT"Create the presign on the host. Inside OpenShell, provider secrets are placeholders; they work for HTTP headers but not as JSON body values for Openrind Gateway's client_api_key. The metadata.labels: ["openrind-shell", "openclaw"] field is what Openrind Gateway's vendor portfolio classifier reads, so OpenClaw usage shows up separately from Claude Code in your dashboard.
setup.sh reads the uploaded presign.json, exports ANTHROPIC_BASE_URL so the openclaw gateway routes all Anthropic traffic through the proxy, and writes the URL into ~/.openclaw/openclaw.json so reconnect sessions also get the override. The real ANTHROPIC_API_KEY is still required — openclaw onboard writes it to ~/.openclaw/agents/main/agent/auth-profiles.json, and the Openrind Gateway proxy ignores the inbound x-api-key because it authenticates via the token embedded in the proxy URL.
openshell sandbox list
openshell sandbox connect <name>
openshell sandbox delete <name>Run one-off commands through SSH config:
openshell sandbox ssh-config <name> > /tmp/openrind-shell-sandbox-ssh
ssh -F /tmp/openrind-shell-sandbox-ssh openshell-<name> \
'HOME=/home/agent node /opt/openrind-shell/dist/bin/openrind-shell.js memory refresh'Keep the HOME=/home/agent prefix. OpenShell SSH starts in /sandbox, while Openrind Shell state lives under /home/agent.
No active gateway / gateway not reachable - run openshell gateway start --recreate. The --recreate flag handles a stopped or crashed gateway container without conflicts.
Claude exits with Input must be provided either through stdin or as a prompt argument - the command was run without an interactive terminal. Use a real terminal and keep --tty in the command.
Claude says authentication failed - set ANTHROPIC_API_KEY in the same shell that runs openshell sandbox create.
Claude says credit balance is too low - the Anthropic account for that key needs credits or billing enabled.
Files disappear after sandbox delete - PostgreSQL persistence was not enabled. Use the /sandbox/db-url upload flow above.
OpenClaw hangs at noodling… and never responds — the API key was not delivered to OpenClaw. The openclaw provider credential arrives as an opaque placeholder that OpenClaw cannot use directly. You must upload the real key as a file: include anthropic-api-key in the openrind-shell-input directory as shown in Start OpenClaw.
OpenClaw shows Gateway: not reachable at ws://127.0.0.1:18789 — the openclaw gateway failed to start before the TUI launched. Check /tmp/openclaw-gateway.log inside the sandbox (openshell sandbox connect <name> then cat /tmp/openclaw-gateway.log). The gateway stages 35 npm packages on first cold start and can take a few minutes; setup waits up to 10 minutes before giving up.
setup.sh: error: DATABASE_URL is required. — no PostgreSQL connection string was uploaded. Openrind Shell has no embedded fallback. Pass --upload /tmp/openrind-shell-db-url:/sandbox/db-url (or place db-url inside /sandbox/openrind-shell-input/ for OpenClaw) as shown in Start Claude Code or Start OpenClaw.
Migration fails with tunnel to ... denied - 403 - the PostgreSQL host is not allowlisted in the image policy. Common Supabase pooler hosts are included. Other hosts require a custom image; see BUILD.md.
Migration fails with EAI_AGAIN or a placeholder-looking database URL - do not use a generic db provider for PostgreSQL. Upload the connection string file with --upload /tmp/openrind-shell-db-url:/sandbox/db-url.
The openrind-desktop/ subdirectory is Openrind Desktop — our rebrand of the open-source OpenWork project (the local-first desktop app and CLI for AI-assisted workflows, built on top of OpenCode).
Openrind Desktop provides sessions, live SSE streaming, permissions, templates, and a skills manager. The non-opensource ee/ directory has been removed; everything here is MIT-licensed.
To restore dependencies after cloning, see openrind-desktop/README.md.
To sync openrind-desktop to a newer version:
git fetch https://github.com/Pavitra-programmers/openwork feat/openshell-integration
git read-tree --prefix=openrind-desktop/ -u FETCH_HEADArchitecture, image customization, source-development workflows, and tests are documented in BUILD.md.