@AGENTS.md
- Read the relevant skill file in
.agents/skills/before writing code for a new feature, API, database table, worker, or integration.- New feature or new operation: build and test the public API procedure (
api/public.ts) before the UI — AI agents are the primary users (AGENTS.md invariant 23).
- New feature or new operation: build and test the public API procedure (
- When touching
packages/database, always runpnpm --filter @chatbotx.io/database db:migrateafter schema changes. - After any code change, run
pnpm lintandpnpm --filter <app> check-typesbefore reporting done. - Use
pnpm fix(Biome auto-fix) instead of manually formatting code.
| Task | Skill to read first |
|---|---|
| Broad/ambiguous request, onboarding, "where does X live" | chatbotx-basecode |
New feature / page (then orpc-api for the public API first, cli-mcp-docs last) |
feature-scaffold |
| Builder UI component, form, table, dialog, or any user-facing string | builder-ui-i18n |
| New API endpoint | orpc-api |
| Result-returning operation (link, preview, test run/test send, stats, export, AI generation) — see "Result-returning operations" | orpc-api |
| After any public API change (every one surfaces in the CLI/MCP), or CLI/MCP docs/skill drift | cli-mcp-docs |
| Business logic, new service method, any DB read/write from app code | business-data-access |
| New DB table or migration | drizzle-database |
| New table / FK / workspace-scoped data, or any change to workspace deletion/purge/freeze | workspace-purge |
| New background job or queue | worker-development |
| New channel integration | integration-channel |
| Contact filter field/operator, filter SQL, or contact-based audience | contact-filter |
| Comment automation (auto-reply/like/hide on post comments — Messenger, Instagram, Threads, TikTok) | comment-automation |
| Minigame tool (Jackpot CRUD, prize draw, public play link/token, extending to a new minigame type) | minigame |
| New flow step with states (success/error/skip routing) | flow-step-development |
| New resource users build (shareable via Templates), new field/id reference on one (flow step, trigger action, contact filter, JSON column), or a write/delete path / list / editor of a template-copied kind | template-integration |
| Dev/build/lint commands | turborepo-workflow |
| Approved implementation plan | implement-plan |
| Security-sensitive change (auth, scoping, webhooks, AI tools, permissions) | security-review |
| Writing tests / verifying a change is done | testing-workflow |
| Fixing a bug, flaky test, or performance regression | diagnosing-bugs |
| Concurrent code (worker jobs, migrations, replace-writes) | reliability-concurrency |
Dispatch these project subagents by name when relevant:
| Agent | When |
|---|---|
invariant-guard |
after editing apps//packages//integrations/ — checks the ChatbotX invariants no linter enforces |
rag-eval |
changes under packages/ai or the embedding repositories/handlers |
incident-responder |
triaging a production error or failed job (then diagnosing-bugs to reproduce and fix it locally) |
Reviewers, planners, build-fixers, etc. come from the ~/.claude/ global set — don't recreate them here.
Default to the cheapest tier that fits the task; reserve the top tier for judgment:
| Task class | Tier |
|---|---|
| file lookup, grep, inventory, verification/refutation | Haiku / Sonnet |
| implementation, code review, debugging | Sonnet |
| architecture, synthesis, incident root-cause | Opus |
- Stage specific files only. A
PreToolUsehook (.claude/hooks/block-dangerous-git.mjs) blocksgit add -A/., force push,reset --hard,clean -f,branch -D, andcheckout ./restore .; if one is truly needed, ask the user to run it. - Do not commit
.envfiles or secrets. - Do not skip
pnpm lint— the CI will fail. - Do not hardcode user-facing strings — use
useTranslations(). - Do not ship a UI-only feature or UI-only button — every operation, including result-returning ones like the bot simulator link, needs a public API procedure unless it is on the exempt list of invariant 23 in
docs/agents/invariants.md. - Do not import
dbdirectly inapps/orintegrations/— the chain isaction | API handler → service (@chatbotx.io/business) → repository (@chatbotx.io/database/repositories) → DB; app code calls a service, never a repository directly (the one exception is a pure read with zero business logic). See.agents/rules/data-access.md. - Do not put Node-only code (
node:crypto,node:stream,fs, anyprocess.*butenv) in a module the builder's oRPC router reaches — it lands in the Edge instrumentation bundle. Split it into its own file + package subpath (outsideindex.ts) imported only by actions/public API/workers; never gateinstrumentation.tsinstead. Guarded byapps/builder/__tests__/edge-instrumentation-graph.test.ts; see AGENTS.md invariant 25. - Do not use dynamic
import()in tsdown-built code (packages/*,integrations/*,apps/worker,apps/cli,apps/mcp-server,apps/javascript-executor) — it breaks the tsdown build. Inapps/builder/srcdynamic imports andnext/dynamicare allowed (and preferred for heavy client islands). See.agents/rules/no-dynamic-import.md.