# AGENTS.MD Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work. Skills own workflows; root owns hard policy and routing. ## Start - Repo: `https://github.com/openclaw/openclaw` - Replies: repo-root refs only: `extensions/telegram/src/index.ts:80`. No absolute paths, no `~/`. - Docs/user-visible work: `pnpm docs:list`, then read relevant docs only. - Fix/triage answers need source, tests, current/shipped behavior, and dependency contract proof. - Dependency-backed behavior: read upstream docs/source/types first. No API/default/error/timing guesses. - Live-verify when feasible. Check env/`~/.profile` for keys before saying blocked; never print secrets. - Missing deps: `pnpm install`, retry once, then report first actionable error. - CODEOWNERS: maint/refactor/tests ok. Larger behavior/product/security/ownership: owner ask/review. - Product/docs/UI/changelog wording: "plugin/plugins"; `extensions/` is internal. - New channel/plugin/app/doc surface: update `.github/labeler.yml` + GH labels. - New `AGENTS.md`: add sibling `CLAUDE.md` symlink. ## 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/`. - Installers: sibling `../openclaw.ai`. - Scoped guides: `extensions/`, `src/{plugin-sdk,channels,plugins,gateway,gateway/protocol,agents}/`, `test/helpers*/`, `docs/`, `ui/`, `scripts/`. ## Architecture - Core stays plugin-agnostic. No bundled ids/defaults/policy in core when manifest/registry/capability contracts work. - Plugins cross into core only via `openclaw/plugin-sdk/*`, manifest metadata, injected runtime helpers, documented barrels (`api.ts`, `runtime-api.ts`). - Plugin prod code: no core `src/**`, `src/plugin-sdk-internal/**`, other plugin `src/**`, or relative outside package. - Core/tests: no deep plugin internals (`extensions/*/src/**`, `onboard.js`). Use public barrels, SDK facade, generic contracts. - Owner boundary: owner-specific repair/detection/onboarding/auth/defaults/provider behavior lives in owner plugin. Shared/core gets generic seams only. - Dependency ownership follows runtime ownership: plugin-only deps stay plugin-local; root deps only for core imports or intentionally internalized bundled plugin runtime. - Legacy config repair belongs in `openclaw doctor --fix`, not startup/load-time core migrations. Runtime paths use canonical contracts. - New seams: backward-compatible, documented, versioned. Third-party plugins exist. - Channels are implementation under `src/channels/**`; plugin authors get SDK seams. Providers own auth/catalog/runtime hooks; core owns generic loop. - Hot paths should carry prepared facts forward: provider id, model ref, channel id, target, capability family, attachment class. Do not rediscover with broad plugin/provider/channel/capability loaders. - Do not fix repeated request-time discovery with scattered caches. Move the canonical fact earlier; reuse prepared runtime objects; delete duplicate lookup branches. - 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 only. - 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. - Package manager/runtime: repo defaults only. No swaps without approval. - Install: `pnpm install` (keep Bun lock/patches aligned if touched). - CLI: `pnpm openclaw ...` or `pnpm dev`; build: `pnpm build`. - Tests: `pnpm test [vitest args...]`, `pnpm test:changed`, `pnpm test:serial`, `pnpm test:coverage`; never raw `vitest`. - Checks: `pnpm check:changed`; lanes: `pnpm changed:lanes --json`; staged: `pnpm check:changed --staged`; full: `pnpm check`. - Extension tests: `pnpm test:extensions`, `pnpm test extensions`, `pnpm test extensions/`. - Typecheck: `tsgo` lanes only (`pnpm tsgo*`, `pnpm check:test-types`); never add `tsc --noEmit`, `typecheck`, `check:types`. - Formatting: `oxfmt`, not Prettier. Use repo wrappers (`pnpm format:*`, `pnpm lint:*`, `scripts/run-oxlint.mjs`). - Build before push when build output, packaging, lazy/module boundaries, dynamic imports, or published surfaces can change. ## Validation - Use `$openclaw-testing` for test/CI choice and `$crabbox` for remote/full/E2E proof. - Small/narrow tests, lints, format checks, and type probes are fine locally. - Full suites, broad changed gates, Docker/package/E2E/live/cross-OS proof, or anything that bogs down the Mac: Crabbox/Testbox. - One/few files local. If a local command fans out, stop and move broad proof to Crabbox/Testbox. - Before handoff/push: prove touched surface. Before landing to `main`: issue proof plus appropriate full/broad proof unless scope is clearly narrow. - If proof is blocked, say exactly what is missing and why. - Do not land related failing format/lint/type/build/tests. If unrelated on latest `origin/main`, say so with scoped proof. - Docs/changelog-only and CI/workflow metadata-only: `git diff --check` plus relevant docs/workflow sanity; escalate only if scripts/config/generated/package/runtime behavior changed. ## GitHub / PRs - Use `$openclaw-pr-maintainer` immediately for OpenClaw issue/PR URLs/numbers, review, triage, duplicate search, close, labels, landing, comments, or maintainer evidence. - PR refs: `gh pr view/diff`, not web search. Prefer `gitcrawl` for local candidate discovery; verify live with `gh` before mutation. - Bare issue/PR URL/number means review/report in chat. Suggest comment/close/merge when appropriate; mutate only when asked. - No unsolicited PR comments/reviews/labels/retitles/rebases/fixups/landing. Exception: close/duplicate action that needs a reason comment after explicit close/sweep/landing request. - PR review answer: bug/behavior, URL(s), affected surface, best-fix judgment, evidence from code/tests/CI/current or shipped behavior. - Issue/PR final answer: last line is the full GitHub URL. - Changelog: PR landings/fixes need one unless pure test/internal. Do not mention missing changelog as a review finding; Codex handles it during fix/landing. - PR verification: before merge, post exact local commands, CI/Testbox run IDs, before/after proof when used, and known proof gaps. - Issue fixed on `main` with proof: comment proof + commit/PR, then close. - After landing or requested close/sweep: search duplicates; comment proof + canonical commit/PR/release before closing. - `ship` that fixes an issue: after push, comment proof + commit link, then close the issue. - GH comments with backticks, `$`, or shell snippets: use heredoc/body file, not inline double-quoted `--body`. - PR create: real body required. Include Summary + Verification; mention refs, behavior, and proof. - PR artifacts/screenshots: attach to PR/comment/external artifact store. Do not commit `.github/pr-assets`. - CI polling: exact SHA, relevant checks only, minimal fields. Skip routine noise (`Auto response`, `Labeler`, docs agents, performance/stale). Logs only after failure/completion or concrete need. - Maintainers: ignore `Real behavior proof` failures that only say PR body lacks real after-fix evidence. - `/landpr`: use `~/.codex/prompts/landpr.md`; do not idle on `auto-response` or `check-docs`. ## Code - TS ESM, strict. Avoid `any`; prefer real types, `unknown`, narrow adapters. - No `@ts-nocheck`. Lint suppressions only intentional + explained. - External boundaries: prefer `zod` or existing schema helpers. - Runtime branching: discriminated unions/closed codes over freeform strings. Avoid semantic sentinels (`?? 0`, empty object/string). - Dynamic import: no static+dynamic import for same prod module. Use `*.runtime.ts` lazy 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; `openclaw` CLI/package/path/config. - English: American spelling. ## Tests - Vitest. Colocated `*.test.ts`; e2e `*.e2e.test.ts`; example models `sonnet-4.6`, `gpt-5.5`; test GPT with 5.5 preferred, 5.4 ok; no GPT-4.x agent-smoke defaults. - Prefer behavior tests over workflow/docs string greps. Put operator policy reminders in AGENTS/docs. - Clean timers/env/globals/mocks/sockets/temp dirs/module state; `--isolate=false` safe. - Prefer injection and narrow `*.runtime.ts` mocks over broad barrels or `openclaw/plugin-sdk/*`. - Do not edit baseline/inventory/ignore/snapshot/expected-failure files to silence checks without explicit approval. - Do not run independent `pnpm test`/Vitest commands concurrently in one worktree; Vitest cache races with `ENOTEMPTY`. Group one command or use distinct `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH`. - Test workers max 16. Memory pressure: `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test`. - Live: `OPENCLAW_LIVE_TEST=1 pnpm test:live`; verbose `OPENCLAW_LIVE_TEST_QUIET=0`. - Guide: `docs/reference/test.md`. ## Docs / Changelog - Use `$openclaw-docs` for docs writing/review. Docs change with behavior/API. - Codex harness upgrade (`extensions/codex/package.json` `@openai/codex`): refresh `docs/plugins/codex-harness.md` model snapshot from the new harness `model/list`. - Docs final answers: include relevant full `https://docs.openclaw.ai/...` URL(s). If issue/PR work too, GitHub URL last. - Changelog entries: active version `### Changes`/`### Fixes`; single-line bullets only. - Contributor PR authors should not edit `CHANGELOG.md`; maintainer/AI adds entries during landing/merge. - Contributor-facing changelog entries thank credited human `@author`. Never thank bots, `@openclaw`, `@clawsweeper`, or `@steipete`; if unknown, omit thanks. ## Git - Commit via `scripts/committer "" `; stage intended files only. - Commits: conventional-ish, concise, grouped. - No manual stash/autostash unless explicit. No branch/worktree changes unless requested. - `main`: no merge commits; rebase on latest `origin/main` before push. After one green run plus clean rebase sanity, do not chase moving `main` with repeated full gates. - User says `commit`: your changes only. `commit all`: all changes in grouped chunks. `push`: may `git pull --rebase` first. - User says `ship it`: changelog if needed, commit intended changes, pull --rebase, push. - Do not delete/rename unexpected files; ask if blocking, else ignore. - Bulk PR close/reopen >5: ask with count/scope. ## Security / Release - Never commit real phone numbers, videos, credentials, live config. - Secrets: channel/provider creds in `~/.openclaw/credentials/`; model auth profiles in `~/.openclaw/agents//agent/auth-profiles.json`. - Env keys: check `~/.profile`; redact output. - Dependency patches/overrides/vendor changes need explicit approval. `pnpm-workspace.yaml` patched dependencies use exact versions only. - Carbon pins owner-only: do not change `@buape/carbon` unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks. - Releases/publish/version bumps need explicit approval. Use `$openclaw-release-maintainer`. - GHSA/advisories: `$openclaw-ghsa-maintainer` / `$security-triage`. Secret scanning: `$openclaw-secret-scanning-maintainer`. - Beta tag/version match: `vYYYY.M.D-beta.N` -> npm `YYYY.M.D-beta.N --tag beta`. ## Platform / Ops - Before simulator/emulator testing, check real iOS/Android devices. - "restart iOS/Android apps" = rebuild/reinstall/relaunch, not kill/launch. - SwiftUI: Observation (`@Observable`, `@Bindable`) over new `ObservableObject`. - Mac gateway: dev watch = `pnpm gateway:watch`; managed installs = `openclaw gateway restart/status --deep`; logs = `./scripts/clawlog.sh`. No launchd/ad-hoc tmux. - Version bump surfaces live in `$openclaw-release-maintainer`. - Parallels: `$openclaw-parallels-smoke`; Discord roundtrip: `$parallels-discord-roundtrip`. - Crabbox/WebVNC human demos: keep remote desktop visible/windowed; no fullscreen remote browser unless video/capture-style output. - ClawSweeper ops: `$clawsweeper`. Deployed hook sessions may post one concise `#clawsweeper` note only when surprising/actionable/risky; if using message tool, reply exactly `NO_REPLY`. - Memory wiki prompt digest stays tiny; prefer `wiki_search` / `wiki_get`; verify contact data before use; source-class provenance for generated people facts. - Rebrand/migration/config warnings: run `openclaw doctor`. - Never edit `node_modules`. - Local-only `.agents` ignores: `.git/info/exclude`, not repo `.gitignore`. - Provider tool schemas: prefer flat string enum helpers over `Type.Union([Type.Literal(...)])`; some providers reject `anyOf`. - External messaging: no token-delta channel messages. Follow `docs/concepts/streaming.md`.