mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
24 KiB
24 KiB
Repository Guidelines
- Repo: https://github.com/openclaw/openclaw
- In chat replies, file references must be repo-root relative only (example:
extensions/bluebubbles/src/channel.ts:80); never absolute paths or~/.... - GitHub issues/comments/PR comments: use literal multiline strings or
-F - <<'EOF'(or $'...') for real newlines; never embed "\n". - GitHub comment footgun: never use
gh issue/pr comment -b "..."when body contains backticks or shell chars. Always use single-quoted heredoc (-F - <<'EOF') so no command substitution/escaping corruption. - GitHub linking footgun: don’t wrap issue/PR refs like
#24643in backticks when you want auto-linking. Use plain#24643(optionally add full URL). - GitHub searching footgun: don't limit yourself to the first 500 issues or PRs when wanting to search all. Unless you're supposed to look at the most recent, keep going until you've reached the last page in the search
- Security advisory analysis: before triage/severity decisions, read
SECURITY.mdto align with OpenClaw's trust model and design boundaries.
Project Structure & Module Organization
- Source code:
src/(CLI wiring insrc/cli, commands insrc/commands, web provider insrc/provider-web.ts, infra insrc/infra, media pipeline insrc/media). - Tests: colocated
*.test.ts. - Docs:
docs/(images, queue, Pi config). Built output lives indist/. - Plugins/extensions: live under
extensions/*(workspace packages). Keep plugin-only deps in the extensionpackage.json; do not add them to the rootpackage.jsonunless core uses them. - Plugins: install runs
npm install --omit=devin plugin dir; runtime deps must live independencies. Avoidworkspace:*independencies(npm install breaks); putopenclawindevDependenciesorpeerDependenciesinstead (runtime resolvesopenclaw/plugin-sdkvia jiti alias). - Installers served from
https://openclaw.ai/*: live in the sibling repo../openclaw.ai(public/install.sh,public/install-cli.sh,public/install.ps1). - Messaging channels: always consider all built-in + extension channels when refactoring shared logic (routing, allowlists, pairing, command gating, onboarding, docs).
- Core channel docs:
docs/channels/ - Core channel code:
src/telegram,src/discord,src/slack,src/signal,src/imessage,src/web(WhatsApp web),src/channels,src/routing - Extensions (channel plugins):
extensions/*(e.g.extensions/msteams,extensions/matrix,extensions/zalo,extensions/zalouser,extensions/voice-call)
- Core channel docs:
- When adding channels/extensions/apps/docs, update
.github/labeler.ymland create matching GitHub labels (use existing channel/extension label colors).
Docs Linking (Mintlify)
- Docs are hosted on Mintlify (docs.openclaw.ai).
- Internal doc links in
docs/**/*.md: root-relative, no.md/.mdx(example:[Config](/configuration)). - When working with documentation, read the mintlify skill.
- Section cross-references: use anchors on root-relative paths (example:
[Hooks](/configuration#hooks)). - Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links.
- When Peter asks for links, reply with full
https://docs.openclaw.ai/...URLs (not root-relative). - When you touch docs, end the reply with the
https://docs.openclaw.ai/...URLs you referenced. - 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-hostand “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) → runscripts/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 it’s dragging, ping @jospalmbier on Discord instead of hacking around it.
exe.dev VM ops (general)
- Access: stable path is
ssh exe.devthenssh vm-name(assume SSH key already set). - SSH flaky: use exe.dev web terminal or Shelley (web agent); keep a tmux session for long ops.
- Update:
sudo npm i -g openclaw@latest(global install needs root on/usr/lib/node_modules). - Config: use
openclaw config set ...; ensuregateway.mode=localis set. - Discord: store raw token only (no
DISCORD_BOT_TOKEN=prefix). - Restart: stop old gateway and run:
pkill -9 -f openclaw-gateway || true; nohup openclaw gateway run --bind loopback --port 18789 --force > /tmp/openclaw-gateway.log 2>&1 & - Verify:
openclaw channels status --probe,ss -ltnp | rg 18789,tail -n 120 /tmp/openclaw-gateway.log.
Build, Test, and Development Commands
- Runtime baseline: Node 22+ (keep Node + Bun paths working).
- Install deps:
pnpm install - If deps are missing (for example
node_modulesmissing,vitest not found, orcommand not found), run the repo’s package-manager install command (prefer lockfile/README-defined PM), then rerun the exact requested command once. Apply this to test/build/lint/typecheck/dev commands; if retry still fails, report the command and first actionable error. - Pre-commit hooks:
prek install(runs same checks as CI) - Also supported:
bun install(keeppnpm-lock.yaml+ Bun patching in sync when touching deps/patches). - Prefer Bun for TypeScript execution (scripts, dev, tests):
bun <file.ts>/bunx <tool>. - Run CLI in dev:
pnpm openclaw ...(bun) orpnpm dev. - Node remains supported for running built output (
dist/*) and production installs. - Mac packaging (dev):
scripts/package-mac-app.shdefaults to current arch. Release checklist:docs/platforms/mac/release.md. - Type-check/build:
pnpm build - TypeScript checks:
pnpm tsgo - Lint/format:
pnpm check - Format check:
pnpm format(oxfmt --check) - Format fix:
pnpm format:fix(oxfmt --write) - Tests:
pnpm test(vitest); coverage:pnpm test:coverage
Coding Style & Naming Conventions
- Language: TypeScript (ESM). Prefer strict typing; avoid
any. - Formatting/linting via Oxlint and Oxfmt; run
pnpm checkbefore commits. - Never add
@ts-nocheckand do not disableno-explicit-any; fix root causes and update Oxlint/Oxfmt config only when required. - Dynamic import guardrail: do not mix
await import("x")and staticimport ... from "x"for the same module in production code paths. If you need lazy loading, create a dedicated*.runtime.tsboundary (that re-exports fromx) and dynamically import that boundary from lazy callers only. - Dynamic import verification: after refactors that touch lazy-loading/module boundaries, run
pnpm buildand check for[INEFFECTIVE_DYNAMIC_IMPORT]warnings before submitting. - Never share class behavior via prototype mutation (
applyPrototypeMixins,Object.definePropertyon.prototype, or exportingClass.prototypefor merges). Use explicit inheritance/composition (A extends B extends C) or helper composition so TypeScript can typecheck. - If this pattern is needed, stop and get explicit approval before shipping; default behavior is to split/refactor into an explicit class hierarchy and keep members strongly typed.
- In tests, prefer per-instance stubs over prototype mutation (
SomeClass.prototype.method = ...) unless a test explicitly documents why prototype-level patching is required. - Add brief code comments for tricky or non-obvious logic.
- Keep files concise; extract helpers instead of “V2” copies. Use existing patterns for CLI options and dependency injection via
createDefaultDeps. - Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability.
- Naming: use OpenClaw for product/app/docs headings; use
openclawfor CLI command, package/binary, paths, and config keys.
Release Channels (Naming)
- stable: tagged releases only (e.g.
vYYYY.M.D), npm dist-taglatest. - beta: prerelease tags
vYYYY.M.D-beta.N, npm dist-tagbeta(may ship without macOS app). - beta naming: prefer
-beta.N; do not mint new-1/-2betas. LegacyvYYYY.M.D-<patch>andvYYYY.M.D.beta.Nremain recognized. - dev: moving head on
main(no tag; git checkout main).
Testing Guidelines
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
- Naming: match source names with
*.test.ts; e2e in*.e2e.test.ts. - Run
pnpm test(orpnpm test:coverage) before pushing when you touch logic. - Do not set test workers above 16; tried already.
- If local Vitest runs cause memory pressure (common on non-Mac-Studio hosts), use
OPENCLAW_TEST_PROFILE=low OPENCLAW_TEST_SERIAL_GATEWAY=1 pnpm testfor land/gate runs. - Live tests (real keys):
CLAWDBOT_LIVE_TEST=1 pnpm test:live(OpenClaw-only) orLIVE=1 pnpm test:live(includes provider live tests). Docker:pnpm test:docker:live-models,pnpm test:docker:live-gateway. Onboarding Docker E2E:pnpm test:docker:onboard. - Full kit + what’s covered:
docs/testing.md. - Changelog: user-facing changes only; no internal/meta notes (version alignment, appcast reminders, release process).
- Changelog placement: in the active version block, append new entries to the end of the target section (
### Changesor### Fixes); do not insert new entries at the top of a section. - Pure test additions/fixes generally do not need a changelog entry unless they alter user-facing behavior or the user asks for one.
- Mobile: before using a simulator, check for connected real devices (iOS + Android) and prefer them when available.
Commit & Pull Request Guidelines
Full maintainer PR workflow (optional): If you want the repo's end-to-end maintainer workflow (triage order, quality bar, rebase rules, commit/changelog conventions, co-contributor policy, and the review-pr > prepare-pr > merge-pr pipeline), see .agents/skills/PR_WORKFLOW.md. Maintainers may use other workflows; when a maintainer specifies a workflow, follow that. If no workflow is specified, default to PR_WORKFLOW.
- Create commits with
scripts/committer "<msg>" <file...>; avoid manualgit add/git commitso staging stays scoped. - Follow concise, action-oriented commit messages (e.g.,
CLI: add verbose flag to send). - Group related changes; avoid bundling unrelated refactors.
- PR submission template (canonical):
.github/pull_request_template.md - Issue submission templates (canonical):
.github/ISSUE_TEMPLATE/
Shorthand Commands
sync: if working tree is dirty, commit all changes (pick a sensible Conventional Commit message), thengit pull --rebase; if rebase conflicts and cannot resolve, stop; otherwisegit push.
Git Notes
- If
git branch -d/-D <branch>is policy-blocked, delete the local ref directly:git update-ref -d refs/heads/<branch>. - Bulk PR close/reopen safety: if a close action would affect more than 5 PRs, first ask for explicit user confirmation with the exact PR count and target scope/query.
GitHub Search (gh)
- Prefer targeted keyword search before proposing new work or duplicating fixes.
- Use
--repo openclaw/openclaw+--match title,bodyfirst; add--match commentswhen triaging follow-up threads. - PRs:
gh search prs --repo openclaw/openclaw --match title,body --limit 50 -- "auto-update" - Issues:
gh search issues --repo openclaw/openclaw --match title,body --limit 50 -- "auto-update" - Structured output example:
gh search issues --repo openclaw/openclaw --match title,body --limit 50 --json number,title,state,url,updatedAt -- "auto update" --jq '.[] | "\(.number) | \(.state) | \(.title) | \(.url)"'
Security & Configuration Tips
- Web provider stores creds at
~/.openclaw/credentials/; rerunopenclaw loginif logged out. - Pi sessions live under
~/.openclaw/sessions/by default; the base directory is not configurable. - Environment variables: see
~/.profile. - Never commit or publish real phone numbers, videos, or live configuration values. Use obviously fake placeholders in docs, tests, and examples.
- Release flow: always read
docs/reference/RELEASING.mdanddocs/platforms/mac/release.mdbefore any release work; do not ask routine questions once those docs answer them.
GHSA (Repo Advisory) Patch/Publish
- Before reviewing security advisories, read
SECURITY.md. - Fetch:
gh api /repos/openclaw/openclaw/security-advisories/<GHSA> - Latest npm:
npm view openclaw version --userconfig "$(mktemp)" - Private fork PRs must be closed:
fork=$(gh api /repos/openclaw/openclaw/security-advisories/<GHSA> | jq -r .private_fork.full_name)gh pr list -R "$fork" --state open(must be empty) - Description newline footgun: write Markdown via heredoc to
/tmp/ghsa.desc.md(no"\\n"strings) - Build patch JSON via jq:
jq -n --rawfile desc /tmp/ghsa.desc.md '{summary,severity,description:$desc,vulnerabilities:[...]}' > /tmp/ghsa.patch.json - GHSA API footgun: cannot set
severityandcvss_vector_stringin the same PATCH; do separate calls. - Patch + publish:
gh api -X PATCH /repos/openclaw/openclaw/security-advisories/<GHSA> --input /tmp/ghsa.patch.json(publish = include"state":"published"; no/publishendpoint) - If publish fails (HTTP 422): missing
severity/description/vulnerabilities[], or private fork has open PRs - Verify: re-fetch; ensure
state=published,published_atset;jq -r .description | rg '\\\\n'returns nothing
Troubleshooting
- Rebrand/migration issues or legacy config/service warnings: run
openclaw doctor(seedocs/gateway/doctor.md).
Agent-Specific Notes
- Vocabulary: "makeup" = "mac app".
- Never edit
node_modules(global/Homebrew/npm/git installs too). Updates overwrite. Skill notes go intools.mdorAGENTS.md. - When adding a new
AGENTS.mdanywhere in the repo, also add aCLAUDE.mdsymlink pointing to it (example:ln -s AGENTS.md CLAUDE.md). - Signal: "update fly" =>
fly ssh console -a flawd-bot -C "bash -lc 'cd /data/clawd/openclaw && git pull --rebase origin main'"thenfly machines restart e825232f34d058 -a flawd-bot. - When working on a GitHub Issue or PR, print the full URL at the end of the task.
- When answering questions, respond with high-confidence answers only: verify in code; do not guess.
- Never update the Carbon dependency.
- Any dependency with
pnpm.patchedDependenciesmust use an exact version (no^/~). - Patching dependencies (pnpm patches, overrides, or vendored changes) requires explicit approval; do not do this by default.
- CLI progress: use
src/cli/progress.ts(osc-progress+@clack/promptsspinner); don’t hand-roll spinners/bars. - Status output: keep tables + ANSI-safe wrapping (
src/terminal/table.ts);status --all= read-only/pasteable,status --deep= probes. - Gateway currently runs only as the menubar app; there is no separate LaunchAgent/helper label installed. Restart via the OpenClaw Mac app or
scripts/restart-mac.sh; to verify/kill uselaunchctl print gui/$UID | grep openclawrather than assuming a fixed label. When debugging on macOS, start/stop the gateway via the app, not ad-hoc tmux sessions; kill any temporary tunnels before handoff. - macOS logs: use
./scripts/clawlog.shto query unified logs for the OpenClaw subsystem; it supports follow/tail/category filters and expects passwordless sudo for/usr/bin/log. - If shared guardrails are available locally, review them; otherwise follow this repo's guidance.
- SwiftUI state management (iOS/macOS): prefer the
Observationframework (@Observable,@Bindable) overObservableObject/@StateObject; don’t introduce newObservableObjectunless required for compatibility, and migrate existing usages when touching related code. - Connection providers: when adding a new connection, update every UI surface and docs (macOS app, web UI, mobile if applicable, onboarding/overview docs) and add matching status + configuration forms so provider lists and settings stay in sync.
- Version locations:
package.json(CLI),apps/android/app/build.gradle.kts(versionName/versionCode),apps/ios/Sources/Info.plist+apps/ios/Tests/Info.plist(CFBundleShortVersionString/CFBundleVersion),apps/macos/Sources/OpenClaw/Resources/Info.plist(CFBundleShortVersionString/CFBundleVersion),docs/install/updating.md(pinned npm version),docs/platforms/mac/release.md(APP_VERSION/APP_BUILD examples), Peekaboo Xcode projects/Info.plists (MARKETING_VERSION/CURRENT_PROJECT_VERSION). - "Bump version everywhere" means all version locations above except
appcast.xml(only touch appcast when cutting a new macOS Sparkle release). - Restart apps: “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch.
- Device checks: before testing, verify connected real devices (iOS/Android) before reaching for simulators/emulators.
- iOS Team ID lookup:
security find-identity -p codesigning -v→ use Apple Development (…) TEAMID. Fallback:defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers. - A2UI bundle hash:
src/canvas-host/a2ui/.bundle.hashis auto-generated; ignore unexpected changes, and only regenerate viapnpm canvas:a2ui:bundle(orscripts/bundle-a2ui.sh) when needed. Commit the hash as a separate commit. - Release signing/notary keys are managed outside the repo; follow internal release docs.
- Notary auth env vars (
APP_STORE_CONNECT_ISSUER_ID,APP_STORE_CONNECT_KEY_ID,APP_STORE_CONNECT_API_KEY_P8) are expected in your environment (per internal release docs). - Multi-agent safety: do not create/apply/drop
git stashentries unless explicitly requested (this includesgit pull --rebase --autostash). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes. - Multi-agent safety: when the user says "push", you may
git pull --rebaseto integrate latest changes (never discard other agents' work). When the user says "commit", scope to your changes only. When the user says "commit all", commit everything in grouped chunks. - Multi-agent safety: do not create/remove/modify
git worktreecheckouts (or edit.worktrees/*) unless explicitly requested. - Multi-agent safety: do not switch branches / check out a different branch unless explicitly requested.
- Multi-agent safety: running multiple agents is OK as long as each agent has its own session.
- Multi-agent safety: when you see unrecognized files, keep going; focus on your changes and commit only those.
- Lint/format churn:
- If staged+unstaged diffs are formatting-only, auto-resolve without asking.
- If commit/push already requested, auto-stage and include formatting-only follow-ups in the same commit (or a tiny follow-up commit if needed), no extra confirmation.
- Only ask when changes are semantic (logic/data/behavior).
- Lobster seam: use the shared CLI palette in
src/terminal/palette.ts(no hardcoded colors); apply palette to onboarding/config prompts and other TTY UI output as needed. - Multi-agent safety: focus reports on your edits; avoid guard-rail disclaimers unless truly blocked; when multiple agents touch the same file, continue if safe; end with a brief “other files present” note only if relevant.
- Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause.
- Code style: add brief comments for tricky logic; keep files under ~500 LOC when feasible (split/refactor as needed).
- Tool schema guardrails (google-antigravity): avoid
Type.Unionin tool input schemas; noanyOf/oneOf/allOf. UsestringEnum/optionalStringEnum(Type.Unsafe enum) for string lists, andType.Optional(...)instead of... | null. Keep top-level tool schema astype: "object"withproperties. - Tool schema guardrails: avoid raw
formatproperty names in tool schemas; some validators treatformatas a reserved keyword and reject the schema. - When asked to open a “session” file, open the Pi session logs under
~/.openclaw/agents/<agentId>/sessions/*.jsonl(use theagent=<id>value in the Runtime line of the system prompt; newest unless a specific ID is given), not the defaultsessions.json. If logs are needed from another machine, SSH via Tailscale and read the same path there. - Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac.
- Never send streaming/partial replies to external messaging surfaces (WhatsApp, Telegram); only final replies should be delivered there. Streaming/tool events may still go to internal UIs/control channel.
- Voice wake forwarding tips:
- Command template should stay
openclaw-mac agent --message "${text}" --thinking low;VoiceWakeForwarderalready shell-escapes${text}. Don’t add extra quotes. - launchd PATH is minimal; ensure the app’s launch agent PATH includes standard system paths plus your pnpm bin (typically
$HOME/Library/pnpm) sopnpm/openclawbinaries resolve when invoked viaopenclaw-mac.
- Command template should stay
- For manual
openclaw message sendmessages that include!, use the heredoc pattern noted below to avoid the Bash tool’s escaping. - Release guardrails: do not change version numbers without operator’s explicit consent; always ask permission before running any npm publish/release step.
- Beta release guardrail: when using a beta Git tag (for example
vYYYY.M.D-beta.N), publish npm with a matching beta version suffix (for exampleYYYY.M.D-beta.N) rather than a plain version on--tag beta; otherwise the plain version name gets consumed/blocked.
NPM + 1Password (publish/verify)
- Use the 1password skill; all
opcommands must run inside a fresh tmux session. - Sign in:
eval "$(op signin --account my.1password.com)"(app unlocked + integration on). - OTP:
op read 'op://Private/Npmjs/one-time password?attribute=otp'. - Publish:
npm publish --access public --otp="<otp>"(run from the package dir). - Verify without local npmrc side effects:
npm view <pkg> version --userconfig "$(mktemp)". - Kill the tmux session after publish.
Plugin Release Fast Path (no core openclaw publish)
- Release only already-on-npm plugins. Source list is in
docs/reference/RELEASING.mdunder "Current npm plugin list". - Run all CLI
opcalls andnpm publishinside tmux to avoid hangs/interruption:tmux new -d -s release-plugins-$(date +%Y%m%d-%H%M%S)eval "$(op signin --account my.1password.com)"
- 1Password helpers:
- password used by
npm login:op item get Npmjs --format=json | jq -r '.fields[] | select(.id=="password").value' - OTP:
op read 'op://Private/Npmjs/one-time password?attribute=otp'
- password used by
- Fast publish loop (local helper script in
/tmpis fine; keep repo clean):- compare local plugin
versiontonpm view <name> version - only run
npm publish --access public --otp="<otp>"when versions differ - skip if package is missing on npm or version already matches.
- compare local plugin
- Keep
openclawuntouched: never run publish from repo root unless explicitly requested. - Post-check for each release:
- per-plugin:
npm view @openclaw/<name> version --userconfig "$(mktemp)"should be2026.2.17 - core guard:
npm view openclaw version --userconfig "$(mktemp)"should stay at previous version unless explicitly requested.
- per-plugin:
Changelog Release Notes
-
When cutting a mac release with beta GitHub prerelease:
- Tag
vYYYY.M.D-beta.Nfrom the release commit (example:v2026.2.15-beta.1). - Create prerelease with title
openclaw YYYY.M.D-beta.N. - Use release notes from
CHANGELOG.mdversion section (Changes+Fixes, no title duplicate). - Attach at least
OpenClaw-YYYY.M.D.zipandOpenClaw-YYYY.M.D.dSYM.zip; include.dmgif available.
- Tag
-
Keep top version entries in
CHANGELOG.mdsorted by impact:### Changesfirst.### Fixesdeduped and ranked with user-facing fixes first.
-
Before tagging/publishing, run:
node --import tsx scripts/release-check.tspnpm release:checkpnpm test:install:smokeorOPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smokefor non-root smoke path.