Most guides about AGENTS.md, CLAUDE.md, and .cursorrules treat them as a formatting problem. Pick one, fill it out, ship it. Job done.
That framing is wrong in a way that costs you real productivity. The file format is the least important decision. The important decisions are: which file to use given your toolchain, what information actually belongs in it, and how to scope rules so they stay accurate six months from now when your stack has drifted.
This guide skips the introductory comparisons — if you want those, see AGENTS.md vs CLAUDE.md: When to Use Which. What follows is an opinionated template catalog organized by use case, each with a file-selection rationale and a ready-to-copy configuration. The final sections cover common pitfalls, multi-file composition, and a FAQ.
The File-Selection Problem
Before the templates: a quick mental model for which file to reach for.
Use AGENTS.md when:
- Your team runs multiple AI tools (Claude Code + Cursor + Codex CLI + GitHub Copilot)
- You want a single source of truth that works across all of them
- Your rules are project-wide, not tool-specific
Use CLAUDE.md when:
- Claude Code is your primary or only AI coding tool
- You need hierarchical rules (root + per-directory)
- You want to use Claude-specific features:
@import, path-scoped.claude/rules/, or user-level overrides - You need CLAUDE.md alongside AGENTS.md to add Claude-specific depth on top of shared context
Use .cursorrules when:
- Cursor is your primary IDE and you are not running other AI tools
- You are migrating from an existing .cursorrules file and not ready to switch formats yet
- Note: .cursorrules is a flat file with no hierarchy. If your project has grown, consider
.cursor/rules/*.mdcinstead
The practical answer for most teams in 2026:
- AGENTS.md at repo root (universal context, all tools read this)
- CLAUDE.md layered on top (Claude-specific depth and directory scoping)
- .cursorrules only if you are Cursor-only and have not migrated yet
With that framing established, here are the templates.
Template 1: Solo Developer, TypeScript SaaS
Profile: One developer. Full-stack TypeScript. Next.js frontend, Node/Express or Hono backend, PostgreSQL. Deploys to Vercel. Uses Claude Code as primary tool, occasionally opens the same repo in Cursor.
File choice: AGENTS.md at root (both tools will read it), CLAUDE.md with Claude-specific additions.
Why both? Claude Code needs the operational details (database commands, env setup, test patterns). Cursor should know the same architectural rules. AGENTS.md covers shared ground; CLAUDE.md adds Claude-specific behavior like “ask before installing new dependencies.”
AGENTS.md
# Project: [Your SaaS Name]
TypeScript SaaS. Next.js 15 (App Router) frontend, Hono backend, PostgreSQL with Drizzle ORM. Auth via Clerk. Deployed to Vercel (frontend) and Railway (backend).
## Tech Stack
- Frontend: Next.js 15, TypeScript strict, Tailwind CSS, shadcn/ui
- Backend: Hono on Node.js, Zod for validation, Drizzle ORM
- Database: PostgreSQL (Railway). Local dev uses Docker.
- Auth: Clerk (JWT-based, webhooks for user sync)
- Package manager: pnpm workspaces
## Architecture Rules
- Server Components by default. Add `'use client'` only for interactivity, browser APIs, or React hooks.
- Mutations go through Server Actions in `src/app/actions/`. No REST endpoints for mutations from the frontend.
- Validate all external input (API bodies, form data, URL params) with Zod schemas before touching the database.
- No raw SQL. All database access goes through Drizzle query builder.
- Feature flags live in `src/lib/flags.ts`. Check this before adding new behavior.
## File Conventions
- `apps/web/` — Next.js frontend
- `apps/api/` — Hono backend
- `packages/db/` — Drizzle schema, migrations, client
- `packages/types/` — Shared TypeScript types
- File names: kebab-case. Component names: PascalCase. No default exports except pages and layouts.
- Co-locate tests: `feature.test.ts` next to `feature.ts`.
## Commands
- `pnpm dev` — Start all apps in development
- `pnpm build` — Production build (runs from repo root)
- `pnpm test` — Run all tests (Vitest)
- `pnpm db:generate` — Generate Drizzle migrations
- `pnpm db:migrate` — Apply migrations to local DB
- `pnpm lint` — ESLint across all packages
- `docker compose up -d` — Start local PostgreSQL
## Environment
- Copy `.env.example` to `.env.local` in each app before first run.
- Never commit `.env` files. Database URLs are in Railway dashboard.
- `DATABASE_URL` must be set for backend to start.
## TypeScript Rules
- No `any`. Use `unknown` and narrow with type guards or Zod.
- Prefer `interface` over `type` for object shapes.
- All async functions must handle errors explicitly (no unhandled promise rejections).
- `strictNullChecks` is on. Handle null/undefined at the boundary, not deep in the call stack.
CLAUDE.md (adds Claude-specific behavior)
# Claude Code Configuration
@import AGENTS.md
## Behavior
- Ask before installing new npm packages. State why you need it and list alternatives considered.
- Ask before modifying the Drizzle schema. Schema changes require migrations and can break production.
- Never auto-commit. Stage changes and describe what you are about to do.
- If a task requires more than 3 files to be changed, outline the plan before starting.
## Preferred Patterns
- Use the `cn()` utility from `@/lib/utils` for conditional classes.
- Use `useOptimistic` for optimistic UI updates, not manual state management.
- Error boundaries go in `src/app/error.tsx` and `src/app/global-error.tsx`.
- For new API endpoints, add Zod schema to `packages/types/` first, then implement.
## Testing
- Every new utility function needs a unit test.
- Integration tests for Hono endpoints go in `apps/api/test/`.
- Do not mock the database in integration tests. Use test containers (see `docker-compose.test.yml`).
Template 2: Open Source Library Maintainer
Profile: OSS library. Multiple contributors, mixed AI tool setups. Some use Claude Code, some use Cursor, some use Codex CLI. You want to enforce contribution standards without requiring everyone to configure their tools the same way.
File choice: AGENTS.md only. Single file, maximum compatibility.
Why not CLAUDE.md? Contributors use different tools. A CLAUDE.md only helps Claude Code users. AGENTS.md is the one file all modern AI agents will read.
AGENTS.md
# [Library Name]
TypeScript utility library for [brief description]. Published to npm. Supports Node 18+, Deno, and browser environments via ESM.
## Contribution Rules
- Public API surface lives in `src/index.ts`. Do not add to this file without a proposal in Discussions first.
- Every public function must have a JSDoc comment with at minimum: description, `@param` for each parameter, `@returns`, and one `@example`.
- Breaking changes require a BREAKING CHANGE note in the commit body (triggers major version bump via release-please).
## Code Standards
- TypeScript strict mode. No `any`, no `// @ts-ignore`.
- Pure functions where possible. Side effects must be documented.
- Zero runtime dependencies. Dev dependencies only. Check `package.json` before adding anything.
- Bundle size matters. Every new export adds to the bundle. Prefer tree-shakeable named exports.
## Testing
- Test runner: Vitest
- `pnpm test` — Run tests
- `pnpm test:coverage` — Coverage report (must stay above 90%)
- Test file naming: `feature.test.ts` alongside `feature.ts`
- Test public behavior, not implementation. Do not import private functions in tests.
- Each test file must have a `describe` block matching the module name.
## Build and Release
- `pnpm build` — Compile TypeScript to `dist/` (ESM + CJS dual output)
- `pnpm typecheck` — TypeScript type checking without emitting files
- Do not manually edit `CHANGELOG.md` or version numbers. release-please manages these.
- PR titles must follow Conventional Commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
## What Not to Do
- Do not add dependencies (runtime or peer) without opening a Discussion.
- Do not modify the build config (`tsup.config.ts`, `tsconfig.json`) without discussing first.
- Do not use browser-only APIs (`window`, `document`, `localStorage`). This library runs in Node and Deno.
- Do not write tests that depend on execution order.
Template 3: Enterprise Monorepo
Profile: Monorepo with 30+ packages. Multiple teams. Standardized on Claude Code. Need per-directory rules so the frontend team’s rules do not bleed into the backend, and vice versa.
File choice: CLAUDE.md with directory-scoped rules. AGENTS.md at root for shared context.
Why CLAUDE.md for per-directory scoping? AGENTS.md does not support directory-level scoping. CLAUDE.md can be placed in any directory, and Claude Code reads the most specific one. This is the key capability that makes enterprise monorepos manageable.
Root AGENTS.md (read by all tools)
# Monorepo
Monorepo managed by Turborepo. 30+ packages across frontend, backend, and shared utilities. Teams: Platform, Growth, Data, Mobile.
## Repo Structure
- `apps/` — Deployable applications
- `packages/shared/` — Cross-team shared libraries
- `packages/ui/` — Design system components
- `services/` — Backend microservices
- `infra/` — Terraform and Kubernetes configs
- `tools/` — Build tooling and code generators
## Universal Rules
- Every package must have a `README.md` with: purpose, owner team, usage example.
- Cross-package dependencies must go through the proper package boundary. No relative imports across package directories.
- All packages use `pnpm` for package management. Never use `npm install`.
- Changesets manage versioning. Run `pnpm changeset` before opening a PR that changes a public package API.
- CI must pass before merge. Do not merge with failing tests or type errors.
## Commit Convention
- Conventional Commits required: `feat(scope):`, `fix(scope):`, `chore(scope):`, etc.
- Scope = package or app name (e.g., `feat(ui):`, `fix(auth-service):`)
Root CLAUDE.md (Claude-specific behavior)
# Claude Code — Root Configuration
@import AGENTS.md
## Behavior in This Repo
- Always check which package you are in before suggesting changes. Package boundaries are strict.
- Do not suggest moving code between packages without asking the owner team first.
- When creating a new file, check if a generator exists: `pnpm turbo gen [type]`
- Ask before modifying `turbo.json`, `pnpm-workspace.yaml`, or any root-level config.
## Turbo Commands
- `pnpm turbo build` — Build all affected packages
- `pnpm turbo test` — Test all affected packages
- `pnpm turbo lint` — Lint all packages
- `pnpm turbo dev --filter=[app-name]` — Dev mode for a single app
packages/ui/CLAUDE.md (UI package scoped rules)
# Design System Package
This package contains the shared UI component library. Used by all frontend apps.
## Contribution Rules
- Every new component needs: TypeScript props interface, Storybook story, unit test, documentation in `docs/`.
- Use Radix UI primitives for accessibility-critical components (dialogs, dropdowns, tooltips).
- Components must work in light and dark mode. Test both before submitting.
- No business logic in components. Data fetching, API calls, and routing belong in apps, not here.
## Component File Structure
src/ components/ Button/ Button.tsx — Component Button.test.tsx — Unit tests Button.stories.tsx — Storybook index.ts — Re-export
## Commands
- `pnpm storybook` — Start Storybook dev server
- `pnpm test` — Run component tests
- `pnpm build` — Build component library
services/auth-service/CLAUDE.md
# Auth Service
Node.js microservice. Handles authentication, session management, and user provisioning. Deployed to Kubernetes.
## Security Rules (Non-Negotiable)
- All endpoints require authentication unless explicitly marked as public in `src/routes/public.ts`.
- Never log passwords, tokens, or PII. Check `src/lib/logger.ts` for the safe logging utility.
- Input validation is required on every endpoint. Use the Zod schemas in `src/schemas/`.
- Database queries use parameterized statements via Drizzle. No string interpolation in queries.
- Secrets come from environment variables, never from config files in the repo.
## Architecture
- Route handlers in `src/routes/`. One file per resource.
- Business logic in `src/services/`. No database code in services.
- Database access in `src/repositories/`. Only repositories talk to the database.
- JWT verification middleware in `src/middleware/auth.ts`.
## Testing Requirements
- Security-critical paths must have integration tests, not just unit tests.
- Test auth failure cases explicitly (expired tokens, tampered tokens, missing permissions).
- `pnpm test:integration` runs against a test database (see Docker setup).
Template 4: Mobile Team (Flutter)
Profile: Flutter app. iOS and Android targets. Team of 4. Uses Claude Code and GitHub Copilot. State management with Riverpod. Supabase backend.
File choice: AGENTS.md (Copilot compatibility required) + CLAUDE.md for Flutter-specific Claude behavior.
AGENTS.md
# [App Name] — Flutter App
Flutter application targeting iOS and Android. Backend: Supabase (auth, database, storage). State management: Riverpod 2.x.
## Architecture
This project follows Feature-First architecture:
lib/ core/ — App-wide utilities, constants, themes features/ auth/ data/ — Repositories, API clients domain/ — Entities, use cases presentation/ — Screens, widgets, providers shared/ — Widgets and utilities used by multiple features
- Each feature is self-contained. Features communicate through the domain layer, never directly.
- No business logic in widgets. Widgets read from providers and dispatch events.
- Providers are defined in `presentation/providers/`. One provider file per screen or major widget.
## Code Standards
- `flutter_lints` is enforced. Run `flutter analyze` before committing.
- Null safety is enabled. No `!` force-unwrapping without a comment explaining why null is impossible.
- Use `const` constructors wherever possible.
- Widget files: one widget per file. Filename matches widget name in snake_case.
- No `BuildContext` in business logic. Pass data as parameters, not context.
## State Management (Riverpod)
- Prefer `AsyncNotifierProvider` for async state.
- Providers that depend on auth state use `ref.watch(authProvider)` and handle unauthenticated state.
- Never call `.read()` in the widget `build` method. Use `.watch()`.
- Providers that make network calls must handle loading, data, and error states explicitly.
## Commands
- `flutter run` — Run on connected device
- `flutter test` — Run all tests
- `flutter analyze` — Static analysis
- `flutter build apk --release` — Android release build
- `flutter build ipa` — iOS release build (requires Mac + Xcode)
- `dart run build_runner build` — Generate code (Freezed, Riverpod annotations)
## Testing
- Unit tests for use cases and repositories in `test/features/[feature]/`.
- Widget tests for complex UI in `test/widget/`.
- Use `mocktail` for mocking. Do not use `mockito`.
- Golden tests for UI components that must not visually regress.
## Platform Considerations
- Check `Platform.isIOS` / `Platform.isAndroid` when behavior must differ. Document why in a comment.
- Assets are in `assets/`. Image assets need @2x and @3x variants for iOS.
- Deep links are handled in `core/router/`. Do not add route handling elsewhere.
CLAUDE.md
# Claude Code Configuration — Flutter
@import AGENTS.md
## Flutter-Specific Behavior
- When generating code, run `dart run build_runner build` mentally. If your new code requires generated files (Freezed models, Riverpod providers with `@riverpod` annotations), remind me to run the code generator.
- For platform-specific code, scaffold both iOS and Android implementations even if one is a no-op stub.
- Hot reload works for most changes. A full restart (`R` in terminal) is needed for: new native plugins, main.dart changes, and asset additions.
## Common Patterns in This Codebase
- Error handling: Use `Either<Failure, T>` from `fpdart` in the domain layer. Never throw from repositories.
- Navigation: `go_router` handles all routing. Add routes to `core/router/app_router.dart`.
- Localization: All user-facing strings go through `AppLocalizations` from `flutter_localizations`. No hardcoded strings.
- HTTP client: `Dio` with interceptors in `core/network/`. Use the configured client, never `http` package directly.
## When Modifying Supabase Schema
- Schema changes require updating the Supabase dashboard AND the local type generation.
- Run `supabase gen types typescript --project-id [id] > lib/core/supabase/database.types.ts` after schema changes (yes, TypeScript types — they are used for the admin dashboard).
- Row Level Security policies must be updated when adding new tables.
Template 5: Data / ML Pipeline
Profile: Python ML project. Data ingestion, feature engineering, model training, batch inference. Uses DVC for data versioning. Team of 3 data scientists who all use Claude Code.
File choice: CLAUDE.md only. All team members use Claude Code. DVC and MLflow are Claude-specific workflow needs.
CLAUDE.md
# ML Pipeline — Claude Code Configuration
Python ML project. DVC for data versioning. MLflow for experiment tracking. Training on AWS SageMaker, inference on Lambda.
## Environment Setup
- Python 3.11. Always use the project venv: `source .venv/bin/activate`
- `pip install -e ".[dev]"` installs the package in editable mode with dev dependencies
- DVC remote is configured in `.dvc/config`. Run `dvc pull` to sync data files before working.
- MLflow tracking server: `mlflow ui --backend-store-uri sqlite:///mlflow.db`
## Project Structure
src/ data/ — Data loading, validation, and preprocessing features/ — Feature engineering pipelines models/ — Model definitions and training code evaluation/ — Metrics, visualizations, and reports serving/ — Inference code for Lambda notebooks/ — Exploratory analysis (not used in production) pipelines/ — DVC pipeline definitions (dvc.yaml) tests/ — Unit and integration tests
## Data Rules
- Raw data is read-only. Never modify files in `data/raw/`.
- All data transformations must be reproducible. No random operations without a fixed seed.
- Data that leaves the pipeline must be validated with Pandera schemas in `src/data/schemas.py`.
- Data files are tracked by DVC, not Git. Never `git add` a .csv, .parquet, or .pkl file.
## Experiment Tracking
- Every training run logs to MLflow. Required params: `model_name`, `dataset_version`, `feature_set`, `random_seed`.
- Tag experiments with the ticket number if applicable: `mlflow.set_tag("ticket", "ML-42")`.
- Model artifacts are logged with `mlflow.log_model()`. Do not save models manually.
## Code Standards
- Type hints required on all function signatures. Use `numpy.typing` for arrays.
- No Jupyter notebooks in `src/`. Notebooks are in `notebooks/` for exploration only.
- `black` for formatting, `ruff` for linting. Run `make lint` before committing.
- Tests for data transformations are mandatory. Each `features/` module has a corresponding test.
## DVC Pipeline
- `dvc repro` — Run the full pipeline (only reruns changed stages)
- `dvc dag` — Show pipeline dependency graph
- `dvc params diff` — Show parameter changes vs last commit
- Never hardcode file paths. Use the paths defined in `params.yaml`.
## Commands
- `make lint` — Black + ruff
- `make test` — pytest with coverage
- `make train` — Run training stage via DVC
- `make evaluate` — Run evaluation stage
- `dvc push` — Push data and model artifacts to remote
## What Not to Do
- Do not import from `notebooks/`. Notebooks are scratch space.
- Do not hardcode AWS region or bucket names. They are in environment variables.
- Do not commit model weights. They are DVC artifacts.
- Do not use `print()` for logging. Use the `logging` module configured in `src/utils/logging.py`.
Template 6: Game Development (Unity)
Profile: Unity game project. C# scripts. Mobile target (iOS/Android). Small team using Claude Code. Project uses a custom ECS-like architecture.
File choice: CLAUDE.md. Unity projects are effectively Claude Code-only setups in most small studios.
CLAUDE.md
# Game Project — Unity
Unity 6 (6000.0 LTS). C# scripting. Mobile target: iOS and Android. Render pipeline: URP.
## Architecture
This project uses a component-based entity system. Key concepts:
- **Systems**: `MonoBehaviour` classes in `Assets/Scripts/Systems/` that process entities each frame. One responsibility per system.
- **Components**: Plain C# classes (`[System.Serializable]`) that hold data. No logic in components.
- **Events**: `ScriptableObject`-based event channels in `Assets/Scripts/Events/`. Systems communicate through events, not direct references.
- **Services**: Singletons in `Assets/Scripts/Services/` for cross-cutting concerns (audio, analytics, save data).
## C# Conventions
- Namespaces: `[Studio].[Module]` (e.g., `Studio.Combat`, `Studio.UI`).
- Private fields: `_camelCase`. Public properties: `PascalCase`.
- `sealed` classes by default unless inheritance is explicitly needed.
- `readonly` for fields that do not change after initialization.
- No `Find()` or `GetComponent()` in `Update()`. Cache references in `Awake()` or `Start()`.
- Avoid `string` comparisons for tags and layers. Use integer hashes or the constants in `Assets/Scripts/Constants/`.
## Performance Rules
- Target: 60fps on iPhone 12 / mid-range Android. Profile before optimizing.
- Avoid allocations in hot paths (`Update`, physics callbacks). Pool GameObjects in `Assets/Scripts/Pools/`.
- `[SerializeField]` private fields instead of public fields. Keeps the Inspector clean.
- Texture atlases for UI sprites. No individual textures for UI elements.
- Audio: `AudioSource.PlayOneShot()` for one-shots via the AudioService. Do not create AudioSource components in scripts.
## Scenes and Prefabs
- `Assets/Scenes/` — One scene per major game state (MainMenu, Gameplay, Loading).
- Prefabs in `Assets/Prefabs/`. Never use scene-embedded variants of shared objects.
- Prefab variants for enemies with different stats. Base prefab in `Assets/Prefabs/Enemies/Base/`.
## Build and Test
- Build via `File > Build Settings` or CI (see `.github/workflows/unity-build.yml`).
- Play Mode tests in `Assets/Tests/PlayMode/`. Edit Mode tests in `Assets/Tests/EditMode/`.
- Run tests: `Test Runner` window in Unity, or `./scripts/run-tests.sh` in CI.
## What Not to Do
- Do not use `DontDestroyOnLoad` except in `Assets/Scripts/Services/`. Overuse causes memory leaks.
- Do not put game data in scripts. Data goes in `ScriptableObject` assets in `Assets/Data/`.
- Do not reference scene objects from `ScriptableObject` assets.
- Do not use `Invoke()` or `InvokeRepeating()`. Use Coroutines or the `UpdateService`.
Template 7: Static Site / Marketing
Profile: Astro-based marketing site. Content team edits MDX files. One developer maintains it. Claude Code used for component work and content automation.
File choice: CLAUDE.md. Site is Claude Code-only, and the content team does not use AI tools directly on the repo.
CLAUDE.md
# Marketing Site — Astro
Astro 5 site. Content in MDX. Deployed to Cloudflare Pages via GitHub Actions.
## Content Structure
- `src/content/blog/` — Blog posts (MDX). Frontmatter schema: `src/content.config.ts`.
- `src/content/pages/` — Landing pages (MDX).
- `src/components/` — Astro components and React islands.
- `public/` — Static assets. Images served directly, no optimization pipeline.
## Content Rules
- Required frontmatter for blog posts: `title`, `description`, `pubDate`, `draft`, `tags`.
- `draft: true` keeps posts out of production builds. Set to `false` when ready to publish.
- Images referenced in MDX must exist in `public/images/`. Check before referencing.
- No external images in MDX (they will break if the source goes down). Download and add to `public/`.
## Component Patterns
- Astro components (`.astro`) for static content. React components (`.tsx`) only when client-side interactivity is needed.
- Client-side React: use `client:load` for immediately needed interactivity, `client:idle` for non-critical, `client:visible` for below-fold.
- Tailwind CSS for all styling. No `<style>` blocks in components.
- The `cn()` utility is in `src/lib/utils.ts`. Use it for conditional classes.
## Routing
- File-based routing. `src/pages/[slug].astro` generates dynamic routes from content collections.
- Redirects are in `public/_redirects` (Cloudflare Pages format).
- Dynamic OG images generated via `src/pages/og/[slug].png.ts` (using Satori).
## Commands
- `pnpm dev` — Start dev server (localhost:4321)
- `pnpm build` — Production build to `dist/`
- `pnpm preview` — Preview production build locally
- `pnpm check` — Astro type checking
## SEO Rules
- Every page needs a unique `<title>` and `<meta name="description">`.
- `BaseLayout.astro` handles OG tags. Pass `title` and `description` as props.
- Canonical URLs are set in `BaseLayout.astro` using the site URL from `astro.config.mjs`.
## Deployment
- Push to `main` triggers Cloudflare Pages deployment automatically.
- Preview deployments on every PR.
- Do not edit `dist/`. It is the build output and is git-ignored.
Template 8: Backend API (Go)
Profile: Go REST API. PostgreSQL database. Docker-based local development. Team uses both Claude Code and Cursor.
File choice: AGENTS.md + CLAUDE.md. Mixed tool environment needs AGENTS.md for Cursor. Claude Code benefits from the additional Go-specific rules in CLAUDE.md.
AGENTS.md
# Backend API — Go
Go REST API. PostgreSQL with pgx driver. Docker for local development. Deployed to GCP Cloud Run.
## Architecture
Layered architecture:
cmd/ api/ main.go — Entrypoint, dependency wiring internal/ handler/ — HTTP handlers (request parsing, response formatting) service/ — Business logic (no HTTP or database dependencies) repository/ — Database access (no business logic) model/ — Domain types shared across layers middleware/ — HTTP middleware (auth, logging, rate limiting) pkg/ database/ — Database connection and migrations config/ — Configuration loading errors/ — Custom error types
- Handlers call services. Services call repositories. No skipping layers.
- No `net/http` imports in `service/`. Services must be testable without a running HTTP server.
- No database imports in `handler/`. Database is a dependency injection concern.
## Code Standards
- `gofmt` and `golangci-lint` required. Run `make lint` before committing.
- Error handling: always check errors. No `_` for error returns unless explicitly documented.
- Use `errors.New()` from the `pkg/errors` package for domain errors (they carry status codes).
- Context propagation: all functions that may block accept `context.Context` as first argument.
- Avoid global state. Pass dependencies through function arguments or struct fields.
- Exported types and functions must have godoc comments.
## Database
- Migrations in `db/migrations/`. Numbered with `goose` format: `001_create_users.sql`.
- `make migrate-up` — Apply pending migrations
- `make migrate-down` — Roll back last migration
- No ORM. Raw SQL with `pgx`. Queries in repository files.
- Parameterized queries only. No string formatting with user input.
## Testing
- `make test` — Run all tests
- `make test-integration` — Integration tests (requires Docker)
- Unit tests mock the layer below. Use the `mock/` subdirectory in each package.
- Integration tests use a real PostgreSQL instance via Docker Compose.
- Table-driven tests for handlers and services where there are multiple input variations.
## Commands
- `make dev` — Start API with hot reload (using Air)
- `make build` — Build binary
- `make test` — Unit tests
- `make test-integration` — Integration tests
- `make lint` — Run golangci-lint
- `docker compose up -d` — Start PostgreSQL locally
Template 9: DevOps / Infrastructure
Profile: Infrastructure team managing Terraform configs, Kubernetes manifests, and CI/CD pipelines. Uses Claude Code for IaC assistance.
File choice: CLAUDE.md. Infrastructure changes are high-risk. The Claude.md file needs to encode safety constraints that may not be obvious to a general-purpose AI.
CLAUDE.md
# Infrastructure Repository
Terraform and Kubernetes configurations for production infrastructure. AWS + GCP multi-cloud. Environments: dev, staging, production.
## IMPORTANT: Safety Rules
Before suggesting any change, identify which environment it affects. Production changes require:
1. A Terraform plan review (never apply directly)
2. A peer review from another team member
3. Off-peak deployment window (avoid 09:00-17:00 UTC Mon-Fri for production)
Never suggest changes that would:
- Modify IAM roles or policies without a documented business reason
- Delete resources (use `lifecycle { prevent_destroy = true }` instead of removal)
- Change networking rules that could affect internet-facing services
- Reduce cluster node counts below the minimum in `terraform/environments/production/variables.tf`
## Repository Structure
terraform/ modules/ — Reusable Terraform modules environments/ dev/ staging/ production/ kubernetes/ base/ — Base Kustomize configs overlays/ dev/ staging/ production/ .github/ workflows/ — CI/CD pipeline definitions
## Terraform Conventions
- All resources must have a `Name` tag and an `Environment` tag.
- Variables without defaults in `variables.tf` are required inputs. Document why they have no default.
- Remote state in S3 (AWS) or GCS (GCP). Never run `terraform init` with local state in a team environment.
- Use `terraform fmt` before committing. CI will fail if formatting is inconsistent.
- `terraform validate` and `terraform plan` are read-only. `terraform apply` is a write operation that requires approval.
## Kubernetes Conventions
- All Deployments must have resource `requests` and `limits` set.
- Pods must have `readinessProbe` and `livenessProbe` defined.
- Secrets come from Kubernetes Secrets or external-secrets-operator (reading from AWS Secrets Manager / GCP Secret Manager). No secrets in ConfigMaps or manifests.
- Namespace per application, not per environment. Environment differentiation via Kustomize overlays.
## CI/CD
- `main` branch → staging (automatic)
- Staging → production: manual promotion via `workflow_dispatch` with approvals
- Rollback: `kubectl rollout undo deployment/[name] -n [namespace]`
- Drift detection runs nightly. Check `#infra-alerts` Slack channel for drift notifications.
## Commands
- `terraform plan -var-file=environments/dev/terraform.tfvars` — Plan for dev
- `kubectl kustomize kubernetes/overlays/dev | kubectl apply -f -` — Apply dev overlay
- `make validate` — Validate all Terraform modules and Kubernetes manifests
- `make docs` — Generate terraform-docs documentation
Template 10: Quick PoC / Spike
Profile: Exploring a new library, prototyping an integration, or investigating feasibility. Time-boxed (1-5 days). Will be thrown away or rewritten.
File choice: Neither. Or AGENTS.md at root if you must have something.
Rationale: Proof-of-concept code has different constraints than production code. A CLAUDE.md that enforces production-grade patterns will slow you down and generate arguments with the AI. Either skip the config file, or use a minimal AGENTS.md that sets context without imposing constraints.
AGENTS.md (minimal, for PoC)
# PoC: [Name of Exploration]
Time-boxed exploration. Goal: [specific question to answer]. Deadline: [date].
This is throwaway code. Prioritize:
1. Speed of iteration over code quality
2. Working demonstration over production readiness
3. Learning outcomes over architectural correctness
## What We Are Exploring
[Describe the specific integration or capability being tested]
## Known Constraints
- [Any real constraints that matter even in PoC — e.g., "API is rate-limited to 10 req/s"]
- [Security constraints that cannot be skipped even in PoC]
## Setup
[How to run this]
## Success Criteria
[What does "this PoC succeeded" look like? Specific, testable outcome]
Template 11: Backend API (Python / FastAPI)
Profile: Python FastAPI service. Async. PostgreSQL with SQLAlchemy async. Used by a team split between Claude Code and Copilot.
File choice: AGENTS.md + CLAUDE.md (same reasoning as Go API above).
AGENTS.md
# API Service — Python / FastAPI
FastAPI application. Async throughout. PostgreSQL with SQLAlchemy (async). Pydantic v2 for data validation. Deployed to AWS ECS.
## Structure
src/ api/ routes/ — Route definitions (one file per resource) dependencies/ — FastAPI dependency injection functions models/ db/ — SQLAlchemy ORM models schemas/ — Pydantic request/response schemas services/ — Business logic (no HTTP or database details) repositories/ — Database access (SQLAlchemy sessions) core/ config.py — Settings via pydantic-settings database.py — Async session factory security.py — Auth utilities
## Python Standards
- Python 3.12. Type hints on all function signatures.
- `ruff` for linting and formatting (replaces black + flake8). Config in `pyproject.toml`.
- `mypy` for type checking. Strict mode enabled.
- Async functions throughout. No sync database calls. No `asyncio.run()` in request handlers.
- Pydantic v2 models for all request/response shapes. Do not use dicts where a model would be clearer.
## FastAPI Patterns
- Route functions are thin: validate input, call a service, return a schema.
- Dependency injection via `Depends()` for: auth, database sessions, configuration.
- All database sessions come from `Depends(get_db)`. Never create sessions manually in routes.
- HTTP exceptions: use `raise HTTPException(status_code=..., detail=...)`. Do not return error dicts.
- Response models defined in `models/schemas/`. Never return SQLAlchemy models directly from routes.
## Database
- Alembic for migrations. `alembic upgrade head` applies pending migrations.
- All schema changes: create a new migration with `alembic revision --autogenerate -m "description"`.
- Transactions: repositories are responsible for committing. Services call repositories and do not manage sessions directly.
- Parameterized queries via SQLAlchemy. No string interpolation.
## Testing
- `pytest` with `pytest-asyncio`. All test functions are `async def`.
- `httpx.AsyncClient` for endpoint integration tests.
- Fixtures in `tests/conftest.py`. Database fixtures use transactions that roll back after each test.
- `make test` — Run tests with coverage
- `make lint` — ruff + mypy
## Commands
- `uvicorn src.main:app --reload` — Development server
- `make test` — Tests
- `make lint` — Lint and type check
- `alembic upgrade head` — Apply migrations
- `docker compose up -d` — Start PostgreSQL locally
Common Pitfalls
Pitfall 1: Rules That Cannot Be Verified
If a rule cannot be checked programmatically, AI tools will forget it under pressure.
# Bad — unverifiable
Be careful about performance.
# Better — specific and checkable
Do not add new npm dependencies without running `bundlephobia` on the package first and confirming the bundle size impact is under 10KB.
Pitfall 2: Mixing Context, Constraints, and Process
AI tools read the file top to bottom. Context (what the project is) should come before constraints (what not to do) which should come before process (how to do things). Files that mix these freely cause the AI to apply the wrong frame to the wrong type of information.
# Good structure
## About This Project
[context]
## Architecture Rules
[constraints]
## Development Workflow
[process]
## Commands
[reference]
Pitfall 3: The Never-Updated File
A CLAUDE.md written six months ago that still mentions pnpm when the project migrated to bun, or still references v1 of a library that is now on v3, actively hurts you. The AI will follow the outdated instructions and generate broken code.
Fix: Add a ## Last Updated line with the date and schedule a monthly check. Treat your config files like documentation — if they are not maintained, they become technical debt.
## Meta
Last reviewed: 2026-04-25
Reviewer: @your-handle
Next review: 2026-07-01
Pitfall 4: One File for a Monorepo
A single root-level CLAUDE.md for a monorepo with 20+ packages will become too large to be useful and will mix concerns from different teams. Use the hierarchical approach from Template 3: shared context at root, team-specific rules at the package level.
Pitfall 5: Copy-Paste Without Customization
These templates are starting points. The commands, file paths, and conventions in your actual project will differ. An AI following a template that says pnpm test when your project uses make test will generate confusing error messages. Do the customization before committing the file.
Pitfall 6: Rules Without Rationale
For non-obvious rules, the AI benefits from understanding why:
# Bad
Do not use Prisma.
# Better
Do not use Prisma. This project uses raw SQL via `pg` for performance reasons
(we found Prisma's query generation was causing N+1 issues in our specific access patterns).
Use parameterized queries and the query builder in `src/lib/db.ts`.
Rules with rationale survive context window compression better than bare imperatives.
Composing Multiple Files
For complex setups (enterprise monorepo, multi-team, mixed tooling), here is the composition pattern that scales:
Layer 1: AGENTS.md at Root
Universal context. Any AI tool that touches this repo reads it. Keep it factual and focused on architecture, commands, and hard constraints. No tool-specific instructions here.
Layer 2: Root CLAUDE.md
Claude-specific behavior layered on top. Import AGENTS.md to avoid duplication:
@import AGENTS.md
## Claude-Specific Configuration
[Claude-specific rules that would mean nothing to Cursor or Codex]
Layer 3: Directory-Level CLAUDE.md
For monorepos or projects with different conventions per subdirectory. Claude Code reads the nearest CLAUDE.md and walks up the directory tree. Each sub-CLAUDE.md can be additive (just add rules for that directory) or can override specific parent rules.
Layer 4: .claude/rules/
For large CLAUDE.md files, split by concern:
.claude/
rules/
testing.md
security.md
database.md
Reference from CLAUDE.md:
@import .claude/rules/testing.md
@import .claude/rules/security.md
@import .claude/rules/database.md
.cursorrules for Cursor Users in a Multi-Tool Repo
If you have Cursor users in a repo that primarily uses AGENTS.md + CLAUDE.md, a minimal .cursorrules that imports or mirrors key content is enough:
# This project uses AGENTS.md for shared configuration.
# Read AGENTS.md at the repo root for architecture rules, conventions, and commands.
# Additional Cursor-specific settings:
[cursor-specific additions here]
FAQ
Q: Do I need all three files?
No. Most projects need one or two. If your whole team uses Claude Code, CLAUDE.md alone is sufficient. If you have mixed tooling, AGENTS.md alone covers 80% of use cases. The three-file setup is for complex environments where you need universal compatibility and Claude-specific depth.
Q: What happens if AGENTS.md and CLAUDE.md contradict each other?
Claude Code reads both and attempts to reconcile them. In practice, the more specific rule wins — if CLAUDE.md says “always ask before installing packages” and AGENTS.md says nothing about package installation, Claude Code follows the CLAUDE.md rule. If they genuinely contradict (one says do X, the other says do not do X), Claude Code will likely follow CLAUDE.md since it is the more specific-to-tool file. Avoid contradictions by treating AGENTS.md as the base and CLAUDE.md as additive.
Q: How long should the file be?
Shorter is better. A 300-line CLAUDE.md that tries to cover everything will have its important rules ignored because they get buried or cut from context. Target under 200 lines for most projects. For larger setups, split into .claude/rules/ and import what you need for the current task.
Q: Can I put secrets or credentials in CLAUDE.md?
No. CLAUDE.md is committed to your repository. It is public (or at minimum accessible to anyone with repo access). Reference the name and location of environment variables, not their values.
Q: My CLAUDE.md is getting large. How do I know what to cut?
Ask: “Would the AI do the wrong thing if this rule were not here?” If the answer is no — if the rule describes behavior that would happen anyway — cut it. The file should encode project-specific constraints, not general software engineering advice. Claude already knows how to write clean code; it does not need you to tell it to use meaningful variable names.
Q: Should AI-generated code be allowed to change CLAUDE.md itself?
Treat CLAUDE.md as an engineering document, not a living file for the AI to modify. If you want the AI to propose changes, have it output the proposed diff and you apply it manually. Allowing the AI to self-modify its configuration file is a pattern that has caused subtle drift in production setups.
Q: Does file placement matter for .cursorrules?
Yes. Cursor reads .cursorrules from the workspace root. If you have a monorepo, one root-level .cursorrules applies to all packages unless you also use .cursor/rules/ directory format, which supports per-directory scoping similar to how CLAUDE.md hierarchy works.
The templates here represent patterns that work at scale, not theoretical best practices. Start with the closest match, strip out anything that does not apply to your project, add the conventions your team actually uses, and revisit the file every few months as your stack evolves. A configuration file that accurately reflects your current project is worth ten times a comprehensive one that drifted six months ago.