mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 20:46:57 +02:00
16 KiB
16 KiB
AGENTS.MD
Telegraph style. Root rules only. Read scoped AGENTS.md before subtree work.
Start
- Repo:
https://github.com/openclaw/openclaw - Replies: repo-root refs only:
extensions/telegram/src/index.ts:80. No absolute paths, no~/. - Run docs list first:
pnpm docs:listif available; read relevant docs only. - High-confidence answers only when fixing/triaging: verify source, tests, shipped/current behavior, and dependency contracts before deciding.
- Dependency-backed behavior: read upstream dependency docs/source/types first. Do not assume APIs, defaults, errors, timing, or runtime behavior.
- Live-verify when feasible. Check env/
~/.profilefor keys before assuming live tests are blocked; keep secret output redacted. - Missing deps:
pnpm install, retry once, then report first actionable error. - CODEOWNERS: maint/refactor/tests ok. Larger behavior/product/security/ownership: owner ask/review.
- Wording: product/docs/UI/changelog say "plugin/plugins";
extensions/is internal. - New channel/plugin/app/doc surface: update
.github/labeler.yml+ GH labels. - New
AGENTS.md: add siblingCLAUDE.mdsymlink.
Map
- Core TS:
src/,ui/,packages/; plugins:extensions/; SDK:src/plugin-sdk/*; channels:src/channels/*; loader:src/plugins/*; protocol:src/gateway/protocol/*; docs/apps:docs/,apps/,Swabble/. - Installers: sibling
../openclaw.ai. - Scoped guides exist in:
extensions/,src/{plugin-sdk,channels,plugins,gateway,gateway/protocol,agents}/,test/helpers*/,docs/,ui/,scripts/.
Architecture
- Core stays extension-agnostic. No bundled ids in core when manifest/registry/capability contracts work.
- Extensions cross into core only via
openclaw/plugin-sdk/*, manifest metadata, injected runtime helpers, documented barrels (api.ts,runtime-api.ts). - Extension prod code: no core
src/**,src/plugin-sdk-internal/**, other extensionsrc/**, or relative outside package. - Core/tests: no deep plugin internals (
extensions/*/src/**,onboard.js). Useapi.ts, SDK facade, generic contracts. - Extension-owned behavior stays extension-owned: repair, detection, onboarding, auth/provider defaults, provider tools/settings.
- Owner boundary: fix owner-specific behavior in the owner module. Shared/core gets generic seams only; no owner ids, dependency strings, defaults, migrations, or recovery policy. If a bug names an extension or its dependency, start in that extension and add a generic core seam only when multiple owners need it.
- Legacy config repair: doctor/fix paths, not startup/load-time core migrations.
- Core test asserting extension-specific behavior: move to owner extension or generic contract test.
- New seams: backwards-compatible, documented, versioned. Third-party plugins exist.
- Channels:
src/channels/**is implementation; plugin authors get SDK seams. - Providers: core owns generic loop; provider plugins own auth/catalog/runtime hooks.
- Gateway protocol changes: additive first; incompatible needs versioning/docs/client follow-through.
- Config contract: exported types, schema/help, metadata, baselines, docs aligned. Retired public keys stay retired; compat in raw migration/doctor.
- Direction: manifest-first control plane; targeted runtime loaders; no hidden contract bypasses; broad mutable registries transitional.
- Prompt cache: deterministic ordering for maps/sets/registries/plugin lists/files/network results before model/tool payloads. Preserve old transcript bytes when possible.
Commands
- Runtime: Node 22+. Keep Node + Bun paths working.
- Install:
pnpm install(keep Bun lock/patches aligned if touched). - CLI:
pnpm openclaw ...orpnpm dev; build:pnpm build. - Smart gate:
pnpm check:changed; explainpnpm changed:lanes --json; staged previewpnpm check:changed --staged. - Sparse worktrees:
pnpm check:changedis sparse-safe and may skip sparse-missing typecheck projects; do not expand sparse checkout just to satisfy changed-gate tsgo. Directpnpm tsgo*remains strict; use a fuller worktree when you need direct typecheck proof. - Prod sweep:
pnpm check; tests:pnpm test,pnpm test:changed,pnpm test:serial,pnpm test:coverage. - Extension tests:
pnpm test:extensions,pnpm test extensions,pnpm test extensions/<id>. - Targeted tests:
pnpm test <path-or-filter> [vitest args...]; never rawvitest. - Typecheck:
tsgolanes only (pnpm tsgo*,pnpm check:test-types); do not addtsc --noEmit,typecheck,check:types. - Formatting: use
oxfmt, not Prettier. Preferpnpm format:check/pnpm format; for targeted files usepnpm exec oxfmt --check --threads=1 <files...>orpnpm exec oxfmt --write --threads=1 <files...>. - Linting: use repo wrappers (
pnpm lint:*,scripts/run-oxlint.mjs); do not invoke generic JS formatters/lints unless a repo script uses them. - Heavy checks:
OPENCLAW_LOCAL_CHECK=1, modeOPENCLAW_LOCAL_CHECK_MODE=throttled|full; CI/shared useOPENCLAW_LOCAL_CHECK=0. - Local first. Use repo
pnpmlanes before Blacksmith/Testbox. Remote only for parity-only failures, secrets/services, or explicit ask.
GitHub / CI
- Triage: list first, hydrate few. Use bounded
gh --json --jq; avoid repeated full comment scans. - Automatic PR/issue discovery: skip maintainer-owned items unless directly relevant. Do not comment, close, label, retitle, rebase, fix up, or land them without Peter asking.
- PR scan/triage: no unsolicited PR comments/reviews. Report in chat only unless explicitly asked, or a close/duplicate action needs a reason comment.
- Search/dedupe: prefer
gh search issues 'repo:openclaw/openclaw is:open <terms>' --json number,title,state,updatedAt --limit 20. - GitHub search boolean text is fussy. If
ORqueries return empty, split exact terms and search title/body/comments separately before concluding no hits. - PR shortlist:
gh pr list ...; thengh pr view <n> --json number,title,body,closingIssuesReferences,files,statusCheckRollup,reviewDecision. - After landing PR: search duplicate open issues/PRs. Before closing: comment why + canonical link.
- GH comments with markdown backticks,
$, or shell snippets: avoid inline double-quoted--body; use single quotes or--body-file. - PR execution artifacts/screenshots: attach them to the PR, comment, or an external artifact store. Do not add
.github/pr-assetsor other PR-only assets to the repo. - PR review answer must explicitly cover: what bug/behavior we are trying to fix; PR/issue URL(s) and affected endpoint/surface; whether this is the best possible fix, with high-certainty evidence from code, tests, CI, and shipped/current behavior.
- CI polling: exact SHA, needed fields only. Example:
gh api repos/<owner>/<repo>/actions/runs/<id> --jq '{status,conclusion,head_sha,updated_at,name,path}'. - Post-land wait: minimal. Exact landed SHA only. If superseded on
main, same-branchcancel-in-progresscancellations are expected; stop once local touched-surface proof exists. Never wait for newer unrelatedmainunless asked. - Wait matrix:
- never:
Auto response,Labeler,Docs Sync Publish Repo,Docs Agent,Test Performance Agent,Stale. - conditional:
CIexact SHA only;Docsonly docs task/no local docs proof;Workflow Sanityonly workflow/composite/CI-policy edits;Plugin NPM Releaseonly plugin package/release metadata. - release/manual only:
Docker Release,OpenClaw NPM Release,macOS Release,OpenClaw Release Checks,Cross-OS Release Checks,NPM Telegram Beta E2E. - explicit/surface only:
QA-Lab - All Lanes,Scheduled Live And E2E,Install Smoke,CodeQL,Sandbox Common Smoke,Parity gate,Blacksmith Testbox,Control UI Locale Refresh.
- never:
/landpr: do not idle onauto-responseorcheck-docs. Treat docs as local proof unlesscheck-docsalready failed with actionable relevant error.- Poll 30-60s. Fetch jobs/logs/artifacts only after failure/completion or concrete need.
Gates
- Pre-commit hook: staged formatting only. Validation explicit.
- Changed lanes:
- core prod: core prod typecheck + core tests
- core tests: core test typecheck/tests
- extension prod: extension prod typecheck + extension tests
- extension tests: extension test typecheck/tests
- public SDK/plugin contract: extension prod/test too
- unknown root/config: all lanes
- Before handoff/push for code/test/runtime/config changes:
pnpm check:changed. Tests-only:pnpm test:changed. Full prod sweep:pnpm check. - Docs/changelog-only and CI/workflow metadata-only changes are not changed-gate work by default. Use
git diff --checkplus the relevant formatter/docs/workflow sanity check; escalate topnpm check:changedonly when scripts, test config, generated docs/API, package metadata, or runtime/build behavior changed. - Rebase sanity: after a green
pnpm check:changed, a clean rebase onto currentorigin/maindoes not require rerunning the full changed gate when the rebase has no conflicts and the branch diff is materially unchanged. Do a quickgit status,git diff --check, and diff/stat sanity check; rerun targeted or full checks only if conflict resolution, upstream overlap, generated drift, dependency/config changes, or touched-file content changes make the prior result stale. - Landing on
main: verify touched surface near landing. Default feasible bar:pnpm check+pnpm test. - Hard build gate:
pnpm buildbefore push if build output, packaging, lazy/module boundaries, or published surfaces can change. - Do not land related failing format/lint/type/build/tests. If unrelated on latest
origin/main, say so with scoped proof. - Generated/API drift:
pnpm check:architecture,pnpm config:docs:gen/check,pnpm plugin-sdk:api:gen/check. Trackdocs/.generated/*.sha256; full JSON ignored.
Code
- TS ESM, strict. Avoid
any; prefer real types,unknown, narrow adapters. - No
@ts-nocheck. Lint suppressions only intentional + explained. - External boundaries: prefer
zodor existing schema helpers. - Runtime branching: discriminated unions/closed codes over freeform strings.
- Avoid semantic sentinels:
?? 0, empty object/string, etc. - Dynamic import: no static+dynamic import for same prod module. Use
*.runtime.tslazy boundary. After edits:pnpm build; check[INEFFECTIVE_DYNAMIC_IMPORT]. - Cycles: keep
pnpm check:import-cycles+ architecture/madge green. - Classes: no prototype mixins/mutations. Prefer inheritance/composition. Tests prefer per-instance stubs.
- Comments: brief, only non-obvious logic.
- Split files around ~700 LOC when clarity/testability improves.
- Naming: OpenClaw product/docs;
openclawCLI/package/path/config. - English: American spelling.
Tests
- Vitest. Colocated
*.test.ts; e2e*.e2e.test.ts; example modelssonnet-4.6,gpt-5.4. - Avoid brittle tests that grep workflow/docs strings for operator policy. Prefer executable behavior, parsed config/schema checks, or live run proof; put release/CI policy reminders in AGENTS/docs instead.
- Clean timers/env/globals/mocks/sockets/temp dirs/module state;
--isolate=falsesafe. - Hot tests: avoid per-test
vi.resetModules()+ heavy imports. Measure withpnpm test:perf:imports <file>/pnpm test:perf:hotspots --limit N. - Seam depth: pure helper/contract unit tests; one integration smoke per boundary.
- Mock expensive seams directly: scanners, manifests, registries, fs crawls, provider SDKs, network/process launch.
- Prefer injection; if module mocking, mock narrow local
*.runtime.ts, not broad barrels oropenclaw/plugin-sdk/*. - Share fixtures/builders; delete duplicate assertions; assert behavior that can regress here.
- Do not edit baseline/inventory/ignore/snapshot/expected-failure files to silence checks without explicit approval.
- Test workers max 16. Memory pressure:
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test. - Live:
OPENCLAW_LIVE_TEST=1 pnpm test:live; verboseOPENCLAW_LIVE_TEST_QUIET=0. - Guide:
docs/help/testing.md.
Docs / Changelog
- Docs change with behavior/API. Use docs list/read_when hints; docs links per
docs/AGENTS.md. - Changelog user-facing only; pure test/internal usually no entry.
- Changelog placement: active version
### Changes/### Fixes; every added entry must include at least oneThanks @authorattribution, using credited GitHub username(s). Never addThanks @steipeteorThanks @codex. - Changelog bullets are always single-line. No wrapping/continuation across multiple lines. Long entries stay on one long line so dedupe, PR-ref, and credit-audit tooling work and so the visual style stays uniform.
Git
- Commit via
scripts/committer "<msg>" <file...>; stage intended files only. It formats staged files; still run gates. - Commits: conventional-ish, concise, grouped.
- No manual stash/autostash unless explicit. No branch/worktree changes unless requested.
main: no merge commits; rebase on latestorigin/mainbefore push. Do not keep chasingmainwith repeated full gates after one green run plus a clean rebase sanity pass.- User says
commit: your changes only.commit all: all changes in grouped chunks.push: maygit pull --rebasefirst. - Do not delete/rename unexpected files; ask if blocking, else ignore.
- Bulk PR close/reopen >5: ask with count/scope.
- PR/issue workflows:
$openclaw-pr-maintainer./landpr:~/.codex/prompts/landpr.md.
Security / Release
- Never commit real phone numbers, videos, credentials, live config.
- Secrets: channel/provider creds in
~/.openclaw/credentials/; model auth profiles in~/.openclaw/agents/<agentId>/agent/auth-profiles.json. - Env keys: check
~/.profile. - Dependency patches/overrides/vendor changes need explicit approval.
pnpm.patchedDependenciesexact versions only. - Carbon pins owner-only: do not change
@buape/carbonunless Shadow (@thewilloftheshadow, verified bygh) asks. - Releases/publish/version bumps need explicit approval. Release docs:
docs/reference/RELEASING.md; use$openclaw-release-maintainer. - GHSA/advisories:
$openclaw-ghsa-maintainer. - Beta tag/version match:
vYYYY.M.D-beta.N-> npmYYYY.M.D-beta.N --tag beta.
Apps / Platform
- Before simulator/emulator testing, check real iOS/Android devices.
- "restart iOS/Android apps" = rebuild/reinstall/relaunch, not kill/launch.
- SwiftUI: Observation (
@Observable,@Bindable) over newObservableObject. - Mac gateway: use app or
openclaw gateway restart/status --deep; no ad-hoc tmux gateway. Logs:./scripts/clawlog.sh. - Version bump touches:
package.json,apps/android/app/build.gradle.kts,apps/ios/version.json+pnpm ios:version:sync, macOSInfo.plist,docs/install/updating.md. Appcast only for Sparkle release. - Mobile LAN pairing: plaintext
ws://loopback-only. Private-networkws://needsOPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1; Tailscale/public usewss://or tunnel. - A2UI hash
src/canvas-host/a2ui/.bundle.hash: generated; ignore unless runningpnpm canvas:a2ui:bundle; commit separately.
Ops / Footguns
- Remote install docs:
docs/install/{exe-dev,fly,hetzner}.md. Parallels smoke:$openclaw-parallels-smoke; Discord roundtrip:parallels-discord-roundtrip. - Rebrand/migration/config warnings: run
openclaw doctor. - Never edit
node_modules. - Local-only
.agentsignores:.git/info/exclude, not repo.gitignore. - CLI progress:
src/cli/progress.ts; status tables:src/terminal/table.ts. - Connection/provider additions: update all UI surfaces + docs + status/config forms.
- Provider tool schemas: prefer flat string enum helpers over
Type.Union([Type.Literal(...)]); some providers rejectanyOf. Not a repo-wide protocol/schema ban. - External messaging: no token-delta channel messages. Follow
docs/concepts/streaming.md; preview/block streaming uses edits/chunks and preserves final/fallback delivery.