diff --git a/docs/channels/bluebubbles.md b/docs/channels/bluebubbles.md index f67ddf32d80..8868901ce40 100644 --- a/docs/channels/bluebubbles.md +++ b/docs/channels/bluebubbles.md @@ -381,7 +381,7 @@ BlueBubbles supports advanced message actions when enabled in config: - **reply**: Reply to a specific message (`messageId`, `text`, `to`). - **sendWithEffect**: Send with iMessage effect (`text`, `to`, `effectId`). - **renameGroup**: Rename a group chat (`chatGuid`, `displayName`). - - **setGroupIcon**: Set a group chat's icon/photo (`chatGuid`, `media`) — flaky on macOS 26 Tahoe (API may return success but the icon does not sync). + - **setGroupIcon**: Set a group chat's icon/photo (`chatGuid`, `media`) - flaky on macOS 26 Tahoe (API may return success but the icon does not sync). - **addParticipant**: Add someone to a group (`chatGuid`, `address`). - **removeParticipant**: Remove someone from a group (`chatGuid`, `address`). - **leaveGroup**: Leave a group chat (`chatGuid`). @@ -412,12 +412,12 @@ See [Configuration](/gateway/configuration) for template variables. ## Coalescing split-send DMs (command + URL in one composition) -When a user types a command and a URL together in iMessage — e.g. `Dump https://example.com/article` — Apple splits the send into **two separate webhook deliveries**: +When a user types a command and a URL together in iMessage - e.g. `Dump https://example.com/article` - Apple splits the send into **two separate webhook deliveries**: 1. A text message (`"Dump"`). 2. A URL-preview balloon (`"https://..."`) with OG-preview images as attachments. -The two webhooks arrive at OpenClaw ~0.8-2.0 s apart on most setups. Without coalescing, the agent receives the command alone on turn 1, replies (often "send me the URL"), and only sees the URL on turn 2 — at which point the command context is already lost. +The two webhooks arrive at OpenClaw ~0.8-2.0 s apart on most setups. Without coalescing, the agent receives the command alone on turn 1, replies (often "send me the URL"), and only sees the URL on turn 2 - at which point the command context is already lost. `channels.bluebubbles.coalesceSameSenderDms` opts a DM into merging consecutive same-sender webhooks into a single agent turn. Group chats continue to key per-message so multi-user turn structure is preserved. @@ -446,7 +446,7 @@ The two webhooks arrive at OpenClaw ~0.8-2.0 s apart on most setups. Without coa } ``` - With the flag on and no explicit `messages.inbound.byChannel.bluebubbles`, the debounce window widens to **2500 ms** (the default for non-coalescing is 500 ms). The wider window is required — Apple's split-send cadence of 0.8-2.0 s does not fit in the tighter default. + With the flag on and no explicit `messages.inbound.byChannel.bluebubbles`, the debounce window widens to **2500 ms** (the default for non-coalescing is 500 ms). The wider window is required - Apple's split-send cadence of 0.8-2.0 s does not fit in the tighter default. To tune the window yourself: @@ -467,7 +467,7 @@ The two webhooks arrive at OpenClaw ~0.8-2.0 s apart on most setups. Without coa - **Added latency for DM control commands.** With the flag on, DM control-command messages (like `Dump`, `Save`, etc.) now wait up to the debounce window before dispatching, in case a payload webhook is coming. Group-chat commands keep instant dispatch. - - **Merged output is bounded** — merged text caps at 4000 chars with an explicit `…[truncated]` marker; attachments cap at 20; source entries cap at 10 (first-plus-latest retained beyond that). Every source `messageId` still reaches inbound-dedupe so a later MessagePoller replay of any individual event is recognized as a duplicate. + - **Merged output is bounded** - merged text caps at 4000 chars with an explicit `…[truncated]` marker; attachments cap at 20; source entries cap at 10 (first-plus-latest retained beyond that). Every source `messageId` still reaches inbound-dedupe so a later MessagePoller replay of any individual event is recognized as a duplicate. - **Opt-in, per-channel.** Other channels (Telegram, WhatsApp, Slack, …) are unaffected. @@ -494,7 +494,7 @@ If the flag is on and split-sends still arrive as two turns, check each layer: grep coalesceSameSenderDms ~/.openclaw/openclaw.json ``` - Then `openclaw gateway restart` — the flag is read at debouncer-registry creation. + Then `openclaw gateway restart` - the flag is read at debouncer-registry creation. @@ -508,13 +508,13 @@ If the flag is on and split-sends still arrive as two turns, check each layer: - Session event timestamps (`~/.openclaw/agents//sessions/*.jsonl`) reflect when the gateway hands a message to the agent, **not** when the webhook arrived. A queued-second message tagged `[Queued messages while agent was busy]` means the first turn was still running when the second webhook arrived — the coalesce bucket had already flushed. Tune the window against the BB server log, not the session log. + Session event timestamps (`~/.openclaw/agents//sessions/*.jsonl`) reflect when the gateway hands a message to the agent, **not** when the webhook arrived. A queued-second message tagged `[Queued messages while agent was busy]` means the first turn was still running when the second webhook arrived - the coalesce bucket had already flushed. Tune the window against the BB server log, not the session log. On smaller machines (8 GB), agent turns can take long enough that the coalesce bucket flushes before the reply completes, and the URL lands as a queued second turn. Check `memory_pressure` and `ps -o rss -p $(pgrep openclaw-gateway)`; if the gateway is over ~500 MB RSS and the compressor is active, close other heavy processes or bump to a larger host. - If the user tapped `Dump` as a **reply** to an existing URL-balloon (iMessage shows a "1 Reply" badge on the Dump bubble), the URL lives in `replyToBody`, not in a second webhook. Coalescing does not apply — that's a skill/prompt concern, not a debouncer concern. + If the user tapped `Dump` as a **reply** to an existing URL-balloon (iMessage shows a "1 Reply" badge on the Dump bubble), the URL lives in `replyToBody`, not in a second webhook. Coalescing does not apply - that's a skill/prompt concern, not a debouncer concern. @@ -617,15 +617,15 @@ When the same handle has both an iMessage and an SMS chat on the Mac (for exampl - Edit/unsend require macOS 13+ and a compatible BlueBubbles server version. On macOS 26 (Tahoe), edit is currently broken due to private API changes. - Group icon updates can be flaky on macOS 26 (Tahoe): the API may return success but the new icon does not sync. - OpenClaw auto-hides known-broken actions based on the BlueBubbles server's macOS version. If edit still appears on macOS 26 (Tahoe), disable it manually with `channels.bluebubbles.actions.edit=false`. -- `coalesceSameSenderDms` enabled but split-sends (e.g. `Dump` + URL) still arrive as two turns: see the [split-send coalescing troubleshooting](#split-send-coalescing-troubleshooting) checklist — common causes are too-tight debounce window, session-log timestamps misread as webhook arrival, or a reply-quote send (which uses `replyToBody`, not a second webhook). +- `coalesceSameSenderDms` enabled but split-sends (e.g. `Dump` + URL) still arrive as two turns: see the [split-send coalescing troubleshooting](#split-send-coalescing-troubleshooting) checklist - common causes are too-tight debounce window, session-log timestamps misread as webhook arrival, or a reply-quote send (which uses `replyToBody`, not a second webhook). - For status/health info: `openclaw status --all` or `openclaw status --deep`. For general channel workflow reference, see [Channels](/channels) and the [Plugins](/tools/plugin) guide. ## Related -- [Channel Routing](/channels/channel-routing) — session routing for messages -- [Channels Overview](/channels) — all supported channels -- [Groups](/channels/groups) — group chat behavior and mention gating -- [Pairing](/channels/pairing) — DM authentication and pairing flow -- [Security](/gateway/security) — access model and hardening +- [Channel Routing](/channels/channel-routing) - session routing for messages +- [Channels Overview](/channels) - all supported channels +- [Groups](/channels/groups) - group chat behavior and mention gating +- [Pairing](/channels/pairing) - DM authentication and pairing flow +- [Security](/gateway/security) - access model and hardening diff --git a/docs/concepts/oauth.md b/docs/concepts/oauth.md index e23212f892e..3f48dbb0d83 100644 --- a/docs/concepts/oauth.md +++ b/docs/concepts/oauth.md @@ -8,7 +8,7 @@ read_when: title: "OAuth" --- -OpenClaw supports “subscription auth” via OAuth for providers that offer it +OpenClaw supports "subscription auth" via OAuth for providers that offer it (notably **OpenAI Codex (ChatGPT OAuth)**). For Anthropic, the practical split is now: @@ -25,7 +25,7 @@ For Anthropic in production, API key auth is the safer recommended path. - where tokens are **stored** (and why) - how to handle **multiple accounts** (profiles + per-session overrides) -OpenClaw also supports **provider plugins** that ship their own OAuth or API‑key +OpenClaw also supports **provider plugins** that ship their own OAuth or API-key flows. Run them via: ```bash @@ -38,7 +38,7 @@ OAuth providers commonly mint a **new refresh token** during login/refresh flows Practical symptom: -- you log in via OpenClaw _and_ via Claude Code / Codex CLI → one of them randomly gets “logged out” later +- you log in via OpenClaw _and_ via Claude Code / Codex CLI → one of them randomly gets "logged out" later To reduce that, OpenClaw treats `auth-profiles.json` as a **token sink**: @@ -105,7 +105,7 @@ Claude login on the host, onboarding/configure can reuse it directly. ## OAuth exchange (how login works) -OpenClaw’s interactive login flows are implemented in `@mariozechner/pi-ai` and wired into the wizards/commands. +OpenClaw's interactive login flows are implemented in `@mariozechner/pi-ai` and wired into the wizards/commands. ### Anthropic setup-token @@ -125,7 +125,7 @@ Flow shape (PKCE): 1. generate PKCE verifier/challenge + random `state` 2. open `https://auth.openai.com/oauth/authorize?...` 3. try to capture callback on `http://127.0.0.1:1455/auth/callback` -4. if callback can’t bind (or you’re remote/headless), paste the redirect URL/code +4. if callback can't bind (or you're remote/headless), paste the redirect URL/code 5. exchange at `https://auth.openai.com/oauth/token` 6. extract `accountId` from the access token and store `{ access, refresh, expires, accountId }` @@ -156,7 +156,7 @@ Two patterns: ### 1) Preferred: separate agents -If you want “personal” and “work” to never interact, use isolated agents (separate sessions + credentials + workspace): +If you want "personal" and "work" to never interact, use isolated agents (separate sessions + credentials + workspace): ```bash openclaw agents add work @@ -189,6 +189,6 @@ Related docs: ## Related -- [Authentication](/gateway/authentication) — model provider auth overview -- [Secrets](/gateway/secrets) — credential storage and SecretRef -- [Configuration Reference](/gateway/configuration-reference#auth-storage) — auth config keys +- [Authentication](/gateway/authentication) - model provider auth overview +- [Secrets](/gateway/secrets) - credential storage and SecretRef +- [Configuration Reference](/gateway/configuration-reference#auth-storage) - auth config keys diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md index ad5fa0a7087..51f4b260238 100644 --- a/docs/gateway/configuration.md +++ b/docs/gateway/configuration.md @@ -103,16 +103,16 @@ candidate contains redacted secret placeholders such as `***`. Each channel has its own config section under `channels.`. See the dedicated channel page for setup steps: - - [WhatsApp](/channels/whatsapp) — `channels.whatsapp` - - [Telegram](/channels/telegram) — `channels.telegram` - - [Discord](/channels/discord) — `channels.discord` - - [Feishu](/channels/feishu) — `channels.feishu` - - [Google Chat](/channels/googlechat) — `channels.googlechat` - - [Microsoft Teams](/channels/msteams) — `channels.msteams` - - [Slack](/channels/slack) — `channels.slack` - - [Signal](/channels/signal) — `channels.signal` - - [iMessage](/channels/imessage) — `channels.imessage` - - [Mattermost](/channels/mattermost) — `channels.mattermost` + - [WhatsApp](/channels/whatsapp) - `channels.whatsapp` + - [Telegram](/channels/telegram) - `channels.telegram` + - [Discord](/channels/discord) - `channels.discord` + - [Feishu](/channels/feishu) - `channels.feishu` + - [Google Chat](/channels/googlechat) - `channels.googlechat` + - [Microsoft Teams](/channels/msteams) - `channels.msteams` + - [Slack](/channels/slack) - `channels.slack` + - [Signal](/channels/signal) - `channels.signal` + - [iMessage](/channels/imessage) - `channels.imessage` + - [Mattermost](/channels/mattermost) - `channels.mattermost` All channels share the same DM policy pattern: @@ -329,7 +329,7 @@ candidate contains redacted secret placeholders such as `***`. } ``` - Build the image first — from a source checkout run `scripts/sandbox-setup.sh`, or from an npm install see the inline `docker build` command in [Sandboxing § Images and setup](/gateway/sandboxing#images-and-setup). + Build the image first - from a source checkout run `scripts/sandbox-setup.sh`, or from an npm install see the inline `docker build` command in [Sandboxing § Images and setup](/gateway/sandboxing#images-and-setup). See [Sandboxing](/gateway/sandboxing) for the full guide and [full reference](/gateway/config-agents#agentsdefaultssandbox) for all options. @@ -531,7 +531,7 @@ candidate contains redacted secret placeholders such as `***`. ## Config hot reload -The Gateway watches `~/.openclaw/openclaw.json` and applies changes automatically — no manual restart needed for most settings. +The Gateway watches `~/.openclaw/openclaw.json` and applies changes automatically - no manual restart needed for most settings. Direct file edits are treated as untrusted until they validate. The watcher waits for editor temp-write/rename churn to settle, reads the final file, and rejects @@ -550,7 +550,7 @@ for the checklist. | Mode | Behavior | | ---------------------- | --------------------------------------------------------------------------------------- | | **`hybrid`** (default) | Hot-applies safe changes instantly. Automatically restarts for critical ones. | -| **`hot`** | Hot-applies safe changes only. Logs a warning when a restart is needed — you handle it. | +| **`hot`** | Hot-applies safe changes only. Logs a warning when a restart is needed - you handle it. | | **`restart`** | Restarts the Gateway on any config change, safe or not. | | **`off`** | Disables file watching. Changes take effect on the next manual restart. | @@ -568,7 +568,7 @@ Most fields hot-apply without downtime. In `hybrid` mode, restart-required chang | Category | Fields | Restart needed? | | ------------------- | ----------------------------------------------------------------- | --------------- | -| Channels | `channels.*`, `web` (WhatsApp) — all built-in and plugin channels | No | +| Channels | `channels.*`, `web` (WhatsApp) - all built-in and plugin channels | No | | Agent & models | `agent`, `agents`, `models`, `routing` | No | | Automation | `hooks`, `cron`, `agent.heartbeat` | No | | Sessions & messages | `session`, `messages` | No | @@ -578,7 +578,7 @@ Most fields hot-apply without downtime. In `hybrid` mode, restart-required chang | Infrastructure | `discovery`, `canvasHost`, `plugins` | **Yes** | -`gateway.reload` and `gateway.remote` are exceptions — changing them does **not** trigger a restart. +`gateway.reload` and `gateway.remote` are exceptions - changing them does **not** trigger a restart. ### Reload planning diff --git a/docs/gateway/pairing.md b/docs/gateway/pairing.md index 89bec89181d..f5218e803c2 100644 --- a/docs/gateway/pairing.md +++ b/docs/gateway/pairing.md @@ -27,8 +27,8 @@ Only clients that explicitly call `node.pair.*` use this flow. 1. A node connects to the Gateway WS and requests pairing. 2. The Gateway stores a **pending request** and emits `node.pair.requested`. 3. You approve or reject the request (CLI or UI). -4. On approval, the Gateway issues a **new token** (tokens are rotated on re‑pair). -5. The node reconnects using the token and is now “paired”. +4. On approval, the Gateway issues a **new token** (tokens are rotated on re-pair). +5. The node reconnects using the token and is now "paired". Pending requests expire automatically after **5 minutes**. @@ -49,17 +49,17 @@ openclaw nodes rename --node --name "Living Room iPad" Events: -- `node.pair.requested` — emitted when a new pending request is created. -- `node.pair.resolved` — emitted when a request is approved/rejected/expired. +- `node.pair.requested` - emitted when a new pending request is created. +- `node.pair.resolved` - emitted when a request is approved/rejected/expired. Methods: -- `node.pair.request` — create or reuse a pending request. -- `node.pair.list` — list pending + paired nodes (`operator.pairing`). -- `node.pair.approve` — approve a pending request (issues token). -- `node.pair.reject` — reject a pending request. -- `node.pair.remove` — remove a stale paired node entry. -- `node.pair.verify` — verify `{ nodeId, token }`. +- `node.pair.request` - create or reuse a pending request. +- `node.pair.list` - list pending + paired nodes (`operator.pairing`). +- `node.pair.approve` - approve a pending request (issues token). +- `node.pair.reject` - reject a pending request. +- `node.pair.remove` - remove a stale paired node entry. +- `node.pair.verify` - verify `{ nodeId, token }`. Notes: @@ -120,7 +120,7 @@ The macOS app can optionally attempt a **silent approval** when: - the request is marked `silent`, and - the app can verify an SSH connection to the gateway host using the same user. -If silent approval fails, it falls back to the normal “Approve/Reject” prompt. +If silent approval fails, it falls back to the normal "Approve/Reject" prompt. ## Trusted-CIDR device auto-approval @@ -159,7 +159,7 @@ to trusted non-browser local reconnects that already proved possession of local or shared credentials, including same-host native app reconnects after OS version metadata changes. Browser/Control UI clients and remote clients still use the explicit re-approval flow. Scope upgrades (read to write/admin) and -public key changes are **not** eligible for metadata-upgrade auto-approval — +public key changes are **not** eligible for metadata-upgrade auto-approval - they stay as explicit re-approval requests. ## QR pairing helpers @@ -199,7 +199,7 @@ Security notes: - The transport is **stateless**; it does not store membership. - If the Gateway is offline or pairing is disabled, nodes cannot pair. -- If the Gateway is in remote mode, pairing still happens against the remote Gateway’s store. +- If the Gateway is in remote mode, pairing still happens against the remote Gateway's store. ## Related diff --git a/docs/plugins/skill-workshop.md b/docs/plugins/skill-workshop.md index 5be1ac5a649..48e1ed54ec2 100644 --- a/docs/plugins/skill-workshop.md +++ b/docs/plugins/skill-workshop.md @@ -38,7 +38,7 @@ Skill Workshop is useful when the agent learns a procedure such as: It is not intended for: -- facts like “the user likes blue” +- facts like "the user likes blue" - broad autobiographical memory - raw transcript archiving - secrets, credentials, or hidden prompt text @@ -217,7 +217,7 @@ The reviewer has no tools: - `toolsAllow: []` - `disableMessageTool: true` -The reviewer returns either `{ "action": "none" }` or one proposal. The `action` field is `create`, `append`, or `replace` — prefer `append`/`replace` when a relevant skill already exists; use `create` only when no existing skill fits. +The reviewer returns either `{ "action": "none" }` or one proposal. The `action` field is `create`, `append`, or `replace` - prefer `append`/`replace` when a relevant skill already exists; use `create` only when no existing skill fits. Example `create`: @@ -579,12 +579,12 @@ warning/debug message and skips that review pass. Use Skill Workshop when the user says: -- “next time, do X” -- “from now on, prefer Y” -- “make sure to verify Z” -- “save this as a workflow” -- “this took a while; remember the process” -- “update the local skill for this” +- "next time, do X" +- "from now on, prefer Y" +- "make sure to verify Z" +- "save this as a workflow" +- "this took a while; remember the process" +- "update the local skill for this" Good skill text: