docs/gateway/security/index.md was 89,057 characters, 9,905 words and 25 H2 sections mixing explanation, how-to, reference and vulnerability-report triage policy for two audiences. The page already lived in a directory with five siblings, so the split extends that directory rather than creating a parallel one, and index.md becomes a real index. New children in docs/gateway/security/ (alongside audit-checks, exposure-runbook, rate-limiting, secure-file-operations and dependency-locking): - trust-model.md (Security trust model) - scope, trust boundary matrix, findings closed as no-action, gateway/node trust, threat model, reporting. - running-the-audit.md - the `openclaw security audit` command, what it checks, triage order. - hardened-baseline.md - both copy/paste baselines and the requester-scoped controls note. - access-control.md - DM policy, allowlists, DM session isolation, context visibility, command authorization. - prompt-injection.md - prompt injection, external-content wrapping, bypass flags. - tool-permissions.md - control-plane tools, node execution, dynamic skills, plugins, sandboxing, per-agent access profiles. - browser-control.md - browser control risks and the SSRF policy. - network-exposure.md - bind/firewall, Docker/UFW, mDNS, Gateway auth, Tailscale, reverse proxy, HSTS, Control UI over HTTP, dangerous flags. - secrets-and-storage.md - host trust, secrets on disk, credential map, permissions, workspace .env, logs and transcripts, secret scanning. - operator-incident-response.md - contain, rotate, audit, collect. Anchor strategy Per-anchor redirects are not possible: redirectSource() in scripts/lib/docs-redirects.mjs rejects any source containing [?#]. Every anchor the old page published is therefore kept alive on the index itself as an authored <a id="..." /> stub inside a "Where each section moved" list, each pointing at its new home. Ids were computed with parseDocsDocument, not a slug approximation, so percent-encoded punctuation and compatibility aliases are preserved exactly. The index publishes no original heading itself, so no stub can collide with a canonical id. - pre-split ids on /gateway/security: 80 (57 headings, 20 compatibility aliases, 3 accordion targets) - still published by /gateway/security after the split: 80 - index collisions reported by parseDocsDocument: 0 - stub destinations checked against the destination pages: 60 (all resolve) Losslessness Reassembling the child section bodies in original order reproduces the original body byte for byte. Counts, original body vs children: - words 9,665 -> 9,664 - characters 87,422 -> 87,491 - code fences 32 -> 32 - markdown links 44 -> 45 - table rows 38 -> 38 The single word/link delta is the one declared prose edit: a cross-reference the split orphaned, `(see "Per-agent access profiles" above)` in the secure-baseline section, is now a link to /gateway/security/tool-permissions. The index intro line "The rest of this page is the deep end" became "The pages below are the deep end" for the same reason. No security control, threat-model statement, default or guarantee was reworded, softened or reordered; sections keep their original relative order within each child. Also updated: the "Security and sandboxing" nav group in docs/docs.json, eleven in-repo deep links repointed at the new pages (release notes left untouched, and their anchors still resolve through the stubs), and src/docs/environment-docs.test.ts, which asserts on the workspace-dotenv text that now lives in secrets-and-storage.md. Closes audit findings: r3-0302, r3-0308
9 KiB
| summary | read_when | title | ||
|---|---|---|---|---|
| Advanced setup and development workflows for OpenClaw |
|
Setup |
TL;DR
Pick a setup workflow based on how often you want updates and whether you want to run the Gateway yourself:
- Tailoring lives outside the repo: keep your config and workspace in
~/.openclaw/openclaw.jsonand~/.openclaw/workspace/so repo updates don't touch them. - Stable workflow (recommended for most): install the macOS app and let it run the bundled Gateway.
- Bleeding edge workflow (dev): run the Gateway yourself via
pnpm gateway:watch, then let the macOS app attach in Local mode.
Prereqs (from source)
- Node 24.16+ LTS or Node 26.1+ (recommended)
pnpmrequired for source checkouts. OpenClaw loads bundled plugins from theextensions/*pnpm workspace packages in dev mode, so rootnpm installdoes not prepare the full source tree.- Docker (optional; only for containerized setup/e2e - see Docker)
Use the pnpm version pinned in package.json. The workspace applies a seven-day
publication cooldown to npm dependencies, with trusted @openai/codex and
@openai/codex-* packages exempt. The standalone pnpm toolchain is managed separately.
For npm tooling that reads the project's .npmrc, use npm 11.19 or newer for
install and npm pack cooldowns and Codex exclusions. Node runtime support does
not imply support for its bundled npm as a source resolver. Published/global installs do not
inherit the repository's .npmrc. Source installs continue to use pnpm.
pnpm owns root and plugin-local dependencies, including workspace links and
versions that differ between packages. Postinstall and build preparation preserve
those trees. If an older checkout pruned plugin-local dependencies, run
pnpm install --frozen-lockfile after updating to restore them before testing.
Tailoring strategy (so updates do not hurt)
If you want "100% tailored to me" and easy updates, keep your customization in:
- Config:
~/.openclaw/openclaw.json(JSON/JSON5-ish) - Workspace:
~/.openclaw/workspace(skills, prompts, memories; make it a private git repo)
Bootstrap the config/workspace folders once, without running the full onboarding wizard:
openclaw setup --baseline
No global install yet? Run it from this repo instead:
pnpm openclaw setup --baseline
(Bare openclaw setup, without --baseline, opens an interactive OpenClaw chat on a configured system and falls through to guided onboarding on a fresh one. See Setup CLI for the full routing order.)
Run the Gateway from this repo
After pnpm build, you can run the packaged CLI directly:
node openclaw.mjs gateway --port 18789 --verbose
Stable workflow (macOS app first)
- Install + launch OpenClaw.app (menu bar).
- Complete the onboarding/permissions checklist (TCC prompts).
- Ensure Gateway is Local and running (the app manages it).
- Link surfaces (example: WhatsApp):
openclaw channels login
- Sanity check:
openclaw health
If onboarding is not available in your build:
- Run
openclaw setup, thenopenclaw channels login, then start the Gateway manually (openclaw gateway).
Bleeding edge workflow (Gateway in a terminal)
Goal: work on the TypeScript Gateway, get hot reload, keep the macOS app UI attached.
0) (Optional) Run the macOS app from source too
If you also want the macOS app on the bleeding edge:
./scripts/restart-mac.sh
1) Start the dev Gateway
pnpm install
# First run only (or after resetting local OpenClaw config/workspace)
pnpm openclaw setup
pnpm gateway:watch
What gateway:watch does:
- It starts or restarts the Gateway watch process in a named tmux session,
openclaw-gateway-watch-main, and auto-attaches from interactive terminals. - Non-interactive shells stay detached and print
tmux attach -t openclaw-gateway-watch-main. RunOPENCLAW_GATEWAY_WATCH_ATTACH=0 pnpm gateway:watchto keep an interactive run detached, orpnpm gateway:watch:rawfor foreground watch mode. - It stops the active profile's installed Gateway service before it takes over
that service's configured or default port. This prevents the service
supervisor from replacing the source process. The service stays installed.
Run
pnpm openclaw gateway startwhen you finish watching. - The tmux pane remains available after a startup failure, so another terminal or agent can attach to it or capture its logs.
- It reloads on relevant source, config, and bundled-plugin metadata changes.
- If the watched Gateway exits during startup,
gateway:watchrunsopenclaw doctor --fix --non-interactiveonce and retries. SetOPENCLAW_GATEWAY_WATCH_AUTO_DOCTOR=0to disable that dev-only repair pass.
TypeScript rebuilds triggered by pnpm openclaw ... or pnpm gateway:watch preserve existing dist/control-ui assets. When the Gateway starts, it rebuilds missing, incomplete, or stale bundled UI assets before serving them. Headless commands do not rebuild the UI. Run pnpm ui:build after ui/ changes, or use pnpm ui:dev while developing the Control UI.
2) Point the macOS app at your running Gateway
In OpenClaw.app:
- Connection Mode: Local The app will attach to the running gateway on the configured port.
3) Verify
- In-app Gateway status should read "Using existing gateway …"
- Or via CLI:
openclaw health
Common footguns
- Wrong port: Gateway WS defaults to
ws://127.0.0.1:18789; keep app + CLI on the same port. - Wrong developer CLI: When
PATHincludesnode_modules/.bin,codexcan resolve to the workspace-pinned CLI instead of your standalone installation. For developer workers, use the intended executable's absolute path for both--versionandexec, and confirm the worker's startup version. A package manifest or a version check in another shell does not identify a running worker. OpenClaw's managed Codex app-server has a separate pinned-version contract; do not change that pin or your model/auth settings to fix developer CLI selection. If the installed workspace package and native executable disagree with the lockfile, repair the install withpnpm installrather than editingnode_modules. - Where state lives:
- Channel/provider state:
~/.openclaw/credentials/ - Model auth profiles: SQLite auth stores (shared:
~/.openclaw/state/openclaw.sqlite; agent-local:~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite) - Sessions and transcripts:
~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite - Legacy/archive session artifacts:
~/.openclaw/agents/<agentId>/sessions/ - Logs:
/tmp/openclaw/
- Channel/provider state:
Credential storage map
Use this when debugging auth or deciding what to back up:
- WhatsApp:
~/.openclaw/credentials/whatsapp/<accountId>/creds.json - Telegram bot token: config/env or
channels.telegram.tokenFile(regular file only; symlinks rejected) - Discord bot token: config/env or SecretRef (env/file/exec/store providers)
- Slack tokens: config/env (
channels.slack.*) - Pairing allowlists:
~/.openclaw/credentials/<channel>-allowFrom.json(default account)~/.openclaw/credentials/<channel>-<accountId>-allowFrom.json(non-default accounts)
- Model auth profiles: shared and agent-local SQLite auth stores; see Auth credential semantics for inheritance and legacy shared-store relocation
- File-backed secrets payload (optional):
~/.openclaw/secrets.json - Legacy OAuth import:
~/.openclaw/credentials/oauth.jsonMore detail: Security.
Updating (without wrecking your setup)
- Keep
~/.openclaw/workspaceand~/.openclaw/as "your stuff"; don't put personal prompts/config into theopenclawrepo. - Updating source:
git pull+pnpm install+ keep usingpnpm gateway:watch.
Linux (systemd user service)
Linux installs use a systemd user service. By default, systemd stops user services on logout/idle, which kills the Gateway. Onboarding attempts to enable lingering for you (may prompt for sudo). If it's still off, run:
sudo loginctl enable-linger $USER
For always-on or multi-user servers, consider a system service instead of a user service (no lingering needed). See Gateway runbook for the systemd notes.
Related docs
- Gateway runbook (flags, supervision, ports)
- Gateway configuration (config schema + examples)
- Discord and Telegram (reply tags + replyToMode settings)
- OpenClaw assistant setup
- macOS app (gateway lifecycle)