Compare commits

..

331 Commits

Author SHA1 Message Date
Jake
e78ae48e69 fix(memory): add input_type to Voyage AI embeddings for improved retrieval (#10818)
* fix(memory): add input_type to Voyage AI embeddings for improved retrieval

Voyage AI recommends passing input_type='document' when indexing and
input_type='query' when searching. This improves retrieval quality by
optimising the embedding space for each direction.

Changes:
- embedQuery now passes input_type: 'query'
- embedBatch now passes input_type: 'document'
- Batch API request_params includes input_type: 'document'
- Tests updated to verify input_type is passed correctly

* Changelog: note Voyage embeddings input_type fix (#10818) (thanks @mcinteerj)

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-06 21:55:09 -06:00
Markus Buhatem Koch
4c1da23a71 Revert previous change from 'Clawdbot' to 'OpenClaw' in lore (#9119) 2026-02-06 21:53:02 -05:00
Val Alexander
3d2fe9284e Fix repository links in formal-verification.md (#10200)
Updated repository links for formal verification models.
2026-02-06 21:47:55 -05:00
Peter Steinberger
a3b5f1b15c fix(build): unblock pnpm build dts 2026-02-06 18:43:11 -08:00
DEOKLYONG MOON
d1dc60774b Docs: fix broken /plugins links (#9308)
* Docs: fix broken /plugins links to /plugin

The documentation linked to /plugins which doesn't exist.
The correct path is /plugin (singular) which contains the
plugins overview documentation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: drop manual zh-CN doc edits from plugins link fix

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-06 21:08:26 -05:00
Tyler Yust
d90cac990c fix: cron scheduler reliability, store hardening, and UX improvements (#10776)
* refactor: update cron job wake mode and run mode handling

- Changed default wake mode from 'next-heartbeat' to 'now' in CronJobEditor and related CLI commands.
- Updated cron-tool tests to reflect changes in run mode, introducing 'due' and 'force' options.
- Enhanced cron-tool logic to handle new run modes and ensure compatibility with existing job structures.
- Added new tests for delivery plan consistency and job execution behavior under various conditions.
- Improved normalization functions to handle wake mode and session target casing.

This refactor aims to streamline cron job configurations and enhance the overall user experience with clearer defaults and improved functionality.

* test: enhance cron job functionality and UI

- Added tests to ensure the isolated agent correctly announces the final payload text when delivering messages via Telegram.
- Implemented a new function to pick the last deliverable payload from a list of delivery payloads.
- Enhanced the cron service to maintain legacy "every" jobs while minute cron jobs recompute schedules.
- Updated the cron store migration tests to verify the addition of anchorMs to legacy every schedules.
- Improved the UI for displaying cron job details, including job state and delivery information, with new styles and layout adjustments.

These changes aim to improve the reliability and user experience of the cron job system.

* test: enhance sessions thinking level handling

- Added tests to verify that the correct thinking levels are applied during session spawning.
- Updated the sessions-spawn-tool to include a new parameter for overriding thinking levels.
- Enhanced the UI to support additional thinking levels, including "xhigh" and "full", and improved the handling of current options in dropdowns.

These changes aim to improve the flexibility and accuracy of thinking level configurations in session management.

* feat: enhance session management and cron job functionality

- Introduced passthrough arguments in the test-parallel script to allow for flexible command-line options.
- Updated session handling to hide cron run alias session keys from the sessions list, improving clarity.
- Enhanced the cron service to accurately record job start times and durations, ensuring better tracking of job execution.
- Added tests to verify the correct behavior of the cron service under various conditions, including zero-delay timers.

These changes aim to improve the usability and reliability of session and cron job management.

* feat: implement job running state checks in cron service

- Added functionality to prevent manual job runs if a job is already in progress, enhancing job management.
- Updated the `isJobDue` function to include checks for running jobs, ensuring accurate scheduling.
- Enhanced the `run` function to return a specific reason when a job is already running.
- Introduced a new test case to verify the behavior of forced manual runs during active job execution.

These changes aim to improve the reliability and clarity of cron job execution and management.

* feat: add session ID and key to CronRunLogEntry model

- Introduced `sessionid` and `sessionkey` properties to the `CronRunLogEntry` struct for enhanced tracking of session-related information.
- Updated the initializer and Codable conformance to accommodate the new properties, ensuring proper serialization and deserialization.

These changes aim to improve the granularity of logging and session management within the cron job system.

* fix: improve session display name resolution

- Updated the `resolveSessionDisplayName` function to ensure that both label and displayName are trimmed and default to an empty string if not present.
- Enhanced the logic to prevent returning the key if it matches the label or displayName, improving clarity in session naming.

These changes aim to enhance the accuracy and usability of session display names in the UI.

* perf: skip cron store persist when idle timer tick produces no changes

recomputeNextRuns now returns a boolean indicating whether any job
state was mutated. The idle path in onTimer only persists when the
return value is true, eliminating unnecessary file writes every 60s
for far-future or idle schedules.

* fix: prep for merge - explicit delivery mode migration, docs + changelog (#10776) (thanks @tyler6204)
2026-02-06 18:03:03 -08:00
Peter Steinberger
0dd7033521 chore(lockfile): fix pnpm-lock 2026-02-06 17:56:22 -08:00
Raymond Berger
c80a09fc2f Fix QMD CLI installation link in memory.md (#8647)
Correct the installation link for the QMD CLI in the documentation.
2026-02-06 20:53:47 -05:00
Peter Steinberger
f831c48e56 docs(changelog): highlight Opus 4.6 + Codex 5.3 first 2026-02-06 17:28:46 -08:00
Peter Steinberger
c237a82b42 docs(changelog): curate 2026.2.6 2026-02-06 16:56:29 -08:00
Peter Steinberger
94b2fc14f2 chore(deps): bump carbon beta 2026-02-06 16:56:25 -08:00
Peter Steinberger
0daf416908 fix(agents): add Opus 4.6 forward-compat fallback 2026-02-06 16:56:21 -08:00
Peter Steinberger
dca8cf958b chore(deps): update deps 2026-02-06 16:37:56 -08:00
Seb Slight
93bf75279f docs(imessage): improve macOS TCC troubleshooting guidance (#10781) 2026-02-06 19:21:52 -05:00
gitpds
fe308a3aa1 docs(imessage): add macOS TCC troubleshooting 2026-02-06 19:10:01 -05:00
Peter Steinberger
7be921c434 docs(changelog): refresh 2026.2.6 since v2026.2.3 2026-02-06 15:47:10 -08:00
Peter Steinberger
5163833be5 docs: fix markdownlint fragments + headings 2026-02-06 15:45:39 -08:00
Peter Steinberger
d898ad6807 fix(telegram): cast fetch for grammY ApiClientOptions 2026-02-06 15:45:34 -08:00
Peter Steinberger
677450cd9b chore(release): bump version to 2026.2.6 2026-02-06 15:37:31 -08:00
Peter Steinberger
ac5944cde7 docs(changelog): include merged PRs since v2026.2.3 2026-02-06 15:36:13 -08:00
Peter Steinberger
3b768a2851 docs(changelog): prepare 2026.2.6 2026-02-06 15:30:17 -08:00
Shadril Hassan Shifat
2c8af78d20 fix(hooks): replace debug console.log with proper subsystem logging in session-memory (#10730)
* fix: replace debug console.log with proper subsystem logging in session-memory

* fix(hooks): normalize session-memory subsystem logging

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-06 17:22:38 -06:00
calvin-hpnet
48b0fd8d88 feat(antigravity): update default model to Claude Opus 4.6 (#10720)
* feat(antigravity): update default model to Claude Opus 4.6

Claude Opus 4.5 has been replaced by Claude Opus 4.6 on the
Antigravity (Google Cloud Code Assist) platform.

- Update DEFAULT_MODEL in google-antigravity-auth extension
- Update testing docs to reference the new model

* fix: update remaining antigravity opus 4.5 refs in zh-CN docs and tests

Address review comments from Greptile:
- Update zh-CN/testing.md antigravity model references
- Update pi-tools-agent-config.test.ts model IDs

* Antigravity: default OAuth model to Opus 4.6 (#10720) (thanks @calvin-hpnet)

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-06 16:42:57 -06:00
Tak Hoffman
40425db0f1 feat(memory): document Voyage embeddings + VOYAGE_API_KEY (#7078) (thanks @mcinteerj) (#10699) 2026-02-06 15:51:47 -06:00
Jake
6965a2cc9d feat(memory): native Voyage AI support (#7078)
* feat(memory): add native Voyage AI embedding support with batching

Cherry-picked from PR #2519, resolved conflict in memory-search.ts
(hasRemote -> hasRemoteConfig rename + added voyage provider)

* fix(memory): optimize voyage batch memory usage with streaming and deduplicate code

Cherry-picked from PR #2519. Fixed lint error: changed this.runWithConcurrency
to use imported runWithConcurrency function after extraction to internal.ts
2026-02-06 15:09:32 -06:00
Tak Hoffman
e3d3893d5d Docs: revise PR and issue submission guides (#10617)
* Docs: revise PR submission guide

* Docs: revise issue submission guide
2026-02-06 13:29:11 -06:00
Yida-Dev
4216449405 fix: guard resolveUserPath against undefined input (#10176)
* fix: guard resolveUserPath against undefined input

When subagent spawner omits workspaceDir, resolveUserPath receives
undefined and crashes on .trim().  Add a falsy guard that falls back
to process.cwd(), matching the behavior callers already expect.

Closes #10089

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden runner workspace fallback (#10176) (thanks @Yida-Dev)

* fix: harden workspace fallback scoping (#10176) (thanks @Yida-Dev)

* refactor: centralize workspace fallback classification and redaction (#10176) (thanks @Yida-Dev)

* test: remove explicit any from utils mock (#10176) (thanks @Yida-Dev)

* security: reject malformed agent session keys for workspace resolution (#10176) (thanks @Yida-Dev)

---------

Co-authored-by: Yida-Dev <reyifeijun@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-06 13:16:58 -05:00
Tak Hoffman
5842bcaaf7 Docs: add PR sign-off template (#10561) 2026-02-06 11:58:39 -06:00
Seb Slight
991cf4d7fe Docs: revamp installer internals for readability and accuracy (#10499)
* docs(install): revamp installer internals for readability and accuracy

Restructure the installer internals page with better flow and Mintlify
components (CardGroup, Steps, Tabs, AccordionGroup). All flags, env vars,
and behavioral descriptions cross-checked against install.sh,
install-cli.sh, and install.ps1 source code.

- Add CardGroup chooser and Quick Commands section at top
- Organize each script into consistent Flow → Examples → Reference pattern
- Move flags/env var tables into collapsible Accordions
- Consolidate troubleshooting into AccordionGroup at bottom
- Add missing flags (--version, --beta, --verbose, --help, etc.)
- Add missing env vars (OPENCLAW_VERSION, OPENCLAW_BETA, etc.)
- Document install-cli.sh fully (was one paragraph)
- Fix non-interactive checkout detection behavior (defaults to npm)
- Use --proto/--tlsv1.2 in curl examples to match script usage
- No content deleted; all original info preserved or relocated

* fix(docs): correct in-page anchor hrefs for installer cards

* docs(install): replace CardGroup with table for installer overview
2026-02-06 10:49:38 -05:00
Seb Slight
578a6e27aa Docs: enable markdownlint autofixables except list numbering (#10476)
* docs(markdownlint): enable autofixable rules except list numbering

* docs(zalo): fix malformed bot platform link
2026-02-06 10:08:59 -05:00
Sebastian
0a1f4f666a revert(docs): undo markdownlint autofix churn 2026-02-06 10:00:08 -05:00
Sebastian
c7aec0660e docs(markdownlint): enable autofixable rules and normalize links 2026-02-06 09:55:12 -05:00
Sebastian
1bf9f237f7 docs: linting 2026-02-06 09:35:57 -05:00
Sebastian
134c03a903 feat: add markdownlint configuration for documentation formatting and linting 2026-02-06 09:14:36 -05:00
Seb Slight
18b480dd3e Docs: sharpen Install tab to stop duplicating Getting Started (#10416)
* docs(install): reframe install overview to stop duplicating getting started

* docs(install): link default installer row to getting started, not internals

* docs(install): use Mintlify components for install overview

* docs(install): fix card grid layout with CardGroup

* docs(install): platform tabs for global install, npm/pnpm as accordion

* docs(install): add PowerShell no-onboard alternative

* docs(install): add repo link to from-source clone step

* docs(install): capitalize OpenClaw in repo link

* docs(install): add pnpm link --global to from-source steps

* docs(install): rewrite install overview for clarity and flow

* docs(install): use tooltip for Windows WSL2 recommendation

* docs(install): use Note box for Windows WSL2 recommendation

* docs(install): group install methods under single heading

* docs(install): standardize tab labels across installer sections

* docs(install): rewrite Node.js page with install instructions and better structure

* docs(install): clarify Node.js page intro

* docs(install): scope auto-install note to installer script, link Node page

* docs(install): fix installer script link to internals page

* docs: rename Install methods nav group to Other install methods

* docs(install): link to on-page anchor, use Tip box for recommended

* docs(install): wrap install methods in AccordionGroup with Tip box

* docs: move Node.js page from Install to Help > Environment and debugging

* docs(install): add complete flags and env vars reference to installer internals

* docs(install): use stable troubleshooting anchor for Node.js link

* docs(install): fix Node page installer anchor

* docs(install): fix broken installer script anchor in requirements note
2026-02-06 08:55:05 -05:00
Gustavo Madeira Santana
c75275f109 Update: harden control UI asset handling in update flow (#10146)
* Update: harden control UI asset handling in update flow

* fix: harden update doctor entrypoint guard (#10146) (thanks @gumadeiras)
2026-02-06 01:14:00 -05:00
Tak Hoffman
50e687d17d Docs: add PR and issue submission guides (#10150)
* Docs: add PR and issue submission guides

* Docs: fix LLM-assisted wording
2026-02-05 23:59:47 -06:00
Gustavo Madeira Santana
4a59b7786b fix: CLI harden update restart imports and fix nested bundle version resolution 2026-02-06 00:09:48 -05:00
Tak Hoffman
8a352c8f9d Web UI: add token usage dashboard (#10072)
* feat(ui): Token Usage dashboard with session analytics

Adds a comprehensive Token Usage view to the dashboard:

Backend:
- Extended session-cost-usage.ts with per-session daily breakdown
- Added date range filtering (startMs/endMs) to API endpoints
- New sessions.usage, sessions.usage.timeseries, sessions.usage.logs endpoints
- Cost breakdown by token type (input/output/cache read/write)

Frontend:
- Two-column layout: Daily chart + breakdown | Sessions list
- Interactive daily bar chart with click-to-filter and shift-click range select
- Session detail panel with usage timeline, conversation logs, context weight
- Filter chips for active day/session selections
- Toggle between tokens/cost view modes (default: cost)
- Responsive design for smaller screens

UX improvements:
- 21-day default date range
- Debounced date input (400ms)
- Session list shows filtered totals when days selected
- Context weight breakdown shows skills, tools, files contribution

* fix(ui): restore gatewayUrl validation and syncUrlWithSessionKey signature

- Restore normalizeGatewayUrl() to validate ws:/wss: protocol
- Restore isTopLevelWindow() guard for iframe security
- Revert syncUrlWithSessionKey signature (host param was unused)

* feat(ui): Token Usage dashboard with session analytics

Adds a comprehensive Token Usage view to the dashboard:

Backend:
- Extended session-cost-usage.ts with per-session daily breakdown
- Added date range filtering (startMs/endMs) to API endpoints
- New sessions.usage, sessions.usage.timeseries, sessions.usage.logs endpoints
- Cost breakdown by token type (input/output/cache read/write)

Frontend:
- Two-column layout: Daily chart + breakdown | Sessions list
- Interactive daily bar chart with click-to-filter and shift-click range select
- Session detail panel with usage timeline, conversation logs, context weight
- Filter chips for active day/session selections
- Toggle between tokens/cost view modes (default: cost)
- Responsive design for smaller screens

UX improvements:
- 21-day default date range
- Debounced date input (400ms)
- Session list shows filtered totals when days selected
- Context weight breakdown shows skills, tools, files contribution

* fix: usage dashboard data + cost handling (#8462) (thanks @mcinteerj)

* Usage: enrich metrics dashboard

* Usage: add latency + model trends

* Gateway: improve usage log parsing

* UI: add usage query helpers

* UI: client-side usage filter + debounce

* Build: harden write-cli-compat timing

* UI: add conversation log filters

* UI: fix usage dashboard lint + state

* Web UI: default usage dates to local day

* Protocol: sync session usage params (#8462) (thanks @mcinteerj, @TakHoffman)

---------

Co-authored-by: Jake McInteer <mcinteerj@gmail.com>
2026-02-05 22:35:46 -06:00
Gustavo Madeira Santana
b40da2cb7a fix: remove dead restore control-ui step from update runner 2026-02-05 22:10:55 -05:00
Gustavo Madeira Santana
72245855e5 fix: add fallback for Control UI asset resolution in global installs 2026-02-05 22:03:43 -05:00
Gustavo Madeira Santana
7b2a221212 chore: run lint step after build during preflight check 2026-02-05 21:22:27 -05:00
Sebastian
ac0c2f260f docs: update clawtributors (add @unisone) 2026-02-05 21:19:42 -05:00
Alex Zaytsev
d2aee7da68 docs: add activeHours to heartbeat field notes and examples (#9366)
Co-authored-by: unisone <unisone@users.noreply.github.com>
2026-02-05 21:18:57 -05:00
Coy Geek
717129f7f9 fix: silence unused hook token url param (#9436)
* fix: Gateway authentication token exposed in URL query parameters

* fix: silence unused hook token url param

* fix: remove gateway auth tokens from URLs (#9436) (thanks @coygeek)

* test: fix Windows path separators in audit test (#9436)

---------

Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 18:08:29 -08:00
Matt Ezell
b1430aaaca Chore: Update memory.md with current default workspace path (#9559)
Removed 'clawd' workspace reference - updated with current default workspace path of '~/.openclaw/workspace'
2026-02-05 21:06:14 -05:00
Shailesh
bccdc95a9b Cap sessions_history payloads to prevent context overflow (#10000)
* Cap sessions_history payloads to prevent context overflow

* fix: harden sessions_history payload caps

* fix: cap sessions_history payloads to prevent context overflow (#10000) (thanks @gut-puncture)

---------

Co-authored-by: Shailesh Rana <shaileshrana@ShaileshMM.local>
Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 17:50:57 -08:00
cpojer
328b69be17 chore: Fix audit test on Windows. 2026-02-06 10:22:48 +09:00
cpojer
f16e32b73d fix: Do not process.exit(0) in the middle of a test. 2026-02-06 09:57:51 +09:00
cpojer
8abce8a84d fix: onToolResult fallback is not expected. 2026-02-06 09:55:56 +09:00
therealZpoint-bot
c448e5da6f fix(docs): correct OpenCode Zen description in code comment (#9998)
* fix(docs): correct OpenCode Zen description in code comment

OpenCode Zen is a pay-as-you-go token-based API, not a $200/month
subscription. The subscription tiers ($20/$100/$200) are OpenCode Black,
a separate product.

This fixes the misleading comment that conflated Zen with Black.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: align OpenCode Zen billing copy (#9998) (thanks @therealZpoint-bot)

---------

Co-authored-by: Claude <claude@archibald.local>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-05 19:55:02 -05:00
cpojer
6c42d34610 chore: Add VS Code defaults and extensions so that Oxlint/Oxfmt work automatically. 2026-02-06 09:49:47 +09:00
cpojer
ee1ec3faba Add proper onToolResult fallback. 2026-02-06 09:42:10 +09:00
George Pickett
a459e237e8 fix(gateway): require auth for canvas host and a2ui assets (#9518) (thanks @coygeek) 2026-02-05 16:37:58 -08:00
Coy Geek
47538bca4d fix: Gateway canvas host bypasses auth and serves files unauthenticated 2026-02-05 16:37:58 -08:00
adam91holt
05b28c147d fix: wire onToolResult callback for verbose tool summaries (#2022)
HOTFIX: Tool summaries were not being sent to chat channels when verbose mode
was enabled. The onToolResult callback was defined in the types but never
wired up in dispatch-from-config.ts.

This adds the missing callback alongside onBlockReply, using the same
dispatcher.sendBlockReply() path to deliver tool summaries to WhatsApp,
Telegram, and other chat channels.

Fixes verbose tool summaries not appearing in WhatsApp despite /verbose on.
2026-02-05 16:37:30 -08:00
Gustavo Madeira Santana
0a48592475 add PR review workflow templates 2026-02-05 19:36:34 -05:00
zerone0x
3ad7958365 fix: untrack dist/control-ui build artifacts (#1856)
The dist/control-ui/ files were committed before the dist/ gitignore
rule was effective. These build artifacts get regenerated during
builds, causing dirty repo errors that block the auto-update mechanism.

Removes the files from git tracking while keeping them locally and
respecting the existing dist/ gitignore entry.

Fixes #1838

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-05 16:35:56 -08:00
Raphael Borg Ellul Vincenti
34a58b839c fix(ollama): add streaming config and fix OLLAMA_API_KEY env var support (#9870)
* fix(ollama): add streaming config and fix OLLAMA_API_KEY env var support

Adds configurable streaming parameter to model configuration and sets streaming
to false by default for Ollama models. This addresses the corrupted response
issue caused by upstream SDK bug badlogic/pi-mono#1205 where interleaved
content/reasoning deltas in streaming responses cause garbled output.

Changes:
- Add streaming param to AgentModelEntryConfig type
- Set streaming: false default for Ollama models
- Add OLLAMA_API_KEY to envMap (was missing, preventing env var auth)
- Document streaming configuration in Ollama provider docs
- Add tests for Ollama model configuration

Users can now configure streaming per-model and Ollama authentication
via OLLAMA_API_KEY environment variable works correctly.

Fixes #8839
Related: badlogic/pi-mono#1205

* docs(ollama): use gpt-oss:20b as primary example

Updates documentation to use gpt-oss:20b as the primary example model
since it supports tool calling. The model examples now show:

- gpt-oss:20b as the primary recommended model (tool-capable)
- llama3.3 and qwen2.5-coder:32b as additional options

This provides users with a clear, working example that supports
OpenClaw's tool calling features.

* chore: remove unused vi import from ollama test
2026-02-05 16:35:38 -08:00
Sash Zats
ec0728b357 fix: release session locks on process termination (#1962)
Adds cleanup handlers to release held file locks when the process
terminates via SIGTERM, SIGINT, or normal exit. This prevents orphaned
lock files that would block future sessions.

Fixes #1951
2026-02-05 16:35:34 -08:00
Abdel Sy Fane
0c7fa2b0d5 security: redact credentials from config.get gateway responses (#9858)
* security: add skill/plugin code safety scanner module

* security: integrate skill scanner into security audit

* security: add pre-install code safety scan for plugins

* style: fix curly brace lint errors in skill-scanner.ts

* docs: add changelog entry for skill code safety scanner

* security: redact credentials from config.get gateway responses

The config.get gateway method returned the full config snapshot
including channel credentials (Discord tokens, Slack botToken/appToken,
Telegram botToken, Feishu appSecret, etc.), model provider API keys,
and gateway auth tokens in plaintext.

Any WebSocket client—including the unauthenticated Control UI when
dangerouslyDisableDeviceAuth is set—could read every secret.

This adds redactConfigSnapshot() which:
- Deep-walks the config object and masks any field whose key matches
  token, password, secret, or apiKey patterns
- Uses the existing redactSensitiveText() to scrub the raw JSON5 source
- Preserves the hash for change detection
- Includes 15 test cases covering all channel types

* security: make gateway config writes return redacted values

* test: disable control UI by default in gateway server tests

* fix: redact credentials in gateway config APIs (#9858) (thanks @abdelsfane)

---------

Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 16:34:48 -08:00
Yifeng Wang
5f6e1c19bd feat(feishu): sync with clawdbot-feishu #137 (multi-account support)
- Sync latest changes from clawdbot-feishu including multi-account support
- Add eslint-disable comments for SDK-related any types
- Remove unused imports
- Fix no-floating-promises in monitor.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:32:10 +09:00
Yifeng Wang
7e005acd3c chore: update pnpm-lock.yaml for feishu extension deps
Add lockfile entries for:
- @larksuiteoapi/node-sdk@^1.56.1
- @sinclair/typebox@0.34.47
- zod@^4.3.6

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:32:10 +09:00
Yifeng Wang
8ba1387ba2 fix(feishu): fix webhook mode silent exit and receive_id_type default
- monitor.ts: throw error for webhook mode instead of silently returning,
  so gateway properly marks channel as failed
- targets.ts: default receive_id_type to "user_id" instead of "open_id"
  for non-prefixed IDs, fixing message delivery for enterprise user IDs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:32:10 +09:00
Yifeng Wang
7e32f1ce20 fix(feishu): add targeted eslint-disable comments for SDK integration
Add line-specific eslint-disable-next-line comments for SDK type casts
and union type issues, rather than file-level disables.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:32:10 +09:00
Yifeng Wang
2267d58afc feat(feishu): replace built-in SDK with community plugin
Replace the built-in Feishu SDK with the community-maintained
clawdbot-feishu plugin by @m1heng.

Changes:
- Remove src/feishu/ directory (19 files)
- Remove src/channels/plugins/outbound/feishu.ts
- Remove src/channels/plugins/normalize/feishu.ts
- Remove src/config/types.feishu.ts
- Remove feishu exports from plugin-sdk/index.ts
- Remove FeishuConfig from types.channels.ts

New features in community plugin:
- Document tools (read/create/edit Feishu docs)
- Wiki tools (navigate/manage knowledge base)
- Drive tools (folder/file management)
- Bitable tools (read/write table records)
- Permission tools (collaborator management)
- Emoji reactions support
- Typing indicators
- Rich media support (bidirectional image/file transfer)
- @mention handling
- Skills for feishu-doc, feishu-wiki, feishu-drive, feishu-perm

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:32:10 +09:00
ironbyte-rgb
02842bef91 fix(slack): add mention stripPatterns for /new and /reset commands (#9971)
* fix(slack): add mention stripPatterns for /new and /reset commands

Fixes #9937

The Slack dock was missing mentions.stripPatterns that Discord has.
This caused /new and /reset to fail when sent with a mention
(e.g. @bot /reset) because <@USERID> wasn't stripped before matching.

* fix(slack): strip mentions for /new and /reset (#9971) (thanks @ironbyte-rgb)

---------

Co-authored-by: ironbyte-rgb <amontaboi76@gmail.com>
Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 16:29:07 -08:00
wangai-studio
57326f72e6 fix(nextcloud-talk): sign message text instead of JSON body (#2092)
Nextcloud Talk's ChecksumVerificationService verifies HMAC against the
extracted message/reaction text, not the full JSON body. This fixes 401
authentication errors when sending messages via the bot API.

- sendMessageNextcloudTalk: sign 'message' text only
- sendReactionNextcloudTalk: sign 'reaction' string only
2026-02-05 16:25:21 -08:00
Tyler Yust
370bbcd89b Model: add strict gpt-5.3-codex fallback for OpenAI Codex (fixes #9989) (#9995)
* Model: allow forward-compatible OpenAI Codex GPT-5 IDs

* Model: scope Codex fallback to gpt-5.3-codex

* fix: reorder codex fallback before providerCfg, add ordering test, changelog (#9989) (thanks @w1kke)

---------

Co-authored-by: Robin <4robinlehmann@gmail.com>
2026-02-05 16:23:18 -08:00
cpojer
6f4665dda3 chore: Update deps. 2026-02-06 09:11:46 +09:00
大猫子
2d15dd757d fix(cron): handle undefined sessionTarget in list output (#9649) (#9752)
* fix(cron): handle undefined sessionTarget in list output (#9649)

When sessionTarget is undefined, pad() would crash with 'Cannot read
properties of undefined (reading trim)'. Use '-' as fallback value.

* test(cron): add regression test for undefined sessionTarget (#9649)

Verifies that printCronList handles jobs with undefined sessionTarget
without crashing. Test fails on main branch, passes with the fix.

* fix: use correct CronSchedule format in tests (#9752) (thanks @lailoo)

Tests were using { kind: 'at', atMs: number } but the CronSchedule type
requires { kind: 'at', at: string } where 'at' is an ISO date string.

---------

Co-authored-by: damaozi <1811866786@qq.com>
Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-02-05 16:11:19 -08:00
Aisling Cahill
861725fba1 fix(agents): skip tool extraction for aborted/errored assistant messages (#4598)
Fixes tool call/tool_result pairing issues that cause permanent session corruption when assistant messages have stopReason "error" or "aborted". Includes 4 unit tests.
2026-02-05 16:08:46 -08:00
Darshil
de7b2ba7d5 fix: normalize xhigh aliases and docs sync (#9976) 2026-02-05 16:07:51 -08:00
slonce70
7db839544d Changelog: note #9976 thinking alias + Codex 5.3 docs sync 2026-02-05 16:07:51 -08:00
slonce70
5958e5693c Thinking: accept extra-high alias and sync Codex FAQ wording 2026-02-05 16:07:51 -08:00
Abdel Sy Fane
bc88e58fcf security: add skill/plugin code safety scanner (#9806)
* security: add skill/plugin code safety scanner module

* security: integrate skill scanner into security audit

* security: add pre-install code safety scan for plugins

* style: fix curly brace lint errors in skill-scanner.ts

* docs: add changelog entry for skill code safety scanner

* style: append ellipsis to truncated evidence strings

* fix(security): harden plugin code safety scanning

* fix: scan skills on install and report code-safety details

* fix: dedupe audit-extra import

* fix(security): make code safety scan failures observable

* fix(test): stabilize smoke + gateway timeouts (#9806) (thanks @abdelsfane)

---------

Co-authored-by: Darshil <ddhameliya@mail.sfsu.edu>
Co-authored-by: Darshil <81693876+dvrshil@users.noreply.github.com>
Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 16:06:11 -08:00
George Pickett
141f551a4c fix(exec-approvals): coerce bare string allowlist entries (#9903) (thanks @mcaxtr) 2026-02-05 15:52:51 -08:00
Marcus Castro
6ff209e932 fix(exec-approvals): coerce bare string allowlist entries to objects (#9790) 2026-02-05 15:52:51 -08:00
fujiwara-tofu-shop
b0befb5f5d fix(cron): handle legacy atMs field in schedule when computing next run (#9932)
* fix(cron): handle legacy atMs field in schedule when computing next run

The cron scheduler only checked for `schedule.at` (string) but legacy jobs
may have `schedule.atMs` (number) from before the schema migration.

This caused nextRunAtMs to stay null because:
1. Store migration runs on load but may not persist immediately
2. Race conditions or file mtime issues can skip migration
3. computeJobNextRunAtMs/computeNextRunAtMs only checked `at`, not `atMs`

Fix: Make both functions defensive by checking `atMs` first (number),
then `atMs` (string, for edge cases), then falling back to `at` (string).

This ensures jobs fire correctly even if:
- Migration hasn't run yet
- Old data was written by a previous version
- The store was manually edited

Fixes #9930

* fix: validate numeric atMs to prevent NaN/Infinity propagation

Addresses review feedback - numeric atMs values are now validated with
Number.isFinite() && atMs > 0 before use. This prevents corrupted or
manually edited stores from causing hot timer loops via setTimeout(..., NaN).
2026-02-05 15:49:03 -08:00
Maksym Brashchenko
40e23b05f7 fix(cron): re-arm timer in finally to survive transient errors (#9948) 2026-02-05 15:46:59 -08:00
Igor Markelov
313e2f2e85 fix(cron): prevent recomputeNextRuns from skipping due jobs in onTimer (#9823)
* fix(cron): prevent recomputeNextRuns from skipping due jobs in onTimer

ensureLoaded(forceReload) called recomputeNextRuns before runDueJobs,
which recalculated nextRunAtMs to a strictly future time. Since
setTimeout always fires a few ms late, the due check (now >= nextRunAtMs)
always failed and every/cron jobs never executed. Fixes #9788.

* docs: add changelog entry for cron timer race fix (#9823) (thanks @pycckuu)

---------

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-02-05 15:43:37 -08:00
George Pickett
68393bfa36 chore: changelog for xAI onboarding (#9885) (thanks @grp06) 2026-02-05 15:14:50 -08:00
George Pickett
155dfa93e5 fix(onboard): align xAI default model to grok-4 2026-02-05 15:14:50 -08:00
George Pickett
db31c0ccca feat: add xAI Grok provider support 2026-02-05 15:14:50 -08:00
Daijiro Miyazawa
cefd87f355 Fix: Enable scrolling on the dashboard config page (#1822)
* Fix: Enable scrolling in dashboard

* Fix: Enable scrolling in dashboard

* Fix: Enable scrolling in dashboard
2026-02-05 15:10:11 -08:00
Gustavo Madeira Santana
8577d015b2 chore: remove tracked .DS_Store files 2026-02-05 18:01:29 -05:00
nicolasstanley
4a5e9f0a4f fix(telegram): accept messages from group members in allowlisted groups (#9775)
* fix(telegram): accept messages from group members in allowlisted groups

Issue #4559: Telegram bot was silently dropping messages from non-paired users
in allowlisted group chats due to overly strict sender filtering.

The fix adds a check to distinguish between:
1. Group itself is allowlisted → accept messages from any member
2. Group is NOT allowlisted → only accept from allowlisted senders

Changes:
- Check if group ID is in the allowlist (or allowlist is wildcard)
- Only reject sender if they're not in allowlist AND group is not allowlisted
- Improved logging to indicate the actual reason for rejection

This preserves security controls while fixing the UX issue where group members
couldn't participate unless individually allowlisted.

Backwards compatible: existing allowlists continue to work as before.

* style: format telegram fix for oxfmt compliance

* refactor(telegram): clarify group allowlist semantics in fix for #4559

Changes:
- Rename 'isGroupInAllowlist' to 'isGroupChatIdInAllowlist' for clarity
- Expand comments to explain the semantic distinction:
  * Group chat ID in allowlist -> accept any group member (fixes #4559)
  * Group chat ID NOT in allowlist -> enforce sender allowlist (preserves security)
- This addresses concerns about config semantics raised in code review

The fix maintains backward compatibility:
- 'groupAllowFrom' with group chat IDs now correctly acts as group enablement
- 'groupAllowFrom' with sender IDs continues to work as sender allowlist
- Operators should use group chat IDs for group enablement, sender IDs for sender control

Note: If operators were using 'groupAllowFrom' with group IDs expecting sender-level
filtering, they should migrate to a separate sender allowlist config. This is the
intended behavior per issue #4559.

* Telegram: allow per-group groupPolicy overrides

* Telegram: support per-group groupPolicy overrides (#9775) (thanks @nicolasstanley)

---------

Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 14:45:45 -08:00
Seb Slight
c18452598a docs: restructure Get Started tab and improve onboarding flow (#9950)
* docs: restructure Get Started tab and improve onboarding flow

- Flatten nested Onboarding group into linear First Steps flow
- Add 'What is OpenClaw?' narrative section to landing page
- Split wizard.md into streamlined overview + full reference (reference/wizard.md)
- Move Pairing to Channels > Configuration
- Move Bootstrapping to Agents > Fundamentals
- Move macOS app onboarding to Platforms > macOS companion app
- Move Lore to Help > Community
- Remove duplicate install instructions from openclaw.md
- Mirror navigation changes in zh-CN tabs
- No content deleted — all detail preserved or relocated

* docs: move deployment pages to install/, fix Platforms tab routing, clarify onboarding paths

- Move deployment guides (fly, hetzner, gcp, macos-vm, exe-dev, railway, render,
  northflank) from platforms/ and root to install/
- Add 'Hosting and deployment' group to Install tab
- Slim Gateway & Ops 'Remote access and deployment' down to 'Remote access'
- Swap Platforms tab before Gateway & Ops to fix path-prefix routing
- Move macOS app onboarding into First steps (parallel to CLI wizard)
- Rename sidebar titles to 'Onboarding: CLI' / 'Onboarding: macOS App'
- Add redirects for all moved paths
- Update all internal links (en + zh-CN)
- Fix img tag syntax in onboarding.md
2026-02-05 17:45:01 -05:00
Gustavo Madeira Santana
3299aeb904 Agents: bump pi-mono to 0.52.5 (#9949)
* Agents: bump pi-mono to 0.52.5

* Changelog: add PR reference for pi bump
2026-02-05 17:36:25 -05:00
George Pickett
8fdc0a2841 docs: note secure DM guidance update (#9377) (thanks @Shrinija17) 2026-02-05 14:27:56 -08:00
George Pickett
873182ec2d docs: tighten secure DM example 2026-02-05 14:27:56 -08:00
Shrinija Kummari
b8004a28cc docs: improve DM security guidance with concrete example
Add a more prominent security warning for multi-user DM setups:
- Add blockquote security warning about context leakage
- Include concrete example showing the privacy risk
- Add "When to enable this" checklist
- Clarify that default is fine for single-user setups

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:27:56 -08:00
Gustavo Madeira Santana
6b7d3c3062 Revert "feat(skills): add QR code skill (#8817)"
This reverts commit ad13c265ba.
2026-02-05 17:20:27 -05:00
Glucksberg
d4c560853c fix(errors): show clear billing error instead of cryptic API response (#8391)
* fix(errors): return clear billing error message instead of cryptic raw error (#8136)

When an LLM API provider returns a credit/billing-related error (HTTP 402,
insufficient credits, low balance, etc.), OpenClaw now shows a clear,
actionable message instead of passing through the raw/cryptic error text:

  ⚠️ API provider returned a billing error — your API key has run out of
  credits or has an insufficient balance. Check your provider's billing
  dashboard and top up or switch to a different API key.

Changes:
- formatAssistantErrorText: detect billing errors via isBillingErrorMessage()
  and return a user-friendly message (placed before the generic HTTP/JSON
  error fallthrough)
- sanitizeUserFacingText: same billing detection for the sanitization path
- pi-embedded-runner/run.ts: add billingFailure detection in the profile
  exhaustion fallback, so the FailoverError message is billing-specific
- Added 3 new tests for credit balance, HTTP 402, and insufficient credits

* fix: extract billing error message to shared constant
2026-02-05 13:58:43 -08:00
Glucksberg
4e1a7cd60c fix: allow multiple compaction retries on context overflow (#8928)
Previously, overflowCompactionAttempted was a boolean flag set once, preventing
recovery when a single compaction wasn't enough. Change to a counter allowing up
to 3 attempts before giving up. Also add diagnostic logging on overflow events to
help debug early-overflow issues.

Fixes sessions that hit context overflow during long agentic turns with many tool
calls, where one compaction round isn't sufficient to bring context below limits.
2026-02-05 13:58:37 -08:00
Gustavo Madeira Santana
4629054403 chore: apply local workspace updates (#9911)
* chore: apply local workspace updates

* fix: resolve prep findings after rebase (#9898) (thanks @gumadeiras)

* refactor: centralize model allowlist normalization (#9898) (thanks @gumadeiras)

* fix: guard model allowlist initialization (#9911)

* docs: update changelog scope for #9911

* docs: remove model names from changelog entry (#9911)

* fix: satisfy type-aware lint in model allowlist (#9911)
2026-02-05 16:54:44 -05:00
Glucksberg
93b450349f fix: clear stale token metrics on /new and /reset (#8929)
When starting a new session via /new or /reset, the token usage fields
(totalTokens, inputTokens, outputTokens, contextTokens) survived from the
previous session via the spread pattern in session init. This caused /status
to display misleading context usage from the old session.

Clear all four token metrics explicitly in the isNewSession block, alongside
the existing compactionCount reset. Also add diagnostic logging for session
forking via ParentSessionKey to help trace context inheritance.
2026-02-05 13:42:59 -08:00
Glucksberg
2ca78a8aed fix(runtime): bump minimum Node.js version to 22.12.0 (#5370)
* fix(runtime): bump minimum Node.js version to 22.12.0

Aligns the runtime guard with the declared package.json engines requirement.

The Matrix plugin (and potentially others) requires Node >= 22.12.0,
but the runtime guard previously allowed 22.0.0+. This caused confusing
errors like 'Cannot find module @vector-im/matrix-bot-sdk' when the real
issue was an unsupported Node version.

- Update MIN_NODE from 22.0.0 to 22.12.0
- Update error message to reflect the correct version
- Update tests to use 22.12.0 as the minimum valid version

Fixes #5292

* fix: update test versions to match MIN_NODE=22.12.0

---------

Co-authored-by: Markus Glucksberg <markus@glucksberg.com>
2026-02-05 13:42:52 -08:00
Vincent Koc
db8e9b37c6 chore(agentsmd): add tsgo command to AGENTS.md (#9894)
Add `pnpm tsgo` command to AGENTS.md development reference

Co-authored-by: vincentkoc <vincentkoc@users.noreply.github.com>
2026-02-05 13:37:14 -08:00
Omar Khaleel
ad13c265ba feat(skills): add QR code skill (#8817)
feat(skills): add QR code generation and reading skill

Adds qr-code skill with:
- qr_generate.py - Generate QR codes with customizable size/error correction
- qr_read.py - Decode QR codes from images
- SKILL.md documentation

Co-authored-by: Omar-Khaleel
2026-02-05 13:34:43 -08:00
MattQ
7159d3b254 Docs: escape hash symbol in help channel names in issue template (#9695) 2026-02-05 13:27:50 -08:00
Caelum
d6c088910b chore: add agent credentials to gitignore (#9874)
Protect sensitive files from accidental commit:
- memory/ (moltbook credentials, session data)
- .agent/*.json (agent config, moltbook.json)

Workflows in .agent/workflows/ remain tracked.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 13:27:45 -08:00
Tyler Yust
821520a057 fix cron scheduling and reminder delivery regressions (#9733)
* fix(cron): prevent timer from allowing process exit (fixes #9694)

The cron timer was using .unref(), which caused the Node.js event
loop to exit or sleep if no other handles were active. This prevented
cron jobs from firing in some environments.

* fix(cron): infer delivery target for isolated jobs (fixes #9683)

When creating isolated agentTurn jobs (e.g. reminders) without explicit
delivery options, the job would default to 'announce' but fail to
resolve the target conversation. Now, we infer the channel and
recipient from the agent's current session key.

* fix(cron): enhance delivery inference for threaded sessions and null inputs (#9733)

Improves the delivery inference logic in the cron tool to correctly handle threaded session keys and cases where delivery is explicitly set to null. This ensures that the appropriate delivery mode and target are inferred based on the agent's session key, enhancing the reliability of job execution.

* fix: preserve telegram topic delivery inference (#9733) (thanks @tyler6204)

* fix: simplify cron delivery merge spread (#9733) (thanks @tyler6204)
2026-02-05 13:08:41 -08:00
Christian Klotz
f32eeae3bc fix: remove orphaned tool_results during compaction pruning
When pruneHistoryForContextShare drops chunks of messages, it could drop
an assistant message with tool_use blocks while leaving corresponding
tool_result messages in the kept portion. These orphaned tool_results
cause Anthropic's API to reject the session with 'unexpected tool_use_id'.

Fix by calling repairToolUseResultPairing after each chunk drop to clean
up any orphaned tool_results. This reuses existing battle-tested code
from session-transcript-repair.ts.

Fixes #9769, #9724, #9672
2026-02-05 20:37:53 +00:00
Josh Palmer
7c951b01ab 🤖 Feishu: tighten mention gating
What:
- require the bot open_id match for group mention detection when available

Why:
- prevent replies when other users are mentioned and the bot id is known

Tests:
- pnpm test
2026-02-05 12:33:59 -08:00
Josh Palmer
4fc4c5256a 🤖 Feishu: expand channel support
What:
- add post parsing, doc link extraction, routing, replies, reactions, typing, and user lookup
- fix media download/send flows and make doc fetches domain-aware
- update Feishu docs and clawtributor credits

Why:
- raise Feishu parity with other channels and avoid dropped group messages
- keep replies threaded while supporting Lark domains
- document new configuration and credit the contributor

Tests:
- pnpm build
- pnpm check
- pnpm test (gateway suite timed out; reran pnpm vitest run --config vitest.gateway.config.ts)

Co-authored-by: 九灵云 <server@jiulingyun.cn>
2026-02-05 12:29:04 -08:00
Michael Lee
eb80b9acb3 feat: add Claude Opus 4.6 to built-in model catalog (#9853)
* feat: add Claude Opus 4.6 to built-in model catalog

- Update default model from claude-opus-4-5 to claude-opus-4-6
- Add opus-4.6 model ID normalization
- Add claude-opus-4-6 to live model filter prefixes
- Update image tool to prefer claude-opus-4-6 for vision
- Add CLI backend alias for opus-4.6
- Update onboard auth default selections to include opus-4.6
- Update model picker placeholder

Closes #9811

* test: update tests for claude-opus-4-6 default

- Fix model-alias-defaults test to use claude-opus-4-6
- Fix image-tool test to expect claude-opus-4-6 in fallbacks

* feat: support claude-opus-4-6

* docs: update changelog for opus 4.6 (#9853) (thanks @TinyTb)

* chore: bump pi to 0.52.0

---------

Co-authored-by: Slurpy <slurpy@openclaw.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-05 12:09:23 -08:00
Rajat Joshi
ea237115a9 fix(cli): avoid NODE_OPTIONS for --disable-warning (#9691) (thanks @18-RAJAT)
Fixes npm pack failing on modern Node where --disable-warning is disallowed in NODE_OPTIONS.
2026-02-05 12:05:14 -08:00
大猫子
679bb087db docs: fix incorrect model.fallback to model.fallbacks in Ollama config (#9384) (#9749)
Both English and Chinese documentation had incorrect configuration template
using 'fallback' instead of 'fallbacks' in agents.defaults.model config.

Co-authored-by: damaozi <1811866786@qq.com>
2026-02-05 13:56:58 -05:00
Gustavo Madeira Santana
1473fb19a5 update handle 2026-02-05 13:56:10 -05:00
Ayaan Zaidi
01db1dde1a fix: telegram topic auto-threading — use parseTelegramTarget, add tests (#7235) (thanks @Lukavyi) 2026-02-06 00:23:04 +05:30
Clawdbot
a13efbe2b5 fix: pass threadId/to/accountId from parent to subagent gateway call
When spawning a subagent, the requesterOrigin's threadId, to, and
accountId were not forwarded to the callGateway({method:'agent'}) params.
This meant the subagent's runContext had no currentThreadTs or
currentChannelId, so resolveTelegramAutoThreadId could not auto-inject
the forum topic thread ID when the subagent used the message tool.

Changes:
- sessions-spawn-tool: pass to, accountId, threadId from requesterOrigin
- run-context: populate currentChannelId from opts.to as fallback

Fixes subagent messages landing in General Topic instead of the correct
Telegram DM topic thread.
2026-02-06 00:23:04 +05:30
Clawdbot
6ac5dd2c0e test: cover telegram topic threadId auto-injection and subagent origin threading 2026-02-06 00:23:04 +05:30
Clawdbot
eef247b7a4 fix: auto-inject Telegram forum topic threadId in message tool
When using Telegram DM topics (forum topics), messages sent via the
message tool (media, buttons, etc.) land in General Topic instead of
the user's current topic. This happens because Slack has
resolveSlackAutoThreadId for auto-threading but Telegram had no
equivalent.

Add resolveTelegramAutoThreadId that mirrors the Slack pattern:
- When channel is telegram and no explicit threadId is provided
- Check if toolContext.currentThreadTs (the topic ID) is set
- Verify the target matches the originating chat
- Inject the threadId into params so the Telegram plugin action
  handler picks it up for sendMessage/sendMedia

The subagent announce path already correctly passes threadId via
requesterOrigin (set from agentThreadId in sessions-spawn-tool),
so no changes needed there.
2026-02-06 00:23:04 +05:30
Seb Slight
9e0030b75f docs(onboarding): streamline CLI onboarding docs (#9830) 2026-02-05 13:46:11 -05:00
Christian Klotz
ddedb56c01 fix(telegram): pass parentPeer for forum topic binding inheritance (#9789)
Fixes #9545 and #9351.

When a message comes from a Telegram forum topic, the peer ID includes
the topic suffix (e.g., `-1001234567890:topic:99`). Users configure
bindings with the base group ID, which previously did not match.

This adds `parentPeer` to `resolveAgentRoute()` calls for forum groups,
enabling binding inheritance from the parent group to all topics.

- Extract `buildTelegramParentPeer()` helper in bot/helpers.ts
- Pass parentPeer in bot-message-context.ts, bot-handlers.ts,
  bot-native-commands.ts, and bot.ts (reaction handler)
- Add tests for forum topic routing and topic precedence
2026-02-05 18:25:03 +00:00
Peter Steinberger
547374220c chore: reset appcast to 2026.2.3 2026-02-05 09:48:14 -08:00
Sebastian
c8f4bca0c4 docs: fix onboarding rendering issues 2026-02-05 12:14:45 -05:00
Seb Slight
3011b00d39 docs(onboarding): add bootstrapping page (#9767) 2026-02-05 12:08:35 -05:00
Ayaan Zaidi
cf95b2f3f4 fix: update changelog for help sorting (#8068) (thanks @deepsoumya617) 2026-02-05 21:23:41 +05:30
Soumyadeep Ghosh
203e3804b3 CLI: sort commands alphabetically in help output
Fixes #7964

Added sortSubcommands: true to configureHelp() to display
commands in alphabetical order when running 'openclaw --help'.
2026-02-05 21:23:41 +05:30
sebslight
34424ce536 docs(install): rename install overview page 2026-02-05 10:29:35 -05:00
Seb Slight
675c26b2b0 Docs: streamline start and install docs (#9648)
* docs(start): streamline getting started flow

* docs(nav): reorganize start and install sections

* docs(style): move custom css to style.css

* docs(navigation): align zh-CN ordering

* docs(navigation): localize zh-Hans labels
2026-02-05 10:09:45 -05:00
cpojer
8b8451231c chore: Typecheck test helper files. 2026-02-05 19:51:00 +09:00
cpojer
460808e0c8 Update deps. 2026-02-05 19:44:08 +09:00
Ayaan Zaidi
f2c5c847bd fix: preserve telegram DM topic threadId (#9039) (thanks @lailoo) 2026-02-05 15:33:30 +05:30
damaozi
c0b267a03a test(telegram): add DM topic threadId deliveryContext test for #8891
Verifies that threadId is passed to updateLastRoute for DM topics.
Test fails on main branch, passes with the fix.
2026-02-05 15:33:30 +05:30
damaozi
8860d2ed7f fix(telegram): preserve DM topic threadId in deliveryContext
When receiving messages in Telegram DM topics (Topics in Private Chats),
the threadId was not saved in the session's deliveryContext, causing
replies to go to General chat instead of the topic.

Now we pass threadId to updateLastRoute for DM topics.

Fixes #8891
2026-02-05 15:33:30 +05:30
Peter Steinberger
a4d1af1b11 fix: resolve discord owner allowFrom matches 2026-02-05 00:51:39 -08:00
Peter Steinberger
5031b283a5 chore: bump version to 2026.2.4 2026-02-05 00:38:50 -08:00
Peter Steinberger
bdb90ea4ee test: register discord plugin in allowlist test 2026-02-05 00:38:50 -08:00
Peter Steinberger
d6cde28c8e fix: stabilize windows acl tests and command auth registry (#9335) (thanks @M00N7682) 2026-02-05 00:38:35 -08:00
M00N7682
f26cc60872 Tests: add test coverage for security/windows-acl.ts
Adds comprehensive unit tests for Windows ACL inspection utilities:
- resolveWindowsUserPrincipal: username resolution with fallback
- parseIcaclsOutput: icacls output parsing
- summarizeWindowsAcl: ACL entry classification (trusted/world/group)
- inspectWindowsAcl: async ACL inspection with mocked exec
- formatWindowsAclSummary: summary string formatting
- formatIcaclsResetCommand: reset command string generation
- createIcaclsResetCommand: structured reset command generation

All 26 tests passing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 00:35:29 -08:00
Peter Steinberger
1ee1522daa fix: resolve bundled chrome extension assets (#8914) (thanks @kelvinCB) 2026-02-05 00:17:09 -08:00
Kelvin Calcano
34e78a7054 style(cli): satisfy lint rules in extension path resolver 2026-02-05 00:17:09 -08:00
Kelvin Calcano
44bbe09bee fix(cli): support bundled extension path in dist root 2026-02-05 00:17:09 -08:00
Kelvin Calcano
1008c28f5a test(cli): use unique temp dir for extension install 2026-02-05 00:17:09 -08:00
Kelvin Calcano
0621d0e9e8 fix(cli): resolve bundled chrome extension path 2026-02-05 00:17:09 -08:00
Peter Steinberger
3b40227bc6 fix: remove unused cron import 2026-02-05 07:56:16 +00:00
Peter Steinberger
d84eb46467 fix: restore discord owner hint from allowlists 2026-02-04 23:34:22 -08:00
hyf0-agent
8524666454 fix: gracefully downgrade xhigh thinking level in cron isolated agent (#9363)
When thinkingDefault is set to "xhigh" but the configured model does not
support it (e.g. Claude), the cron isolated-agent path throws a hard error
causing the job to fail. The interactive chat path already handles this by
silently downgrading to "high".

Apply the same graceful downgrade in the cron path: log a warning and
fall back to "high" instead of crashing.

Co-authored-by: hyf0-agent <hyf0-agent@users.noreply.github.com>
2026-02-05 13:52:55 +09:00
Peter Steinberger
54ddbc4660 chore: update 2026.2.3 notes 2026-02-04 17:55:13 -08:00
Peter Steinberger
7f95cdac78 chore(mac): update appcast for 2026.2.3 2026-02-04 17:55:13 -08:00
Peter Steinberger
cfdc551346 fix(mac): resolve cron schedule formatters 2026-02-04 17:55:13 -08:00
Peter Steinberger
f895c9fba1 chore: sync plugin versions to 2026.2.3 2026-02-04 17:55:13 -08:00
Gustavo Madeira Santana
22927b0834 fix: infer --auth-choice from API key flags during non-interactive onboarding (#9241)
* fix: infer --auth-choice from API key flags during non-interactive onboarding

When --anthropic-api-key (or other provider key flags) is passed without
an explicit --auth-choice, the auth choice defaults to "skip", silently
discarding the API key. This means the gateway starts without credentials
and fails on every inbound message with "No API key found for provider".

Add inferAuthChoiceFromFlags() to derive the correct auth choice from
whichever provider API key flag was supplied, so credentials are persisted
to auth-profiles.json as expected.

Fixes #8481

* fix: infer auth choice from API key flags (#8484) (thanks @f-trycua)

* refactor: centralize auth choice inference flags (#8484) (thanks @f-trycua)

---------

Co-authored-by: f-trycua <f@trycua.com>
2026-02-04 20:38:46 -05:00
Gustavo Madeira Santana
385a7eba33 fix: enforce owner allowlist for commands 2026-02-04 20:05:08 -05:00
Gustavo Madeira Santana
a6fd76efeb Message: clarify media schema + fix MEDIA newline 2026-02-04 19:59:15 -05:00
Christian Klotz
21f8c3db18 Telegram: remove last @ts-nocheck from bot-handlers.ts (#9206)
* Telegram: remove @ts-nocheck from bot-handlers.ts, use Grammy types directly, deduplicate StickerMetadata

* Telegram: remove last @ts-nocheck from bot-handlers.ts (#9206)
2026-02-05 00:58:49 +00:00
Gustavo Madeira Santana
392bbddf29 Security: owner-only tools + command auth hardening (#9202)
* Security: gate whatsapp_login by sender auth

* Security: treat undefined senderAuthorized as unauthorized (opt-in)

* fix: gate whatsapp_login to owner senders (#8768) (thanks @victormier)

* fix: add explicit owner allowlist for tools (#8768) (thanks @victormier)

* fix: normalize escaped newlines in send actions (#8768) (thanks @victormier)

---------

Co-authored-by: Victor Mier <victormier@gmail.com>
2026-02-04 19:49:36 -05:00
Tak Hoffman
0cd47d830f fix: cover anonymous voice allowlist callers (#8104) (thanks @victormier) (#9188) 2026-02-04 18:23:19 -06:00
Christian Klotz
90b4e54354 Telegram: remove @ts-nocheck from bot-message.ts (#9180)
* Telegram: remove @ts-nocheck from bot-message.ts, type deps via Omit<BuildTelegramMessageContextParams>

* Telegram: widen allMedia to TelegramMediaRef[] so stickerMetadata flows through

* Telegram: remove @ts-nocheck from bot-message.ts (#9180)
2026-02-05 00:20:44 +00:00
Gustavo Madeira Santana
4434cae565 Security: harden sandboxed media handling (#9182)
* Message: enforce sandbox for media param

* fix: harden sandboxed media handling (#8780) (thanks @victormier)

* chore: format message action runner (#8780) (thanks @victormier)

---------

Co-authored-by: Victor Mier <victormier@gmail.com>
2026-02-04 19:11:23 -05:00
Gustavo Madeira Santana
5e025c4ba3 Tests: restore TUI gateway env 2026-02-04 19:09:52 -05:00
Gustavo Madeira Santana
a13ff55bd9 Security: Prevent gateway credential exfiltration via URL override (#9179)
* Gateway: require explicit auth for url overrides

* Gateway: scope credential blocking to non-local URLs only

Address review feedback: the previous fix blocked credential fallback for
ALL URL overrides, which was overly strict and could break workflows that
use --url to switch between loopback/tailnet without passing credentials.

Now credential fallback is only blocked for non-local URLs (public IPs,
external hostnames). Local addresses (127.0.0.1, localhost, private IPs
like 192.168.x.x, 10.x.x.x, tailnet 100.x.x.x) still get credential
fallback as before.

This maintains the security fix (preventing credential exfiltration to
attacker-controlled URLs) while preserving backward compatibility for
legitimate local URL overrides.

* Security: require explicit credentials for gateway url overrides (#8113) (thanks @victormier)

* Gateway: reuse explicit auth helper for url overrides (#8113) (thanks @victormier)

* Tests: format gateway chat test (#8113) (thanks @victormier)

* Tests: require explicit auth for gateway url overrides (#8113) (thanks @victormier)

---------

Co-authored-by: Victor Mier <victormier@gmail.com>
2026-02-04 18:59:44 -05:00
Christian Klotz
96abc1c864 Telegram: remove @ts-nocheck from bot.ts, fix duplicate error handler, harden sticker caching (#9077)
* Telegram: remove @ts-nocheck from bot.ts and bot-message-dispatch.ts

- bot/types.ts: TelegramContext.me uses UserFromGetMe (Grammy) instead of manual inline type
- bot.ts: remove 6 unsafe casts (as any, as unknown, as object), use Grammy types directly
- bot.ts: remove dead message_thread_id access on reactions (not in Telegram Bot API)
- bot.ts: remove resolveThreadSessionKeys import (no longer needed for reactions)
- bot-message-dispatch.ts: replace ': any' with DispatchTelegramMessageParams type
- bot-message-dispatch.ts: add sticker.fileId guard before cache access
- bot.test.ts: update reaction tests, remove dead DM thread-reaction test

* Telegram: remove duplicate bot.catch handler (only the last one runs in Grammy)

* Telegram: remove @ts-nocheck from bot.ts, fix duplicate error handler, harden sticker caching (#9077)
2026-02-04 22:35:51 +00:00
Gustavo Madeira Santana
38e6da1fe0 TUI/Gateway: fix pi streaming + tool routing + model display + msg updating (#8432)
* TUI/Gateway: fix pi streaming + tool routing

* Tests: clarify verbose tool output expectation

* fix: avoid seq gaps for targeted tool events (#8432) (thanks @gumadeiras)
2026-02-04 17:12:16 -05:00
lsh411
a42e3cb78a feat(heartbeat): add accountId config option for multi-agent routing (#8702)
* feat(heartbeat): add accountId config option for multi-agent routing

Add optional accountId field to heartbeat configuration, allowing
multi-agent setups to explicitly specify which Telegram account
should be used for heartbeat delivery.

Previously, heartbeat delivery would use the accountId from the
session's deliveryContext. When a session had no prior conversation
history, heartbeats would default to the first/primary account
instead of the agent's intended bot.

Changes:
- Add accountId to HeartbeatSchema (zod-schema.agent-runtime.ts)
- Use heartbeat.accountId with fallback to session accountId (targets.ts)

Backward compatible: if accountId is not specified, behavior is unchanged.

Closes #8695

* fix: improve heartbeat accountId routing (#8702) (thanks @lsh411)

* fix: harden heartbeat accountId routing (#8702) (thanks @lsh411)

* fix: expose heartbeat accountId in status (#8702) (thanks @lsh411)

* chore: format status + heartbeat tests (#8702) (thanks @lsh411)

---------

Co-authored-by: m1 16 512 <m116512@m1ui-MacBookAir-2.local>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-04 16:49:12 -05:00
Josh Palmer
bebf323775 Discord: allow disabling thread starter context 2026-02-04 13:25:56 -08:00
mudrii
5d82c82313 feat: per-channel responsePrefix override (#9001)
* feat: per-channel responsePrefix override

Add responsePrefix field to all channel config types and Zod schemas,
enabling per-channel and per-account outbound response prefix overrides.

Resolution cascade (most specific wins):
  L1: channels.<ch>.accounts.<id>.responsePrefix
  L2: channels.<ch>.responsePrefix
  L3: (reserved for channels.defaults)
  L4: messages.responsePrefix (existing global)

Semantics:
  - undefined -> inherit from parent level
  - empty string -> explicitly no prefix (stops cascade)
  - "auto" -> derive [identity.name] from routed agent

Changes:
  - Core logic: resolveResponsePrefix() in identity.ts accepts
    optional channel/accountId and walks the cascade
  - resolveEffectiveMessagesConfig() passes channel context through
  - Types: responsePrefix added to WhatsApp, Telegram, Discord, Slack,
    Signal, iMessage, Google Chat, MS Teams, Feishu, BlueBubbles configs
  - Zod schemas: responsePrefix added for config validation
  - All channel handlers wired: telegram, discord, slack, signal,
    imessage, line, heartbeat runner, route-reply, native commands
  - 23 new tests covering backward compat, channel/account levels,
    full cascade, auto keyword, empty string stops, unknown fallthrough

Fully backward compatible - no existing config is affected.
Fixes #8857

* fix: address CI lint + review feedback

- Replace Record<string, any> with proper typed helpers (no-explicit-any)
- Add curly braces to single-line if returns (eslint curly)
- Fix JSDoc: 'Per-channel' → 'channel/account' on shared config types
- Extract getChannelConfig() helper for type-safe dynamic key access

* fix: finish responsePrefix overrides (#9001) (thanks @mudrii)

* fix: normalize prefix wiring and types (#9001) (thanks @mudrii)

---------

Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-04 16:16:34 -05:00
Shakker
43590d8287 changelog: add shell completion auto-fix entry 2026-02-04 19:51:06 +00:00
Shakker
dae0e2b325 scripts: update test-shell-completion to use shared helpers
- Use `checkShellCompletionStatus` and `ensureCompletionCacheExists` from doctor-completion
- Display "Uses slow pattern" status in output
- Simulate doctor/update/onboard behavior for all completion scenarios
- Remove duplicated utility functions
2026-02-04 19:51:06 +00:00
Shakker
3e14192730 onboard: use shared completion helpers for shell completion setup
- Replace inline completion logic with `checkShellCompletionStatus` and `ensureCompletionCacheExists`
- Auto-upgrade old slow dynamic patterns silently during onboarding
- Auto-regenerate cache if profile exists but cache is missing
- Prompt to install if no completion is configured
2026-02-04 19:51:06 +00:00
Shakker
dbaf0a8ae2 update: use shared completion helpers for shell completion setup
- Replace inline completion logic with `checkShellCompletionStatus` and `ensureCompletionCacheExists`
- Auto-upgrade old slow dynamic patterns silently during update
- Auto-regenerate cache if profile exists but cache is missing
- Prompt to install if no completion is configured
2026-02-04 19:51:06 +00:00
Shakker
5bd63b012c doctor: integrate shell completion check into doctor command
- Import and call `doctorShellCompletion` during doctor run
- Checks/fixes completion issues before gateway health check
2026-02-04 19:51:06 +00:00
Shakker
3fae903863 doctor: add shell completion check module
- Add `checkShellCompletionStatus` to get profile/cache/slow-pattern status
- Add `ensureCompletionCacheExists` for silent cache regeneration
- Add `doctorShellCompletion` to check and fix completion issues:
  - Auto-upgrade old slow dynamic patterns to cached version
  - Auto-regenerate cache if profile exists but cache is missing
  - Prompt to install if no completion is configured
2026-02-04 19:51:06 +00:00
Shakker
d5f8208c38 completion: export cache utilities and require cached file for installation
- Export `resolveCompletionCachePath` and `completionCacheExists` for external use
- Update `installCompletion` to require cache existence (never use slow dynamic pattern)
- Add `usesSlowDynamicCompletion` to detect old `source <(...)` patterns
- Add `getShellProfilePath` helper for consistent profile path resolution
- Update `formatCompletionSourceLine` to always use cached file
2026-02-04 19:51:06 +00:00
Shakker
42c690632d feat: add shell completion test script for installation verification 2026-02-04 19:51:06 +00:00
Shakker
1d17630dc6 feat: add shell completion installation prompt to CLI update command 2026-02-04 19:51:06 +00:00
Josh Palmer
2b1da4f5d8 🤖 docs: note zh-CN landing revamp (#8994) (thanks @joshp123)
What:
- add changelog entry for the zh-CN landing revamp docs

Why:
- record the doc update and thank the contributor

Tests:
- pnpm lint && pnpm build && pnpm test
2026-02-04 10:42:12 -08:00
Josh Palmer
aaeecc8c8d 🤖 docs: mirror landing revamp for zh-CN
What:
- add zh-CN versions of landing revamp pages (features, quickstart, docs directory, network model, credits)
- refresh zh-CN index and hubs, plus glossary entries

Why:
- keep Chinese docs aligned with the new English landing experience
- ensure navigation surfaces the new entry points

Tests:
- pnpm build && pnpm check && pnpm test
2026-02-04 10:42:12 -08:00
Christian Klotz
eab0a07f71 chore: replace landpr prompt with end-to-end landing workflow (#8916) 2026-02-04 16:01:46 +00:00
Shakker
01ce144fa9 fix(app-render): handle optional model in renderApp function 2026-02-04 15:42:58 +00:00
Seb Slight
718dba8cb6 Docs: landing page revamp (#8885)
* Docs: refresh landing page

* Docs: add landing page companion pages

* Docs: drop legacy Jekyll assets

* Docs: remove legacy terminal css test

* Docs: restore terminal css assets

* Docs: remove terminal css assets
2026-02-04 10:37:14 -05:00
Tak Hoffman
9822985ea6 fix(web ui): agent model selection 2026-02-04 09:25:38 -06:00
Seb Slight
2196456d4a Revert "feat: Add Docs Chat Widget with RAG-powered Q&A (#7908)" (#8834)
This reverts commit fa4b28d7af.
2026-02-04 08:35:46 -05:00
Peter Steinberger
6f200ea77f fix: force reload cron store 2026-02-04 04:24:04 -08:00
Peter Steinberger
5b0851ebd8 feat: add cloudflare ai gateway provider 2026-02-04 04:10:13 -08:00
Peter Steinberger
19ecdce275 fix: align proxy fetch typing 2026-02-04 04:09:53 -08:00
Iranb
18652d181b fix(imessage): detect self-chat echoes to prevent infinite loops (#8680) 2026-02-04 03:31:35 -08:00
Yudong Han
f633a8cb22 fix: address review comments
- Use optional timeoutMs parameter (undefined = use config/default)
- Extract DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS to shared constants.ts
- Import constant in client.ts instead of hardcoding
- Re-export constant from probe.ts for backwards compatibility
2026-02-04 03:26:13 -08:00
Yudong Han
78f8a29071 fix(imessage): unify timeout configuration with configurable probeTimeoutMs
- Add probeTimeoutMs config option to channels.imessage
- Export DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS constant (10s) from probe.ts
- Propagate timeout config through all iMessage probe/RPC operations
- Fix hardcoded 2000ms timeouts that were too short for SSH connections

Closes: timeout issues when using SSH wrapper scripts (imsg-ssh)
2026-02-04 03:26:13 -08:00
Ayaan Zaidi
78fd194722 fix: telegram forward metadata + cron delivery guard (#8392) (thanks @Glucksberg) 2026-02-04 16:43:20 +05:30
Glucksberg
b2361292e7 fix: trim legacy signature fallback, type fromChatType as union 2026-02-04 16:43:20 +05:30
Glucksberg
57566c5e4d fix(telegram): include forward_from_chat metadata in forwarded message context (#8133)
Extract missing metadata from forwarded Telegram messages:

- Add fromChatType to TelegramForwardedContext, capturing the original
  chat type (channel/supergroup/group) from forward_from_chat.type
  and forward_origin.chat/sender_chat.type
- Add fromMessageId to capture the original message ID from channel forwards
- Read author_signature from forward_origin objects (modern API),
  preferring it over the deprecated forward_signature field
- Pass ForwardedFromChatType and ForwardedFromMessageId through to
  the inbound context payload
- Add test coverage for forward_origin channel/chat types, including
  author_signature extraction and fromChatType propagation
2026-02-04 16:43:20 +05:30
Christian Klotz
da6de49815 Telegram: use Grammy types directly, add typed Probe/Audit to plugin interface (#8403)
* Telegram: replace duplicated types with Grammy imports, add Probe/Audit generics to plugin interface

* Telegram: remove legacy forward metadata (deprecated in Bot API 7.0), simplify required-field checks

* Telegram: clean up remaining legacy references and unnecessary casts

* Telegram: keep RequestInit parameter type in proxy fetch (addresses review feedback)

* Telegram: add exhaustiveness guard to resolveForwardOrigin switch
2026-02-04 10:09:28 +00:00
Peter Steinberger
6341819d74 fix: cron announce delivery path (#8540) (thanks @tyler6204) 2026-02-04 01:03:59 -08:00
Tyler Yust
c396877dd9 Changelog: move cron entries to 2026.2.3 2026-02-04 01:03:59 -08:00
Tyler Yust
79d00e20db UI: handle future timestamps in formatAgo 2026-02-04 01:03:59 -08:00
Tyler Yust
f8d2534062 fix(cron): fix test failures and regenerate protocol files
- Add forceReload option to ensureLoaded to avoid stat I/O in normal
  paths while still detecting cross-service writes in the timer path
- Post isolated job summary back to main session (restores the old
  isolation.postToMainPrefix behavior via delivery model)
- Update legacy migration tests to check delivery.channel instead of
  payload.channel (normalization now moves delivery fields to top-level)
- Remove legacy deliver/channel/to/bestEffortDeliver from payload schema
- Update protocol conformance test for delivery modes
- Regenerate GatewayModels.swift (isolation -> delivery)
2026-02-04 01:03:59 -08:00
Tyler Yust
6fb8d8850e feat(cron): enhance legacy delivery handling in job patches
- Introduced logic to map legacy payload delivery updates onto the delivery object for `agentTurn` jobs, ensuring backward compatibility with legacy clients.
- Added tests to validate the correct application of legacy delivery settings in job patches, improving reliability in job configuration.
- Refactored delivery handling functions to streamline the merging of legacy delivery fields into the current job structure.

This update enhances the flexibility of delivery configurations, ensuring that legacy settings are properly handled in the context of new job patches.
2026-02-04 01:03:59 -08:00
Tyler Yust
246896d64b refactor(cron): improve delivery configuration handling in CronJobEditor and CLI
- Enhanced the delivery configuration logic in CronJobEditor to explicitly set the bestEffort property based on job settings.
- Refactored the CLI command to streamline delivery object creation, ensuring proper handling of optional fields like channel and to.
- Improved code readability and maintainability by restructuring delivery assignment logic.

This update clarifies the delivery configuration process, enhancing the reliability of job settings in both the editor and CLI.
2026-02-04 01:03:59 -08:00
Tyler Yust
64df61f697 feat(cron): enhance delivery handling and testing for isolated jobs
- Introduced new properties for explicit message targeting and message tool disabling in the EmbeddedRunAttemptParams type.
- Updated cron job tests to validate best-effort delivery behavior and handling of delivery failures.
- Added logic to clear delivery settings when switching session targets in cron jobs.
- Improved the resolution of delivery failures and best-effort logic in the isolated agent's run function.

This update enhances the flexibility and reliability of delivery mechanisms in isolated cron jobs, ensuring better handling of message delivery scenarios.
2026-02-04 01:03:59 -08:00
Tyler Yust
ef4949b936 refactor(cron): update delivery instructions for isolated agent
- Revised the delivery instructions in the isolated agent's command body to clarify that summaries should be returned as plain text and will be delivered by the main agent.
- Removed the previous directive regarding messaging tools to streamline communication guidelines.

This change enhances clarity in the delivery process for isolated agent tasks.
2026-02-04 01:03:59 -08:00
Tyler Yust
1409943863 feat(cron): set default enabled state for cron jobs
- Added logic to default the `enabled` property to `true` if not explicitly set as a boolean in the cron job input.
- Updated job creation and store functions to ensure consistent handling of the `enabled` state across the application.
- Enhanced input normalization to improve job configuration reliability.

This update ensures that cron jobs are enabled by default, enhancing user experience and reducing potential misconfigurations.
2026-02-04 01:03:59 -08:00
Tyler Yust
3f82daefd8 feat(cron): enhance delivery modes and job configuration
- Updated isolated cron jobs to support new delivery modes: `announce` and `none`, improving output management.
- Refactored job configuration to remove legacy fields and streamline delivery settings.
- Enhanced the `CronJobEditor` UI to reflect changes in delivery options, including a new segmented control for delivery mode selection.
- Updated documentation to clarify the new delivery configurations and their implications for job execution.
- Improved tests to validate the new delivery behavior and ensure backward compatibility with legacy settings.

This update provides users with greater flexibility in managing how isolated jobs deliver their outputs, enhancing overall usability and clarity in job configurations.
2026-02-04 01:03:59 -08:00
Tyler Yust
ab9f06f4ff feat(cron): enhance one-shot job behavior and CLI options
- Default one-shot jobs to delete after success, improving job management.
- Introduced `--keep-after-run` CLI option to allow users to retain one-shot jobs post-execution.
- Updated documentation to clarify default behaviors and new options for one-shot jobs.
- Adjusted cron job creation logic to ensure consistent handling of delete options.
- Enhanced tests to validate new behaviors and ensure reliability.

This update streamlines the handling of one-shot jobs, providing users with more control over job persistence and execution outcomes.
2026-02-04 01:03:59 -08:00
Tyler Yust
0bb0dfc9bc feat(cron): default isolated jobs to announce delivery and enhance scheduling options
- Updated isolated cron jobs to default to `announce` delivery mode, improving user experience.
- Enhanced scheduling options to accept ISO 8601 timestamps for `schedule.at`, while still supporting epoch milliseconds.
- Refined documentation to clarify delivery modes and scheduling formats.
- Adjusted related CLI commands and UI components to reflect these changes, ensuring consistency across the platform.
- Improved handling of legacy delivery fields for backward compatibility.

This update streamlines the configuration of isolated jobs, making it easier for users to manage job outputs and schedules.
2026-02-04 01:03:59 -08:00
Tyler Yust
511c656cbc feat(cron): introduce delivery modes for isolated jobs
- Added support for new delivery modes in cron jobs: `announce`, `deliver`, and `none`.
- Updated documentation to reflect changes in delivery options and usage examples.
- Enhanced the cron job schema to include delivery configuration.
- Refactored related CLI commands and UI components to accommodate the new delivery settings.
- Improved handling of legacy delivery fields for backward compatibility.

This update allows users to choose how output from isolated jobs is delivered, enhancing flexibility in job management.
2026-02-04 01:03:59 -08:00
Tyler Yust
3a03e38378 fix(cron): fix timeout, add timestamp validation, enable file sync
Fixes #7667

Task 1: Fix cron operation timeouts
- Increase default gateway tool timeout from 10s to 30s
- Increase cron-specific tool timeout to 60s
- Increase CLI default timeout from 10s to 30s
- Prevents timeouts when gateway is busy with long-running jobs

Task 2: Add timestamp validation
- New validateScheduleTimestamp() function in validate-timestamp.ts
- Rejects atMs timestamps more than 1 minute in the past
- Rejects atMs timestamps more than 10 years in the future
- Applied to both cron.add and cron.update operations
- Provides helpful error messages with current time and offset

Task 3: Enable file sync for manual edits
- Track file modification time (storeFileMtimeMs) in CronServiceState
- Check file mtime in ensureLoaded() and reload if changed
- Recompute next runs after reload to maintain accuracy
- Update mtime after persist() to prevent reload loop
- Dashboard now picks up manual edits to ~/.openclaw/cron/jobs.json
2026-02-04 01:03:59 -08:00
Peter Steinberger
a749db9820 fix: harden voice-call webhook verification 2026-02-03 23:47:27 -08:00
Val Alexander
fa4b28d7af feat: Add Docs Chat Widget with RAG-powered Q&A (#7908)
* feat: add docs chat prototype and related scripts

- Introduced a minimal documentation chatbot that builds a search index from markdown files and serves responses via an API.
- Added scripts for building the index and serving the chat API.
- Updated package.json with new commands for chat index building and serving.
- Created a new Vercel configuration file for deployment.
- Added a README for the docs chat prototype detailing usage and integration.

* feat: enhance docs chat with vector-based RAG pipeline

- Added vector index building and serving capabilities to the docs chat.
- Introduced new scripts for generating embeddings and serving the chat API using vector search.
- Updated package.json with new commands for vector index operations.
- Enhanced README with instructions for the new RAG pipeline and legacy keyword pipeline.
- Removed outdated Vercel configuration file.

* feat: enhance chat widget with markdown rendering and style updates

- Integrated dynamic loading of markdown rendering for chat responses.
- Implemented a fallback for markdown rendering to ensure consistent display.
- Updated CSS variables for improved theming and visual consistency.
- Enhanced chat bubble and input styles for better user experience.
- Added new styles for markdown content in chat bubbles, including code blocks and lists.

* feat: add copy buttons to chat widget for enhanced user interaction

- Implemented copy buttons for chat responses and code blocks in the chat widget.
- Updated CSS styles for improved visibility and interaction of copy buttons.
- Adjusted textarea height for better user experience.
- Enhanced functionality to allow users to easily copy text from chat bubbles and code snippets.

* feat: update chat widget styles for improved user experience

- Changed accent color for better visibility.
- Enhanced preformatted text styles for code blocks, including padding and word wrapping.
- Adjusted positioning and styles of copy buttons for chat responses and code snippets.
- Improved hover effects for copy buttons to enhance interactivity.

* feat: enhance chat widget styles for better responsiveness and scrollbar design

- Updated chat panel dimensions for improved adaptability on various screen sizes.
- Added custom scrollbar styles for better aesthetics and usability.
- Adjusted chat bubble styles for enhanced visibility and interaction.
- Improved layout for expanded chat widget on smaller screens.

* feat: refine chat widget code block styles and copy button functionality

- Adjusted padding and margin for preformatted text in chat responses for better visual consistency.
- Introduced a compact style for single-line code blocks to enhance layout.
- Updated copy button logic to skip short code blocks, improving user experience when copying code snippets.

* feat: add resize handle functionality to chat widget for adjustable panel width

- Implemented a draggable resize handle for the chat widget's sidebar, allowing users to adjust the panel width.
- Added CSS styles for the resize handle, including hover effects and responsive behavior.
- Integrated drag-to-resize logic to maintain user-set width across interactions.
- Ensured the panel resets to default width when closed, enhancing user experience.

* feat: implement rate limiting and error handling in chat API

- Added rate limiting functionality to the chat API, allowing a maximum number of requests per IP within a specified time window.
- Implemented error handling for rate limit exceeded responses, including appropriate headers and retry instructions.
- Enhanced error handling for other API errors, providing user-friendly messages for various failure scenarios.
- Updated README to include new environment variables for rate limiting configuration.

* feat: integrate Upstash Vector for enhanced document retrieval in chat API

- Implemented Upstash Vector as a cloud-based storage solution for document chunks, replacing the local LanceDB option.
- Added auto-detection of storage mode based on environment variables for seamless integration.
- Updated the chat API to utilize the new retrieval mechanism, enhancing response accuracy and performance.
- Enhanced README with setup instructions for Upstash and updated environment variable requirements.
- Introduced new scripts and configurations for managing the vector index and API interactions.

* feat: add create-markdown-preview.js for markdown rendering

- Introduced a new script for framework-agnostic HTML rendering of markdown content.
- The script includes various parsing functions to handle different markdown elements.
- Updated the chat widget to load the vendored version of @create-markdown/preview for improved markdown rendering.

* docs: update README for Upstash Vector index setup and environment variables

- Enhanced instructions for creating a Vector index in Upstash, including detailed settings and important notes.
- Clarified environment variable requirements for both Upstash and LanceDB modes.
- Improved formatting and organization of setup steps for better readability.
- Added health check and API endpoint details for clearer usage guidance.

* feat: add TRUST_PROXY environment variable for IP address handling

- Introduced the TRUST_PROXY variable to control the trust of X-Forwarded-For headers when behind a reverse proxy.
- Updated the README to document the new environment variable and its default value.
- Enhanced the getClientIP function to conditionally trust proxy headers based on the TRUST_PROXY setting.

* feat: add ALLOWED_ORIGINS environment variable for CORS configuration

- Introduced the ALLOWED_ORIGINS variable to specify allowed origins for CORS, enhancing security and flexibility.
- Updated the README to document the new environment variable and its usage.
- Refactored CORS handling in the server code to utilize the ALLOWED_ORIGINS setting for dynamic origin control.

* fix: ensure complete markdown rendering in chat widget

- Added logic to flush any remaining buffered bytes from the decoder, ensuring that all text is rendered correctly in the assistant bubble.
- Updated the assistant bubble's innerHTML to reflect the complete markdown content after streaming completes.

* feat: enhance DocsStore with improved vector handling and similarity conversion

- Added a constant for the distance metric used in vector searches, clarifying the assumption of L2 distance.
- Updated the createTable method to ensure all chunk properties are correctly mapped during table creation.
- Improved the similarity score calculation by providing a clear explanation of the conversion from L2 distance, ensuring accurate ranking of results.

* chore: fix code formatting

* Revert "chore: fix code formatting"

This reverts commit 6721f5b0b7.

* chore: format code for improved readability

- Reformatted code in serve.ts to enhance readability by adjusting indentation and line breaks.
- Ensured consistent style for function return types and object properties throughout the file.

* feat: Update API URL selection logic in chat widget

- Enhanced the API URL configuration to prioritize explicit settings, defaulting to localhost for development and using a production URL otherwise.
- Improved clarity in the code by adding comments to explain the logic behind the API URL selection.

* chore: Update documentation structure for improved organization

- Changed the path for the "Start Here" page to "start/index" for better clarity.
- Reformatted the "Web & Interfaces" and "Help" groups to use multi-line arrays for improved readability.

* feat: Enhance markdown preview integration and improve chat widget asset loading

- Wrapped the markdown preview functionality in an IIFE to expose a global API for easier integration.
- Updated the chat widget to load the markdown preview library dynamically, checking for existing instances to avoid duplicate loads.
- Adjusted asset paths in the chat widget to ensure correct loading based on the environment (local or production).
- Added CORS headers in the Vercel configuration for improved API accessibility.

* fix: Update chat API URL to include '/api' for correct endpoint access

- Modified the chat configuration and widget files to append '/api' to the API URL, ensuring proper endpoint usage in production and local environments.

* refactor: Simplify docs-chat configuration and remove unused scripts

- Removed outdated scripts and configurations related to the docs-chat feature, including build and serve scripts, as well as the associated package.json and README files.
- Streamlined the API URL configuration in the chat widget for better clarity and maintainability.
- Updated the package.json to remove unnecessary scripts related to the now-deleted functionality.

* refactor: Update documentation structure for improved clarity

- Changed the path for the "Start Here" page from "start/index" to "index" to enhance navigation and organization within the documentation.

* chore: Remove unused dependencies from package.json and pnpm-lock.yaml

- Deleted `@lancedb/lancedb`, `@upstash/vector`, and `openai` from both package.json and pnpm-lock.yaml to streamline the project and reduce bloat.

* chore: Clean up .gitignore by removing obsolete entries

- Deleted unused entries related to the docs-chat vector database from .gitignore to maintain a cleaner configuration.

* chore: Remove deprecated chat configuration and markdown preview script

- Deleted the `create-markdown-preview.js` script and the `docs-chat-config.js` file to eliminate unused assets and streamline the project.
- Updated the `docs-chat-widget.js` to directly reference the markdown library from a CDN, enhancing maintainability.

* chore: Update markdown rendering in chat widget to use marked library

- Replaced the deprecated `create-markdown-preview` library with the `marked` library for markdown rendering.
- Adjusted the script loading mechanism to fetch `marked` from a CDN, improving performance and maintainability.
- Enhanced the markdown rendering function to ensure security by disabling HTML pass-through and opening links in new tabs.

* Delete docs/start/index.md
2026-02-04 07:42:20 +00:00
Peter Steinberger
5292367324 docs: update Feishu plugin docs 2026-02-03 23:24:41 -08:00
Peter Steinberger
35eb40a700 fix(security): separate untrusted channel metadata from system prompt (thanks @KonstantinMirin) 2026-02-03 23:02:45 -08:00
Lucas Kim
6fdb136688 docs: document secure DM mode preset (#7872)
* docs: document secure DM mode preset

* fix: resolve merge conflict in resizable-divider
2026-02-04 06:55:13 +00:00
Peter Steinberger
44d1aa31f3 docs: add changelog for #7178 (thanks @Yeom-JinHo) 2026-02-03 22:47:21 -08:00
Yeom-JinHo
7b3d23b703 fix(control-ui): resolve header logo when gateway.controlUi.basePath is set (#7178)
* fix(control-ui): resolve header logo when gateway.controlUi.basePath is set

* refactor(control-ui): header logo under basePath; normalize logo URL with normalizeBasePath
2026-02-03 22:46:14 -08:00
Peter Steinberger
efc9d0a498 docs: note tmux send-keys TUI guidance (#7737) (thanks @Wangnov) 2026-02-03 22:04:27 -08:00
Wangnov
089d03453d docs(skills): split tmux send-keys for TUI (#7737)
* docs(skills): split tmux send-keys for TUI

* docs(skills): soften TUI send-keys wording

---------

Co-authored-by: wangnov <1694546283@qq.com>
2026-02-03 22:03:47 -08:00
Peter Steinberger
4a5d368926 fix: keep Moonshot CN base URL in onboarding (#7180) (thanks @waynelwz) 2026-02-03 21:58:51 -08:00
Liu Weizhan
1c6b25ddbb feat: add support for Moonshot API key for China endpoint 2026-02-03 21:58:51 -08:00
Peter Steinberger
9f16de2533 style: update chat new-messages button 2026-02-03 21:53:50 -08:00
Stephen Chen
d2ff28dda7 Make openclaw consistent in this file (#8533)
Co-authored-by: stephenchen2025 <schenjobs@gmail.com>
2026-02-04 00:02:25 -05:00
Michelle Tilley
f04e84f194 Address PR feedback 2026-02-04 04:02:38 +00:00
Michelle Tilley
5af322f710 feat(discord): add set-presence action for bot activity and status
Bridge the agent tools layer to the Discord gateway WebSocket via a new
gateway registry, allowing agents to set the bot's activity and online
status. Supports playing, streaming, listening, watching, custom, and
competing activity types. Custom type uses activityState as the sidebar
text; other types show activityName in the sidebar and activityState in
the flyout. Opt-in via channels.discord.actions.presence (default false).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 04:02:38 +00:00
Ayaan Zaidi
b64c1a56a1 chore: update changelog for #8193 (thanks @gildo) 2026-02-04 09:23:17 +05:30
Ayaan Zaidi
41a4f1200b fix: honor telegram model overrides in buttons (#8193) (thanks @gildo) 2026-02-04 09:23:17 +05:30
Ermenegildo Fiorito
202c554d09 Telegram: fix model button review issues
- Add currentModel to callback handler for checkmark display
- Add 64-byte callback_data limit protection (skip long model IDs)
- Add tests for large model lists and callback_data limits
2026-02-04 09:23:17 +05:30
Ermenegildo Fiorito
16349b6e93 Telegram: add inline button model selection for /models and /model commands 2026-02-04 09:23:17 +05:30
Tyler Yust
efb4a34be4 feat: add new messages indicator style for chat interface
- Introduced a floating pill element above the compose area to indicate new messages.
- Styled the indicator with hover effects and responsive design for better user interaction.
2026-02-03 19:32:50 -08:00
Peter Steinberger
e4b084c762 chore: bump version to 2026.2.3 2026-02-03 18:33:27 -08:00
Tyler Yust
3e6c623cfe refactor: remove unnecessary blank line in policy test file 2026-02-03 18:10:26 -08:00
Tyler Yust
9c4eab69cc iMessage: promote BlueBubbles and refresh docs/skills (#8415)
* feat: Make BlueBubbles the primary iMessage integration

- Remove old imsg skill (skills/imsg/SKILL.md)
- Create new BlueBubbles skill (skills/bluebubbles/SKILL.md) with message tool examples
- Add keep-alive script documentation for VM/headless setups to docs/channels/bluebubbles.md
  - AppleScript that pokes Messages.app every 5 minutes
  - LaunchAgent configuration for automatic execution
  - Prevents Messages.app from going idle in VM environments
- Update all documentation to prioritize BlueBubbles over legacy imsg:
  - Mark imsg channel as legacy throughout docs
  - Update README.md channel lists
  - Update wizard, hubs, pairing, and index docs
  - Update FAQ to recommend BlueBubbles for iMessage
  - Update RPC docs to note imsg as legacy pattern
  - Update Chinese documentation (zh-CN)
- Replace imsg examples with generic macOS skill examples where appropriate

BlueBubbles is now the recommended first-class iMessage integration,
with the legacy imsg integration marked for potential future removal.

* refactor: Update import paths and improve code formatting

- Adjusted import paths in session-status-tool.ts, whatsapp-heartbeat.ts, and heartbeat-runner.ts for consistency.
- Reformatted code for better readability by aligning and grouping related imports and function parameters.
- Enhanced error messages and conditional checks for clarity in heartbeat-runner.ts.

* skills: restore imsg skill and align bluebubbles skill

* docs: update FAQ for clarity and formatting

- Adjusted the formatting of the FAQ section to ensure consistent bullet point alignment.
- No content changes were made, only formatting improvements for better readability.

* style: oxfmt touched files

* fix: preserve BlueBubbles developer reference (#8415) (thanks @tyler6204)
2026-02-03 18:06:54 -08:00
Peter Steinberger
9c5941ba46 fix: add legacy daemon-cli shim for updates 2026-02-03 18:04:48 -08:00
Peter Steinberger
41d2993f7b fix(matrix): require unique allowlist matches in wizard 2026-02-03 18:04:02 -08:00
Peter Steinberger
d3ba57b7d7 feat: add configurable web_fetch maxChars cap 2026-02-03 18:03:53 -08:00
Peter Steinberger
6b4b6049b4 fix: enforce Nextcloud Talk allowlist by user id 2026-02-03 18:03:53 -08:00
Peter Steinberger
bbe9cb3022 fix(update): honor update.channel for update.run 2026-02-03 17:57:55 -08:00
Tak Hoffman
61a7fc5e0e Docs: drop healthcheck from bootstrap 2026-02-03 19:50:40 -06:00
Peter Steinberger
e895e85f54 fix: improve build-info resolution for commit/version 2026-02-03 17:31:51 -08:00
Peter Steinberger
e59eb814bd chore: bump version to 2026.2.2-1 2026-02-03 17:26:10 -08:00
Gustavo Madeira Santana
df55eeacdb Merge branch 'main' of https://github.com/openclaw/openclaw 2026-02-03 20:20:16 -05:00
Josh Palmer
fd8f8843bd Docs: guard zh-CN i18n workflow
What:
- document zh-CN docs pipeline and generated-doc guardrails
- note Discord escalation when the pipeline drags

Why:
- prevent accidental edits to generated translations

Tests:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Josh Palmer <joshpalmer123@gmail.com>
2026-02-03 17:19:58 -08:00
Gustavo Madeira Santana
a9bb96ade3 fix: use build-info for version fallback 2026-02-03 20:19:32 -05:00
Peter Steinberger
f1cbe7db1d chore: add mac dSYM zip to release artifacts 2026-02-03 17:15:02 -08:00
Peter Steinberger
95cd2210f9 chore: update appcast for 2026.2.2 2026-02-03 17:04:27 -08:00
Peter Steinberger
539a15e63f chore: prep 2026.2.2 docs/release checks 2026-02-03 16:38:42 -08:00
Peter Steinberger
4df4435c45 test: reset /approve mock per test (#1) (thanks @mitsuhiko) 2026-02-03 16:19:41 -08:00
Peter Steinberger
d41acf99a6 test: add /approve gateway scope coverage (#1) (thanks @mitsuhiko) 2026-02-03 16:19:20 -08:00
Armin Ronacher
efe2a464af fix(approvals): gate /approve by gateway scopes 2026-02-03 16:18:49 -08:00
Peter Steinberger
66d8117d44 fix: harden control ui framing + ws origin 2026-02-03 16:00:57 -08:00
Josh Palmer
0223416c61 Channels: finish Feishu/Lark integration 2026-02-03 14:27:39 -08:00
Josh Palmer
2483f26c23 Channels: add Feishu/Lark support 2026-02-03 14:27:13 -08:00
Josh Palmer
4027b3583e Docs(zh-CN): add AGENTS translation workflow 2026-02-03 13:23:15 -08:00
Josh Palmer
a3ec2d0734 Docs: update zh-CN translations and pipeline
What:
- update zh-CN glossary, TM, and translator prompt
- regenerate zh-CN docs and apply targeted fixes
- add zh-CN AGENTS pipeline guidance

Why:
- address terminology/spacing feedback from #6995

Tests:
- pnpm build && pnpm check && pnpm test
2026-02-03 13:23:00 -08:00
Josh Palmer
9f03791aa9 Docs: refresh zh-CN translations + i18n guidance
What:
- update zh-CN glossary, translation prompt, and TM
- regenerate zh-CN docs and apply targeted fixes
- add zh-CN AGENTS guidance for translation pipeline

Why:
- address zh-CN terminology and spacing feedback from #6995

Tests:
- pnpm build && pnpm check && pnpm test
2026-02-03 13:22:28 -08:00
Gustavo Madeira Santana
f52ca0a712 fix(ui): note agent file refresh in changelog 2026-02-03 14:15:47 -05:00
Gustavo Madeira Santana
ddccfd3ec1 fix(ui): refresh agent files after external edits 2026-02-03 14:14:16 -05:00
Gustavo Madeira Santana
f60eae83fa fix(skills): warn when bundled dir missing 2026-02-03 14:01:40 -05:00
Gustavo Madeira Santana
5935c4d23d fix(ui): fix web UI after tsdown migration and typing changes 2026-02-03 13:56:20 -05:00
Peter Steinberger
1c4db91593 chore: prepare 2026.2.2 release 2026-02-03 10:02:01 -08:00
Peter Steinberger
9d2066bd53 fix: restore OpenClaw docs/source links in system prompt 2026-02-03 10:01:04 -08:00
Ethan Palm
f57e70912c docs: Update information architecture for OpenClaw docs (#7622)
* docs: restructure navigation into 5 tabs for better IA

* dedupe redirects

* use 8 tabs

* add missing /index extensions

* update zh navigation

* remove `default: true` and rearrange languages

* add missing redirects

* format:fix

* docs: update IA tabs + restore /images redirect (#7622) (thanks @ethanpalm)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-03 09:57:43 -08:00
Peter Steinberger
a7f4a53ce8 fix: harden Windows exec allowlist 2026-02-03 09:34:25 -08:00
Peter Steinberger
8f3bfbd1c4 fix(matrix): harden allowlists 2026-02-03 09:34:02 -08:00
Peter Steinberger
f8dfd034f5 fix(voice-call): harden inbound policy 2026-02-03 09:33:25 -08:00
Tak Hoffman
fc40ba8e7e Skills: refine healthcheck guidance 2026-02-03 09:21:34 -06:00
cpojer
1f2f79a7a7 chore: Merge tsconfigs, typecheck ui as part of pnpm tsgo locally and on CI. 2026-02-03 22:50:00 +09:00
cpojer
6e09c1142e chore: Switch to NodeNext for module/moduleResolution in ui. 2026-02-03 22:48:28 +09:00
cpojer
27677dd8bd chore: Fix all TypeScript errors in ui. 2026-02-03 22:45:29 +09:00
cpojer
be4f7ef361 fix: Fix Mac app build step. 2026-02-03 22:14:11 +09:00
cpojer
6b83d82e82 chore: clean up git hooks and actually install them again. 2026-02-03 22:08:24 +09:00
cpojer
6fb2d3d7d7 feat: remove slop. 2026-02-03 22:04:17 +09:00
cpojer
425003417d fix: Remove tsconfig.oxlint.json AGAIN. 2026-02-03 21:53:48 +09:00
cpojer
a8893094ea fix: CI: We no longer need to test the tsc build with Bun, we are always using tsdown to build now. 2026-02-03 21:34:49 +09:00
cpojer
a03d852d65 chore: Migrate to tsdown, speed up JS bundling by ~10x (thanks @hyf0).
The previous migration to tsdown was reverted because it caused a ~20x slowdown when running OpenClaw from the repo. @hyf0 investigated and found that simply renaming the `dist` folder also caused the same slowdown. It turns out the Plugin script loader has a bunch of voodoo vibe logic to determine if it should load files from source and compile them, or if it should load them from dist. When building with tsdown, the filesystem layout is different (bundled), and so some files weren't in the right location, and the Plugin script loader decided to compile source files from scratch using Jiti.

The new implementation uses tsdown to embed `NODE_ENV: 'production'`, which we now use to determine if we are running OpenClaw from a "production environmen" (ie. from dist). This removes the slop in favor of a deterministic toggle, and doesn't rely on directory names or similar.

There is some code reaching into `dist` to load specific modules, primarily in the voice-call extension, which I simplified into loading an "officially" exported `extensionAPI.js` file. With tsdown, entry points need to be explicitly configured, so we should be able to avoid sloppy code reaching into internals from now on. This might break some existing users, but if it does, it's because they were using "private" APIs.
2026-02-03 20:18:16 +09:00
Shakker
e3b85b9829 fix: shell completion and drop onboarding prompt 2026-02-03 08:45:49 +00:00
Shakker
3014a91b07 chore: update changelog for completion caching 2026-02-03 08:43:25 +00:00
Shakker
981de05181 Onboarding: drop completion prompt 2026-02-03 08:43:25 +00:00
Shakker
9950440cf6 Install: cache completion scripts on install/update 2026-02-03 08:43:25 +00:00
Shakker
80d8fe7786 CLI: cache shell completion scripts 2026-02-03 08:43:25 +00:00
Vignesh Natarajan
b37626ce6b docs: finish renaming memory state dir references 2026-02-03 00:24:13 -08:00
Vignesh Natarajan
1ee57cf727 fix: changelog entry for QMD memory (#3160) (thanks @vignesh07) 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
4322ca6f4a chore: oxfmt 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
afbb1af6c5 fix: restore safety + session_status hints 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
600c46b5a4 chore: oxfmt 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
7d5ca1176d fix: restore session_status and CLI examples 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
5915d479dc chore: oxfmt 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
30098b04d7 chore: fix lint warnings 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
f72214725d chore: restore OpenClaw branding 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
9bef525944 chore: apply formatter 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
edd6289f26 fix: derive citations chat type via session parser 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
d0b98c75e5 fix: make QMD cache key deterministic 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
e332a717a8 Lint: add braces for single-line ifs 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
23cfcd60df Fix build regressions after merge 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
465536e811 QMD: use OpenClaw config types 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
3d1c3b78ec Tests: cover QMD scope, reads, and citation clamp 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
1861e76360 Memory: clamp QMD citations to injected budget 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
c248da0317 Memory: harden QMD memory_get path checks 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
b7f4755020 Memory: fix QMD scope channel parsing 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
3e82cbd55b Memory: parse quoted qmd command 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
11a968f5c3 Docs: align QMD state dir with OpenClaw 2026-02-02 23:45:05 -08:00
Benjamin Jesuiter
5d8c665baf Tests: use OPENCLAW_STATE_DIR in qmd manager 2026-02-02 23:45:05 -08:00
vignesh07
9df78b3379 fix(memory/qmd): throttle embed + citations auto + restore --force 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
20578da204 Add how to trigger model downloads for qmd in documentation 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
564fe6f089 fix(memory-qmd): create collections via qmd CLI (no YAML) 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
dd8373a424 fix(memory-qmd): write XDG index.yml + legacy compat 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
9be3c27bb7 fix(qmd): use XDG dirs for qmd home; drop ollama docs 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
e12184661e Fix build errors 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
3a57106c1e Add more tests; make fall back more resilient and visible 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
2c30ba400b Make memory more resilient to failure 2026-02-02 23:45:05 -08:00
Vignesh Natarajan
5d3af3bc62 feat (memory): Implement new (opt-in) QMD memory backend 2026-02-02 23:45:05 -08:00
Shakker
e9f182def7 fix: error handling in restore failure reporting 2026-02-03 06:22:51 +00:00
Shakker
1b31e2f345 Onboarding/TUI: prevent prompt overlap and auto-open
- Stop onboarding output once TUI launches
- Avoid background Web UI open on TUI path
- Restore terminal state on exit
- Add terminal restore helper
2026-02-03 06:18:33 +00:00
Shakker
58d5b39c9a Onboarding: keep TUI flow exclusive 2026-02-03 06:11:11 +00:00
Shakker
157d6d2db7 CLI: restore terminal state on exit 2026-02-03 06:10:19 +00:00
Tak Hoffman
d5593d647c chore: fix formatting 2026-02-02 22:58:04 -06:00
Tak Hoffman
83715eca49 Security: tune bootstrap healthcheck prompt + healthcheck wording 2026-02-02 22:33:43 -06:00
Gustavo Madeira Santana
7dfa99a6f7 chore: fix formatting 2026-02-02 21:49:15 -05:00
Gustavo Madeira Santana
ac2b71f240 chore: fix CI 2026-02-02 21:44:31 -05:00
Tak Hoffman
578bde1e0d Security: healthcheck skill (#7641) (thanks @Takhoffman) 2026-02-02 20:36:58 -06:00
Tak Hoffman
e2c03845c7 Security: refine healthcheck workflow 2026-02-02 20:36:58 -06:00
Tak Hoffman
1523ef2494 Security: remove openclaw-system-admin skill path 2026-02-02 20:36:58 -06:00
Tak Hoffman
cdec53b22b Security: rename openclaw-system-admin skill to healthcheck 2026-02-02 20:36:58 -06:00
Tak Hoffman
a6afcb4c1d Security: new openclaw-system-admin skill + bootstrap audit 2026-02-02 20:36:58 -06:00
Gustavo Madeira Santana
2a68bcbeb3 feat(ui): add Agents dashboard 2026-02-02 21:31:17 -05:00
Aldo
c8af8e9555 Docs: clarify whats new FAQ heading (#7394) 2026-02-02 21:16:31 -05:00
cpojer
e77988f747 chore: Fix CI. 2026-02-03 10:25:32 +09:00
Peter Steinberger
96ad19a627 style(ui): format resizable divider 2026-02-02 17:01:17 -08:00
Peter Steinberger
fe81b1d712 fix(gateway): require shared auth before device bypass 2026-02-02 16:56:38 -08:00
Peter Steinberger
d1ecb46076 fix: harden exec allowlist parsing 2026-02-02 16:53:15 -08:00
Peter Steinberger
fff59da962 fix(slack): fail closed on slash command channel type lookup 2026-02-02 16:53:07 -08:00
cpojer
9e3ea2687c chore: Update deps. 2026-02-03 09:09:03 +09:00
Shakker
cfd6b21d0e fix: repair malformed tool calls and session transcripts (#7473) (thanks @justinhuangcode) 2026-02-02 23:56:27 +00:00
Shakker
118507953b Docs: simplify transcript hygiene scope 2026-02-02 23:56:27 +00:00
Shakker
befa421a57 Agents: flush pending tool results on drop 2026-02-02 23:56:27 +00:00
Shakker
e6fdac7bfb Agents: harden session file repair 2026-02-02 23:56:27 +00:00
Justin
67f90dae54 Agents: fix lint in tool-call sanitizers 2026-02-02 23:56:27 +00:00
Justin
31face5740 Changelog: note tool call repair 2026-02-02 23:56:27 +00:00
Justin
0da6de6624 Agent: repair malformed tool calls and session files 2026-02-02 23:56:27 +00:00
Tak Hoffman
0eae9f456c Docs: fix compatibility shim note 2026-02-02 17:22:22 -06:00
1168 changed files with 66832 additions and 20587 deletions

View File

@@ -0,0 +1,185 @@
---
name: merge-pr
description: Merge a GitHub PR via squash after /preparepr. Use when asked to merge a ready PR. Do not push to main or modify code. Ensure the PR ends in MERGED state and clean up worktrees after success.
---
# Merge PR
## Overview
Merge a prepared PR via `gh pr merge --squash` and clean up the worktree after success.
## Inputs
- Ask for PR number or URL.
- If missing, auto-detect from conversation.
- If ambiguous, ask.
## Safety
- Use `gh pr merge --squash` as the only path to `main`.
- Do not run `git push` at all during merge.
- Do not run gateway stop commands. Do not kill processes. Do not touch port 18792.
## Execution Rule
- Execute the workflow. Do not stop after printing the TODO checklist.
- If delegating, require the delegate to run commands and capture outputs.
## Known Footguns
- If you see "fatal: not a git repository", you are in the wrong directory. Use `~/Development/openclaw`, not `~/openclaw`.
- Read `.local/review.md` and `.local/prep.md` in the worktree. Do not skip.
- Clean up the real worktree directory `.worktrees/pr-<PR>` only after a successful merge.
- Expect cleanup to remove `.local/` artifacts.
## Completion Criteria
- Ensure `gh pr merge` succeeds.
- Ensure PR state is `MERGED`, never `CLOSED`.
- Record the merge SHA.
- Run cleanup only after merge success.
## First: Create a TODO Checklist
Create a checklist of all merge steps, print it, then continue and execute the commands.
## Setup: Use a Worktree
Use an isolated worktree for all merge work.
```sh
cd ~/Development/openclaw
# Sanity: confirm you are in the repo
git rev-parse --show-toplevel
WORKTREE_DIR=".worktrees/pr-<PR>"
```
Run all commands inside the worktree directory.
## Load Local Artifacts (Mandatory)
Expect these files from earlier steps:
- `.local/review.md` from `/reviewpr`
- `.local/prep.md` from `/preparepr`
```sh
ls -la .local || true
if [ -f .local/review.md ]; then
echo "Found .local/review.md"
sed -n '1,120p' .local/review.md
else
echo "Missing .local/review.md. Stop and run /reviewpr, then /preparepr."
exit 1
fi
if [ -f .local/prep.md ]; then
echo "Found .local/prep.md"
sed -n '1,120p' .local/prep.md
else
echo "Missing .local/prep.md. Stop and run /preparepr first."
exit 1
fi
```
## Steps
1. Identify PR meta
```sh
gh pr view <PR> --json number,title,state,isDraft,author,headRefName,baseRefName,headRepository,body --jq '{number,title,state,isDraft,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner,body}'
contrib=$(gh pr view <PR> --json author --jq .author.login)
head=$(gh pr view <PR> --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view <PR> --json headRepository --jq .headRepository.url)
```
2. Run sanity checks
Stop if any are true:
- PR is a draft.
- Required checks are failing.
- Branch is behind main.
```sh
# Checks
gh pr checks <PR>
# Check behind main
git fetch origin main
git fetch origin pull/<PR>/head:pr-<PR>
git merge-base --is-ancestor origin/main pr-<PR> || echo "PR branch is behind main, run /preparepr"
```
If anything is failing or behind, stop and say to run `/preparepr`.
3. Merge PR and delete branch
If checks are still running, use `--auto` to queue the merge.
```sh
# Check status first
check_status=$(gh pr checks <PR> 2>&1)
if echo "$check_status" | grep -q "pending\|queued"; then
echo "Checks still running, using --auto to queue merge"
gh pr merge <PR> --squash --delete-branch --auto
echo "Merge queued. Monitor with: gh pr checks <PR> --watch"
else
gh pr merge <PR> --squash --delete-branch
fi
```
If merge fails, report the error and stop. Do not retry in a loop.
If the PR needs changes beyond what `/preparepr` already did, stop and say to run `/preparepr` again.
4. Get merge SHA
```sh
merge_sha=$(gh pr view <PR> --json mergeCommit --jq '.mergeCommit.oid')
echo "merge_sha=$merge_sha"
```
5. Optional comment
Use a literal multiline string or heredoc for newlines.
```sh
gh pr comment <PR> -F - <<'EOF'
Merged via squash.
- Merge commit: $merge_sha
Thanks @$contrib!
EOF
```
6. Verify PR state is MERGED
```sh
gh pr view <PR> --json state --jq .state
```
7. Clean up worktree only on success
Run cleanup only if step 6 returned `MERGED`.
```sh
cd ~/Development/openclaw
git worktree remove ".worktrees/pr-<PR>" --force
git branch -D temp/pr-<PR> 2>/dev/null || true
git branch -D pr-<PR> 2>/dev/null || true
```
## Guardrails
- Worktree only.
- Do not close PRs.
- End in MERGED state.
- Clean up only after merge success.
- Never push to main. Use `gh pr merge --squash` only.
- Do not run `git push` at all in this command.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "Merge PR"
short_description: "Merge GitHub PRs via squash"
default_prompt: "Use $merge-pr to merge a GitHub PR via squash after preparation."

View File

@@ -0,0 +1,248 @@
---
name: prepare-pr
description: Prepare a GitHub PR for merge by rebasing onto main, fixing review findings, running gates, committing fixes, and pushing to the PR head branch. Use after /reviewpr. Never merge or push to main.
---
# Prepare PR
## Overview
Prepare a PR branch for merge with review fixes, green gates, and an updated head branch.
## Inputs
- Ask for PR number or URL.
- If missing, auto-detect from conversation.
- If ambiguous, ask.
## Safety
- Never push to `main` or `origin/main`. Push only to the PR head branch.
- Never run `git push` without specifying remote and branch explicitly. Do not run bare `git push`.
- Do not run gateway stop commands. Do not kill processes. Do not touch port 18792.
- Do not run `git clean -fdx`.
- Do not run `git add -A` or `git add .`. Stage only specific files changed.
## Execution Rule
- Execute the workflow. Do not stop after printing the TODO checklist.
- If delegating, require the delegate to run commands and capture outputs.
## Known Footguns
- If you see "fatal: not a git repository", you are in the wrong directory. Use `~/openclaw`.
- Do not run `git clean -fdx`.
- Do not run `git add -A` or `git add .`.
## Completion Criteria
- Rebase PR commits onto `origin/main`.
- Fix all BLOCKER and IMPORTANT items from `.local/review.md`.
- Run gates and pass.
- Commit prep changes.
- Push the updated HEAD back to the PR head branch.
- Write `.local/prep.md` with a prep summary.
- Output exactly: `PR is ready for /mergepr`.
## First: Create a TODO Checklist
Create a checklist of all prep steps, print it, then continue and execute the commands.
## Setup: Use a Worktree
Use an isolated worktree for all prep work.
```sh
cd ~/openclaw
# Sanity: confirm you are in the repo
git rev-parse --show-toplevel
WORKTREE_DIR=".worktrees/pr-<PR>"
```
Run all commands inside the worktree directory.
## Load Review Findings (Mandatory)
```sh
if [ -f .local/review.md ]; then
echo "Found review findings from /reviewpr"
else
echo "Missing .local/review.md. Run /reviewpr first and save findings."
exit 1
fi
# Read it
sed -n '1,200p' .local/review.md
```
## Steps
1. Identify PR meta (author, head branch, head repo URL)
```sh
gh pr view <PR> --json number,title,author,headRefName,baseRefName,headRepository,body --jq '{number,title,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner,body}'
contrib=$(gh pr view <PR> --json author --jq .author.login)
head=$(gh pr view <PR> --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view <PR> --json headRepository --jq .headRepository.url)
```
2. Fetch the PR branch tip into a local ref
```sh
git fetch origin pull/<PR>/head:pr-<PR>
```
3. Rebase PR commits onto latest main
```sh
# Move worktree to the PR tip first
git reset --hard pr-<PR>
# Rebase onto current main
git fetch origin main
git rebase origin/main
```
If conflicts happen:
- Resolve each conflicted file.
- Run `git add <resolved_file>` for each file.
- Run `git rebase --continue`.
If the rebase gets confusing or you resolve conflicts 3 or more times, stop and report.
4. Fix issues from `.local/review.md`
- Fix all BLOCKER and IMPORTANT items.
- NITs are optional.
- Keep scope tight.
Keep a running log in `.local/prep.md`:
- List which review items you fixed.
- List which files you touched.
- Note behavior changes.
5. Update `CHANGELOG.md` if flagged in review
Check `.local/review.md` section H for guidance.
If flagged and user-facing:
- Check if `CHANGELOG.md` exists.
```sh
ls CHANGELOG.md 2>/dev/null
```
- Follow existing format.
- Add a concise entry with PR number and contributor.
6. Update docs if flagged in review
Check `.local/review.md` section G for guidance.
If flagged, update only docs related to the PR changes.
7. Commit prep fixes
Stage only specific files:
```sh
git add <file1> <file2> ...
```
Preferred commit tool:
```sh
committer "fix: <summary> (#<PR>) (thanks @$contrib)" <changed files>
```
If `committer` is not found:
```sh
git commit -m "fix: <summary> (#<PR>) (thanks @$contrib)"
```
8. Run full gates before pushing
```sh
pnpm install
pnpm build
pnpm ui:build
pnpm check
pnpm test
```
Require all to pass. If something fails, fix, commit, and rerun. Allow at most 3 fix and rerun cycles. If gates still fail after 3 attempts, stop and report the failures. Do not loop indefinitely.
9. Push updates back to the PR head branch
```sh
# Ensure remote for PR head exists
git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git"
# Use force with lease after rebase
# Double check: $head must NOT be "main" or "master"
echo "Pushing to branch: $head"
if [ "$head" = "main" ] || [ "$head" = "master" ]; then
echo "ERROR: head branch is main/master. This is wrong. Stopping."
exit 1
fi
git push --force-with-lease prhead HEAD:$head
```
10. Verify PR is not behind main (Mandatory)
```sh
git fetch origin main
git fetch origin pull/<PR>/head:pr-<PR>-verify --force
git merge-base --is-ancestor origin/main pr-<PR>-verify && echo "PR is up to date with main" || echo "ERROR: PR is still behind main, rebase again"
git branch -D pr-<PR>-verify 2>/dev/null || true
```
If still behind main, repeat steps 2 through 9.
11. Write prep summary artifacts (Mandatory)
Update `.local/prep.md` with:
- Current HEAD sha from `git rev-parse HEAD`.
- Short bullet list of changes.
- Gate results.
- Push confirmation.
- Rebase verification result.
Create or overwrite `.local/prep.md` and verify it exists and is non-empty:
```sh
git rev-parse HEAD
ls -la .local/prep.md
wc -l .local/prep.md
```
12. Output
Include a diff stat summary:
```sh
git diff --stat origin/main..HEAD
git diff --shortstat origin/main..HEAD
```
Report totals: X files changed, Y insertions(+), Z deletions(-).
If gates passed and push succeeded, print exactly:
```
PR is ready for /mergepr
```
Otherwise, list remaining failures and stop.
## Guardrails
- Worktree only.
- Do not delete the worktree on success. `/mergepr` may reuse it.
- Do not run `gh pr merge`.
- Never push to main. Only push to the PR head branch.
- Run and pass all gates before pushing.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "Prepare PR"
short_description: "Prepare GitHub PRs for merge"
default_prompt: "Use $prepare-pr to prep a GitHub PR for merge without merging."

View File

@@ -0,0 +1,228 @@
---
name: review-pr
description: Review-only GitHub pull request analysis with the gh CLI. Use when asked to review a PR, provide structured feedback, or assess readiness to land. Do not merge, push, or make code changes you intend to keep.
---
# Review PR
## Overview
Perform a thorough review-only PR assessment and return a structured recommendation on readiness for /preparepr.
## Inputs
- Ask for PR number or URL.
- If missing, always ask. Never auto-detect from conversation.
- If ambiguous, ask.
## Safety
- Never push to `main` or `origin/main`, not during review, not ever.
- Do not run `git push` at all during review. Treat review as read only.
- Do not stop or kill the gateway. Do not run gateway stop commands. Do not kill processes on port 18792.
## Execution Rule
- Execute the workflow. Do not stop after printing the TODO checklist.
- If delegating, require the delegate to run commands and capture outputs, not a plan.
## Known Failure Modes
- If you see "fatal: not a git repository", you are in the wrong directory. Use `~/openclaw`.
- Do not stop after printing the checklist. That is not completion.
## Writing Style for Output
- Write casual and direct.
- Avoid em dashes and en dashes. Use commas or separate sentences.
## Completion Criteria
- Run the commands in the worktree and inspect the PR directly.
- Produce the structured review sections A through J.
- Save the full review to `.local/review.md` inside the worktree.
## First: Create a TODO Checklist
Create a checklist of all review steps, print it, then continue and execute the commands.
## Setup: Use a Worktree
Use an isolated worktree for all review work.
```sh
cd ~/Development/openclaw
# Sanity: confirm you are in the repo
git rev-parse --show-toplevel
WORKTREE_DIR=".worktrees/pr-<PR>"
git fetch origin main
# Reuse existing worktree if it exists, otherwise create new
if [ -d "$WORKTREE_DIR" ]; then
cd "$WORKTREE_DIR"
git checkout temp/pr-<PR> 2>/dev/null || git checkout -b temp/pr-<PR>
git fetch origin main
git reset --hard origin/main
else
git worktree add "$WORKTREE_DIR" -b temp/pr-<PR> origin/main
cd "$WORKTREE_DIR"
fi
# Create local scratch space that persists across /reviewpr to /preparepr to /mergepr
mkdir -p .local
```
Run all commands inside the worktree directory.
Start on `origin/main` so you can check for existing implementations before looking at PR code.
## Steps
1. Identify PR meta and context
```sh
gh pr view <PR> --json number,title,state,isDraft,author,baseRefName,headRefName,headRepository,url,body,labels,assignees,reviewRequests,files,additions,deletions --jq '{number,title,url,state,isDraft,author:.author.login,base:.baseRefName,head:.headRefName,headRepo:.headRepository.nameWithOwner,additions,deletions,files:.files|length,body}'
```
2. Check if this already exists in main before looking at the PR branch
- Identify the core feature or fix from the PR title and description.
- Search for existing implementations using keywords from the PR title, changed file paths, and function or component names from the diff.
```sh
# Use keywords from the PR title and changed files
rg -n "<keyword_from_pr_title>" -S src packages apps ui || true
rg -n "<function_or_component_name>" -S src packages apps ui || true
git log --oneline --all --grep="<keyword_from_pr_title>" | head -20
```
If it already exists, call it out as a BLOCKER or at least IMPORTANT.
3. Claim the PR
Assign yourself so others know someone is reviewing. Skip if the PR looks like spam or is a draft you plan to recommend closing.
```sh
gh_user=$(gh api user --jq .login)
gh pr edit <PR> --add-assignee "$gh_user"
```
4. Read the PR description carefully
Use the body from step 1. Summarize goal, scope, and missing context.
5. Read the diff thoroughly
Minimum:
```sh
gh pr diff <PR>
```
If you need full code context locally, fetch the PR head to a local ref and diff it. Do not create a merge commit.
```sh
git fetch origin pull/<PR>/head:pr-<PR>
# Show changes without modifying the working tree
git diff --stat origin/main..pr-<PR>
git diff origin/main..pr-<PR>
```
If you want to browse the PR version of files directly, temporarily check out `pr-<PR>` in the worktree. Do not commit or push. Return to `temp/pr-<PR>` and reset to `origin/main` afterward.
```sh
# Use only if needed
# git checkout pr-<PR>
# ...inspect files...
git checkout temp/pr-<PR>
git reset --hard origin/main
```
6. Validate the change is needed and valuable
Be honest. Call out low value AI slop.
7. Evaluate implementation quality
Review correctness, design, performance, and ergonomics.
8. Perform a security review
Assume OpenClaw subagents run with full disk access, including git, gh, and shell. Check auth, input validation, secrets, dependencies, tool safety, and privacy.
9. Review tests and verification
Identify what exists, what is missing, and what would be a minimal regression test.
10. Check docs
Check if the PR touches code with related documentation such as README, docs, inline API docs, or config examples.
- If docs exist for the changed area and the PR does not update them, flag as IMPORTANT.
- If the PR adds a new feature or config option with no docs, flag as IMPORTANT.
- If the change is purely internal with no user-facing impact, skip this.
11. Check changelog
Check if `CHANGELOG.md` exists and whether the PR warrants an entry.
- If the project has a changelog and the PR is user-facing, flag missing entry as IMPORTANT.
- Leave the change for /preparepr, only flag it here.
12. Answer the key question
Decide if /preparepr can fix issues or the contributor must update the PR.
13. Save findings to the worktree
Write the full structured review sections A through J to `.local/review.md`.
Create or overwrite the file and verify it exists and is non-empty.
```sh
ls -la .local/review.md
wc -l .local/review.md
```
14. Output the structured review
Produce a review that matches what you saved to `.local/review.md`.
A) TL;DR recommendation
- One of: READY FOR /preparepr | NEEDS WORK | NEEDS DISCUSSION | NOT USEFUL (CLOSE)
- 1 to 3 sentences.
B) What changed
C) What is good
D) Security findings
E) Concerns or questions (actionable)
- Numbered list.
- Mark each item as BLOCKER, IMPORTANT, or NIT.
- For each, point to file or area and propose a concrete fix.
F) Tests
G) Docs status
- State if related docs are up to date, missing, or not applicable.
H) Changelog
- State if `CHANGELOG.md` needs an entry and which category.
I) Follow ups (optional)
J) Suggested PR comment (optional)
## Guardrails
- Worktree only.
- Do not delete the worktree after review.
- Review only, do not merge, do not push.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "Review PR"
short_description: "Review GitHub PRs without merging"
default_prompt: "Use $review-pr to perform a thorough, review-only GitHub PR review."

View File

@@ -2,7 +2,7 @@ blank_issues_enabled: true
contact_links:
- name: Onboarding
url: https://discord.gg/clawd
about: New to Clawdbot? Join Discord for setup guidance from Krill in #help.
about: New to Clawdbot? Join Discord for setup guidance from Krill in \#help.
- name: Support
url: https://discord.gg/clawd
about: Get help from Krill and the community on Discord in #help.
about: Get help from Krill and the community on Discord in \#help.

6
.github/labeler.yml vendored
View File

@@ -9,6 +9,12 @@
- "src/discord/**"
- "extensions/discord/**"
- "docs/channels/discord.md"
"channel: feishu":
- changed-files:
- any-glob-to-any-file:
- "src/feishu/**"
- "extensions/feishu/**"
- "docs/channels/feishu.md"
"channel: googlechat":
- changed-files:
- any-glob-to-any-file:

View File

@@ -89,9 +89,6 @@ jobs:
- runtime: bun
task: test
command: pnpm canvas:a2ui:bundle && bunx vitest run
- runtime: bun
task: build
command: bunx tsc -p tsconfig.json --noEmit false
steps:
- name: Checkout
uses: actions/checkout@v4

6
.gitignore vendored
View File

@@ -64,10 +64,14 @@ apps/ios/*.mobileprovision
# Local untracked files
.local/
.vscode/
IDENTITY.md
USER.md
.tgz
# local tooling
.serena/
# Agent credentials and memory (NEVER COMMIT)
memory/
.agent/*.json
!.agent/workflows/

52
.markdownlint-cli2.jsonc Normal file
View File

@@ -0,0 +1,52 @@
{
"globs": ["docs/**/*.md", "docs/**/*.mdx", "README.md"],
"ignores": ["docs/zh-CN/**", "docs/.i18n/**", "docs/reference/templates/**"],
"config": {
"default": true,
"MD013": false,
"MD025": false,
"MD029": false,
"MD033": {
"allowed_elements": [
"Note",
"Info",
"Tip",
"Warning",
"Card",
"CardGroup",
"Columns",
"Steps",
"Step",
"Tabs",
"Tab",
"Accordion",
"AccordionGroup",
"CodeGroup",
"Frame",
"Callout",
"ParamField",
"ResponseField",
"RequestExample",
"ResponseExample",
"img",
"a",
"br",
"details",
"summary",
"p",
"strong",
"picture",
"source",
"Tooltip",
"Check",
],
},
"MD036": false,
"MD040": false,
"MD041": false,
"MD046": false,
},
}

View File

@@ -16,7 +16,6 @@
"oxc/no-map-spread": "off",
"typescript/no-explicit-any": "error",
"typescript/no-extraneous-class": "off",
"typescript/no-redundant-type-constituents": "off",
"typescript/no-unsafe-type-assertion": "off",
"unicorn/consistent-function-scoping": "off",
"unicorn/require-post-message-target-origin": "off"

View File

@@ -8,98 +8,63 @@ Input
- If missing: use the most recent PR mentioned in the conversation.
- If ambiguous: ask.
Do (review-only)
Goal: produce a thorough review and a clear recommendation (READY for /landpr vs NEEDS WORK). Do NOT merge, do NOT push, do NOT make changes in the repo as part of this command.
Do (end-to-end)
Goal: PR must end in GitHub state = MERGED (never CLOSED). Use `gh pr merge` with `--rebase` or `--squash`.
1. Identify PR meta + context
1. Repo clean: `git status`.
2. Identify PR meta (author + head branch):
```sh
gh pr view <PR> --json number,title,state,isDraft,author,baseRefName,headRefName,headRepository,url,body,labels,assignees,reviewRequests,files,additions,deletions --jq '{number,title,url,state,isDraft,author:.author.login,base:.baseRefName,head:.headRefName,headRepo:.headRepository.nameWithOwner,additions,deletions,files:.files|length}'
gh pr view <PR> --json number,title,author,headRefName,baseRefName,headRepository --jq '{number,title,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner}'
contrib=$(gh pr view <PR> --json author --jq .author.login)
head=$(gh pr view <PR> --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view <PR> --json headRepository --jq .headRepository.url)
```
2. Read the PR description carefully
- Summarize the stated goal, scope, and any “why now?” rationale.
- Call out any missing context: motivation, alternatives considered, rollout/compat notes, risk.
3. Fast-forward base:
- `git checkout main`
- `git pull --ff-only`
4. Create temp base branch from main:
- `git checkout -b temp/landpr-<ts-or-pr>`
5. Check out PR branch locally:
- `gh pr checkout <PR>`
6. Rebase PR branch onto temp base:
- `git rebase temp/landpr-<ts-or-pr>`
- Fix conflicts; keep history tidy.
7. Fix + tests + changelog:
- Implement fixes + add/adjust tests
- Update `CHANGELOG.md` and mention `#<PR>` + `@$contrib`
8. Decide merge strategy:
- Rebase if we want to preserve commit history
- Squash if we want a single clean commit
- If unclear, ask
9. Full gate (BEFORE commit):
- `pnpm lint && pnpm build && pnpm test`
10. Commit via committer (include # + contributor in commit message):
- `committer "fix: <summary> (#<PR>) (thanks @$contrib)" CHANGELOG.md <changed files>`
- `land_sha=$(git rev-parse HEAD)`
11. Push updated PR branch (rebase => usually needs force):
3. Read the diff thoroughly (prefer full diff)
```sh
git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git"
git push --force-with-lease prhead HEAD:$head
```
```sh
gh pr diff <PR>
# If you need more surrounding context for files:
gh pr checkout <PR> # optional; still review-only
git show --stat
```
12. Merge PR (must show MERGED on GitHub):
- Rebase: `gh pr merge <PR> --rebase`
- Squash: `gh pr merge <PR> --squash`
- Never `gh pr close` (closing is wrong)
13. Sync main:
- `git checkout main`
- `git pull --ff-only`
14. Comment on PR with what we did + SHAs + thanks:
4. Validate the change is needed / valuable
- What user/customer/dev pain does this solve?
- Is this change the smallest reasonable fix?
- Are we introducing complexity for marginal benefit?
- Are we changing behavior/contract in a way that needs docs or a release note?
```sh
merge_sha=$(gh pr view <PR> --json mergeCommit --jq '.mergeCommit.oid')
gh pr comment <PR> --body "Landed via temp rebase onto main.\n\n- Gate: pnpm lint && pnpm build && pnpm test\n- Land commit: $land_sha\n- Merge commit: $merge_sha\n\nThanks @$contrib!"
```
5. Evaluate implementation quality + optimality
- Correctness: edge cases, error handling, null/undefined, concurrency, ordering.
- Design: is the abstraction/architecture appropriate or over/under-engineered?
- Performance: hot paths, allocations, queries, network, N+1s, caching.
- Security/privacy: authz/authn, input validation, secrets, logging PII.
- Backwards compatibility: public APIs, config, migrations.
- Style consistency: formatting, naming, patterns used elsewhere.
6. Tests & verification
- Identify whats covered by tests (unit/integration/e2e).
- Are there regression tests for the bug fixed / scenario added?
- Missing tests? Call out exact cases that should be added.
- If tests are present, do they actually assert the important behavior (not just snapshots / happy path)?
7. Follow-up refactors / cleanup suggestions
- Any code that should be simplified before merge?
- Any TODOs that should be tickets vs addressed now?
- Any deprecations, docs, types, or lint rules we should adjust?
8. Key questions to answer explicitly
- Can we fix everything ourselves in a follow-up, or does the contributor need to update this PR?
- Any blocking concerns (must-fix before merge)?
- Is this PR ready to land, or does it need work?
9. Output (structured)
Produce a review with these sections:
A) TL;DR recommendation
- One of: READY FOR /landpr | NEEDS WORK | NEEDS DISCUSSION
- 13 sentence rationale.
B) What changed
- Brief bullet summary of the diff/behavioral changes.
C) Whats good
- Bullets: correctness, simplicity, tests, docs, ergonomics, etc.
D) Concerns / questions (actionable)
- Numbered list.
- Mark each item as:
- BLOCKER (must fix before merge)
- IMPORTANT (should fix before merge)
- NIT (optional)
- For each: point to the file/area and propose a concrete fix or alternative.
E) Tests
- What exists.
- Whats missing (specific scenarios).
F) Follow-ups (optional)
- Non-blocking refactors/tickets to open later.
G) Suggested PR comment (optional)
- Offer: “Want me to draft a PR comment to the author?”
- If yes, provide a ready-to-paste comment summarizing the above, with clear asks.
Rules / Guardrails
- Review only: do not merge (`gh pr merge`), do not push branches, do not edit code.
- If you need clarification, ask questions rather than guessing.
15. Verify PR state == MERGED:
- `gh pr view <PR> --json state --jq .state`
16. Delete temp branch:
- `git branch -D temp/landpr-<ts-or-pr>`

3
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["oxc.oxc-vscode"]
}

22
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
"editor.formatOnSave": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"[javascript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[json]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"typescript.preferences.importModuleSpecifierEnding": "js",
"typescript.reportStyleChecksAsWarnings": false,
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.experimental.useTsgo": true
}

View File

@@ -28,6 +28,14 @@
- README (GitHub): keep absolute docs URLs (`https://docs.openclaw.ai/...`) so links work on GitHub.
- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”.
## Docs i18n (zh-CN)
- `docs/zh-CN/**` is generated; do not edit unless the user explicitly asks.
- Pipeline: update English docs → adjust glossary (`docs/.i18n/glossary.zh-CN.json`) → run `scripts/docs-i18n` → apply targeted fixes only if instructed.
- Translation memory: `docs/.i18n/zh-CN.tm.jsonl` (generated).
- See `docs/.i18n/README.md`.
- The pipeline can be slow/inefficient; if its dragging, ping @jospalmbier on Discord instead of hacking around it.
## exe.dev VM ops (general)
- Access: stable path is `ssh exe.dev` then `ssh vm-name` (assume SSH key already set).
@@ -50,6 +58,7 @@
- Node remains supported for running built output (`dist/*`) and production installs.
- Mac packaging (dev): `scripts/package-mac-app.sh` defaults to current arch. Release checklist: `docs/platforms/mac/release.md`.
- Type-check/build: `pnpm build`
- TypeScript checks: `pnpm tsgo`
- Lint/format: `pnpm check`
- Tests: `pnpm test` (vitest); coverage: `pnpm test:coverage`
@@ -86,6 +95,8 @@
- Group related changes; avoid bundling unrelated refactors.
- Changelog workflow: keep latest released version at top (no `Unreleased`); after publishing, bump version and start a new top section.
- PRs should summarize scope, note testing performed, and mention any user-facing changes or new flags.
- Read this when submitting a PR: `docs/help/submitting-a-pr.md` ([Submitting a PR](https://docs.openclaw.ai/help/submitting-a-pr))
- Read this when submitting an issue: `docs/help/submitting-an-issue.md` ([Submitting an Issue](https://docs.openclaw.ai/help/submitting-an-issue))
- PR review flow: when given a PR link, review via `gh pr view`/`gh pr diff` and do **not** change branches.
- PR review calls: prefer a single `gh pr view --json ...` to batch metadata/comments; run `gh pr diff` only when needed.
- Before starting a review when a GH Issue/PR is pasted: run `git pull`; if there are local changes or unpushed commits, stop and alert the user before reviewing.

View File

@@ -2,24 +2,147 @@
Docs: https://docs.openclaw.ai
## 2026.2.6
### Changes
- Cron: default `wakeMode` is now `"now"` for new jobs (was `"next-heartbeat"`). (#10776) Thanks @tyler6204.
- Cron: `cron run` defaults to force execution; use `--due` to restrict to due-only. (#10776) Thanks @tyler6204.
- Models: support Anthropic Opus 4.6 and OpenAI Codex gpt-5.3-codex (forward-compat fallbacks). (#9853, #10720, #9995) Thanks @TinyTb, @calvin-hpnet, @tyler6204.
- Providers: add xAI (Grok) support. (#9885) Thanks @grp06.
- Web UI: add token usage dashboard. (#10072) Thanks @Takhoffman.
- Memory: native Voyage AI support. (#7078) Thanks @mcinteerj.
- Sessions: cap sessions_history payloads to reduce context overflow. (#10000) Thanks @gut-puncture.
- CLI: sort commands alphabetically in help output. (#8068) Thanks @deepsoumya617.
- Agents: bump pi-mono to 0.52.7; add embedded forward-compat fallback for Opus 4.6 model ids.
### Added
- Cron: run history deep-links to session chat from the dashboard. (#10776) Thanks @tyler6204.
- Cron: per-run session keys in run log entries and default labels for cron sessions. (#10776) Thanks @tyler6204.
- Cron: legacy payload field compatibility (`deliver`, `channel`, `to`, `bestEffortDeliver`) in schema. (#10776) Thanks @tyler6204.
### Fixes
- Cron: scheduler reliability (timer drift, restart catch-up, lock contention, stale running markers). (#10776) Thanks @tyler6204.
- Cron: store migration hardening (legacy field migration, parse error handling, explicit delivery mode persistence). (#10776) Thanks @tyler6204.
- Memory: set Voyage embeddings `input_type` for improved retrieval. (#10818) Thanks @mcinteerj.
- Telegram: auto-inject DM topic threadId in message tool + subagent announce. (#7235) Thanks @Lukavyi.
- Security: require auth for Gateway canvas host and A2UI assets. (#9518) Thanks @coygeek.
- Cron: fix scheduling and reminder delivery regressions; harden next-run recompute + timer re-arming + legacy schedule fields. (#9733, #9823, #9948, #9932) Thanks @tyler6204, @pycckuu, @j2h4u, @fujiwara-tofu-shop.
- Update: harden Control UI asset handling in update flow. (#10146) Thanks @gumadeiras.
- Security: add skill/plugin code safety scanner; redact credentials from config.get gateway responses. (#9806, #9858) Thanks @abdelsfane.
- Exec approvals: coerce bare string allowlist entries to objects. (#9903) Thanks @mcaxtr.
- Slack: add mention stripPatterns for /new and /reset. (#9971) Thanks @ironbyte-rgb.
- Chrome extension: fix bundled path resolution. (#8914) Thanks @kelvinCB.
- Compaction/errors: allow multiple compaction retries on context overflow; show clear billing errors. (#8928, #8391) Thanks @Glucksberg.
## 2026.2.3
### Changes
- Telegram: remove last `@ts-nocheck` from `bot-handlers.ts`, use Grammy types directly, deduplicate `StickerMetadata`. Zero `@ts-nocheck` remaining in `src/telegram/`. (#9206)
- Telegram: remove `@ts-nocheck` from `bot-message.ts`, type deps via `Omit<BuildTelegramMessageContextParams>`, widen `allMedia` to `TelegramMediaRef[]`. (#9180)
- Telegram: remove `@ts-nocheck` from `bot.ts`, fix duplicate `bot.catch` error handler (Grammy overrides), remove dead reaction `message_thread_id` routing, harden sticker cache guard. (#9077)
- Onboarding: add Cloudflare AI Gateway provider setup and docs. (#7914) Thanks @roerohan.
- Onboarding: add Moonshot (.cn) auth choice and keep the China base URL when preserving defaults. (#7180) Thanks @waynelwz.
- Docs: clarify tmux send-keys for TUI by splitting text and Enter. (#7737) Thanks @Wangnov.
- Docs: mirror the landing page revamp for zh-CN (features, quickstart, docs directory, network model, credits). (#8994) Thanks @joshp123.
- Messages: add per-channel and per-account responsePrefix overrides across channels. (#9001) Thanks @mudrii.
- Cron: add announce delivery mode for isolated jobs (CLI + Control UI) and delivery mode config.
- Cron: default isolated jobs to announce delivery; accept ISO 8601 `schedule.at` in tool inputs.
- Cron: hard-migrate isolated jobs to announce/none delivery; drop legacy post-to-main/payload delivery fields and `atMs` inputs.
- Cron: delete one-shot jobs after success by default; add `--keep-after-run` for CLI.
- Cron: suppress messaging tools during announce delivery so summaries post consistently.
- Cron: avoid duplicate deliveries when isolated runs send messages directly.
### Fixes
- Heartbeat: allow explicit accountId routing for multi-account channels. (#8702) Thanks @lsh411.
- TUI/Gateway: handle non-streaming finals, refresh history for non-local chat runs, and avoid event gap warnings for targeted tool streams. (#8432) Thanks @gumadeiras.
- Shell completion: auto-detect and migrate slow dynamic patterns to cached files for faster terminal startup; add completion health checks to doctor/update/onboard.
- Telegram: honor session model overrides in inline model selection. (#8193) Thanks @gildo.
- Web UI: fix agent model selection saves for default/non-default agents and wrap long workspace paths. Thanks @Takhoffman.
- Web UI: resolve header logo path when `gateway.controlUi.basePath` is set. (#7178) Thanks @Yeom-JinHo.
- Web UI: apply button styling to the new-messages indicator.
- Onboarding: infer auth choice from non-interactive API key flags. (#8484) Thanks @f-trycua.
- Security: keep untrusted channel metadata out of system prompts (Slack/Discord). Thanks @KonstantinMirin.
- Security: enforce sandboxed media paths for message tool attachments. (#9182) Thanks @victormier.
- Security: require explicit credentials for gateway URL overrides to prevent credential leakage. (#8113) Thanks @victormier.
- Security: gate `whatsapp_login` tool to owner senders and default-deny non-owner contexts. (#8768) Thanks @victormier.
- Voice call: harden webhook verification with host allowlists/proxy trust and keep ngrok loopback bypass.
- Voice call: add regression coverage for anonymous inbound caller IDs with allowlist policy. (#8104) Thanks @victormier.
- Cron: accept epoch timestamps and 0ms durations in CLI `--at` parsing.
- Cron: reload store data when the store file is recreated or mtime changes.
- Cron: deliver announce runs directly, honor delivery mode, and respect wakeMode for summaries. (#8540) Thanks @tyler6204.
- Telegram: include forward_from_chat metadata in forwarded messages and harden cron delivery target checks. (#8392) Thanks @Glucksberg.
- macOS: fix cron payload summary rendering and ISO 8601 formatter concurrency safety.
## 2026.2.2-3
### Fixes
- Update: ship legacy daemon-cli shim for pre-tsdown update imports (fixes daemon restart after npm update).
## 2026.2.2-2
### Changes
- Docs: promote BlueBubbles as the recommended iMessage integration; mark imsg channel as legacy. (#8415) Thanks @tyler6204.
### Fixes
- CLI status: resolve build-info from bundled dist output (fixes "unknown" commit in npm builds).
## 2026.2.2-1
### Fixes
- CLI status: fall back to build-info for version detection (fixes "unknown" in beta builds). Thanks @gumadeira.
## 2026.2.2
### Changes
- Docs: seed zh-CN translations. (#6619) Thanks @joshp123.
- Docs: expand zh-Hans navigation and fix zh-CN index asset paths. (#7242) Thanks @joshp123.
- Docs: add zh-CN landing notice + AI-translated image. (#7303) Thanks @joshp123.
- Docs: fix typo - clawdbot is the compatibility shim, not openclaw. (#7415) Thanks @lailoo.
- Feishu: add Feishu/Lark plugin support + docs. (#7313) Thanks @jiulingyun (openclaw-cn).
- Web UI: add Agents dashboard for managing agent files, tools, skills, models, channels, and cron jobs.
- Subagents: discourage direct messaging tool use unless a specific external recipient is requested.
- Memory: implement the opt-in QMD backend for workspace memory. (#3160) Thanks @vignesh07.
- Security: add healthcheck skill and bootstrap audit guidance. (#7641) Thanks @Takhoffman.
- Config: allow setting a default subagent thinking level via `agents.defaults.subagents.thinking` (and per-agent `agents.list[].subagents.thinking`). (#7372) Thanks @tyler6204.
- Docs: zh-CN translations seed + polish, pipeline guidance, nav/landing updates, and typo fixes. (#8202, #6995, #6619, #7242, #7303, #7415) Thanks @AaronWander, @taiyi747, @Explorer1092, @rendaoyuan, @joshp123, @lailoo.
- Docs: add zh-CN i18n guardrails to avoid editing generated translations. (#8416) Thanks @joshp123.
### Fixes
- Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.
- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed).
- Onboarding: drop completion prompt now handled by install/update.
- TUI: block onboarding output while TUI is active and restore terminal state on exit.
- CLI: cache shell completion scripts in state dir and source cached files in profiles.
- Zsh completion: escape option descriptions to avoid invalid option errors.
- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.
- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)
- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)
- Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.
- Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.
- Security: enforce access-group gating for Slack slash commands when channel type lookup fails.
- Security: require validated shared-secret auth before skipping device identity on gateway connect.
- Security: guard skill installer downloads with SSRF checks (block private/localhost URLs).
- Security: harden Windows exec allowlist; block cmd.exe bypass via single &. Thanks @simecek.
- fix(voice-call): harden inbound allowlist; reject anonymous callers; require Telnyx publicKey for allowlist; token-gate Twilio media streams; cap webhook body size (thanks @simecek)
- Media understanding: apply SSRF guardrails to provider fetches; allow private baseUrl overrides explicitly.
- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)
- Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.
- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.
- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)
- Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.
- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed); completion prompt now handled by install/update.
- TUI: block onboarding output while TUI is active and restore terminal state on exit.
- CLI/Zsh completion: cache scripts in state dir and escape option descriptions to avoid invalid option errors.
- fix(ui): resolve Control UI asset path correctly.
- fix(ui): refresh agent files after external edits.
- Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.
- Tests: stub SSRF DNS pinning in web auto-reply + Gemini video coverage. (#6619) Thanks @joshp123.
## 2026.2.1

View File

@@ -22,6 +22,9 @@ Welcome to the lobster tank! 🦞
- **Christoph Nakazawa** - JS Infra
- GitHub: [@cpojer](https://github.com/cpojer) · X: [@cnakazawa](https://x.com/cnakazawa)
- **Gustavo Madeira Santana** - Multi-agents, CLI, web UI
- GitHub: [@gumadeiras](https://github.com/gumadeiras) · X: [@gumadeiras](https://x.com/gumadeiras)
## How to Contribute
1. **Bugs & small fixes** → Open a PR!
@@ -35,6 +38,21 @@ Welcome to the lobster tank! 🦞
- Keep PRs focused (one thing per PR)
- Describe what & why
## Control UI Decorators
The Control UI uses Lit with **legacy** decorators (current Rollup parsing does not support
`accessor` fields required for standard decorators). When adding reactive fields, keep the
legacy style:
```ts
@state() foo = "bar";
@property({ type: Number }) count = 0;
```
The root `tsconfig.json` is configured for legacy decorators (`experimentalDecorators: true`)
with `useDefineForClassFields: false`. Avoid flipping these unless you are also updating the UI
build tooling to support standard decorators.
## AI/Vibe-Coded PRs Welcome! 🤖
Built with Codex, Claude, or other AI tools? **Awesome - just mark it!**

103
README.md
View File

@@ -34,7 +34,7 @@ New install? Start here: [Getting started](https://docs.openclaw.ai/start/gettin
- **[Anthropic](https://www.anthropic.com/)** (Claude Pro/Max)
- **[OpenAI](https://openai.com/)** (ChatGPT/Codex)
Model note: while any model is supported, I strongly recommend **Anthropic Pro/Max (100/200) + Opus 4.5** for longcontext strength and better promptinjection resistance. See [Onboarding](https://docs.openclaw.ai/start/onboarding).
Model note: while any model is supported, I strongly recommend **Anthropic Pro/Max (100/200) + Opus 4.6** for longcontext strength and better promptinjection resistance. See [Onboarding](https://docs.openclaw.ai/start/onboarding).
## Models (selection + auth)
@@ -120,7 +120,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
## Highlights
- **[Local-first Gateway](https://docs.openclaw.ai/gateway)** — single control plane for sessions, channels, tools, and events.
- **[Multi-channel inbox](https://docs.openclaw.ai/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, BlueBubbles, Microsoft Teams, Matrix, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
- **[Multi-channel inbox](https://docs.openclaw.ai/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, BlueBubbles (iMessage), iMessage (legacy), Microsoft Teams, Matrix, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
- **[Multi-agent routing](https://docs.openclaw.ai/gateway/configuration)** — route inbound channels/accounts/peers to isolated agents (workspaces + per-agent sessions).
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — always-on speech for macOS/iOS/Android with ElevenLabs.
- **[Live Canvas](https://docs.openclaw.ai/platforms/mac/canvas)** — agent-driven visual workspace with [A2UI](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
@@ -144,7 +144,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
### Channels
- [Channels](https://docs.openclaw.ai/channels): [WhatsApp](https://docs.openclaw.ai/channels/whatsapp) (Baileys), [Telegram](https://docs.openclaw.ai/channels/telegram) (grammY), [Slack](https://docs.openclaw.ai/channels/slack) (Bolt), [Discord](https://docs.openclaw.ai/channels/discord) (discord.js), [Google Chat](https://docs.openclaw.ai/channels/googlechat) (Chat API), [Signal](https://docs.openclaw.ai/channels/signal) (signal-cli), [iMessage](https://docs.openclaw.ai/channels/imessage) (imsg), [BlueBubbles](https://docs.openclaw.ai/channels/bluebubbles) (extension), [Microsoft Teams](https://docs.openclaw.ai/channels/msteams) (extension), [Matrix](https://docs.openclaw.ai/channels/matrix) (extension), [Zalo](https://docs.openclaw.ai/channels/zalo) (extension), [Zalo Personal](https://docs.openclaw.ai/channels/zalouser) (extension), [WebChat](https://docs.openclaw.ai/web/webchat).
- [Channels](https://docs.openclaw.ai/channels): [WhatsApp](https://docs.openclaw.ai/channels/whatsapp) (Baileys), [Telegram](https://docs.openclaw.ai/channels/telegram) (grammY), [Slack](https://docs.openclaw.ai/channels/slack) (Bolt), [Discord](https://docs.openclaw.ai/channels/discord) (discord.js), [Google Chat](https://docs.openclaw.ai/channels/googlechat) (Chat API), [Signal](https://docs.openclaw.ai/channels/signal) (signal-cli), [BlueBubbles](https://docs.openclaw.ai/channels/bluebubbles) (iMessage, recommended), [iMessage](https://docs.openclaw.ai/channels/imessage) (legacy imsg), [Microsoft Teams](https://docs.openclaw.ai/channels/msteams) (extension), [Matrix](https://docs.openclaw.ai/channels/matrix) (extension), [Zalo](https://docs.openclaw.ai/channels/zalo) (extension), [Zalo Personal](https://docs.openclaw.ai/channels/zalouser) (extension), [WebChat](https://docs.openclaw.ai/web/webchat).
- [Group routing](https://docs.openclaw.ai/concepts/group-messages): mention gating, reply tags, per-channel chunking and routing. Channel rules: [Channels](https://docs.openclaw.ai/channels).
### Apps + nodes
@@ -316,7 +316,7 @@ Minimal `~/.openclaw/openclaw.json` (model + defaults):
```json5
{
agent: {
model: "anthropic/claude-opus-4-5",
model: "anthropic/claude-opus-4-6",
},
}
```
@@ -375,9 +375,15 @@ Details: [Security guide](https://docs.openclaw.ai/gateway/security) · [Docker
- Requires `signal-cli` and a `channels.signal` config section.
### [iMessage](https://docs.openclaw.ai/channels/imessage)
### [BlueBubbles (iMessage)](https://docs.openclaw.ai/channels/bluebubbles)
- macOS only; Messages must be signed in.
- **Recommended** iMessage integration.
- Configure `channels.bluebubbles.serverUrl` + `channels.bluebubbles.password` and a webhook (`channels.bluebubbles.webhookPath`).
- The BlueBubbles server runs on macOS; the Gateway can run on macOS or elsewhere.
### [iMessage (legacy)](https://docs.openclaw.ai/channels/imessage)
- Legacy macOS-only integration via `imsg` (Messages must be signed in).
- If `channels.imessage.groups` is set, it becomes a group allowlist; include `"*"` to allow all.
### [Microsoft Teams](https://docs.openclaw.ai/channels/msteams)
@@ -490,44 +496,49 @@ Special thanks to Adam Doppelt for lobster.bot.
Thanks to all clawtributors:
<p align="left">
<a href="https://github.com/steipete"><img src="https://avatars.githubusercontent.com/u/58493?v=4&s=48" width="48" height="48" alt="steipete" title="steipete"/></a> <a href="https://github.com/cpojer"><img src="https://avatars.githubusercontent.com/u/13352?v=4&s=48" width="48" height="48" alt="cpojer" title="cpojer"/></a> <a href="https://github.com/plum-dawg"><img src="https://avatars.githubusercontent.com/u/5909950?v=4&s=48" width="48" height="48" alt="plum-dawg" title="plum-dawg"/></a> <a href="https://github.com/bohdanpodvirnyi"><img src="https://avatars.githubusercontent.com/u/31819391?v=4&s=48" width="48" height="48" alt="bohdanpodvirnyi" title="bohdanpodvirnyi"/></a> <a href="https://github.com/iHildy"><img src="https://avatars.githubusercontent.com/u/25069719?v=4&s=48" width="48" height="48" alt="iHildy" title="iHildy"/></a> <a href="https://github.com/jaydenfyi"><img src="https://avatars.githubusercontent.com/u/213395523?v=4&s=48" width="48" height="48" alt="jaydenfyi" title="jaydenfyi"/></a> <a href="https://github.com/joshp123"><img src="https://avatars.githubusercontent.com/u/1497361?v=4&s=48" width="48" height="48" alt="joshp123" title="joshp123"/></a> <a href="https://github.com/joaohlisboa"><img src="https://avatars.githubusercontent.com/u/8200873?v=4&s=48" width="48" height="48" alt="joaohlisboa" title="joaohlisboa"/></a> <a href="https://github.com/mneves75"><img src="https://avatars.githubusercontent.com/u/2423436?v=4&s=48" width="48" height="48" alt="mneves75" title="mneves75"/></a> <a href="https://github.com/MatthieuBizien"><img src="https://avatars.githubusercontent.com/u/173090?v=4&s=48" width="48" height="48" alt="MatthieuBizien" title="MatthieuBizien"/></a>
<a href="https://github.com/MaudeBot"><img src="https://avatars.githubusercontent.com/u/255777700?v=4&s=48" width="48" height="48" alt="MaudeBot" title="MaudeBot"/></a> <a href="https://github.com/Glucksberg"><img src="https://avatars.githubusercontent.com/u/80581902?v=4&s=48" width="48" height="48" alt="Glucksberg" title="Glucksberg"/></a> <a href="https://github.com/rahthakor"><img src="https://avatars.githubusercontent.com/u/8470553?v=4&s=48" width="48" height="48" alt="rahthakor" title="rahthakor"/></a> <a href="https://github.com/vrknetha"><img src="https://avatars.githubusercontent.com/u/20596261?v=4&s=48" width="48" height="48" alt="vrknetha" title="vrknetha"/></a> <a href="https://github.com/radek-paclt"><img src="https://avatars.githubusercontent.com/u/50451445?v=4&s=48" width="48" height="48" alt="radek-paclt" title="radek-paclt"/></a> <a href="https://github.com/vignesh07"><img src="https://avatars.githubusercontent.com/u/1436853?v=4&s=48" width="48" height="48" alt="vignesh07" title="vignesh07"/></a> <a href="https://github.com/tobiasbischoff"><img src="https://avatars.githubusercontent.com/u/711564?v=4&s=48" width="48" height="48" alt="Tobias Bischoff" title="Tobias Bischoff"/></a> <a href="https://github.com/sebslight"><img src="https://avatars.githubusercontent.com/u/19554889?v=4&s=48" width="48" height="48" alt="sebslight" title="sebslight"/></a> <a href="https://github.com/czekaj"><img src="https://avatars.githubusercontent.com/u/1464539?v=4&s=48" width="48" height="48" alt="czekaj" title="czekaj"/></a> <a href="https://github.com/mukhtharcm"><img src="https://avatars.githubusercontent.com/u/56378562?v=4&s=48" width="48" height="48" alt="mukhtharcm" title="mukhtharcm"/></a>
<a href="https://github.com/maxsumrall"><img src="https://avatars.githubusercontent.com/u/628843?v=4&s=48" width="48" height="48" alt="maxsumrall" title="maxsumrall"/></a> <a href="https://github.com/xadenryan"><img src="https://avatars.githubusercontent.com/u/165437834?v=4&s=48" width="48" height="48" alt="xadenryan" title="xadenryan"/></a> <a href="https://github.com/VACInc"><img src="https://avatars.githubusercontent.com/u/3279061?v=4&s=48" width="48" height="48" alt="VACInc" title="VACInc"/></a> <a href="https://github.com/mbelinky"><img src="https://avatars.githubusercontent.com/u/132747814?v=4&s=48" width="48" height="48" alt="Mariano Belinky" title="Mariano Belinky"/></a> <a href="https://github.com/rodrigouroz"><img src="https://avatars.githubusercontent.com/u/384037?v=4&s=48" width="48" height="48" alt="rodrigouroz" title="rodrigouroz"/></a> <a href="https://github.com/tyler6204"><img src="https://avatars.githubusercontent.com/u/64381258?v=4&s=48" width="48" height="48" alt="tyler6204" title="tyler6204"/></a> <a href="https://github.com/juanpablodlc"><img src="https://avatars.githubusercontent.com/u/92012363?v=4&s=48" width="48" height="48" alt="juanpablodlc" title="juanpablodlc"/></a> <a href="https://github.com/conroywhitney"><img src="https://avatars.githubusercontent.com/u/249891?v=4&s=48" width="48" height="48" alt="conroywhitney" title="conroywhitney"/></a> <a href="https://github.com/hsrvc"><img src="https://avatars.githubusercontent.com/u/129702169?v=4&s=48" width="48" height="48" alt="hsrvc" title="hsrvc"/></a> <a href="https://github.com/magimetal"><img src="https://avatars.githubusercontent.com/u/36491250?v=4&s=48" width="48" height="48" alt="magimetal" title="magimetal"/></a>
<a href="https://github.com/zerone0x"><img src="https://avatars.githubusercontent.com/u/39543393?v=4&s=48" width="48" height="48" alt="zerone0x" title="zerone0x"/></a> <a href="https://github.com/meaningfool"><img src="https://avatars.githubusercontent.com/u/2862331?v=4&s=48" width="48" height="48" alt="meaningfool" title="meaningfool"/></a> <a href="https://github.com/patelhiren"><img src="https://avatars.githubusercontent.com/u/172098?v=4&s=48" width="48" height="48" alt="patelhiren" title="patelhiren"/></a> <a href="https://github.com/NicholasSpisak"><img src="https://avatars.githubusercontent.com/u/129075147?v=4&s=48" width="48" height="48" alt="NicholasSpisak" title="NicholasSpisak"/></a> <a href="https://github.com/jonisjongithub"><img src="https://avatars.githubusercontent.com/u/86072337?v=4&s=48" width="48" height="48" alt="jonisjongithub" title="jonisjongithub"/></a> <a href="https://github.com/AbhisekBasu1"><img src="https://avatars.githubusercontent.com/u/40645221?v=4&s=48" width="48" height="48" alt="abhisekbasu1" title="abhisekbasu1"/></a> <a href="https://github.com/jamesgroat"><img src="https://avatars.githubusercontent.com/u/2634024?v=4&s=48" width="48" height="48" alt="jamesgroat" title="jamesgroat"/></a> <a href="https://github.com/claude"><img src="https://avatars.githubusercontent.com/u/81847?v=4&s=48" width="48" height="48" alt="claude" title="claude"/></a> <a href="https://github.com/JustYannicc"><img src="https://avatars.githubusercontent.com/u/52761674?v=4&s=48" width="48" height="48" alt="JustYannicc" title="JustYannicc"/></a> <a href="https://github.com/Hyaxia"><img src="https://avatars.githubusercontent.com/u/36747317?v=4&s=48" width="48" height="48" alt="Hyaxia" title="Hyaxia"/></a>
<a href="https://github.com/dantelex"><img src="https://avatars.githubusercontent.com/u/631543?v=4&s=48" width="48" height="48" alt="dantelex" title="dantelex"/></a> <a href="https://github.com/SocialNerd42069"><img src="https://avatars.githubusercontent.com/u/118244303?v=4&s=48" width="48" height="48" alt="SocialNerd42069" title="SocialNerd42069"/></a> <a href="https://github.com/daveonkels"><img src="https://avatars.githubusercontent.com/u/533642?v=4&s=48" width="48" height="48" alt="daveonkels" title="daveonkels"/></a> <a href="https://github.com/apps/google-labs-jules"><img src="https://avatars.githubusercontent.com/in/842251?v=4&s=48" width="48" height="48" alt="google-labs-jules[bot]" title="google-labs-jules[bot]"/></a> <a href="https://github.com/lc0rp"><img src="https://avatars.githubusercontent.com/u/2609441?v=4&s=48" width="48" height="48" alt="lc0rp" title="lc0rp"/></a> <a href="https://github.com/mousberg"><img src="https://avatars.githubusercontent.com/u/57605064?v=4&s=48" width="48" height="48" alt="mousberg" title="mousberg"/></a> <a href="https://github.com/adam91holt"><img src="https://avatars.githubusercontent.com/u/9592417?v=4&s=48" width="48" height="48" alt="adam91holt" title="adam91holt"/></a> <a href="https://github.com/hougangdev"><img src="https://avatars.githubusercontent.com/u/105773686?v=4&s=48" width="48" height="48" alt="hougangdev" title="hougangdev"/></a> <a href="https://github.com/gumadeiras"><img src="https://avatars.githubusercontent.com/u/5599352?v=4&s=48" width="48" height="48" alt="gumadeiras" title="gumadeiras"/></a> <a href="https://github.com/shakkernerd"><img src="https://avatars.githubusercontent.com/u/165377636?v=4&s=48" width="48" height="48" alt="shakkernerd" title="shakkernerd"/></a>
<a href="https://github.com/mteam88"><img src="https://avatars.githubusercontent.com/u/84196639?v=4&s=48" width="48" height="48" alt="mteam88" title="mteam88"/></a> <a href="https://github.com/hirefrank"><img src="https://avatars.githubusercontent.com/u/183158?v=4&s=48" width="48" height="48" alt="hirefrank" title="hirefrank"/></a> <a href="https://github.com/joeynyc"><img src="https://avatars.githubusercontent.com/u/17919866?v=4&s=48" width="48" height="48" alt="joeynyc" title="joeynyc"/></a> <a href="https://github.com/orlyjamie"><img src="https://avatars.githubusercontent.com/u/6668807?v=4&s=48" width="48" height="48" alt="orlyjamie" title="orlyjamie"/></a> <a href="https://github.com/dbhurley"><img src="https://avatars.githubusercontent.com/u/5251425?v=4&s=48" width="48" height="48" alt="dbhurley" title="dbhurley"/></a> <a href="https://github.com/omniwired"><img src="https://avatars.githubusercontent.com/u/322761?v=4&s=48" width="48" height="48" alt="Eng. Juan Combetto" title="Eng. Juan Combetto"/></a> <a href="https://github.com/TSavo"><img src="https://avatars.githubusercontent.com/u/877990?v=4&s=48" width="48" height="48" alt="TSavo" title="TSavo"/></a> <a href="https://github.com/aerolalit"><img src="https://avatars.githubusercontent.com/u/17166039?v=4&s=48" width="48" height="48" alt="aerolalit" title="aerolalit"/></a> <a href="https://github.com/julianengel"><img src="https://avatars.githubusercontent.com/u/10634231?v=4&s=48" width="48" height="48" alt="julianengel" title="julianengel"/></a> <a href="https://github.com/bradleypriest"><img src="https://avatars.githubusercontent.com/u/167215?v=4&s=48" width="48" height="48" alt="bradleypriest" title="bradleypriest"/></a>
<a href="https://github.com/benithors"><img src="https://avatars.githubusercontent.com/u/20652882?v=4&s=48" width="48" height="48" alt="benithors" title="benithors"/></a> <a href="https://github.com/rohannagpal"><img src="https://avatars.githubusercontent.com/u/4009239?v=4&s=48" width="48" height="48" alt="rohannagpal" title="rohannagpal"/></a> <a href="https://github.com/timolins"><img src="https://avatars.githubusercontent.com/u/1440854?v=4&s=48" width="48" height="48" alt="timolins" title="timolins"/></a> <a href="https://github.com/f-trycua"><img src="https://avatars.githubusercontent.com/u/195596869?v=4&s=48" width="48" height="48" alt="f-trycua" title="f-trycua"/></a> <a href="https://github.com/benostein"><img src="https://avatars.githubusercontent.com/u/31802821?v=4&s=48" width="48" height="48" alt="benostein" title="benostein"/></a> <a href="https://github.com/elliotsecops"><img src="https://avatars.githubusercontent.com/u/141947839?v=4&s=48" width="48" height="48" alt="elliotsecops" title="elliotsecops"/></a> <a href="https://github.com/christianklotz"><img src="https://avatars.githubusercontent.com/u/69443?v=4&s=48" width="48" height="48" alt="christianklotz" title="christianklotz"/></a> <a href="https://github.com/Nachx639"><img src="https://avatars.githubusercontent.com/u/71144023?v=4&s=48" width="48" height="48" alt="nachx639" title="nachx639"/></a> <a href="https://github.com/pvoo"><img src="https://avatars.githubusercontent.com/u/20116814?v=4&s=48" width="48" height="48" alt="pvoo" title="pvoo"/></a> <a href="https://github.com/sreekaransrinath"><img src="https://avatars.githubusercontent.com/u/50989977?v=4&s=48" width="48" height="48" alt="sreekaransrinath" title="sreekaransrinath"/></a>
<a href="https://github.com/gupsammy"><img src="https://avatars.githubusercontent.com/u/20296019?v=4&s=48" width="48" height="48" alt="gupsammy" title="gupsammy"/></a> <a href="https://github.com/cristip73"><img src="https://avatars.githubusercontent.com/u/24499421?v=4&s=48" width="48" height="48" alt="cristip73" title="cristip73"/></a> <a href="https://github.com/stefangalescu"><img src="https://avatars.githubusercontent.com/u/52995748?v=4&s=48" width="48" height="48" alt="stefangalescu" title="stefangalescu"/></a> <a href="https://github.com/nachoiacovino"><img src="https://avatars.githubusercontent.com/u/50103937?v=4&s=48" width="48" height="48" alt="nachoiacovino" title="nachoiacovino"/></a> <a href="https://github.com/vsabavat"><img src="https://avatars.githubusercontent.com/u/50385532?v=4&s=48" width="48" height="48" alt="Vasanth Rao Naik Sabavat" title="Vasanth Rao Naik Sabavat"/></a> <a href="https://github.com/petter-b"><img src="https://avatars.githubusercontent.com/u/62076402?v=4&s=48" width="48" height="48" alt="petter-b" title="petter-b"/></a> <a href="https://github.com/thewilloftheshadow"><img src="https://avatars.githubusercontent.com/u/35580099?v=4&s=48" width="48" height="48" alt="thewilloftheshadow" title="thewilloftheshadow"/></a> <a href="https://github.com/leszekszpunar"><img src="https://avatars.githubusercontent.com/u/13106764?v=4&s=48" width="48" height="48" alt="leszekszpunar" title="leszekszpunar"/></a> <a href="https://github.com/scald"><img src="https://avatars.githubusercontent.com/u/1215913?v=4&s=48" width="48" height="48" alt="scald" title="scald"/></a> <a href="https://github.com/andranik-sahakyan"><img src="https://avatars.githubusercontent.com/u/8908029?v=4&s=48" width="48" height="48" alt="andranik-sahakyan" title="andranik-sahakyan"/></a>
<a href="https://github.com/davidguttman"><img src="https://avatars.githubusercontent.com/u/431696?v=4&s=48" width="48" height="48" alt="davidguttman" title="davidguttman"/></a> <a href="https://github.com/sleontenko"><img src="https://avatars.githubusercontent.com/u/7135949?v=4&s=48" width="48" height="48" alt="sleontenko" title="sleontenko"/></a> <a href="https://github.com/denysvitali"><img src="https://avatars.githubusercontent.com/u/4939519?v=4&s=48" width="48" height="48" alt="denysvitali" title="denysvitali"/></a> <a href="https://github.com/sircrumpet"><img src="https://avatars.githubusercontent.com/u/4436535?v=4&s=48" width="48" height="48" alt="sircrumpet" title="sircrumpet"/></a> <a href="https://github.com/peschee"><img src="https://avatars.githubusercontent.com/u/63866?v=4&s=48" width="48" height="48" alt="peschee" title="peschee"/></a> <a href="https://github.com/nonggialiang"><img src="https://avatars.githubusercontent.com/u/14367839?v=4&s=48" width="48" height="48" alt="nonggialiang" title="nonggialiang"/></a> <a href="https://github.com/rafaelreis-r"><img src="https://avatars.githubusercontent.com/u/57492577?v=4&s=48" width="48" height="48" alt="rafaelreis-r" title="rafaelreis-r"/></a> <a href="https://github.com/dominicnunez"><img src="https://avatars.githubusercontent.com/u/43616264?v=4&s=48" width="48" height="48" alt="dominicnunez" title="dominicnunez"/></a> <a href="https://github.com/lploc94"><img src="https://avatars.githubusercontent.com/u/28453843?v=4&s=48" width="48" height="48" alt="lploc94" title="lploc94"/></a> <a href="https://github.com/ratulsarna"><img src="https://avatars.githubusercontent.com/u/105903728?v=4&s=48" width="48" height="48" alt="ratulsarna" title="ratulsarna"/></a>
<a href="https://github.com/sfo2001"><img src="https://avatars.githubusercontent.com/u/103369858?v=4&s=48" width="48" height="48" alt="sfo2001" title="sfo2001"/></a> <a href="https://github.com/lutr0"><img src="https://avatars.githubusercontent.com/u/76906369?v=4&s=48" width="48" height="48" alt="lutr0" title="lutr0"/></a> <a href="https://github.com/kiranjd"><img src="https://avatars.githubusercontent.com/u/25822851?v=4&s=48" width="48" height="48" alt="kiranjd" title="kiranjd"/></a> <a href="https://github.com/danielz1z"><img src="https://avatars.githubusercontent.com/u/235270390?v=4&s=48" width="48" height="48" alt="danielz1z" title="danielz1z"/></a> <a href="https://github.com/AdeboyeDN"><img src="https://avatars.githubusercontent.com/u/65312338?v=4&s=48" width="48" height="48" alt="AdeboyeDN" title="AdeboyeDN"/></a> <a href="https://github.com/Alg0rix"><img src="https://avatars.githubusercontent.com/u/53804949?v=4&s=48" width="48" height="48" alt="Alg0rix" title="Alg0rix"/></a> <a href="https://github.com/Takhoffman"><img src="https://avatars.githubusercontent.com/u/781889?v=4&s=48" width="48" height="48" alt="Takhoffman" title="Takhoffman"/></a> <a href="https://github.com/papago2355"><img src="https://avatars.githubusercontent.com/u/68721273?v=4&s=48" width="48" height="48" alt="papago2355" title="papago2355"/></a> <a href="https://github.com/apps/clawdinator"><img src="https://avatars.githubusercontent.com/in/2607181?v=4&s=48" width="48" height="48" alt="clawdinator[bot]" title="clawdinator[bot]"/></a> <a href="https://github.com/emanuelst"><img src="https://avatars.githubusercontent.com/u/9994339?v=4&s=48" width="48" height="48" alt="emanuelst" title="emanuelst"/></a>
<a href="https://github.com/evanotero"><img src="https://avatars.githubusercontent.com/u/13204105?v=4&s=48" width="48" height="48" alt="evanotero" title="evanotero"/></a> <a href="https://github.com/KristijanJovanovski"><img src="https://avatars.githubusercontent.com/u/8942284?v=4&s=48" width="48" height="48" alt="KristijanJovanovski" title="KristijanJovanovski"/></a> <a href="https://github.com/jlowin"><img src="https://avatars.githubusercontent.com/u/153965?v=4&s=48" width="48" height="48" alt="jlowin" title="jlowin"/></a> <a href="https://github.com/rdev"><img src="https://avatars.githubusercontent.com/u/8418866?v=4&s=48" width="48" height="48" alt="rdev" title="rdev"/></a> <a href="https://github.com/rhuanssauro"><img src="https://avatars.githubusercontent.com/u/164682191?v=4&s=48" width="48" height="48" alt="rhuanssauro" title="rhuanssauro"/></a> <a href="https://github.com/joshrad-dev"><img src="https://avatars.githubusercontent.com/u/62785552?v=4&s=48" width="48" height="48" alt="joshrad-dev" title="joshrad-dev"/></a> <a href="https://github.com/obviyus"><img src="https://avatars.githubusercontent.com/u/22031114?v=4&s=48" width="48" height="48" alt="obviyus" title="obviyus"/></a> <a href="https://github.com/osolmaz"><img src="https://avatars.githubusercontent.com/u/2453968?v=4&s=48" width="48" height="48" alt="osolmaz" title="osolmaz"/></a> <a href="https://github.com/adityashaw2"><img src="https://avatars.githubusercontent.com/u/41204444?v=4&s=48" width="48" height="48" alt="adityashaw2" title="adityashaw2"/></a> <a href="https://github.com/CashWilliams"><img src="https://avatars.githubusercontent.com/u/613573?v=4&s=48" width="48" height="48" alt="CashWilliams" title="CashWilliams"/></a>
<a href="https://github.com/search?q=sheeek"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="sheeek" title="sheeek"/></a> <a href="https://github.com/ryancontent"><img src="https://avatars.githubusercontent.com/u/39743613?v=4&s=48" width="48" height="48" alt="ryancontent" title="ryancontent"/></a> <a href="https://github.com/jasonsschin"><img src="https://avatars.githubusercontent.com/u/1456889?v=4&s=48" width="48" height="48" alt="jasonsschin" title="jasonsschin"/></a> <a href="https://github.com/artuskg"><img src="https://avatars.githubusercontent.com/u/11966157?v=4&s=48" width="48" height="48" alt="artuskg" title="artuskg"/></a> <a href="https://github.com/onutc"><img src="https://avatars.githubusercontent.com/u/152018508?v=4&s=48" width="48" height="48" alt="onutc" title="onutc"/></a> <a href="https://github.com/pauloportella"><img src="https://avatars.githubusercontent.com/u/22947229?v=4&s=48" width="48" height="48" alt="pauloportella" title="pauloportella"/></a> <a href="https://github.com/HirokiKobayashi-R"><img src="https://avatars.githubusercontent.com/u/37167840?v=4&s=48" width="48" height="48" alt="HirokiKobayashi-R" title="HirokiKobayashi-R"/></a> <a href="https://github.com/ThanhNguyxn"><img src="https://avatars.githubusercontent.com/u/74597207?v=4&s=48" width="48" height="48" alt="ThanhNguyxn" title="ThanhNguyxn"/></a> <a href="https://github.com/kimitaka"><img src="https://avatars.githubusercontent.com/u/167225?v=4&s=48" width="48" height="48" alt="kimitaka" title="kimitaka"/></a> <a href="https://github.com/yuting0624"><img src="https://avatars.githubusercontent.com/u/32728916?v=4&s=48" width="48" height="48" alt="yuting0624" title="yuting0624"/></a>
<a href="https://github.com/neooriginal"><img src="https://avatars.githubusercontent.com/u/54811660?v=4&s=48" width="48" height="48" alt="neooriginal" title="neooriginal"/></a> <a href="https://github.com/ManuelHettich"><img src="https://avatars.githubusercontent.com/u/17690367?v=4&s=48" width="48" height="48" alt="manuelhettich" title="manuelhettich"/></a> <a href="https://github.com/minghinmatthewlam"><img src="https://avatars.githubusercontent.com/u/14224566?v=4&s=48" width="48" height="48" alt="minghinmatthewlam" title="minghinmatthewlam"/></a> <a href="https://github.com/baccula"><img src="https://avatars.githubusercontent.com/u/22080883?v=4&s=48" width="48" height="48" alt="baccula" title="baccula"/></a> <a href="https://github.com/manikv12"><img src="https://avatars.githubusercontent.com/u/49544491?v=4&s=48" width="48" height="48" alt="manikv12" title="manikv12"/></a> <a href="https://github.com/myfunc"><img src="https://avatars.githubusercontent.com/u/19294627?v=4&s=48" width="48" height="48" alt="myfunc" title="myfunc"/></a> <a href="https://github.com/travisirby"><img src="https://avatars.githubusercontent.com/u/5958376?v=4&s=48" width="48" height="48" alt="travisirby" title="travisirby"/></a> <a href="https://github.com/buddyh"><img src="https://avatars.githubusercontent.com/u/31752869?v=4&s=48" width="48" height="48" alt="buddyh" title="buddyh"/></a> <a href="https://github.com/connorshea"><img src="https://avatars.githubusercontent.com/u/2977353?v=4&s=48" width="48" height="48" alt="connorshea" title="connorshea"/></a> <a href="https://github.com/kyleok"><img src="https://avatars.githubusercontent.com/u/58307870?v=4&s=48" width="48" height="48" alt="kyleok" title="kyleok"/></a>
<a href="https://github.com/mcinteerj"><img src="https://avatars.githubusercontent.com/u/3613653?v=4&s=48" width="48" height="48" alt="mcinteerj" title="mcinteerj"/></a> <a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4&s=48" width="48" height="48" alt="dependabot[bot]" title="dependabot[bot]"/></a> <a href="https://github.com/amitbiswal007"><img src="https://avatars.githubusercontent.com/u/108086198?v=4&s=48" width="48" height="48" alt="amitbiswal007" title="amitbiswal007"/></a> <a href="https://github.com/John-Rood"><img src="https://avatars.githubusercontent.com/u/62669593?v=4&s=48" width="48" height="48" alt="John-Rood" title="John-Rood"/></a> <a href="https://github.com/timkrase"><img src="https://avatars.githubusercontent.com/u/38947626?v=4&s=48" width="48" height="48" alt="timkrase" title="timkrase"/></a> <a href="https://github.com/uos-status"><img src="https://avatars.githubusercontent.com/u/255712580?v=4&s=48" width="48" height="48" alt="uos-status" title="uos-status"/></a> <a href="https://github.com/gerardward2007"><img src="https://avatars.githubusercontent.com/u/3002155?v=4&s=48" width="48" height="48" alt="gerardward2007" title="gerardward2007"/></a> <a href="https://github.com/roshanasingh4"><img src="https://avatars.githubusercontent.com/u/88576930?v=4&s=48" width="48" height="48" alt="roshanasingh4" title="roshanasingh4"/></a> <a href="https://github.com/tosh-hamburg"><img src="https://avatars.githubusercontent.com/u/58424326?v=4&s=48" width="48" height="48" alt="tosh-hamburg" title="tosh-hamburg"/></a> <a href="https://github.com/azade-c"><img src="https://avatars.githubusercontent.com/u/252790079?v=4&s=48" width="48" height="48" alt="azade-c" title="azade-c"/></a>
<a href="https://github.com/badlogic"><img src="https://avatars.githubusercontent.com/u/514052?v=4&s=48" width="48" height="48" alt="badlogic" title="badlogic"/></a> <a href="https://github.com/dlauer"><img src="https://avatars.githubusercontent.com/u/757041?v=4&s=48" width="48" height="48" alt="dlauer" title="dlauer"/></a> <a href="https://github.com/JonUleis"><img src="https://avatars.githubusercontent.com/u/7644941?v=4&s=48" width="48" height="48" alt="JonUleis" title="JonUleis"/></a> <a href="https://github.com/shivamraut101"><img src="https://avatars.githubusercontent.com/u/110457469?v=4&s=48" width="48" height="48" alt="shivamraut101" title="shivamraut101"/></a> <a href="https://github.com/bjesuiter"><img src="https://avatars.githubusercontent.com/u/2365676?v=4&s=48" width="48" height="48" alt="bjesuiter" title="bjesuiter"/></a> <a href="https://github.com/cheeeee"><img src="https://avatars.githubusercontent.com/u/21245729?v=4&s=48" width="48" height="48" alt="cheeeee" title="cheeeee"/></a> <a href="https://github.com/robbyczgw-cla"><img src="https://avatars.githubusercontent.com/u/239660374?v=4&s=48" width="48" height="48" alt="robbyczgw-cla" title="robbyczgw-cla"/></a> <a href="https://github.com/YuriNachos"><img src="https://avatars.githubusercontent.com/u/19365375?v=4&s=48" width="48" height="48" alt="YuriNachos" title="YuriNachos"/></a> <a href="https://github.com/j1philli"><img src="https://avatars.githubusercontent.com/u/3744255?v=4&s=48" width="48" height="48" alt="Josh Phillips" title="Josh Phillips"/></a> <a href="https://github.com/pookNast"><img src="https://avatars.githubusercontent.com/u/14242552?v=4&s=48" width="48" height="48" alt="pookNast" title="pookNast"/></a>
<a href="https://github.com/Whoaa512"><img src="https://avatars.githubusercontent.com/u/1581943?v=4&s=48" width="48" height="48" alt="Whoaa512" title="Whoaa512"/></a> <a href="https://github.com/chriseidhof"><img src="https://avatars.githubusercontent.com/u/5382?v=4&s=48" width="48" height="48" alt="chriseidhof" title="chriseidhof"/></a> <a href="https://github.com/ngutman"><img src="https://avatars.githubusercontent.com/u/1540134?v=4&s=48" width="48" height="48" alt="ngutman" title="ngutman"/></a> <a href="https://github.com/ysqander"><img src="https://avatars.githubusercontent.com/u/80843820?v=4&s=48" width="48" height="48" alt="ysqander" title="ysqander"/></a> <a href="https://github.com/search?q=Yurii%20Chukhlib"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Yurii Chukhlib" title="Yurii Chukhlib"/></a> <a href="https://github.com/aj47"><img src="https://avatars.githubusercontent.com/u/8023513?v=4&s=48" width="48" height="48" alt="aj47" title="aj47"/></a> <a href="https://github.com/kennyklee"><img src="https://avatars.githubusercontent.com/u/1432489?v=4&s=48" width="48" height="48" alt="kennyklee" title="kennyklee"/></a> <a href="https://github.com/superman32432432"><img src="https://avatars.githubusercontent.com/u/7228420?v=4&s=48" width="48" height="48" alt="superman32432432" title="superman32432432"/></a> <a href="https://github.com/grp06"><img src="https://avatars.githubusercontent.com/u/1573959?v=4&s=48" width="48" height="48" alt="grp06" title="grp06"/></a> <a href="https://github.com/Hisleren"><img src="https://avatars.githubusercontent.com/u/83217244?v=4&s=48" width="48" height="48" alt="Hisleren" title="Hisleren"/></a>
<a href="https://github.com/shatner"><img src="https://avatars.githubusercontent.com/u/17735435?v=4&s=48" width="48" height="48" alt="shatner" title="shatner"/></a> <a href="https://github.com/antons"><img src="https://avatars.githubusercontent.com/u/129705?v=4&s=48" width="48" height="48" alt="antons" title="antons"/></a> <a href="https://github.com/austinm911"><img src="https://avatars.githubusercontent.com/u/31991302?v=4&s=48" width="48" height="48" alt="austinm911" title="austinm911"/></a> <a href="https://github.com/apps/blacksmith-sh"><img src="https://avatars.githubusercontent.com/in/807020?v=4&s=48" width="48" height="48" alt="blacksmith-sh[bot]" title="blacksmith-sh[bot]"/></a> <a href="https://github.com/damoahdominic"><img src="https://avatars.githubusercontent.com/u/4623434?v=4&s=48" width="48" height="48" alt="damoahdominic" title="damoahdominic"/></a> <a href="https://github.com/dan-dr"><img src="https://avatars.githubusercontent.com/u/6669808?v=4&s=48" width="48" height="48" alt="dan-dr" title="dan-dr"/></a> <a href="https://github.com/GHesericsu"><img src="https://avatars.githubusercontent.com/u/60202455?v=4&s=48" width="48" height="48" alt="GHesericsu" title="GHesericsu"/></a> <a href="https://github.com/HeimdallStrategy"><img src="https://avatars.githubusercontent.com/u/223014405?v=4&s=48" width="48" height="48" alt="HeimdallStrategy" title="HeimdallStrategy"/></a> <a href="https://github.com/imfing"><img src="https://avatars.githubusercontent.com/u/5097752?v=4&s=48" width="48" height="48" alt="imfing" title="imfing"/></a> <a href="https://github.com/jalehman"><img src="https://avatars.githubusercontent.com/u/550978?v=4&s=48" width="48" height="48" alt="jalehman" title="jalehman"/></a>
<a href="https://github.com/jarvis-medmatic"><img src="https://avatars.githubusercontent.com/u/252428873?v=4&s=48" width="48" height="48" alt="jarvis-medmatic" title="jarvis-medmatic"/></a> <a href="https://github.com/kkarimi"><img src="https://avatars.githubusercontent.com/u/875218?v=4&s=48" width="48" height="48" alt="kkarimi" title="kkarimi"/></a> <a href="https://github.com/mahmoudashraf93"><img src="https://avatars.githubusercontent.com/u/9130129?v=4&s=48" width="48" height="48" alt="mahmoudashraf93" title="mahmoudashraf93"/></a> <a href="https://github.com/pkrmf"><img src="https://avatars.githubusercontent.com/u/1714267?v=4&s=48" width="48" height="48" alt="pkrmf" title="pkrmf"/></a> <a href="https://github.com/RandyVentures"><img src="https://avatars.githubusercontent.com/u/149904821?v=4&s=48" width="48" height="48" alt="RandyVentures" title="RandyVentures"/></a> <a href="https://github.com/robhparker"><img src="https://avatars.githubusercontent.com/u/7404740?v=4&s=48" width="48" height="48" alt="robhparker" title="robhparker"/></a> <a href="https://github.com/search?q=Ryan%20Lisse"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ryan Lisse" title="Ryan Lisse"/></a> <a href="https://github.com/dougvk"><img src="https://avatars.githubusercontent.com/u/401660?v=4&s=48" width="48" height="48" alt="dougvk" title="dougvk"/></a> <a href="https://github.com/erikpr1994"><img src="https://avatars.githubusercontent.com/u/6299331?v=4&s=48" width="48" height="48" alt="erikpr1994" title="erikpr1994"/></a> <a href="https://github.com/fal3"><img src="https://avatars.githubusercontent.com/u/6484295?v=4&s=48" width="48" height="48" alt="fal3" title="fal3"/></a>
<a href="https://github.com/search?q=Ghost"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ghost" title="Ghost"/></a> <a href="https://github.com/jonasjancarik"><img src="https://avatars.githubusercontent.com/u/2459191?v=4&s=48" width="48" height="48" alt="jonasjancarik" title="jonasjancarik"/></a> <a href="https://github.com/search?q=Keith%20the%20Silly%20Goose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Keith the Silly Goose" title="Keith the Silly Goose"/></a> <a href="https://github.com/search?q=L36%20Server"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="L36 Server" title="L36 Server"/></a> <a href="https://github.com/search?q=Marc"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Marc" title="Marc"/></a> <a href="https://github.com/mitschabaude-bot"><img src="https://avatars.githubusercontent.com/u/247582884?v=4&s=48" width="48" height="48" alt="mitschabaude-bot" title="mitschabaude-bot"/></a> <a href="https://github.com/mkbehr"><img src="https://avatars.githubusercontent.com/u/1285?v=4&s=48" width="48" height="48" alt="mkbehr" title="mkbehr"/></a> <a href="https://github.com/neist"><img src="https://avatars.githubusercontent.com/u/1029724?v=4&s=48" width="48" height="48" alt="neist" title="neist"/></a> <a href="https://github.com/sibbl"><img src="https://avatars.githubusercontent.com/u/866535?v=4&s=48" width="48" height="48" alt="sibbl" title="sibbl"/></a> <a href="https://github.com/abhijeet117"><img src="https://avatars.githubusercontent.com/u/192859219?v=4&s=48" width="48" height="48" alt="abhijeet117" title="abhijeet117"/></a>
<a href="https://github.com/chrisrodz"><img src="https://avatars.githubusercontent.com/u/2967620?v=4&s=48" width="48" height="48" alt="chrisrodz" title="chrisrodz"/></a> <a href="https://github.com/search?q=Friederike%20Seiler"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Friederike Seiler" title="Friederike Seiler"/></a> <a href="https://github.com/gabriel-trigo"><img src="https://avatars.githubusercontent.com/u/38991125?v=4&s=48" width="48" height="48" alt="gabriel-trigo" title="gabriel-trigo"/></a> <a href="https://github.com/Iamadig"><img src="https://avatars.githubusercontent.com/u/102129234?v=4&s=48" width="48" height="48" alt="iamadig" title="iamadig"/></a> <a href="https://github.com/itsjling"><img src="https://avatars.githubusercontent.com/u/2521993?v=4&s=48" width="48" height="48" alt="itsjling" title="itsjling"/></a> <a href="https://github.com/jdrhyne"><img src="https://avatars.githubusercontent.com/u/7828464?v=4&s=48" width="48" height="48" alt="Jonathan D. Rhyne (DJ-D)" title="Jonathan D. Rhyne (DJ-D)"/></a> <a href="https://github.com/search?q=Joshua%20Mitchell"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Joshua Mitchell" title="Joshua Mitchell"/></a> <a href="https://github.com/search?q=Kit"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kit" title="Kit"/></a> <a href="https://github.com/koala73"><img src="https://avatars.githubusercontent.com/u/996596?v=4&s=48" width="48" height="48" alt="koala73" title="koala73"/></a> <a href="https://github.com/manmal"><img src="https://avatars.githubusercontent.com/u/142797?v=4&s=48" width="48" height="48" alt="manmal" title="manmal"/></a>
<a href="https://github.com/ogulcancelik"><img src="https://avatars.githubusercontent.com/u/7064011?v=4&s=48" width="48" height="48" alt="ogulcancelik" title="ogulcancelik"/></a> <a href="https://github.com/pasogott"><img src="https://avatars.githubusercontent.com/u/23458152?v=4&s=48" width="48" height="48" alt="pasogott" title="pasogott"/></a> <a href="https://github.com/petradonka"><img src="https://avatars.githubusercontent.com/u/7353770?v=4&s=48" width="48" height="48" alt="petradonka" title="petradonka"/></a> <a href="https://github.com/rubyrunsstuff"><img src="https://avatars.githubusercontent.com/u/246602379?v=4&s=48" width="48" height="48" alt="rubyrunsstuff" title="rubyrunsstuff"/></a> <a href="https://github.com/siddhantjain"><img src="https://avatars.githubusercontent.com/u/4835232?v=4&s=48" width="48" height="48" alt="siddhantjain" title="siddhantjain"/></a> <a href="https://github.com/spiceoogway"><img src="https://avatars.githubusercontent.com/u/105812383?v=4&s=48" width="48" height="48" alt="spiceoogway" title="spiceoogway"/></a> <a href="https://github.com/suminhthanh"><img src="https://avatars.githubusercontent.com/u/2907636?v=4&s=48" width="48" height="48" alt="suminhthanh" title="suminhthanh"/></a> <a href="https://github.com/svkozak"><img src="https://avatars.githubusercontent.com/u/31941359?v=4&s=48" width="48" height="48" alt="svkozak" title="svkozak"/></a> <a href="https://github.com/wes-davis"><img src="https://avatars.githubusercontent.com/u/16506720?v=4&s=48" width="48" height="48" alt="wes-davis" title="wes-davis"/></a> <a href="https://github.com/zats"><img src="https://avatars.githubusercontent.com/u/2688806?v=4&s=48" width="48" height="48" alt="zats" title="zats"/></a>
<a href="https://github.com/24601"><img src="https://avatars.githubusercontent.com/u/1157207?v=4&s=48" width="48" height="48" alt="24601" title="24601"/></a> <a href="https://github.com/ameno-"><img src="https://avatars.githubusercontent.com/u/2416135?v=4&s=48" width="48" height="48" alt="ameno-" title="ameno-"/></a> <a href="https://github.com/bonald"><img src="https://avatars.githubusercontent.com/u/12394874?v=4&s=48" width="48" height="48" alt="bonald" title="bonald"/></a> <a href="https://github.com/bravostation"><img src="https://avatars.githubusercontent.com/u/257991910?v=4&s=48" width="48" height="48" alt="bravostation" title="bravostation"/></a> <a href="https://github.com/search?q=Chris%20Taylor"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Chris Taylor" title="Chris Taylor"/></a> <a href="https://github.com/dguido"><img src="https://avatars.githubusercontent.com/u/294844?v=4&s=48" width="48" height="48" alt="dguido" title="dguido"/></a> <a href="https://github.com/djangonavarro220"><img src="https://avatars.githubusercontent.com/u/251162586?v=4&s=48" width="48" height="48" alt="Django Navarro" title="Django Navarro"/></a> <a href="https://github.com/evalexpr"><img src="https://avatars.githubusercontent.com/u/23485511?v=4&s=48" width="48" height="48" alt="evalexpr" title="evalexpr"/></a> <a href="https://github.com/henrino3"><img src="https://avatars.githubusercontent.com/u/4260288?v=4&s=48" width="48" height="48" alt="henrino3" title="henrino3"/></a> <a href="https://github.com/humanwritten"><img src="https://avatars.githubusercontent.com/u/206531610?v=4&s=48" width="48" height="48" alt="humanwritten" title="humanwritten"/></a>
<a href="https://github.com/larlyssa"><img src="https://avatars.githubusercontent.com/u/13128869?v=4&s=48" width="48" height="48" alt="larlyssa" title="larlyssa"/></a> <a href="https://github.com/Lukavyi"><img src="https://avatars.githubusercontent.com/u/1013690?v=4&s=48" width="48" height="48" alt="Lukavyi" title="Lukavyi"/></a> <a href="https://github.com/mitsuhiko"><img src="https://avatars.githubusercontent.com/u/7396?v=4&s=48" width="48" height="48" alt="mitsuhiko" title="mitsuhiko"/></a> <a href="https://github.com/odysseus0"><img src="https://avatars.githubusercontent.com/u/8635094?v=4&s=48" width="48" height="48" alt="odysseus0" title="odysseus0"/></a> <a href="https://github.com/oswalpalash"><img src="https://avatars.githubusercontent.com/u/6431196?v=4&s=48" width="48" height="48" alt="oswalpalash" title="oswalpalash"/></a> <a href="https://github.com/pcty-nextgen-service-account"><img src="https://avatars.githubusercontent.com/u/112553441?v=4&s=48" width="48" height="48" alt="pcty-nextgen-service-account" title="pcty-nextgen-service-account"/></a> <a href="https://github.com/pi0"><img src="https://avatars.githubusercontent.com/u/5158436?v=4&s=48" width="48" height="48" alt="pi0" title="pi0"/></a> <a href="https://github.com/rmorse"><img src="https://avatars.githubusercontent.com/u/853547?v=4&s=48" width="48" height="48" alt="rmorse" title="rmorse"/></a> <a href="https://github.com/search?q=Roopak%20Nijhara"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Roopak Nijhara" title="Roopak Nijhara"/></a> <a href="https://github.com/Syhids"><img src="https://avatars.githubusercontent.com/u/671202?v=4&s=48" width="48" height="48" alt="Syhids" title="Syhids"/></a>
<a href="https://github.com/search?q=Ubuntu"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ubuntu" title="Ubuntu"/></a> <a href="https://github.com/search?q=xiaose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="xiaose" title="xiaose"/></a> <a href="https://github.com/search?q=Aaron%20Konyer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Aaron Konyer" title="Aaron Konyer"/></a> <a href="https://github.com/aaronveklabs"><img src="https://avatars.githubusercontent.com/u/225997828?v=4&s=48" width="48" height="48" alt="aaronveklabs" title="aaronveklabs"/></a> <a href="https://github.com/andreabadesso"><img src="https://avatars.githubusercontent.com/u/3586068?v=4&s=48" width="48" height="48" alt="andreabadesso" title="andreabadesso"/></a> <a href="https://github.com/search?q=Andrii"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Andrii" title="Andrii"/></a> <a href="https://github.com/cash-echo-bot"><img src="https://avatars.githubusercontent.com/u/252747386?v=4&s=48" width="48" height="48" alt="cash-echo-bot" title="cash-echo-bot"/></a> <a href="https://github.com/search?q=Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawd" title="Clawd"/></a> <a href="https://github.com/search?q=ClawdFx"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ClawdFx" title="ClawdFx"/></a> <a href="https://github.com/danballance"><img src="https://avatars.githubusercontent.com/u/13839912?v=4&s=48" width="48" height="48" alt="danballance" title="danballance"/></a>
<a href="https://github.com/EnzeD"><img src="https://avatars.githubusercontent.com/u/9866900?v=4&s=48" width="48" height="48" alt="EnzeD" title="EnzeD"/></a> <a href="https://github.com/erik-agens"><img src="https://avatars.githubusercontent.com/u/80908960?v=4&s=48" width="48" height="48" alt="erik-agens" title="erik-agens"/></a> <a href="https://github.com/Evizero"><img src="https://avatars.githubusercontent.com/u/10854026?v=4&s=48" width="48" height="48" alt="Evizero" title="Evizero"/></a> <a href="https://github.com/fcatuhe"><img src="https://avatars.githubusercontent.com/u/17382215?v=4&s=48" width="48" height="48" alt="fcatuhe" title="fcatuhe"/></a> <a href="https://github.com/itsjaydesu"><img src="https://avatars.githubusercontent.com/u/220390?v=4&s=48" width="48" height="48" alt="itsjaydesu" title="itsjaydesu"/></a> <a href="https://github.com/ivancasco"><img src="https://avatars.githubusercontent.com/u/2452858?v=4&s=48" width="48" height="48" alt="ivancasco" title="ivancasco"/></a> <a href="https://github.com/ivanrvpereira"><img src="https://avatars.githubusercontent.com/u/183991?v=4&s=48" width="48" height="48" alt="ivanrvpereira" title="ivanrvpereira"/></a> <a href="https://github.com/search?q=Jarvis"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis" title="Jarvis"/></a> <a href="https://github.com/jayhickey"><img src="https://avatars.githubusercontent.com/u/1676460?v=4&s=48" width="48" height="48" alt="jayhickey" title="jayhickey"/></a> <a href="https://github.com/jeffersonwarrior"><img src="https://avatars.githubusercontent.com/u/89030989?v=4&s=48" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a>
<a href="https://github.com/search?q=jeffersonwarrior"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/jverdi"><img src="https://avatars.githubusercontent.com/u/345050?v=4&s=48" width="48" height="48" alt="jverdi" title="jverdi"/></a> <a href="https://github.com/longmaba"><img src="https://avatars.githubusercontent.com/u/9361500?v=4&s=48" width="48" height="48" alt="longmaba" title="longmaba"/></a> <a href="https://github.com/MarvinCui"><img src="https://avatars.githubusercontent.com/u/130876763?v=4&s=48" width="48" height="48" alt="MarvinCui" title="MarvinCui"/></a> <a href="https://github.com/mjrussell"><img src="https://avatars.githubusercontent.com/u/1641895?v=4&s=48" width="48" height="48" alt="mjrussell" title="mjrussell"/></a> <a href="https://github.com/odnxe"><img src="https://avatars.githubusercontent.com/u/403141?v=4&s=48" width="48" height="48" alt="odnxe" title="odnxe"/></a> <a href="https://github.com/optimikelabs"><img src="https://avatars.githubusercontent.com/u/31423109?v=4&s=48" width="48" height="48" alt="optimikelabs" title="optimikelabs"/></a> <a href="https://github.com/p6l-richard"><img src="https://avatars.githubusercontent.com/u/18185649?v=4&s=48" width="48" height="48" alt="p6l-richard" title="p6l-richard"/></a> <a href="https://github.com/philipp-spiess"><img src="https://avatars.githubusercontent.com/u/458591?v=4&s=48" width="48" height="48" alt="philipp-spiess" title="philipp-spiess"/></a> <a href="https://github.com/search?q=Pocket%20Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Pocket Clawd" title="Pocket Clawd"/></a>
<a href="https://github.com/robaxelsen"><img src="https://avatars.githubusercontent.com/u/13132899?v=4&s=48" width="48" height="48" alt="robaxelsen" title="robaxelsen"/></a> <a href="https://github.com/search?q=Sash%20Catanzarite"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Sash Catanzarite" title="Sash Catanzarite"/></a> <a href="https://github.com/Suksham-sharma"><img src="https://avatars.githubusercontent.com/u/94667656?v=4&s=48" width="48" height="48" alt="Suksham-sharma" title="Suksham-sharma"/></a> <a href="https://github.com/T5-AndyML"><img src="https://avatars.githubusercontent.com/u/22801233?v=4&s=48" width="48" height="48" alt="T5-AndyML" title="T5-AndyML"/></a> <a href="https://github.com/tewatia"><img src="https://avatars.githubusercontent.com/u/22875334?v=4&s=48" width="48" height="48" alt="tewatia" title="tewatia"/></a> <a href="https://github.com/thejhinvirtuoso"><img src="https://avatars.githubusercontent.com/u/258521837?v=4&s=48" width="48" height="48" alt="thejhinvirtuoso" title="thejhinvirtuoso"/></a> <a href="https://github.com/travisp"><img src="https://avatars.githubusercontent.com/u/165698?v=4&s=48" width="48" height="48" alt="travisp" title="travisp"/></a> <a href="https://github.com/search?q=VAC"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="VAC" title="VAC"/></a> <a href="https://github.com/search?q=william%20arzt"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="william arzt" title="william arzt"/></a> <a href="https://github.com/zknicker"><img src="https://avatars.githubusercontent.com/u/1164085?v=4&s=48" width="48" height="48" alt="zknicker" title="zknicker"/></a>
<a href="https://github.com/0oAstro"><img src="https://avatars.githubusercontent.com/u/79555780?v=4&s=48" width="48" height="48" alt="0oAstro" title="0oAstro"/></a> <a href="https://github.com/abhaymundhara"><img src="https://avatars.githubusercontent.com/u/62872231?v=4&s=48" width="48" height="48" alt="abhaymundhara" title="abhaymundhara"/></a> <a href="https://github.com/aduk059"><img src="https://avatars.githubusercontent.com/u/257603478?v=4&s=48" width="48" height="48" alt="aduk059" title="aduk059"/></a> <a href="https://github.com/aldoeliacim"><img src="https://avatars.githubusercontent.com/u/17973757?v=4&s=48" width="48" height="48" alt="aldoeliacim" title="aldoeliacim"/></a> <a href="https://github.com/search?q=alejandro%20maza"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="alejandro maza" title="alejandro maza"/></a> <a href="https://github.com/Alex-Alaniz"><img src="https://avatars.githubusercontent.com/u/88956822?v=4&s=48" width="48" height="48" alt="Alex-Alaniz" title="Alex-Alaniz"/></a> <a href="https://github.com/alexanderatallah"><img src="https://avatars.githubusercontent.com/u/1011391?v=4&s=48" width="48" height="48" alt="alexanderatallah" title="alexanderatallah"/></a> <a href="https://github.com/alexstyl"><img src="https://avatars.githubusercontent.com/u/1665273?v=4&s=48" width="48" height="48" alt="alexstyl" title="alexstyl"/></a> <a href="https://github.com/andrewting19"><img src="https://avatars.githubusercontent.com/u/10536704?v=4&s=48" width="48" height="48" alt="andrewting19" title="andrewting19"/></a> <a href="https://github.com/anpoirier"><img src="https://avatars.githubusercontent.com/u/1245729?v=4&s=48" width="48" height="48" alt="anpoirier" title="anpoirier"/></a>
<a href="https://github.com/araa47"><img src="https://avatars.githubusercontent.com/u/22760261?v=4&s=48" width="48" height="48" alt="araa47" title="araa47"/></a> <a href="https://github.com/arthyn"><img src="https://avatars.githubusercontent.com/u/5466421?v=4&s=48" width="48" height="48" alt="arthyn" title="arthyn"/></a> <a href="https://github.com/Asleep123"><img src="https://avatars.githubusercontent.com/u/122379135?v=4&s=48" width="48" height="48" alt="Asleep123" title="Asleep123"/></a> <a href="https://github.com/search?q=Ayush%20Ojha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ayush Ojha" title="Ayush Ojha"/></a> <a href="https://github.com/Ayush10"><img src="https://avatars.githubusercontent.com/u/7945279?v=4&s=48" width="48" height="48" alt="Ayush10" title="Ayush10"/></a> <a href="https://github.com/bguidolim"><img src="https://avatars.githubusercontent.com/u/987360?v=4&s=48" width="48" height="48" alt="bguidolim" title="bguidolim"/></a> <a href="https://github.com/bolismauro"><img src="https://avatars.githubusercontent.com/u/771999?v=4&s=48" width="48" height="48" alt="bolismauro" title="bolismauro"/></a> <a href="https://github.com/championswimmer"><img src="https://avatars.githubusercontent.com/u/1327050?v=4&s=48" width="48" height="48" alt="championswimmer" title="championswimmer"/></a> <a href="https://github.com/chenyuan99"><img src="https://avatars.githubusercontent.com/u/25518100?v=4&s=48" width="48" height="48" alt="chenyuan99" title="chenyuan99"/></a> <a href="https://github.com/Chloe-VP"><img src="https://avatars.githubusercontent.com/u/257371598?v=4&s=48" width="48" height="48" alt="Chloe-VP" title="Chloe-VP"/></a>
<a href="https://github.com/search?q=Clawdbot%20Maintainers"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawdbot Maintainers" title="Clawdbot Maintainers"/></a> <a href="https://github.com/conhecendoia"><img src="https://avatars.githubusercontent.com/u/82890727?v=4&s=48" width="48" height="48" alt="conhecendoia" title="conhecendoia"/></a> <a href="https://github.com/dasilva333"><img src="https://avatars.githubusercontent.com/u/947827?v=4&s=48" width="48" height="48" alt="dasilva333" title="dasilva333"/></a> <a href="https://github.com/David-Marsh-Photo"><img src="https://avatars.githubusercontent.com/u/228404527?v=4&s=48" width="48" height="48" alt="David-Marsh-Photo" title="David-Marsh-Photo"/></a> <a href="https://github.com/search?q=Developer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Developer" title="Developer"/></a> <a href="https://github.com/search?q=Dimitrios%20Ploutarchos"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Dimitrios Ploutarchos" title="Dimitrios Ploutarchos"/></a> <a href="https://github.com/search?q=Drake%20Thomsen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Drake Thomsen" title="Drake Thomsen"/></a> <a href="https://github.com/dylanneve1"><img src="https://avatars.githubusercontent.com/u/31746704?v=4&s=48" width="48" height="48" alt="dylanneve1" title="dylanneve1"/></a> <a href="https://github.com/search?q=Felix%20Krause"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Felix Krause" title="Felix Krause"/></a> <a href="https://github.com/foeken"><img src="https://avatars.githubusercontent.com/u/13864?v=4&s=48" width="48" height="48" alt="foeken" title="foeken"/></a>
<a href="https://github.com/frankekn"><img src="https://avatars.githubusercontent.com/u/4488090?v=4&s=48" width="48" height="48" alt="frankekn" title="frankekn"/></a> <a href="https://github.com/fredheir"><img src="https://avatars.githubusercontent.com/u/3304869?v=4&s=48" width="48" height="48" alt="fredheir" title="fredheir"/></a> <a href="https://github.com/search?q=ganghyun%20kim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ganghyun kim" title="ganghyun kim"/></a> <a href="https://github.com/grrowl"><img src="https://avatars.githubusercontent.com/u/907140?v=4&s=48" width="48" height="48" alt="grrowl" title="grrowl"/></a> <a href="https://github.com/gtsifrikas"><img src="https://avatars.githubusercontent.com/u/8904378?v=4&s=48" width="48" height="48" alt="gtsifrikas" title="gtsifrikas"/></a> <a href="https://github.com/HassanFleyah"><img src="https://avatars.githubusercontent.com/u/228002017?v=4&s=48" width="48" height="48" alt="HassanFleyah" title="HassanFleyah"/></a> <a href="https://github.com/HazAT"><img src="https://avatars.githubusercontent.com/u/363802?v=4&s=48" width="48" height="48" alt="HazAT" title="HazAT"/></a> <a href="https://github.com/hclsys"><img src="https://avatars.githubusercontent.com/u/7755017?v=4&s=48" width="48" height="48" alt="hclsys" title="hclsys"/></a> <a href="https://github.com/hrdwdmrbl"><img src="https://avatars.githubusercontent.com/u/554881?v=4&s=48" width="48" height="48" alt="hrdwdmrbl" title="hrdwdmrbl"/></a> <a href="https://github.com/hugobarauna"><img src="https://avatars.githubusercontent.com/u/2719?v=4&s=48" width="48" height="48" alt="hugobarauna" title="hugobarauna"/></a>
<a href="https://github.com/iamEvanYT"><img src="https://avatars.githubusercontent.com/u/47493765?v=4&s=48" width="48" height="48" alt="iamEvanYT" title="iamEvanYT"/></a> <a href="https://github.com/search?q=Jamie%20Openshaw"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jamie Openshaw" title="Jamie Openshaw"/></a> <a href="https://github.com/search?q=Jane"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jane" title="Jane"/></a> <a href="https://github.com/search?q=Jarvis%20Deploy"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis Deploy" title="Jarvis Deploy"/></a> <a href="https://github.com/search?q=Jefferson%20Nunn"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jefferson Nunn" title="Jefferson Nunn"/></a> <a href="https://github.com/jogi47"><img src="https://avatars.githubusercontent.com/u/1710139?v=4&s=48" width="48" height="48" alt="jogi47" title="jogi47"/></a> <a href="https://github.com/kentaro"><img src="https://avatars.githubusercontent.com/u/3458?v=4&s=48" width="48" height="48" alt="kentaro" title="kentaro"/></a> <a href="https://github.com/search?q=Kevin%20Lin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kevin Lin" title="Kevin Lin"/></a> <a href="https://github.com/kira-ariaki"><img src="https://avatars.githubusercontent.com/u/257352493?v=4&s=48" width="48" height="48" alt="kira-ariaki" title="kira-ariaki"/></a> <a href="https://github.com/kitze"><img src="https://avatars.githubusercontent.com/u/1160594?v=4&s=48" width="48" height="48" alt="kitze" title="kitze"/></a>
<a href="https://github.com/Kiwitwitter"><img src="https://avatars.githubusercontent.com/u/25277769?v=4&s=48" width="48" height="48" alt="Kiwitwitter" title="Kiwitwitter"/></a> <a href="https://github.com/levifig"><img src="https://avatars.githubusercontent.com/u/1605?v=4&s=48" width="48" height="48" alt="levifig" title="levifig"/></a> <a href="https://github.com/search?q=Lloyd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Lloyd" title="Lloyd"/></a> <a href="https://github.com/loganaden"><img src="https://avatars.githubusercontent.com/u/1688420?v=4&s=48" width="48" height="48" alt="loganaden" title="loganaden"/></a> <a href="https://github.com/longjos"><img src="https://avatars.githubusercontent.com/u/740160?v=4&s=48" width="48" height="48" alt="longjos" title="longjos"/></a> <a href="https://github.com/loukotal"><img src="https://avatars.githubusercontent.com/u/18210858?v=4&s=48" width="48" height="48" alt="loukotal" title="loukotal"/></a> <a href="https://github.com/louzhixian"><img src="https://avatars.githubusercontent.com/u/7994361?v=4&s=48" width="48" height="48" alt="louzhixian" title="louzhixian"/></a> <a href="https://github.com/martinpucik"><img src="https://avatars.githubusercontent.com/u/5503097?v=4&s=48" width="48" height="48" alt="martinpucik" title="martinpucik"/></a> <a href="https://github.com/search?q=Matt%20mini"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Matt mini" title="Matt mini"/></a> <a href="https://github.com/mertcicekci0"><img src="https://avatars.githubusercontent.com/u/179321902?v=4&s=48" width="48" height="48" alt="mertcicekci0" title="mertcicekci0"/></a>
<a href="https://github.com/search?q=Miles"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Miles" title="Miles"/></a> <a href="https://github.com/mrdbstn"><img src="https://avatars.githubusercontent.com/u/58957632?v=4&s=48" width="48" height="48" alt="mrdbstn" title="mrdbstn"/></a> <a href="https://github.com/MSch"><img src="https://avatars.githubusercontent.com/u/7475?v=4&s=48" width="48" height="48" alt="MSch" title="MSch"/></a> <a href="https://github.com/search?q=Mustafa%20Tag%20Eldeen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mustafa Tag Eldeen" title="Mustafa Tag Eldeen"/></a> <a href="https://github.com/mylukin"><img src="https://avatars.githubusercontent.com/u/1021019?v=4&s=48" width="48" height="48" alt="mylukin" title="mylukin"/></a> <a href="https://github.com/nathanbosse"><img src="https://avatars.githubusercontent.com/u/4040669?v=4&s=48" width="48" height="48" alt="nathanbosse" title="nathanbosse"/></a> <a href="https://github.com/ndraiman"><img src="https://avatars.githubusercontent.com/u/12609607?v=4&s=48" width="48" height="48" alt="ndraiman" title="ndraiman"/></a> <a href="https://github.com/nexty5870"><img src="https://avatars.githubusercontent.com/u/3869659?v=4&s=48" width="48" height="48" alt="nexty5870" title="nexty5870"/></a> <a href="https://github.com/Noctivoro"><img src="https://avatars.githubusercontent.com/u/183974570?v=4&s=48" width="48" height="48" alt="Noctivoro" title="Noctivoro"/></a> <a href="https://github.com/ozgur-polat"><img src="https://avatars.githubusercontent.com/u/26483942?v=4&s=48" width="48" height="48" alt="ozgur-polat" title="ozgur-polat"/></a>
<a href="https://github.com/ppamment"><img src="https://avatars.githubusercontent.com/u/2122919?v=4&s=48" width="48" height="48" alt="ppamment" title="ppamment"/></a> <a href="https://github.com/prathamdby"><img src="https://avatars.githubusercontent.com/u/134331217?v=4&s=48" width="48" height="48" alt="prathamdby" title="prathamdby"/></a> <a href="https://github.com/ptn1411"><img src="https://avatars.githubusercontent.com/u/57529765?v=4&s=48" width="48" height="48" alt="ptn1411" title="ptn1411"/></a> <a href="https://github.com/reeltimeapps"><img src="https://avatars.githubusercontent.com/u/637338?v=4&s=48" width="48" height="48" alt="reeltimeapps" title="reeltimeapps"/></a> <a href="https://github.com/RLTCmpe"><img src="https://avatars.githubusercontent.com/u/10762242?v=4&s=48" width="48" height="48" alt="RLTCmpe" title="RLTCmpe"/></a> <a href="https://github.com/search?q=Rony%20Kelner"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rony Kelner" title="Rony Kelner"/></a> <a href="https://github.com/ryancnelson"><img src="https://avatars.githubusercontent.com/u/347171?v=4&s=48" width="48" height="48" alt="ryancnelson" title="ryancnelson"/></a> <a href="https://github.com/search?q=Samrat%20Jha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Samrat Jha" title="Samrat Jha"/></a> <a href="https://github.com/senoldogann"><img src="https://avatars.githubusercontent.com/u/45736551?v=4&s=48" width="48" height="48" alt="senoldogann" title="senoldogann"/></a> <a href="https://github.com/Seredeep"><img src="https://avatars.githubusercontent.com/u/22802816?v=4&s=48" width="48" height="48" alt="Seredeep" title="Seredeep"/></a>
<a href="https://github.com/sergical"><img src="https://avatars.githubusercontent.com/u/3760543?v=4&s=48" width="48" height="48" alt="sergical" title="sergical"/></a> <a href="https://github.com/shiv19"><img src="https://avatars.githubusercontent.com/u/9407019?v=4&s=48" width="48" height="48" alt="shiv19" title="shiv19"/></a> <a href="https://github.com/shiyuanhai"><img src="https://avatars.githubusercontent.com/u/1187370?v=4&s=48" width="48" height="48" alt="shiyuanhai" title="shiyuanhai"/></a> <a href="https://github.com/siraht"><img src="https://avatars.githubusercontent.com/u/73152895?v=4&s=48" width="48" height="48" alt="siraht" title="siraht"/></a> <a href="https://github.com/snopoke"><img src="https://avatars.githubusercontent.com/u/249606?v=4&s=48" width="48" height="48" alt="snopoke" title="snopoke"/></a> <a href="https://github.com/search?q=techboss"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="techboss" title="techboss"/></a> <a href="https://github.com/testingabc321"><img src="https://avatars.githubusercontent.com/u/8577388?v=4&s=48" width="48" height="48" alt="testingabc321" title="testingabc321"/></a> <a href="https://github.com/search?q=The%20Admiral"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="The Admiral" title="The Admiral"/></a> <a href="https://github.com/thesash"><img src="https://avatars.githubusercontent.com/u/1166151?v=4&s=48" width="48" height="48" alt="thesash" title="thesash"/></a> <a href="https://github.com/search?q=Vibe%20Kanban"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vibe Kanban" title="Vibe Kanban"/></a>
<a href="https://github.com/voidserf"><img src="https://avatars.githubusercontent.com/u/477673?v=4&s=48" width="48" height="48" alt="voidserf" title="voidserf"/></a> <a href="https://github.com/search?q=Vultr-Clawd%20Admin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vultr-Clawd Admin" title="Vultr-Clawd Admin"/></a> <a href="https://github.com/search?q=Wimmie"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Wimmie" title="Wimmie"/></a> <a href="https://github.com/search?q=wolfred"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="wolfred" title="wolfred"/></a> <a href="https://github.com/wstock"><img src="https://avatars.githubusercontent.com/u/1394687?v=4&s=48" width="48" height="48" alt="wstock" title="wstock"/></a> <a href="https://github.com/YangHuang2280"><img src="https://avatars.githubusercontent.com/u/201681634?v=4&s=48" width="48" height="48" alt="YangHuang2280" title="YangHuang2280"/></a> <a href="https://github.com/yazinsai"><img src="https://avatars.githubusercontent.com/u/1846034?v=4&s=48" width="48" height="48" alt="yazinsai" title="yazinsai"/></a> <a href="https://github.com/yevhen"><img src="https://avatars.githubusercontent.com/u/107726?v=4&s=48" width="48" height="48" alt="yevhen" title="yevhen"/></a> <a href="https://github.com/YiWang24"><img src="https://avatars.githubusercontent.com/u/176262341?v=4&s=48" width="48" height="48" alt="YiWang24" title="YiWang24"/></a> <a href="https://github.com/search?q=ymat19"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ymat19" title="ymat19"/></a>
<a href="https://github.com/search?q=Zach%20Knickerbocker"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Zach Knickerbocker" title="Zach Knickerbocker"/></a> <a href="https://github.com/zackerthescar"><img src="https://avatars.githubusercontent.com/u/38077284?v=4&s=48" width="48" height="48" alt="zackerthescar" title="zackerthescar"/></a> <a href="https://github.com/0xJonHoldsCrypto"><img src="https://avatars.githubusercontent.com/u/81202085?v=4&s=48" width="48" height="48" alt="0xJonHoldsCrypto" title="0xJonHoldsCrypto"/></a> <a href="https://github.com/aaronn"><img src="https://avatars.githubusercontent.com/u/1653630?v=4&s=48" width="48" height="48" alt="aaronn" title="aaronn"/></a> <a href="https://github.com/Alphonse-arianee"><img src="https://avatars.githubusercontent.com/u/254457365?v=4&s=48" width="48" height="48" alt="Alphonse-arianee" title="Alphonse-arianee"/></a> <a href="https://github.com/atalovesyou"><img src="https://avatars.githubusercontent.com/u/3534502?v=4&s=48" width="48" height="48" alt="atalovesyou" title="atalovesyou"/></a> <a href="https://github.com/search?q=Azade"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Azade" title="Azade"/></a> <a href="https://github.com/carlulsoe"><img src="https://avatars.githubusercontent.com/u/34673973?v=4&s=48" width="48" height="48" alt="carlulsoe" title="carlulsoe"/></a> <a href="https://github.com/search?q=ddyo"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ddyo" title="ddyo"/></a> <a href="https://github.com/search?q=Erik"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Erik" title="Erik"/></a>
<a href="https://github.com/latitudeki5223"><img src="https://avatars.githubusercontent.com/u/119656367?v=4&s=48" width="48" height="48" alt="latitudeki5223" title="latitudeki5223"/></a> <a href="https://github.com/search?q=Manuel%20Maly"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Manuel Maly" title="Manuel Maly"/></a> <a href="https://github.com/search?q=Mourad%20Boustani"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mourad Boustani" title="Mourad Boustani"/></a> <a href="https://github.com/odrobnik"><img src="https://avatars.githubusercontent.com/u/333270?v=4&s=48" width="48" height="48" alt="odrobnik" title="odrobnik"/></a> <a href="https://github.com/pcty-nextgen-ios-builder"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="pcty-nextgen-ios-builder" title="pcty-nextgen-ios-builder"/></a> <a href="https://github.com/search?q=Quentin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Quentin" title="Quentin"/></a> <a href="https://github.com/search?q=Randy%20Torres"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Randy Torres" title="Randy Torres"/></a> <a href="https://github.com/rhjoh"><img src="https://avatars.githubusercontent.com/u/105699450?v=4&s=48" width="48" height="48" alt="rhjoh" title="rhjoh"/></a> <a href="https://github.com/search?q=Rolf%20Fredheim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rolf Fredheim" title="Rolf Fredheim"/></a> <a href="https://github.com/ronak-guliani"><img src="https://avatars.githubusercontent.com/u/23518228?v=4&s=48" width="48" height="48" alt="ronak-guliani" title="ronak-guliani"/></a>
<a href="https://github.com/search?q=William%20Stock"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="William Stock" title="William Stock"/></a>
<a href="https://github.com/steipete"><img src="https://avatars.githubusercontent.com/u/58493?v=4&s=48" width="48" height="48" alt="steipete" title="steipete"/></a> <a href="https://github.com/joshp123"><img src="https://avatars.githubusercontent.com/u/1497361?v=4&s=48" width="48" height="48" alt="joshp123" title="joshp123"/></a> <a href="https://github.com/cpojer"><img src="https://avatars.githubusercontent.com/u/13352?v=4&s=48" width="48" height="48" alt="cpojer" title="cpojer"/></a> <a href="https://github.com/mbelinky"><img src="https://avatars.githubusercontent.com/u/132747814?v=4&s=48" width="48" height="48" alt="Mariano Belinky" title="Mariano Belinky"/></a> <a href="https://github.com/plum-dawg"><img src="https://avatars.githubusercontent.com/u/5909950?v=4&s=48" width="48" height="48" alt="plum-dawg" title="plum-dawg"/></a> <a href="https://github.com/bohdanpodvirnyi"><img src="https://avatars.githubusercontent.com/u/31819391?v=4&s=48" width="48" height="48" alt="bohdanpodvirnyi" title="bohdanpodvirnyi"/></a> <a href="https://github.com/sebslight"><img src="https://avatars.githubusercontent.com/u/19554889?v=4&s=48" width="48" height="48" alt="sebslight" title="sebslight"/></a> <a href="https://github.com/iHildy"><img src="https://avatars.githubusercontent.com/u/25069719?v=4&s=48" width="48" height="48" alt="iHildy" title="iHildy"/></a> <a href="https://github.com/jaydenfyi"><img src="https://avatars.githubusercontent.com/u/213395523?v=4&s=48" width="48" height="48" alt="jaydenfyi" title="jaydenfyi"/></a> <a href="https://github.com/joaohlisboa"><img src="https://avatars.githubusercontent.com/u/8200873?v=4&s=48" width="48" height="48" alt="joaohlisboa" title="joaohlisboa"/></a>
<a href="https://github.com/mneves75"><img src="https://avatars.githubusercontent.com/u/2423436?v=4&s=48" width="48" height="48" alt="mneves75" title="mneves75"/></a> <a href="https://github.com/MatthieuBizien"><img src="https://avatars.githubusercontent.com/u/173090?v=4&s=48" width="48" height="48" alt="MatthieuBizien" title="MatthieuBizien"/></a> <a href="https://github.com/Glucksberg"><img src="https://avatars.githubusercontent.com/u/80581902?v=4&s=48" width="48" height="48" alt="Glucksberg" title="Glucksberg"/></a> <a href="https://github.com/MaudeBot"><img src="https://avatars.githubusercontent.com/u/255777700?v=4&s=48" width="48" height="48" alt="MaudeBot" title="MaudeBot"/></a> <a href="https://github.com/gumadeiras"><img src="https://avatars.githubusercontent.com/u/5599352?v=4&s=48" width="48" height="48" alt="gumadeiras" title="gumadeiras"/></a> <a href="https://github.com/tyler6204"><img src="https://avatars.githubusercontent.com/u/64381258?v=4&s=48" width="48" height="48" alt="tyler6204" title="tyler6204"/></a> <a href="https://github.com/rahthakor"><img src="https://avatars.githubusercontent.com/u/8470553?v=4&s=48" width="48" height="48" alt="rahthakor" title="rahthakor"/></a> <a href="https://github.com/vrknetha"><img src="https://avatars.githubusercontent.com/u/20596261?v=4&s=48" width="48" height="48" alt="vrknetha" title="vrknetha"/></a> <a href="https://github.com/vignesh07"><img src="https://avatars.githubusercontent.com/u/1436853?v=4&s=48" width="48" height="48" alt="vignesh07" title="vignesh07"/></a> <a href="https://github.com/radek-paclt"><img src="https://avatars.githubusercontent.com/u/50451445?v=4&s=48" width="48" height="48" alt="radek-paclt" title="radek-paclt"/></a>
<a href="https://github.com/abdelsfane"><img src="https://avatars.githubusercontent.com/u/32418586?v=4&s=48" width="48" height="48" alt="abdelsfane" title="abdelsfane"/></a> <a href="https://github.com/tobiasbischoff"><img src="https://avatars.githubusercontent.com/u/711564?v=4&s=48" width="48" height="48" alt="Tobias Bischoff" title="Tobias Bischoff"/></a> <a href="https://github.com/christianklotz"><img src="https://avatars.githubusercontent.com/u/69443?v=4&s=48" width="48" height="48" alt="christianklotz" title="christianklotz"/></a> <a href="https://github.com/czekaj"><img src="https://avatars.githubusercontent.com/u/1464539?v=4&s=48" width="48" height="48" alt="czekaj" title="czekaj"/></a> <a href="https://github.com/ethanpalm"><img src="https://avatars.githubusercontent.com/u/56270045?v=4&s=48" width="48" height="48" alt="ethanpalm" title="ethanpalm"/></a> <a href="https://github.com/mukhtharcm"><img src="https://avatars.githubusercontent.com/u/56378562?v=4&s=48" width="48" height="48" alt="mukhtharcm" title="mukhtharcm"/></a> <a href="https://github.com/maxsumrall"><img src="https://avatars.githubusercontent.com/u/628843?v=4&s=48" width="48" height="48" alt="maxsumrall" title="maxsumrall"/></a> <a href="https://github.com/xadenryan"><img src="https://avatars.githubusercontent.com/u/165437834?v=4&s=48" width="48" height="48" alt="xadenryan" title="xadenryan"/></a> <a href="https://github.com/VACInc"><img src="https://avatars.githubusercontent.com/u/3279061?v=4&s=48" width="48" height="48" alt="VACInc" title="VACInc"/></a> <a href="https://github.com/rodrigouroz"><img src="https://avatars.githubusercontent.com/u/384037?v=4&s=48" width="48" height="48" alt="rodrigouroz" title="rodrigouroz"/></a>
<a href="https://github.com/juanpablodlc"><img src="https://avatars.githubusercontent.com/u/92012363?v=4&s=48" width="48" height="48" alt="juanpablodlc" title="juanpablodlc"/></a> <a href="https://github.com/conroywhitney"><img src="https://avatars.githubusercontent.com/u/249891?v=4&s=48" width="48" height="48" alt="conroywhitney" title="conroywhitney"/></a> <a href="https://github.com/hsrvc"><img src="https://avatars.githubusercontent.com/u/129702169?v=4&s=48" width="48" height="48" alt="hsrvc" title="hsrvc"/></a> <a href="https://github.com/magimetal"><img src="https://avatars.githubusercontent.com/u/36491250?v=4&s=48" width="48" height="48" alt="magimetal" title="magimetal"/></a> <a href="https://github.com/zerone0x"><img src="https://avatars.githubusercontent.com/u/39543393?v=4&s=48" width="48" height="48" alt="zerone0x" title="zerone0x"/></a> <a href="https://github.com/Takhoffman"><img src="https://avatars.githubusercontent.com/u/781889?v=4&s=48" width="48" height="48" alt="Takhoffman" title="Takhoffman"/></a> <a href="https://github.com/meaningfool"><img src="https://avatars.githubusercontent.com/u/2862331?v=4&s=48" width="48" height="48" alt="meaningfool" title="meaningfool"/></a> <a href="https://github.com/mudrii"><img src="https://avatars.githubusercontent.com/u/220262?v=4&s=48" width="48" height="48" alt="mudrii" title="mudrii"/></a> <a href="https://github.com/patelhiren"><img src="https://avatars.githubusercontent.com/u/172098?v=4&s=48" width="48" height="48" alt="patelhiren" title="patelhiren"/></a> <a href="https://github.com/NicholasSpisak"><img src="https://avatars.githubusercontent.com/u/129075147?v=4&s=48" width="48" height="48" alt="NicholasSpisak" title="NicholasSpisak"/></a>
<a href="https://github.com/jonisjongithub"><img src="https://avatars.githubusercontent.com/u/86072337?v=4&s=48" width="48" height="48" alt="jonisjongithub" title="jonisjongithub"/></a> <a href="https://github.com/AbhisekBasu1"><img src="https://avatars.githubusercontent.com/u/40645221?v=4&s=48" width="48" height="48" alt="abhisekbasu1" title="abhisekbasu1"/></a> <a href="https://github.com/jamesgroat"><img src="https://avatars.githubusercontent.com/u/2634024?v=4&s=48" width="48" height="48" alt="jamesgroat" title="jamesgroat"/></a> <a href="https://github.com/BunsDev"><img src="https://avatars.githubusercontent.com/u/68980965?v=4&s=48" width="48" height="48" alt="BunsDev" title="BunsDev"/></a> <a href="https://github.com/claude"><img src="https://avatars.githubusercontent.com/u/81847?v=4&s=48" width="48" height="48" alt="claude" title="claude"/></a> <a href="https://github.com/JustYannicc"><img src="https://avatars.githubusercontent.com/u/52761674?v=4&s=48" width="48" height="48" alt="JustYannicc" title="JustYannicc"/></a> <a href="https://github.com/Hyaxia"><img src="https://avatars.githubusercontent.com/u/36747317?v=4&s=48" width="48" height="48" alt="Hyaxia" title="Hyaxia"/></a> <a href="https://github.com/dantelex"><img src="https://avatars.githubusercontent.com/u/631543?v=4&s=48" width="48" height="48" alt="dantelex" title="dantelex"/></a> <a href="https://github.com/SocialNerd42069"><img src="https://avatars.githubusercontent.com/u/118244303?v=4&s=48" width="48" height="48" alt="SocialNerd42069" title="SocialNerd42069"/></a> <a href="https://github.com/daveonkels"><img src="https://avatars.githubusercontent.com/u/533642?v=4&s=48" width="48" height="48" alt="daveonkels" title="daveonkels"/></a>
<a href="https://github.com/apps/google-labs-jules"><img src="https://avatars.githubusercontent.com/in/842251?v=4&s=48" width="48" height="48" alt="google-labs-jules[bot]" title="google-labs-jules[bot]"/></a> <a href="https://github.com/lc0rp"><img src="https://avatars.githubusercontent.com/u/2609441?v=4&s=48" width="48" height="48" alt="lc0rp" title="lc0rp"/></a> <a href="https://github.com/adam91holt"><img src="https://avatars.githubusercontent.com/u/9592417?v=4&s=48" width="48" height="48" alt="adam91holt" title="adam91holt"/></a> <a href="https://github.com/mousberg"><img src="https://avatars.githubusercontent.com/u/57605064?v=4&s=48" width="48" height="48" alt="mousberg" title="mousberg"/></a> <a href="https://github.com/hougangdev"><img src="https://avatars.githubusercontent.com/u/105773686?v=4&s=48" width="48" height="48" alt="hougangdev" title="hougangdev"/></a> <a href="https://github.com/shakkernerd"><img src="https://avatars.githubusercontent.com/u/165377636?v=4&s=48" width="48" height="48" alt="shakkernerd" title="shakkernerd"/></a> <a href="https://github.com/coygeek"><img src="https://avatars.githubusercontent.com/u/65363919?v=4&s=48" width="48" height="48" alt="coygeek" title="coygeek"/></a> <a href="https://github.com/mteam88"><img src="https://avatars.githubusercontent.com/u/84196639?v=4&s=48" width="48" height="48" alt="mteam88" title="mteam88"/></a> <a href="https://github.com/hirefrank"><img src="https://avatars.githubusercontent.com/u/183158?v=4&s=48" width="48" height="48" alt="hirefrank" title="hirefrank"/></a> <a href="https://github.com/M00N7682"><img src="https://avatars.githubusercontent.com/u/170746674?v=4&s=48" width="48" height="48" alt="M00N7682" title="M00N7682"/></a>
<a href="https://github.com/joeynyc"><img src="https://avatars.githubusercontent.com/u/17919866?v=4&s=48" width="48" height="48" alt="joeynyc" title="joeynyc"/></a> <a href="https://github.com/orlyjamie"><img src="https://avatars.githubusercontent.com/u/6668807?v=4&s=48" width="48" height="48" alt="orlyjamie" title="orlyjamie"/></a> <a href="https://github.com/dbhurley"><img src="https://avatars.githubusercontent.com/u/5251425?v=4&s=48" width="48" height="48" alt="dbhurley" title="dbhurley"/></a> <a href="https://github.com/omniwired"><img src="https://avatars.githubusercontent.com/u/322761?v=4&s=48" width="48" height="48" alt="Eng. Juan Combetto" title="Eng. Juan Combetto"/></a> <a href="https://github.com/TSavo"><img src="https://avatars.githubusercontent.com/u/877990?v=4&s=48" width="48" height="48" alt="TSavo" title="TSavo"/></a> <a href="https://github.com/aerolalit"><img src="https://avatars.githubusercontent.com/u/17166039?v=4&s=48" width="48" height="48" alt="aerolalit" title="aerolalit"/></a> <a href="https://github.com/julianengel"><img src="https://avatars.githubusercontent.com/u/10634231?v=4&s=48" width="48" height="48" alt="julianengel" title="julianengel"/></a> <a href="https://github.com/bradleypriest"><img src="https://avatars.githubusercontent.com/u/167215?v=4&s=48" width="48" height="48" alt="bradleypriest" title="bradleypriest"/></a> <a href="https://github.com/benithors"><img src="https://avatars.githubusercontent.com/u/20652882?v=4&s=48" width="48" height="48" alt="benithors" title="benithors"/></a> <a href="https://github.com/lsh411"><img src="https://avatars.githubusercontent.com/u/6801488?v=4&s=48" width="48" height="48" alt="lsh411" title="lsh411"/></a>
<a href="https://github.com/gut-puncture"><img src="https://avatars.githubusercontent.com/u/75851986?v=4&s=48" width="48" height="48" alt="gut-puncture" title="gut-puncture"/></a> <a href="https://github.com/rohannagpal"><img src="https://avatars.githubusercontent.com/u/4009239?v=4&s=48" width="48" height="48" alt="rohannagpal" title="rohannagpal"/></a> <a href="https://github.com/timolins"><img src="https://avatars.githubusercontent.com/u/1440854?v=4&s=48" width="48" height="48" alt="timolins" title="timolins"/></a> <a href="https://github.com/f-trycua"><img src="https://avatars.githubusercontent.com/u/195596869?v=4&s=48" width="48" height="48" alt="f-trycua" title="f-trycua"/></a> <a href="https://github.com/benostein"><img src="https://avatars.githubusercontent.com/u/31802821?v=4&s=48" width="48" height="48" alt="benostein" title="benostein"/></a> <a href="https://github.com/elliotsecops"><img src="https://avatars.githubusercontent.com/u/141947839?v=4&s=48" width="48" height="48" alt="elliotsecops" title="elliotsecops"/></a> <a href="https://github.com/Nachx639"><img src="https://avatars.githubusercontent.com/u/71144023?v=4&s=48" width="48" height="48" alt="nachx639" title="nachx639"/></a> <a href="https://github.com/pvoo"><img src="https://avatars.githubusercontent.com/u/20116814?v=4&s=48" width="48" height="48" alt="pvoo" title="pvoo"/></a> <a href="https://github.com/sreekaransrinath"><img src="https://avatars.githubusercontent.com/u/50989977?v=4&s=48" width="48" height="48" alt="sreekaransrinath" title="sreekaransrinath"/></a> <a href="https://github.com/gupsammy"><img src="https://avatars.githubusercontent.com/u/20296019?v=4&s=48" width="48" height="48" alt="gupsammy" title="gupsammy"/></a>
<a href="https://github.com/cristip73"><img src="https://avatars.githubusercontent.com/u/24499421?v=4&s=48" width="48" height="48" alt="cristip73" title="cristip73"/></a> <a href="https://github.com/stefangalescu"><img src="https://avatars.githubusercontent.com/u/52995748?v=4&s=48" width="48" height="48" alt="stefangalescu" title="stefangalescu"/></a> <a href="https://github.com/nachoiacovino"><img src="https://avatars.githubusercontent.com/u/50103937?v=4&s=48" width="48" height="48" alt="nachoiacovino" title="nachoiacovino"/></a> <a href="https://github.com/vsabavat"><img src="https://avatars.githubusercontent.com/u/50385532?v=4&s=48" width="48" height="48" alt="Vasanth Rao Naik Sabavat" title="Vasanth Rao Naik Sabavat"/></a> <a href="https://github.com/petter-b"><img src="https://avatars.githubusercontent.com/u/62076402?v=4&s=48" width="48" height="48" alt="petter-b" title="petter-b"/></a> <a href="https://github.com/thewilloftheshadow"><img src="https://avatars.githubusercontent.com/u/35580099?v=4&s=48" width="48" height="48" alt="thewilloftheshadow" title="thewilloftheshadow"/></a> <a href="https://github.com/leszekszpunar"><img src="https://avatars.githubusercontent.com/u/13106764?v=4&s=48" width="48" height="48" alt="leszekszpunar" title="leszekszpunar"/></a> <a href="https://github.com/scald"><img src="https://avatars.githubusercontent.com/u/1215913?v=4&s=48" width="48" height="48" alt="scald" title="scald"/></a> <a href="https://github.com/pycckuu"><img src="https://avatars.githubusercontent.com/u/1489583?v=4&s=48" width="48" height="48" alt="pycckuu" title="pycckuu"/></a> <a href="https://github.com/andranik-sahakyan"><img src="https://avatars.githubusercontent.com/u/8908029?v=4&s=48" width="48" height="48" alt="andranik-sahakyan" title="andranik-sahakyan"/></a>
<a href="https://github.com/davidguttman"><img src="https://avatars.githubusercontent.com/u/431696?v=4&s=48" width="48" height="48" alt="davidguttman" title="davidguttman"/></a> <a href="https://github.com/sleontenko"><img src="https://avatars.githubusercontent.com/u/7135949?v=4&s=48" width="48" height="48" alt="sleontenko" title="sleontenko"/></a> <a href="https://github.com/denysvitali"><img src="https://avatars.githubusercontent.com/u/4939519?v=4&s=48" width="48" height="48" alt="denysvitali" title="denysvitali"/></a> <a href="https://github.com/apps/clawdinator"><img src="https://avatars.githubusercontent.com/in/2607181?v=4&s=48" width="48" height="48" alt="clawdinator[bot]" title="clawdinator[bot]"/></a> <a href="https://github.com/TinyTb"><img src="https://avatars.githubusercontent.com/u/5957298?v=4&s=48" width="48" height="48" alt="TinyTb" title="TinyTb"/></a> <a href="https://github.com/sircrumpet"><img src="https://avatars.githubusercontent.com/u/4436535?v=4&s=48" width="48" height="48" alt="sircrumpet" title="sircrumpet"/></a> <a href="https://github.com/peschee"><img src="https://avatars.githubusercontent.com/u/63866?v=4&s=48" width="48" height="48" alt="peschee" title="peschee"/></a> <a href="https://github.com/nicolasstanley"><img src="https://avatars.githubusercontent.com/u/60584925?v=4&s=48" width="48" height="48" alt="nicolasstanley" title="nicolasstanley"/></a> <a href="https://github.com/davidiach"><img src="https://avatars.githubusercontent.com/u/28102235?v=4&s=48" width="48" height="48" alt="davidiach" title="davidiach"/></a> <a href="https://github.com/nonggialiang"><img src="https://avatars.githubusercontent.com/u/14367839?v=4&s=48" width="48" height="48" alt="nonggialiang" title="nonggialiang"/></a>
<a href="https://github.com/ironbyte-rgb"><img src="https://avatars.githubusercontent.com/u/230665944?v=4&s=48" width="48" height="48" alt="ironbyte-rgb" title="ironbyte-rgb"/></a> <a href="https://github.com/rafaelreis-r"><img src="https://avatars.githubusercontent.com/u/57492577?v=4&s=48" width="48" height="48" alt="rafaelreis-r" title="rafaelreis-r"/></a> <a href="https://github.com/dominicnunez"><img src="https://avatars.githubusercontent.com/u/43616264?v=4&s=48" width="48" height="48" alt="dominicnunez" title="dominicnunez"/></a> <a href="https://github.com/lploc94"><img src="https://avatars.githubusercontent.com/u/28453843?v=4&s=48" width="48" height="48" alt="lploc94" title="lploc94"/></a> <a href="https://github.com/ratulsarna"><img src="https://avatars.githubusercontent.com/u/105903728?v=4&s=48" width="48" height="48" alt="ratulsarna" title="ratulsarna"/></a> <a href="https://github.com/sfo2001"><img src="https://avatars.githubusercontent.com/u/103369858?v=4&s=48" width="48" height="48" alt="sfo2001" title="sfo2001"/></a> <a href="https://github.com/lutr0"><img src="https://avatars.githubusercontent.com/u/76906369?v=4&s=48" width="48" height="48" alt="lutr0" title="lutr0"/></a> <a href="https://github.com/kiranjd"><img src="https://avatars.githubusercontent.com/u/25822851?v=4&s=48" width="48" height="48" alt="kiranjd" title="kiranjd"/></a> <a href="https://github.com/danielz1z"><img src="https://avatars.githubusercontent.com/u/235270390?v=4&s=48" width="48" height="48" alt="danielz1z" title="danielz1z"/></a> <a href="https://github.com/Iranb"><img src="https://avatars.githubusercontent.com/u/49674669?v=4&s=48" width="48" height="48" alt="Iranb" title="Iranb"/></a>
<a href="https://github.com/AdeboyeDN"><img src="https://avatars.githubusercontent.com/u/65312338?v=4&s=48" width="48" height="48" alt="AdeboyeDN" title="AdeboyeDN"/></a> <a href="https://github.com/Alg0rix"><img src="https://avatars.githubusercontent.com/u/53804949?v=4&s=48" width="48" height="48" alt="Alg0rix" title="Alg0rix"/></a> <a href="https://github.com/obviyus"><img src="https://avatars.githubusercontent.com/u/22031114?v=4&s=48" width="48" height="48" alt="obviyus" title="obviyus"/></a> <a href="https://github.com/papago2355"><img src="https://avatars.githubusercontent.com/u/68721273?v=4&s=48" width="48" height="48" alt="papago2355" title="papago2355"/></a> <a href="https://github.com/emanuelst"><img src="https://avatars.githubusercontent.com/u/9994339?v=4&s=48" width="48" height="48" alt="emanuelst" title="emanuelst"/></a> <a href="https://github.com/evanotero"><img src="https://avatars.githubusercontent.com/u/13204105?v=4&s=48" width="48" height="48" alt="evanotero" title="evanotero"/></a> <a href="https://github.com/KristijanJovanovski"><img src="https://avatars.githubusercontent.com/u/8942284?v=4&s=48" width="48" height="48" alt="KristijanJovanovski" title="KristijanJovanovski"/></a> <a href="https://github.com/jlowin"><img src="https://avatars.githubusercontent.com/u/153965?v=4&s=48" width="48" height="48" alt="jlowin" title="jlowin"/></a> <a href="https://github.com/rdev"><img src="https://avatars.githubusercontent.com/u/8418866?v=4&s=48" width="48" height="48" alt="rdev" title="rdev"/></a> <a href="https://github.com/rhuanssauro"><img src="https://avatars.githubusercontent.com/u/164682191?v=4&s=48" width="48" height="48" alt="rhuanssauro" title="rhuanssauro"/></a>
<a href="https://github.com/joshrad-dev"><img src="https://avatars.githubusercontent.com/u/62785552?v=4&s=48" width="48" height="48" alt="joshrad-dev" title="joshrad-dev"/></a> <a href="https://github.com/osolmaz"><img src="https://avatars.githubusercontent.com/u/2453968?v=4&s=48" width="48" height="48" alt="osolmaz" title="osolmaz"/></a> <a href="https://github.com/adityashaw2"><img src="https://avatars.githubusercontent.com/u/41204444?v=4&s=48" width="48" height="48" alt="adityashaw2" title="adityashaw2"/></a> <a href="https://github.com/CashWilliams"><img src="https://avatars.githubusercontent.com/u/613573?v=4&s=48" width="48" height="48" alt="CashWilliams" title="CashWilliams"/></a> <a href="https://github.com/search?q=sheeek"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="sheeek" title="sheeek"/></a> <a href="https://github.com/ryancontent"><img src="https://avatars.githubusercontent.com/u/39743613?v=4&s=48" width="48" height="48" alt="ryancontent" title="ryancontent"/></a> <a href="https://github.com/jasonsschin"><img src="https://avatars.githubusercontent.com/u/1456889?v=4&s=48" width="48" height="48" alt="jasonsschin" title="jasonsschin"/></a> <a href="https://github.com/artuskg"><img src="https://avatars.githubusercontent.com/u/11966157?v=4&s=48" width="48" height="48" alt="artuskg" title="artuskg"/></a> <a href="https://github.com/onutc"><img src="https://avatars.githubusercontent.com/u/152018508?v=4&s=48" width="48" height="48" alt="onutc" title="onutc"/></a> <a href="https://github.com/pauloportella"><img src="https://avatars.githubusercontent.com/u/22947229?v=4&s=48" width="48" height="48" alt="pauloportella" title="pauloportella"/></a>
<a href="https://github.com/HirokiKobayashi-R"><img src="https://avatars.githubusercontent.com/u/37167840?v=4&s=48" width="48" height="48" alt="HirokiKobayashi-R" title="HirokiKobayashi-R"/></a> <a href="https://github.com/ThanhNguyxn"><img src="https://avatars.githubusercontent.com/u/74597207?v=4&s=48" width="48" height="48" alt="ThanhNguyxn" title="ThanhNguyxn"/></a> <a href="https://github.com/18-RAJAT"><img src="https://avatars.githubusercontent.com/u/78920780?v=4&s=48" width="48" height="48" alt="18-RAJAT" title="18-RAJAT"/></a> <a href="https://github.com/kimitaka"><img src="https://avatars.githubusercontent.com/u/167225?v=4&s=48" width="48" height="48" alt="kimitaka" title="kimitaka"/></a> <a href="https://github.com/yuting0624"><img src="https://avatars.githubusercontent.com/u/32728916?v=4&s=48" width="48" height="48" alt="yuting0624" title="yuting0624"/></a> <a href="https://github.com/neooriginal"><img src="https://avatars.githubusercontent.com/u/54811660?v=4&s=48" width="48" height="48" alt="neooriginal" title="neooriginal"/></a> <a href="https://github.com/ManuelHettich"><img src="https://avatars.githubusercontent.com/u/17690367?v=4&s=48" width="48" height="48" alt="manuelhettich" title="manuelhettich"/></a> <a href="https://github.com/minghinmatthewlam"><img src="https://avatars.githubusercontent.com/u/14224566?v=4&s=48" width="48" height="48" alt="minghinmatthewlam" title="minghinmatthewlam"/></a> <a href="https://github.com/unisone"><img src="https://avatars.githubusercontent.com/u/32521398?v=4&s=48" width="48" height="48" alt="unisone" title="unisone"/></a> <a href="https://github.com/baccula"><img src="https://avatars.githubusercontent.com/u/22080883?v=4&s=48" width="48" height="48" alt="baccula" title="baccula"/></a>
<a href="https://github.com/manikv12"><img src="https://avatars.githubusercontent.com/u/49544491?v=4&s=48" width="48" height="48" alt="manikv12" title="manikv12"/></a> <a href="https://github.com/myfunc"><img src="https://avatars.githubusercontent.com/u/19294627?v=4&s=48" width="48" height="48" alt="myfunc" title="myfunc"/></a> <a href="https://github.com/travisirby"><img src="https://avatars.githubusercontent.com/u/5958376?v=4&s=48" width="48" height="48" alt="travisirby" title="travisirby"/></a> <a href="https://github.com/fujiwara-tofu-shop"><img src="https://avatars.githubusercontent.com/u/259415332?v=4&s=48" width="48" height="48" alt="fujiwara-tofu-shop" title="fujiwara-tofu-shop"/></a> <a href="https://github.com/buddyh"><img src="https://avatars.githubusercontent.com/u/31752869?v=4&s=48" width="48" height="48" alt="buddyh" title="buddyh"/></a> <a href="https://github.com/connorshea"><img src="https://avatars.githubusercontent.com/u/2977353?v=4&s=48" width="48" height="48" alt="connorshea" title="connorshea"/></a> <a href="https://github.com/bjesuiter"><img src="https://avatars.githubusercontent.com/u/2365676?v=4&s=48" width="48" height="48" alt="bjesuiter" title="bjesuiter"/></a> <a href="https://github.com/kyleok"><img src="https://avatars.githubusercontent.com/u/58307870?v=4&s=48" width="48" height="48" alt="kyleok" title="kyleok"/></a> <a href="https://github.com/slonce70"><img src="https://avatars.githubusercontent.com/u/130596182?v=4&s=48" width="48" height="48" alt="slonce70" title="slonce70"/></a> <a href="https://github.com/mcinteerj"><img src="https://avatars.githubusercontent.com/u/3613653?v=4&s=48" width="48" height="48" alt="mcinteerj" title="mcinteerj"/></a>
<a href="https://github.com/badlogic"><img src="https://avatars.githubusercontent.com/u/514052?v=4&s=48" width="48" height="48" alt="badlogic" title="badlogic"/></a> <a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4&s=48" width="48" height="48" alt="dependabot[bot]" title="dependabot[bot]"/></a> <a href="https://github.com/amitbiswal007"><img src="https://avatars.githubusercontent.com/u/108086198?v=4&s=48" width="48" height="48" alt="amitbiswal007" title="amitbiswal007"/></a> <a href="https://github.com/John-Rood"><img src="https://avatars.githubusercontent.com/u/62669593?v=4&s=48" width="48" height="48" alt="John-Rood" title="John-Rood"/></a> <a href="https://github.com/timkrase"><img src="https://avatars.githubusercontent.com/u/38947626?v=4&s=48" width="48" height="48" alt="timkrase" title="timkrase"/></a> <a href="https://github.com/uos-status"><img src="https://avatars.githubusercontent.com/u/255712580?v=4&s=48" width="48" height="48" alt="uos-status" title="uos-status"/></a> <a href="https://github.com/gerardward2007"><img src="https://avatars.githubusercontent.com/u/3002155?v=4&s=48" width="48" height="48" alt="gerardward2007" title="gerardward2007"/></a> <a href="https://github.com/roshanasingh4"><img src="https://avatars.githubusercontent.com/u/88576930?v=4&s=48" width="48" height="48" alt="roshanasingh4" title="roshanasingh4"/></a> <a href="https://github.com/tosh-hamburg"><img src="https://avatars.githubusercontent.com/u/58424326?v=4&s=48" width="48" height="48" alt="tosh-hamburg" title="tosh-hamburg"/></a> <a href="https://github.com/azade-c"><img src="https://avatars.githubusercontent.com/u/252790079?v=4&s=48" width="48" height="48" alt="azade-c" title="azade-c"/></a>
<a href="https://github.com/dlauer"><img src="https://avatars.githubusercontent.com/u/757041?v=4&s=48" width="48" height="48" alt="dlauer" title="dlauer"/></a> <a href="https://github.com/grp06"><img src="https://avatars.githubusercontent.com/u/1573959?v=4&s=48" width="48" height="48" alt="grp06" title="grp06"/></a> <a href="https://github.com/JonUleis"><img src="https://avatars.githubusercontent.com/u/7644941?v=4&s=48" width="48" height="48" alt="JonUleis" title="JonUleis"/></a> <a href="https://github.com/shivamraut101"><img src="https://avatars.githubusercontent.com/u/110457469?v=4&s=48" width="48" height="48" alt="shivamraut101" title="shivamraut101"/></a> <a href="https://github.com/cheeeee"><img src="https://avatars.githubusercontent.com/u/21245729?v=4&s=48" width="48" height="48" alt="cheeeee" title="cheeeee"/></a> <a href="https://github.com/robbyczgw-cla"><img src="https://avatars.githubusercontent.com/u/239660374?v=4&s=48" width="48" height="48" alt="robbyczgw-cla" title="robbyczgw-cla"/></a> <a href="https://github.com/YuriNachos"><img src="https://avatars.githubusercontent.com/u/19365375?v=4&s=48" width="48" height="48" alt="YuriNachos" title="YuriNachos"/></a> <a href="https://github.com/j1philli"><img src="https://avatars.githubusercontent.com/u/3744255?v=4&s=48" width="48" height="48" alt="Josh Phillips" title="Josh Phillips"/></a> <a href="https://github.com/Wangnov"><img src="https://avatars.githubusercontent.com/u/48670012?v=4&s=48" width="48" height="48" alt="Wangnov" title="Wangnov"/></a> <a href="https://github.com/kaizen403"><img src="https://avatars.githubusercontent.com/u/134706404?v=4&s=48" width="48" height="48" alt="kaizen403" title="kaizen403"/></a>
<a href="https://github.com/pookNast"><img src="https://avatars.githubusercontent.com/u/14242552?v=4&s=48" width="48" height="48" alt="pookNast" title="pookNast"/></a> <a href="https://github.com/Whoaa512"><img src="https://avatars.githubusercontent.com/u/1581943?v=4&s=48" width="48" height="48" alt="Whoaa512" title="Whoaa512"/></a> <a href="https://github.com/chriseidhof"><img src="https://avatars.githubusercontent.com/u/5382?v=4&s=48" width="48" height="48" alt="chriseidhof" title="chriseidhof"/></a> <a href="https://github.com/ngutman"><img src="https://avatars.githubusercontent.com/u/1540134?v=4&s=48" width="48" height="48" alt="ngutman" title="ngutman"/></a> <a href="https://github.com/therealZpoint-bot"><img src="https://avatars.githubusercontent.com/u/258706705?v=4&s=48" width="48" height="48" alt="therealZpoint-bot" title="therealZpoint-bot"/></a> <a href="https://github.com/wangai-studio"><img src="https://avatars.githubusercontent.com/u/256938352?v=4&s=48" width="48" height="48" alt="wangai-studio" title="wangai-studio"/></a> <a href="https://github.com/ysqander"><img src="https://avatars.githubusercontent.com/u/80843820?v=4&s=48" width="48" height="48" alt="ysqander" title="ysqander"/></a> <a href="https://github.com/search?q=Yurii%20Chukhlib"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Yurii Chukhlib" title="Yurii Chukhlib"/></a> <a href="https://github.com/aj47"><img src="https://avatars.githubusercontent.com/u/8023513?v=4&s=48" width="48" height="48" alt="aj47" title="aj47"/></a> <a href="https://github.com/kennyklee"><img src="https://avatars.githubusercontent.com/u/1432489?v=4&s=48" width="48" height="48" alt="kennyklee" title="kennyklee"/></a>
<a href="https://github.com/superman32432432"><img src="https://avatars.githubusercontent.com/u/7228420?v=4&s=48" width="48" height="48" alt="superman32432432" title="superman32432432"/></a> <a href="https://github.com/Hisleren"><img src="https://avatars.githubusercontent.com/u/83217244?v=4&s=48" width="48" height="48" alt="Hisleren" title="Hisleren"/></a> <a href="https://github.com/shatner"><img src="https://avatars.githubusercontent.com/u/17735435?v=4&s=48" width="48" height="48" alt="shatner" title="shatner"/></a> <a href="https://github.com/antons"><img src="https://avatars.githubusercontent.com/u/129705?v=4&s=48" width="48" height="48" alt="antons" title="antons"/></a> <a href="https://github.com/austinm911"><img src="https://avatars.githubusercontent.com/u/31991302?v=4&s=48" width="48" height="48" alt="austinm911" title="austinm911"/></a> <a href="https://github.com/apps/blacksmith-sh"><img src="https://avatars.githubusercontent.com/in/807020?v=4&s=48" width="48" height="48" alt="blacksmith-sh[bot]" title="blacksmith-sh[bot]"/></a> <a href="https://github.com/damoahdominic"><img src="https://avatars.githubusercontent.com/u/4623434?v=4&s=48" width="48" height="48" alt="damoahdominic" title="damoahdominic"/></a> <a href="https://github.com/dan-dr"><img src="https://avatars.githubusercontent.com/u/6669808?v=4&s=48" width="48" height="48" alt="dan-dr" title="dan-dr"/></a> <a href="https://github.com/GHesericsu"><img src="https://avatars.githubusercontent.com/u/60202455?v=4&s=48" width="48" height="48" alt="GHesericsu" title="GHesericsu"/></a> <a href="https://github.com/HeimdallStrategy"><img src="https://avatars.githubusercontent.com/u/223014405?v=4&s=48" width="48" height="48" alt="HeimdallStrategy" title="HeimdallStrategy"/></a>
<a href="https://github.com/imfing"><img src="https://avatars.githubusercontent.com/u/5097752?v=4&s=48" width="48" height="48" alt="imfing" title="imfing"/></a> <a href="https://github.com/jalehman"><img src="https://avatars.githubusercontent.com/u/550978?v=4&s=48" width="48" height="48" alt="jalehman" title="jalehman"/></a> <a href="https://github.com/jarvis-medmatic"><img src="https://avatars.githubusercontent.com/u/252428873?v=4&s=48" width="48" height="48" alt="jarvis-medmatic" title="jarvis-medmatic"/></a> <a href="https://github.com/kkarimi"><img src="https://avatars.githubusercontent.com/u/875218?v=4&s=48" width="48" height="48" alt="kkarimi" title="kkarimi"/></a> <a href="https://github.com/Lukavyi"><img src="https://avatars.githubusercontent.com/u/1013690?v=4&s=48" width="48" height="48" alt="Lukavyi" title="Lukavyi"/></a> <a href="https://github.com/mahmoudashraf93"><img src="https://avatars.githubusercontent.com/u/9130129?v=4&s=48" width="48" height="48" alt="mahmoudashraf93" title="mahmoudashraf93"/></a> <a href="https://github.com/pkrmf"><img src="https://avatars.githubusercontent.com/u/1714267?v=4&s=48" width="48" height="48" alt="pkrmf" title="pkrmf"/></a> <a href="https://github.com/RandyVentures"><img src="https://avatars.githubusercontent.com/u/149904821?v=4&s=48" width="48" height="48" alt="RandyVentures" title="RandyVentures"/></a> <a href="https://github.com/robhparker"><img src="https://avatars.githubusercontent.com/u/7404740?v=4&s=48" width="48" height="48" alt="robhparker" title="robhparker"/></a> <a href="https://github.com/search?q=Ryan%20Lisse"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ryan Lisse" title="Ryan Lisse"/></a>
<a href="https://github.com/Yeom-JinHo"><img src="https://avatars.githubusercontent.com/u/81306489?v=4&s=48" width="48" height="48" alt="Yeom-JinHo" title="Yeom-JinHo"/></a> <a href="https://github.com/doodlewind"><img src="https://avatars.githubusercontent.com/u/7312949?v=4&s=48" width="48" height="48" alt="doodlewind" title="doodlewind"/></a> <a href="https://github.com/dougvk"><img src="https://avatars.githubusercontent.com/u/401660?v=4&s=48" width="48" height="48" alt="dougvk" title="dougvk"/></a> <a href="https://github.com/erikpr1994"><img src="https://avatars.githubusercontent.com/u/6299331?v=4&s=48" width="48" height="48" alt="erikpr1994" title="erikpr1994"/></a> <a href="https://github.com/fal3"><img src="https://avatars.githubusercontent.com/u/6484295?v=4&s=48" width="48" height="48" alt="fal3" title="fal3"/></a> <a href="https://github.com/search?q=Ghost"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ghost" title="Ghost"/></a> <a href="https://github.com/hyf0-agent"><img src="https://avatars.githubusercontent.com/u/258783736?v=4&s=48" width="48" height="48" alt="hyf0-agent" title="hyf0-agent"/></a> <a href="https://github.com/jonasjancarik"><img src="https://avatars.githubusercontent.com/u/2459191?v=4&s=48" width="48" height="48" alt="jonasjancarik" title="jonasjancarik"/></a> <a href="https://github.com/search?q=Keith%20the%20Silly%20Goose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Keith the Silly Goose" title="Keith the Silly Goose"/></a> <a href="https://github.com/search?q=L36%20Server"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="L36 Server" title="L36 Server"/></a>
<a href="https://github.com/search?q=Marc"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Marc" title="Marc"/></a> <a href="https://github.com/mitschabaude-bot"><img src="https://avatars.githubusercontent.com/u/247582884?v=4&s=48" width="48" height="48" alt="mitschabaude-bot" title="mitschabaude-bot"/></a> <a href="https://github.com/mkbehr"><img src="https://avatars.githubusercontent.com/u/1285?v=4&s=48" width="48" height="48" alt="mkbehr" title="mkbehr"/></a> <a href="https://github.com/neist"><img src="https://avatars.githubusercontent.com/u/1029724?v=4&s=48" width="48" height="48" alt="neist" title="neist"/></a> <a href="https://github.com/sibbl"><img src="https://avatars.githubusercontent.com/u/866535?v=4&s=48" width="48" height="48" alt="sibbl" title="sibbl"/></a> <a href="https://github.com/zats"><img src="https://avatars.githubusercontent.com/u/2688806?v=4&s=48" width="48" height="48" alt="zats" title="zats"/></a> <a href="https://github.com/abhijeet117"><img src="https://avatars.githubusercontent.com/u/192859219?v=4&s=48" width="48" height="48" alt="abhijeet117" title="abhijeet117"/></a> <a href="https://github.com/chrisrodz"><img src="https://avatars.githubusercontent.com/u/2967620?v=4&s=48" width="48" height="48" alt="chrisrodz" title="chrisrodz"/></a> <a href="https://github.com/search?q=Friederike%20Seiler"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Friederike Seiler" title="Friederike Seiler"/></a> <a href="https://github.com/gabriel-trigo"><img src="https://avatars.githubusercontent.com/u/38991125?v=4&s=48" width="48" height="48" alt="gabriel-trigo" title="gabriel-trigo"/></a>
<a href="https://github.com/Iamadig"><img src="https://avatars.githubusercontent.com/u/102129234?v=4&s=48" width="48" height="48" alt="iamadig" title="iamadig"/></a> <a href="https://github.com/itsjling"><img src="https://avatars.githubusercontent.com/u/2521993?v=4&s=48" width="48" height="48" alt="itsjling" title="itsjling"/></a> <a href="https://github.com/jdrhyne"><img src="https://avatars.githubusercontent.com/u/7828464?v=4&s=48" width="48" height="48" alt="Jonathan D. Rhyne (DJ-D)" title="Jonathan D. Rhyne (DJ-D)"/></a> <a href="https://github.com/search?q=Joshua%20Mitchell"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Joshua Mitchell" title="Joshua Mitchell"/></a> <a href="https://github.com/kelvinCB"><img src="https://avatars.githubusercontent.com/u/50544379?v=4&s=48" width="48" height="48" alt="kelvinCB" title="kelvinCB"/></a> <a href="https://github.com/search?q=Kit"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kit" title="Kit"/></a> <a href="https://github.com/koala73"><img src="https://avatars.githubusercontent.com/u/996596?v=4&s=48" width="48" height="48" alt="koala73" title="koala73"/></a> <a href="https://github.com/manmal"><img src="https://avatars.githubusercontent.com/u/142797?v=4&s=48" width="48" height="48" alt="manmal" title="manmal"/></a> <a href="https://github.com/mattqdev"><img src="https://avatars.githubusercontent.com/u/115874885?v=4&s=48" width="48" height="48" alt="mattqdev" title="mattqdev"/></a> <a href="https://github.com/mitsuhiko"><img src="https://avatars.githubusercontent.com/u/7396?v=4&s=48" width="48" height="48" alt="mitsuhiko" title="mitsuhiko"/></a>
<a href="https://github.com/ogulcancelik"><img src="https://avatars.githubusercontent.com/u/7064011?v=4&s=48" width="48" height="48" alt="ogulcancelik" title="ogulcancelik"/></a> <a href="https://github.com/pasogott"><img src="https://avatars.githubusercontent.com/u/23458152?v=4&s=48" width="48" height="48" alt="pasogott" title="pasogott"/></a> <a href="https://github.com/petradonka"><img src="https://avatars.githubusercontent.com/u/7353770?v=4&s=48" width="48" height="48" alt="petradonka" title="petradonka"/></a> <a href="https://github.com/rubyrunsstuff"><img src="https://avatars.githubusercontent.com/u/246602379?v=4&s=48" width="48" height="48" alt="rubyrunsstuff" title="rubyrunsstuff"/></a> <a href="https://github.com/siddhantjain"><img src="https://avatars.githubusercontent.com/u/4835232?v=4&s=48" width="48" height="48" alt="siddhantjain" title="siddhantjain"/></a> <a href="https://github.com/spiceoogway"><img src="https://avatars.githubusercontent.com/u/105812383?v=4&s=48" width="48" height="48" alt="spiceoogway" title="spiceoogway"/></a> <a href="https://github.com/suminhthanh"><img src="https://avatars.githubusercontent.com/u/2907636?v=4&s=48" width="48" height="48" alt="suminhthanh" title="suminhthanh"/></a> <a href="https://github.com/svkozak"><img src="https://avatars.githubusercontent.com/u/31941359?v=4&s=48" width="48" height="48" alt="svkozak" title="svkozak"/></a> <a href="https://github.com/wes-davis"><img src="https://avatars.githubusercontent.com/u/16506720?v=4&s=48" width="48" height="48" alt="wes-davis" title="wes-davis"/></a> <a href="https://github.com/24601"><img src="https://avatars.githubusercontent.com/u/1157207?v=4&s=48" width="48" height="48" alt="24601" title="24601"/></a>
<a href="https://github.com/ameno-"><img src="https://avatars.githubusercontent.com/u/2416135?v=4&s=48" width="48" height="48" alt="ameno-" title="ameno-"/></a> <a href="https://github.com/bonald"><img src="https://avatars.githubusercontent.com/u/12394874?v=4&s=48" width="48" height="48" alt="bonald" title="bonald"/></a> <a href="https://github.com/bravostation"><img src="https://avatars.githubusercontent.com/u/257991910?v=4&s=48" width="48" height="48" alt="bravostation" title="bravostation"/></a> <a href="https://github.com/search?q=Chris%20Taylor"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Chris Taylor" title="Chris Taylor"/></a> <a href="https://github.com/dguido"><img src="https://avatars.githubusercontent.com/u/294844?v=4&s=48" width="48" height="48" alt="dguido" title="dguido"/></a> <a href="https://github.com/djangonavarro220"><img src="https://avatars.githubusercontent.com/u/251162586?v=4&s=48" width="48" height="48" alt="Django Navarro" title="Django Navarro"/></a> <a href="https://github.com/evalexpr"><img src="https://avatars.githubusercontent.com/u/23485511?v=4&s=48" width="48" height="48" alt="evalexpr" title="evalexpr"/></a> <a href="https://github.com/henrino3"><img src="https://avatars.githubusercontent.com/u/4260288?v=4&s=48" width="48" height="48" alt="henrino3" title="henrino3"/></a> <a href="https://github.com/humanwritten"><img src="https://avatars.githubusercontent.com/u/206531610?v=4&s=48" width="48" height="48" alt="humanwritten" title="humanwritten"/></a> <a href="https://github.com/j2h4u"><img src="https://avatars.githubusercontent.com/u/39818683?v=4&s=48" width="48" height="48" alt="j2h4u" title="j2h4u"/></a>
<a href="https://github.com/larlyssa"><img src="https://avatars.githubusercontent.com/u/13128869?v=4&s=48" width="48" height="48" alt="larlyssa" title="larlyssa"/></a> <a href="https://github.com/odysseus0"><img src="https://avatars.githubusercontent.com/u/8635094?v=4&s=48" width="48" height="48" alt="odysseus0" title="odysseus0"/></a> <a href="https://github.com/oswalpalash"><img src="https://avatars.githubusercontent.com/u/6431196?v=4&s=48" width="48" height="48" alt="oswalpalash" title="oswalpalash"/></a> <a href="https://github.com/pcty-nextgen-service-account"><img src="https://avatars.githubusercontent.com/u/112553441?v=4&s=48" width="48" height="48" alt="pcty-nextgen-service-account" title="pcty-nextgen-service-account"/></a> <a href="https://github.com/pi0"><img src="https://avatars.githubusercontent.com/u/5158436?v=4&s=48" width="48" height="48" alt="pi0" title="pi0"/></a> <a href="https://github.com/rmorse"><img src="https://avatars.githubusercontent.com/u/853547?v=4&s=48" width="48" height="48" alt="rmorse" title="rmorse"/></a> <a href="https://github.com/search?q=Roopak%20Nijhara"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Roopak Nijhara" title="Roopak Nijhara"/></a> <a href="https://github.com/Syhids"><img src="https://avatars.githubusercontent.com/u/671202?v=4&s=48" width="48" height="48" alt="Syhids" title="Syhids"/></a> <a href="https://github.com/search?q=Ubuntu"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ubuntu" title="Ubuntu"/></a> <a href="https://github.com/search?q=xiaose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="xiaose" title="xiaose"/></a>
<a href="https://github.com/search?q=Aaron%20Konyer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Aaron Konyer" title="Aaron Konyer"/></a> <a href="https://github.com/aaronveklabs"><img src="https://avatars.githubusercontent.com/u/225997828?v=4&s=48" width="48" height="48" alt="aaronveklabs" title="aaronveklabs"/></a> <a href="https://github.com/aldoeliacim"><img src="https://avatars.githubusercontent.com/u/17973757?v=4&s=48" width="48" height="48" alt="aldoeliacim" title="aldoeliacim"/></a> <a href="https://github.com/andreabadesso"><img src="https://avatars.githubusercontent.com/u/3586068?v=4&s=48" width="48" height="48" alt="andreabadesso" title="andreabadesso"/></a> <a href="https://github.com/search?q=Andrii"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Andrii" title="Andrii"/></a> <a href="https://github.com/BinaryMuse"><img src="https://avatars.githubusercontent.com/u/189606?v=4&s=48" width="48" height="48" alt="BinaryMuse" title="BinaryMuse"/></a> <a href="https://github.com/bqcfjwhz85-arch"><img src="https://avatars.githubusercontent.com/u/239267175?v=4&s=48" width="48" height="48" alt="bqcfjwhz85-arch" title="bqcfjwhz85-arch"/></a> <a href="https://github.com/cash-echo-bot"><img src="https://avatars.githubusercontent.com/u/252747386?v=4&s=48" width="48" height="48" alt="cash-echo-bot" title="cash-echo-bot"/></a> <a href="https://github.com/search?q=Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawd" title="Clawd"/></a> <a href="https://github.com/search?q=ClawdFx"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ClawdFx" title="ClawdFx"/></a>
<a href="https://github.com/search?q=damaozi"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="damaozi" title="damaozi"/></a> <a href="https://github.com/danballance"><img src="https://avatars.githubusercontent.com/u/13839912?v=4&s=48" width="48" height="48" alt="danballance" title="danballance"/></a> <a href="https://github.com/Elarwei001"><img src="https://avatars.githubusercontent.com/u/168552401?v=4&s=48" width="48" height="48" alt="Elarwei001" title="Elarwei001"/></a> <a href="https://github.com/EnzeD"><img src="https://avatars.githubusercontent.com/u/9866900?v=4&s=48" width="48" height="48" alt="EnzeD" title="EnzeD"/></a> <a href="https://github.com/erik-agens"><img src="https://avatars.githubusercontent.com/u/80908960?v=4&s=48" width="48" height="48" alt="erik-agens" title="erik-agens"/></a> <a href="https://github.com/Evizero"><img src="https://avatars.githubusercontent.com/u/10854026?v=4&s=48" width="48" height="48" alt="Evizero" title="Evizero"/></a> <a href="https://github.com/fcatuhe"><img src="https://avatars.githubusercontent.com/u/17382215?v=4&s=48" width="48" height="48" alt="fcatuhe" title="fcatuhe"/></a> <a href="https://github.com/gildo"><img src="https://avatars.githubusercontent.com/u/133645?v=4&s=48" width="48" height="48" alt="gildo" title="gildo"/></a> <a href="https://github.com/hclsys"><img src="https://avatars.githubusercontent.com/u/7755017?v=4&s=48" width="48" height="48" alt="hclsys" title="hclsys"/></a> <a href="https://github.com/itsjaydesu"><img src="https://avatars.githubusercontent.com/u/220390?v=4&s=48" width="48" height="48" alt="itsjaydesu" title="itsjaydesu"/></a>
<a href="https://github.com/ivancasco"><img src="https://avatars.githubusercontent.com/u/2452858?v=4&s=48" width="48" height="48" alt="ivancasco" title="ivancasco"/></a> <a href="https://github.com/ivanrvpereira"><img src="https://avatars.githubusercontent.com/u/183991?v=4&s=48" width="48" height="48" alt="ivanrvpereira" title="ivanrvpereira"/></a> <a href="https://github.com/search?q=Jarvis"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis" title="Jarvis"/></a> <a href="https://github.com/jayhickey"><img src="https://avatars.githubusercontent.com/u/1676460?v=4&s=48" width="48" height="48" alt="jayhickey" title="jayhickey"/></a> <a href="https://github.com/jeffersonwarrior"><img src="https://avatars.githubusercontent.com/u/89030989?v=4&s=48" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/search?q=jeffersonwarrior"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/jverdi"><img src="https://avatars.githubusercontent.com/u/345050?v=4&s=48" width="48" height="48" alt="jverdi" title="jverdi"/></a> <a href="https://github.com/lailoo"><img src="https://avatars.githubusercontent.com/u/20536249?v=4&s=48" width="48" height="48" alt="lailoo" title="lailoo"/></a> <a href="https://github.com/longmaba"><img src="https://avatars.githubusercontent.com/u/9361500?v=4&s=48" width="48" height="48" alt="longmaba" title="longmaba"/></a> <a href="https://github.com/search?q=Marco%20Marandiz"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Marco Marandiz" title="Marco Marandiz"/></a>
<a href="https://github.com/MarvinCui"><img src="https://avatars.githubusercontent.com/u/130876763?v=4&s=48" width="48" height="48" alt="MarvinCui" title="MarvinCui"/></a> <a href="https://github.com/mattezell"><img src="https://avatars.githubusercontent.com/u/361409?v=4&s=48" width="48" height="48" alt="mattezell" title="mattezell"/></a> <a href="https://github.com/mjrussell"><img src="https://avatars.githubusercontent.com/u/1641895?v=4&s=48" width="48" height="48" alt="mjrussell" title="mjrussell"/></a> <a href="https://github.com/odnxe"><img src="https://avatars.githubusercontent.com/u/403141?v=4&s=48" width="48" height="48" alt="odnxe" title="odnxe"/></a> <a href="https://github.com/optimikelabs"><img src="https://avatars.githubusercontent.com/u/31423109?v=4&s=48" width="48" height="48" alt="optimikelabs" title="optimikelabs"/></a> <a href="https://github.com/p6l-richard"><img src="https://avatars.githubusercontent.com/u/18185649?v=4&s=48" width="48" height="48" alt="p6l-richard" title="p6l-richard"/></a> <a href="https://github.com/philipp-spiess"><img src="https://avatars.githubusercontent.com/u/458591?v=4&s=48" width="48" height="48" alt="philipp-spiess" title="philipp-spiess"/></a> <a href="https://github.com/search?q=Pocket%20Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Pocket Clawd" title="Pocket Clawd"/></a> <a href="https://github.com/robaxelsen"><img src="https://avatars.githubusercontent.com/u/13132899?v=4&s=48" width="48" height="48" alt="robaxelsen" title="robaxelsen"/></a> <a href="https://github.com/search?q=Sash%20Catanzarite"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Sash Catanzarite" title="Sash Catanzarite"/></a>
<a href="https://github.com/Suksham-sharma"><img src="https://avatars.githubusercontent.com/u/94667656?v=4&s=48" width="48" height="48" alt="Suksham-sharma" title="Suksham-sharma"/></a> <a href="https://github.com/T5-AndyML"><img src="https://avatars.githubusercontent.com/u/22801233?v=4&s=48" width="48" height="48" alt="T5-AndyML" title="T5-AndyML"/></a> <a href="https://github.com/tewatia"><img src="https://avatars.githubusercontent.com/u/22875334?v=4&s=48" width="48" height="48" alt="tewatia" title="tewatia"/></a> <a href="https://github.com/thejhinvirtuoso"><img src="https://avatars.githubusercontent.com/u/258521837?v=4&s=48" width="48" height="48" alt="thejhinvirtuoso" title="thejhinvirtuoso"/></a> <a href="https://github.com/travisp"><img src="https://avatars.githubusercontent.com/u/165698?v=4&s=48" width="48" height="48" alt="travisp" title="travisp"/></a> <a href="https://github.com/search?q=VAC"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="VAC" title="VAC"/></a> <a href="https://github.com/search?q=william%20arzt"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="william arzt" title="william arzt"/></a> <a href="https://github.com/yudshj"><img src="https://avatars.githubusercontent.com/u/16971372?v=4&s=48" width="48" height="48" alt="yudshj" title="yudshj"/></a> <a href="https://github.com/zknicker"><img src="https://avatars.githubusercontent.com/u/1164085?v=4&s=48" width="48" height="48" alt="zknicker" title="zknicker"/></a> <a href="https://github.com/0oAstro"><img src="https://avatars.githubusercontent.com/u/79555780?v=4&s=48" width="48" height="48" alt="0oAstro" title="0oAstro"/></a>
<a href="https://github.com/abhaymundhara"><img src="https://avatars.githubusercontent.com/u/62872231?v=4&s=48" width="48" height="48" alt="abhaymundhara" title="abhaymundhara"/></a> <a href="https://github.com/aduk059"><img src="https://avatars.githubusercontent.com/u/257603478?v=4&s=48" width="48" height="48" alt="aduk059" title="aduk059"/></a> <a href="https://github.com/aisling404"><img src="https://avatars.githubusercontent.com/u/211950534?v=4&s=48" width="48" height="48" alt="aisling404" title="aisling404"/></a> <a href="https://github.com/akramcodez"><img src="https://avatars.githubusercontent.com/u/179671552?v=4&s=48" width="48" height="48" alt="akramcodez" title="akramcodez"/></a> <a href="https://github.com/search?q=alejandro%20maza"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="alejandro maza" title="alejandro maza"/></a> <a href="https://github.com/Alex-Alaniz"><img src="https://avatars.githubusercontent.com/u/88956822?v=4&s=48" width="48" height="48" alt="Alex-Alaniz" title="Alex-Alaniz"/></a> <a href="https://github.com/alexanderatallah"><img src="https://avatars.githubusercontent.com/u/1011391?v=4&s=48" width="48" height="48" alt="alexanderatallah" title="alexanderatallah"/></a> <a href="https://github.com/alexstyl"><img src="https://avatars.githubusercontent.com/u/1665273?v=4&s=48" width="48" height="48" alt="alexstyl" title="alexstyl"/></a> <a href="https://github.com/AlexZhangji"><img src="https://avatars.githubusercontent.com/u/3280924?v=4&s=48" width="48" height="48" alt="AlexZhangji" title="AlexZhangji"/></a> <a href="https://github.com/andrewting19"><img src="https://avatars.githubusercontent.com/u/10536704?v=4&s=48" width="48" height="48" alt="andrewting19" title="andrewting19"/></a>
<a href="https://github.com/anpoirier"><img src="https://avatars.githubusercontent.com/u/1245729?v=4&s=48" width="48" height="48" alt="anpoirier" title="anpoirier"/></a> <a href="https://github.com/araa47"><img src="https://avatars.githubusercontent.com/u/22760261?v=4&s=48" width="48" height="48" alt="araa47" title="araa47"/></a> <a href="https://github.com/arthyn"><img src="https://avatars.githubusercontent.com/u/5466421?v=4&s=48" width="48" height="48" alt="arthyn" title="arthyn"/></a> <a href="https://github.com/Asleep123"><img src="https://avatars.githubusercontent.com/u/122379135?v=4&s=48" width="48" height="48" alt="Asleep123" title="Asleep123"/></a> <a href="https://github.com/search?q=Ayush%20Ojha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ayush Ojha" title="Ayush Ojha"/></a> <a href="https://github.com/Ayush10"><img src="https://avatars.githubusercontent.com/u/7945279?v=4&s=48" width="48" height="48" alt="Ayush10" title="Ayush10"/></a> <a href="https://github.com/bguidolim"><img src="https://avatars.githubusercontent.com/u/987360?v=4&s=48" width="48" height="48" alt="bguidolim" title="bguidolim"/></a> <a href="https://github.com/bolismauro"><img src="https://avatars.githubusercontent.com/u/771999?v=4&s=48" width="48" height="48" alt="bolismauro" title="bolismauro"/></a> <a href="https://github.com/caelum0x"><img src="https://avatars.githubusercontent.com/u/130079063?v=4&s=48" width="48" height="48" alt="caelum0x" title="caelum0x"/></a> <a href="https://github.com/championswimmer"><img src="https://avatars.githubusercontent.com/u/1327050?v=4&s=48" width="48" height="48" alt="championswimmer" title="championswimmer"/></a>
<a href="https://github.com/chenyuan99"><img src="https://avatars.githubusercontent.com/u/25518100?v=4&s=48" width="48" height="48" alt="chenyuan99" title="chenyuan99"/></a> <a href="https://github.com/Chloe-VP"><img src="https://avatars.githubusercontent.com/u/257371598?v=4&s=48" width="48" height="48" alt="Chloe-VP" title="Chloe-VP"/></a> <a href="https://github.com/search?q=Clawdbot%20Maintainers"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawdbot Maintainers" title="Clawdbot Maintainers"/></a> <a href="https://github.com/conhecendoia"><img src="https://avatars.githubusercontent.com/u/82890727?v=4&s=48" width="48" height="48" alt="conhecendoia" title="conhecendoia"/></a> <a href="https://github.com/dasilva333"><img src="https://avatars.githubusercontent.com/u/947827?v=4&s=48" width="48" height="48" alt="dasilva333" title="dasilva333"/></a> <a href="https://github.com/David-Marsh-Photo"><img src="https://avatars.githubusercontent.com/u/228404527?v=4&s=48" width="48" height="48" alt="David-Marsh-Photo" title="David-Marsh-Photo"/></a> <a href="https://github.com/deepsoumya617"><img src="https://avatars.githubusercontent.com/u/80877391?v=4&s=48" width="48" height="48" alt="deepsoumya617" title="deepsoumya617"/></a> <a href="https://github.com/search?q=Developer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Developer" title="Developer"/></a> <a href="https://github.com/search?q=Dimitrios%20Ploutarchos"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Dimitrios Ploutarchos" title="Dimitrios Ploutarchos"/></a> <a href="https://github.com/search?q=Drake%20Thomsen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Drake Thomsen" title="Drake Thomsen"/></a>
<a href="https://github.com/dvrshil"><img src="https://avatars.githubusercontent.com/u/81693876?v=4&s=48" width="48" height="48" alt="dvrshil" title="dvrshil"/></a> <a href="https://github.com/dxd5001"><img src="https://avatars.githubusercontent.com/u/1886046?v=4&s=48" width="48" height="48" alt="dxd5001" title="dxd5001"/></a> <a href="https://github.com/dylanneve1"><img src="https://avatars.githubusercontent.com/u/31746704?v=4&s=48" width="48" height="48" alt="dylanneve1" title="dylanneve1"/></a> <a href="https://github.com/search?q=Felix%20Krause"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Felix Krause" title="Felix Krause"/></a> <a href="https://github.com/foeken"><img src="https://avatars.githubusercontent.com/u/13864?v=4&s=48" width="48" height="48" alt="foeken" title="foeken"/></a> <a href="https://github.com/frankekn"><img src="https://avatars.githubusercontent.com/u/4488090?v=4&s=48" width="48" height="48" alt="frankekn" title="frankekn"/></a> <a href="https://github.com/fredheir"><img src="https://avatars.githubusercontent.com/u/3304869?v=4&s=48" width="48" height="48" alt="fredheir" title="fredheir"/></a> <a href="https://github.com/search?q=ganghyun%20kim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ganghyun kim" title="ganghyun kim"/></a> <a href="https://github.com/grrowl"><img src="https://avatars.githubusercontent.com/u/907140?v=4&s=48" width="48" height="48" alt="grrowl" title="grrowl"/></a> <a href="https://github.com/gtsifrikas"><img src="https://avatars.githubusercontent.com/u/8904378?v=4&s=48" width="48" height="48" alt="gtsifrikas" title="gtsifrikas"/></a>
<a href="https://github.com/HassanFleyah"><img src="https://avatars.githubusercontent.com/u/228002017?v=4&s=48" width="48" height="48" alt="HassanFleyah" title="HassanFleyah"/></a> <a href="https://github.com/HazAT"><img src="https://avatars.githubusercontent.com/u/363802?v=4&s=48" width="48" height="48" alt="HazAT" title="HazAT"/></a> <a href="https://github.com/hrdwdmrbl"><img src="https://avatars.githubusercontent.com/u/554881?v=4&s=48" width="48" height="48" alt="hrdwdmrbl" title="hrdwdmrbl"/></a> <a href="https://github.com/hugobarauna"><img src="https://avatars.githubusercontent.com/u/2719?v=4&s=48" width="48" height="48" alt="hugobarauna" title="hugobarauna"/></a> <a href="https://github.com/iamEvanYT"><img src="https://avatars.githubusercontent.com/u/47493765?v=4&s=48" width="48" height="48" alt="iamEvanYT" title="iamEvanYT"/></a> <a href="https://github.com/ichbinlucaskim"><img src="https://avatars.githubusercontent.com/u/125564751?v=4&s=48" width="48" height="48" alt="ichbinlucaskim" title="ichbinlucaskim"/></a> <a href="https://github.com/search?q=Jamie%20Openshaw"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jamie Openshaw" title="Jamie Openshaw"/></a> <a href="https://github.com/search?q=Jane"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jane" title="Jane"/></a> <a href="https://github.com/search?q=Jarvis%20Deploy"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis Deploy" title="Jarvis Deploy"/></a> <a href="https://github.com/search?q=Jefferson%20Nunn"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jefferson Nunn" title="Jefferson Nunn"/></a>
<a href="https://github.com/jogi47"><img src="https://avatars.githubusercontent.com/u/1710139?v=4&s=48" width="48" height="48" alt="jogi47" title="jogi47"/></a> <a href="https://github.com/kentaro"><img src="https://avatars.githubusercontent.com/u/3458?v=4&s=48" width="48" height="48" alt="kentaro" title="kentaro"/></a> <a href="https://github.com/search?q=Kevin%20Lin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kevin Lin" title="Kevin Lin"/></a> <a href="https://github.com/kira-ariaki"><img src="https://avatars.githubusercontent.com/u/257352493?v=4&s=48" width="48" height="48" alt="kira-ariaki" title="kira-ariaki"/></a> <a href="https://github.com/kitze"><img src="https://avatars.githubusercontent.com/u/1160594?v=4&s=48" width="48" height="48" alt="kitze" title="kitze"/></a> <a href="https://github.com/Kiwitwitter"><img src="https://avatars.githubusercontent.com/u/25277769?v=4&s=48" width="48" height="48" alt="Kiwitwitter" title="Kiwitwitter"/></a> <a href="https://github.com/levifig"><img src="https://avatars.githubusercontent.com/u/1605?v=4&s=48" width="48" height="48" alt="levifig" title="levifig"/></a> <a href="https://github.com/search?q=Lloyd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Lloyd" title="Lloyd"/></a> <a href="https://github.com/loganaden"><img src="https://avatars.githubusercontent.com/u/1688420?v=4&s=48" width="48" height="48" alt="loganaden" title="loganaden"/></a> <a href="https://github.com/longjos"><img src="https://avatars.githubusercontent.com/u/740160?v=4&s=48" width="48" height="48" alt="longjos" title="longjos"/></a>
<a href="https://github.com/loukotal"><img src="https://avatars.githubusercontent.com/u/18210858?v=4&s=48" width="48" height="48" alt="loukotal" title="loukotal"/></a> <a href="https://github.com/louzhixian"><img src="https://avatars.githubusercontent.com/u/7994361?v=4&s=48" width="48" height="48" alt="louzhixian" title="louzhixian"/></a> <a href="https://github.com/search?q=mac%20mimi"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="mac mimi" title="mac mimi"/></a> <a href="https://github.com/martinpucik"><img src="https://avatars.githubusercontent.com/u/5503097?v=4&s=48" width="48" height="48" alt="martinpucik" title="martinpucik"/></a> <a href="https://github.com/search?q=Matt%20mini"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Matt mini" title="Matt mini"/></a> <a href="https://github.com/mcaxtr"><img src="https://avatars.githubusercontent.com/u/7562095?v=4&s=48" width="48" height="48" alt="mcaxtr" title="mcaxtr"/></a> <a href="https://github.com/mertcicekci0"><img src="https://avatars.githubusercontent.com/u/179321902?v=4&s=48" width="48" height="48" alt="mertcicekci0" title="mertcicekci0"/></a> <a href="https://github.com/search?q=Miles"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Miles" title="Miles"/></a> <a href="https://github.com/mrdbstn"><img src="https://avatars.githubusercontent.com/u/58957632?v=4&s=48" width="48" height="48" alt="mrdbstn" title="mrdbstn"/></a> <a href="https://github.com/MSch"><img src="https://avatars.githubusercontent.com/u/7475?v=4&s=48" width="48" height="48" alt="MSch" title="MSch"/></a>
<a href="https://github.com/search?q=Mustafa%20Tag%20Eldeen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mustafa Tag Eldeen" title="Mustafa Tag Eldeen"/></a> <a href="https://github.com/mylukin"><img src="https://avatars.githubusercontent.com/u/1021019?v=4&s=48" width="48" height="48" alt="mylukin" title="mylukin"/></a> <a href="https://github.com/nathanbosse"><img src="https://avatars.githubusercontent.com/u/4040669?v=4&s=48" width="48" height="48" alt="nathanbosse" title="nathanbosse"/></a> <a href="https://github.com/ndraiman"><img src="https://avatars.githubusercontent.com/u/12609607?v=4&s=48" width="48" height="48" alt="ndraiman" title="ndraiman"/></a> <a href="https://github.com/nexty5870"><img src="https://avatars.githubusercontent.com/u/3869659?v=4&s=48" width="48" height="48" alt="nexty5870" title="nexty5870"/></a> <a href="https://github.com/Noctivoro"><img src="https://avatars.githubusercontent.com/u/183974570?v=4&s=48" width="48" height="48" alt="Noctivoro" title="Noctivoro"/></a> <a href="https://github.com/Omar-Khaleel"><img src="https://avatars.githubusercontent.com/u/240748662?v=4&s=48" width="48" height="48" alt="Omar-Khaleel" title="Omar-Khaleel"/></a> <a href="https://github.com/ozgur-polat"><img src="https://avatars.githubusercontent.com/u/26483942?v=4&s=48" width="48" height="48" alt="ozgur-polat" title="ozgur-polat"/></a> <a href="https://github.com/ppamment"><img src="https://avatars.githubusercontent.com/u/2122919?v=4&s=48" width="48" height="48" alt="ppamment" title="ppamment"/></a> <a href="https://github.com/prathamdby"><img src="https://avatars.githubusercontent.com/u/134331217?v=4&s=48" width="48" height="48" alt="prathamdby" title="prathamdby"/></a>
<a href="https://github.com/ptn1411"><img src="https://avatars.githubusercontent.com/u/57529765?v=4&s=48" width="48" height="48" alt="ptn1411" title="ptn1411"/></a> <a href="https://github.com/rafelbev"><img src="https://avatars.githubusercontent.com/u/467120?v=4&s=48" width="48" height="48" alt="rafelbev" title="rafelbev"/></a> <a href="https://github.com/reeltimeapps"><img src="https://avatars.githubusercontent.com/u/637338?v=4&s=48" width="48" height="48" alt="reeltimeapps" title="reeltimeapps"/></a> <a href="https://github.com/RLTCmpe"><img src="https://avatars.githubusercontent.com/u/10762242?v=4&s=48" width="48" height="48" alt="RLTCmpe" title="RLTCmpe"/></a> <a href="https://github.com/search?q=Rony%20Kelner"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rony Kelner" title="Rony Kelner"/></a> <a href="https://github.com/ryancnelson"><img src="https://avatars.githubusercontent.com/u/347171?v=4&s=48" width="48" height="48" alt="ryancnelson" title="ryancnelson"/></a> <a href="https://github.com/search?q=Samrat%20Jha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Samrat Jha" title="Samrat Jha"/></a> <a href="https://github.com/senoldogann"><img src="https://avatars.githubusercontent.com/u/45736551?v=4&s=48" width="48" height="48" alt="senoldogann" title="senoldogann"/></a> <a href="https://github.com/Seredeep"><img src="https://avatars.githubusercontent.com/u/22802816?v=4&s=48" width="48" height="48" alt="Seredeep" title="Seredeep"/></a> <a href="https://github.com/sergical"><img src="https://avatars.githubusercontent.com/u/3760543?v=4&s=48" width="48" height="48" alt="sergical" title="sergical"/></a>
<a href="https://github.com/shiv19"><img src="https://avatars.githubusercontent.com/u/9407019?v=4&s=48" width="48" height="48" alt="shiv19" title="shiv19"/></a> <a href="https://github.com/shiyuanhai"><img src="https://avatars.githubusercontent.com/u/1187370?v=4&s=48" width="48" height="48" alt="shiyuanhai" title="shiyuanhai"/></a> <a href="https://github.com/Shrinija17"><img src="https://avatars.githubusercontent.com/u/199155426?v=4&s=48" width="48" height="48" alt="Shrinija17" title="Shrinija17"/></a> <a href="https://github.com/siraht"><img src="https://avatars.githubusercontent.com/u/73152895?v=4&s=48" width="48" height="48" alt="siraht" title="siraht"/></a> <a href="https://github.com/snopoke"><img src="https://avatars.githubusercontent.com/u/249606?v=4&s=48" width="48" height="48" alt="snopoke" title="snopoke"/></a> <a href="https://github.com/stephenchen2025"><img src="https://avatars.githubusercontent.com/u/218387130?v=4&s=48" width="48" height="48" alt="stephenchen2025" title="stephenchen2025"/></a> <a href="https://github.com/search?q=techboss"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="techboss" title="techboss"/></a> <a href="https://github.com/testingabc321"><img src="https://avatars.githubusercontent.com/u/8577388?v=4&s=48" width="48" height="48" alt="testingabc321" title="testingabc321"/></a> <a href="https://github.com/search?q=The%20Admiral"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="The Admiral" title="The Admiral"/></a> <a href="https://github.com/thesash"><img src="https://avatars.githubusercontent.com/u/1166151?v=4&s=48" width="48" height="48" alt="thesash" title="thesash"/></a>
<a href="https://github.com/search?q=Vibe%20Kanban"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vibe Kanban" title="Vibe Kanban"/></a> <a href="https://github.com/vincentkoc"><img src="https://avatars.githubusercontent.com/u/25068?v=4&s=48" width="48" height="48" alt="vincentkoc" title="vincentkoc"/></a> <a href="https://github.com/voidserf"><img src="https://avatars.githubusercontent.com/u/477673?v=4&s=48" width="48" height="48" alt="voidserf" title="voidserf"/></a> <a href="https://github.com/search?q=Vultr-Clawd%20Admin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vultr-Clawd Admin" title="Vultr-Clawd Admin"/></a> <a href="https://github.com/search?q=Wimmie"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Wimmie" title="Wimmie"/></a> <a href="https://github.com/search?q=wolfred"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="wolfred" title="wolfred"/></a> <a href="https://github.com/wstock"><img src="https://avatars.githubusercontent.com/u/1394687?v=4&s=48" width="48" height="48" alt="wstock" title="wstock"/></a> <a href="https://github.com/wytheme"><img src="https://avatars.githubusercontent.com/u/5009358?v=4&s=48" width="48" height="48" alt="wytheme" title="wytheme"/></a> <a href="https://github.com/YangHuang2280"><img src="https://avatars.githubusercontent.com/u/201681634?v=4&s=48" width="48" height="48" alt="YangHuang2280" title="YangHuang2280"/></a> <a href="https://github.com/yazinsai"><img src="https://avatars.githubusercontent.com/u/1846034?v=4&s=48" width="48" height="48" alt="yazinsai" title="yazinsai"/></a>
<a href="https://github.com/yevhen"><img src="https://avatars.githubusercontent.com/u/107726?v=4&s=48" width="48" height="48" alt="yevhen" title="yevhen"/></a> <a href="https://github.com/YiWang24"><img src="https://avatars.githubusercontent.com/u/176262341?v=4&s=48" width="48" height="48" alt="YiWang24" title="YiWang24"/></a> <a href="https://github.com/search?q=ymat19"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ymat19" title="ymat19"/></a> <a href="https://github.com/search?q=Zach%20Knickerbocker"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Zach Knickerbocker" title="Zach Knickerbocker"/></a> <a href="https://github.com/zackerthescar"><img src="https://avatars.githubusercontent.com/u/38077284?v=4&s=48" width="48" height="48" alt="zackerthescar" title="zackerthescar"/></a> <a href="https://github.com/0xJonHoldsCrypto"><img src="https://avatars.githubusercontent.com/u/81202085?v=4&s=48" width="48" height="48" alt="0xJonHoldsCrypto" title="0xJonHoldsCrypto"/></a> <a href="https://github.com/aaronn"><img src="https://avatars.githubusercontent.com/u/1653630?v=4&s=48" width="48" height="48" alt="aaronn" title="aaronn"/></a> <a href="https://github.com/Alphonse-arianee"><img src="https://avatars.githubusercontent.com/u/254457365?v=4&s=48" width="48" height="48" alt="Alphonse-arianee" title="Alphonse-arianee"/></a> <a href="https://github.com/atalovesyou"><img src="https://avatars.githubusercontent.com/u/3534502?v=4&s=48" width="48" height="48" alt="atalovesyou" title="atalovesyou"/></a> <a href="https://github.com/search?q=Azade"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Azade" title="Azade"/></a>
<a href="https://github.com/carlulsoe"><img src="https://avatars.githubusercontent.com/u/34673973?v=4&s=48" width="48" height="48" alt="carlulsoe" title="carlulsoe"/></a> <a href="https://github.com/search?q=ddyo"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ddyo" title="ddyo"/></a> <a href="https://github.com/search?q=Erik"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Erik" title="Erik"/></a> <a href="https://github.com/jiulingyun"><img src="https://avatars.githubusercontent.com/u/126459548?v=4&s=48" width="48" height="48" alt="jiulingyun" title="jiulingyun"/></a> <a href="https://github.com/latitudeki5223"><img src="https://avatars.githubusercontent.com/u/119656367?v=4&s=48" width="48" height="48" alt="latitudeki5223" title="latitudeki5223"/></a> <a href="https://github.com/search?q=Manuel%20Maly"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Manuel Maly" title="Manuel Maly"/></a> <a href="https://github.com/search?q=Mourad%20Boustani"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mourad Boustani" title="Mourad Boustani"/></a> <a href="https://github.com/odrobnik"><img src="https://avatars.githubusercontent.com/u/333270?v=4&s=48" width="48" height="48" alt="odrobnik" title="odrobnik"/></a> <a href="https://github.com/pcty-nextgen-ios-builder"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="pcty-nextgen-ios-builder" title="pcty-nextgen-ios-builder"/></a> <a href="https://github.com/search?q=Quentin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Quentin" title="Quentin"/></a>
<a href="https://github.com/search?q=Randy%20Torres"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Randy Torres" title="Randy Torres"/></a> <a href="https://github.com/rhjoh"><img src="https://avatars.githubusercontent.com/u/105699450?v=4&s=48" width="48" height="48" alt="rhjoh" title="rhjoh"/></a> <a href="https://github.com/search?q=Rolf%20Fredheim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rolf Fredheim" title="Rolf Fredheim"/></a> <a href="https://github.com/ronak-guliani"><img src="https://avatars.githubusercontent.com/u/23518228?v=4&s=48" width="48" height="48" alt="ronak-guliani" title="ronak-guliani"/></a> <a href="https://github.com/search?q=William%20Stock"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="William Stock" title="William Stock"/></a>
</p>

View File

@@ -2,6 +2,100 @@
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>OpenClaw</title>
<item>
<title>2026.2.3</title>
<pubDate>Wed, 04 Feb 2026 17:47:10 -0800</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8900</sparkle:version>
<sparkle:shortVersionString>2026.2.3</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.3</h2>
<h3>Changes</h3>
<ul>
<li>Telegram: remove last <code>@ts-nocheck</code> from <code>bot-handlers.ts</code>, use Grammy types directly, deduplicate <code>StickerMetadata</code>. Zero <code>@ts-nocheck</code> remaining in <code>src/telegram/</code>. (#9206)</li>
<li>Telegram: remove <code>@ts-nocheck</code> from <code>bot-message.ts</code>, type deps via <code>Omit<BuildTelegramMessageContextParams></code>, widen <code>allMedia</code> to <code>TelegramMediaRef[]</code>. (#9180)</li>
<li>Telegram: remove <code>@ts-nocheck</code> from <code>bot.ts</code>, fix duplicate <code>bot.catch</code> error handler (Grammy overrides), remove dead reaction <code>message_thread_id</code> routing, harden sticker cache guard. (#9077)</li>
<li>Onboarding: add Cloudflare AI Gateway provider setup and docs. (#7914) Thanks @roerohan.</li>
<li>Onboarding: add Moonshot (.cn) auth choice and keep the China base URL when preserving defaults. (#7180) Thanks @waynelwz.</li>
<li>Docs: clarify tmux send-keys for TUI by splitting text and Enter. (#7737) Thanks @Wangnov.</li>
<li>Docs: mirror the landing page revamp for zh-CN (features, quickstart, docs directory, network model, credits). (#8994) Thanks @joshp123.</li>
<li>Messages: add per-channel and per-account responsePrefix overrides across channels. (#9001) Thanks @mudrii.</li>
<li>Cron: add announce delivery mode for isolated jobs (CLI + Control UI) and delivery mode config.</li>
<li>Cron: default isolated jobs to announce delivery; accept ISO 8601 <code>schedule.at</code> in tool inputs.</li>
<li>Cron: hard-migrate isolated jobs to announce/none delivery; drop legacy post-to-main/payload delivery fields and <code>atMs</code> inputs.</li>
<li>Cron: delete one-shot jobs after success by default; add <code>--keep-after-run</code> for CLI.</li>
<li>Cron: suppress messaging tools during announce delivery so summaries post consistently.</li>
<li>Cron: avoid duplicate deliveries when isolated runs send messages directly.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Heartbeat: allow explicit accountId routing for multi-account channels. (#8702) Thanks @lsh411.</li>
<li>TUI/Gateway: handle non-streaming finals, refresh history for non-local chat runs, and avoid event gap warnings for targeted tool streams. (#8432) Thanks @gumadeiras.</li>
<li>Shell completion: auto-detect and migrate slow dynamic patterns to cached files for faster terminal startup; add completion health checks to doctor/update/onboard.</li>
<li>Telegram: honor session model overrides in inline model selection. (#8193) Thanks @gildo.</li>
<li>Web UI: fix agent model selection saves for default/non-default agents and wrap long workspace paths. Thanks @Takhoffman.</li>
<li>Web UI: resolve header logo path when <code>gateway.controlUi.basePath</code> is set. (#7178) Thanks @Yeom-JinHo.</li>
<li>Web UI: apply button styling to the new-messages indicator.</li>
<li>Security: keep untrusted channel metadata out of system prompts (Slack/Discord). Thanks @KonstantinMirin.</li>
<li>Security: enforce sandboxed media paths for message tool attachments. (#9182) Thanks @victormier.</li>
<li>Security: require explicit credentials for gateway URL overrides to prevent credential leakage. (#8113) Thanks @victormier.</li>
<li>Security: gate <code>whatsapp_login</code> tool to owner senders and default-deny non-owner contexts. (#8768) Thanks @victormier.</li>
<li>Voice call: harden webhook verification with host allowlists/proxy trust and keep ngrok loopback bypass.</li>
<li>Voice call: add regression coverage for anonymous inbound caller IDs with allowlist policy. (#8104) Thanks @victormier.</li>
<li>Cron: accept epoch timestamps and 0ms durations in CLI <code>--at</code> parsing.</li>
<li>Cron: reload store data when the store file is recreated or mtime changes.</li>
<li>Cron: deliver announce runs directly, honor delivery mode, and respect wakeMode for summaries. (#8540) Thanks @tyler6204.</li>
<li>Telegram: include forward_from_chat metadata in forwarded messages and harden cron delivery target checks. (#8392) Thanks @Glucksberg.</li>
<li>macOS: fix cron payload summary rendering and ISO 8601 formatter concurrency safety.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.3/OpenClaw-2026.2.3.zip" length="22530161" type="application/octet-stream" sparkle:edSignature="7eHUaQC6cx87HWbcaPh9T437+LqfE9VtQBf4p9JBjIyBrqGYxxp9KPvI5unEjg55j9j2djCXhseSMeyyRmvYBg=="/>
</item>
<item>
<title>2026.2.2</title>
<pubDate>Tue, 03 Feb 2026 17:04:17 -0800</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8809</sparkle:version>
<sparkle:shortVersionString>2026.2.2</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.2</h2>
<h3>Changes</h3>
<ul>
<li>Feishu: add Feishu/Lark plugin support + docs. (#7313) Thanks @jiulingyun (openclaw-cn).</li>
<li>Web UI: add Agents dashboard for managing agent files, tools, skills, models, channels, and cron jobs.</li>
<li>Memory: implement the opt-in QMD backend for workspace memory. (#3160) Thanks @vignesh07.</li>
<li>Security: add healthcheck skill and bootstrap audit guidance. (#7641) Thanks @Takhoffman.</li>
<li>Config: allow setting a default subagent thinking level via <code>agents.defaults.subagents.thinking</code> (and per-agent <code>agents.list[].subagents.thinking</code>). (#7372) Thanks @tyler6204.</li>
<li>Docs: zh-CN translations seed + polish, pipeline guidance, nav/landing updates, and typo fixes. (#8202, #6995, #6619, #7242, #7303, #7415) Thanks @AaronWander, @taiyi747, @Explorer1092, @rendaoyuan, @joshp123, @lailoo.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Security: require operator.approvals for gateway /approve commands. (#1) Thanks @mitsuhiko, @yueyueL.</li>
<li>Security: Matrix allowlists now require full MXIDs; ambiguous name resolution no longer grants access. Thanks @MegaManSec.</li>
<li>Security: enforce access-group gating for Slack slash commands when channel type lookup fails.</li>
<li>Security: require validated shared-secret auth before skipping device identity on gateway connect.</li>
<li>Security: guard skill installer downloads with SSRF checks (block private/localhost URLs).</li>
<li>Security: harden Windows exec allowlist; block cmd.exe bypass via single &. Thanks @simecek.</li>
<li>fix(voice-call): harden inbound allowlist; reject anonymous callers; require Telnyx publicKey for allowlist; token-gate Twilio media streams; cap webhook body size (thanks @simecek)</li>
<li>Media understanding: apply SSRF guardrails to provider fetches; allow private baseUrl overrides explicitly.</li>
<li>fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)</li>
<li>Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.</li>
<li>Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.</li>
<li>fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)</li>
<li>Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.</li>
<li>Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed); completion prompt now handled by install/update.</li>
<li>TUI: block onboarding output while TUI is active and restore terminal state on exit.</li>
<li>CLI/Zsh completion: cache scripts in state dir and escape option descriptions to avoid invalid option errors.</li>
<li>fix(ui): resolve Control UI asset path correctly.</li>
<li>fix(ui): refresh agent files after external edits.</li>
<li>Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.</li>
<li>Tests: stub SSRF DNS pinning in web auto-reply + Gemini video coverage. (#6619) Thanks @joshp123.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.2/OpenClaw-2026.2.2.zip" length="22519052" type="application/octet-stream" sparkle:edSignature="a6viD+aS5EfY/RkPIPMfoQQNkJCk6QTdV5WobXFxyYwURskUm8/nXTHVXsCh1c5+0WKUnmlDIyf0i+6IWiavAA=="/>
</item>
<item>
<title>2026.2.1</title>
<pubDate>Mon, 02 Feb 2026 03:53:03 -0800</pubDate>
@@ -68,182 +162,5 @@
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.1/OpenClaw-2026.2.1.zip" length="22458919" type="application/octet-stream" sparkle:edSignature="kA/8VQlVdtYphcB1iuFrhWczwWKgkVZMfDfQ7T9WD405D8JKTv5CZ1n8lstIVkpk4xog3UhrfaaoTG8Bf8DMAQ=="/>
</item>
<item>
<title>2026.1.30</title>
<pubDate>Sat, 31 Jan 2026 14:29:57 +0100</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8469</sparkle:version>
<sparkle:shortVersionString>2026.1.30</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.1.30</h2>
<h3>Changes</h3>
<ul>
<li>CLI: add <code>completion</code> command (Zsh/Bash/PowerShell/Fish) and auto-setup during postinstall/onboarding.</li>
<li>CLI: add per-agent <code>models status</code> (<code>--agent</code> filter). (#4780) Thanks @jlowin.</li>
<li>Agents: add Kimi K2.5 to the synthetic model catalog. (#4407) Thanks @manikv12.</li>
<li>Auth: switch Kimi Coding to built-in provider; normalize OAuth profile email.</li>
<li>Auth: add MiniMax OAuth plugin + onboarding option. (#4521) Thanks @Maosghoul.</li>
<li>Agents: update pi SDK/API usage and dependencies.</li>
<li>Web UI: refresh sessions after chat commands and improve session display names.</li>
<li>Build: move TypeScript builds to <code>tsdown</code> + <code>tsgo</code> (faster builds, CI typechecks), update tsconfig target, and clean up lint rules.</li>
<li>Build: align npm tar override and bin metadata so the <code>openclaw</code> CLI entrypoint is preserved in npm publishes.</li>
<li>Docs: add pi/pi-dev docs and update OpenClaw branding + install links.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Security: restrict local path extraction in media parser to prevent LFI. (#4880)</li>
<li>Gateway: prevent token defaults from becoming the literal "undefined". (#4873) Thanks @Hisleren.</li>
<li>Control UI: fix assets resolution for npm global installs. (#4909) Thanks @YuriNachos.</li>
<li>macOS: avoid stderr pipe backpressure in gateway discovery. (#3304) Thanks @abhijeet117.</li>
<li>Telegram: normalize account token lookup for non-normalized IDs. (#5055) Thanks @jasonsschin.</li>
<li>Telegram: preserve delivery thread fallback and fix threadId handling in delivery context.</li>
<li>Telegram: fix HTML nesting for overlapping styles/links. (#4578) Thanks @ThanhNguyxn.</li>
<li>Telegram: accept numeric messageId/chatId in react actions. (#4533) Thanks @Ayush10.</li>
<li>Telegram: honor per-account proxy dispatcher via undici fetch. (#4456) Thanks @spiceoogway.</li>
<li>Telegram: scope skill commands to bound agent per bot. (#4360) Thanks @robhparker.</li>
<li>BlueBubbles: debounce by messageId to preserve attachments in text+image messages. (#4984)</li>
<li>Routing: prefer requesterOrigin over stale session entries for sub-agent announce delivery. (#4957)</li>
<li>Extensions: restore embedded extension discovery typings.</li>
<li>CLI: fix <code>tui:dev</code> port resolution.</li>
<li>LINE: fix status command TypeError. (#4651)</li>
<li>OAuth: skip expired-token warnings when refresh tokens are still valid. (#4593)</li>
<li>Build: skip redundant UI install step in Dockerfile. (#4584) Thanks @obviyus.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.1.30/OpenClaw-2026.1.30.zip" length="22458594" type="application/octet-stream" sparkle:edSignature="77/GuEcruKGgu2CJyMq+OVwzaJ2v1VzRQC9NmOirKO3uH5Nn5HaoouwrOHnOanrzlD4OvPW0FS5GH2E4Ntu4CQ=="/>
</item>
<item>
<title>2026.1.29</title>
<pubDate>Fri, 30 Jan 2026 06:24:15 +0100</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8345</sparkle:version>
<sparkle:shortVersionString>2026.1.29</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.1.29</h2>
Status: stable.
<h3>Changes</h3>
<ul>
<li>Rebrand: rename the npm package/CLI to <code>openclaw</code>, add a <code>openclaw</code> compatibility shim, and move extensions to the <code>@openclaw/*</code> scope.</li>
<li>Onboarding: strengthen security warning copy for beta + access control expectations.</li>
<li>Onboarding: add Venice API key to non-interactive flow. (#1893) Thanks @jonisjongithub.</li>
<li>Config: auto-migrate legacy state/config paths and keep config resolution consistent across legacy filenames.</li>
<li>Gateway: warn on hook tokens via query params; document header auth preference. (#2200) Thanks @YuriNachos.</li>
<li>Gateway: add dangerous Control UI device auth bypass flag + audit warnings. (#2248)</li>
<li>Doctor: warn on gateway exposure without auth. (#2016) Thanks @Alex-Alaniz.</li>
<li>Web UI: keep sub-agent announce replies visible in WebChat. (#1977) Thanks @andrescardonas7.</li>
<li>Browser: route browser control via gateway/node; remove standalone browser control command and control URL config.</li>
<li>Browser: route <code>browser.request</code> via node proxies when available; honor proxy timeouts; derive browser ports from <code>gateway.port</code>.</li>
<li>Browser: fall back to URL matching for extension relay target resolution. (#1999) Thanks @jonit-dev.</li>
<li>Telegram: allow caption param for media sends. (#1888) Thanks @mguellsegarra.</li>
<li>Telegram: support plugin sendPayload channelData (media/buttons) and validate plugin commands. (#1917) Thanks @JoshuaLelon.</li>
<li>Telegram: avoid block replies when streaming is disabled. (#1885) Thanks @ivancasco.</li>
<li>Telegram: add optional silent send flag (disable notifications). (#2382) Thanks @Suksham-sharma.</li>
<li>Telegram: support editing sent messages via message(action="edit"). (#2394) Thanks @marcelomar21.</li>
<li>Telegram: support quote replies for message tool and inbound context. (#2900) Thanks @aduk059.</li>
<li>Telegram: add sticker receive/send with vision caching. (#2629) Thanks @longjos.</li>
<li>Telegram: send sticker pixels to vision models. (#2650)</li>
<li>Telegram: keep topic IDs in restart sentinel notifications. (#1807) Thanks @hsrvc.</li>
<li>Discord: add configurable privileged gateway intents for presences/members. (#2266) Thanks @kentaro.</li>
<li>Slack: clear ack reaction after streamed replies. (#2044) Thanks @fancyboi999.</li>
<li>Matrix: switch plugin SDK to @vector-im/matrix-bot-sdk.</li>
<li>Tlon: format thread reply IDs as @ud. (#1837) Thanks @wca4a.</li>
<li>Tools: add per-sender group tool policies and fix precedence. (#1757) Thanks @adam91holt.</li>
<li>Agents: summarize dropped messages during compaction safeguard pruning. (#2509) Thanks @jogi47.</li>
<li>Agents: expand cron tool description with full schema docs. (#1988) Thanks @tomascupr.</li>
<li>Agents: honor tools.exec.safeBins in exec allowlist checks. (#2281)</li>
<li>Memory Search: allow extra paths for memory indexing (ignores symlinks). (#3600) Thanks @kira-ariaki.</li>
<li>Skills: add multi-image input support to Nano Banana Pro skill. (#1958) Thanks @tyler6204.</li>
<li>Skills: add missing dependency metadata for GitHub, Notion, Slack, Discord. (#1995) Thanks @jackheuberger.</li>
<li>Commands: group /help and /commands output with Telegram paging. (#2504) Thanks @hougangdev.</li>
<li>Routing: add per-account DM session scope and document multi-account isolation. (#3095) Thanks @jarvis-sam.</li>
<li>Routing: precompile session key regexes. (#1697) Thanks @Ray0907.</li>
<li>CLI: use Node's module compile cache for faster startup. (#2808) Thanks @pi0.</li>
<li>Auth: show copyable Google auth URL after ASCII prompt. (#1787) Thanks @robbyczgw-cla.</li>
<li>TUI: avoid width overflow when rendering selection lists. (#1686) Thanks @mossein.</li>
<li>macOS: finish OpenClaw app rename for macOS sources, bundle identifiers, and shared kit paths. (#2844) Thanks @fal3.</li>
<li>Branding: update launchd labels, mobile bundle IDs, and logging subsystems to bot.molt (legacy bundle ID migrations). Thanks @thewilloftheshadow.</li>
<li>macOS: limit project-local <code>node_modules/.bin</code> PATH preference to debug builds (reduce PATH hijacking risk).</li>
<li>macOS: keep custom SSH usernames in remote target. (#2046) Thanks @algal.</li>
<li>macOS: avoid crash when rendering code blocks by bumping Textual to 0.3.1. (#2033) Thanks @garricn.</li>
<li>Update: ignore dist/control-ui for dirty checks and restore after ui builds. (#1976) Thanks @Glucksberg.</li>
<li>Build: bundle A2UI assets during build and stop tracking generated bundles. (#2455) Thanks @0oAstro.</li>
<li>CI: increase Node heap size for macOS checks. (#1890) Thanks @realZachi.</li>
<li>Config: apply config.env before ${VAR} substitution. (#1813) Thanks @spanishflu-est1918.</li>
<li>Gateway: prefer newest session metadata when combining stores. (#1823) Thanks @emanuelst.</li>
<li>Docs: tighten Fly private deployment steps. (#2289) Thanks @dguido.</li>
<li>Docs: add migration guide for moving to a new machine. (#2381)</li>
<li>Docs: add Northflank one-click deployment guide. (#2167) Thanks @AdeboyeDN.</li>
<li>Docs: add Vercel AI Gateway to providers sidebar. (#1901) Thanks @jerilynzheng.</li>
<li>Docs: add Render deployment guide. (#1975) Thanks @anurag.</li>
<li>Docs: add Claude Max API Proxy guide. (#1875) Thanks @atalovesyou.</li>
<li>Docs: add DigitalOcean deployment guide. (#1870) Thanks @0xJonHoldsCrypto.</li>
<li>Docs: add Oracle Cloud (OCI) platform guide + cross-links. (#2333) Thanks @hirefrank.</li>
<li>Docs: add Raspberry Pi install guide. (#1871) Thanks @0xJonHoldsCrypto.</li>
<li>Docs: add GCP Compute Engine deployment guide. (#1848) Thanks @hougangdev.</li>
<li>Docs: add LINE channel guide. Thanks @thewilloftheshadow.</li>
<li>Docs: credit both contributors for Control UI refresh. (#1852) Thanks @EnzeD.</li>
<li>Docs: keep docs header sticky so navbar stays visible while scrolling. (#2445) Thanks @chenyuan99.</li>
<li>Docs: update exe.dev install instructions. (#https://github.com/openclaw/openclaw/pull/3047) Thanks @zackerthescar.</li>
</ul>
<h3>Breaking</h3>
<ul>
<li><strong>BREAKING:</strong> Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed).</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796)</li>
<li>Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R.</li>
<li>Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald.</li>
<li>Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald.</li>
<li>Agents: prevent retries on oversized image errors and surface size limits. (#2871) Thanks @Suksham-sharma.</li>
<li>Agents: inherit provider baseUrl/api for inline models. (#2740) Thanks @lploc94.</li>
<li>Memory Search: keep auto provider model defaults and only include remote when configured. (#2576) Thanks @papago2355.</li>
<li>Telegram: include AccountId in native command context for multi-agent routing. (#2942) Thanks @Chloe-VP.</li>
<li>Telegram: handle video note attachments in media extraction. (#2905) Thanks @mylukin.</li>
<li>TTS: read OPENAI_TTS_BASE_URL at runtime instead of module load to honor config.env. (#3341) Thanks @hclsys.</li>
<li>macOS: auto-scroll to bottom when sending a new message while scrolled up. (#2471) Thanks @kennyklee.</li>
<li>Web UI: auto-expand the chat compose textarea while typing (with sensible max height). (#2950) Thanks @shivamraut101.</li>
<li>Gateway: prevent crashes on transient network errors (fetch failures, timeouts, DNS). Added fatal error detection to only exit on truly critical errors. Fixes #2895, #2879, #2873. (#2980) Thanks @elliotsecops.</li>
<li>Agents: guard channel tool listActions to avoid plugin crashes. (#2859) Thanks @mbelinky.</li>
<li>Discord: stop resolveDiscordTarget from passing directory params into messaging target parsers. Fixes #3167. Thanks @thewilloftheshadow.</li>
<li>Discord: avoid resolving bare channel names to user DMs when a username matches. Thanks @thewilloftheshadow.</li>
<li>Discord: fix directory config type import for target resolution. Thanks @thewilloftheshadow.</li>
<li>Providers: update MiniMax API endpoint and compatibility mode. (#3064) Thanks @hlbbbbbbb.</li>
<li>Telegram: treat more network errors as recoverable in polling. (#3013) Thanks @ryancontent.</li>
<li>Discord: resolve usernames to user IDs for outbound messages. (#2649) Thanks @nonggialiang.</li>
<li>Providers: update Moonshot Kimi model references to kimi-k2.5. (#2762) Thanks @MarvinCui.</li>
<li>Gateway: suppress AbortError and transient network errors in unhandled rejections. (#2451) Thanks @Glucksberg.</li>
<li>TTS: keep /tts status replies on text-only commands and avoid duplicate block-stream audio. (#2451) Thanks @Glucksberg.</li>
<li>Security: pin npm overrides to keep tar@7.5.4 for install toolchains.</li>
<li>Security: properly test Windows ACL audit for config includes. (#2403) Thanks @dominicnunez.</li>
<li>CLI: recognize versioned Node executables when parsing argv. (#2490) Thanks @David-Marsh-Photo.</li>
<li>CLI: avoid prompting for gateway runtime under the spinner. (#2874)</li>
<li>BlueBubbles: coalesce inbound URL link preview messages. (#1981) Thanks @tyler6204.</li>
<li>Cron: allow payloads containing "heartbeat" in event filter. (#2219) Thanks @dwfinkelstein.</li>
<li>CLI: avoid loading config for global help/version while registering plugin commands. (#2212) Thanks @dial481.</li>
<li>Agents: include memory.md when bootstrapping memory context. (#2318) Thanks @czekaj.</li>
<li>Agents: release session locks on process termination and cover more signals. (#2483) Thanks @janeexai.</li>
<li>Agents: skip cooldowned providers during model failover. (#2143) Thanks @YiWang24.</li>
<li>Telegram: harden polling + retry behavior for transient network errors and Node 22 transport issues. (#2420) Thanks @techboss.</li>
<li>Telegram: ignore non-forum group message_thread_id while preserving DM thread sessions. (#2731) Thanks @dylanneve1.</li>
<li>Telegram: wrap reasoning italics per line to avoid raw underscores. (#2181) Thanks @YuriNachos.</li>
<li>Telegram: centralize API error logging for delivery and bot calls. (#2492) Thanks @altryne.</li>
<li>Voice Call: enforce Twilio webhook signature verification for ngrok URLs; disable ngrok free tier bypass by default.</li>
<li>Security: harden Tailscale Serve auth by validating identity via local tailscaled before trusting headers.</li>
<li>Media: fix text attachment MIME misclassification with CSV/TSV inference and UTF-16 detection; add XML attribute escaping for file output. (#3628) Thanks @frankekn.</li>
<li>Build: align memory-core peer dependency with lockfile.</li>
<li>Security: add mDNS discovery mode with minimal default to reduce information disclosure. (#1882) Thanks @orlyjamie.</li>
<li>Security: harden URL fetches with DNS pinning to reduce rebinding risk. Thanks Chris Zheng.</li>
<li>Web UI: improve WebChat image paste previews and allow image-only sends. (#1925) Thanks @smartprogrammer93.</li>
<li>Security: wrap external hook content by default with a per-hook opt-out. (#1827) Thanks @mertcicekci0.</li>
<li>Gateway: default auth now fail-closed (token/password required; Tailscale Serve identity remains allowed).</li>
<li>Gateway: treat loopback + non-local Host connections as remote unless trusted proxy headers are present.</li>
<li>Onboarding: remove unsupported gateway auth "off" choice from onboarding/configure flows and CLI flags.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.1.29/OpenClaw-2026.1.29.zip" length="22458204" type="application/octet-stream" sparkle:edSignature="HqHwZHQyG/CEfBuQnQ/RffJQPKpSbCVrho9C6rgt93S5ek4AH6hUhB3BBKY8sbX1IVFATKK5QZZNE0YPAf7eBw=="/>
</item>
</channel>
</rss>
</rss>

View File

@@ -21,8 +21,8 @@ android {
applicationId = "ai.openclaw.android"
minSdk = 31
targetSdk = 36
versionCode = 202602010
versionName = "2026.2.1"
versionCode = 202602030
versionName = "2026.2.6"
}
buildTypes {

View File

@@ -19,9 +19,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.2.1</string>
<string>2026.2.6</string>
<key>CFBundleVersion</key>
<string>20260201</string>
<string>20260202</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>

View File

@@ -17,8 +17,8 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>2026.2.1</string>
<string>2026.2.6</string>
<key>CFBundleVersion</key>
<string>20260201</string>
<string>20260202</string>
</dict>
</plist>

View File

@@ -81,8 +81,8 @@ targets:
properties:
CFBundleDisplayName: OpenClaw
CFBundleIconName: AppIcon
CFBundleShortVersionString: "2026.2.1"
CFBundleVersion: "20260201"
CFBundleShortVersionString: "2026.2.6"
CFBundleVersion: "20260202"
UILaunchScreen: {}
UIApplicationSceneManifest:
UIApplicationSupportsMultipleScenes: false
@@ -130,5 +130,5 @@ targets:
path: Tests/Info.plist
properties:
CFBundleDisplayName: OpenClawTests
CFBundleShortVersionString: "2026.2.1"
CFBundleVersion: "20260201"
CFBundleShortVersionString: "2026.2.6"
CFBundleVersion: "20260202"

View File

@@ -20,9 +20,11 @@ extension CronJobEditor {
self.wakeMode = job.wakeMode
switch job.schedule {
case let .at(atMs):
case let .at(at):
self.scheduleKind = .at
self.atDate = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
if let date = CronSchedule.parseAtDate(at) {
self.atDate = date
}
case let .every(everyMs, _):
self.scheduleKind = .every
self.everyText = self.formatDuration(ms: everyMs)
@@ -36,19 +38,22 @@ extension CronJobEditor {
case let .systemEvent(text):
self.payloadKind = .systemEvent
self.systemEventText = text
case let .agentTurn(message, thinking, timeoutSeconds, deliver, channel, to, bestEffortDeliver):
case let .agentTurn(message, thinking, timeoutSeconds, _, _, _, _):
self.payloadKind = .agentTurn
self.agentMessage = message
self.thinking = thinking ?? ""
self.timeoutSeconds = timeoutSeconds.map(String.init) ?? ""
self.deliver = deliver ?? false
let trimmed = (channel ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
self.channel = trimmed.isEmpty ? "last" : trimmed
self.to = to ?? ""
self.bestEffortDeliver = bestEffortDeliver ?? false
}
self.postPrefix = job.isolation?.postToMainPrefix ?? "Cron"
if let delivery = job.delivery {
self.deliveryMode = delivery.mode == .announce ? .announce : .none
let trimmed = (delivery.channel ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
self.channel = trimmed.isEmpty ? "last" : trimmed
self.to = delivery.to ?? ""
self.bestEffortDeliver = delivery.bestEffort ?? false
} else if self.sessionTarget == .isolated {
self.deliveryMode = .announce
}
}
func save() {
@@ -88,15 +93,29 @@ extension CronJobEditor {
}
if self.sessionTarget == .isolated {
let trimmed = self.postPrefix.trimmingCharacters(in: .whitespacesAndNewlines)
root["isolation"] = [
"postToMainPrefix": trimmed.isEmpty ? "Cron" : trimmed,
]
root["delivery"] = self.buildDelivery()
}
return root.mapValues { AnyCodable($0) }
}
func buildDelivery() -> [String: Any] {
let mode = self.deliveryMode == .announce ? "announce" : "none"
var delivery: [String: Any] = ["mode": mode]
if self.deliveryMode == .announce {
let trimmed = self.channel.trimmingCharacters(in: .whitespacesAndNewlines)
delivery["channel"] = trimmed.isEmpty ? "last" : trimmed
let to = self.to.trimmingCharacters(in: .whitespacesAndNewlines)
if !to.isEmpty { delivery["to"] = to }
if self.bestEffortDeliver {
delivery["bestEffort"] = true
} else if self.job?.delivery?.bestEffort == true {
delivery["bestEffort"] = false
}
}
return delivery
}
func trimmed(_ value: String) -> String {
value.trimmingCharacters(in: .whitespacesAndNewlines)
}
@@ -115,7 +134,7 @@ extension CronJobEditor {
func buildSchedule() throws -> [String: Any] {
switch self.scheduleKind {
case .at:
return ["kind": "at", "atMs": Int(self.atDate.timeIntervalSince1970 * 1000)]
return ["kind": "at", "at": CronSchedule.formatIsoDate(self.atDate)]
case .every:
guard let ms = Self.parseDurationMs(self.everyText) else {
throw NSError(
@@ -209,14 +228,6 @@ extension CronJobEditor {
let thinking = self.thinking.trimmingCharacters(in: .whitespacesAndNewlines)
if !thinking.isEmpty { payload["thinking"] = thinking }
if let n = Int(self.timeoutSeconds), n > 0 { payload["timeoutSeconds"] = n }
payload["deliver"] = self.deliver
if self.deliver {
let trimmed = self.channel.trimmingCharacters(in: .whitespacesAndNewlines)
payload["channel"] = trimmed.isEmpty ? "last" : trimmed
let to = self.to.trimmingCharacters(in: .whitespacesAndNewlines)
if !to.isEmpty { payload["to"] = to }
payload["bestEffortDeliver"] = self.bestEffortDeliver
}
return payload
}

View File

@@ -13,13 +13,12 @@ extension CronJobEditor {
self.payloadKind = .agentTurn
self.agentMessage = "Run diagnostic"
self.deliver = true
self.deliveryMode = .announce
self.channel = "last"
self.to = "+15551230000"
self.thinking = "low"
self.timeoutSeconds = "90"
self.bestEffortDeliver = true
self.postPrefix = "Cron"
_ = self.buildAgentTurnPayload()
_ = try? self.buildPayload()

View File

@@ -16,23 +16,20 @@ struct CronJobEditor: View {
+ "Use an isolated session for agent turns so your main chat stays clean."
static let sessionTargetNote =
"Main jobs post a system event into the current main session. "
+ "Isolated jobs run OpenClaw in a dedicated session and can deliver results (WhatsApp/Telegram/Discord/etc)."
+ "Isolated jobs run OpenClaw in a dedicated session and can announce results to a channel."
static let scheduleKindNote =
"“At” runs once, “Every” repeats with a duration, “Cron” uses a 5-field Unix expression."
static let isolatedPayloadNote =
"Isolated jobs always run an agent turn. The result can be delivered to a channel, "
+ "and a short summary is posted back to your main chat."
"Isolated jobs always run an agent turn. Announce sends a short summary to a channel."
static let mainPayloadNote =
"System events are injected into the current main session. Agent turns require an isolated session target."
static let mainSummaryNote =
"Controls the label used when posting the completion summary back to the main session."
@State var name: String = ""
@State var description: String = ""
@State var agentId: String = ""
@State var enabled: Bool = true
@State var sessionTarget: CronSessionTarget = .main
@State var wakeMode: CronWakeMode = .nextHeartbeat
@State var wakeMode: CronWakeMode = .now
@State var deleteAfterRun: Bool = false
enum ScheduleKind: String, CaseIterable, Identifiable { case at, every, cron; var id: String { rawValue } }
@@ -46,13 +43,13 @@ struct CronJobEditor: View {
@State var payloadKind: PayloadKind = .systemEvent
@State var systemEventText: String = ""
@State var agentMessage: String = ""
@State var deliver: Bool = false
enum DeliveryChoice: String, CaseIterable, Identifiable { case announce, none; var id: String { rawValue } }
@State var deliveryMode: DeliveryChoice = .announce
@State var channel: String = "last"
@State var to: String = ""
@State var thinking: String = ""
@State var timeoutSeconds: String = ""
@State var bestEffortDeliver: Bool = false
@State var postPrefix: String = "Cron"
var channelOptions: [String] {
let ordered = self.channelsStore.orderedChannelIds()
@@ -122,8 +119,8 @@ struct CronJobEditor: View {
GridRow {
self.gridLabel("Wake mode")
Picker("", selection: self.$wakeMode) {
Text("next-heartbeat").tag(CronWakeMode.nextHeartbeat)
Text("now").tag(CronWakeMode.now)
Text("next-heartbeat").tag(CronWakeMode.nextHeartbeat)
}
.labelsHidden()
.pickerStyle(.segmented)
@@ -248,27 +245,6 @@ struct CronJobEditor: View {
}
}
if self.sessionTarget == .isolated {
GroupBox("Main session summary") {
Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) {
GridRow {
self.gridLabel("Prefix")
TextField("Cron", text: self.$postPrefix)
.textFieldStyle(.roundedBorder)
.frame(maxWidth: .infinity)
}
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text(
Self.mainSummaryNote)
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.vertical, 2)
@@ -340,13 +316,17 @@ struct CronJobEditor: View {
.frame(width: 180, alignment: .leading)
}
GridRow {
self.gridLabel("Deliver")
Toggle("Deliver result to a channel", isOn: self.$deliver)
.toggleStyle(.switch)
self.gridLabel("Delivery")
Picker("", selection: self.$deliveryMode) {
Text("Announce summary").tag(DeliveryChoice.announce)
Text("None").tag(DeliveryChoice.none)
}
.labelsHidden()
.pickerStyle(.segmented)
}
}
if self.deliver {
if self.deliveryMode == .announce {
Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) {
GridRow {
self.gridLabel("Channel")
@@ -367,7 +347,7 @@ struct CronJobEditor: View {
}
GridRow {
self.gridLabel("Best-effort")
Toggle("Do not fail the job if delivery fails", isOn: self.$bestEffortDeliver)
Toggle("Do not fail the job if announce fails", isOn: self.$bestEffortDeliver)
.toggleStyle(.switch)
}
}

View File

@@ -14,12 +14,26 @@ enum CronWakeMode: String, CaseIterable, Identifiable, Codable {
var id: String { self.rawValue }
}
enum CronDeliveryMode: String, CaseIterable, Identifiable, Codable {
case none
case announce
var id: String { self.rawValue }
}
struct CronDelivery: Codable, Equatable {
var mode: CronDeliveryMode
var channel: String?
var to: String?
var bestEffort: Bool?
}
enum CronSchedule: Codable, Equatable {
case at(atMs: Int)
case at(at: String)
case every(everyMs: Int, anchorMs: Int?)
case cron(expr: String, tz: String?)
enum CodingKeys: String, CodingKey { case kind, atMs, everyMs, anchorMs, expr, tz }
enum CodingKeys: String, CodingKey { case kind, at, atMs, everyMs, anchorMs, expr, tz }
var kind: String {
switch self {
@@ -34,7 +48,21 @@ enum CronSchedule: Codable, Equatable {
let kind = try container.decode(String.self, forKey: .kind)
switch kind {
case "at":
self = try .at(atMs: container.decode(Int.self, forKey: .atMs))
if let at = try container.decodeIfPresent(String.self, forKey: .at),
!at.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
self = .at(at: at)
return
}
if let atMs = try container.decodeIfPresent(Int.self, forKey: .atMs) {
let date = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
self = .at(at: Self.formatIsoDate(date))
return
}
throw DecodingError.dataCorruptedError(
forKey: .at,
in: container,
debugDescription: "Missing schedule.at")
case "every":
self = try .every(
everyMs: container.decode(Int.self, forKey: .everyMs),
@@ -55,8 +83,8 @@ enum CronSchedule: Codable, Equatable {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.kind, forKey: .kind)
switch self {
case let .at(atMs):
try container.encode(atMs, forKey: .atMs)
case let .at(at):
try container.encode(at, forKey: .at)
case let .every(everyMs, anchorMs):
try container.encode(everyMs, forKey: .everyMs)
try container.encodeIfPresent(anchorMs, forKey: .anchorMs)
@@ -65,6 +93,25 @@ enum CronSchedule: Codable, Equatable {
try container.encodeIfPresent(tz, forKey: .tz)
}
}
static func parseAtDate(_ value: String) -> Date? {
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty { return nil }
if let date = makeIsoFormatter(withFractional: true).date(from: trimmed) { return date }
return makeIsoFormatter(withFractional: false).date(from: trimmed)
}
static func formatIsoDate(_ date: Date) -> String {
makeIsoFormatter(withFractional: false).string(from: date)
}
private static func makeIsoFormatter(withFractional: Bool) -> ISO8601DateFormatter {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = withFractional
? [.withInternetDateTime, .withFractionalSeconds]
: [.withInternetDateTime]
return formatter
}
}
enum CronPayload: Codable, Equatable {
@@ -131,10 +178,6 @@ enum CronPayload: Codable, Equatable {
}
}
struct CronIsolation: Codable, Equatable {
var postToMainPrefix: String?
}
struct CronJobState: Codable, Equatable {
var nextRunAtMs: Int?
var runningAtMs: Int?
@@ -157,7 +200,7 @@ struct CronJob: Identifiable, Codable, Equatable {
let sessionTarget: CronSessionTarget
let wakeMode: CronWakeMode
let payload: CronPayload
let isolation: CronIsolation?
let delivery: CronDelivery?
let state: CronJobState
var displayName: String {

View File

@@ -17,9 +17,11 @@ extension CronSettings {
func scheduleSummary(_ schedule: CronSchedule) -> String {
switch schedule {
case let .at(atMs):
let date = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
return "at \(date.formatted(date: .abbreviated, time: .standard))"
case let .at(at):
if let date = CronSchedule.parseAtDate(at) {
return "at \(date.formatted(date: .abbreviated, time: .standard))"
}
return "at \(at)"
case let .every(everyMs, _):
return "every \(self.formatDuration(ms: everyMs))"
case let .cron(expr, tz):

View File

@@ -128,7 +128,7 @@ extension CronSettings {
.foregroundStyle(.orange)
.textSelection(.enabled)
}
self.payloadSummary(job.payload)
self.payloadSummary(job)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(10)
@@ -205,8 +205,9 @@ extension CronSettings {
.padding(.vertical, 4)
}
func payloadSummary(_ payload: CronPayload) -> some View {
VStack(alignment: .leading, spacing: 6) {
func payloadSummary(_ job: CronJob) -> some View {
let payload = job.payload
return VStack(alignment: .leading, spacing: 6) {
Text("Payload")
.font(.caption.weight(.semibold))
.foregroundStyle(.secondary)
@@ -215,7 +216,7 @@ extension CronSettings {
Text(text)
.font(.callout)
.textSelection(.enabled)
case let .agentTurn(message, thinking, timeoutSeconds, deliver, provider, to, _):
case let .agentTurn(message, thinking, timeoutSeconds, _, _, _, _):
VStack(alignment: .leading, spacing: 4) {
Text(message)
.font(.callout)
@@ -223,10 +224,19 @@ extension CronSettings {
HStack(spacing: 8) {
if let thinking, !thinking.isEmpty { StatusPill(text: "think \(thinking)", tint: .secondary) }
if let timeoutSeconds { StatusPill(text: "\(timeoutSeconds)s", tint: .secondary) }
if deliver ?? false {
StatusPill(text: "deliver", tint: .secondary)
if let provider, !provider.isEmpty { StatusPill(text: provider, tint: .secondary) }
if let to, !to.isEmpty { StatusPill(text: to, tint: .secondary) }
if job.sessionTarget == .isolated {
let delivery = job.delivery
if let delivery {
if delivery.mode == .announce {
StatusPill(text: "announce", tint: .secondary)
if let channel = delivery.channel, !channel.isEmpty {
StatusPill(text: channel, tint: .secondary)
}
if let to = delivery.to, !to.isEmpty { StatusPill(text: to, tint: .secondary) }
} else {
StatusPill(text: "no delivery", tint: .secondary)
}
}
}
}
}

View File

@@ -21,11 +21,11 @@ struct CronSettings_Previews: PreviewProvider {
message: "Summarize inbox",
thinking: "low",
timeoutSeconds: 600,
deliver: true,
channel: "last",
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "Cron"),
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "last", to: nil, bestEffort: true),
state: CronJobState(
nextRunAtMs: Int(Date().addingTimeInterval(3600).timeIntervalSince1970 * 1000),
runningAtMs: nil,
@@ -75,11 +75,11 @@ extension CronSettings {
message: "Summarize",
thinking: "low",
timeoutSeconds: 120,
deliver: true,
channel: "whatsapp",
to: "+15551234567",
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "[cron] "),
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "whatsapp", to: "+15551234567", bestEffort: true),
state: CronJobState(
nextRunAtMs: 1_700_000_200_000,
runningAtMs: nil,
@@ -111,7 +111,7 @@ extension CronSettings {
_ = view.detailCard(job)
_ = view.runHistoryCard(job)
_ = view.runRow(run)
_ = view.payloadSummary(job.payload)
_ = view.payloadSummary(job)
_ = view.scheduleSummary(job.schedule)
_ = view.statusTint(job.state.lastStatus)
_ = view.nextRunLabel(Date())

View File

@@ -335,7 +335,7 @@ extension OnboardingView {
.multilineTextAlignment(.center)
.frame(maxWidth: 540)
.fixedSize(horizontal: false, vertical: true)
Text("OpenClaw supports any model — we strongly recommend Opus 4.5 for the best experience.")
Text("OpenClaw supports any model — we strongly recommend Opus 4.6 for the best experience.")
.font(.callout)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)

View File

@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.2.1</string>
<string>2026.2.6</string>
<key>CFBundleVersion</key>
<string>202602010</string>
<string>202602020</string>
<key>CFBundleIconFile</key>
<string>OpenClaw</string>
<key>CFBundleURLTypes</key>

View File

@@ -169,7 +169,7 @@ extension SessionRow {
systemSent: true,
abortedLastRun: true,
tokens: SessionTokenStats(input: 5000, output: 1200, total: 6200, contextTokens: 200_000),
model: "claude-opus-4-5"),
model: "claude-opus-4-6"),
SessionRow(
id: "global",
key: "global",
@@ -242,7 +242,7 @@ struct SessionStoreSnapshot {
@MainActor
enum SessionLoader {
static let fallbackModel = "claude-opus-4-5"
static let fallbackModel = "claude-opus-4-6"
static let fallbackContextTokens = 200_000
static let defaultStorePath = standardize(

View File

@@ -589,20 +589,24 @@ public struct AgentIdentityResult: Codable, Sendable {
public let agentid: String
public let name: String?
public let avatar: String?
public let emoji: String?
public init(
agentid: String,
name: String?,
avatar: String?
avatar: String?,
emoji: String?
) {
self.agentid = agentid
self.name = name
self.avatar = avatar
self.emoji = emoji
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case avatar
case emoji
}
}
@@ -1115,6 +1119,35 @@ public struct SessionsCompactParams: Codable, Sendable {
}
}
public struct SessionsUsageParams: Codable, Sendable {
public let key: String?
public let startdate: String?
public let enddate: String?
public let limit: Int?
public let includecontextweight: Bool?
public init(
key: String?,
startdate: String?,
enddate: String?,
limit: Int?,
includecontextweight: Bool?
) {
self.key = key
self.startdate = startdate
self.enddate = enddate
self.limit = limit
self.includecontextweight = includecontextweight
}
private enum CodingKeys: String, CodingKey {
case key
case startdate = "startDate"
case enddate = "endDate"
case limit
case includecontextweight = "includeContextWeight"
}
}
public struct ConfigGetParams: Codable, Sendable {
}
@@ -1556,6 +1589,157 @@ public struct AgentSummary: Codable, Sendable {
}
}
public struct AgentsFileEntry: Codable, Sendable {
public let name: String
public let path: String
public let missing: Bool
public let size: Int?
public let updatedatms: Int?
public let content: String?
public init(
name: String,
path: String,
missing: Bool,
size: Int?,
updatedatms: Int?,
content: String?
) {
self.name = name
self.path = path
self.missing = missing
self.size = size
self.updatedatms = updatedatms
self.content = content
}
private enum CodingKeys: String, CodingKey {
case name
case path
case missing
case size
case updatedatms = "updatedAtMs"
case content
}
}
public struct AgentsFilesListParams: Codable, Sendable {
public let agentid: String
public init(
agentid: String
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct AgentsFilesListResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let files: [AgentsFileEntry]
public init(
agentid: String,
workspace: String,
files: [AgentsFileEntry]
) {
self.agentid = agentid
self.workspace = workspace
self.files = files
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case files
}
}
public struct AgentsFilesGetParams: Codable, Sendable {
public let agentid: String
public let name: String
public init(
agentid: String,
name: String
) {
self.agentid = agentid
self.name = name
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
}
}
public struct AgentsFilesGetResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsFilesSetParams: Codable, Sendable {
public let agentid: String
public let name: String
public let content: String
public init(
agentid: String,
name: String,
content: String
) {
self.agentid = agentid
self.name = name
self.content = content
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case content
}
}
public struct AgentsFilesSetResult: Codable, Sendable {
public let ok: Bool
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
ok: Bool,
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.ok = ok
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case ok
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsListParams: Codable, Sendable {
}
@@ -1630,6 +1814,16 @@ public struct ModelsListResult: Codable, Sendable {
}
public struct SkillsStatusParams: Codable, Sendable {
public let agentid: String?
public init(
agentid: String?
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct SkillsBinsParams: Codable, Sendable {
@@ -1707,7 +1901,7 @@ public struct CronJob: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let isolation: [String: AnyCodable]?
public let delivery: [String: AnyCodable]?
public let state: [String: AnyCodable]
public init(
@@ -1723,7 +1917,7 @@ public struct CronJob: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
isolation: [String: AnyCodable]?,
delivery: [String: AnyCodable]?,
state: [String: AnyCodable]
) {
self.id = id
@@ -1738,7 +1932,7 @@ public struct CronJob: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.isolation = isolation
self.delivery = delivery
self.state = state
}
private enum CodingKeys: String, CodingKey {
@@ -1754,7 +1948,7 @@ public struct CronJob: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case isolation
case delivery
case state
}
}
@@ -1785,7 +1979,7 @@ public struct CronAddParams: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let isolation: [String: AnyCodable]?
public let delivery: [String: AnyCodable]?
public init(
name: String,
@@ -1797,7 +1991,7 @@ public struct CronAddParams: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
isolation: [String: AnyCodable]?
delivery: [String: AnyCodable]?
) {
self.name = name
self.agentid = agentid
@@ -1808,7 +2002,7 @@ public struct CronAddParams: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.isolation = isolation
self.delivery = delivery
}
private enum CodingKeys: String, CodingKey {
case name
@@ -1820,7 +2014,7 @@ public struct CronAddParams: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case isolation
case delivery
}
}
@@ -1831,6 +2025,8 @@ public struct CronRunLogEntry: Codable, Sendable {
public let status: AnyCodable?
public let error: String?
public let summary: String?
public let sessionid: String?
public let sessionkey: String?
public let runatms: Int?
public let durationms: Int?
public let nextrunatms: Int?
@@ -1842,6 +2038,8 @@ public struct CronRunLogEntry: Codable, Sendable {
status: AnyCodable?,
error: String?,
summary: String?,
sessionid: String?,
sessionkey: String?,
runatms: Int?,
durationms: Int?,
nextrunatms: Int?
@@ -1852,6 +2050,8 @@ public struct CronRunLogEntry: Codable, Sendable {
self.status = status
self.error = error
self.summary = summary
self.sessionid = sessionid
self.sessionkey = sessionkey
self.runatms = runatms
self.durationms = durationms
self.nextrunatms = nextrunatms
@@ -1863,6 +2063,8 @@ public struct CronRunLogEntry: Codable, Sendable {
case status
case error
case summary
case sessionid = "sessionId"
case sessionkey = "sessionKey"
case runatms = "runAtMs"
case durationms = "durationMs"
case nextrunatms = "nextRunAtMs"

View File

@@ -40,11 +40,11 @@ struct CronJobEditorSmokeTests {
message: "Summarize the last day",
thinking: "low",
timeoutSeconds: 120,
deliver: true,
channel: "whatsapp",
to: "+15551234567",
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "Cron"),
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "whatsapp", to: "+15551234567", bestEffort: true),
state: CronJobState(
nextRunAtMs: 1_700_000_100_000,
runningAtMs: nil,

View File

@@ -5,12 +5,24 @@ import Testing
@Suite
struct CronModelsTests {
@Test func scheduleAtEncodesAndDecodes() throws {
let schedule = CronSchedule.at(atMs: 123)
let schedule = CronSchedule.at(at: "2026-02-03T18:00:00Z")
let data = try JSONEncoder().encode(schedule)
let decoded = try JSONDecoder().decode(CronSchedule.self, from: data)
#expect(decoded == schedule)
}
@Test func scheduleAtDecodesLegacyAtMs() throws {
let json = """
{"kind":"at","atMs":1700000000000}
"""
let decoded = try JSONDecoder().decode(CronSchedule.self, from: Data(json.utf8))
if case let .at(at) = decoded {
#expect(at.hasPrefix("2023-"))
} else {
#expect(Bool(false))
}
}
@Test func scheduleEveryEncodesAndDecodesWithAnchor() throws {
let schedule = CronSchedule.every(everyMs: 5000, anchorMs: 10000)
let data = try JSONEncoder().encode(schedule)
@@ -49,11 +61,11 @@ struct CronModelsTests {
deleteAfterRun: true,
createdAtMs: 0,
updatedAtMs: 0,
schedule: .at(atMs: 1_700_000_000_000),
schedule: .at(at: "2026-02-03T18:00:00Z"),
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "ping"),
isolation: nil,
delivery: nil,
state: CronJobState())
let data = try JSONEncoder().encode(job)
let decoded = try JSONDecoder().decode(CronJob.self, from: data)
@@ -62,7 +74,7 @@ struct CronModelsTests {
@Test func scheduleDecodeRejectsUnknownKind() {
let json = """
{"kind":"wat","atMs":1}
{"kind":"wat","at":"2026-02-03T18:00:00Z"}
"""
#expect(throws: DecodingError.self) {
_ = try JSONDecoder().decode(CronSchedule.self, from: Data(json.utf8))
@@ -88,11 +100,11 @@ struct CronModelsTests {
deleteAfterRun: nil,
createdAtMs: 0,
updatedAtMs: 0,
schedule: .at(atMs: 0),
schedule: .at(at: "2026-02-03T18:00:00Z"),
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "hi"),
isolation: nil,
delivery: nil,
state: CronJobState())
#expect(base.displayName == "hello")
@@ -111,11 +123,11 @@ struct CronModelsTests {
deleteAfterRun: nil,
createdAtMs: 0,
updatedAtMs: 0,
schedule: .at(atMs: 0),
schedule: .at(at: "2026-02-03T18:00:00Z"),
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "hi"),
isolation: nil,
delivery: nil,
state: CronJobState(
nextRunAtMs: 1_700_000_000_000,
runningAtMs: nil,

View File

@@ -23,7 +23,7 @@ struct MenuSessionsInjectorTests {
let injector = MenuSessionsInjector()
injector.setTestingControlChannelConnected(true)
let defaults = SessionDefaults(model: "anthropic/claude-opus-4-5", contextTokens: 200_000)
let defaults = SessionDefaults(model: "anthropic/claude-opus-4-6", contextTokens: 200_000)
let rows = [
SessionRow(
id: "main",
@@ -41,7 +41,7 @@ struct MenuSessionsInjectorTests {
systemSent: false,
abortedLastRun: false,
tokens: SessionTokenStats(input: 10, output: 20, total: 30, contextTokens: 200_000),
model: "claude-opus-4-5"),
model: "claude-opus-4-6"),
SessionRow(
id: "discord:group:alpha",
key: "discord:group:alpha",
@@ -58,7 +58,7 @@ struct MenuSessionsInjectorTests {
systemSent: true,
abortedLastRun: true,
tokens: SessionTokenStats(input: 50, output: 50, total: 100, contextTokens: 200_000),
model: "claude-opus-4-5"),
model: "claude-opus-4-6"),
]
let snapshot = SessionStoreSnapshot(
storePath: "/tmp/sessions.json",

View File

@@ -23,7 +23,7 @@ struct SettingsViewSmokeTests {
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "ping"),
isolation: nil,
delivery: nil,
state: CronJobState(
nextRunAtMs: 1_700_000_200_000,
runningAtMs: nil,
@@ -48,11 +48,11 @@ struct SettingsViewSmokeTests {
message: "hello",
thinking: "low",
timeoutSeconds: 30,
deliver: true,
channel: "sms",
to: "+15551234567",
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "[cron] "),
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "sms", to: "+15551234567", bestEffort: true),
state: CronJobState(
nextRunAtMs: nil,
runningAtMs: nil,

View File

@@ -589,20 +589,24 @@ public struct AgentIdentityResult: Codable, Sendable {
public let agentid: String
public let name: String?
public let avatar: String?
public let emoji: String?
public init(
agentid: String,
name: String?,
avatar: String?
avatar: String?,
emoji: String?
) {
self.agentid = agentid
self.name = name
self.avatar = avatar
self.emoji = emoji
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case avatar
case emoji
}
}
@@ -1115,6 +1119,35 @@ public struct SessionsCompactParams: Codable, Sendable {
}
}
public struct SessionsUsageParams: Codable, Sendable {
public let key: String?
public let startdate: String?
public let enddate: String?
public let limit: Int?
public let includecontextweight: Bool?
public init(
key: String?,
startdate: String?,
enddate: String?,
limit: Int?,
includecontextweight: Bool?
) {
self.key = key
self.startdate = startdate
self.enddate = enddate
self.limit = limit
self.includecontextweight = includecontextweight
}
private enum CodingKeys: String, CodingKey {
case key
case startdate = "startDate"
case enddate = "endDate"
case limit
case includecontextweight = "includeContextWeight"
}
}
public struct ConfigGetParams: Codable, Sendable {
}
@@ -1556,6 +1589,157 @@ public struct AgentSummary: Codable, Sendable {
}
}
public struct AgentsFileEntry: Codable, Sendable {
public let name: String
public let path: String
public let missing: Bool
public let size: Int?
public let updatedatms: Int?
public let content: String?
public init(
name: String,
path: String,
missing: Bool,
size: Int?,
updatedatms: Int?,
content: String?
) {
self.name = name
self.path = path
self.missing = missing
self.size = size
self.updatedatms = updatedatms
self.content = content
}
private enum CodingKeys: String, CodingKey {
case name
case path
case missing
case size
case updatedatms = "updatedAtMs"
case content
}
}
public struct AgentsFilesListParams: Codable, Sendable {
public let agentid: String
public init(
agentid: String
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct AgentsFilesListResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let files: [AgentsFileEntry]
public init(
agentid: String,
workspace: String,
files: [AgentsFileEntry]
) {
self.agentid = agentid
self.workspace = workspace
self.files = files
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case files
}
}
public struct AgentsFilesGetParams: Codable, Sendable {
public let agentid: String
public let name: String
public init(
agentid: String,
name: String
) {
self.agentid = agentid
self.name = name
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
}
}
public struct AgentsFilesGetResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsFilesSetParams: Codable, Sendable {
public let agentid: String
public let name: String
public let content: String
public init(
agentid: String,
name: String,
content: String
) {
self.agentid = agentid
self.name = name
self.content = content
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case content
}
}
public struct AgentsFilesSetResult: Codable, Sendable {
public let ok: Bool
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
ok: Bool,
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.ok = ok
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case ok
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsListParams: Codable, Sendable {
}
@@ -1630,6 +1814,16 @@ public struct ModelsListResult: Codable, Sendable {
}
public struct SkillsStatusParams: Codable, Sendable {
public let agentid: String?
public init(
agentid: String?
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct SkillsBinsParams: Codable, Sendable {
@@ -1707,7 +1901,7 @@ public struct CronJob: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let isolation: [String: AnyCodable]?
public let delivery: [String: AnyCodable]?
public let state: [String: AnyCodable]
public init(
@@ -1723,7 +1917,7 @@ public struct CronJob: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
isolation: [String: AnyCodable]?,
delivery: [String: AnyCodable]?,
state: [String: AnyCodable]
) {
self.id = id
@@ -1738,7 +1932,7 @@ public struct CronJob: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.isolation = isolation
self.delivery = delivery
self.state = state
}
private enum CodingKeys: String, CodingKey {
@@ -1754,7 +1948,7 @@ public struct CronJob: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case isolation
case delivery
case state
}
}
@@ -1785,7 +1979,7 @@ public struct CronAddParams: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let isolation: [String: AnyCodable]?
public let delivery: [String: AnyCodable]?
public init(
name: String,
@@ -1797,7 +1991,7 @@ public struct CronAddParams: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
isolation: [String: AnyCodable]?
delivery: [String: AnyCodable]?
) {
self.name = name
self.agentid = agentid
@@ -1808,7 +2002,7 @@ public struct CronAddParams: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.isolation = isolation
self.delivery = delivery
}
private enum CodingKeys: String, CodingKey {
case name
@@ -1820,7 +2014,7 @@ public struct CronAddParams: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case isolation
case delivery
}
}
@@ -1831,6 +2025,8 @@ public struct CronRunLogEntry: Codable, Sendable {
public let status: AnyCodable?
public let error: String?
public let summary: String?
public let sessionid: String?
public let sessionkey: String?
public let runatms: Int?
public let durationms: Int?
public let nextrunatms: Int?
@@ -1842,6 +2038,8 @@ public struct CronRunLogEntry: Codable, Sendable {
status: AnyCodable?,
error: String?,
summary: String?,
sessionid: String?,
sessionkey: String?,
runatms: Int?,
durationms: Int?,
nextrunatms: Int?
@@ -1852,6 +2050,8 @@ public struct CronRunLogEntry: Codable, Sendable {
self.status = status
self.error = error
self.summary = summary
self.sessionid = sessionid
self.sessionkey = sessionkey
self.runatms = runatms
self.durationms = durationms
self.nextrunatms = nextrunatms
@@ -1863,6 +2063,8 @@ public struct CronRunLogEntry: Codable, Sendable {
case status
case error
case summary
case sessionid = "sessionId"
case sessionkey = "sessionKey"
case runatms = "runAtMs"
case durationms = "durationMs"
case nextrunatms = "nextRunAtMs"

View File

@@ -5,7 +5,7 @@
},
{
"source": "Gateway",
"target": "Gateway网关"
"target": "Gateway 网关"
},
{
"source": "Pi",
@@ -17,11 +17,11 @@
},
{
"source": "Skills config",
"target": "Skills配置"
"target": "Skills 配置"
},
{
"source": "Skills Config",
"target": "Skills配置"
"target": "Skills 配置"
},
{
"source": "local loopback",
@@ -39,6 +39,26 @@
"source": "Getting started",
"target": "入门指南"
},
{
"source": "Quick start",
"target": "快速开始"
},
{
"source": "Quick Start",
"target": "快速开始"
},
{
"source": "Docs directory",
"target": "文档目录"
},
{
"source": "Credits",
"target": "致谢"
},
{
"source": "Features",
"target": "功能"
},
{
"source": "DMs",
"target": "私信"
@@ -47,6 +67,22 @@
"source": "DM",
"target": "私信"
},
{
"source": "sandbox",
"target": "沙箱"
},
{
"source": "Sandbox",
"target": "沙箱"
},
{
"source": "sandboxing",
"target": "沙箱隔离"
},
{
"source": "Sandboxing",
"target": "沙箱隔离"
},
{
"source": "sandboxed",
"target": "沙箱隔离"
@@ -55,6 +91,46 @@
"source": "Sandboxed",
"target": "沙箱隔离"
},
{
"source": "Sandboxing note",
"target": "沙箱注意事项"
},
{
"source": "Companion apps",
"target": "配套应用"
},
{
"source": "expected keys",
"target": "预期键名"
},
{
"source": "block streaming",
"target": "分块流式传输"
},
{
"source": "Block streaming",
"target": "分块流式传输"
},
{
"source": "Discovery + transports",
"target": "设备发现 + 传输协议"
},
{
"source": "Discovery",
"target": "设备发现"
},
{
"source": "Network model",
"target": "网络模型"
},
{
"source": "for full details",
"target": "了解详情"
},
{
"source": "First 60 seconds",
"target": "最初的六十秒"
},
{
"source": "Auth: where it lives (important)",
"target": "凭证:存储位置(重要)"

View File

@@ -3,13 +3,10 @@
{"cache_key":"00ee1ece05b05ab7b12cfe673000c037bb2037fe93a069a71ec2368184e83944","segment_id":"index.md:45e6d69dbe995a36","source_path":"index.md","text_hash":"45e6d69dbe995a36f7bc20755eff4eb4d2afaaedbcac4668ab62540c57219f32","text":"macOS app","translated":"macOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:06Z"}
{"cache_key":"00eeb87b1774979860c4b016d48e416ab9157539c41f5f3f0c58c1deb8f075c9","segment_id":"environment.md:frontmatter:read_when:2","source_path":"environment.md:frontmatter:read_when:2","text_hash":"822b3d74ce16c1be19059fad4ca5bf7ae9327f58fa1ff4e75e78d5afa75c038f","text":"You are documenting provider auth or deployment environments","translated":"你正在记录提供商认证或部署环境的相关文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:51Z"}
{"cache_key":"01063749652c55481b7da485911a80de3049ded0257874b376efbc55a14293a7","segment_id":"start/wizard.md:037b8f564390e097","source_path":"start/wizard.md","text_hash":"037b8f564390e09742421c621a1f785d2ee5338d0c680c76f7a9b991518e909d","text":" and optional ","translated":" 和可选的 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:48Z"}
{"cache_key":"011732db491eea64ff252f1a211df0eee3edbf29b3839a36468aff0d600565a8","segment_id":"index.md:58d30d963f28264b","source_path":"index.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:52:44Z"}
{"cache_key":"01814fd9d09399c075081056c6fa2befa388c67ba4f8745122804fd044fd82d6","segment_id":"start/getting-started.md:d1564fd156e28160","source_path":"start/getting-started.md","text_hash":"d1564fd156e28160c83922ad7a18428ce2c966e790f477e740d1d9f6cadd51e9","text":"WhatsApp (QR login)","translated":"WhatsApp二维码登录","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:08Z"}
{"cache_key":"019f9aef85c71dc5ed35acd441246cf7ca7e8734347c659aff797b91a593805e","segment_id":"index.md:22159a426e4f2635","source_path":"index.md","text_hash":"22159a426e4f26356382cc3ac9b2e7af5123c1309250332f5dcbbc6e6f952b0e","text":"Network model","translated":"网络 模型","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:48:28Z"}
{"cache_key":"01b87576d7ade6b91ca28935f65c167c2f4fb5d1b6bfd1189fd416b229500af4","segment_id":"start/getting-started.md:7421b911bc203f6f","source_path":"start/getting-started.md","text_hash":"7421b911bc203f6fe3c677d752379f23dc314719d39d18179406da675f58d039","text":"Scan via WhatsApp → Settings → Linked Devices.","translated":"通过 WhatsApp → 设置 → 已关联设备 进行扫描。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:10Z"}
{"cache_key":"01d8d8ec84ad8f4c74e29e254e56c02f7d75005160c27d99e9ce183767e16c55","segment_id":"index.md:6b8ebac7903757ce","source_path":"index.md","text_hash":"6b8ebac7903757ce7399cc729651a27e459903c24c64aa94827b20d8a2a411d2","text":"For Tailnet access, run ","translated":"如需 Tailnet 访问,请运行 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:08Z"}
{"cache_key":"024efbb5ac15e07c191effa78c0b23bf173c8af6725e988743ea055e9a4e8c3b","segment_id":"index.md:f9b8279bc46e847b","source_path":"index.md","text_hash":"f9b8279bc46e847bfcc47b8701fd5c5dc27baa304d5add8278a7f97925c3ec13","text":"Mattermost (plugin)","translated":"Mattermost插件","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:40Z"}
{"cache_key":"025574196252a6e36b88a27c440de11b7f0e0d981df3595a0aefda198b2cde9c","segment_id":"index.md:4d705f0fa835fd21","source_path":"index.md","text_hash":"4d705f0fa835fd216c4fd6dea0ee851d33720e23fb714c4c9ea74ac3211fccdc","text":"Discovery + transports","translated":"发现 + 传输","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:02Z"}
{"cache_key":"02d1e10492e8721462f16e39467b94ad3197e4eb76f6d671a09b4246d5b4d27b","segment_id":"start/getting-started.md:7ac362063b9f2046","source_path":"start/getting-started.md","text_hash":"7ac362063b9f204602f38f9f1ec9cf047f03e0d7b83896571c9df6d31ad41e9c","text":"Nodes","translated":"节点","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:38:28Z"}
{"cache_key":"02f39c075115bee6bdb015a49436f2b2a56365b87558fdd7aff7b17cb83bff6c","segment_id":"environment.md:frontmatter:summary","source_path":"environment.md:frontmatter:summary","text_hash":"78351223e7068721146d2de022fdf440c2866b2ee02fbbb50bf64369b999820b","text":"Where OpenClaw loads environment variables and the precedence order","translated":"OpenClaw 加载环境变量的位置及优先级顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:12Z"}
{"cache_key":"02f4067265058ed8929f3772d87e1c5dc0af8422b8e7b513b7db155108a422c3","segment_id":"start/wizard.md:961eb43699731759","source_path":"start/wizard.md","text_hash":"961eb43699731759fd0d04f177bb24f09971bddd41426702276e761269d0a5b9","text":" does ","translated":" 会 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:48Z"}
@@ -19,13 +16,8 @@
{"cache_key":"0457a19cd3a82171f6cdb92d82d5a0f6358da4c1220d42d5b0575bde871e7f91","segment_id":"environment.md:e234227b0e001687","source_path":"environment.md","text_hash":"e234227b0e001687821541fac3af38fc6be293ec6e13910c6826b9afc8ca33be","text":" syntax:","translated":" 语法:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:00Z"}
{"cache_key":"045fb6f3989827561e347dfa56a164069bf8b7afaa50d2d02c20ad264495d351","segment_id":"index.md:e9f63c8876aec738","source_path":"index.md","text_hash":"e9f63c8876aec7381ffb5a68efb39f50525f9fc4e732857488561516d47f5654","text":" — Uses Baileys for WhatsApp Web protocol","translated":" — 使用 Baileys 实现 WhatsApp Web 协议","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:31Z"}
{"cache_key":"046c83b658b7dd8bce829f07bd09dcee3413753ab72cf95d638925aa163d3486","segment_id":"start/getting-started.md:f4117324994aaad1","source_path":"start/getting-started.md","text_hash":"f4117324994aaad1d3413064ade8f2037e43ab2fac0b385d731ff154925ec3b3","text":"Windows (PowerShell):","translated":"Windows (PowerShell)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:51Z"}
{"cache_key":"04b1191bfbfc3062975be3fbc5b169b9c3151d3fbce07bfffc05483c40191c76","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:07Z"}
{"cache_key":"04d48cfdb6b444cb4691ea55a5deb23df20694659ae1bc5e082e242e749f5e3c","segment_id":"help/index.md:bfc5930cc2660330","source_path":"help/index.md","text_hash":"bfc5930cc2660330260afd407e98d86adaec0af48dd72b88dc33ef8e9066e2c9","text":"Install sanity (Node/npm/PATH):","translated":"安装完整性检查Node/npm/PATH","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:38Z"}
{"cache_key":"04fee8dc5ef25d6bc83852bc30abc64dab335a974f1a9aa3528d0a463f3df80e","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:53Z"}
{"cache_key":"05405710e256b2e1031234be855a7c11cf1505c627df14884d655fa42a1568a7","segment_id":"index.md:f0a7f9d068cb7a14","source_path":"index.md","text_hash":"f0a7f9d068cb7a146d0bb89b3703688d690ed0b92734b78bcdb909aace617dbf","text":"WhatsApp group messages","translated":"WhatsApp 群组消息","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:45Z"}
{"cache_key":"060d0a2c79a17edab07399082756201b03bbc948813e274fd902e138a7188268","segment_id":"start/getting-started.md:9bb7dee21b23322b","source_path":"start/getting-started.md","text_hash":"9bb7dee21b23322b15ce4a4400e6fe70a582d3d15f7e61f2c4cdf68654de1f09","text":" is also supported if you want to reuse Claude Code credentials.","translated":" 如果您想复用 Claude Code 凭据,也受支持。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:35Z"}
{"cache_key":"0644dfe5ea449a35c3a87047a17fb132ee1ef58000d49c1849006ad247310f90","segment_id":"index.md:f14185309c5ab262","source_path":"index.md","text_hash":"f14185309c5ab26233fde49831f9fc27857a6e7ac200e91dc247ae3e3b74be27","text":"Companion apps:","translated":"伴侣应用:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:03Z"}
{"cache_key":"06489e87ae62a43327838658fac6a96383f6c84a0f1e59319d89b2ce6a6f34b9","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:57:57Z"}
{"cache_key":"064dcdb5051313b748c0b775ec69683149e1861d84fa47a74c68ddd8086bdebc","segment_id":"index.md:81a1c0449ea684aa","source_path":"index.md","text_hash":"81a1c0449ea684aadad54a7f8575061ddc5bfa713b6ca3eb8a0228843d2a3ea1","text":"Nodes (iOS/Android)","translated":"节点iOS/Android","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:52:57Z"}
{"cache_key":"0687549a28e71ec1e17b261001a9e818e27784ce3286b7d21e856e37c07915a6","segment_id":"start/getting-started.md:bad5d156dc5e0cd3","source_path":"start/getting-started.md","text_hash":"bad5d156dc5e0cd39db3a90645cd150e846743103f3acfa5182ad5a003a172dc","text":"0) Prereqs","translated":"0前提条件","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:23Z"}
{"cache_key":"06c13f0dfc6cd5fa142e329fd2cfb2538e19e33de83c4b9d366542f0d03cdf08","segment_id":"index.md:c3af076f92c5ed8d","source_path":"index.md","text_hash":"c3af076f92c5ed8dcb0d0b0d36dd120bc31b68264efea96cf8019ca19f1c13a3","text":"Troubleshooting","translated":"故障排除","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:14Z"}
@@ -40,7 +32,6 @@
{"cache_key":"08a071c1e71388ad18ffca39565a37edb304794146d2f7ea1e2bac93493f89d6","segment_id":"start/wizard.md:903ea1cf1f2831b3","source_path":"start/wizard.md","text_hash":"903ea1cf1f2831b3e836aff6e23c7d261a83381614361e65df16ade48e84b26c","text":" (API keys + OAuth).","translated":" API 密钥 + OAuth。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:34Z"}
{"cache_key":"08b4ff7a8e04409d740ca4090c8d83bc3b05d7084bce4b83fa4c91b930eb7161","segment_id":"environment.md:62d66b8c36a6c9aa","source_path":"environment.md","text_hash":"62d66b8c36a6c9aa7134c8f9fe5912435cb0b3bfce3172712646a187954e7040","text":"See [Configuration: Env var substitution](/gateway/configuration#env-var-substitution-in-config) for full details.","translated":"详见 [配置:环境变量替换](/gateway/configuration#env-var-substitution-in-config)。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:11:58Z"}
{"cache_key":"08f97e3d7baa10a515db441b79273f697f85c83da040cdf821f9e725243112f2","segment_id":"environment.md:f6b2ffe1d0d5f521","source_path":"environment.md","text_hash":"f6b2ffe1d0d5f521b76cabc67d6e96da2b1170eef8086d530558e9906a7f092d","text":"Models overview","translated":"模型概览","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:17:17Z"}
{"cache_key":"09057abbc867280c96888e1b1eb5d35e4f5b3175c0c5fca9900f147e577fb4b7","segment_id":"index.md:80fc402133201fbe","source_path":"index.md","text_hash":"80fc402133201fbe0e4e9962a9570e741856aa8b0c033f1a20a9bcb06c68e809","text":"Discovery","translated":"发现机制","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:24Z"}
{"cache_key":"090f33f5db1fde14d7fc04aaa9febae674e9e6ed0d04ce8f1813dac53ccae3a2","segment_id":"start/wizard.md:ab4386608f0ebc6e","source_path":"start/wizard.md","text_hash":"ab4386608f0ebc6e151eab042c6de71d09863aab6dcb2551665e34210e4a4439","text":"What youll set:","translated":"您需要设置的内容:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:15Z"}
{"cache_key":"09824fcf1352f54ff162268163b8670ead0660d4e0a45d1f236b5b3ef938a56b","segment_id":"index.md:86e2bbbc305c31aa","source_path":"index.md","text_hash":"86e2bbbc305c31aa988751196a1e207da68801a48798c48b90485c11578443a0","text":"Providers and UX:","translated":"提供商 和用户体验:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:39Z"}
{"cache_key":"0a2b53b4943a0ba87fb991fef20f822df6c2fd0584f88d394de35b081daac564","segment_id":"environment.md:668e5590b5bb9990","source_path":"environment.md","text_hash":"668e5590b5bb9990eeb25bf657f7d17281a4c613ee4442036787cd4b2efd22bb","text":"If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"如果配置文件完全缺失,则跳过第 4 步如果已启用shell 导入仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:00Z"}
@@ -52,7 +43,6 @@
{"cache_key":"0aaaa653a1bad3c2f1d6bbf34819ea4ae8700ea5d6c593937aa6812051809168","segment_id":"environment.md:453c14128fbfb5f6","source_path":"environment.md","text_hash":"453c14128fbfb5f6757511557132a1dbb3bcbf243267630bfec49db8518c7780","text":"Env var substitution in config","translated":"配置中的 环境变量 替换","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:16Z"}
{"cache_key":"0b149311bd258e33ab5e06f16483d6b14bfb23bbf8137339bc4cf8d29e2d3d5c","segment_id":"environment.md:453c14128fbfb5f6","source_path":"environment.md","text_hash":"453c14128fbfb5f6757511557132a1dbb3bcbf243267630bfec49db8518c7780","text":"Env var substitution in config","translated":"配置中的环境变量替换","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:11:54Z"}
{"cache_key":"0b68a76b412628864a90e4b194a0db6bcc593e8700ee9228d04b45427a95c7af","segment_id":"environment.md:cf3f9ba035da9f09","source_path":"environment.md","text_hash":"cf3f9ba035da9f09202ba669adca3109148811ef31d484cc2efa1ff50a1621b1","text":" (what the Gateway process already has from the parent shell/daemon).","translated":" Gateway 进程从父 shell/守护进程继承的已有环境变量)。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:57:23Z"}
{"cache_key":"0b6b7380e75d36476a24a56bb3825600832745e76c1a2d862e6631c0aa48c51e","segment_id":"index.md:41dc1288a547d7d1","source_path":"index.md","text_hash":"41dc1288a547d7d155c2d7b831e8cff388e12ab9d77d4c24cd0757ed47e9e209","text":" — Block streaming + Telegram draft streaming details (","translated":" — 块流式传输 + Telegram 草稿流式传输详情(","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:01:36Z"}
{"cache_key":"0bab5344d37eb10f7f0a1105ba4cf723e069867a7f745d016657752c1dc0c21a","segment_id":"environment.md:5105555b1be5f84b","source_path":"environment.md","text_hash":"5105555b1be5f84b47576d6ea432675cef742e63fa52f7b254ef2aa4c90e7cca","text":" (applied only if","translated":" (仅在","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:46:04Z"}
{"cache_key":"0bbc0779389fa7b103e39fff721c2df8f37e36a72350175e61b8334f79dd6555","segment_id":"index.md:0b7e778664921066","source_path":"index.md","text_hash":"0b7e77866492106632e98e7718a8e1e89e8cb0ee3f44c1572dfd9e54845023de","text":"/concepts/streaming","translated":"/concepts/streaming","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:06Z"}
{"cache_key":"0bda3d8fa9978471f16800fbab17622f054477505f8a680d6165e924184818eb","segment_id":"index.md:3fc5f55ea5862824","source_path":"index.md","text_hash":"3fc5f55ea5862824fc266d26cd39fb5da22cc56670c11905d5743adac10bc9ef","text":"Mattermost Bot (plugin)","translated":"Mattermost 机器人(插件)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:46Z"}
@@ -87,7 +77,6 @@
{"cache_key":"11951539669d912b24dac16f9ed27e1de0a950a3baa481474a65de0ca85fbe7b","segment_id":"start/wizard.md:ec2d0a7d20f3b660","source_path":"start/wizard.md","text_hash":"ec2d0a7d20f3b6602a6593e0abef2337e84ba728ca8f6fef2534dc1e9dbfe06b","text":"Remote mode configures a local client to connect to a Gateway elsewhere.","translated":"远程模式配置本地客户端以连接到其他位置的 Gateway。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:13Z"}
{"cache_key":"11a42ddb57b9c1ba4022984efe25b463da52e7b9c5d7ec3a925d7a6d0e5a6c39","segment_id":"index.md:cdb4ee2aea69cc6a","source_path":"index.md","text_hash":"cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8","text":".","translated":".","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:19Z"}
{"cache_key":"11a6809809867ab84f2a66da213f7894876530602a0743b37fc93e614c7ccbfe","segment_id":"help/index.md:71095a6d42f5d9c2","source_path":"help/index.md","text_hash":"71095a6d42f5d9c2464a8e3f231fc53636d4ce0f9356b645d245874162ec07e2","text":"Gateway troubleshooting","translated":"Gateway 故障排除","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:44Z"}
{"cache_key":"11e66a0f11d149ca8994761cbc3771066650e21d33cb9986d47624a35fb5f177","segment_id":"help/index.md:5c94724fa7810fa9","source_path":"help/index.md","text_hash":"5c94724fa7810fa9902e565cf66c5f5a973074f2961fcd3a40bad4ee4aeca5e0","text":"If you want a quick “get unstuck” flow, start here:","translated":"如果你想快速\"脱困\",从这里开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:21:37Z"}
{"cache_key":"1226fe0b47712f49a01581113142855bc5ae36e3289353b5d592ece5191b0159","segment_id":"start/wizard.md:c90e6f2be18d7e02","source_path":"start/wizard.md","text_hash":"c90e6f2be18d7e02413e18d4174fe7d855c9753005652614556204123b37c96e","text":": browser flow; paste the ","translated":":浏览器流程;粘贴 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:18Z"}
{"cache_key":"1249a5c279b0761418bca0826571d62b0526075a0c91018c35002331e3c6d6b5","segment_id":"environment.md:aac7246f5e97142c","source_path":"environment.md","text_hash":"aac7246f5e97142c3f257b7d8b84976f10c29e1b89804bb9d3eb7c43cc03cb8e","text":"Environment variables","translated":"环境变量","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:14Z"}
{"cache_key":"124e4ad52161941e1842f43e4f5d0c12d573babaf3f319ec7d5db46ba8ee7e84","segment_id":"index.md:0b60fe04b3c5c3c7","source_path":"index.md","text_hash":"0b60fe04b3c5c3c76371b6eca8b19c8e09a0e54c9010711ff87e782d87d2190b","text":"Android app","translated":"Android 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:57Z"}
@@ -115,7 +104,6 @@
{"cache_key":"18bd8d592ca11411d1c02c1a70123dc798352f581db4c9ce297c5ebb04841fa3","segment_id":"index.md:03279877bfe1de07","source_path":"index.md","text_hash":"03279877bfe1de0766393b51e69853dec7e95c287ef887d65d91c8bbe84ff9ff","text":"WebChat + macOS app","translated":"网页聊天 + macOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:02:30Z"}
{"cache_key":"190c49164ee5535fac803e9c0f057588d634e056d2c4fc072a0ca26e01ddc391","segment_id":"index.md:7d8b3819c6a9fb72","source_path":"index.md","text_hash":"7d8b3819c6a9fb726f40c191f606079b473f6f72d4080c13bf3b99063a736187","text":"Ops and safety:","translated":"运维和安全:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:19Z"}
{"cache_key":"19207e4ed0ae44f965f33707377a0217c1765cf57b09c0268ee36c10fb108dd9","segment_id":"index.md:c6e91f3b51641b1c","source_path":"index.md","text_hash":"c6e91f3b51641b1c43d297281ee782b40d9b3a0bdd7afc144ba86ba329d5f95f","text":"OpenClaw = CLAW + TARDIS","translated":"OpenClaw = CLAW + TARDIS","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:18Z"}
{"cache_key":"19429bac6dc1b8ea7457c6d7eb4bcf0f89cef2a5b2a017e79a0ed5d093e1665a","segment_id":"start/getting-started.md:6b65292dc52408c1","source_path":"start/getting-started.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果您尚未进行全局安装,请通过以下方式运行上手引导步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:47Z"}
{"cache_key":"194e63ecfe45556973c28ccafc39f814f42d2478037734ce44eee72f6fc6fc66","segment_id":"index.md:856302569e24c4d6","source_path":"index.md","text_hash":"856302569e24c4d64997e2ec5c37729f852bcccf333ba1e2f71e189c9d172e6d","text":": SSH tunnel or tailnet/VPN; see ","translated":"SSH 隧道或 Tailnet/VPN请参阅 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:21Z"}
{"cache_key":"196942db05e9e40cbdf74a89cdd1be042430343a64ac2185009414f0d092af66","segment_id":"environment.md:cda454f61dfcac70","source_path":"environment.md","text_hash":"cda454f61dfcac7007a9edc538f9f58cf38caa0652e253975979308162bccc53","text":"Gateway configuration","translated":"Gateway 配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:11Z"}
{"cache_key":"19c0ced45bb35a1d8801864910a9f7bc2c460229fdd97366f546255feeb1db0e","segment_id":"index.md:8816c52bc5877a2b","source_path":"index.md","text_hash":"8816c52bc5877a2b24e3a2f4ae7313d29cf4eba0ca568a36f2d00616cfe721d0","text":"Wizard","translated":"向导","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:12Z"}
@@ -162,10 +150,8 @@
{"cache_key":"221e7c2c0fe8b9bb39aa23d66ead440852512864ee62242cc3d9290dbd135860","segment_id":"index.md:9bd86b0bbc71de88","source_path":"index.md","text_hash":"9bd86b0bbc71de88337aa8ca00f0365c1333c43613b77aaa46394c431cb9afd8","text":"Maxim Vovshin","translated":"Maxim Vovshin","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:49Z"}
{"cache_key":"2220f5ebb94a086ce480f01165b1993d04e470d58154e2aa482056a2eecbb1f1","segment_id":"help/index.md:3c33340bd23b8db8","source_path":"help/index.md","text_hash":"3c33340bd23b8db89f18fe7d05a954738c0dd5ba9623cf6bdb7bb5d1a3729cfc","text":"FAQ (concepts)","translated":"常见问题(概念)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:59Z"}
{"cache_key":"2229ff2bff7c65fc1a4cd5515373b1b3319f43a26222f43787452e985cf5e4bb","segment_id":"index.md:11d28de5b79e3973","source_path":"index.md","text_hash":"11d28de5b79e3973f6a3e44d08725cdd5852e3e65e2ff188f6708ae9ce776afc","text":"Docs hubs (all pages linked)","translated":"文档中心(所有页面链接)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:49Z"}
{"cache_key":"228b4027bfc7ab84d118c7534132c84e4135f86c319e047f014d862beb938c26","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:16Z"}
{"cache_key":"22baac03ae69320ee9635f7e23e85e926ed40c441e97357b30b48e271e88770f","segment_id":"index.md:013e11a23ec9833f","source_path":"index.md","text_hash":"013e11a23ec9833f907b2ead492b0949015e25d10ba92461669609aee559335d","text":"Start here:","translated":"从这里开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:47Z"}
{"cache_key":"22bfdd3e9e4f7a5447edf31592e38d663a8907afca5f46061f314b924280a94b","segment_id":"index.md:d53b75d922286041","source_path":"index.md","text_hash":"d53b75d9222860417f783b0829023b450905d982011d35f0e71de8eed93d90fc","text":"New install from zero:","translated":"从零开始全新安装:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:47:41Z"}
{"cache_key":"22c699e5178ceeaa86c9029a62d9e0cea3b3c6ff75e19666d912f28097ecca91","segment_id":"index.md:5eeecff4ba2df15c","source_path":"index.md","text_hash":"5eeecff4ba2df15c51bcc1ba70a5a2198fbcac141ebe047a2db7acf0e1e83450","text":" — Local UI + menu bar companion for ops and voice wake","translated":" —— 本地界面 + 菜单栏伴侣应用,用于操作和语音唤醒","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:05Z"}
{"cache_key":"22c7a06691f087acabe4321804edbb000eaf7520b16060ac2879f19252b639e3","segment_id":"index.md:31365ab9453d6a1e","source_path":"index.md","text_hash":"31365ab9453d6a1ec03731622803d3b44f345b6afad08040d7f3e97290c77913","text":"do nothing","translated":"不做任何操作","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:33Z"}
{"cache_key":"22d40e91dde10d2912781df931ab0fac2802d5b81e63fdd93bdb7856c8c43976","segment_id":"environment.md:7175517a370b5cd2","source_path":"environment.md","text_hash":"7175517a370b5cd2e664e3fd29c4ea9db5ce17058eb9772fe090a5485e49dad6","text":" or ","translated":" 或 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:00Z"}
{"cache_key":"23004dacbc322d02e170261429793a8b23569f398c4f21352a030b42543cdef9","segment_id":"index.md:6b65292dc52408c1","source_path":"index.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果您还没有全局安装,请通过以下方式运行 上手引导 步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:37Z"}
@@ -488,7 +474,6 @@
{"cache_key":"60cd1a8fee21c221c625fe6961c620592e9f99a88910d9f557d86f92e17d793c","segment_id":"start/wizard.md:1d6bc09c9a9a3dad","source_path":"start/wizard.md","text_hash":"1d6bc09c9a9a3dad8fcbe9ed89a206b2dba3d8cf16046315aee976577d534cae","text":"Downloads the appropriate release asset.","translated":"下载相应的发布资源。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:59Z"}
{"cache_key":"60f998f050fe63afd0938f40b2f1cf78a16d5dd9fa6abc631aa8e217ce1e7cc5","segment_id":"index.md:053bc65874ad6098","source_path":"index.md","text_hash":"053bc65874ad6098e58c41c57b378a2f36b0220e5e0b46722245e6c2f796818c","text":"Discord","translated":"Discord","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:15Z"}
{"cache_key":"61277a40a0e409e2f324452a28cc35c44e1ac080b4400e7bdaa3c161ce51d545","segment_id":"start/wizard.md:3fcf806de5c2ace5","source_path":"start/wizard.md","text_hash":"3fcf806de5c2ace5327f65078cfb2139aaa8dd33ffdc3b04e9fef6f11778423c","text":"MiniMax M2.1","translated":"MiniMax M2.1","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:55Z"}
{"cache_key":"6131873fe6c607965685280107b0527c8bda0c8c322154c415c74adf0b2d6aea","segment_id":"environment.md:cf0923bd0c80e86a","source_path":"environment.md","text_hash":"cf0923bd0c80e86a7aa644d04aa412cbd7baa3273153c40c625ceca9e012bde8","text":" runs your login shell and imports only **missing** expected keys:","translated":" 运行你的登录 shell 并仅导入**缺失的**预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:37Z"}
{"cache_key":"613744b9849b1cacbbcdcebd3fcb2637696f177d0364b9e32042a74bf2c1b350","segment_id":"index.md:80fc402133201fbe","source_path":"index.md","text_hash":"80fc402133201fbe0e4e9962a9570e741856aa8b0c033f1a20a9bcb06c68e809","text":"Discovery","translated":"发现","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:20Z"}
{"cache_key":"613d01b2aa6e9a9127f428233d5f88e84e2c86b5079776f57becfe4143f86992","segment_id":"start/wizard.md:3ccbb3a92014470f","source_path":"start/wizard.md","text_hash":"3ccbb3a92014470f73c71c81684da45b1e07ee3a49cca372ec678ce89229ea58","text":"Vercel AI Gateway example:","translated":"Vercel AI Gateway 示例:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:26Z"}
{"cache_key":"614a1ff5ae5f98f2f46f1ee6bbb53ace3482d9d15a8842906f26dcbad10c4d71","segment_id":"index.md:084514e91f37c3ce","source_path":"index.md","text_hash":"084514e91f37c3ce85360e26c70b77fdc95f0d3551ce309db96fbcf956a53b01","text":"Dashboard (browser Control UI)","translated":"仪表板(浏览器控制界面)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:30Z"}
@@ -559,7 +544,6 @@
{"cache_key":"6b14f5e839df1e54026ee6d3db5886a6e9360039fd681101a4a9a2b101ff0919","segment_id":"index.md:084514e91f37c3ce","source_path":"index.md","text_hash":"084514e91f37c3ce85360e26c70b77fdc95f0d3551ce309db96fbcf956a53b01","text":"Dashboard (browser Control UI)","translated":"仪表盘(浏览器控制界面)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:21Z"}
{"cache_key":"6b3dbfa396df75c279946f5b8741a67863a0107d3f08c55dc642a8fac173a4c8","segment_id":"index.md:1074116f823ec992","source_path":"index.md","text_hash":"1074116f823ec992e76d7e8be19d3235fec5ddd7020562b06e7242e410174686","text":"Remote use","translated":"远程使用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:11Z"}
{"cache_key":"6b44e5cb8d21527ef6ad754e2792b9416080f2a132c8fd7b6d431fc76113aad9","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期的键:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:25Z"}
{"cache_key":"6bf1a3983ec9759b076402ea6998c8207a0b0ef0d87b56ef4945599c9f8bd90a","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:02Z"}
{"cache_key":"6c18bb32586b6c812ebf5323b8ed442c63be7b4014bc62e51f0d7f5eb46d223b","segment_id":"environment.md:582967534d0f909d","source_path":"environment.md","text_hash":"582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf","text":" in ","translated":" 在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:40:54Z"}
{"cache_key":"6c1b9632694258c227417b61df6433ac71eca1f2d35ff31cb5e145a7188dacfe","segment_id":"start/getting-started.md:d7849463c3ab6a49","source_path":"start/getting-started.md","text_hash":"d7849463c3ab6a496d77b8e6745d00ad430324bc5ed419a859f7c9e494102d68","text":"Manual run (foreground):","translated":"手动运行(前台):","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:51Z"}
{"cache_key":"6c3d2263be9d0d6dd77934bd87f882599e2e9449e67bdee4388f84ab0aa6571b","segment_id":"start/wizard.md:698fdfc9c55bd3e4","source_path":"start/wizard.md","text_hash":"698fdfc9c55bd3e4ed5a9365317ae70aac20783ec38057088da27012a470a901","text":"Gateway port ","translated":"Gateway 端口 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:50Z"}
@@ -588,7 +572,6 @@
{"cache_key":"71667555ad1cea654225fec33df1804c97a0b8167affbf3d3c426ccb778e780a","segment_id":"start/wizard.md:82e1216ede141cb1","source_path":"start/wizard.md","text_hash":"82e1216ede141cb1553d20be7356c3f1ab9da9a4a05303cf7cd05ef01142558f","text":"Gateway settings (port/bind/auth/tailscale)","translated":"Gateway 设置(端口/绑定/认证/Tailscale","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:23Z"}
{"cache_key":"7170dcd349905701fd3cde7dc5bce0aed2618717e87ffa06e9ab230041f689a1","segment_id":"environment.md:cdb4ee2aea69cc6a","source_path":"environment.md","text_hash":"cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8","text":".","translated":"。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:45:26Z"}
{"cache_key":"724a450b6cdfc09dd0fc5acf94bb7f20a45c43e524810239d0e6e7cac65ff74b","segment_id":"index.md:bd293e4db98037bc","source_path":"index.md","text_hash":"bd293e4db98037bc9da5137af50453ac9c81b49e14eb4c47f121b12bed880877","text":" — Direct chats collapse into shared ","translated":" — 直接聊天合并到共享的 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:01:59Z"}
{"cache_key":"726990d1aefefc1ae562bce73f84f1de90c5c6cc094dc9121495e4480aedab92","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:42Z"}
{"cache_key":"72d5ce369dd6489f427c02710fae70f6426a51de9441678410a023761cee215b","segment_id":"start/wizard.md:8f7c7d2f15e90b42","source_path":"start/wizard.md","text_hash":"8f7c7d2f15e90b420fb6f2cc7632d7d7a433bc94eeb262d9718286e5ffd9b365","text":"Related docs","translated":"相关文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:49:00Z"}
{"cache_key":"730b6369e65b8f27f57a90f6ee355beca28d783793767209a7cfe7beb736769b","segment_id":"start/wizard.md:eda31fe8fb873697","source_path":"start/wizard.md","text_hash":"eda31fe8fb873697fd7d5bfba08f263eaa917808a644bddd2b6d89d3a6b1c868","text":"QuickStart vs Advanced","translated":"快速入门与高级模式","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:30Z"}
{"cache_key":"73164a8584f9cc4e546493100199d4ebcbb65ce74c33e21d06da689c6d7b9328","segment_id":"start/wizard.md:ce85fecfbffa2746","source_path":"start/wizard.md","text_hash":"ce85fecfbffa2746f0a9b66464140eb2ed5a085ce85fff062ef0ff8b5686a0a5","text":".\nSessions are stored under ","translated":"下。会话存储在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:54Z"}
@@ -624,7 +607,6 @@
{"cache_key":"77b6a43a45b36b25b51859a5b976fa12609b6d19ed351bc0e84fae2290d32da9","segment_id":"help/index.md:2adc964c084749b1","source_path":"help/index.md","text_hash":"2adc964c084749b1f2d8aef24030988b667dbda2e38a6a1699556c93e07c1cea","text":"Start here","translated":"从这里开始","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:11:12Z"}
{"cache_key":"7806b590e1e2ff8ab2244875f7a2c370ab3b11462fd2061e5f4af9cf72f70d19","segment_id":"start/wizard.md:9c706a2bb9ebcb20","source_path":"start/wizard.md","text_hash":"9c706a2bb9ebcb206633616f2a40867b0c02716657ac4c0e95c7c1939287d3d8","text":"; auth profiles live in ","translated":";认证配置存储在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:31Z"}
{"cache_key":"78161c8de8a14607cd003796d4c4ace7048f9116ecbe036601136d7f0cef4ff3","segment_id":"start/getting-started.md:bfd99edf844f6205","source_path":"start/getting-started.md","text_hash":"bfd99edf844f62050af2f7d37df7cfa7f651b8e1be341eb4f07c3849ca4efc43","text":"Fastest chat: open the Control UI (no channel setup needed). Run ","translated":"最快聊天方式:打开控制界面(无需设置渠道)。运行 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:33Z"}
{"cache_key":"78165d4ed88f199c04e34f0686aca8ee87969331cf02c78e26a1851d3673baae","segment_id":"help/index.md:0b554dd0f4b96cff","source_path":"help/index.md","text_hash":"0b554dd0f4b96cff4e1137c5fb22253b12125b6a3dce5d9238c80b20491bcb8e","text":"Help\n\nIf you want a quick “get unstuck” flow, start here:","translated":"# 帮助\n\n如果你想要一个快速的\"脱困\"流程,从这里开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:12Z"}
{"cache_key":"785cae01bc172c4c47e2e82cda4c5afd7d37d7069a008e44c8a4176eeacafe67","segment_id":"help/index.md:a8ab86b9313a9236","source_path":"help/index.md","text_hash":"a8ab86b9313a92362150f5e5ba8a19de4ee52f2e3162f9bd2bc6cf128a2fcd18","text":"If youre looking for conceptual questions (not “something","translated":"如果你在寻找概念性问题(不是\"出了什么","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:45:00Z"}
{"cache_key":"78ae0fabb1aab02156d5bf1b4e148ba155369b079aa0b733aca5a750a3d0cdc2","segment_id":"index.md:329f3c913c0a1636","source_path":"index.md","text_hash":"329f3c913c0a16363949eb8ee7eb0cda7e81137a3851108019f33e5d18b57d8f","text":"Switching between npm and git installs later is easy: install the other flavor and run ","translated":"之后在 npm 和 git 安装之间切换很简单:安装另一种方式然后运行 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:30Z"}
{"cache_key":"791458a3464d7dd0036471e90590958905611942f9f0aefd8917c701e4e587d4","segment_id":"start/wizard.md:0516de0bbbd36c95","source_path":"start/wizard.md","text_hash":"0516de0bbbd36c95c5c45902d43caf2abdab59363114c4d6abae961f6ed1c1cb","text":" imply non-interactive mode. Use ","translated":" 意味着非交互模式。请使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:50Z"}
@@ -669,7 +651,6 @@
{"cache_key":"7eefff451137a5fd592db6fef6e65447cae69abe23699c34cb838a1c3cc04d73","segment_id":"start/wizard.md:d3745cec7a646b22","source_path":"start/wizard.md","text_hash":"d3745cec7a646b229f6d7123ef3557f68640f35a54a593f1e0e32776da0677c1","text":" (autogenerated, even on loopback)","translated":" (自动生成,即使在回环地址上也是如此)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:58Z"}
{"cache_key":"7f2e9e14503f22acab8659b458900c0864bdc52ee5055d4a3a742508a8e41314","segment_id":"environment.md:45ca56d179d4788c","source_path":"environment.md","text_hash":"45ca56d179d4788c55ba9f7653b376d62e7faa738e92259e3d4f6f5c1b554f28","text":"Related","translated":"相关","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:47:13Z"}
{"cache_key":"7f4d30ae34bbfb95b016db35c14a77f46cdda52ff397a69b63ad655c6128f0f6","segment_id":"index.md:30f035b33a6c35d5","source_path":"index.md","text_hash":"30f035b33a6c35d51e09f9241c61061355c872f2fb9a82822cd2f5f443fd4ad4","text":"Group Chat Support","translated":"群聊支持","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:31Z"}
{"cache_key":"7f5759f942e4173b7e990de6fbc0eada6e5b6c3106c5aa6fae08456d7b79dcf8","segment_id":"index.md:6b65292dc52408c1","source_path":"index.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果尚未进行全局安装,请通过以下方式运行上手引导步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:19Z"}
{"cache_key":"7f8a0ec6c0614299ed8aca539dde67e208ecc32d4022975fbb37f7930f3f70e5","segment_id":"start/getting-started.md:4cc7ae6d3b7fbaaf","source_path":"start/getting-started.md","text_hash":"4cc7ae6d3b7fbaaf56673ea3268caa38af191a587867ef1090c9f689ecccec96","text":"Headless/server tip: do OAuth on a normal machine first, then copy ","translated":"无头/服务器提示:先在普通机器上完成 OAuth然后复制 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:40Z"}
{"cache_key":"7fec8c329b4438aef905e1918364b86faca2a2580bb29eded4850a67ba16109b","segment_id":"environment.md:496aca80e4d8f29f","source_path":"environment.md","text_hash":"496aca80e4d8f29fb8e8cd816c3afb48d3f103970b3a2ee1600c08ca67326dee","text":" block","translated":" 块","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:48Z"}
{"cache_key":"8070c35741bdfaa2f8878a7460406a597ccf7fec7994522389adeafea46b6e8e","segment_id":"environment.md:frontmatter:read_when:0","source_path":"environment.md:frontmatter:read_when:0","text_hash":"90fc0487bff88009979cff1061c1a882df8c3b1baa9c43538331d9d5dab15479","text":"You need to know which env vars are loaded, and in what order","translated":"你需要了解加载了哪些环境变量,以及加载的顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:45:10Z"}
@@ -681,7 +662,6 @@
{"cache_key":"822efbc5bcf680421493847f6b76e9626f1d8202ff5ff47cd3e141ecdac58a9f","segment_id":"environment.md:496aca80e4d8f29f","source_path":"environment.md","text_hash":"496aca80e4d8f29fb8e8cd816c3afb48d3f103970b3a2ee1600c08ca67326dee","text":" block","translated":" 块","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:27Z"}
{"cache_key":"829cc48b5c60f16b09e63437a5de27acc17910473f8e3dfbc505a0d3e3b593c7","segment_id":"start/wizard.md:79a482cf546c23b0","source_path":"start/wizard.md","text_hash":"79a482cf546c23b04cd48a33d4ca8411f62e5b7dc8c3a8f30165e28e747f263a","text":"iMessage","translated":"iMessage","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:44:54Z"}
{"cache_key":"82d122e7cc5c895b61dec28850c3f07a68e69c19f554d9088318f62c6cd30fe1","segment_id":"environment.md:6d28a9f099e563d9","source_path":"environment.md","text_hash":"6d28a9f099e563d9322b5bcdea9ff98af87e9c213c2222462ae738d2fb27ecbe","text":" block\n\nTwo equivalent ways to set inline env vars (both are non-overriding):","translated":" 块\n\n设置内联环境变量的两种等效方式均为非覆盖式","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:44Z"}
{"cache_key":"83090d5cbebceddaa2f500bdb4240d4ea9a8ee14da3654f77128a067e4dc220a","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:37Z"}
{"cache_key":"8334186d1a61e931ed7b3905a26e470159f86593819124c5626df7a012733ee9","segment_id":"environment.md:frontmatter:summary","source_path":"environment.md:frontmatter:summary","text_hash":"78351223e7068721146d2de022fdf440c2866b2ee02fbbb50bf64369b999820b","text":"Where OpenClaw loads environment variables and the precedence order","translated":"其中 OpenClaw 加载 环境变量 及优先级顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:56:59Z"}
{"cache_key":"833685db37cf96f2342238018bd6a4a6e7812d1794a7389dc1e349917b140f50","segment_id":"environment.md:668e5590b5bb9990","source_path":"environment.md","text_hash":"668e5590b5bb9990eeb25bf657f7d17281a4c613ee4442036787cd4b2efd22bb","text":"If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"如果配置文件完全缺失,则跳过第 4 步;如果启用了 shell 导入,它仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:28Z"}
{"cache_key":"834bd8857aa5700b0ec493efb4625ba88e34c885a8254b13f6c44a75589021d2","segment_id":"index.md:9bcda844990ec646","source_path":"index.md","text_hash":"9bcda844990ec646b3b6ee63cbdf10f70b0403727dea3b5ab601ca55e3949db9","text":" for node WebViews; see ","translated":" 用于节点 WebView请参阅 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:13Z"}
@@ -695,7 +675,6 @@
{"cache_key":"84c686db4b4fc386bbb4efa35c380073babbc5fb4b2eb1ba3a8213a5f135a5bc","segment_id":"start/getting-started.md:161660030aa6c9e3","source_path":"start/getting-started.md","text_hash":"161660030aa6c9e32470cc1c023dab32dc748d80b0e61882b368cb775d12638e","text":" → ","translated":" → ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:27Z"}
{"cache_key":"84e200d4c823802e34a99da4faa8328d0e250aca858b0a32cc08e3ae12e0cc0e","segment_id":"start/wizard.md:e4442451c634e0db","source_path":"start/wizard.md","text_hash":"e4442451c634e0db2db0fae78725becbeafd567302e3ecbfeb5ccdc5887d29be","text":" from GitHub releases:","translated":" (从 GitHub 发布版本):","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:56Z"}
{"cache_key":"85040674d9e2db6adb1ebb8c6215e72171d213a9dac8bd3c6bcb438178adc88b","segment_id":"index.md:0a4a282eda1af348","source_path":"index.md","text_hash":"0a4a282eda1af34874b588bce628b76331fbe907de07b57d39afdedccac2ba14","text":" http://127.0.0.1:18789/ (or http://localhost:18789/)","translated":" http://127.0.0.1:18789/(或 http://localhost:18789/","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:15Z"}
{"cache_key":"850dacfab0ff7f9fd9498aeac24c0b84c59f266291d504465d7dead52da552bf","segment_id":"index.md:41dc1288a547d7d1","source_path":"index.md","text_hash":"41dc1288a547d7d155c2d7b831e8cff388e12ab9d77d4c24cd0757ed47e9e209","text":" — Block streaming + Telegram draft streaming details (","translated":" — 块流式传输 + Telegram 草稿流式传输详情(","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:04Z"}
{"cache_key":"85cb0b7ed6991128b9fe65b7b103c5f32da742641cb24ffc1a3469002a2bcad6","segment_id":"start/getting-started.md:e24d86fa815827a4","source_path":"start/getting-started.md","text_hash":"e24d86fa815827a4dc5b8b22711caaf036427796512a74167ebaf615c495f9f8","text":"Telegram / Discord / others","translated":"Telegram / Discord / 其他","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:17Z"}
{"cache_key":"85e39779810391375b7241f2d999fbd5e6b2830ddf226a9ad561132c40d4fd47","segment_id":"start/wizard.md:21b111cbfe6e8fca","source_path":"start/wizard.md","text_hash":"21b111cbfe6e8fca2d181c43f53ad548b22e38aca955b9824706a504b0a07a2d","text":"Default ","translated":"默认 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:41Z"}
{"cache_key":"85fdea7998dfe111261588f998c93aceaa9b04ba174bc16bd188e3bbd8f3228a","segment_id":"environment.md:668e5590b5bb9990","source_path":"environment.md","text_hash":"668e5590b5bb9990eeb25bf657f7d17281a4c613ee4442036787cd4b2efd22bb","text":"If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"如果配置文件完全缺失,则跳过第 4 步如果已启用shell 导入仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:40Z"}
@@ -712,7 +691,6 @@
{"cache_key":"87b42c17fb63bfdcd059198572016f6b8b3cd297aaa991c4c1dea8723a68fbfe","segment_id":"index.md:9abe8e9025013e78","source_path":"index.md","text_hash":"9abe8e9025013e78a6bf2913f8c20ee43134ad001ce29ced89e2af9c07096d8f","text":"Media: images","translated":"媒体:图片","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:48Z"}
{"cache_key":"87d80d180c9d4789c20123b3bc177f99c4d00909f70c6fe3c209c078bdcafdce","segment_id":"index.md:1074116f823ec992","source_path":"index.md","text_hash":"1074116f823ec992e76d7e8be19d3235fec5ddd7020562b06e7242e410174686","text":"Remote use","translated":"远程使用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:36Z"}
{"cache_key":"87f8e99a729beb8e55fdef7ca70ebe4b11f4ff1c5dbbfcb3e654429198c6bf0f","segment_id":"help/index.md:729bc562eec2658b","source_path":"help/index.md","text_hash":"729bc562eec2658bd11ffdd522fe5277177dc73e86eaca7baac0b472a4d8f8b2","text":"If youre looking for conceptual questions (not “something broke”):","translated":"如果你在寻找概念性问题(不是\"出了故障\"","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:05Z"}
{"cache_key":"8819cee05e67d9206c9adc7cf9539b1586a050f9c259e65a3099184303440591","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:11Z"}
{"cache_key":"88ab429b0aa43b0cfc93a1fc0e69576a2acbf64d0cd407fc1028488a0c27c9fc","segment_id":"index.md:fdef9f917ee2f72f","source_path":"index.md","text_hash":"fdef9f917ee2f72fbd5c08b709272d28a2ae7ad8787c7d3b973063f0ebeeff7a","text":" to update the gateway service entrypoint.","translated":" 以更新网关服务入口点。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:03Z"}
{"cache_key":"88d02146dbe2246af19afc2deecbb627547528cd1bf8b9839d358e8987a88a99","segment_id":"index.md:9c870aa6e5e93270","source_path":"index.md","text_hash":"9c870aa6e5e93270170d5a81277ad3e623afe8d4efd186d3e28f3d2b646d52e6","text":"How it works","translated":"工作原理","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:42Z"}
{"cache_key":"88f63f39528cb8bcb530a350a6b610125dbf6ab7034c2509a772e2ec28ed9476","segment_id":"help/index.md:frontmatter:read_when:1","source_path":"help/index.md:frontmatter:read_when:1","text_hash":"857eafc389d179e83e21e46c10527fec40894fe064c63847ba06b946b7d5eb73","text":"Something broke and you want the fastest path to a fix","translated":"出了问题,你想找到最快的修复方法","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:10Z"}
@@ -725,7 +703,6 @@
{"cache_key":"8a81f73e519177081d755623ff45ac47552fa513f5aaf9c77335ce2c329087f3","segment_id":"start/getting-started.md:524bf322c2034388","source_path":"start/getting-started.md","text_hash":"524bf322c2034388f76cd94c1c7834341cedfa09bc4a864676749a08b243416d","text":"model/auth (OAuth recommended)","translated":"模型/认证(推荐使用 OAuth","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:53Z"}
{"cache_key":"8a83aabc21a6b84ce7552d72a9bc0a7c2d99864c31350064cbd39564354421f1","segment_id":"index.md:9adcfa4aa10a4e8b","source_path":"index.md","text_hash":"9adcfa4aa10a4e8b991a72ccc45261cd64f296aed5b257e4caf9c87aff1290a0","text":" — Send and receive images, audio, documents","translated":" —— 发送和接收图片、音频、文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:51Z"}
{"cache_key":"8a984f774ac8874be4797ffddd21cbdddc9379fa6bc51121620fbe9395cd91cf","segment_id":"help/index.md:bfc5930cc2660330","source_path":"help/index.md","text_hash":"bfc5930cc2660330260afd407e98d86adaec0af48dd72b88dc33ef8e9066e2c9","text":"Install sanity (Node/npm/PATH):","translated":"安装完整性检查Node/npm/PATH","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:18Z"}
{"cache_key":"8aba2e1efca29d503bd185064c1e676dd87fa34c81fa9bb059ed6300f6bfd517","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:35Z"}
{"cache_key":"8ac55f265f3496db43dce513fde21c137826476afcff2ed1b3e86e613ff28b3c","segment_id":"start/wizard.md:44dab6c89cc5e6d9","source_path":"start/wizard.md","text_hash":"44dab6c89cc5e6d9a3112d3cb45c19cd16c3a9963082276015d4b624e5e67782","text":"Some channels are delivered as plugins. When you pick one during onboarding, the wizard\nwill prompt to install it (npm or a local path) before it can be configured.","translated":"部分渠道以插件形式提供。当您在上手引导期间选择某个渠道时,向导会提示先安装它(通过 npm 或本地路径),然后才能进行配置。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:57Z"}
{"cache_key":"8b2c90beec3893be65468e57df762fcbc285a9772042200eee3d4bf8f7ff9c0d","segment_id":"index.md:96be070791b7d545","source_path":"index.md","text_hash":"96be070791b7d545dc75084e59059d2170eed247350b351db5330fbd947e4be6","text":"👥 ","translated":"👥 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:29Z"}
{"cache_key":"8b921a960a8b92bc6210c2e228fe886cd93000a5a77f1cb5ac97233de2c4f965","segment_id":"index.md:fb87b8dba88b3edc","source_path":"index.md","text_hash":"fb87b8dba88b3edced028edfe2efa5f884ab2639c1b26efa290ccd0469454d25","text":"Slash commands","translated":"斜杠命令","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:03Z"}
@@ -807,7 +784,6 @@
{"cache_key":"9a7478d471c30618239146c8b7adbd3669fd552a2fafba13cc6dc8b51c083243","segment_id":"index.md:a194ca16424ddd17","source_path":"index.md","text_hash":"a194ca16424ddd17dacc45f1cbd7d0e41376d8955a7b6d02bc38c295cedd04e4","text":"RPC adapters","translated":"RPC 适配器","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:25Z"}
{"cache_key":"9aaaeb76bc162fe216b19290b0978994ad43023335a81224b65bf7e4849ed5b6","segment_id":"index.md:frontmatter:summary","source_path":"index.md:frontmatter:summary","text_hash":"891b2aa093410f546b89f8cf1aa2b477ba958c2c06d2ae772e126d49786df061","text":"Top-level overview of OpenClaw, features, and purpose","translated":"OpenClaw 的顶层概述、功能和用途","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:47:18Z"}
{"cache_key":"9b0b553b6bb64b97bc340190fc4f10febadb5c4542122d2dea4661534f60b8b6","segment_id":"index.md:a10f6ed8c1ddbc10","source_path":"index.md","text_hash":"a10f6ed8c1ddbc10d3528db7f7b6921c1dd5a5e78aa191ff017bf29ce2d26449","text":"⏱️ ","translated":"⏱️ ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:04Z"}
{"cache_key":"9b4a9e428618ff38c3d8e54131d987860c0ebbb45007e3493d99964d9cd436a6","segment_id":"index.md:4d705f0fa835fd21","source_path":"index.md","text_hash":"4d705f0fa835fd216c4fd6dea0ee851d33720e23fb714c4c9ea74ac3211fccdc","text":"Discovery + transports","translated":"发现机制 + 传输方式","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:28Z"}
{"cache_key":"9bb6f5ad39ff9d7aff3bca1fda6f474e19f25c0ffaaffaf3b19c924234d8c03a","segment_id":"index.md:f0d82ba647b4a33d","source_path":"index.md","text_hash":"f0d82ba647b4a33da3008927253f9bed21e380f54eab0608b1136de4cbff1286","text":"OpenClaw bridges WhatsApp (via WhatsApp Web / Baileys), Telegram (Bot API / grammY), Discord (Bot API / channels.discord.js), and iMessage (imsg CLI) to coding agents like ","translated":"OpenClaw 将 WhatsApp通过 WhatsApp Web / Baileys、TelegramBot API / grammY、DiscordBot API / 渠道.discord.js和 iMessageimsg CLI桥接到编程 智能体,例如 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:47:31Z"}
{"cache_key":"9c03abf2c27129fa2698e7640a7b9add5936e84cf6d779d5f189bf9a27940aa6","segment_id":"index.md:310cc8cec6b20a30","source_path":"index.md","text_hash":"310cc8cec6b20a3003ffab12f5aade078a0e7a7d6a27ff166d62ab4c3a1ee23d","text":"If you ","translated":"如果你 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:25Z"}
{"cache_key":"9c11b2ec1c922e332f69000a8a937f0a2318b5356faa6278a7580cc49c3526d5","segment_id":"index.md:e47cdb55779aa06a","source_path":"index.md","text_hash":"e47cdb55779aa06a74ae994c998061bd9b7327f5f171c141caf2cf9f626bfe4b","text":"Peter Steinberger","translated":"Peter Steinberger","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:52Z"}
@@ -818,7 +794,6 @@
{"cache_key":"9cbdb7ff14fdd8d015b7bcce3b3c0d48b1711e631ff86cae2c699684f8e4d143","segment_id":"start/wizard.md:c4b2896a2081395e","source_path":"start/wizard.md","text_hash":"c4b2896a2081395e282313d6683f07c81e3339ef8b9d2b5a299ea5b626a0998f","text":").","translated":")。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:41:17Z"}
{"cache_key":"9d44e8f510b7e2cf5ea7b08188a9c606937bc3db8c49e22d903828b34b8b04c1","segment_id":"start/wizard.md:19f53c2ccaf19969","source_path":"start/wizard.md","text_hash":"19f53c2ccaf199696e23d43812941e23fed0625900d2a551533304d6ca1980f6","text":" install or change anything on the remote host.","translated":" 在远程主机上安装或更改任何内容。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:40Z"}
{"cache_key":"9d7b3ce341253f712ecd8b4ca661ae0a6d85b1ee8e8ddf00b1ec02ca13d67237","segment_id":"help/index.md:569ca49f4aaf7846","source_path":"help/index.md","text_hash":"569ca49f4aaf7846e952c1d4aeca72febd0b79fa1c4f9db08fd3127551218572","text":"Install","translated":"安装","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:41Z"}
{"cache_key":"9d829bdffa4f3aa22d063ea4b6391f8094b8f4db9df8a985430559d4a153e286","segment_id":"index.md:58d30d963f28264b","source_path":"index.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:19Z"}
{"cache_key":"9db03f9dc7b789dbc3b4115e9b644cd22de2a63adeed02eb3b403a223d96b819","segment_id":"index.md:2b402c90e9b15d9c","source_path":"index.md","text_hash":"2b402c90e9b15d9c3ef65c432c4111108f54ee544cda5424db46f6ac974928e4","text":"🔐 ","translated":"🔐 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:14Z"}
{"cache_key":"9e0b7ed9895b612971d582145c837e95bfec8b051c6bccddd008d56dff778711","segment_id":"start/wizard.md:28d03596d24eeb4e","source_path":"start/wizard.md","text_hash":"28d03596d24eeb4eab2d6fe21ca1cb95be7cb1fa6f92933db05e2cc4f4cdfa06","text":"Skip","translated":"跳过","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:16Z"}
{"cache_key":"9e3a338fc3d6bce679ff4711d74e67c66877245b6ebd2c2a08f182a3a788dae6","segment_id":"start/getting-started.md:fd82e54418ec23cd","source_path":"start/getting-started.md","text_hash":"fd82e54418ec23cda00219878eaf76c3b37337b3dcb7560a941db6a0d2ec249e","text":": background install (launchd/systemd; WSL2 uses systemd)","translated":"后台安装launchd/systemdWSL2 使用 systemd","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:15Z"}
@@ -848,7 +823,6 @@
{"cache_key":"a235aca76de620b9ed0805727dc5f142a660dc6dac3254a01531acad96cb084d","segment_id":"index.md:d53b75d922286041","source_path":"index.md","text_hash":"d53b75d9222860417f783b0829023b450905d982011d35f0e71de8eed93d90fc","text":"New install from zero:","translated":"从零开始全新安装:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:05Z"}
{"cache_key":"a28528856eac855eaf431dc468f5d1a9b3918df6dc73a9bb54c488aa7c23faad","segment_id":"start/getting-started.md:387847437e10c06c","source_path":"start/getting-started.md","text_hash":"387847437e10c06cae87567a6579b38e71849aea9c2355eba4a8d090418360b9","text":"The wizard can write tokens/config for you. If you prefer manual config, start with:","translated":"向导可以为您写入令牌/配置。如果您更喜欢手动配置,请从以下内容开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:19Z"}
{"cache_key":"a28d9fd85bfd4afc9a62b3cfe12607c86001b32a9a97d72eeb6cd50993fb51ee","segment_id":"index.md:c6e91f3b51641b1c","source_path":"index.md","text_hash":"c6e91f3b51641b1c43d297281ee782b40d9b3a0bdd7afc144ba86ba329d5f95f","text":"OpenClaw = CLAW + TARDIS","translated":"OpenClaw = CLAW + TARDIS","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:54:04Z"}
{"cache_key":"a29d82b0936a3237f692bb4c86bb8bcc8b1840db6ab6f2922a249fda830bdc5a","segment_id":"index.md:4d705f0fa835fd21","source_path":"index.md","text_hash":"4d705f0fa835fd216c4fd6dea0ee851d33720e23fb714c4c9ea74ac3211fccdc","text":"Discovery + transports","translated":"发现 + 传输","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:36Z"}
{"cache_key":"a2c462e51d228b070aba2a14a09d41aa54e0962d795724d5a090c71c7e242dfe","segment_id":"start/getting-started.md:acdd1e734125f341","source_path":"start/getting-started.md","text_hash":"acdd1e734125f341604c0efbabdcc4c4b0597e8f6235d66c2445edd1812838c1","text":"Telegram","translated":"Telegram","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:22Z"}
{"cache_key":"a2f08193fbeb8a9400b75d96157bbbf488ab3aa51d50658094d00bb841646217","segment_id":"help/index.md:2adc964c084749b1","source_path":"help/index.md","text_hash":"2adc964c084749b1f2d8aef24030988b667dbda2e38a6a1699556c93e07c1cea","text":"Start here","translated":"从这里开始","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:44:37Z"}
{"cache_key":"a32d46351380765e1ec38639781fc9e5abaccdf74240eee7ab685f570551f487","segment_id":"index.md:7d8b3819c6a9fb72","source_path":"index.md","text_hash":"7d8b3819c6a9fb726f40c191f606079b473f6f72d4080c13bf3b99063a736187","text":"Ops and safety:","translated":"运维与安全:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:04Z"}
@@ -858,7 +832,6 @@
{"cache_key":"a3909a297d0e74a4cb418a7a549f495f6eed24048ebf8f12f448eff8d7a20c50","segment_id":"environment.md:1ec31258a6b45ea9","source_path":"environment.md","text_hash":"1ec31258a6b45ea903cd76f5b0190a99ab56afff6241a04f0681eb12b7a02484","text":"Env var equivalents:","translated":"等效的环境变量:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:18Z"}
{"cache_key":"a3e59ee4578bdb5fd68940692f78e9389e163da63e350ba9f0689ffbc980d4a5","segment_id":"environment.md:28b1103adde15a9d","source_path":"environment.md","text_hash":"28b1103adde15a9ddd8fc71f0c57dc155395ade46a0564865ccb5135b01c99b7","text":"OpenClaw pulls environment variables from multiple sources. The rule is **never override existing values**.","translated":"OpenClaw 从多个来源拉取环境变量。规则是**永远不覆盖已有的值**。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:23Z"}
{"cache_key":"a4384986e5ce06eca0118051e6a851ac0fd3d922d4d1f31b60000687962a2288","segment_id":"start/wizard.md:ec1a3a5d6d6f0bac","source_path":"start/wizard.md","text_hash":"ec1a3a5d6d6f0baca7805bf1ea17fc7b02042416f02f80bc1970ad8c710abd89","text":"Flow details (local)","translated":"流程详情(本地)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:56Z"}
{"cache_key":"a44af8d86be9e8883c8df3ed68722e659e4d7bb99e2675df13ee0ab386219e51","segment_id":"index.md:22159a426e4f2635","source_path":"index.md","text_hash":"22159a426e4f26356382cc3ac9b2e7af5123c1309250332f5dcbbc6e6f952b0e","text":"Network model","translated":"网络 模型","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:51Z"}
{"cache_key":"a46b3daf9b1e1045e72e437a283e8377ec9b4820cde181d05a24a9a582cbf914","segment_id":"start/wizard.md:12754931af777521","source_path":"start/wizard.md","text_hash":"12754931af777521bcb6a904d2a7d342d0d77e6c4f1f2eb1b8b3753d25a1ab4a","text":"If the Control UI assets are missing, the wizard attempts to build them; fallback is ","translated":"如果 Control UI 资源文件缺失,向导会尝试构建它们;后备方案是 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:06Z"}
{"cache_key":"a4a009f8c9411234d5dd3ef4a71fdf292ec59e29a2b74d197acea1c789825536","segment_id":"help/index.md:6cb77499abdccd9a","source_path":"help/index.md","text_hash":"6cb77499abdccd9a2dbb7c93a4d31eed01613dda06302933057970df9ecdeb54","text":"Logs:","translated":"日志:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:46Z"}
{"cache_key":"a4b963e5c58f681343b2e7b98ade4df71e3a328906ed382ffc8c0e4853fdf162","segment_id":"environment.md:b1d6b91b67c2afa5","source_path":"environment.md","text_hash":"b1d6b91b67c2afa5e322988d9462638d354ddf8a1ef79dba987f815c22b4baee","text":" at ","translated":" 位于 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:39Z"}
@@ -891,7 +864,6 @@
{"cache_key":"a9c30fa450ed436cb03bc256b3075761a9215bd99bcd7bd2891cf15317ffd34f","segment_id":"environment.md:d08a8493f686363a","source_path":"environment.md","text_hash":"d08a8493f686363a78b913d45ebfbd87a3768d1c77b70f23b1fdade3c066e481","text":"Shell env import","translated":"Shell 环境导入","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:47Z"}
{"cache_key":"aa80cfc76e76409c5ba7bf331e4fb8aadf72703ead80d203c94e74209da993f9","segment_id":"index.md:310cc8cec6b20a30","source_path":"index.md","text_hash":"310cc8cec6b20a3003ffab12f5aade078a0e7a7d6a27ff166d62ab4c3a1ee23d","text":"If you ","translated":"如果你 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:31Z"}
{"cache_key":"aaa5becdcd694b68de2e61f6a13bd932c3f80f8b0b5a959a054a61ad5911beef","segment_id":"index.md:81a1c0449ea684aa","source_path":"index.md","text_hash":"81a1c0449ea684aadad54a7f8575061ddc5bfa713b6ca3eb8a0228843d2a3ea1","text":"Nodes (iOS/Android)","translated":"节点iOS/Android","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:22Z"}
{"cache_key":"aab013ce01ee6fc5b450d86a4cb8582865cc8b2e84ef22a6b5e0191462c1ee45","segment_id":"index.md:6b65292dc52408c1","source_path":"index.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果尚未进行全局安装,请通过以下方式运行 上手引导 步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:09Z"}
{"cache_key":"aacffcbc2a97abf1a5eccd00e5893be1125e364251fa27f3e0c88ef2db2b0248","segment_id":"index.md:acdd1e734125f341","source_path":"index.md","text_hash":"acdd1e734125f341604c0efbabdcc4c4b0597e8f6235d66c2445edd1812838c1","text":"Telegram","translated":"Telegram","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:36Z"}
{"cache_key":"aad00bc21098071ff9c86ff467cb7f5c65d3467ce4bf7d707f560479783e9eaa","segment_id":"index.md:b79cac926e0b2e34","source_path":"index.md","text_hash":"b79cac926e0b2e347e72cc91d5174037c9e17ae7733fd7bdb570f71b10cd7bfc","text":"Help","translated":"帮助","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:51Z"}
{"cache_key":"aae01909516ef373ddb2e4996f9016675f297208f7f075a68490f1f48eb0c87f","segment_id":"environment.md:6a26e1694d9e8520","source_path":"environment.md","text_hash":"6a26e1694d9e852038e5a472ed6b54cc023b4ace8ac10d745cad426d5dc057f3","text":" details.","translated":" 详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:47:11Z"}
@@ -939,7 +911,6 @@
{"cache_key":"b1a0214973416cbfb4dcac01605c51911f412a6b7d862a6b8aed7db6364bb93a","segment_id":"start/wizard.md:1a0f5fc7ca6e8a74","source_path":"start/wizard.md","text_hash":"1a0f5fc7ca6e8a74bc099d9c397a23564b55eca50c3b2e33c472acb7032a6f3b","text":" (if Minimax chosen)","translated":" (如果选择了 Minimax","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:35Z"}
{"cache_key":"b1babe6ce88663854adf02aa4a23f21c9a98e036c72bf36dbe4b518d5d025d8b","segment_id":"environment.md:8d076464a84995bc","source_path":"environment.md","text_hash":"8d076464a84995bc095e934b0aa1e4419372f27cd71d033571e4dbba201ee5d8","text":"You can reference env vars directly in config string values using ","translated":"您可以使用以下方式在配置字符串值中直接引用 环境变量 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:25Z"}
{"cache_key":"b1bfed2a2039ffc6f83d8201645caf18d6b942a8e5efbe2a28ca24978f750aa7","segment_id":"index.md:a97c0f391117ef55","source_path":"index.md","text_hash":"a97c0f391117ef554586ed43255ab3ff0e15adcfc1829c62b6d359672c0bec93","text":" — Mention-based by default; owner can toggle ","translated":" — 默认基于提及;所有者可切换 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:02:09Z"}
{"cache_key":"b1d6847512a77312c1152a3f04694cdfc058f6d51d29f421a97d1f7799705076","segment_id":"help/index.md:d5d5bf0c0c86cfaa","source_path":"help/index.md","text_hash":"d5d5bf0c0c86cfaa612b370c3c796bb03e31b285fc928b5a690bfd156d177e88","text":"If you want a quick “get unstuck” flow, start","translated":"如果你想要一个快速的\"摆脱困境\"流程,请从这里开始","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:44:31Z"}
{"cache_key":"b1e93b43d06bcf0651c4bee0920f356e1f38bceca29db1936d449b4be99e77d2","segment_id":"index.md:8f6fb4eb7f42c0e2","source_path":"index.md","text_hash":"8f6fb4eb7f42c0e245e29e63f5b82cc3ba19852681d1ed9aed291f59cf75ec0e","text":"Security","translated":"安全","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:56Z"}
{"cache_key":"b212246fea49637bc0db899bd39dff2b1762ecf0d8cac3ec6160a8cd4c4da860","segment_id":"start/wizard.md:1f01936efef6e09c","source_path":"start/wizard.md","text_hash":"1f01936efef6e09cd29c9b1a9b6a64c1fcdb35682c9cf25db02dfde331f83fa7","text":" if present or prompts for a key, then saves it to ","translated":" (如果存在)或提示输入密钥,然后保存到 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:29Z"}
{"cache_key":"b240cb7927de51aca09fb318798ffd79fe597965722be259f799a2002cbe0f43","segment_id":"start/getting-started.md:4ea5ee68fea05586","source_path":"start/getting-started.md","text_hash":"4ea5ee68fea05586106890ded5733820bb77d919cda27bc4b8139b7cd33b8889","text":" gateway","translated":" Gateway","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:02Z"}
@@ -1031,7 +1002,6 @@
{"cache_key":"c2802148a29fff6480dd7c4126df1d7787f83156807ce1f6e0abb05d2e0a7863","segment_id":"index.md:6e0f6eca4ff17d33","source_path":"index.md","text_hash":"6e0f6eca4ff17d3377c1c3e8e1f73457553ad3b9cfcd5e4f2b94cfb1028b6234","text":"iOS app","translated":"iOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:36Z"}
{"cache_key":"c2acf62bea34b4557cbab8b7ceadd55c5cf37516c124b93afc1b8e9f08d62ab0","segment_id":"index.md:39bbb719fa2b9d22","source_path":"index.md","text_hash":"39bbb719fa2b9d2251039cbf2cd072e1120a414278263e2f11d99af0236c4262","text":"Groups","translated":"群组","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:21Z"}
{"cache_key":"c2e74d237df6614199282b8822741be509ff03e31b7319f3184bb2537860e8a9","segment_id":"index.md:bf084dc7b82e1e62","source_path":"index.md","text_hash":"bf084dc7b82e1e62c63727b13451d1eba2269860e27db290d2d5908d7ade0529","text":" — Pairs as a node and exposes Canvas + Chat + Camera","translated":" — 作为节点配对并提供 Canvas + 聊天 + 相机","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:02:43Z"}
{"cache_key":"c2e91312acca3baab311ea42b62c2fcea1bf5ec3fe9f444cc63f3e00c3b1da02","segment_id":"environment.md:7c3c58e5e1838eae","source_path":"environment.md","text_hash":"7c3c58e5e1838eaeec35be812eb7edad1525e370c3420121710cc1d5fb627c1b","text":"), applied only for missing expected keys.\n\nIf the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"),仅对缺失的预期密钥应用。\n\n如果配置文件完全不存在则跳过第 4 步如果已启用shell 导入仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:42Z"}
{"cache_key":"c335a0e455574c0e23a45c10a55511400b6168c38aa7d8e43521b1c8650e58f9","segment_id":"environment.md:frontmatter:read_when:1","source_path":"environment.md:frontmatter:read_when:1","text_hash":"a3a2d99a99de98220c8e0296d6f4e4b2a34024916bd2379d1b3b9179c8fae46f","text":"You are debugging missing API keys in the Gateway","translated":"您正在调试 Gateway 中缺失的 API 密钥","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:40:15Z"}
{"cache_key":"c34f893f16dcd3b37a3752585df805b44212829550f3d82cb5f539fdb50a5a50","segment_id":"environment.md:87e89abb4c1c551f","source_path":"environment.md","text_hash":"87e89abb4c1c551fe08d355d097f18b8de78edca5f556997085681662fce8eed","text":"Config ","translated":"配置 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:46Z"}
{"cache_key":"c359a69d5e0e9e6470f36436f1b27a946ef28ef1069e7b7d59e0ea3132f6003c","segment_id":"start/wizard.md:4cd440e57b28aba7","source_path":"start/wizard.md","text_hash":"4cd440e57b28aba7f789ba11d0bb5837f09937ba45bab9a80b9a6a980894250e","text":"Followup reconfiguration:","translated":"后续重新配置:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:15Z"}
@@ -1085,7 +1055,6 @@
{"cache_key":"cc8f5dcfbe51a4638b375d367381be97b79d012b56b2c7eadd2e38d164cdd177","segment_id":"start/wizard.md:e18251a039a6b735","source_path":"start/wizard.md","text_hash":"e18251a039a6b7353675decc475898bfdb91d3bd9d37e83c8447d0359b8711c3","text":"Non-interactive flags: ","translated":"非交互标志: ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:05Z"}
{"cache_key":"cc906618700533ea8dd9d752b8e2ef28ffb8707654a557d7cef1b867cdd57f1a","segment_id":"index.md:ceee4f2088b9d5ba","source_path":"index.md","text_hash":"ceee4f2088b9d5ba7d417bac7395003acfbcef576fd4cc1dd3063972f038218a","text":"The name","translated":"名称","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:54:01Z"}
{"cache_key":"cc93bf5458542a509cb8460472bf3269d769fe1cdee6201ab736c4b5460d64d5","segment_id":"start/wizard.md:4bba41aa0148ebb4","source_path":"start/wizard.md","text_hash":"4bba41aa0148ebb49b33763f1b38a983af7c0a4dd22fff07d3cf94fdcb96ecd3","text":"Linux (and Windows via WSL2): systemd user unit","translated":"Linux以及通过 WSL2 的 Windowssystemd 用户单元","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:17Z"}
{"cache_key":"ccd10d490dbeb4a1e0c3b7b4ccf7653af6ff78a7d498755c92bf4a6c24b2aacd","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:51Z"}
{"cache_key":"cd2d7cce6f1c10e008e8efe49ecf02b6ac401d686667986409f7e6796e9f1140","segment_id":"environment.md:45ca56d179d4788c","source_path":"environment.md","text_hash":"45ca56d179d4788c55ba9f7653b376d62e7faa738e92259e3d4f6f5c1b554f28","text":"Related","translated":"相关内容","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:44Z"}
{"cache_key":"cd4cdcf85e185ce70df30cbda64fb2d77baa6a6c989e67cde3f80315c06b3839","segment_id":"index.md:45e6d69dbe995a36","source_path":"index.md","text_hash":"45e6d69dbe995a36f7bc20755eff4eb4d2afaaedbcac4668ab62540c57219f32","text":"macOS app","translated":"macOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:33Z"}
{"cache_key":"cd82c395857efd6e374fec3ad86de5dd8989415770d38a86d8a1980cd372b7f5","segment_id":"start/wizard.md:c4e77a12a2c0b664","source_path":"start/wizard.md","text_hash":"c4e77a12a2c0b664f398de857da71528f66ffb4a70e65769897dcc7147167b2c","text":" or use allowlists.","translated":" 批准,或使用允许名单。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:05Z"}
@@ -1098,7 +1067,6 @@
{"cache_key":"ce3c2713f373fff6ebab9c70141debe3262d0a7ff6214fd146fa277b67c1ab3e","segment_id":"start/wizard.md:bd8a6e0ff884f51d","source_path":"start/wizard.md","text_hash":"bd8a6e0ff884f51d6a4a9b70f4680033876871936c72cf8af5df4e4b2836c75c","text":"Wizard runs a model check and warns if the configured model is unknown or missing auth.","translated":"向导会运行模型检查,如果配置的模型未知或缺少认证则发出警告。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:24Z"}
{"cache_key":"ce618de323766f3aa222b534fb69a1502c03699a6b57e801e6f1a1b3c32d3431","segment_id":"index.md:9abe8e9025013e78","source_path":"index.md","text_hash":"9abe8e9025013e78a6bf2913f8c20ee43134ad001ce29ced89e2af9c07096d8f","text":"Media: images","translated":"媒体:图片","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:25Z"}
{"cache_key":"ce62c5006939b21f7a2d236f9cdb545ce653778800504e85668fe99075067cbf","segment_id":"environment.md:6db0742daaf9f191","source_path":"environment.md","text_hash":"6db0742daaf9f191ab7816d2c9d317b1ea1693453a8c63b95af8b01477e0f5bb","text":" runs your login shell and imports only ","translated":" 运行你的登录 shell并仅导入 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:47Z"}
{"cache_key":"cebc7667fbb15ccecd6359fe5ec38ae1ad00df26f18e56e7debd760a47d30a94","segment_id":"start/getting-started.md:2fa27cf15c3773de","source_path":"start/getting-started.md","text_hash":"2fa27cf15c3773deb54ae880d0f3250d86ef8c316abe07373f5f6a16df7afbed","text":" is also supported.","translated":" 也受支持。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:08Z"}
{"cache_key":"cf001b0403d7ae959797460c96aa4da24818c662362595f2da0be349caeb6a09","segment_id":"index.md:cda454f61dfcac70","source_path":"index.md","text_hash":"cda454f61dfcac7007a9edc538f9f58cf38caa0652e253975979308162bccc53","text":"Gateway configuration","translated":"Gateway 配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:31Z"}
{"cache_key":"cf9fc66b44905a0c47ca04f98d6e6507821789844f1e97ca2026f7df6e5b1451","segment_id":"environment.md:f7e239a42b7cd986","source_path":"environment.md","text_hash":"f7e239a42b7cd986a1558fed234e975ed2e96e9d37cf0a93f381778c461c89dd","text":"OpenClaw pulls environment variables from multiple sources. The rule is ","translated":"OpenClaw 从多个来源拉取 环境变量。规则是 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:57:11Z"}
{"cache_key":"cfc26997d872d590a2aba69f0aba6f704354d3aea9aa3bd433693ca7182cacdc","segment_id":"start/getting-started.md:1093115897879aa3","source_path":"start/getting-started.md","text_hash":"1093115897879aa3ad9511a1dc2850929cfb60ba45ec741605f69f5d20203472","text":"Runtime","translated":"运行时","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:17Z"}
@@ -1110,7 +1078,6 @@
{"cache_key":"d0f76abf14b1216bff9974f7e507a3c2a43f331f1ebd805279843692ae78f662","segment_id":"index.md:5cf9ea2e20780551","source_path":"index.md","text_hash":"5cf9ea2e2078055129b38cfbc394142ca6ca41556bd6e31cbd527425647c1d1e","text":"One Gateway per host (recommended)","translated":"每台主机一个 Gateway推荐","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:48:30Z"}
{"cache_key":"d12af03e20c20a4ebdcdbf4c32f52081339c0aa7bd1bb44b311875547bb39918","segment_id":"start/wizard.md:14a01a1b76ad6311","source_path":"start/wizard.md","text_hash":"14a01a1b76ad63111eb126c1d124a893abcb5cc90fe893825a9c96362112ab4f","text":" adds gateway health probes to status output (requires a reachable gateway).","translated":" 将 Gateway 健康探测添加到状态输出中(需要可达的 Gateway。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:41Z"}
{"cache_key":"d1818c531bc4e1cca14e64f751cf8698cb0701a745fb3da03b37b4fd7129c18b","segment_id":"start/wizard.md:6d0323ac97e5a313","source_path":"start/wizard.md","text_hash":"6d0323ac97e5a3136bae41278bfd46f5985969ee57dea5f25d7faa78bb01c87e","text":" when model is unset or ","translated":" (当模型未设置或为 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:24Z"}
{"cache_key":"d181ecac73ffcad6ec7afe0e692144db4ea470fa5de3a2d218f4b8127ad7d588","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:28Z"}
{"cache_key":"d1a349d8c1859f2d1c00367b86704fa95d4168c8615ada60834a6890215d1f58","segment_id":"index.md:3c064c83b8d244fe","source_path":"index.md","text_hash":"3c064c83b8d244fef61e5fd8ce5f070b857a3578a71745e61eea02892788c020","text":" — Anthropic (Claude Pro/Max) + OpenAI (ChatGPT/Codex) via OAuth","translated":" —— 通过 OAuth 支持 AnthropicClaude Pro/Max+ OpenAIChatGPT/Codex","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:28Z"}
{"cache_key":"d1d30ee69fb8519a966ebbb5cb51d2be029399b2951ef296b23f96d3fea4bc3a","segment_id":"start/wizard.md:3fad3d2e2c01a9ea","source_path":"start/wizard.md","text_hash":"3fad3d2e2c01a9ea3a66cbcb1b05a0d5982e3665cf0e1ec6dee0e031e83137e1","text":"Reads the available skills and checks requirements.","translated":"读取可用技能并检查依赖条件。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:43Z"}
{"cache_key":"d234d82b06f65337a5ab45e775d0f0abda696d4e04e6115c6a042853b3b11ca4","segment_id":"index.md:084514e91f37c3ce","source_path":"index.md","text_hash":"084514e91f37c3ce85360e26c70b77fdc95f0d3551ce309db96fbcf956a53b01","text":"Dashboard (browser Control UI)","translated":"仪表板(浏览器控制界面)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:48:04Z"}
@@ -1151,7 +1118,6 @@
{"cache_key":"d8fe9f40df201863d43f4937a52bac7d14019fae82150f1191fe4bb66819d827","segment_id":"help/index.md:3c33340bd23b8db8","source_path":"help/index.md","text_hash":"3c33340bd23b8db89f18fe7d05a954738c0dd5ba9623cf6bdb7bb5d1a3729cfc","text":"FAQ (concepts)","translated":"常见问题(概念)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:11:34Z"}
{"cache_key":"d93001811d4774893fac9a800d8e9c14259b90fc5ed85a3e5e6d381bfb591846","segment_id":"index.md:32ebb1abcc1c601c","source_path":"index.md","text_hash":"32ebb1abcc1c601ceb9c4e3c4faba0caa5b85bb98c4f1e6612c40faa528a91c9","text":" (","translated":" ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:10Z"}
{"cache_key":"d952c24b47cb7a9f69823c976f2f5e103fdc731a8bd74cae1436d86f420022df","segment_id":"environment.md:frontmatter:read_when:1","source_path":"environment.md:frontmatter:read_when:1","text_hash":"a3a2d99a99de98220c8e0296d6f4e4b2a34024916bd2379d1b3b9179c8fae46f","text":"You are debugging missing API keys in the Gateway","translated":"你正在调试 Gateway 中缺失的 API 密钥","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:21:50Z"}
{"cache_key":"d963cbde28040dde98de9fd8684bb5552ff2ba0e13e2c9921a8e36d90d7237a4","segment_id":"index.md:58d30d963f28264b","source_path":"index.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:15Z"}
{"cache_key":"d972ebc19ef87492ca8c11159fd6342cced6b4e19743d79d81ae33fafe35bbd8","segment_id":"environment.md:f7e239a42b7cd986","source_path":"environment.md","text_hash":"f7e239a42b7cd986a1558fed234e975ed2e96e9d37cf0a93f381778c461c89dd","text":"OpenClaw pulls environment variables from multiple sources. The rule is ","translated":"OpenClaw 从多个来源获取环境变量。规则是 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:21:57Z"}
{"cache_key":"d9923f60f9531ccaaefa870fa682febfe862bf9a38ced5baa99ea8637d7fc5ae","segment_id":"start/getting-started.md:63d3b285bad7d501","source_path":"start/getting-started.md","text_hash":"63d3b285bad7d5015cea4d6e62f972e83221dfce48c6919bd536c5e894a6607d","text":" set an API key (wizard can store it for service use). ","translated":" 设置 API 密钥(向导可以将其存储以供服务使用)。 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:32Z"}
{"cache_key":"d9b22590788b6c0abf9a15102d23d2aeb6608cf4acc0339e69be4e52ae38af48","segment_id":"index.md:f9b8279bc46e847b","source_path":"index.md","text_hash":"f9b8279bc46e847bfcc47b8701fd5c5dc27baa304d5add8278a7f97925c3ec13","text":"Mattermost (plugin)","translated":"Mattermost插件","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:18Z"}
@@ -1167,7 +1133,6 @@
{"cache_key":"dbec24d595565c4c294a91f556c491976ccdeb4f7976d9258e6420af47259608","segment_id":"help/index.md:24669ff48290c187","source_path":"help/index.md","text_hash":"24669ff48290c1875d8067bbd241e8a55444839747bffb8ab99f3a34ef248436","text":"Doctor","translated":"诊断","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:11:29Z"}
{"cache_key":"dbeeb5b2ad003e4152107ceade1290b2001163df5f2fb93a792c8c9d94cec345","segment_id":"start/getting-started.md:922f3f28b57bdd14","source_path":"start/getting-started.md","text_hash":"922f3f28b57bdd146b8892adf494a28a0969d5eaf21333bfdb314db2eb6c8da8","text":"Installer options (install method, non-interactive, from GitHub): ","translated":"安装选项(安装方式、非交互式、从 GitHub 安装): ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:48Z"}
{"cache_key":"dbf5bae2a9b91c346475334bdb1294ace20ee07ca1e471c488c5311579ef37ab","segment_id":"index.md:b0d125182029e6c5","source_path":"index.md","text_hash":"b0d125182029e6c500cbcc81011341df77de8fe24d9e80190c32be390c916ec2","text":"🤖 ","translated":"🤖 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:58Z"}
{"cache_key":"dc16a7d72c37b5b48ed3034555c195ab7432617c1a8182e92d98e23f1051f615","segment_id":"index.md:f14185309c5ab262","source_path":"index.md","text_hash":"f14185309c5ab26233fde49831f9fc27857a6e7ac200e91dc247ae3e3b74be27","text":"Companion apps:","translated":"伴侣应用:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:30Z"}
{"cache_key":"dc745b075f86ec95e5a22fbb2ba14c5a6f2c00911dfa570cbe2f5123627e887d","segment_id":"environment.md:f15f5f9f4ef4d668","source_path":"environment.md","text_hash":"f15f5f9f4ef4d6688876c894f8eba251ed1db6eaf2209084028d43c9e76a8ba1","text":" (aka ","translated":" (即 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:40:44Z"}
{"cache_key":"dc8c80f84e5339af07824daa81e39f2801c9d6beb851b21e632b3eb6ddf79749","segment_id":"start/wizard.md:4b2a013a2a09958e","source_path":"start/wizard.md","text_hash":"4b2a013a2a09958e251e8998bdfa5fd89cc1c69abb1273fe2c1522cf54363cc6","text":"JVM builds require ","translated":"JVM 构建需要 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:09Z"}
{"cache_key":"dcb357452715d4a3fee760c79dfdee6719f235e48d176456a053646ffae10f44","segment_id":"environment.md:d08a8493f686363a","source_path":"environment.md","text_hash":"d08a8493f686363a78b913d45ebfbd87a3768d1c77b70f23b1fdade3c066e481","text":"Shell env import","translated":"Shell 环境导入","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:04Z"}
@@ -1217,7 +1182,6 @@
{"cache_key":"e5b4eab0ca38617f4b76c99dc5fa36151812c02576b33f954a56cf5f77703696","segment_id":"index.md:bf0e823c81b87c5d","source_path":"index.md","text_hash":"bf0e823c81b87c5de79676155debf20a29b52d6d7eb7e77deda73a56d0afbaaa","text":"🧠 ","translated":"🧠 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:08Z"}
{"cache_key":"e5be378ff2d92da3de35b20680f90f5d1aa0a98ce205139d6fcaeac91ef06f65","segment_id":"index.md:9bcda844990ec646","source_path":"index.md","text_hash":"9bcda844990ec646b3b6ee63cbdf10f70b0403727dea3b5ab601ca55e3949db9","text":" for node WebViews; see ","translated":" 用于节点 WebView参见 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:04Z"}
{"cache_key":"e5d655052f08f79672770734c9717dc24a5a9359defba7095dc7a9e2cf9e801b","segment_id":"start/wizard.md:bba52d8bacabbacc","source_path":"start/wizard.md","text_hash":"bba52d8bacabbacc510a1902b4eb35435f691903eb2db22fd110d41eadedec8d","text":" exists, the wizard can reuse it.","translated":" 存在,向导可以复用它。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:13Z"}
{"cache_key":"e5febac01358bd99e804e54a33e30d0d88ea12bcab990c3e29c66351fb5a598f","segment_id":"index.md:41dc1288a547d7d1","source_path":"index.md","text_hash":"41dc1288a547d7d155c2d7b831e8cff388e12ab9d77d4c24cd0757ed47e9e209","text":" — Block streaming + Telegram draft streaming details (","translated":" —— 块流式传输 + Telegram 草稿流式传输详情(","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:10Z"}
{"cache_key":"e628a7773be8d41e10dc53dcb383a11096e0573ec6b470aa13d2a14adcefb8e7","segment_id":"start/wizard.md:e3ba8a2959965f9c","source_path":"start/wizard.md","text_hash":"e3ba8a2959965f9c8360537e304016b2f75d561bdb03655a42adb02ce75a0e3f","text":"Default workspaces follow ","translated":"默认工作区遵循 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:57Z"}
{"cache_key":"e62ed5670f8283396dcc6a81182cda94667ff98973f153e4c86a04db364a4895","segment_id":"start/wizard.md:a8dbd136ed7c8e55","source_path":"start/wizard.md","text_hash":"a8dbd136ed7c8e55f9c0ae6e5acd2576d485f642d964a61f3693afc1c0c4ffdf","text":": uses ","translated":":使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:41:50Z"}
{"cache_key":"e66b34ec94f9a9c10b99b098ad8806551356222f1ac50f6fec7d719991faceee","segment_id":"start/wizard.md:c36d819e7bc6d2b7","source_path":"start/wizard.md","text_hash":"c36d819e7bc6d2b7da51394411c733db89c395987885ca6770167a3b9bc45c3c","text":"Use ","translated":"使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:45Z"}
@@ -1225,7 +1189,6 @@
{"cache_key":"e6b4ca13a3b7e39f521b1aadbb4f54f37875d228cd918c6406bd6519d5c7b6c8","segment_id":"index.md:6638cf2301d3109d","source_path":"index.md","text_hash":"6638cf2301d3109da66a44ee3506fbd35b29773fa4ca33ff35eb838c21609e19","text":"Features (high level)","translated":"功能特性(概览)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:26Z"}
{"cache_key":"e6e2a9985237253e0478229a54f3693bc7b0472bc450d53a4122dc20dfe08b21","segment_id":"environment.md:6863067eb0a2c749","source_path":"environment.md","text_hash":"6863067eb0a2c7499425c6c189b2c88bac55ca754285a6ab1ef37b75b4cfad4d","text":"See ","translated":"参见 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:37Z"}
{"cache_key":"e6e456289628d5a4b6cbbc0fbb263d656ba7d49427a2009ce3c5f608b8505ea0","segment_id":"index.md:f0d82ba647b4a33d","source_path":"index.md","text_hash":"f0d82ba647b4a33da3008927253f9bed21e380f54eab0608b1136de4cbff1286","text":"OpenClaw bridges WhatsApp (via WhatsApp Web / Baileys), Telegram (Bot API / grammY), Discord (Bot API / channels.discord.js), and iMessage (imsg CLI) to coding agents like ","translated":"OpenClaw 将 WhatsApp通过 WhatsApp Web / Baileys、TelegramBot API / grammY、DiscordBot API / channels.discord.js和 iMessageimsg CLI桥接到编程 智能体,例如 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:56Z"}
{"cache_key":"e6ede2965d77195fa0296a69f8dc8beb3a2fee2b0264180126200d4adbaf4aa3","segment_id":"index.md:f14185309c5ab262","source_path":"index.md","text_hash":"f14185309c5ab26233fde49831f9fc27857a6e7ac200e91dc247ae3e3b74be27","text":"Companion apps:","translated":"伴侣应用:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:51Z"}
{"cache_key":"e723a0b2ab360a74b84f4ccd08fdc4cc1639b85d5178d45d8103a18069bd3d8d","segment_id":"start/getting-started.md:1b59a1d9fa6d392f","source_path":"start/getting-started.md","text_hash":"1b59a1d9fa6d392f1f68642200583ed0f7b372af2fbc7c01d5f7f00463e229de","text":" also bundles A2UI assets; if you need to run just that step, use ","translated":" 也会打包 A2UI 资源;如果您只需要运行该步骤,请使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:51Z"}
{"cache_key":"e7279b78eeb5dccdf1897af612ce9f34bbae6f6ad7d8a7fed40a48f2f59c2367","segment_id":"environment.md:frontmatter:summary","source_path":"environment.md:frontmatter:summary","text_hash":"78351223e7068721146d2de022fdf440c2866b2ee02fbbb50bf64369b999820b","text":"Where OpenClaw loads environment variables and the precedence order","translated":"OpenClaw 加载环境变量的位置及优先级顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:05Z"}
{"cache_key":"e73887cca1549bd1acf945a50dfbd054a3ec1c87741be5a0a4381a4840ce13e5","segment_id":"index.md:1df4f2299f0d9cc4","source_path":"index.md","text_hash":"1df4f2299f0d9cc466fa05abeb2831e76e9f89583228174ffcd9af415fd869fe","text":"Send a test message (requires a running Gateway):","translated":"发送测试消息(需要运行中的 Gateway","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:17Z"}
@@ -1235,7 +1198,6 @@
{"cache_key":"e7bc8ffa042426610faa9c40c7191933bfda50deb769ef153580d4ab1c75d679","segment_id":"start/getting-started.md:cdb4ee2aea69cc6a","source_path":"start/getting-started.md","text_hash":"cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8","text":".","translated":"。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:45Z"}
{"cache_key":"e8160fc2a7763ac99c0933d4424a99f211b661b0d7649bb1d33f908c3ff5e0d2","segment_id":"start/getting-started.md:75e23f5184b23835","source_path":"start/getting-started.md","text_hash":"75e23f5184b23835efb6fdc64309312d3c9212d10566350b1a08ff7838c79d03","text":"2) Run the onboarding wizard (and install the service)","translated":"2运行上手引导向导并安装服务","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:55Z"}
{"cache_key":"e81fa8ea81e681a305d677a823722958c2fdf42c3afbf4149a2d5cdfc4c6e1df","segment_id":"index.md:4eb58187170dc141","source_path":"index.md","text_hash":"4eb58187170dc14198eacb534c8577bef076349c26f2479e1f6a2e31df8eb948","text":" — An AI, probably high on tokens","translated":" — 一个可能被令牌冲昏头脑的 AI","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:06:53Z"}
{"cache_key":"e83550368cc1a10f9407b5e8da39dc639896bb6669eca7e49f6107ff3a3c306c","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:05Z"}
{"cache_key":"e87435d09fd52a520aeae4097eb83a149aeb498192ccfbdd63da8db57571de09","segment_id":"index.md:d08cec54f66c140c","source_path":"index.md","text_hash":"d08cec54f66c140c655a1631f6d629927c7c38b9c8bfa91c875df9bd3ad3c559","text":"OpenClaw assistant setup","translated":"OpenClaw 助手设置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:12Z"}
{"cache_key":"e8a313447619fd5d7895acf1c467e347d47a8c35861910facf5ff08f88a8905e","segment_id":"index.md:5928d14b4d45263d","source_path":"index.md","text_hash":"5928d14b4d45263d4964dfd301c84ed2674ca8b4b698c5efeb88fb86076d2bf9","text":"🎮 ","translated":"🎮 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:39Z"}
{"cache_key":"e8bfa9777ff1ca6f2921ef47688f6ddb7d1a68c074dc27c7af195521940fb68f","segment_id":"help/index.md:frontmatter:summary","source_path":"help/index.md:frontmatter:summary","text_hash":"aece82a2d540ab1a9a21c7b038127cae6e9db2149491564bb1856b6f8999f205","text":"Help hub: common fixes, install sanity, and where to look when something breaks","translated":"帮助中心:常见修复方法、安装完整性检查,以及出现问题时的排查指南","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:25Z"}
@@ -1257,11 +1219,9 @@
{"cache_key":"eca7489e62538a4b68a7d49f3a67df1c6bad8affc75d6411f68ca1e81bef47b2","segment_id":"environment.md:f6b2ffe1d0d5f521","source_path":"environment.md","text_hash":"f6b2ffe1d0d5f521b76cabc67d6e96da2b1170eef8086d530558e9906a7f092d","text":"Models overview","translated":"模型概览","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:17Z"}
{"cache_key":"ecb4df64e132ff6212066948863adabaa06122c77d8971d5c924dc2e744df845","segment_id":"index.md:98a670e2fb754896","source_path":"index.md","text_hash":"98a670e2fb7548964e8b78b90fef47f679580423427bfd15e5869aca9681d0dd","text":"\"We're all just playing with our own prompts.\"","translated":"\"我们都只是在玩弄自己的提示词。\"","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:43Z"}
{"cache_key":"ecd894720faa37450014e0fe1630be8382cf6ec23cbb9bfe76bc4125495d8fa5","segment_id":"index.md:9adcfa4aa10a4e8b","source_path":"index.md","text_hash":"9adcfa4aa10a4e8b991a72ccc45261cd64f296aed5b257e4caf9c87aff1290a0","text":" — Send and receive images, audio, documents","translated":" — 收发图片、音频、文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:38Z"}
{"cache_key":"ed00b197a3002ae69c3929cf870943136f802bf17b2850a71b6091111b76527d","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:33Z"}
{"cache_key":"ed10c233aa195883b17061f166f647efac5a27535a85ce4d16fc90d40e138882","segment_id":"help/index.md:8cd501e1124c3047","source_path":"help/index.md","text_hash":"8cd501e1124c30473473c06e536a2d145e2a14a6d7dc1b99028ce818e14442e2","text":"Repairs:","translated":"修复:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:56Z"}
{"cache_key":"ed15427258ffbf85620a0c9c0c42deb7f37be17b7abeff5993a34962964f0e96","segment_id":"index.md:a194ca16424ddd17","source_path":"index.md","text_hash":"a194ca16424ddd17dacc45f1cbd7d0e41376d8955a7b6d02bc38c295cedd04e4","text":"RPC adapters","translated":"RPC 适配器","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:19Z"}
{"cache_key":"ed24753e60b54d629cfd978be87185f4772676322534432302319caf28452d29","segment_id":"index.md:ab201ddd7ab330d0","source_path":"index.md","text_hash":"ab201ddd7ab330d04be364c0ac14ce68c52073a0ee8d164a98c3034e91ce1848","text":" from the repo.","translated":" (在仓库目录中执行)。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:21Z"}
{"cache_key":"ed366700bbcca6548c3fb1f7dae544b9a9cb0c56d6b36ca8e26c4880bc4e5667","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:17:08Z"}
{"cache_key":"ed37a2b1a8c3351a6c04bee81df6f507f306be344485e69eb87b3b2451aad89f","segment_id":"help/index.md:d3ef01b4a9c99103","source_path":"help/index.md","text_hash":"d3ef01b4a9c9910364c9b26b2499c8787a0461d2d24ab80376fff736a288b34c","text":"Logging","translated":"日志记录","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:47Z"}
{"cache_key":"ee3f1647acf674397ba7f7e1aee0f9972b9830f978b622695d8ab5360de5a496","segment_id":"index.md:255ce77b7a6a015f","source_path":"index.md","text_hash":"255ce77b7a6a015f8595868a524b67c134e8fb405f4584fdac020e57f4ccd5f6","text":"Loopback-first","translated":"回环优先","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:01Z"}
{"cache_key":"ee582fba5363de60fb2c00f9238f2ac9ad6dc7615694d8d23d24d88bf7ec13e1","segment_id":"environment.md:582967534d0f909d","source_path":"environment.md","text_hash":"582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf","text":" in ","translated":" 在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:29Z"}
@@ -1291,7 +1251,6 @@
{"cache_key":"f2a0941718593a4be66a7a033a4117a7b3a502ef64b25fd7d6d3475c77dd5a1a","segment_id":"environment.md:87e89abb4c1c551f","source_path":"environment.md","text_hash":"87e89abb4c1c551fe08d355d097f18b8de78edca5f556997085681662fce8eed","text":"Config ","translated":"配置 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:24Z"}
{"cache_key":"f2a0c70d8b9f94722b586320f11c58339d30dd1fe8ff7250a962bb2db84d5ab4","segment_id":"environment.md:ffa63583dfa6706b","source_path":"environment.md","text_hash":"ffa63583dfa6706b87d284b86b0d693a161e4840aad2c5cf6b5d27c3b9621f7d","text":"missing","translated":"缺失的","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:09Z"}
{"cache_key":"f2c14989f888bbff9c7330f2d5b3892af3b900910840435595031590dc8248e3","segment_id":"environment.md:frontmatter:read_when:0","source_path":"environment.md:frontmatter:read_when:0","text_hash":"90fc0487bff88009979cff1061c1a882df8c3b1baa9c43538331d9d5dab15479","text":"You need to know which env vars are loaded, and in what order","translated":"你需要了解加载了哪些环境变量,以及它们的加载顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:47Z"}
{"cache_key":"f2e6682f149332f775039f6c872837c04dbab51ea935ed4fe0085aa2a75cabe6","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:18Z"}
{"cache_key":"f34789e2cb492196e8c057294dd98c5f9d4b8054d548a7b883a47f113efa1277","segment_id":"index.md:31365ab9453d6a1e","source_path":"index.md","text_hash":"31365ab9453d6a1ec03731622803d3b44f345b6afad08040d7f3e97290c77913","text":"do nothing","translated":"不做任何操作","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:55Z"}
{"cache_key":"f36f13a67a73f6768bfbf346d552067475ef4f8137e13edfd4f636e1b7ef2ef8","segment_id":"start/getting-started.md:649cfa2f76a80b42","source_path":"start/getting-started.md","text_hash":"649cfa2f76a80b42e1821c89edd348794689409dcdf619dcd10624fb577c676b","text":"not recommended","translated":"不推荐","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:21Z"}
{"cache_key":"f3701b1ce8ac7f8931cafd209250aa5ae388ecfdb0154dbbb21c03fd72ce5d08","segment_id":"help/index.md:729bc562eec2658b","source_path":"help/index.md","text_hash":"729bc562eec2658bd11ffdd522fe5277177dc73e86eaca7baac0b472a4d8f8b2","text":"If youre looking for conceptual questions (not “something broke”):","translated":"如果你在寻找概念性问题(不是\"某个东西坏了\"","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:11:29Z"}
@@ -1340,7 +1299,6 @@
{"cache_key":"fab1c40ef11182f7118f5528b5ba6ed5b5c169c37b302382107e3fbab3d200c1","segment_id":"index.md:3d8fed7c358b2ccf","source_path":"index.md","text_hash":"3d8fed7c358b2ccf225ee16857a0bb9b950fd414319749e0f6fff58c99fa5f22","text":"Subscription auth","translated":"订阅认证","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:25Z"}
{"cache_key":"fae191ae8b8380df30a34afd63fc9ba9125258cee9f76e625da9a9c41a858973","segment_id":"start/wizard.md:158ac20b77d1dc12","source_path":"start/wizard.md","text_hash":"158ac20b77d1dc1223a47723e75f03b49fe61d0a6d69de4c3bba9fdd4c123c04","text":" only configures the local client to connect to a Gateway elsewhere.\nIt does ","translated":" 仅配置本地客户端以连接到其他位置的 Gateway。它 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:36Z"}
{"cache_key":"faf6394b29b7de4f1af4a5c01405a2c33d4a1f8f58691915d75eedd3572b1d49","segment_id":"index.md:a7a19d4f14d001a5","source_path":"index.md","text_hash":"a7a19d4f14d001a56c27f68a13ff267859a407c7a9ab457c0945693c9067dd1c","text":"Configuration (optional)","translated":"配置(可选)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:21Z"}
{"cache_key":"fb2cd6f6a8308f9b9ad6cb30dec3a08de2db675e77bc696aeb2ddb3084c9a6c4","segment_id":"start/wizard.md:58d30d963f28264b","source_path":"start/wizard.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:49:20Z"}
{"cache_key":"fc41f7c0ff1d82b20353a8a79f2da756675af014a48e1c36b3e693e2030aca4c","segment_id":"help/index.md:6201111b83a0cb5b","source_path":"help/index.md","text_hash":"6201111b83a0cb5b0922cb37cc442b9a40e24e3b1ce100a4bb204f4c63fd2ac0","text":" and ","translated":" 和 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:50Z"}
{"cache_key":"fc43ec1fbbcff82d8d617e73687d1fa0c004b3fa731fdb6c9a1b0825ac2df2f5","segment_id":"start/wizard.md:d80c4025fe9728d6","source_path":"start/wizard.md","text_hash":"d80c4025fe9728d67b8330bdbb25a3062c7748ae6779d348b66687d5a796550f","text":"Gateway wizard RPC","translated":"Gateway 向导 RPC","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:41Z"}
{"cache_key":"fc503e5044847f8c5412b75ba55ec912df5577a3bc37a7a975393684059d9c12","segment_id":"environment.md:61115f6649792387","source_path":"environment.md","text_hash":"61115f664979238731a390e84433a818965b7eaf1d38fa5b4b1507c33ef28c91","text":"Precedence (highest → lowest)","translated":"优先级(从高到低)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:00Z"}

View File

@@ -1,53 +0,0 @@
title: "OpenClaw Docs"
description: "A TypeScript/Node gateway + macOS/iOS/Android companions for WhatsApp (web) and Telegram (bot)."
markdown: kramdown
highlighter: rouge
# Keep GitHub Pages' default page URLs (e.g. /gateway.html). Many docs links
# are written as relative *.md links and are rewritten during the build.
plugins:
- jekyll-relative-links
relative_links:
enabled: true
collections: true
defaults:
- scope:
path: ""
values:
layout: default
nav:
- title: "Home"
url: "/"
- title: "OpenClaw Assistant"
url: "/start/openclaw/"
- title: "Gateway"
url: "/gateway/"
- title: "Remote"
url: "/gateway/remote/"
- title: "Discovery"
url: "/gateway/discovery/"
- title: "Configuration"
url: "/gateway/configuration/"
- title: "WebChat"
url: "/web/webchat/"
- title: "macOS App"
url: "/platforms/macos/"
- title: "iOS App"
url: "/platforms/ios/"
- title: "Android App"
url: "/platforms/android/"
- title: "Telegram"
url: "/channels/telegram/"
- title: "Security"
url: "/gateway/security/"
- title: "Troubleshooting"
url: "/gateway/troubleshooting/"
kramdown:
input: GFM
hard_wrap: false
syntax_highlighter: rouge

View File

@@ -1,145 +0,0 @@
<!doctype html>
<html lang="en" data-theme="auto">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light dark" />
<title>
{% if page.url == "/" %}{{ site.title }}{% else %}{{ page.title | default: page.path | split: "/" | last | replace: ".md", "" }} · {{ site.title }}{% endif %}
</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400..700&family=Fragment+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
/>
<script>
(() => {
try {
const stored = localStorage.getItem("openclaw:theme");
if (stored === "light" || stored === "dark") document.documentElement.dataset.theme = stored;
} catch {
// ignore
}
})();
</script>
<link rel="stylesheet" href="{{ "/assets/terminal.css" | relative_url }}" />
<link rel="stylesheet" href="{{ "/assets/markdown.css" | relative_url }}" />
<script defer src="{{ "/assets/theme.js" | relative_url }}"></script>
</head>
<body>
<a class="skip-link" href="#content">Skip to content</a>
<header class="shell">
<div class="shell__frame" role="banner">
<div class="shell__titlebar">
<div class="brand" aria-label="OpenClaw docs terminal">
<img
class="brand__logo"
src="{{ "/assets/pixel-lobster.svg" | relative_url }}"
alt=""
width="40"
height="40"
decoding="async"
/>
<div class="brand__text">
<div class="brand__name">OpenClaw</div>
<div class="brand__hint">docs // lobster terminal</div>
</div>
</div>
<div class="titlebar__actions">
<a class="titlebar__cta" href="https://github.com/openclaw/openclaw">
<span class="titlebar__cta-label">GitHub</span>
<span class="titlebar__cta-meta">repo</span>
</a>
<a class="titlebar__cta titlebar__cta--accent" href="https://github.com/openclaw/openclaw/releases/latest">
<span class="titlebar__cta-label">Download</span>
<span class="titlebar__cta-meta">latest</span>
</a>
</div>
</div>
<div class="shell__nav" aria-label="Primary">
<nav class="nav">
{% assign nav = site.nav | default: empty %}
{% for item in nav %}
{% assign item_url = item.url | relative_url %}
<a class="nav__link" href="{{ item_url }}">
<span class="nav__chev"></span>{{ item.title }}
</a>
{% endfor %}
</nav>
<div class="shell__status" aria-hidden="true">
<span class="status__dot"></span>
<span class="status__text">
{% if page.url == "/" %}
ready
{% else %}
viewing: {{ page.path }}
{% endif %}
</span>
</div>
</div>
</div>
</header>
<main id="content" class="content" role="main">
<div class="terminal">
<div class="terminal__prompt" aria-hidden="true">
<span class="prompt__user">openclaw</span>@<span class="prompt__host">openclaw</span>:<span class="prompt__path">~/docs</span>$<span class="prompt__cmd">
{% if page.url == "/" %}cat index.md{% else %}less {{ page.path }}{% endif %}
</span>
</div>
{% if page.summary %}
<p class="terminal__summary">{{ page.summary }}</p>
{% endif %}
{% if page.read_when %}
<details class="terminal__meta">
<summary>Read when…</summary>
<ul>
{% for hint in page.read_when %}
<li>{{ hint }}</li>
{% endfor %}
</ul>
</details>
{% endif %}
<article class="markdown">
{{ content }}
</article>
<footer class="terminal__footer" role="contentinfo">
<div class="footer__line">
<span class="footer__sig">openclaw.ai</span>
<span class="footer__sep">·</span>
<a href="https://github.com/openclaw/openclaw">source</a>
<span class="footer__sep">·</span>
<a href="https://github.com/openclaw/openclaw/releases">releases</a>
</div>
<div class="footer__hint" aria-hidden="true">
tip: press <kbd>F2</kbd> (Mac: <kbd>fn</kbd>+<kbd>F2</kbd>) to flip
the universe
</div>
<div class="footer__actions">
<button
class="theme-toggle"
type="button"
data-theme-toggle
aria-label="Toggle theme (F2; on Mac: fn+F2)"
aria-pressed="false"
>
<span class="theme-toggle__key">F2</span>
<span class="theme-toggle__label" data-theme-label>theme</span>
</button>
</div>
</footer>
</div>
</main>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

View File

@@ -1,179 +0,0 @@
.markdown {
margin-top: 18px;
line-height: 1.7;
}
.mdx-content > h1:first-of-type {
display: none;
}
.markdown h1,
.markdown h2,
.markdown h3,
.markdown h4 {
font-family: var(--font-pixel);
letter-spacing: 0.04em;
line-height: 1.15;
}
.markdown h1 {
font-size: clamp(28px, 4vw, 44px);
margin: 26px 0 10px;
}
.markdown h2 {
font-size: 22px;
margin: 26px 0 10px;
}
.markdown h3 {
font-size: 18px;
margin: 22px 0 8px;
}
.markdown p {
margin: 0 0 14px;
}
.markdown a {
color: var(--link);
text-decoration: none;
border-bottom: 1px dotted color-mix(in oklab, var(--link) 65%, transparent);
}
.markdown a:hover {
color: var(--link2);
border-bottom-color: color-mix(in oklab, var(--link2) 75%, transparent);
}
.markdown hr {
border: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent,
color-mix(in oklab, var(--frame-border) 30%, transparent),
transparent
);
margin: 26px 0;
}
.markdown blockquote {
margin: 18px 0;
padding: 14px 14px;
border-radius: var(--radius-sm);
background: color-mix(in oklab, var(--panel) 70%, transparent);
border-left: 6px solid color-mix(in oklab, var(--accent) 60%, transparent);
color: var(--muted);
}
.markdown ul,
.markdown ol {
margin: 0 0 14px 22px;
}
.markdown li {
margin: 4px 0;
}
.markdown img {
max-width: 100%;
height: auto;
border-radius: 12px;
border: 1px solid color-mix(in oklab, var(--frame-border) 20%, transparent);
box-shadow: 0 12px 0 -8px rgba(0, 0, 0, 0.18);
}
.showcase-link {
position: relative;
display: inline-flex;
align-items: center;
gap: 6px;
}
.showcase-preview {
position: absolute;
left: 50%;
top: 100%;
width: min(420px, 80vw);
padding: 8px;
border-radius: 14px;
background: color-mix(in oklab, var(--panel) 92%, transparent);
border: 1px solid color-mix(in oklab, var(--frame-border) 30%, transparent);
box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.55);
transform: translate(-50%, 10px) scale(0.98);
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 20;
transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s ease;
}
.showcase-preview img {
width: 100%;
height: auto;
border-radius: 10px;
border: 1px solid color-mix(in oklab, var(--frame-border) 25%, transparent);
box-shadow: none;
}
.showcase-link:hover .showcase-preview,
.showcase-link:focus-within .showcase-preview {
opacity: 1;
visibility: visible;
transform: translate(-50%, 6px) scale(1);
}
@media (hover: none) {
.showcase-preview {
display: none;
}
}
.markdown code {
font-family: var(--font-body);
font-size: 0.95em;
padding: 0.15em 0.35em;
border-radius: 8px;
background: color-mix(in oklab, var(--panel) 70%, var(--code-bg));
border: 1px solid color-mix(in oklab, var(--frame-border) 18%, transparent);
}
.markdown pre {
background: var(--code-bg);
color: var(--code-fg);
padding: 14px 14px;
border-radius: var(--radius-sm);
border: 1px solid color-mix(in oklab, var(--frame-border) 18%, transparent);
overflow-x: auto;
box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--code-accent) 12%, transparent);
}
.markdown pre code {
background: transparent;
border: 0;
padding: 0;
color: inherit;
}
.markdown table {
width: 100%;
border-collapse: collapse;
margin: 16px 0 22px;
border: 1px solid color-mix(in oklab, var(--frame-border) 20%, transparent);
border-radius: var(--radius-sm);
overflow: hidden;
}
.markdown th,
.markdown td {
padding: 10px 10px;
border-bottom: 1px solid color-mix(in oklab, var(--frame-border) 15%, transparent);
vertical-align: top;
}
.markdown th {
background: color-mix(in oklab, var(--panel2) 85%, transparent);
font-family: var(--font-pixel);
letter-spacing: 0.06em;
}

View File

@@ -1,473 +0,0 @@
:root {
--font-body: "Fragment Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--font-pixel: "Pixelify Sans", system-ui, sans-serif;
--radius: 14px;
--radius-sm: 10px;
--border: 2px;
--shadow-px: 0 0 0 var(--border) var(--frame-border), 0 12px 0 -4px rgba(0, 0, 0, 0.25);
--scanline-size: 6px;
--scanline-opacity: 0.08;
}
html[data-theme="light"],
html[data-theme="auto"] {
--bg0: #fbf4e7;
--bg1: #fffaf0;
--panel: #fffdf8;
--panel2: #fff6e5;
--text: #10221c;
--muted: #3e5a50;
--faint: #6b7f77;
--link: #0f6b4c;
--link2: #ff4f40;
--accent: #ff4f40;
--accent2: #00b88a;
--frame-border: #1b2e27;
--code-bg: #0b1713;
--code-fg: #eafff6;
--code-accent: #67ff9b;
}
html[data-theme="dark"] {
--bg0: #0b1a22;
--bg1: #0a1720;
--panel: #0e231f;
--panel2: #102a24;
--text: #c9eadc;
--muted: #8ab8aa;
--faint: #699b8d;
--link: #6fe8c7;
--link2: #ff7b63;
--accent: #ff4f40;
--accent2: #5fdfa2;
--frame-border: #6fbfa8;
--code-bg: #091814;
--code-fg: #d7f5e8;
--code-accent: #5fdfa2;
}
@media (prefers-color-scheme: dark) {
html[data-theme="auto"] {
--bg0: #0b1a22;
--bg1: #0a1720;
--panel: #0e231f;
--panel2: #102a24;
--text: #c9eadc;
--muted: #8ab8aa;
--faint: #699b8d;
--link: #6fe8c7;
--link2: #ff7b63;
--accent: #ff4f40;
--accent2: #5fdfa2;
--frame-border: #6fbfa8;
--code-bg: #091814;
--code-fg: #d7f5e8;
--code-accent: #5fdfa2;
}
}
* {
box-sizing: border-box;
}
html {
height: 100%;
}
body {
min-height: 100%;
}
body {
margin: 0;
font-family: var(--font-body);
color: var(--text);
background:
radial-gradient(1100px 700px at 20% -10%, color-mix(in oklab, var(--accent) 18%, transparent), transparent 55%),
radial-gradient(900px 600px at 95% 10%, color-mix(in oklab, var(--accent2) 14%, transparent), transparent 60%),
radial-gradient(900px 600px at 50% 120%, color-mix(in oklab, var(--link) 10%, transparent), transparent 55%),
linear-gradient(180deg, var(--bg0), var(--bg1));
overflow-x: hidden;
}
body::before,
body::after {
display: none;
}
.skip-link {
position: absolute;
top: 10px;
left: 10px;
z-index: 10;
padding: 10px 12px;
border-radius: 999px;
background: var(--panel);
color: var(--text);
text-decoration: none;
transform: translateY(-130%);
box-shadow: var(--shadow-px);
}
.skip-link:focus {
transform: translateY(0);
outline: none;
}
.shell {
position: sticky;
top: 0;
z-index: 100;
padding: 22px 16px 10px;
}
.shell__frame {
max-width: 1120px;
margin: 0 auto;
border-radius: var(--radius);
background:
linear-gradient(180deg, color-mix(in oklab, var(--panel2) 88%, transparent), color-mix(in oklab, var(--panel) 92%, transparent));
box-shadow: var(--shadow-px);
border: var(--border) solid var(--frame-border);
overflow: hidden;
}
.shell__titlebar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 14px 12px;
background:
linear-gradient(90deg, color-mix(in oklab, var(--accent) 26%, transparent), transparent 42%),
linear-gradient(180deg, color-mix(in oklab, var(--panel) 90%, #000 10%), color-mix(in oklab, var(--panel2) 90%, #000 10%));
}
.brand {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
}
.brand__logo {
flex: 0 0 auto;
width: 40px;
height: 40px;
image-rendering: pixelated;
filter: drop-shadow(0 2px 0 color-mix(in oklab, var(--frame-border) 80%, transparent));
}
.brand__text {
min-width: 0;
}
.brand__name {
font-family: var(--font-pixel);
letter-spacing: 0.14em;
font-weight: 700;
font-size: 18px;
line-height: 1.1;
text-shadow: 0 1px 0 color-mix(in oklab, var(--frame-border) 55%, transparent);
}
.brand__hint {
margin-top: 2px;
font-size: 12px;
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.titlebar__actions {
display: flex;
align-items: center;
gap: 10px;
}
.titlebar__cta {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 12px 8px 10px;
border-radius: 12px;
background:
linear-gradient(140deg, color-mix(in oklab, var(--accent) 10%, transparent), transparent 60%),
color-mix(in oklab, var(--panel) 92%, transparent);
border: var(--border) solid color-mix(in oklab, var(--frame-border) 80%, transparent);
color: var(--text);
text-decoration: none;
box-shadow:
0 6px 0 -3px rgba(0, 0, 0, 0.25),
inset 0 0 0 1px color-mix(in oklab, var(--panel2) 55%, transparent);
}
.titlebar__cta:hover {
border-color: color-mix(in oklab, var(--accent2) 45%, transparent);
box-shadow:
0 0 0 2px color-mix(in oklab, var(--accent2) 30%, transparent),
0 6px 0 -3px rgba(0, 0, 0, 0.25);
}
.titlebar__cta:active {
transform: translateY(1px);
box-shadow: 0 4px 0 -3px rgba(0, 0, 0, 0.25);
}
.titlebar__cta:focus-visible {
outline: 3px solid color-mix(in oklab, var(--accent2) 60%, transparent);
outline-offset: 2px;
}
.titlebar__cta--accent {
background:
linear-gradient(120deg, color-mix(in oklab, var(--accent) 22%, transparent), transparent 70%),
color-mix(in oklab, var(--panel) 88%, transparent);
border-color: color-mix(in oklab, var(--accent) 60%, var(--frame-border));
}
.titlebar__cta-label {
font-family: var(--font-pixel);
letter-spacing: 0.12em;
font-size: 12px;
text-transform: uppercase;
}
.titlebar__cta-meta {
display: inline-flex;
align-items: center;
justify-content: center;
height: 20px;
padding: 0 8px;
border-radius: 999px;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
background: var(--code-bg);
color: var(--code-accent);
border: 1px solid color-mix(in oklab, var(--code-accent) 30%, transparent);
box-shadow: inset 0 0 12px color-mix(in oklab, var(--code-accent) 25%, transparent);
}
.theme-toggle {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 9px 10px;
border-radius: 12px;
background: color-mix(in oklab, var(--panel) 92%, transparent);
border: var(--border) solid var(--frame-border);
color: var(--text);
cursor: pointer;
box-shadow: 0 6px 0 -3px rgba(0, 0, 0, 0.25);
user-select: none;
}
.theme-toggle:active {
transform: translateY(1px);
box-shadow: 0 4px 0 -3px rgba(0, 0, 0, 0.25);
}
.theme-toggle__key {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 28px;
border-radius: 9px;
background: var(--code-bg);
color: var(--code-accent);
border: 1px solid color-mix(in oklab, var(--code-accent) 30%, transparent);
font-weight: 700;
font-size: 12px;
letter-spacing: 0.06em;
text-shadow: 0 0 14px color-mix(in oklab, var(--code-accent) 55%, transparent);
}
.theme-toggle__label {
font-family: var(--font-pixel);
letter-spacing: 0.12em;
font-size: 12px;
text-transform: uppercase;
}
.theme-toggle:focus-visible {
outline: 3px solid color-mix(in oklab, var(--accent2) 60%, transparent);
outline-offset: 2px;
}
.shell__nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
padding: 10px 14px 12px;
border-top: 1px solid color-mix(in oklab, var(--frame-border) 25%, transparent);
background: linear-gradient(180deg, transparent, color-mix(in oklab, var(--panel2) 78%, transparent));
}
.nav {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.nav__link {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border-radius: 999px;
text-decoration: none;
color: var(--text);
background: color-mix(in oklab, var(--panel) 85%, transparent);
border: 1px solid color-mix(in oklab, var(--frame-border) 20%, transparent);
}
.nav__link:hover {
border-color: color-mix(in oklab, var(--accent2) 45%, transparent);
box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent2) 30%, transparent);
}
.nav__chev {
color: var(--accent);
font-weight: 700;
}
.shell__status {
display: inline-flex;
align-items: center;
gap: 10px;
color: var(--muted);
font-size: 12px;
white-space: nowrap;
}
.status__dot {
width: 10px;
height: 10px;
border-radius: 999px;
background: radial-gradient(circle at 30% 30%, var(--accent2), color-mix(in oklab, var(--accent2) 30%, #000));
box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent2) 18%, transparent), 0 0 18px color-mix(in oklab, var(--accent2) 50%, transparent);
}
.content {
padding: 18px 16px 48px;
}
.terminal {
position: relative;
max-width: 1120px;
margin: 0 auto;
border-radius: var(--radius);
border: var(--border) solid var(--frame-border);
background: linear-gradient(180deg, color-mix(in oklab, var(--panel) 92%, transparent), color-mix(in oklab, var(--panel2) 86%, transparent));
box-shadow: var(--shadow-px);
padding: 18px 16px 16px;
}
.terminal__prompt {
display: block;
padding: 10px 12px;
border-radius: var(--radius-sm);
background: var(--code-bg);
color: var(--code-fg);
border: 1px solid color-mix(in oklab, var(--frame-border) 18%, transparent);
overflow-x: auto;
white-space: nowrap;
}
.prompt__user {
color: var(--code-accent);
text-shadow: 0 0 16px color-mix(in oklab, var(--code-accent) 52%, transparent);
}
.prompt__host {
color: color-mix(in oklab, var(--code-fg) 92%, var(--accent2));
}
.prompt__path {
color: color-mix(in oklab, var(--code-fg) 78%, var(--link));
}
.prompt__cmd {
margin-left: 8px;
color: color-mix(in oklab, var(--code-fg) 90%, var(--accent));
}
.terminal__summary {
margin: 12px 2px 0;
color: var(--muted);
font-size: 14px;
line-height: 1.5;
}
.terminal__meta {
margin: 12px 2px 0;
padding: 12px 12px;
border-radius: var(--radius-sm);
border: 1px dashed color-mix(in oklab, var(--frame-border) 25%, transparent);
background: color-mix(in oklab, var(--panel) 76%, transparent);
color: var(--faint);
font-size: 13px;
}
.terminal__meta summary {
cursor: pointer;
font-family: var(--font-pixel);
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text);
}
.terminal__meta ul {
margin: 10px 0 0 18px;
}
.terminal__footer {
margin-top: 22px;
padding-top: 16px;
border-top: 1px solid color-mix(in oklab, var(--frame-border) 20%, transparent);
color: var(--muted);
font-size: 13px;
}
.footer__actions {
margin-top: 14px;
display: flex;
justify-content: flex-end;
}
.terminal__footer a {
color: var(--link);
text-decoration: none;
border-bottom: 1px dotted color-mix(in oklab, var(--link) 55%, transparent);
}
.terminal__footer a:hover {
color: var(--link2);
border-bottom-color: color-mix(in oklab, var(--link2) 75%, transparent);
}
.footer__hint {
margin-top: 8px;
color: var(--faint);
}
kbd {
font-family: var(--font-body);
font-size: 0.9em;
padding: 2px 6px;
border-radius: 8px;
border: 1px solid color-mix(in oklab, var(--frame-border) 18%, transparent);
background: color-mix(in oklab, var(--panel) 65%, transparent);
box-shadow: 0 6px 0 -4px rgba(0, 0, 0, 0.18);
}
@supports not (color: color-mix(in oklab, black, white)) {
body::before,
body::after {
opacity: 0.2;
}
}

View File

@@ -1,55 +0,0 @@
const THEME_STORAGE_KEY = "openclaw:theme";
function safeGet(key) {
try {
return localStorage.getItem(key);
} catch {
return null;
}
}
function safeSet(key, value) {
try {
localStorage.setItem(key, value);
} catch {
// ignore
}
}
function preferredTheme() {
const stored = safeGet(THEME_STORAGE_KEY);
if (stored === "light" || stored === "dark") return stored;
return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
function applyTheme(theme) {
document.documentElement.dataset.theme = theme;
const toggle = document.querySelector("[data-theme-toggle]");
const label = document.querySelector("[data-theme-label]");
if (toggle instanceof HTMLButtonElement) toggle.setAttribute("aria-pressed", theme === "dark" ? "true" : "false");
if (label) label.textContent = theme === "dark" ? "dark" : "light";
}
function toggleTheme() {
const current = document.documentElement.dataset.theme === "dark" ? "dark" : "light";
const next = current === "dark" ? "light" : "dark";
safeSet(THEME_STORAGE_KEY, next);
applyTheme(next);
}
applyTheme(preferredTheme());
document.addEventListener("click", (event) => {
const target = event.target;
const button = target instanceof Element ? target.closest("[data-theme-toggle]") : null;
if (button) toggleTheme();
});
document.addEventListener("keydown", (event) => {
if (event.key === "F2") {
event.preventDefault();
toggleTheme();
}
});

View File

@@ -23,7 +23,7 @@ cron is the mechanism.
- Jobs persist under `~/.openclaw/cron/` so restarts dont lose schedules.
- Two execution styles:
- **Main session**: enqueue a system event, then run on the next heartbeat.
- **Isolated**: run a dedicated agent turn in `cron:<jobId>`, optionally deliver output.
- **Isolated**: run a dedicated agent turn in `cron:<jobId>`, with delivery (announce by default or none).
- Wakeups are first-class: a job can request “wake now” vs “next heartbeat”.
## Quick start (actionable)
@@ -40,7 +40,7 @@ openclaw cron add \
--delete-after-run
openclaw cron list
openclaw cron run <job-id> --force
openclaw cron run <job-id>
openclaw cron runs --id <job-id>
```
@@ -53,7 +53,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--deliver \
--announce \
--channel slack \
--to "channel:C1234567890"
```
@@ -86,7 +86,8 @@ Think of a cron job as: **when** to run + **what** to do.
- Main session → `payload.kind = "systemEvent"`
- Isolated session → `payload.kind = "agentTurn"`
Optional: `deleteAfterRun: true` removes successful one-shot jobs from the store.
Optional: one-shot jobs (`schedule.kind = "at"`) delete after success by default. Set
`deleteAfterRun: false` to keep them (they will disable after success).
## Concepts
@@ -96,19 +97,19 @@ A cron job is a stored record with:
- a **schedule** (when it should run),
- a **payload** (what it should do),
- optional **delivery** (where output should be sent).
- optional **delivery mode** (announce or none).
- optional **agent binding** (`agentId`): run the job under a specific agent; if
missing or unknown, the gateway falls back to the default agent.
Jobs are identified by a stable `jobId` (used by CLI/Gateway APIs).
In agent tool calls, `jobId` is canonical; legacy `id` is accepted for compatibility.
Jobs can optionally auto-delete after a successful one-shot run via `deleteAfterRun: true`.
One-shot jobs auto-delete after success by default; set `deleteAfterRun: false` to keep them.
### Schedules
Cron supports three schedule kinds:
- `at`: one-shot timestamp (ms since epoch). Gateway accepts ISO 8601 and coerces to UTC.
- `at`: one-shot timestamp via `schedule.at` (ISO 8601).
- `every`: fixed interval (ms).
- `cron`: 5-field cron expression with optional IANA timezone.
@@ -122,8 +123,8 @@ local timezone is used.
Main jobs enqueue a system event and optionally wake the heartbeat runner.
They must use `payload.kind = "systemEvent"`.
- `wakeMode: "next-heartbeat"` (default): event waits for the next scheduled heartbeat.
- `wakeMode: "now"`: event triggers an immediate heartbeat run.
- `wakeMode: "now"` (default): event triggers an immediate heartbeat run.
- `wakeMode: "next-heartbeat"`: event waits for the next scheduled heartbeat.
This is the best fit when you want the normal heartbeat prompt + main-session context.
See [Heartbeat](/gateway/heartbeat).
@@ -136,9 +137,13 @@ Key behaviors:
- Prompt is prefixed with `[cron:<jobId> <job name>]` for traceability.
- Each run starts a **fresh session id** (no prior conversation carry-over).
- A summary is posted to the main session (prefix `Cron`, configurable).
- `wakeMode: "now"` triggers an immediate heartbeat after posting the summary.
- If `payload.deliver: true`, output is delivered to a channel; otherwise it stays internal.
- Default behavior: if `delivery` is omitted, isolated jobs announce a summary (`delivery.mode = "announce"`).
- `delivery.mode` (isolated-only) chooses what happens:
- `announce`: deliver a summary to the target channel and post a brief summary to the main session.
- `none`: internal only (no delivery, no main-session summary).
- `wakeMode` controls when the main-session summary posts:
- `now`: immediate heartbeat.
- `next-heartbeat`: waits for the next scheduled heartbeat.
Use isolated jobs for noisy, frequent, or "background chores" that shouldn't spam
your main chat history.
@@ -155,16 +160,35 @@ Common `agentTurn` fields:
- `message`: required text prompt.
- `model` / `thinking`: optional overrides (see below).
- `timeoutSeconds`: optional timeout override.
- `deliver`: `true` to send output to a channel target.
- `channel`: `last` or a specific channel.
- `to`: channel-specific target (phone/chat/channel id).
- `bestEffortDeliver`: avoid failing the job if delivery fails.
Isolation options (only for `session=isolated`):
Delivery config (isolated jobs only):
- `postToMainPrefix` (CLI: `--post-prefix`): prefix for the system event in main.
- `postToMainMode`: `summary` (default) or `full`.
- `postToMainMaxChars`: max chars when `postToMainMode=full` (default 8000).
- `delivery.mode`: `none` | `announce`.
- `delivery.channel`: `last` or a specific channel.
- `delivery.to`: channel-specific target (phone/chat/channel id).
- `delivery.bestEffort`: avoid failing the job if announce delivery fails.
Announce delivery suppresses messaging tool sends for the run; use `delivery.channel`/`delivery.to`
to target the chat instead. When `delivery.mode = "none"`, no summary is posted to the main session.
If `delivery` is omitted for isolated jobs, OpenClaw defaults to `announce`.
#### Announce delivery flow
When `delivery.mode = "announce"`, cron delivers directly via the outbound channel adapters.
The main agent is not spun up to craft or forward the message.
Behavior details:
- Content: delivery uses the isolated run's outbound payloads (text/media) with normal chunking and
channel formatting.
- Heartbeat-only responses (`HEARTBEAT_OK` with no real content) are not delivered.
- If the isolated run already sent a message to the same target via the message tool, delivery is
skipped to avoid duplicates.
- Missing or invalid delivery targets fail the job unless `delivery.bestEffort = true`.
- A short summary is posted to the main session only when `delivery.mode = "announce"`.
- The main-session summary respects `wakeMode`: `now` triggers an immediate heartbeat and
`next-heartbeat` waits for the next scheduled heartbeat.
### Model and thinking overrides
@@ -185,19 +209,16 @@ Resolution priority:
### Delivery (channel + target)
Isolated jobs can deliver output to a channel. The job payload can specify:
Isolated jobs can deliver output to a channel via the top-level `delivery` config:
- `channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`
- `to`: channel-specific recipient target
- `delivery.mode`: `announce` (deliver a summary) or `none`.
- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`.
- `delivery.to`: channel-specific recipient target.
If `channel` or `to` is omitted, cron can fall back to the main sessions “last route”
(the last place the agent replied).
Delivery config is only valid for isolated jobs (`sessionTarget: "isolated"`).
Delivery notes:
- If `to` is set, cron auto-delivers the agents final output even if `deliver` is omitted.
- Use `deliver: true` when you want last-route delivery without an explicit `to`.
- Use `deliver: false` to keep output internal even if a `to` is present.
If `delivery.channel` or `delivery.to` is omitted, cron can fall back to the main sessions
“last route” (the last place the agent replied).
Target format reminders:
@@ -220,8 +241,8 @@ Prefixed targets like `telegram:...` / `telegram:group:...` are also accepted:
## JSON schema for tool calls
Use these shapes when calling Gateway `cron.*` tools directly (agent tool calls or RPC).
CLI flags accept human durations like `20m`, but tool calls use epoch milliseconds for
`atMs` and `everyMs` (ISO timestamps are accepted for `at` times).
CLI flags accept human durations like `20m`, but tool calls should use an ISO 8601 string
for `schedule.at` and milliseconds for `schedule.everyMs`.
### cron.add params
@@ -230,7 +251,7 @@ One-shot, main session job (system event):
```json
{
"name": "Reminder",
"schedule": { "kind": "at", "atMs": 1738262400000 },
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
@@ -248,23 +269,26 @@ Recurring, isolated job with delivery:
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates.",
"deliver": true,
"message": "Summarize overnight updates."
},
"delivery": {
"mode": "announce",
"channel": "slack",
"to": "channel:C1234567890",
"bestEffortDeliver": true
},
"isolation": { "postToMainPrefix": "Cron", "postToMainMode": "summary" }
"bestEffort": true
}
}
```
Notes:
- `schedule.kind`: `at` (`atMs`), `every` (`everyMs`), or `cron` (`expr`, optional `tz`).
- `atMs` and `everyMs` are epoch milliseconds.
- `schedule.kind`: `at` (`at`), `every` (`everyMs`), or `cron` (`expr`, optional `tz`).
- `schedule.at` accepts ISO 8601 (timezone optional; treated as UTC when omitted).
- `everyMs` is milliseconds.
- `sessionTarget` must be `"main"` or `"isolated"` and must match `payload.kind`.
- Optional fields: `agentId`, `description`, `enabled`, `deleteAfterRun`, `isolation`.
- `wakeMode` defaults to `"next-heartbeat"` when omitted.
- Optional fields: `agentId`, `description`, `enabled`, `deleteAfterRun` (defaults to true for `at`),
`delivery`.
- `wakeMode` defaults to `"now"` when omitted.
### cron.update params
@@ -341,7 +365,7 @@ openclaw cron add \
--wake now
```
Recurring isolated job (deliver to WhatsApp):
Recurring isolated job (announce to WhatsApp):
```bash
openclaw cron add \
@@ -350,7 +374,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--deliver \
--announce \
--channel whatsapp \
--to "+15551234567"
```
@@ -364,7 +388,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--deliver \
--announce \
--channel telegram \
--to "-1001234567890:topic:123"
```
@@ -380,7 +404,7 @@ openclaw cron add \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--deliver \
--announce \
--channel whatsapp \
--to "+15551234567"
```
@@ -396,10 +420,11 @@ openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent
```
Manual run (debug):
Manual run (force is the default, use `--due` to only run when due):
```bash
openclaw cron run <jobId> --force
openclaw cron run <jobId>
openclaw cron run <jobId> --due
```
Edit an existing job (patch fields):

View File

@@ -90,7 +90,8 @@ Cron jobs run at **exact times** and can run in isolated sessions without affect
- **Exact timing**: 5-field cron expressions with timezone support.
- **Session isolation**: Runs in `cron:<jobId>` without polluting main history.
- **Model overrides**: Use a cheaper or more powerful model per job.
- **Delivery control**: Can deliver directly to a channel; still posts a summary to main by default (configurable).
- **Delivery control**: Isolated jobs default to `announce` (summary); choose `none` as needed.
- **Immediate delivery**: Announce mode posts directly without waiting for heartbeat.
- **No agent context needed**: Runs even if main session is idle or compacted.
- **One-shot support**: `--at` for precise future timestamps.
@@ -104,12 +105,12 @@ openclaw cron add \
--session isolated \
--message "Generate today's briefing: weather, calendar, top emails, news summary." \
--model opus \
--deliver \
--announce \
--channel whatsapp \
--to "+15551234567"
```
This runs at exactly 7:00 AM New York time, uses Opus for quality, and delivers directly to WhatsApp.
This runs at exactly 7:00 AM New York time, uses Opus for quality, and announces a summary directly to WhatsApp.
### Cron example: One-shot reminder
@@ -173,7 +174,7 @@ The most efficient setup uses **both**:
```bash
# Daily morning briefing at 7am
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --deliver
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce
# Weekly project review on Mondays at 9am
openclaw cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus
@@ -214,13 +215,13 @@ See [Lobster](/tools/lobster) for full usage and examples.
Both heartbeat and cron can interact with the main session, but differently:
| | Heartbeat | Cron (main) | Cron (isolated) |
| ------- | ------------------------------- | ------------------------ | ---------------------- |
| Session | Main | Main (via system event) | `cron:<jobId>` |
| History | Shared | Shared | Fresh each run |
| Context | Full | Full | None (starts clean) |
| Model | Main session model | Main session model | Can override |
| Output | Delivered if not `HEARTBEAT_OK` | Heartbeat prompt + event | Summary posted to main |
| | Heartbeat | Cron (main) | Cron (isolated) |
| ------- | ------------------------------- | ------------------------ | -------------------------- |
| Session | Main | Main (via system event) | `cron:<jobId>` |
| History | Shared | Shared | Fresh each run |
| Context | Full | Full | None (starts clean) |
| Model | Main session model | Main session model | Can override |
| Output | Delivered if not `HEARTBEAT_OK` | Heartbeat prompt + event | Announce summary (default) |
### When to use main session cron
@@ -245,7 +246,7 @@ Use `--session isolated` when you want:
- A clean slate without prior context
- Different model or thinking settings
- Output delivered directly to a channel (summary still posts to main by default)
- Announce summaries directly to a channel
- History that doesn't clutter main session
```bash
@@ -256,7 +257,7 @@ openclaw cron add \
--message "Weekly codebase analysis..." \
--model opus \
--thinking high \
--deliver
--announce
```
## Cost Considerations

View File

@@ -78,8 +78,8 @@ export AWS_BEARER_TOKEN_BEDROCK="..."
auth: "aws-sdk",
models: [
{
id: "anthropic.claude-opus-4-5-20251101-v1:0",
name: "Claude Opus 4.5 (Bedrock)",
id: "us.anthropic.claude-opus-4-6-v1:0",
name: "Claude Opus 4.6 (Bedrock)",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
@@ -92,7 +92,7 @@ export AWS_BEARER_TOKEN_BEDROCK="..."
},
agents: {
defaults: {
model: { primary: "amazon-bedrock/anthropic.claude-opus-4-5-20251101-v1:0" },
model: { primary: "amazon-bedrock/us.anthropic.claude-opus-4-6-v1:0" },
},
},
}

View File

@@ -12,7 +12,7 @@ OpenClaw uses Brave Search as the default provider for `web_search`.
## Get an API key
1. Create a Brave Search API account at https://brave.com/search/api/
1. Create a Brave Search API account at [https://brave.com/search/api/](https://brave.com/search/api/)
2. In the dashboard, choose the **Data for Search** plan and generate an API key.
3. Store the key in config (recommended) or set `BRAVE_API_KEY` in the Gateway environment.

View File

@@ -27,6 +27,7 @@ Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **R
1. Install the BlueBubbles server on your Mac (follow the instructions at [bluebubbles.app/install](https://bluebubbles.app/install)).
2. In the BlueBubbles config, enable the web API and set a password.
3. Run `openclaw onboard` and select BlueBubbles, or configure manually:
```json5
{
channels: {
@@ -39,9 +40,84 @@ Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **R
},
}
```
4. Point BlueBubbles webhooks to your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
5. Start the gateway; it will register the webhook handler and start pairing.
## Keeping Messages.app alive (VM / headless setups)
Some macOS VM / always-on setups can end up with Messages.app going “idle” (incoming events stop until the app is opened/foregrounded). A simple workaround is to **poke Messages every 5 minutes** using an AppleScript + LaunchAgent.
### 1) Save the AppleScript
Save this as:
- `~/Scripts/poke-messages.scpt`
Example script (non-interactive; does not steal focus):
```applescript
try
tell application "Messages"
if not running then
launch
end if
-- Touch the scripting interface to keep the process responsive.
set _chatCount to (count of chats)
end tell
on error
-- Ignore transient failures (first-run prompts, locked session, etc).
end try
```
### 2) Install a LaunchAgent
Save this as:
- `~/Library/LaunchAgents/com.user.poke-messages.plist`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.poke-messages</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-lc</string>
<string>/usr/bin/osascript &quot;$HOME/Scripts/poke-messages.scpt&quot;</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>300</integer>
<key>StandardOutPath</key>
<string>/tmp/poke-messages.log</string>
<key>StandardErrorPath</key>
<string>/tmp/poke-messages.err</string>
</dict>
</plist>
```
Notes:
- This runs **every 300 seconds** and **on login**.
- The first run may trigger macOS **Automation** prompts (`osascript` → Messages). Approve them in the same user session that runs the LaunchAgent.
Load it:
```bash
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
```
## Onboarding
BlueBubbles is available in the interactive setup wizard:
@@ -261,4 +337,4 @@ Prefer `chat_guid` for stable routing:
- 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`.
- For status/health info: `openclaw status --all` or `openclaw status --deep`.
For general channel workflow reference, see [Channels](/channels) and the [Plugins](/plugins) guide.
For general channel workflow reference, see [Channels](/channels) and the [Plugins](/plugin) guide.

View File

@@ -100,7 +100,7 @@ In **Bot** → **Privileged Gateway Intents**, enable:
- **Message Content Intent** (required to read message text in most guilds; without it youll see “Used disallowed intents” or the bot will connect but not react to messages)
- **Server Members Intent** (recommended; required for some member/user lookups and allowlist matching in guilds)
You usually do **not** need **Presence Intent**.
You usually do **not** need **Presence Intent**. Setting the bot's own presence (`setPresence` action) uses gateway OP3 and does not require this intent; it is only needed if you want to receive presence updates about other guild members.
### 3) Generate an invite URL (OAuth2 URL Generator)
@@ -196,6 +196,7 @@ Notes:
- If `channels` is present, any channel not listed is denied by default.
- Use a `"*"` channel entry to apply defaults across all channels; explicit channel entries override the wildcard.
- Threads inherit parent channel config (allowlist, `requireMention`, skills, prompts, etc.) unless you add the thread channel id explicitly.
- Owner hint: when a per-guild or per-channel `users` allowlist matches the sender, OpenClaw treats that sender as the owner in the system prompt. For a global owner across channels, set `commands.ownerAllowFrom`.
- Bot-authored messages are ignored by default; set `channels.discord.allowBots=true` to allow them (own messages remain filtered).
- Warning: If you allow replies to other bots (`channels.discord.allowBots=true`), prevent bot-to-bot reply loops with `requireMention`, `channels.discord.guilds.*.channels.<id>.users` allowlists, and/or clear guardrails in `AGENTS.md` and `SOUL.md`.
@@ -278,6 +279,7 @@ Outbound Discord API calls retry on rate limits (429) using Discord `retry_after
voiceStatus: true,
events: true,
moderation: false,
presence: false,
},
replyToMode: "off",
dm: {
@@ -333,7 +335,7 @@ ack reaction after the bot replies.
- `guilds.<id>.channels.<channel>.toolsBySender`: optional per-sender tool policy overrides within the channel (`"*"` wildcard supported).
- `guilds.<id>.channels.<channel>.users`: optional per-channel user allowlist.
- `guilds.<id>.channels.<channel>.skills`: skill filter (omit = all skills, empty = none).
- `guilds.<id>.channels.<channel>.systemPrompt`: extra system prompt for the channel (combined with channel topic).
- `guilds.<id>.channels.<channel>.systemPrompt`: extra system prompt for the channel. Discord channel topics are injected as **untrusted** context (not system prompt).
- `guilds.<id>.channels.<channel>.enabled`: set `false` to disable the channel.
- `guilds.<id>.channels`: channel rules (keys are channel slugs or ids).
- `guilds.<id>.requireMention`: per-guild mention requirement (overridable per channel).
@@ -353,6 +355,7 @@ ack reaction after the bot replies.
- `channels` (create/edit/delete channels + categories + permissions)
- `roles` (role add/remove, default `false`)
- `moderation` (timeout/kick/ban, default `false`)
- `presence` (bot status/activity, default `false`)
- `execApprovals`: Discord-only exec approval DMs (button UI). Supports `enabled`, `approvers`, `agentFilter`, `sessionFilter`.
Reaction notifications use `guilds.<id>.reactionNotifications`:
@@ -412,6 +415,7 @@ Allowlist notes (PK-enabled):
| events | enabled | List/create scheduled events |
| roles | disabled | Role add/remove |
| moderation | disabled | Timeout/kick/ban |
| presence | disabled | Bot status/activity (setPresence) |
- `replyToMode`: `off` (default), `first`, or `all`. Applies only when the model includes a reply tag.
@@ -460,6 +464,7 @@ The agent can call `discord` with actions like:
- `searchMessages`, `memberInfo`, `roleInfo`, `roleAdd`, `roleRemove`, `emojiList`
- `channelInfo`, `channelList`, `voiceStatus`, `eventList`, `eventCreate`
- `timeout`, `kick`, `ban`
- `setPresence` (bot activity and online status)
Discord message ids are surfaced in the injected context (`[discord message id: …]` and history lines) so the agent can target them.
Emoji can be unicode (e.g., `✅`) or custom emoji syntax like `<:party_blob:1234567890>`.

579
docs/channels/feishu.md Normal file
View File

@@ -0,0 +1,579 @@
---
summary: "Feishu bot overview, features, and configuration"
read_when:
- You want to connect a Feishu/Lark bot
- You are configuring the Feishu channel
title: Feishu
---
# Feishu bot
Feishu (Lark) is a team chat platform used by companies for messaging and collaboration. This plugin connects OpenClaw to a Feishu/Lark bot using the platforms WebSocket event subscription so messages can be received without exposing a public webhook URL.
---
## Plugin required
Install the Feishu plugin:
```bash
openclaw plugins install @openclaw/feishu
```
Local checkout (when running from a git repo):
```bash
openclaw plugins install ./extensions/feishu
```
---
## Quickstart
There are two ways to add the Feishu channel:
### Method 1: onboarding wizard (recommended)
If you just installed OpenClaw, run the wizard:
```bash
openclaw onboard
```
The wizard guides you through:
1. Creating a Feishu app and collecting credentials
2. Configuring app credentials in OpenClaw
3. Starting the gateway
**After configuration**, check gateway status:
- `openclaw gateway status`
- `openclaw logs --follow`
### Method 2: CLI setup
If you already completed initial install, add the channel via CLI:
```bash
openclaw channels add
```
Choose **Feishu**, then enter the App ID and App Secret.
**After configuration**, manage the gateway:
- `openclaw gateway status`
- `openclaw gateway restart`
- `openclaw logs --follow`
---
## Step 1: Create a Feishu app
### 1. Open Feishu Open Platform
Visit [Feishu Open Platform](https://open.feishu.cn/app) and sign in.
Lark (global) tenants should use [https://open.larksuite.com/app](https://open.larksuite.com/app) and set `domain: "lark"` in the Feishu config.
### 2. Create an app
1. Click **Create enterprise app**
2. Fill in the app name + description
3. Choose an app icon
![Create enterprise app](../images/feishu-step2-create-app.png)
### 3. Copy credentials
From **Credentials & Basic Info**, copy:
- **App ID** (format: `cli_xxx`)
- **App Secret**
**Important:** keep the App Secret private.
![Get credentials](../images/feishu-step3-credentials.png)
### 4. Configure permissions
On **Permissions**, click **Batch import** and paste:
```json
{
"scopes": {
"tenant": [
"aily:file:read",
"aily:file:write",
"application:application.app_message_stats.overview:readonly",
"application:application:self_manage",
"application:bot.menu:write",
"contact:user.employee_id:readonly",
"corehr:file:download",
"event:ip_list",
"im:chat.access_event.bot_p2p_chat:read",
"im:chat.members:bot_access",
"im:message",
"im:message.group_at_msg:readonly",
"im:message.p2p_msg:readonly",
"im:message:readonly",
"im:message:send_as_bot",
"im:resource"
],
"user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"]
}
}
```
![Configure permissions](../images/feishu-step4-permissions.png)
### 5. Enable bot capability
In **App Capability** > **Bot**:
1. Enable bot capability
2. Set the bot name
![Enable bot capability](../images/feishu-step5-bot-capability.png)
### 6. Configure event subscription
⚠️ **Important:** before setting event subscription, make sure:
1. You already ran `openclaw channels add` for Feishu
2. The gateway is running (`openclaw gateway status`)
In **Event Subscription**:
1. Choose **Use long connection to receive events** (WebSocket)
2. Add the event: `im.message.receive_v1`
⚠️ If the gateway is not running, the long-connection setup may fail to save.
![Configure event subscription](../images/feishu-step6-event-subscription.png)
### 7. Publish the app
1. Create a version in **Version Management & Release**
2. Submit for review and publish
3. Wait for admin approval (enterprise apps usually auto-approve)
---
## Step 2: Configure OpenClaw
### Configure with the wizard (recommended)
```bash
openclaw channels add
```
Choose **Feishu** and paste your App ID + App Secret.
### Configure via config file
Edit `~/.openclaw/openclaw.json`:
```json5
{
channels: {
feishu: {
enabled: true,
dmPolicy: "pairing",
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "My AI assistant",
},
},
},
},
}
```
### Configure via environment variables
```bash
export FEISHU_APP_ID="cli_xxx"
export FEISHU_APP_SECRET="xxx"
```
### Lark (global) domain
If your tenant is on Lark (international), set the domain to `lark` (or a full domain string). You can set it at `channels.feishu.domain` or per account (`channels.feishu.accounts.<id>.domain`).
```json5
{
channels: {
feishu: {
domain: "lark",
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
},
},
},
},
}
```
---
## Step 3: Start + test
### 1. Start the gateway
```bash
openclaw gateway
```
### 2. Send a test message
In Feishu, find your bot and send a message.
### 3. Approve pairing
By default, the bot replies with a pairing code. Approve it:
```bash
openclaw pairing approve feishu <CODE>
```
After approval, you can chat normally.
---
## Overview
- **Feishu bot channel**: Feishu bot managed by the gateway
- **Deterministic routing**: replies always return to Feishu
- **Session isolation**: DMs share a main session; groups are isolated
- **WebSocket connection**: long connection via Feishu SDK, no public URL needed
---
## Access control
### Direct messages
- **Default**: `dmPolicy: "pairing"` (unknown users get a pairing code)
- **Approve pairing**:
```bash
openclaw pairing list feishu
openclaw pairing approve feishu <CODE>
```
- **Allowlist mode**: set `channels.feishu.allowFrom` with allowed Open IDs
### Group chats
**1. Group policy** (`channels.feishu.groupPolicy`):
- `"open"` = allow everyone in groups (default)
- `"allowlist"` = only allow `groupAllowFrom`
- `"disabled"` = disable group messages
**2. Mention requirement** (`channels.feishu.groups.<chat_id>.requireMention`):
- `true` = require @mention (default)
- `false` = respond without mentions
---
## Group configuration examples
### Allow all groups, require @mention (default)
```json5
{
channels: {
feishu: {
groupPolicy: "open",
// Default requireMention: true
},
},
}
```
### Allow all groups, no @mention required
```json5
{
channels: {
feishu: {
groups: {
oc_xxx: { requireMention: false },
},
},
},
}
```
### Allow specific users in groups only
```json5
{
channels: {
feishu: {
groupPolicy: "allowlist",
groupAllowFrom: ["ou_xxx", "ou_yyy"],
},
},
}
```
---
## Get group/user IDs
### Group IDs (chat_id)
Group IDs look like `oc_xxx`.
**Method 1 (recommended)**
1. Start the gateway and @mention the bot in the group
2. Run `openclaw logs --follow` and look for `chat_id`
**Method 2**
Use the Feishu API debugger to list group chats.
### User IDs (open_id)
User IDs look like `ou_xxx`.
**Method 1 (recommended)**
1. Start the gateway and DM the bot
2. Run `openclaw logs --follow` and look for `open_id`
**Method 2**
Check pairing requests for user Open IDs:
```bash
openclaw pairing list feishu
```
---
## Common commands
| Command | Description |
| --------- | ----------------- |
| `/status` | Show bot status |
| `/reset` | Reset the session |
| `/model` | Show/switch model |
> Note: Feishu does not support native command menus yet, so commands must be sent as text.
## Gateway management commands
| Command | Description |
| -------------------------- | ----------------------------- |
| `openclaw gateway status` | Show gateway status |
| `openclaw gateway install` | Install/start gateway service |
| `openclaw gateway stop` | Stop gateway service |
| `openclaw gateway restart` | Restart gateway service |
| `openclaw logs --follow` | Tail gateway logs |
---
## Troubleshooting
### Bot does not respond in group chats
1. Ensure the bot is added to the group
2. Ensure you @mention the bot (default behavior)
3. Check `groupPolicy` is not set to `"disabled"`
4. Check logs: `openclaw logs --follow`
### Bot does not receive messages
1. Ensure the app is published and approved
2. Ensure event subscription includes `im.message.receive_v1`
3. Ensure **long connection** is enabled
4. Ensure app permissions are complete
5. Ensure the gateway is running: `openclaw gateway status`
6. Check logs: `openclaw logs --follow`
### App Secret leak
1. Reset the App Secret in Feishu Open Platform
2. Update the App Secret in your config
3. Restart the gateway
### Message send failures
1. Ensure the app has `im:message:send_as_bot` permission
2. Ensure the app is published
3. Check logs for detailed errors
---
## Advanced configuration
### Multiple accounts
```json5
{
channels: {
feishu: {
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "Primary bot",
},
backup: {
appId: "cli_yyy",
appSecret: "yyy",
botName: "Backup bot",
enabled: false,
},
},
},
},
}
```
### Message limits
- `textChunkLimit`: outbound text chunk size (default: 2000 chars)
- `mediaMaxMb`: media upload/download limit (default: 30MB)
### Streaming
Feishu supports streaming replies via interactive cards. When enabled, the bot updates a card as it generates text.
```json5
{
channels: {
feishu: {
streaming: true, // enable streaming card output (default true)
blockStreaming: true, // enable block-level streaming (default true)
},
},
}
```
Set `streaming: false` to wait for the full reply before sending.
### Multi-agent routing
Use `bindings` to route Feishu DMs or groups to different agents.
```json5
{
agents: {
list: [
{ id: "main" },
{
id: "clawd-fan",
workspace: "/home/user/clawd-fan",
agentDir: "/home/user/.openclaw/agents/clawd-fan/agent",
},
{
id: "clawd-xi",
workspace: "/home/user/clawd-xi",
agentDir: "/home/user/.openclaw/agents/clawd-xi/agent",
},
],
},
bindings: [
{
agentId: "main",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_xxx" },
},
},
{
agentId: "clawd-fan",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_yyy" },
},
},
{
agentId: "clawd-xi",
match: {
channel: "feishu",
peer: { kind: "group", id: "oc_zzz" },
},
},
],
}
```
Routing fields:
- `match.channel`: `"feishu"`
- `match.peer.kind`: `"dm"` or `"group"`
- `match.peer.id`: user Open ID (`ou_xxx`) or group ID (`oc_xxx`)
See [Get group/user IDs](#get-groupuser-ids) for lookup tips.
---
## Configuration reference
Full configuration: [Gateway configuration](/gateway/configuration)
Key options:
| Setting | Description | Default |
| ------------------------------------------------- | ------------------------------- | --------- |
| `channels.feishu.enabled` | Enable/disable channel | `true` |
| `channels.feishu.domain` | API domain (`feishu` or `lark`) | `feishu` |
| `channels.feishu.accounts.<id>.appId` | App ID | - |
| `channels.feishu.accounts.<id>.appSecret` | App Secret | - |
| `channels.feishu.accounts.<id>.domain` | Per-account API domain override | `feishu` |
| `channels.feishu.dmPolicy` | DM policy | `pairing` |
| `channels.feishu.allowFrom` | DM allowlist (open_id list) | - |
| `channels.feishu.groupPolicy` | Group policy | `open` |
| `channels.feishu.groupAllowFrom` | Group allowlist | - |
| `channels.feishu.groups.<chat_id>.requireMention` | Require @mention | `true` |
| `channels.feishu.groups.<chat_id>.enabled` | Enable group | `true` |
| `channels.feishu.textChunkLimit` | Message chunk size | `2000` |
| `channels.feishu.mediaMaxMb` | Media size limit | `30` |
| `channels.feishu.streaming` | Enable streaming card output | `true` |
| `channels.feishu.blockStreaming` | Enable block streaming | `true` |
---
## dmPolicy reference
| Value | Behavior |
| ------------- | --------------------------------------------------------------- |
| `"pairing"` | **Default.** Unknown users get a pairing code; must be approved |
| `"allowlist"` | Only users in `allowFrom` can chat |
| `"open"` | Allow all users (requires `"*"` in allowFrom) |
| `"disabled"` | Disable DMs |
---
## Supported message types
### Receive
- ✅ Text
- ✅ Rich text (post)
- ✅ Images
- ✅ Files
- ✅ Audio
- ✅ Video
- ✅ Stickers
### Send
- ✅ Text
- ✅ Images
- ✅ Files
- ✅ Audio
- ⚠️ Rich text (partial support)

View File

@@ -101,6 +101,7 @@ Use Tailscale Serve for the private dashboard and Funnel for the public webhook
If prompted, visit the authorization URL shown in the output to enable Funnel for this node in your tailnet policy.
5. **Verify the configuration:**
```bash
tailscale serve status
tailscale funnel status
@@ -225,6 +226,7 @@ This means the webhook handler isn't registered. Common causes:
If it shows "disabled", add `plugins.entries.googlechat.enabled: true` to your config.
3. **Gateway not restarted**: After adding config, restart the gateway:
```bash
openclaw gateway restart
```

View File

@@ -1,14 +1,18 @@
---
summary: "iMessage support via imsg (JSON-RPC over stdio), setup, and chat_id routing"
summary: "Legacy iMessage support via imsg (JSON-RPC over stdio). New setups should use BlueBubbles."
read_when:
- Setting up iMessage support
- Debugging iMessage send/receive
title: iMessage
---
# iMessage (imsg)
# iMessage (legacy: imsg)
Status: external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio).
> **Recommended:** Use [BlueBubbles](/channels/bluebubbles) for new iMessage setups.
>
> The `imsg` channel is a legacy external-CLI integration and may be removed in a future release.
Status: legacy external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio).
## Quick setup (beginner)
@@ -58,6 +62,28 @@ Disable with:
- Automation permission when sending.
- `channels.imessage.cliPath` can point to any command that proxies stdin/stdout (for example, a wrapper script that SSHes to another Mac and runs `imsg rpc`).
## Troubleshooting macOS Privacy and Security TCC
If sending/receiving fails (for example, `imsg rpc` exits non-zero, times out, or the gateway appears to hang), a common cause is a macOS permission prompt that was never approved.
macOS grants TCC permissions per app/process context. Approve prompts in the same context that runs `imsg` (for example, Terminal/iTerm, a LaunchAgent session, or an SSH-launched process).
Checklist:
- **Full Disk Access**: allow access for the process running OpenClaw (and any shell/SSH wrapper that executes `imsg`). This is required to read the Messages database (`chat.db`).
- **Automation → Messages**: allow the process running OpenClaw (and/or your terminal) to control **Messages.app** for outbound sends.
- **`imsg` CLI health**: verify `imsg` is installed and supports RPC (`imsg rpc --help`).
Tip: If OpenClaw is running headless (LaunchAgent/systemd/SSH) the macOS prompt can be easy to miss. Run a one-time interactive command in a GUI terminal to force the prompt, then retry:
```bash
imsg chats --limit 1
# or
imsg send <handle> "test"
```
Related macOS folder permissions (Desktop/Documents/Downloads): [/platforms/mac/permissions](/platforms/mac/permissions).
## Setup (fast path)
1. Ensure Messages is signed in on this Mac.
@@ -77,7 +103,7 @@ If you want the bot to send from a **separate iMessage identity** (and keep your
6. Set up SSH so `ssh <bot-macos-user>@localhost true` works without a password.
7. Point `channels.imessage.accounts.bot.cliPath` at an SSH wrapper that runs `imsg` as the bot user.
First-run note: sending/receiving may require GUI approvals (Automation + Full Disk Access) in the _bot macOS user_. If `imsg rpc` looks stuck or exits, log into that user (Screen Sharing helps), run a one-time `imsg chats --limit 1` / `imsg send ...`, approve prompts, then retry.
First-run note: sending/receiving may require GUI approvals (Automation + Full Disk Access) in the _bot macOS user_. If `imsg rpc` looks stuck or exits, log into that user (Screen Sharing helps), run a one-time `imsg chats --limit 1` / `imsg send ...`, approve prompts, then retry. See [Troubleshooting macOS Privacy and Security TCC](#troubleshooting-macos-privacy-and-security-tcc).
Example wrapper (`chmod +x`). Replace `<bot-macos-user>` with your actual macOS username:

View File

@@ -17,11 +17,12 @@ Text is supported everywhere; media and reactions vary by channel.
- [Telegram](/channels/telegram) — Bot API via grammY; supports groups.
- [Discord](/channels/discord) — Discord Bot API + Gateway; supports servers, channels, and DMs.
- [Slack](/channels/slack) — Bolt SDK; workspace apps.
- [Feishu](/channels/feishu) — Feishu/Lark bot via WebSocket (plugin, installed separately).
- [Google Chat](/channels/googlechat) — Google Chat API app via HTTP webhook.
- [Mattermost](/channels/mattermost) — Bot API + WebSocket; channels, groups, DMs (plugin, installed separately).
- [Signal](/channels/signal) — signal-cli; privacy-focused.
- [BlueBubbles](/channels/bluebubbles) — **Recommended for iMessage**; uses the BlueBubbles macOS server REST API with full feature support (edit, unsend, effects, reactions, group management — edit currently broken on macOS 26 Tahoe).
- [iMessage](/channels/imessage) — macOS only; native integration via imsg (legacy, consider BlueBubbles for new setups).
- [iMessage (legacy)](/channels/imessage) — Legacy macOS integration via imsg CLI (deprecated, use BlueBubbles for new setups).
- [Microsoft Teams](/channels/msteams) — Bot Framework; enterprise support (plugin, installed separately).
- [LINE](/channels/line) — LINE Messaging API bot (plugin, installed separately).
- [Nextcloud Talk](/channels/nextcloud-talk) — Self-hosted chat via Nextcloud Talk (plugin, installed separately).

View File

@@ -34,7 +34,7 @@ openclaw plugins install ./extensions/line
## Setup
1. Create a LINE Developers account and open the Console:
https://developers.line.biz/console/
[https://developers.line.biz/console/](https://developers.line.biz/console/)
2. Create (or pick) a Provider and add a **Messaging API** channel.
3. Copy the **Channel access token** and **Channel secret** from the channel settings.
4. Enable **Use webhook** in the Messaging API settings.

View File

@@ -74,7 +74,7 @@ Details: [Plugins](/plugin)
- When set, `channels.matrix.userId` should be the full Matrix ID (example: `@bot:example.org`).
5. Restart the gateway (or finish onboarding).
6. Start a DM with the bot or invite it to a room from any Matrix client
(Element, Beeper, etc.; see https://matrix.org/ecosystem/clients/). Beeper requires E2EE,
(Element, Beeper, etc.; see [https://matrix.org/ecosystem/clients/](https://matrix.org/ecosystem/clients/)). Beeper requires E2EE,
so set `channels.matrix.encryption: true` and verify the device.
Minimal config (access token, user ID auto-fetched):
@@ -148,12 +148,12 @@ Once verified, the bot can decrypt messages in encrypted rooms.
- `openclaw pairing list matrix`
- `openclaw pairing approve matrix <CODE>`
- Public DMs: `channels.matrix.dm.policy="open"` plus `channels.matrix.dm.allowFrom=["*"]`.
- `channels.matrix.dm.allowFrom` accepts user IDs or display names. The wizard resolves display names to user IDs when directory search is available.
- `channels.matrix.dm.allowFrom` accepts full Matrix user IDs (example: `@user:server`). The wizard resolves display names to user IDs when directory search finds a single exact match.
## Rooms (groups)
- Default: `channels.matrix.groupPolicy = "allowlist"` (mention-gated). Use `channels.defaults.groupPolicy` to override the default when unset.
- Allowlist rooms with `channels.matrix.groups` (room IDs, aliases, or names):
- Allowlist rooms with `channels.matrix.groups` (room IDs or aliases; names are resolved to IDs when directory search finds a single exact match):
```json5
{
@@ -172,10 +172,10 @@ Once verified, the bot can decrypt messages in encrypted rooms.
- `requireMention: false` enables auto-reply in that room.
- `groups."*"` can set defaults for mention gating across rooms.
- `groupAllowFrom` restricts which senders can trigger the bot in rooms (optional).
- Per-room `users` allowlists can further restrict senders inside a specific room.
- The configure wizard prompts for room allowlists (room IDs, aliases, or names) and resolves names when possible.
- On startup, OpenClaw resolves room/user names in allowlists to IDs and logs the mapping; unresolved entries are kept as typed.
- `groupAllowFrom` restricts which senders can trigger the bot in rooms (full Matrix user IDs).
- Per-room `users` allowlists can further restrict senders inside a specific room (use full Matrix user IDs).
- The configure wizard prompts for room allowlists (room IDs, aliases, or names) and resolves names only on an exact, unique match.
- On startup, OpenClaw resolves room/user names in allowlists to IDs and logs the mapping; unresolved entries are ignored for allowlist matching.
- Invites are auto-joined by default; control with `channels.matrix.autoJoin` and `channels.matrix.autoJoinAllowlist`.
- To allow **no rooms**, set `channels.matrix.groupPolicy: "disabled"` (or keep an empty allowlist).
- Legacy key: `channels.matrix.rooms` (same shape as `groups`).
@@ -220,9 +220,9 @@ Provider options:
- `channels.matrix.textChunkLimit`: outbound text chunk size (chars).
- `channels.matrix.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking.
- `channels.matrix.dm.policy`: `pairing | allowlist | open | disabled` (default: pairing).
- `channels.matrix.dm.allowFrom`: DM allowlist (user IDs or display names). `open` requires `"*"`. The wizard resolves names to IDs when possible.
- `channels.matrix.dm.allowFrom`: DM allowlist (full Matrix user IDs). `open` requires `"*"`. The wizard resolves names to IDs when possible.
- `channels.matrix.groupPolicy`: `allowlist | open | disabled` (default: allowlist).
- `channels.matrix.groupAllowFrom`: allowlisted senders for group messages.
- `channels.matrix.groupAllowFrom`: allowlisted senders for group messages (full Matrix user IDs).
- `channels.matrix.allowlistOnly`: force allowlist rules for DMs + rooms.
- `channels.matrix.groups`: group allowlist + per-room settings map.
- `channels.matrix.rooms`: legacy group allowlist/config.

View File

@@ -558,6 +558,7 @@ Bots don't have a personal OneDrive drive (the `/me/drive` Graph API endpoint do
```
4. **Configure OpenClaw:**
```json5
{
channels: {
@@ -747,7 +748,7 @@ Bots have limited support in private channels:
- **"Icon file cannot be empty":** The manifest references icon files that are 0 bytes. Create valid PNG icons (32x32 for `outline.png`, 192x192 for `color.png`).
- **"webApplicationInfo.Id already in use":** The app is still installed in another team/chat. Find and uninstall it first, or wait 5-10 minutes for propagation.
- **"Something went wrong" on upload:** Upload via https://admin.teams.microsoft.com instead, open browser DevTools (F12) → Network tab, and check the response body for the actual error.
- **"Something went wrong" on upload:** Upload via [https://admin.teams.microsoft.com](https://admin.teams.microsoft.com) instead, open browser DevTools (F12) → Network tab, and check the response body for the actual error.
- **Sideload failing:** Try "Upload an app to your org's app catalog" instead of "Upload a custom app" - this often bypasses sideload restrictions.
### RSC permissions not working

View File

@@ -34,9 +34,11 @@ Details: [Plugins](/plugin)
1. Install the Nextcloud Talk plugin.
2. On your Nextcloud server, create a bot:
```bash
./occ talk:bot:install "OpenClaw" "<shared-secret>" "<webhook-url>" --feature reaction
```
3. Enable the bot in the target room settings.
4. Configure OpenClaw:
- Config: `channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret`
@@ -72,6 +74,7 @@ Minimal config:
- `openclaw pairing list nextcloud-talk`
- `openclaw pairing approve nextcloud-talk <CODE>`
- Public DMs: `channels.nextcloud-talk.dmPolicy="open"` plus `channels.nextcloud-talk.allowFrom=["*"]`.
- `allowFrom` matches Nextcloud user IDs only; display names are ignored.
## Rooms (groups)

View File

@@ -30,7 +30,7 @@ Minimal config:
### Setup
1. Create a Slack app (From scratch) in https://api.slack.com/apps.
1. Create a Slack app (From scratch) in [https://api.slack.com/apps](https://api.slack.com/apps).
2. **Socket Mode** → toggle on. Then go to **Basic Information****App-Level Tokens****Generate Token and Scopes** with scope `connections:write`. Copy the **App Token** (`xapp-...`).
3. **OAuth & Permissions** → add bot token scopes (use the manifest below). Click **Install to Workspace**. Copy the **Bot User OAuth Token** (`xoxb-...`).
4. Optional: **OAuth & Permissions** → add **User Token Scopes** (see the read-only list below). Reinstall the app and copy the **User OAuth Token** (`xoxp-...`).
@@ -49,7 +49,7 @@ Use the manifest below so scopes and events stay in sync.
Multi-account support: use `channels.slack.accounts` with per-account tokens and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern.
### OpenClaw config (minimal)
### OpenClaw config (Socket mode)
Set tokens via env vars (recommended):
@@ -130,7 +130,7 @@ Example with userTokenReadOnly explicitly set (allow user token writes):
Use HTTP webhook mode when your Gateway is reachable by Slack over HTTPS (typical for server deployments).
HTTP mode uses the Events API + Interactivity + Slash Commands with a shared request URL.
### Setup
### Setup (HTTP mode)
1. Create a Slack app and **disable Socket Mode** (optional if you only use HTTP).
2. **Basic Information** → copy the **Signing Secret**.
@@ -260,30 +260,30 @@ If you enable native commands, add one `slash_commands` entry per command you wa
Slack's Conversations API is type-scoped: you only need the scopes for the
conversation types you actually touch (channels, groups, im, mpim). See
https://docs.slack.dev/apis/web-api/using-the-conversations-api/ for the overview.
[https://docs.slack.dev/apis/web-api/using-the-conversations-api/](https://docs.slack.dev/apis/web-api/using-the-conversations-api/) for the overview.
### Bot token scopes (required)
- `chat:write` (send/update/delete messages via `chat.postMessage`)
https://docs.slack.dev/reference/methods/chat.postMessage
[https://docs.slack.dev/reference/methods/chat.postMessage](https://docs.slack.dev/reference/methods/chat.postMessage)
- `im:write` (open DMs via `conversations.open` for user DMs)
https://docs.slack.dev/reference/methods/conversations.open
[https://docs.slack.dev/reference/methods/conversations.open](https://docs.slack.dev/reference/methods/conversations.open)
- `channels:history`, `groups:history`, `im:history`, `mpim:history`
https://docs.slack.dev/reference/methods/conversations.history
[https://docs.slack.dev/reference/methods/conversations.history](https://docs.slack.dev/reference/methods/conversations.history)
- `channels:read`, `groups:read`, `im:read`, `mpim:read`
https://docs.slack.dev/reference/methods/conversations.info
[https://docs.slack.dev/reference/methods/conversations.info](https://docs.slack.dev/reference/methods/conversations.info)
- `users:read` (user lookup)
https://docs.slack.dev/reference/methods/users.info
[https://docs.slack.dev/reference/methods/users.info](https://docs.slack.dev/reference/methods/users.info)
- `reactions:read`, `reactions:write` (`reactions.get` / `reactions.add`)
https://docs.slack.dev/reference/methods/reactions.get
https://docs.slack.dev/reference/methods/reactions.add
[https://docs.slack.dev/reference/methods/reactions.get](https://docs.slack.dev/reference/methods/reactions.get)
[https://docs.slack.dev/reference/methods/reactions.add](https://docs.slack.dev/reference/methods/reactions.add)
- `pins:read`, `pins:write` (`pins.list` / `pins.add` / `pins.remove`)
https://docs.slack.dev/reference/scopes/pins.read
https://docs.slack.dev/reference/scopes/pins.write
[https://docs.slack.dev/reference/scopes/pins.read](https://docs.slack.dev/reference/scopes/pins.read)
[https://docs.slack.dev/reference/scopes/pins.write](https://docs.slack.dev/reference/scopes/pins.write)
- `emoji:read` (`emoji.list`)
https://docs.slack.dev/reference/scopes/emoji.read
[https://docs.slack.dev/reference/scopes/emoji.read](https://docs.slack.dev/reference/scopes/emoji.read)
- `files:write` (uploads via `files.uploadV2`)
https://docs.slack.dev/messaging/working-with-files/#upload
[https://docs.slack.dev/messaging/working-with-files/#upload](https://docs.slack.dev/messaging/working-with-files/#upload)
### User token scopes (optional, read-only by default)
@@ -302,9 +302,9 @@ Add these under **User Token Scopes** if you configure `channels.slack.userToken
- `mpim:write` (only if we add group-DM open/DM start via `conversations.open`)
- `groups:write` (only if we add private-channel management: create/rename/invite/archive)
- `chat:write.public` (only if we want to post to channels the bot isn't in)
https://docs.slack.dev/reference/scopes/chat.write.public
[https://docs.slack.dev/reference/scopes/chat.write.public](https://docs.slack.dev/reference/scopes/chat.write.public)
- `users:read.email` (only if we need email fields from `users.info`)
https://docs.slack.dev/changelog/2017-04-narrowing-email-access
[https://docs.slack.dev/changelog/2017-04-narrowing-email-access](https://docs.slack.dev/changelog/2017-04-narrowing-email-access)
- `files:read` (only if we start listing/reading file metadata)
## Config

View File

@@ -147,7 +147,7 @@ You can add custom commands to the menu via config:
}
```
## Troubleshooting
## Setup troubleshooting (commands)
- `setMyCommands failed` in logs usually means outbound HTTPS/DNS is blocked to `api.telegram.org`.
- If you see `sendMessage` or `sendChatAction` failures, check IPv6 routing and DNS.
@@ -365,6 +365,7 @@ Alternate (official Bot API):
1. DM your bot.
2. Fetch updates with your bot token and read `message.from.id`:
```bash
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
```
@@ -392,6 +393,23 @@ Two independent controls:
Most users want: `groupPolicy: "allowlist"` + `groupAllowFrom` + specific groups listed in `channels.telegram.groups`
To allow **any group member** to talk in a specific group (while still keeping control commands restricted to authorized senders), set a per-group override:
```json5
{
channels: {
telegram: {
groups: {
"-1001234567890": {
groupPolicy: "open",
requireMention: false,
},
},
},
},
}
```
## Long-polling vs webhook
- Default: long-polling (no public URL required).
@@ -714,12 +732,14 @@ Provider options:
- `channels.telegram.groupPolicy`: `open | allowlist | disabled` (default: allowlist).
- `channels.telegram.groupAllowFrom`: group sender allowlist (ids/usernames).
- `channels.telegram.groups`: per-group defaults + allowlist (use `"*"` for global defaults).
- `channels.telegram.groups.<id>.groupPolicy`: per-group override for groupPolicy (`open | allowlist | disabled`).
- `channels.telegram.groups.<id>.requireMention`: mention gating default.
- `channels.telegram.groups.<id>.skills`: skill filter (omit = all skills, empty = none).
- `channels.telegram.groups.<id>.allowFrom`: per-group sender allowlist override.
- `channels.telegram.groups.<id>.systemPrompt`: extra system prompt for the group.
- `channels.telegram.groups.<id>.enabled`: disable the group when `false`.
- `channels.telegram.groups.<id>.topics.<threadId>.*`: per-topic overrides (same fields as group).
- `channels.telegram.groups.<id>.topics.<threadId>.groupPolicy`: per-topic override for groupPolicy (`open | allowlist | disabled`).
- `channels.telegram.groups.<id>.topics.<threadId>.requireMention`: per-topic mention gating override.
- `channels.telegram.capabilities.inlineButtons`: `off | dm | group | all | allowlist` (default: allowlist).
- `channels.telegram.accounts.<account>.capabilities.inlineButtons`: per-account override.

View File

@@ -1,5 +1,5 @@
---
summary: "Channel-specific troubleshooting shortcuts (Discord/Telegram/WhatsApp)"
summary: "Channel-specific troubleshooting shortcuts (Discord/Telegram/WhatsApp/iMessage)"
read_when:
- A channel connects but messages dont flow
- Investigating channel misconfiguration (intents, permissions, privacy mode)
@@ -22,6 +22,7 @@ openclaw channels status --probe
- Discord: [/channels/discord#troubleshooting](/channels/discord#troubleshooting)
- Telegram: [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting)
- WhatsApp: [/channels/whatsapp#troubleshooting-quick](/channels/whatsapp#troubleshooting-quick)
- iMessage (legacy): [/channels/imessage#troubleshooting-macos-privacy-and-security-tcc](/channels/imessage#troubleshooting-macos-privacy-and-security-tcc)
## Telegram quick fixes

View File

@@ -34,7 +34,7 @@ Details: [Plugins](/plugin)
- Select **Bot Token**
- Verify scopes `chat:read` and `chat:write` are selected
- Copy the **Client ID** and **Access Token**
3. Find your Twitch user ID: https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/
3. Find your Twitch user ID: [https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/](https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/)
4. Configure the token:
- Env: `OPENCLAW_TWITCH_ACCESS_TOKEN=...` (default account only)
- Or config: `channels.twitch.accessToken`
@@ -123,7 +123,7 @@ Prefer `allowFrom` for a hard allowlist. Use `allowedRoles` instead if you want
**Why user IDs?** Usernames can change, allowing impersonation. User IDs are permanent.
Find your Twitch user ID: https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/ (Convert your Twitch username to ID)
Find your Twitch user ID: [https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/](https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/) (Convert your Twitch username to ID)
## Token refresh (optional)

View File

@@ -205,11 +205,13 @@ The wizard uses it to set your **allowlist/owner** so your own DMs are permitted
- `Body` is the current message body with envelope.
- Quoted reply context is **always appended**:
```
[Replying to +1555 id:ABC123]
<quoted text or <media:...>>
[/Replying]
```
- Reply metadata also set:
- `ReplyToId` = stanzaId
- `ReplyToBody` = quoted body or media placeholder

View File

@@ -57,7 +57,7 @@ It is a good fit for support or notifications where you want deterministic routi
### 1) Create a bot token (Zalo Bot Platform)
1. Go to **https://bot.zaloplatforms.com** and sign in.
1. Go to [https://bot.zaloplatforms.com](https://bot.zaloplatforms.com) and sign in.
2. Create a new bot and configure its settings.
3. Copy the bot token (format: `12345689:abc-xyz`).

View File

@@ -16,12 +16,17 @@ Related:
Tip: run `openclaw cron --help` for the full command surface.
Note: isolated `cron add` jobs default to `--announce` delivery. Use `--no-deliver` to keep
output internal. `--deliver` remains as a deprecated alias for `--announce`.
Note: one-shot (`--at`) jobs delete after success by default. Use `--keep-after-run` to keep them.
## Common edits
Update delivery settings without changing the message:
```bash
openclaw cron edit <job-id> --deliver --channel telegram --to "123456789"
openclaw cron edit <job-id> --announce --channel telegram --to "123456789"
```
Disable delivery for an isolated job:
@@ -29,3 +34,9 @@ Disable delivery for an isolated job:
```bash
openclaw cron edit <job-id> --no-deliver
```
Announce to a specific channel:
```bash
openclaw cron edit <job-id> --announce --channel slack --to "channel:C1234567890"
```

View File

@@ -61,6 +61,9 @@ openclaw devices revoke --device <deviceId> --role node
- `--timeout <ms>`: RPC timeout.
- `--json`: JSON output (recommended for scripting).
Note: when you set `--url`, the CLI does not fall back to config or environment credentials.
Pass `--token` or `--password` explicitly. Missing explicit credentials is an error.
## Notes
- Token rotation returns a new token (sensitive). Treat it like a secret.

View File

@@ -78,6 +78,9 @@ Shared options (where supported):
- `--timeout <ms>`: timeout/budget (varies per command).
- `--expect-final`: wait for a “final” response (agent calls).
Note: when you set `--url`, the CLI does not fall back to config or environment credentials.
Pass `--token` or `--password` explicitly. Missing explicit credentials is an error.
### `gateway health`
```bash

View File

@@ -303,7 +303,7 @@ Options:
- `--non-interactive`
- `--mode <local|remote>`
- `--flow <quickstart|advanced|manual>` (manual is an alias for advanced)
- `--auth-choice <setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip>`
- `--auth-choice <setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|moonshot-api-key-cn|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip>`
- `--token-provider <id>` (non-interactive; used with `--auth-choice token`)
- `--token <token>` (non-interactive; used with `--auth-choice token`)
- `--token-profile-id <id>` (non-interactive; default: `<provider>:manual`)
@@ -715,6 +715,8 @@ openclaw logs --no-color
### `gateway <subcommand>`
Gateway CLI helpers (use `--url`, `--token`, `--password`, `--timeout`, `--expect-final` for RPC subcommands).
When you pass `--url`, the CLI does not auto-apply config or environment credentials.
Include `--token` or `--password` explicitly. Missing explicit credentials is an error.
Subcommands:

View File

@@ -14,7 +14,7 @@ Provided by the active memory plugin (default: `memory-core`; set `plugins.slots
Related:
- Memory concept: [Memory](/concepts/memory)
- Plugins: [Plugins](/plugins)
- Plugins: [Plugins](/plugin)
## Examples

View File

@@ -9,9 +9,12 @@ title: "onboard"
Interactive onboarding wizard (local or remote Gateway setup).
Related:
## Related guides
- Wizard guide: [Onboarding](/start/onboarding)
- CLI onboarding hub: [Onboarding Wizard (CLI)](/start/wizard)
- CLI onboarding reference: [CLI Onboarding Reference](/start/wizard-cli-reference)
- CLI automation: [CLI Automation](/start/wizard-cli-automation)
- macOS onboarding: [Onboarding (macOS App)](/start/onboarding)
## Examples
@@ -27,3 +30,14 @@ Flow notes:
- `quickstart`: minimal prompts, auto-generates a gateway token.
- `manual`: full prompts for port/bind/auth (alias of `advanced`).
- Fastest first chat: `openclaw dashboard` (Control UI, no channel setup).
## Common follow-up commands
```bash
openclaw configure
openclaw agents add <name>
```
<Note>
`--json` does not imply non-interactive mode. Use `--non-interactive` for scripts.
</Note>

View File

@@ -22,5 +22,5 @@ openclaw security audit --deep
openclaw security audit --fix
```
The audit warns when multiple DM senders share the main session and recommends `session.dmScope="per-channel-peer"` (or `per-account-channel-peer` for multi-account channels) for shared inboxes.
The audit warns when multiple DM senders share the main session and recommends **secure DM mode**: `session.dmScope="per-channel-peer"` (or `per-account-channel-peer` for multi-account channels) for shared inboxes.
It also warns when small models (`<=300B`) are used without sandboxing and with web/browser tools enabled.

View File

@@ -110,9 +110,11 @@ Details: [Gateway protocol](/gateway/protocol), [Pairing](/start/pairing),
- Preferred: Tailscale or VPN.
- Alternative: SSH tunnel
```bash
ssh -N -L 18789:127.0.0.1:18789 user@host
```
- The same handshake + auth token apply over the tunnel.
- TLS + optional pinning can be enabled for WS in remote setups.

53
docs/concepts/features.md Normal file
View File

@@ -0,0 +1,53 @@
---
summary: "OpenClaw capabilities across channels, routing, media, and UX."
read_when:
- You want a full list of what OpenClaw supports
title: "Features"
---
## Highlights
<Columns>
<Card title="Channels" icon="message-square">
WhatsApp, Telegram, Discord, and iMessage with a single Gateway.
</Card>
<Card title="Plugins" icon="plug">
Add Mattermost and more with extensions.
</Card>
<Card title="Routing" icon="route">
Multi-agent routing with isolated sessions.
</Card>
<Card title="Media" icon="image">
Images, audio, and documents in and out.
</Card>
<Card title="Apps and UI" icon="monitor">
Web Control UI and macOS companion app.
</Card>
<Card title="Mobile nodes" icon="smartphone">
iOS and Android nodes with Canvas support.
</Card>
</Columns>
## Full list
- WhatsApp integration via WhatsApp Web (Baileys)
- Telegram bot support (grammY)
- Discord bot support (channels.discord.js)
- Mattermost bot support (plugin)
- iMessage integration via local imsg CLI (macOS)
- Agent bridge for Pi in RPC mode with tool streaming
- Streaming and chunking for long responses
- Multi-agent routing for isolated sessions per workspace or sender
- Subscription auth for Anthropic and OpenAI via OAuth
- Sessions: direct chats collapse into shared `main`; groups are isolated
- Group chat support with mention based activation
- Media support for images, audio, and documents
- Optional voice note transcription hook
- WebChat and macOS menu bar app
- iOS node with pairing and Canvas surface
- Android node with pairing, Canvas, chat, and camera
<Note>
Legacy Claude, Codex, Gemini, and Opencode paths have been removed. Pi is the only
coding agent path.
</Note>

View File

@@ -39,12 +39,13 @@ otherwise -> reply
![Group message flow](/images/groups-flow.svg)
If you want...
| Goal | What to set |
|------|-------------|
| Allow all groups but only reply on @mentions | `groups: { "*": { requireMention: true } }` |
| Disable all group replies | `groupPolicy: "disabled"` |
| Only specific groups | `groups: { "<group-id>": { ... } }` (no `"*"` key) |
| Only you can trigger in groups | `groupPolicy: "allowlist"`, `groupAllowFrom: ["+1555..."]` |
| Goal | What to set |
| -------------------------------------------- | ---------------------------------------------------------- |
| Allow all groups but only reply on @mentions | `groups: { "*": { requireMention: true } }` |
| Disable all group replies | `groupPolicy: "disabled"` |
| Only specific groups | `groups: { "<group-id>": { ... } }` (no `"*"` key) |
| Only you can trigger in groups | `groupPolicy: "allowlist"`, `groupAllowFrom: ["+1555..."]` |
## Session keys

View File

@@ -3,7 +3,6 @@ summary: "How OpenClaw memory works (workspace files + automatic memory flush)"
read_when:
- You want the memory file layout and workflow
- You want to tune the automatic pre-compaction memory flush
title: "Memory"
---
# Memory
@@ -78,9 +77,8 @@ For the full compaction lifecycle, see
## Vector memory search
OpenClaw can build a small vector index over `MEMORY.md` and `memory/*.md` (plus
any extra directories or files you opt in) so semantic queries can find related
notes even when wording differs.
OpenClaw can build a small vector index over `MEMORY.md` and `memory/*.md` so
semantic queries can find related notes even when wording differs.
Defaults:
@@ -90,7 +88,8 @@ Defaults:
1. `local` if a `memorySearch.local.modelPath` is configured and the file exists.
2. `openai` if an OpenAI key can be resolved.
3. `gemini` if a Gemini key can be resolved.
4. Otherwise memory search stays disabled until configured.
4. `voyage` if a Voyage key can be resolved.
5. Otherwise memory search stays disabled until configured.
- Local mode uses node-llama-cpp and may require `pnpm approve-builds`.
- Uses sqlite-vec (when available) to accelerate vector search inside SQLite.
@@ -98,9 +97,127 @@ Remote embeddings **require** an API key for the embedding provider. OpenClaw
resolves keys from auth profiles, `models.providers.*.apiKey`, or environment
variables. Codex OAuth only covers chat/completions and does **not** satisfy
embeddings for memory search. For Gemini, use `GEMINI_API_KEY` or
`models.providers.google.apiKey`. When using a custom OpenAI-compatible endpoint,
`models.providers.google.apiKey`. For Voyage, use `VOYAGE_API_KEY` or
`models.providers.voyage.apiKey`. When using a custom OpenAI-compatible endpoint,
set `memorySearch.remote.apiKey` (and optional `memorySearch.remote.headers`).
### QMD backend (experimental)
Set `memory.backend = "qmd"` to swap the built-in SQLite indexer for
[QMD](https://github.com/tobi/qmd): a local-first search sidecar that combines
BM25 + vectors + reranking. Markdown stays the source of truth; OpenClaw shells
out to QMD for retrieval. Key points:
**Prereqs**
- Disabled by default. Opt in per-config (`memory.backend = "qmd"`).
- Install the QMD CLI separately (`bun install -g https://github.com/tobi/qmd` or grab
a release) and make sure the `qmd` binary is on the gateways `PATH`.
- QMD needs an SQLite build that allows extensions (`brew install sqlite` on
macOS).
- QMD runs fully locally via Bun + `node-llama-cpp` and auto-downloads GGUF
models from HuggingFace on first use (no separate Ollama daemon required).
- The gateway runs QMD in a self-contained XDG home under
`~/.openclaw/agents/<agentId>/qmd/` by setting `XDG_CONFIG_HOME` and
`XDG_CACHE_HOME`.
- OS support: macOS and Linux work out of the box once Bun + SQLite are
installed. Windows is best supported via WSL2.
**How the sidecar runs**
- The gateway writes a self-contained QMD home under
`~/.openclaw/agents/<agentId>/qmd/` (config + cache + sqlite DB).
- Collections are rewritten from `memory.qmd.paths` (plus default workspace
memory files) into `index.yml`, then `qmd update` + `qmd embed` run on boot and
on a configurable interval (`memory.qmd.update.interval`, default 5m).
- Searches run via `qmd query --json`. If QMD fails or the binary is missing,
OpenClaw automatically falls back to the builtin SQLite manager so memory tools
keep working.
- **First search may be slow**: QMD may download local GGUF models (reranker/query
expansion) on the first `qmd query` run.
- OpenClaw sets `XDG_CONFIG_HOME`/`XDG_CACHE_HOME` automatically when it runs QMD.
- If you want to pre-download models manually (and warm the same index OpenClaw
uses), run a one-off query with the agents XDG dirs.
OpenClaws QMD state lives under your **state dir** (defaults to `~/.openclaw`).
You can point `qmd` at the exact same index by exporting the same XDG vars
OpenClaw uses:
```bash
# Pick the same state dir OpenClaw uses
STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
if [ -d "$HOME/.moltbot" ] && [ ! -d "$HOME/.openclaw" ] \
&& [ -z "${OPENCLAW_STATE_DIR:-}" ]; then
STATE_DIR="$HOME/.moltbot"
fi
export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config"
export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache"
# (Optional) force an index refresh + embeddings
qmd update
qmd embed
# Warm up / trigger first-time model downloads
qmd query "test" -c memory-root --json >/dev/null 2>&1
```
**Config surface (`memory.qmd.*`)**
- `command` (default `qmd`): override the executable path.
- `includeDefaultMemory` (default `true`): auto-index `MEMORY.md` + `memory/**/*.md`.
- `paths[]`: add extra directories/files (`path`, optional `pattern`, optional
stable `name`).
- `sessions`: opt into session JSONL indexing (`enabled`, `retentionDays`,
`exportDir`).
- `update`: controls refresh cadence (`interval`, `debounceMs`, `onBoot`, `embedInterval`).
- `limits`: clamp recall payload (`maxResults`, `maxSnippetChars`,
`maxInjectedChars`, `timeoutMs`).
- `scope`: same schema as [`session.sendPolicy`](/gateway/configuration#session).
Default is DM-only (`deny` all, `allow` direct chats); loosen it to surface QMD
hits in groups/channels.
- Snippets sourced outside the workspace show up as
`qmd/<collection>/<relative-path>` in `memory_search` results; `memory_get`
understands that prefix and reads from the configured QMD collection root.
- When `memory.qmd.sessions.enabled = true`, OpenClaw exports sanitized session
transcripts (User/Assistant turns) into a dedicated QMD collection under
`~/.openclaw/agents/<id>/qmd/sessions/`, so `memory_search` can recall recent
conversations without touching the builtin SQLite index.
- `memory_search` snippets now include a `Source: <path#line>` footer when
`memory.citations` is `auto`/`on`; set `memory.citations = "off"` to keep
the path metadata internal (the agent still receives the path for
`memory_get`, but the snippet text omits the footer and the system prompt
warns the agent not to cite it).
**Example**
```json5
memory: {
backend: "qmd",
citations: "auto",
qmd: {
includeDefaultMemory: true,
update: { interval: "5m", debounceMs: 15000 },
limits: { maxResults: 6, timeoutMs: 4000 },
scope: {
default: "deny",
rules: [{ action: "allow", match: { chatType: "direct" } }]
},
paths: [
{ name: "docs", path: "~/notes", pattern: "**/*.md" }
]
}
}
```
**Citations & fallback**
- `memory.citations` applies regardless of backend (`auto`/`on`/`off`).
- When `qmd` runs, we tag `status().backend = "qmd"` so diagnostics show which
engine served the results. If the QMD subprocess exits or JSON output cant be
parsed, the search manager logs a warning and returns the builtin provider
(existing Markdown embeddings) until QMD recovers.
### Additional memory paths
If you want to index Markdown files outside the default workspace layout, add
@@ -187,8 +304,8 @@ Why OpenAI batch is fast + cheap:
- For large backfills, OpenAI is typically the fastest option we support because we can submit many embedding requests in a single batch job and let OpenAI process them asynchronously.
- OpenAI offers discounted pricing for Batch API workloads, so large indexing runs are usually cheaper than sending the same requests synchronously.
- See the OpenAI Batch API docs and pricing for details:
- https://platform.openai.com/docs/api-reference/batch
- https://platform.openai.com/pricing
- [https://platform.openai.com/docs/api-reference/batch](https://platform.openai.com/docs/api-reference/batch)
- [https://platform.openai.com/pricing](https://platform.openai.com/pricing)
Config example:
@@ -222,14 +339,14 @@ Local mode:
### How the memory tools work
- `memory_search` semantically searches Markdown chunks (~400 token target, 80-token overlap) from `MEMORY.md` + `memory/**/*.md`. It returns snippet text (capped ~700 chars), file path, line range, score, provider/model, and whether we fell back from local → remote embeddings. No full file payload is returned.
- `memory_get` reads a specific memory Markdown file (workspace-relative), optionally from a starting line and for N lines. Paths outside `MEMORY.md` / `memory/` are allowed only when explicitly listed in `memorySearch.extraPaths`.
- `memory_get` reads a specific memory Markdown file (workspace-relative), optionally from a starting line and for N lines. Paths outside `MEMORY.md` / `memory/` are rejected.
- Both tools are enabled only when `memorySearch.enabled` resolves true for the agent.
### What gets indexed (and when)
- File type: Markdown only (`MEMORY.md`, `memory/**/*.md`, plus any `.md` files under `memorySearch.extraPaths`).
- File type: Markdown only (`MEMORY.md`, `memory/**/*.md`).
- Index storage: per-agent SQLite at `~/.openclaw/memory/<agentId>.sqlite` (configurable via `agents.defaults.memorySearch.store.path`, supports `{agentId}` token).
- Freshness: watcher on `MEMORY.md`, `memory/`, and `memorySearch.extraPaths` marks the index dirty (debounce 1.5s). Sync is scheduled on session start, on search, or on an interval and runs asynchronously. Session transcripts use delta thresholds to trigger background sync.
- Freshness: watcher on `MEMORY.md` + `memory/` marks the index dirty (debounce 1.5s). Sync is scheduled on session start, on search, or on an interval and runs asynchronously. Session transcripts use delta thresholds to trigger background sync.
- Reindex triggers: the index stores the embedding **provider/model + endpoint fingerprint + chunking params**. If any of those change, OpenClaw automatically resets and reindexes the entire store.
### Hybrid search (BM25 + vector)

View File

@@ -148,7 +148,7 @@ Details: [Thinking + reasoning directives](/tools/thinking) and [Token use](/tok
Outbound message formatting is centralized in `messages`:
- `messages.responsePrefix` (outbound prefix) and `channels.whatsapp.messagePrefix` (WhatsApp inbound prefix)
- `messages.responsePrefix`, `channels.<channel>.responsePrefix`, and `channels.<channel>.accounts.<id>.responsePrefix` (outbound prefix cascade), plus `channels.whatsapp.messagePrefix` (WhatsApp inbound prefix)
- Reply threading via `replyToMode` and per-channel defaults
Details: [Configuration](/gateway/configuration#messages) and channel docs.

View File

@@ -13,7 +13,7 @@ For model selection rules, see [/concepts/models](/concepts/models).
## Quick rules
- Model refs use `provider/model` (example: `opencode/claude-opus-4-5`).
- Model refs use `provider/model` (example: `opencode/claude-opus-4-6`).
- If you set `agents.defaults.models`, it becomes the allowlist.
- CLI helpers: `openclaw onboard`, `openclaw models list`, `openclaw models set <provider/model>`.
@@ -26,12 +26,12 @@ OpenClaw ships with the piai catalog. These providers require **no**
- Provider: `openai`
- Auth: `OPENAI_API_KEY`
- Example model: `openai/gpt-5.2`
- Example model: `openai/gpt-5.1-codex`
- CLI: `openclaw onboard --auth-choice openai-api-key`
```json5
{
agents: { defaults: { model: { primary: "openai/gpt-5.2" } } },
agents: { defaults: { model: { primary: "openai/gpt-5.1-codex" } } },
}
```
@@ -39,12 +39,12 @@ OpenClaw ships with the piai catalog. These providers require **no**
- Provider: `anthropic`
- Auth: `ANTHROPIC_API_KEY` or `claude setup-token`
- Example model: `anthropic/claude-opus-4-5`
- Example model: `anthropic/claude-opus-4-6`
- CLI: `openclaw onboard --auth-choice token` (paste setup-token) or `openclaw models auth paste-token --provider anthropic`
```json5
{
agents: { defaults: { model: { primary: "anthropic/claude-opus-4-5" } } },
agents: { defaults: { model: { primary: "anthropic/claude-opus-4-6" } } },
}
```
@@ -52,12 +52,12 @@ OpenClaw ships with the piai catalog. These providers require **no**
- Provider: `openai-codex`
- Auth: OAuth (ChatGPT)
- Example model: `openai-codex/gpt-5.2`
- Example model: `openai-codex/gpt-5.3-codex`
- CLI: `openclaw onboard --auth-choice openai-codex` or `openclaw models auth login --provider openai-codex`
```json5
{
agents: { defaults: { model: { primary: "openai-codex/gpt-5.2" } } },
agents: { defaults: { model: { primary: "openai-codex/gpt-5.3-codex" } } },
}
```
@@ -65,12 +65,12 @@ OpenClaw ships with the piai catalog. These providers require **no**
- Provider: `opencode`
- Auth: `OPENCODE_API_KEY` (or `OPENCODE_ZEN_API_KEY`)
- Example model: `opencode/claude-opus-4-5`
- Example model: `opencode/claude-opus-4-6`
- CLI: `openclaw onboard --auth-choice opencode-zen`
```json5
{
agents: { defaults: { model: { primary: "opencode/claude-opus-4-5" } } },
agents: { defaults: { model: { primary: "opencode/claude-opus-4-6" } } },
}
```
@@ -106,7 +106,7 @@ OpenClaw ships with the piai catalog. These providers require **no**
- Provider: `vercel-ai-gateway`
- Auth: `AI_GATEWAY_API_KEY`
- Example model: `vercel-ai-gateway/anthropic/claude-opus-4.5`
- Example model: `vercel-ai-gateway/anthropic/claude-opus-4.6`
- CLI: `openclaw onboard --auth-choice ai-gateway-api-key`
### Other built-in providers
@@ -136,14 +136,14 @@ Moonshot uses OpenAI-compatible endpoints, so configure it as a custom provider:
Kimi K2 model IDs:
{/_ moonshot-kimi-k2-model-refs:start _/ && null}
{/_moonshot-kimi-k2-model-refs:start_/ && null}
- `moonshot/kimi-k2.5`
- `moonshot/kimi-k2-0905-preview`
- `moonshot/kimi-k2-turbo-preview`
- `moonshot/kimi-k2-thinking`
- `moonshot/kimi-k2-thinking-turbo`
{/_ moonshot-kimi-k2-model-refs:end _/ && null}
{/_moonshot-kimi-k2-model-refs:end_/ && null}
```json5
{
@@ -242,7 +242,7 @@ Ollama is a local LLM runtime that provides an OpenAI-compatible API:
- Provider: `ollama`
- Auth: None required (local server)
- Example model: `ollama/llama3.3`
- Installation: https://ollama.ai
- Installation: [https://ollama.ai](https://ollama.ai)
```bash
# Install Ollama, then pull a model:
@@ -309,7 +309,7 @@ Notes:
```bash
openclaw onboard --auth-choice opencode-zen
openclaw models set opencode/claude-opus-4-5
openclaw models set opencode/claude-opus-4-6
openclaw models list
```

View File

@@ -83,7 +83,7 @@ Example allowlist config:
model: { primary: "anthropic/claude-sonnet-4-5" },
models: {
"anthropic/claude-sonnet-4-5": { alias: "Sonnet" },
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-opus-4-6": { alias: "Opus" },
},
},
}

View File

@@ -221,7 +221,7 @@ Split by channel: route WhatsApp to a fast everyday agent and Telegram to an Opu
id: "opus",
name: "Deep Work",
workspace: "~/.openclaw/workspace-opus",
model: "anthropic/claude-opus-4-5",
model: "anthropic/claude-opus-4-6",
},
],
},
@@ -255,7 +255,7 @@ Keep WhatsApp on the fast agent, but route one DM to Opus:
id: "opus",
name: "Deep Work",
workspace: "~/.openclaw/workspace-opus",
model: "anthropic/claude-opus-4-5",
model: "anthropic/claude-opus-4-6",
},
],
},

View File

@@ -17,6 +17,42 @@ Use `session.dmScope` to control how **direct messages** are grouped:
- `per-account-channel-peer`: isolate by account + channel + sender (recommended for multi-account inboxes).
Use `session.identityLinks` to map provider-prefixed peer ids to a canonical identity so the same person shares a DM session across channels when using `per-peer`, `per-channel-peer`, or `per-account-channel-peer`.
## Secure DM mode (recommended for multi-user setups)
> **Security Warning:** If your agent can receive DMs from **multiple people**, you should strongly consider enabling secure DM mode. Without it, all users share the same conversation context, which can leak private information between users.
**Example of the problem with default settings:**
- Alice (`<SENDER_A>`) messages your agent about a private topic (for example, a medical appointment)
- Bob (`<SENDER_B>`) messages your agent asking "What were we talking about?"
- Because both DMs share the same session, the model may answer Bob using Alice's prior context.
**The fix:** Set `dmScope` to isolate sessions per user:
```json5
// ~/.openclaw/openclaw.json
{
session: {
// Secure DM mode: isolate DM context per channel + sender.
dmScope: "per-channel-peer",
},
}
```
**When to enable this:**
- You have pairing approvals for more than one sender
- You use a DM allowlist with multiple entries
- You set `dmPolicy: "open"`
- Multiple phone numbers or accounts can message your agent
Notes:
- Default is `dmScope: "main"` for continuity (all DMs share the main session). This is fine for single-user setups.
- For multi-account inboxes on the same channel, prefer `per-account-channel-peer`.
- If the same person contacts you on multiple channels, use `session.identityLinks` to collapse their DM sessions into one canonical identity.
- You can verify your DM settings with `openclaw security audit` (see [security](/cli/security)).
## Gateway is the source of truth
All session state is **owned by the gateway** (the “master” OpenClaw). UI clients (macOS app, WebChat, etc.) must query the gateway for session lists and token counts instead of reading local files.

View File

@@ -110,6 +110,6 @@ This keeps the base prompt small while still enabling targeted skill usage.
When available, the system prompt includes a **Documentation** section that points to the
local OpenClaw docs directory (either `docs/` in the repo workspace or the bundled npm
package docs) and also notes the public mirror, source repo, community Discord, and
ClawHub (https://clawhub.com) for skills discovery. The prompt instructs the model to consult local docs first
ClawHub ([https://clawhub.com](https://clawhub.com)) for skills discovery. The prompt instructs the model to consult local docs first
for OpenClaw behavior, commands, configuration, or architecture, and to run
`openclaw status` itself when possible (asking the user only when it lacks access).

View File

@@ -280,7 +280,7 @@ Unknown frame types are preserved as raw payloads for forward compatibility.
Generated JSON Schema is in the repo at `dist/protocol.schema.json`. The
published raw file is typically available at:
- https://raw.githubusercontent.com/openclaw/openclaw/main/dist/protocol.schema.json
- [https://raw.githubusercontent.com/openclaw/openclaw/main/dist/protocol.schema.json](https://raw.githubusercontent.com/openclaw/openclaw/main/dist/protocol.schema.json)
## When you change schemas

View File

@@ -62,19 +62,21 @@ node --import tsx scripts/repro/tsx-name-repro.ts
- Use Bun for dev scripts (current temporary revert).
- Use Node + tsc watch, then run compiled output:
```bash
pnpm exec tsc --watch --preserveWatchOutput
node --watch openclaw.mjs status
```
- Confirmed locally: `pnpm exec tsc -p tsconfig.json` + `node openclaw.mjs status` works on Node 25.
- Disable esbuild keepNames in the TS loader if possible (prevents `__name` helper insertion); tsx does not currently expose this.
- Test Node LTS (22/24) with `tsx` to see if the issue is Node 25specific.
## References
- https://opennext.js.org/cloudflare/howtos/keep_names
- https://esbuild.github.io/api/#keep-names
- https://github.com/evanw/esbuild/issues/1031
- [https://opennext.js.org/cloudflare/howtos/keep_names](https://opennext.js.org/cloudflare/howtos/keep_names)
- [https://esbuild.github.io/api/#keep-names](https://esbuild.github.io/api/#keep-names)
- [https://github.com/evanw/esbuild/issues/1031](https://github.com/evanw/esbuild/issues/1031)
## Next steps

File diff suppressed because it is too large Load Diff

View File

@@ -105,10 +105,13 @@ The Gateway advertises small nonsecret hints to make UI flows convenient:
Useful builtin tools:
- Browse instances:
```bash
dns-sd -B _openclaw-gw._tcp local.
```
- Resolve one instance (replace `<instance>`):
```bash
dns-sd -L "<instance>" _openclaw-gw._tcp local.
```

View File

@@ -25,13 +25,13 @@ want “always works” text responses without relying on external APIs.
You can use Claude Code CLI **without any config** (OpenClaw ships a built-in default):
```bash
openclaw agent --message "hi" --model claude-cli/opus-4.5
openclaw agent --message "hi" --model claude-cli/opus-4.6
```
Codex CLI also works out of the box:
```bash
openclaw agent --message "hi" --model codex-cli/gpt-5.2-codex
openclaw agent --message "hi" --model codex-cli/gpt-5.3-codex
```
If your gateway runs under launchd/systemd and PATH is minimal, add just the
@@ -62,11 +62,12 @@ Add a CLI backend to your fallback list so it only runs when primary models fail
agents: {
defaults: {
model: {
primary: "anthropic/claude-opus-4-5",
fallbacks: ["claude-cli/opus-4.5"],
primary: "anthropic/claude-opus-4-6",
fallbacks: ["claude-cli/opus-4.6", "claude-cli/opus-4.5"],
},
models: {
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-opus-4-6": { alias: "Opus" },
"claude-cli/opus-4.6": {},
"claude-cli/opus-4.5": {},
},
},
@@ -112,6 +113,7 @@ The provider id becomes the left side of your model ref:
input: "arg",
modelArg: "--model",
modelAliases: {
"claude-opus-4-6": "opus",
"claude-opus-4-5": "opus",
"claude-sonnet-4-5": "sonnet",
},

View File

@@ -226,13 +226,13 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
userTimezone: "America/Chicago",
model: {
primary: "anthropic/claude-sonnet-4-5",
fallbacks: ["anthropic/claude-opus-4-5", "openai/gpt-5.2"],
fallbacks: ["anthropic/claude-opus-4-6", "openai/gpt-5.2"],
},
imageModel: {
primary: "openrouter/anthropic/claude-sonnet-4-5",
},
models: {
"anthropic/claude-opus-4-5": { alias: "opus" },
"anthropic/claude-opus-4-6": { alias: "opus" },
"anthropic/claude-sonnet-4-5": { alias: "sonnet" },
"openai/gpt-5.2": { alias: "gpt" },
},
@@ -446,6 +446,32 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
}
```
### Secure DM mode (shared inbox / multi-user DMs)
If more than one person can DM your bot (multiple entries in `allowFrom`, pairing approvals for multiple people, or `dmPolicy: "open"`), enable **secure DM mode** so DMs from different senders dont share one context by default:
```json5
{
// Secure DM mode (recommended for multi-user or sensitive DM agents)
session: { dmScope: "per-channel-peer" },
channels: {
// Example: WhatsApp multi-user inbox
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15555550123", "+15555550124"],
},
// Example: Discord multi-user inbox
discord: {
enabled: true,
token: "YOUR_DISCORD_BOT_TOKEN",
dm: { enabled: true, allowFrom: ["alice", "bob"] },
},
},
}
```
### OAuth with API key failover
```json5
@@ -470,7 +496,7 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
workspace: "~/.openclaw/workspace",
model: {
primary: "anthropic/claude-sonnet-4-5",
fallbacks: ["anthropic/claude-opus-4-5"],
fallbacks: ["anthropic/claude-opus-4-6"],
},
},
}
@@ -508,7 +534,7 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
agent: {
workspace: "~/.openclaw/workspace",
model: {
primary: "anthropic/claude-opus-4-5",
primary: "anthropic/claude-opus-4-6",
fallbacks: ["minimax/MiniMax-M2.1"],
},
},

View File

@@ -1310,13 +1310,14 @@ Thread session isolation:
- `channels.slack.thread.inheritParent` controls whether new thread sessions inherit the parent channel transcript (default: false).
Slack action groups (gate `slack` tool actions):
| Action group | Default | Notes |
| --- | --- | --- |
| reactions | enabled | React + list reactions |
| messages | enabled | Read/send/edit/delete |
| pins | enabled | Pin/unpin/list |
| memberInfo | enabled | Member info |
| emojiList | enabled | Custom emoji list |
| Action group | Default | Notes |
| ------------ | ------- | ---------------------- |
| reactions | enabled | React + list reactions |
| messages | enabled | Read/send/edit/delete |
| pins | enabled | Pin/unpin/list |
| memberInfo | enabled | Member info |
| emojiList | enabled | Custom emoji list |
### `channels.mattermost` (bot token)
@@ -1517,6 +1518,25 @@ See [Messages](/concepts/messages) for queueing, sessions, and streaming context
`responsePrefix` is applied to **all outbound replies** (tool summaries, block
streaming, final replies) across channels unless already present.
Overrides can be configured per channel and per account:
- `channels.<channel>.responsePrefix`
- `channels.<channel>.accounts.<id>.responsePrefix`
Resolution order (most specific wins):
1. `channels.<channel>.accounts.<id>.responsePrefix`
2. `channels.<channel>.responsePrefix`
3. `messages.responsePrefix`
Semantics:
- `undefined` falls through to the next level.
- `""` explicitly disables the prefix and stops the cascade.
- `"auto"` derives `[{identity.name}]` for the routed agent.
Overrides apply to all channels, including extensions, and to every outbound reply kind.
If `messages.responsePrefix` is unset, no prefix is applied by default. WhatsApp self-chat
replies are the exception: they default to `[{identity.name}]` when set, otherwise
`[openclaw]`, so same-phone conversations stay legible.
@@ -1528,8 +1548,8 @@ The `responsePrefix` string can include template variables that resolve dynamica
| Variable | Description | Example |
| ----------------- | ---------------------- | --------------------------- |
| `{model}` | Short model name | `claude-opus-4-5`, `gpt-4o` |
| `{modelFull}` | Full model identifier | `anthropic/claude-opus-4-5` |
| `{model}` | Short model name | `claude-opus-4-6`, `gpt-4o` |
| `{modelFull}` | Full model identifier | `anthropic/claude-opus-4-6` |
| `{provider}` | Provider name | `anthropic`, `openai` |
| `{thinkingLevel}` | Current thinking level | `high`, `low`, `off` |
| `{identity.name}` | Agent identity name | (same as `"auto"` mode) |
@@ -1545,7 +1565,7 @@ Unresolved variables remain as literal text.
}
```
Example output: `[claude-opus-4-5 | think:high] Here's my response...`
Example output: `[claude-opus-4-6 | think:high] Here's my response...`
WhatsApp inbound prefix is configured via `channels.whatsapp.messagePrefix` (deprecated:
`messages.messagePrefix`). Default stays **unchanged**: `"[openclaw]"` when
@@ -1691,7 +1711,7 @@ Z.AI GLM-4.x models automatically enable thinking mode unless you:
OpenClaw also ships a few built-in alias shorthands. Defaults only apply when the model
is already present in `agents.defaults.models`:
- `opus` -> `anthropic/claude-opus-4-5`
- `opus` -> `anthropic/claude-opus-4-6`
- `sonnet` -> `anthropic/claude-sonnet-4-5`
- `gpt` -> `openai/gpt-5.2`
- `gpt-mini` -> `openai/gpt-5-mini`
@@ -1700,18 +1720,18 @@ is already present in `agents.defaults.models`:
If you configure the same alias name (case-insensitive) yourself, your value wins (defaults never override).
Example: Opus 4.5 primary with MiniMax M2.1 fallback (hosted MiniMax):
Example: Opus 4.6 primary with MiniMax M2.1 fallback (hosted MiniMax):
```json5
{
agents: {
defaults: {
models: {
"anthropic/claude-opus-4-5": { alias: "opus" },
"anthropic/claude-opus-4-6": { alias: "opus" },
"minimax/MiniMax-M2.1": { alias: "minimax" },
},
model: {
primary: "anthropic/claude-opus-4-5",
primary: "anthropic/claude-opus-4-6",
fallbacks: ["minimax/MiniMax-M2.1"],
},
},
@@ -1767,7 +1787,7 @@ Example:
agents: {
defaults: {
models: {
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-opus-4-6": { alias: "Opus" },
"anthropic/claude-sonnet-4-1": { alias: "Sonnet" },
"openrouter/deepseek/deepseek-r1:free": {},
"zai/glm-4.7": {
@@ -1781,7 +1801,7 @@ Example:
},
},
model: {
primary: "anthropic/claude-opus-4-5",
primary: "anthropic/claude-opus-4-6",
fallbacks: [
"openrouter/deepseek/deepseek-r1:free",
"openrouter/meta-llama/llama-3.3-70b-instruct:free",
@@ -1958,11 +1978,13 @@ Block streaming:
- `agents.defaults.blockStreamingChunk`: soft chunking for streamed blocks. Defaults to
8001200 chars, prefers paragraph breaks (`\n\n`), then newlines, then sentences.
Example:
```json5
{
agents: { defaults: { blockStreamingChunk: { minChars: 800, maxChars: 1200 } } },
}
```
- `agents.defaults.blockStreamingCoalesce`: merge streamed blocks before sending.
Defaults to `{ idleMs: 1000 }` and inherits `minChars` from `blockStreamingChunk`
with `maxChars` capped to the channel text limit. Signal/Slack/Discord/Google Chat default
@@ -1976,11 +1998,13 @@ Block streaming:
Modes: `off` (default), `natural` (8002500ms), `custom` (use `minMs`/`maxMs`).
Per-agent override: `agents.list[].humanDelay`.
Example:
```json5
{
agents: { defaults: { humanDelay: { mode: "natural" } } },
}
```
See [/concepts/streaming](/concepts/streaming) for behavior + chunking details.
Typing indicators:
@@ -1992,7 +2016,7 @@ Typing indicators:
- `session.typingIntervalSeconds`: per-session override for the refresh interval.
See [/concepts/typing-indicators](/concepts/typing-indicators) for behavior details.
`agents.defaults.model.primary` should be set as `provider/model` (e.g. `anthropic/claude-opus-4-5`).
`agents.defaults.model.primary` should be set as `provider/model` (e.g. `anthropic/claude-opus-4-6`).
Aliases come from `agents.defaults.models.*.alias` (e.g. `Opus`).
If you omit the provider, OpenClaw currently assumes `anthropic` as a temporary
deprecation fallback.
@@ -2039,13 +2063,14 @@ of `every`, keep `HEARTBEAT.md` tiny, and/or choose a cheaper `model`.
- `tools.web.search.cacheTtlMinutes` (default 15)
- `tools.web.fetch.enabled` (default true)
- `tools.web.fetch.maxChars` (default 50000)
- `tools.web.fetch.maxCharsCap` (default 50000; clamps maxChars from config/tool calls)
- `tools.web.fetch.timeoutSeconds` (default 30)
- `tools.web.fetch.cacheTtlMinutes` (default 15)
- `tools.web.fetch.userAgent` (optional override)
- `tools.web.fetch.readability` (default true; disable to use basic HTML cleanup only)
- `tools.web.fetch.firecrawl.enabled` (default true when an API key is set)
- `tools.web.fetch.firecrawl.apiKey` (optional; defaults to `FIRECRAWL_API_KEY`)
- `tools.web.fetch.firecrawl.baseUrl` (default https://api.firecrawl.dev)
- `tools.web.fetch.firecrawl.baseUrl` (default [https://api.firecrawl.dev](https://api.firecrawl.dev))
- `tools.web.fetch.firecrawl.onlyMainContent` (default true)
- `tools.web.fetch.firecrawl.maxAgeMs` (optional)
- `tools.web.fetch.firecrawl.timeoutSeconds` (optional)
@@ -2461,11 +2486,11 @@ Select the model via `agents.defaults.model.primary` (provider/model).
OpenCode Zen is a multi-model gateway with per-model endpoints. OpenClaw uses
the built-in `opencode` provider from pi-ai; set `OPENCODE_API_KEY` (or
`OPENCODE_ZEN_API_KEY`) from https://opencode.ai/auth.
`OPENCODE_ZEN_API_KEY`) from [https://opencode.ai/auth](https://opencode.ai/auth).
Notes:
- Model refs use `opencode/<modelId>` (example: `opencode/claude-opus-4-5`).
- Model refs use `opencode/<modelId>` (example: `opencode/claude-opus-4-6`).
- If you enable an allowlist via `agents.defaults.models`, add each model you plan to use.
- Shortcut: `openclaw onboard --auth-choice opencode-zen`.
@@ -2473,8 +2498,8 @@ Notes:
{
agents: {
defaults: {
model: { primary: "opencode/claude-opus-4-5" },
models: { "opencode/claude-opus-4-5": { alias: "Opus" } },
model: { primary: "opencode/claude-opus-4-6" },
models: { "opencode/claude-opus-4-6": { alias: "Opus" } },
},
},
}
@@ -2551,7 +2576,9 @@ Notes:
- Set `MOONSHOT_API_KEY` in the environment or use `openclaw onboard --auth-choice moonshot-api-key`.
- Model ref: `moonshot/kimi-k2.5`.
- Use `https://api.moonshot.cn/v1` if you need the China endpoint.
- For the China endpoint, either:
- Run `openclaw onboard --auth-choice moonshot-api-key-cn` (wizard will set `https://api.moonshot.cn/v1`), or
- Manually set `baseUrl: "https://api.moonshot.cn/v1"` in `models.providers.moonshot`.
### Kimi Coding
@@ -2630,7 +2657,7 @@ Use MiniMax M2.1 directly without LM Studio:
agent: {
model: { primary: "minimax/MiniMax-M2.1" },
models: {
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-opus-4-6": { alias: "Opus" },
"minimax/MiniMax-M2.1": { alias: "Minimax" },
},
},
@@ -2763,6 +2790,7 @@ Fields:
- `per-peer`: isolate DMs by sender id across channels.
- `per-channel-peer`: isolate DMs per channel + sender (recommended for multi-user inboxes).
- `per-account-channel-peer`: isolate DMs per account + channel + sender (recommended for multi-account inboxes).
- Secure DM mode (recommended): set `session.dmScope: "per-channel-peer"` when multiple people can DM the bot (shared inboxes, multi-person allowlists, or `dmPolicy: "open"`).
- `identityLinks`: map canonical ids to provider-prefixed peers so the same person shares a DM session across channels when using `per-peer`, `per-channel-peer`, or `per-account-channel-peer`.
- Example: `alice: ["telegram:123456789", "discord:987654321012345678"]`.
- `reset`: primary reset policy. Defaults to daily resets at 4:00 AM local time on the gateway host.
@@ -2952,6 +2980,7 @@ Control UI base path:
- `gateway.controlUi.basePath` sets the URL prefix where the Control UI is served.
- Examples: `"/ui"`, `"/openclaw"`, `"/apps/openclaw"`.
- Default: root (`/`) (unchanged).
- `gateway.controlUi.root` sets the filesystem root for Control UI assets (default: `dist/control-ui`).
- `gateway.controlUi.allowInsecureAuth` allows token-only auth for the Control UI when
device identity is omitted (typically over HTTP). Default: `false`. Prefer HTTPS
(Tailscale Serve) or `127.0.0.1`.
@@ -3149,8 +3178,7 @@ Defaults:
Requests must include the hook token:
- `Authorization: Bearer <token>` **or**
- `x-openclaw-token: <token>` **or**
- `?token=<token>`
- `x-openclaw-token: <token>`
Endpoints:
@@ -3343,7 +3371,7 @@ openclaw dns setup --apply
}
```
## Template variables
## Media model template variables
Template placeholders are expanded in `tools.media.*.models[].args` and `tools.media.models[].args` (and any future templated argument fields).

View File

@@ -83,10 +83,11 @@ and logged; a message that is only `HEARTBEAT_OK` is dropped.
defaults: {
heartbeat: {
every: "30m", // default: 30m (0m disables)
model: "anthropic/claude-opus-4-5",
model: "anthropic/claude-opus-4-6",
includeReasoning: false, // default: false (deliver separate Reasoning: message when available)
target: "last", // last | none | <channel id> (core or plugin, e.g. "bluebubbles")
to: "+15551234567", // optional channel-specific override
accountId: "ops-bot", // optional multi-account channel id
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
ackMaxChars: 300, // max chars allowed after HEARTBEAT_OK
},
@@ -136,6 +137,59 @@ Example: two agents, only the second agent runs heartbeats.
}
```
### Active hours example
Restrict heartbeats to business hours in a specific timezone:
```json5
{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last",
activeHours: {
start: "09:00",
end: "22:00",
timezone: "America/New_York", // optional; uses your userTimezone if set, otherwise host tz
},
},
},
},
}
```
Outside this window (before 9am or after 10pm Eastern), heartbeats are skipped. The next scheduled tick inside the window will run normally.
### Multi account example
Use `accountId` to target a specific account on multi-account channels like Telegram:
```json5
{
agents: {
list: [
{
id: "ops",
heartbeat: {
every: "1h",
target: "telegram",
to: "12345678",
accountId: "ops-bot",
},
},
],
},
channels: {
telegram: {
accounts: {
"ops-bot": { botToken: "YOUR_TELEGRAM_BOT_TOKEN" },
},
},
},
}
```
### Field notes
- `every`: heartbeat interval (duration string; default unit = minutes).
@@ -150,8 +204,14 @@ Example: two agents, only the second agent runs heartbeats.
- explicit channel: `whatsapp` / `telegram` / `discord` / `googlechat` / `slack` / `msteams` / `signal` / `imessage`.
- `none`: run the heartbeat but **do not deliver** externally.
- `to`: optional recipient override (channel-specific id, e.g. E.164 for WhatsApp or a Telegram chat id).
- `accountId`: optional account id for multi-account channels. When `target: "last"`, the account id applies to the resolved last channel if it supports accounts; otherwise it is ignored. If the account id does not match a configured account for the resolved channel, delivery is skipped.
- `prompt`: overrides the default prompt body (not merged).
- `ackMaxChars`: max chars allowed after `HEARTBEAT_OK` before delivery.
- `activeHours`: restricts heartbeat runs to a time window. Object with `start` (HH:MM, inclusive), `end` (HH:MM exclusive; `24:00` allowed for end-of-day), and optional `timezone`.
- Omitted or `"user"`: uses your `agents.defaults.userTimezone` if set, otherwise falls back to the host system timezone.
- `"local"`: always uses the host system timezone.
- Any IANA identifier (e.g. `America/New_York`): used directly; if invalid, falls back to the `"user"` behavior above.
- Outside the active window, heartbeats are skipped until the next tick inside the window.
## Delivery behavior

View File

@@ -49,9 +49,11 @@ pnpm gateway:watch
## Remote access
- Tailscale/VPN preferred; otherwise SSH tunnel:
```bash
ssh -N -L 18789:127.0.0.1:18789 user@host
```
- Clients then connect to `ws://127.0.0.1:18789` through the tunnel.
- If a token is configured, clients must include it in `connect.params.auth.token` even over the tunnel.

View File

@@ -21,7 +21,7 @@ Best current local stack. Load MiniMax M2.1 in LM Studio, enable the local serve
defaults: {
model: { primary: "lmstudio/minimax-m2.1-gs32" },
models: {
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-opus-4-6": { alias: "Opus" },
"lmstudio/minimax-m2.1-gs32": { alias: "Minimax" },
},
},
@@ -52,7 +52,7 @@ Best current local stack. Load MiniMax M2.1 in LM Studio, enable the local serve
**Setup checklist**
- Install LM Studio: https://lmstudio.ai
- Install LM Studio: [https://lmstudio.ai](https://lmstudio.ai)
- In LM Studio, download the **largest MiniMax M2.1 build available** (avoid “small”/heavily quantized variants), start the server, confirm `http://127.0.0.1:1234/v1/models` lists it.
- Keep the model loaded; cold-load adds startup latency.
- Adjust `contextWindow`/`maxTokens` if your LM Studio build differs.
@@ -68,12 +68,12 @@ Keep hosted models configured even when running local; use `models.mode: "merge"
defaults: {
model: {
primary: "anthropic/claude-sonnet-4-5",
fallbacks: ["lmstudio/minimax-m2.1-gs32", "anthropic/claude-opus-4-5"],
fallbacks: ["lmstudio/minimax-m2.1-gs32", "anthropic/claude-opus-4-6"],
},
models: {
"anthropic/claude-sonnet-4-5": { alias: "Sonnet" },
"lmstudio/minimax-m2.1-gs32": { alias: "MiniMax Local" },
"anthropic/claude-opus-4-5": { alias: "Opus" },
"anthropic/claude-opus-4-6": { alias: "Opus" },
},
},
},

View File

@@ -0,0 +1,17 @@
---
summary: "How the Gateway, nodes, and canvas host connect."
read_when:
- You want a concise view of the Gateway networking model
title: "Network model"
---
Most operations flow through the Gateway (`openclaw gateway`), a single long-running
process that owns channel connections and the WebSocket control plane.
## Core rules
- One Gateway per host is recommended. It is the only process allowed to own the WhatsApp Web session. For rescue bots or strict isolation, run multiple gateways with isolated profiles and ports. See [Multiple gateways](/gateway/multiple-gateways).
- Loopback first: the Gateway WS defaults to `ws://127.0.0.1:18789`. The wizard generates a gateway token by default, even for loopback. For tailnet access, run `openclaw gateway --bind tailnet --token ...` because tokens are required for non-loopback binds.
- Nodes connect to the Gateway WS over LAN, tailnet, or SSH as needed. The legacy TCP bridge is deprecated.
- Canvas host is an HTTP file server on `canvasHost.port` (default `18793`) serving `/__openclaw__/canvas/` for node WebViews. See [Gateway configuration](/gateway/configuration) (`canvasHost`).
- Remote use is typically SSH tunnel or tailnet VPN. See [Remote access](/gateway/remote) and [Discovery](/gateway/discovery).

Some files were not shown because too many files have changed in this diff Show More