mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:10:44 +00:00
12 KiB
12 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. - 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/ - Bundled plugins:
extensions/ - Public SDK:
src/plugin-sdk/* - Channel internals:
src/channels/* - Plugin loader/contracts:
src/plugins/* - Gateway protocol:
src/gateway/protocol/* - Docs:
docs/ - Apps:
apps/,Swabble/ - Installers: sibling
../openclaw.ai
Scoped guides: extensions/, src/plugin-sdk/, src/channels/, src/plugins/, src/gateway/, src/gateway/protocol/, src/agents/, test/helpers/, test/helpers/channels/, 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.
- 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; explain withpnpm changed:lanes --json; staged previewpnpm check:changed --staged. - Prod sweep:
pnpm check(prod type/lint/guards, no tests). - Tests:
pnpm test; changedpnpm test:changed; serialpnpm test:serial; coveragepnpm 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. - Shard timings:
.artifacts/vitest-shard-timings.json; disableOPENCLAW_TEST_PROJECTS_TIMINGS=0. - Format:
pnpm format:check/pnpm format. - Typecheck:
pnpm tsgo,pnpm tsgo:prod,pnpm check:test-types/pnpm tsgo:test,pnpm tsgo:all; profilepnpm tsgo:profile [...]. - Type policy: use
tsgo; do not addtsc --noEmit,typecheck,check:types.tsconly for declaration/package-boundary emit gaps. - Lint:
pnpm lint,pnpm lint:core,pnpm lint:extensions,pnpm lint:scripts,pnpm lint:apps,pnpm lint:all. - Local 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. - Search/dedupe: prefer
gh search issues 'repo:openclaw/openclaw is:open <terms>' --json number,title,state,updatedAt --limit 20. - 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.
- 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}'. - Background workflows:
Auto response,Docs Sync Publish Repo,Docs Agent,Test Performance Agent. Do not wait/rerun/fix unless asked or task is that workflow. - Post-land wait: minimal. Check required workflows for landed SHA only. If superseded on
main, same-branchcancel-in-progresscancellations are expected; stop once local touched-surface proof exists. Do not wait for newer unrelatedmaincommits unless asked. /landpr: do not idle onauto-responseorcheck-docs. Treat docs as local proof unlesscheck-docsalready failed with actionable relevant error. If product/code gates + touched local gates are green, proceed.- Poll lightly, 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:
pnpm check:changed. Tests-only:pnpm test:changed. Full prod sweep:pnpm check. - 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 models:
sonnet-4.6,gpt-5.4. - Clean timers/env/globals/mocks/sockets/temp dirs/module state;
--isolate=falsesafe. - Hot tests: avoid per-test
vi.resetModules()+ heavy imports. Prefer static/beforeAllimports + direct state reset. - Measure first:
pnpm test:perf:imports <file>,pnpm test:perf:hotspots --limit N. - Seam depth: unit-test pure helpers/contracts; one integration smoke per boundary.
- Mock expensive seams directly: scanners, manifests, package registries, fs crawls, provider SDKs, network/process launch.
- Prefer injection over module mocks; if mocking modules, mock narrow local
*.runtime.ts, not broad barrels. - Share fixtures/builders. Do not recreate temp/plugin workspaces per case unless isolation needs it.
- Delete duplicate assertions. Assert behavior that can regress here.
- Avoid broad
importOriginal()/openclaw/plugin-sdk/*partial mocks; add narrow runtime seam. - 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; at most one contributor mention, preferThanks @user.
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.- 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. Rebuild mac app locally. - Mac 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. - iOS Team ID:
security find-identity -p codesigning -v; fallbackdefaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers. - 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.md,docs/install/fly.md,docs/install/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.