Master AGENTS.md, Cursor Rules, and GitHub Copilot Instructions
Note: This guide is designed for both reading and audio consumption. All code examples and visual elements are explained in detail to work well in podcast format.
Agentic coding tools like Claude Code, Cursor, and GitHub Copilot can autonomously read files, execute commands, and make multi-file edits with minimal human intervention. The quality of their output depends entirely on the context you provide. This guide covers three primary approaches to context management: AGENTS.md (the universal standard), Cursor's .cursorrules format, and GitHub Copilot's custom instructions system. You'll learn evidence-based techniques for structuring context files, optimizing project organization, and implementing workflows that maximize agent effectiveness while maintaining code quality and security.
Modern agentic coding tools operate autonomously within your development environment:
Agent effectiveness is directly proportional to context quality. Without proper context, agents will:
This guide provides practical techniques for:
In the context of AI coding agents, "context" refers to all information available to the model when generating responses or making decisions. This includes:
Modern AI agents use several mechanisms to gather and utilize context:
Retrieval-Augmented Generation (RAG): Agents search through your codebase using embeddings to find relevant files and code snippets that might inform their response.
File System Analysis: Agents can read directory structures, analyze file relationships, and understand project organization.
Tool Integration: Through MCP servers and built-in capabilities, agents access external data sources, APIs, and documentation.
Token Window Management: Advanced agents automatically summarize or compact previous context when approaching token limits, maintaining continuity without losing critical information.
Traditional prompt engineering focuses on crafting individual requests to get desired outputs. Context engineering is a higher-level discipline that involves:
Context engineering recognizes that agents operate within an ecosystem of files, tools, and conventions—not just isolated prompts.
AGENTS.md is the emerging cross-tool standard for providing agent-specific instructions. It's a simple Markdown file at your repository root that works with Claude Code, Cursor, GitHub Copilot, and other agentic coding tools.
Advantages over tool-specific formats:
Comparison to README.md:
AGENTS.md files should be concise, human-readable Markdown with no required format. Effective files typically include:
1. Project Overview
# Project Name
Brief description of what the project does and its primary purpose.2. Technology Stack
## Tech Stack
- Backend: Python 3.11 with FastAPI
- Frontend: React 18 with TypeScript
- Database: PostgreSQL 15
- State Management: Zustand
- Testing: pytest, Vitest3. Code Style and Conventions
## Code Guidelines
### Do
- Use type hints in all Python functions
- Prefer functional components with hooks in React
- Use ES modules (import/export), not CommonJS
- Write unit tests for all business logic
### Don't
- Don't hard-code configuration values
- Don't use class components unless necessary
- Don't add dependencies without team approval4. Commands and Scripts
## Common Commands
- `npm run dev` - Start development server
- `npm run test` - Run test suite
- `npm run typecheck` - Run TypeScript type checker
- `npm run lint` - Run ESLint with auto-fix
- `make migrate` - Run database migrations5. Project Structure
## Architecture
- `src/components/` - Reusable UI components
- `src/pages/` - Page-level components (routes)
- `src/lib/` - Shared utilities and helpers
- `src/api/` - API client and data fetching
- `app/routes.tsx` - Application routing configuration
- `app/theme/tokens.ts` - Design system tokens6. Testing Requirements
## Testing
- All new features require unit tests
- Tests must pass before committing: `npm run test`
- Use test-driven development when possible
- Integration tests for API endpoints7. Examples and Anti-Patterns
## Good Examples
- See `Projects.tsx` for functional component patterns
- See `DashForm.tsx` for form implementation
- See `app/api/client.ts` for HTTP requests
## Anti-Patterns to Avoid
- Avoid class-based components like `Admin.tsx` (legacy)
- Don't use `any` type in TypeScript
- Don't mix MobX and Zustand in the same component8. Security and Permissions
## Security
- All API inputs must be validated
- Authentication required for all non-public routes
- Never commit secrets or API keys
- Use environment variables for configurationFor larger projects, AGENTS.md supports hierarchical structures:
/AGENTS.md - General project guidelines/packages/frontend/AGENTS.md - Frontend-specific rules/backend/api/AGENTS.md - API-specific conventionsPrecedence: Agents read the nearest AGENTS.md file in the directory tree, so local files override root-level instructions.
In Practice: Large repositories often contain dozens of AGENTS.md files, providing granular, context-specific instructions throughout the codebase.
Quick Start:
touch AGENTS.md# [Project Name]
## Overview
[One paragraph describing what this project does]
## Tech Stack
[List your main technologies]
## Commands
- [List 3-5 most common commands]
## Code Style
- [List 3-5 most important conventions]Ask your coding agent: "Review this AGENTS.md and suggest additional sections
based on this codebase"Be Specific and Actionable
❌ Poor: "Write good code"
✅ Good: "Use type hints for all function parameters and return values"
❌ Poor: "Follow React best practices"
✅ Good: "Use functional components with hooks; avoid class components"Provide Context, Not Just Rules
## State Management
We use Zustand for global state and React Context for component-level state.
Why: Zustand provides simpler patterns than Redux while being more performant
than Context for frequently updating global state.
Pattern: Create stores in `src/stores/` with clear slice boundaries.
Example: See `src/stores/authStore.ts`Include Commands with Explanations
## Running Tests
- `npm run test` - Run all tests (fast, parallel)
- `npm run test:watch` - Run tests in watch mode for development
- `npm run test:coverage` - Generate coverage report (required >80%)
Before committing: Run `npm run test` and ensure all pass.Point to Canonical Examples
## Component Patterns
Good examples:
- `src/components/DataTable.tsx` - Shows proper data fetching and error handling
- `src/components/Form/LoginForm.tsx` - Shows form validation pattern
Outdated patterns (don't copy):
- `src/components/legacy/OldUserList.tsx` - Uses deprecated class-based approachKeep It Concise
While AGENTS.md is becoming the standard, you may still encounter:
Migration Strategy:
# If you have existing tool-specific files:
mv .cursorrules AGENTS.md
# Or combine them:
cat CLAUDE.md .cursorrules >> AGENTS.md
# Then clean up duplicates and conflictsMaintaining Both: For teams in transition, you can maintain both:
Cursor is an AI-first code editor built on VS Code, offering sophisticated context management through multiple mechanisms:
Context Sources in Cursor:
Cursor supports a specialized .mdc (markdown with conventions) format for rules:
Basic Structure:
# Project: [Name]
## Code Style
- Use TypeScript strict mode
- Prefer const over let
- Use async/await over raw Promises
## Testing
- Jest for unit tests
- Playwright for E2E tests
- Minimum 80% code coverage
## Commands
- npm run dev - Development server
- npm test - Run testsAdvanced Features:
Rule Scope with Glob Patterns:
<rule>
name: api-security
globs: ["src/api/**/*.ts"]
All API endpoints must:
- Validate input with Zod schemas
- Require authentication unless explicitly public
- Return proper HTTP status codes
- Log all errors with context
</rule>Template Literals and Variables:
<rule>
name: context-info-display
Current context size: {context_size}
Remaining requests: {requests_remaining}
Note: These interpolate read-only values but can be unreliable
</rule>1. Agent Mode (Autonomous)
2. Ask Mode (Review Before Apply)
3. Manual Mode (Zero Autonomy)
4. Background Mode (Parallel Execution)
For organizations, Cursor offers centralized rule management:
Setup:
Use Cases:
1. Use @-mentions for Precision
@filename.ts explain the authentication flow
@folder/components add error boundaries to all components2. Leverage Docs Integration
Settings → Cursor Settings → Docs
Add: https://docs.your-framework.comNow agents can reference up-to-date documentation.
3. Enable LSP Integration Cursor uses Language Server Protocols for:
4. Manage Context Window with /clear
/clear # Resets conversation context between distinct tasks5. Create Checklists for Complex Tasks For multi-step features:
# Feature: User Authentication
## Checklist
- [ ] Create database migration
- [ ] Implement auth service
- [ ] Add API endpoints
- [ ] Write tests
- [ ] Update documentation
Agent: Work through this checklist, marking items as you complete them.Permission Management (YOLO Mode)
Configure which commands run automatically:
## Safety and Permissions
### Allowed without prompt:
- Reading files
- Running linters (eslint, prettier)
- Running single-file type checks
- Running single test files
### Require confirmation:
- npm/pip install
- git push
- Deleting files
- Running full build
- chmod operationsSandboxed Terminal (macOS)
Recent versions of Cursor run commands in a secure sandbox by default:
Custom Submit Keywords (Voice Mode)
Configure voice commands to trigger agent:
Settings → Voice → Custom Submit Keywords: "execute", "run it", "do it"Multi-Agent Workflows
Run separate agents for different concerns:
# Terminal 1: Agent for implementation
cursor agent "Implement user authentication"
# Terminal 2: Agent for testing
cursor agent "Write comprehensive tests for auth module"
# Terminal 3: Agent for documentation
cursor agent "Update API docs for new auth endpoints"Each agent works in isolated git worktree, preventing conflicts.
GitHub Copilot operates differently from autonomous agents like Cursor or Claude Code:
Context Sources:
.github/copilot-instructions.md.github/instructions/*.instructions.md#file, #symbol, or @workspaceImportant Limitations:
Repository-Wide Instructions:
Create .github/copilot-instructions.md at repository root:
# Contoso Pet Adoption Platform
## Overview
Web application connecting pet adoption agencies with potential adopters.
## Technology Stack
- Backend: Node.js with Express, TypeScript
- Frontend: React 18 with Next.js 14
- Database: PostgreSQL with Prisma ORM
- State: React Context + Tanstack Query
- Styling: Tailwind CSS
- Testing: Jest (unit), Playwright (E2E)
## Code Conventions
### TypeScript
- Use strict mode
- Always define explicit return types
- Prefer interfaces over type aliases for object shapes
- Use type guards for narrowing
### React
- Functional components with hooks only
- Custom hooks in `src/hooks/`
- Props interfaces named `ComponentNameProps`
- Use React.memo for expensive renders
### API Design
- RESTful endpoints following `/api/v1/resource` pattern
- Always validate input with Zod schemas
- Return consistent error format: `{ error: string, code: string }`
- Use HTTP status codes correctly (200, 201, 400, 401, 404, 500)
### Testing
- Unit test all business logic
- Integration tests for API endpoints
- E2E tests for critical user flows
- Minimum 80% code coverage required
## Project Structure
- `src/components/` - Reusable UI components
- `src/pages/` - Next.js page routes
- `src/lib/` - Utilities and helpers
- `src/api/` - API route handlers
- `src/hooks/` - Custom React hooks
- `prisma/` - Database schema and migrations
## Commands
- `npm run dev` - Start development server (localhost:3000)
- `npm run build` - Production build
- `npm test` - Run all tests
- `npm run test:watch` - Tests in watch mode
- `npm run lint` - ESLint with auto-fix
- `npm run type-check` - TypeScript validation
- `npx prisma migrate dev` - Create/apply migrations
## Security Guidelines
- Never commit environment variables or secrets
- Validate all user input server-side
- Use parameterized queries (Prisma prevents SQL injection)
- Implement rate limiting on public endpoints
- Use HTTPS only in production
## Examples
Good patterns:
- `src/components/PetCard.tsx` - Component structure
- `src/api/pets/route.ts` - API endpoint pattern
- `src/hooks/usePetSearch.tsx` - Custom hook pattern
Avoid:
- `src/components/legacy/OldPetList.tsx` - Outdated class-based approachEnable in VS Code:
Tools → Options → GitHub → Copilot → Copilot Chat →
☑ Enable custom instructions to be loaded from .github/copilot-instructions.mdFor different sections of your codebase with different requirements:
Structure:
.github/
instructions/
api.instructions.md # Applies to src/api/**
components.instructions.md # Applies to src/components/**
tests.instructions.md # Applies to **/*.test.tsExample - api.instructions.md:
---
path: src/api/**/*.ts
---
# API Development Guidelines
## Required Patterns
1. Input validation using Zod schemas
2. Authentication middleware for non-public routes
3. Error handling with try-catch
4. Structured logging with correlation IDs
## Example
\```typescript
import { z } from 'zod';
import { authMiddleware } from '@/middleware/auth';
const CreatePetSchema = z.object({
name: z.string().min(1),
species: z.enum(['dog', 'cat', 'other']),
age: z.number().positive()
});
export async function POST(req: Request) {
try {
const body = await req.json();
const validated = CreatePetSchema.parse(body);
// Implementation...
return Response.json({ data: result }, { status: 201 });
} catch (error) {
if (error instanceof z.ZodError) {
return Response.json({ error: 'Invalid input' }, { status: 400 });
}
throw error;
}
}
\```Combining Instructions: When working on a file that matches path-specific instructions:
In VS Code Insiders, set personal preferences:
Settings → Extensions → GitHub Copilot → Edit User InstructionsExample User Instructions:
# Personal Coding Preferences
## General Style
- Prefer descriptive variable names over abbreviations
- Add comments explaining "why" not "what"
- Use early returns to reduce nesting
## Language Preferences
- TypeScript over JavaScript when possible
- Async/await over Promises.then()
- Template literals over string concatenation
## Testing Philosophy
- Write tests first when behavior is clear
- Include edge cases
- Test error conditionsPrecedence Issues: If user instructions conflict with repository instructions, Copilot may behave unpredictably. Keep user instructions general and let repository instructions be specific.
For frequently-used prompts, create templates:
Location: .github/prompts/*.prompt.md
Example - feature.prompt.md:
# Feature Implementation Template
I need to implement a new feature: {FEATURE_NAME}
Requirements:
{LIST_REQUIREMENTS}
Please:
1. Analyze relevant files using #codebase
2. Propose an implementation approach
3. Identify files that need changes
4. Create a checklist for implementation
5. Ask clarifying questions before proceeding
Follow all guidelines in copilot-instructions.md.Usage in Chat:
Type: #prompt:feature
Fill in: {FEATURE_NAME} and {LIST_REQUIREMENTS}Or use the ➕ icon in chat to select prompt files.
1. Keep Relevant Tabs Open
Copilot prioritizes open tabs, so:
✅ Open: The file you're editing + related test file
✅ Open: Interface definitions used in current file
✅ Open: Example implementations
❌ Don't: Keep 20+ tabs open (dilutes context)
❌ Don't: Have unrelated projects open simultaneously2. Use Explicit References
In Copilot Chat:
# Good - Explicit context
#file:src/auth/login.ts Explain the authentication flow
# Better - Multiple relevant files
#file:src/auth/login.ts
#file:src/auth/middleware.ts
How do these work together?
# Best - With codebase search
@workspace Where are authentication errors handled?3. Maintain README.md
While custom instructions are for agents, README.md still matters:
# Quick Start
## Prerequisites
- Node.js 18+
- PostgreSQL 15+
## Setup
\```bash
npm install
cp .env.example .env
# Edit .env with your database credentials
npx prisma migrate dev
npm run dev
\```Copilot uses README.md to understand setup context.
4. Leverage Slash Commands
Built-in shortcuts for common tasks:
/explain # Explain selected code
/fix # Suggest fixes for problems
/tests # Generate test cases
/doc # Generate documentation
/help # Show available commands5. Workspace Context
Use @workspace for codebase-wide queries:
@workspace Find all API endpoints that return user data
@workspace Show me examples of form validation
@workspace Where is error logging configured?Break Down Complex Tasks:
❌ Poor: "Implement user authentication"
✅ Better:
1. "Show me where authentication is configured"
2. "Generate JWT token signing function"
3. "Create middleware to verify tokens"
4. "Add authentication to user routes"Provide Examples:
I need a function similar to #file:src/utils/formatDate.ts
but for formatting currency values.
Input: number (cents), output: string like "$12.34"Be Specific About Requirements:
Create a React component for displaying product cards.
Requirements:
- Image with fallback
- Title (max 2 lines, ellipsis)
- Price (formatted as currency)
- "Add to Cart" button
- Loading state
- Error state
- Must be mobile responsive
- Use Tailwind CSS
- TypeScript with proper typesIterate Based on Output:
First prompt: "Create a login form component"
Review output, then:
"Add email validation using Zod"
"Add loading state during submission"
"Add error message display"These principles apply regardless of which agentic coding tool you're using.
Principle: Keep context files close to the code they describe.
Structure:
my-project/
├── AGENTS.md # Root-level guidelines
├── .github/
│ ├── copilot-instructions.md # GitHub Copilot
│ └── instructions/ # Path-specific
│ ├── api.instructions.md
│ └── ui.instructions.md
├── src/
│ ├── api/
│ │ ├── AGENTS.md # API-specific rules
│ │ └── README.md # Human docs
│ └── components/
│ ├── AGENTS.md # Component guidelines
│ └── README.md
└── docs/ # Detailed human docs
├── architecture.md
└── deployment.mdBenefits:
AI agents learn better from concrete examples than abstract rules.
Less Effective:
## Component Structure
Components should be modular, reusable, and follow single responsibility principle.
Use composition over inheritance. Separate concerns.More Effective:
## Component Patterns
Good example - Clean, reusable:
- `src/components/UserAvatar.tsx`
Shows:
- Single responsibility (just avatar display)
- Props interface with TypeScript
- Loading and error states
- Accessible image with alt text
Bad example - Don't copy:
- `src/components/legacy/UserDashboard.tsx`
Issues:
- God component (does too much)
- Mixed concerns (data + UI)
- Poor prop namingPattern:
Don't repeat information unnecessarily:
Instead of duplicating:
# AGENTS.md
TypeScript must use strict mode
...
# README.md
TypeScript must use strict mode
...
# .github/copilot-instructions.md
TypeScript must use strict modeUse hierarchy and references:
# AGENTS.md (canonical source)
## TypeScript
- Strict mode enabled in tsconfig.json
- Explicit return types required
- No `any` type without comment justification
# README.md
## Development
See AGENTS.md for detailed coding guidelines.
# .github/copilot-instructions.md
Follow all conventions specified in ../AGENTS.mdTests serve as excellent context for agents:
1. Tests as Documentation
describe('formatCurrency', () => {
it('formats cents as dollars with two decimals', () => {
expect(formatCurrency(1234)).toBe('$12.34');
});
it('handles zero correctly', () => {
expect(formatCurrency(0)).toBe('$0.00');
});
it('handles negative values', () => {
expect(formatCurrency(-500)).toBe('-$5.00');
});
});This test file tells agents:
2. Test-First Workflow for Agents
In your AGENTS.md or instructions:
## Development Workflow
For new features:
1. Write failing tests defining expected behavior
2. Commit the tests
3. Implement the feature to make tests pass
4. Refactor with tests as safety net
Agent: When implementing features, always check for existing tests first.Strong typing provides context automatically:
TypeScript Example:
// This interface tells agents exactly what's expected
interface CreateUserRequest {
email: string; // Agents know this must be a string
age?: number; // Agents know this is optional
role: 'admin' | 'user'; // Agents know the exact valid values
}
// Return type tells agents what to provide
async function createUser(data: CreateUserRequest): Promise<User> {
// Implementation
}Python Example:
from typing import Literal, Optional
from pydantic import BaseModel, EmailStr
class CreateUserRequest(BaseModel):
email: EmailStr # Agents know this must be valid email
age: Optional[int] = None
role: Literal['admin', 'user'] # Agents know exact valid valuesIn Instructions:
## Type Safety
- Use strict types in TypeScript/Python
- Define Pydantic models for Python API requests
- Zod schemas for TypeScript runtime validation
- No `any` or `unknown` without explicit justification
Types serve as inline documentation for both humans and AI.Help agents understand the big picture:
System Overview:
## Architecture
This is a three-tier web application:
1. **Frontend** (React/Next.js in `/src/app`)
- Server components by default
- Client components marked with 'use client'
- API calls via `/src/lib/api-client.ts`
2. **Backend API** (Express in `/api`)
- RESTful endpoints
- JWT authentication
- PostgreSQL via Prisma
3. **Database** (PostgreSQL)
- Schema in `/prisma/schema.prisma`
- Migrations in `/prisma/migrations`
Data Flow:
Frontend → API Client → Backend API → Database
← JSON Response ← ← Query ResultComponent Dependencies:
## Module Structure
Feature modules are self-contained:src/features/ auth/ components/ # Auth-specific UI hooks/ # Auth hooks (useAuth, useLogin) api/ # Auth API calls types/ # Auth TypeScript types
products/ components/ hooks/ api/ types/
Rule: Features should not import from other features.
Shared code goes in src/lib/.Make configuration discoverable to agents:
Environment Variables:
## Configuration
Copy `.env.example` to `.env` and configure:
Required:
- `DATABASE_URL` - PostgreSQL connection string
- `JWT_SECRET` - Secret for signing JWT tokens
- `API_URL` - Backend API URL (e.g., http://localhost:3000)
Optional:
- `LOG_LEVEL` - Logging verbosity (default: info)
- `RATE_LIMIT` - Requests per minute (default: 100)
Never commit `.env` to version control.Feature Flags:
## Feature Flags
Located in `src/config/features.ts`:
\```typescript
export const features = {
newDashboard: process.env.FEATURE_NEW_DASHBOARD === 'true',
aiSearch: process.env.FEATURE_AI_SEARCH === 'true'
};
\```
To add a new feature flag:
1. Add to features object
2. Add to .env.example
3. Guard feature code with flag check
4. Document in this sectionTeach agents how to handle errors in your style:
## Error Handling
### Frontend
\```typescript
// Pattern: Try-catch with user-friendly messages
async function loadUserData() {
try {
const data = await api.users.get();
return { success: true, data };
} catch (error) {
if (error instanceof ApiError) {
// User-friendly message for known errors
showToast('error', error.userMessage);
} else {
// Generic message for unexpected errors
showToast('error', 'Something went wrong');
logError(error); // Log for debugging
}
return { success: false, error };
}
}
\```
### Backend
\```typescript
// Pattern: Structured error responses
class ApiError extends Error {
constructor(
public code: string,
public message: string,
public statusCode: number
) {
super(message);
}
}
// Usage in route handlers
if (!user) {
throw new ApiError(
'USER_NOT_FOUND',
'User not found',
404
);
}
\```
All errors are caught by middleware that returns:
\```json
{
"error": "User-friendly message",
"code": "ERROR_CODE",
"requestId": "uuid"
}
\```Maintenance Routine:
Signs Context Needs Updating:
Version Control:
# Context files should be committed like any code
git add AGENTS.md .github/copilot-instructions.md
git commit -m "Update context: Add new API authentication pattern"Beyond just writing good context files, you can structure your codebase to be inherently more understandable to AI agents.
Agents navigate more effectively with fewer directory levels:
Agent-Unfriendly:
packages/
ui-components/
data-models/
api-client/
utils/
form-validation/
state-management/
analytics/
logger/
config/
types/
...15 more micro-packagesAgent-Friendly:
packages/
frontend/ # UI + state + components
backend/ # API + services + database
shared/ # Common types + utilitiesYou can still organize within these packages, just avoid unnecessary top-level segmentation.
Keep related concerns together:
Instead of organizing by type:
src/
components/ # All components
hooks/ # All hooks
types/ # All types
utils/ # All utilitiesOrganize by feature:
src/
features/
auth/
LoginForm.tsx
useAuth.ts
auth.types.ts
auth.utils.ts
products/
ProductCard.tsx
ProductList.tsx
useProducts.ts
products.types.tsAgents find related code more easily when it's together.
Long, clear names beat short, cryptic ones for agents:
Agent-Unfriendly:
// Short names require context to understand
function proc(d: any) { }
const usr = { n: 'John', a: 25 };Agent-Friendly:
// Self-documenting code
function processUserData(userData: UserData) { }
const authenticatedUser = {
fullName: 'John Doe',
age: 25
};Simpler code is better for agents:
Avoid:
// Clever but opaque
const result = data.reduce((a, c) =>
({ ...a, [c.id]: { ...c, ...a[c.id] } }), {});Prefer:
// Explicit and clear
const resultById = new Map<string, Item>();
for (const item of data) {
const existing = resultById.get(item.id);
resultById.set(item.id, {
...existing,
...item
});
}Agents understand imperative code better than functional tricks.
Use Plain SQL Instead of ORM Magic:
Agents work better with explicit database queries:
// ❌ Hard for agents to trace
const users = await User.findAll({
include: [{
model: Post,
where: { published: true },
include: [Comment]
}]
});
// ✅ Clear SQL agents can match with logs
const users = await db.query(`
SELECT
users.*,
posts.*,
comments.*
FROM users
LEFT JOIN posts ON posts.user_id = users.id
AND posts.published = true
LEFT JOIN comments ON comments.post_id = posts.id
`);Benefits:
Keep Permission Checks Local:
// ❌ Agent might forget to check permissions
// Permission checked in middleware in different file
async function deletePost(postId: string) {
return db.posts.delete({ where: { id: postId } });
}
// ✅ Permission check is obvious
async function deletePost(userId: string, postId: string) {
const post = await db.posts.findUnique({ where: { id: postId } });
// Clear permission check
if (post.authorId !== userId) {
throw new ForbiddenError('Cannot delete others posts');
}
return db.posts.delete({ where: { id: postId } });
}Each package/module adds cognitive overhead:
Signs of Over-Segmentation:
Simplification Strategy:
Establish and follow patterns throughout:
Route Handler Pattern:
// Every route handler follows this pattern:
export async function POST(req: Request) {
// 1. Parse and validate input
const body = await req.json();
const validated = CreateItemSchema.parse(body);
// 2. Authentication/authorization
const user = await authenticate(req);
if (!canCreateItem(user)) {
return forbidden();
}
// 3. Business logic
const item = await itemService.create(validated, user.id);
// 4. Return success response
return Response.json({ data: item }, { status: 201 });
}Document this in AGENTS.md, and agents will follow it automatically.
For Go Projects:
Go is particularly well-suited for agentic coding:
## Why Go Works Well with AI Agents
1. **Context System**: Explicit context.Context flows through code
2. **Simple Testing**: `go test ./...` just works
3. **No Magic**: Explicit error handling, no hidden control flow
4. **Standard Library**: Agents know common patterns
5. **Fast Builds**: Quick feedback loops
Example Agent-Friendly Go:
\```go
// Clear function signature with context
func CreateUser(ctx context.Context, req CreateUserRequest) (*User, error) {
// Explicit error handling
if err := validateUser(req); err != nil {
return nil, fmt.Errorf("validation failed: %w", err)
}
// Clear database operation
user, err := db.InsertUser(ctx, req)
if err != nil {
return nil, fmt.Errorf("db insert failed: %w", err)
}
return user, nil
}
\```For Python Projects:
## Python Best Practices for Agents
Use type hints everywhere:
\```python
from typing import Optional, List
from pydantic import BaseModel
class User(BaseModel):
id: int
email: str
name: Optional[str] = None
def get_users(limit: int = 10) -> List[User]:
# Agents understand this signature completely
pass
\```
Use Pydantic for validation:
- Agents can see validation rules in model definition
- Runtime validation catches errors early
- Automatic JSON serializationEffective workflows that leverage agent capabilities:
Most effective pattern for complex tasks:
Step 1: Research & Read (No Writing)
Prompt: "Read the relevant files for implementing user authentication.
List what files are involved and how they connect.
Don't write any code yet."Agent will:
Step 2: Plan & Outline
Prompt: "Based on what you read, create a detailed implementation plan for
adding JWT authentication. Use extended thinking to create a thorough plan."Agent will:
Step 3: Implement & Verify
Prompt: "Implement the plan you created. After each file, verify your work
is consistent with the plan. When done, run the tests and create a PR."Agent will:
Why This Works:
Particularly powerful workflow:
Pattern:
1. Agent writes failing tests based on requirements
2. Commit tests to version control
3. Agent implements code to pass tests
4. Agent refactors with tests as safety netExample Session:
Developer: "Implement a shopping cart that can add items,
remove items, and calculate totals with tax."
Agent: "I'll start by writing tests for this functionality..."
[Agent creates CartManager.test.ts]
[Agent runs tests - all fail as expected]
[Agent commits tests]
Agent: "Tests committed. Now implementing CartManager to pass tests..."
[Agent implements CartManager.ts]
[Agent runs tests iteratively]
[All tests pass]
Agent: "Implementation complete. All tests passing.
Ready for code review."For complex implementations:
Setup:
## Agent Instructions for Feature Implementation
1. Write implementation code
2. Run `npm test` immediately
3. If tests fail, analyze failures and fix
4. Repeat until all tests pass
5. Only then move to next part of feature
Never proceed with failing tests.Agent follows this loop automatically:
Write code → Run tests → Fix failures → Write more code → Run tests → ...For long-running operations:
Use Case: Large-scale refactoring, comprehensive test generation
# Start background agent
cursor agent --background "Refactor all class components to functional components"
# Continue working on other tasks
# Agent operates in isolated worktree
# Check progress
cursor agent --status
# Review when complete
cursor agent --reviewBest Practices:
Run multiple agents simultaneously for different concerns:
Example: New Feature Development
# Terminal 1: Implementation
cursor agent "Implement user profile editing"
# Terminal 2: Testing
cursor agent "Write comprehensive tests for profile editing"
# Terminal 3: Documentation
cursor agent "Document the profile API in OpenAPI spec"Each agent works in isolation, then you merge results.
Manage context window effectively:
When to Clear Context:
Use `/clear` between:
- Unrelated tasks
- When switching to different part of codebase
- After completing a feature
- When agent seems "confused" by old contextWhen to Keep Context:
Keep context when:
- Iterating on same problem
- Related tasks in same area
- Building on previous work
- Agent needs to remember decisions madeCreate detailed specs before coding:
Workflow:
Example Spec:
# Feature: User Password Reset
## User Story
As a user who forgot their password,
I want to request a password reset link,
So that I can regain access to my account.
## Requirements
1. User enters email address
2. System sends reset link if email exists
3. Link expires after 1 hour
4. Link is single-use
5. User sets new password via link
## Acceptance Criteria
- [ ] Reset link email sent to valid addresses
- [ ] No error shown for invalid addresses (security)
- [ ] Link contains secure token
- [ ] Token expires after 1 hour
- [ ] Token invalidated after use
- [ ] New password meets complexity requirements
## Technical Implementation
- POST /api/auth/request-reset
- POST /api/auth/reset-password
- Database: password_reset_tokens table
- Email service integration
## Security Considerations
- Rate limit reset requests (5 per hour per IP)
- Don't reveal if email exists
- Use cryptographically secure tokens
- Invalidate all existing sessions on resetFor complex multi-step tasks:
Create Checklist:
# Implement Payment Processing
## Database
- [ ] Create payments table migration
- [ ] Add foreign key to orders
- [ ] Add indexes on user_id and created_at
## Backend
- [ ] Create Payment model
- [ ] Implement Stripe integration
- [ ] Add webhook handler for payment events
- [ ] Add payment status API endpoint
## Frontend
- [ ] Create CheckoutForm component
- [ ] Add Stripe Elements integration
- [ ] Handle payment success/failure
- [ ] Update order status display
## Testing
- [ ] Unit tests for payment model
- [ ] Integration tests for Stripe API
- [ ] E2E test for complete checkout flow
## Documentation
- [ ] API documentation
- [ ] Webhook setup guide
- [ ] Environment variables guideAgent Usage:
"Work through this checklist systematically.
Mark each item complete as you finish it.
Ask for review before moving to next section."Critical considerations when giving agents autonomy:
Define Clear Boundaries:
## Agent Permissions
### ✅ Allowed Without Approval
- Read any file in repository
- Run linters (eslint, prettier, mypy)
- Run type checkers (tsc --noEmit, mypy)
- Run single test files
- View logs
- Search documentation
### ⚠️ Requires Confirmation
- Installing npm/pip packages
- Modifying package.json/requirements.txt
- Running full test suite (time-consuming)
- Running database migrations
- Making git commits
- Opening pull requests
### ❌ Never Allowed
- git push to main/master
- Deleting files outside src/
- Modifying CI/CD configurations
- chmod/chown operations
- Accessing environment variables
- Making API calls to productionCursor's Sandboxed Terminal (macOS):
Automatically enabled by default:
Configure Allowlist:
## Approved Commands
- npm/pnpm/yarn (install, test, build)
- python/pip
- git (status, diff, log, commit, branch)
- docker-compose (up -d, down, logs)
All other commands require approval.Claude Code Safety:
## Safety Practices
Before running sensitive commands, Claude Code will:
1. Show you the exact command
2. Explain what it will do
3. Wait for your approval
You can mark commands as always-allowed in config.Never merge agent-generated code without review:
Review Checklist:
## Agent-Generated Code Review
Security:
- [ ] No hardcoded secrets or credentials
- [ ] Input validation present
- [ ] Authentication/authorization checks
- [ ] No SQL injection vulnerabilities
- [ ] No XSS vulnerabilities
Quality:
- [ ] Tests written and passing
- [ ] Error handling appropriate
- [ ] Code follows project conventions
- [ ] No unnecessary dependencies added
- [ ] Performance acceptable
Architecture:
- [ ] Follows established patterns
- [ ] Doesn't break abstractions
- [ ] Module boundaries respected
- [ ] No circular dependencies introducedNever Let Agents Handle Secrets:
## Security: Secrets and Credentials
❌ NEVER commit:
- API keys
- Database passwords
- JWT secrets
- Private keys
- OAuth client secrets
✅ ALWAYS use:
- Environment variables
- Secret management services (Vault, AWS Secrets Manager)
- .env files (added to .gitignore)
Agent: If you need a secret value, ask the user to provide it via
environment variable. Never write actual secret values in code.Example Pattern:
// ❌ Don't do this
const API_KEY = 'sk-abc123...';
// ✅ Do this
const API_KEY = process.env.STRIPE_API_KEY;
if (!API_KEY) {
throw new Error('STRIPE_API_KEY environment variable not set');
}Manage API costs with agents:
Set Expectations:
## Agent Token Usage
Be mindful of costs:
- Prefer reading files over asking agent to search
- Use `/clear` to reset context when switching tasks
- Avoid sending large files to chat unnecessarily
- Use `@file` references instead of pasting code
For Cursor:
- Agent mode uses more tokens than Ask mode
- Background mode can use significant tokens
- Review token usage in Settings → UsageTrack agent actions:
## Audit Requirements
For important projects:
1. Review all git commits made by agents
2. Document major agent-generated changes
3. Tag commits with [agent] prefix
4. Keep agent conversation transcripts
Example commit message:[agent] Add JWT authentication middleware
Generated by: Claude Code Session: auth-feature-implementation Reviewed by: @username
Real-world examples of effective agent context:
AGENTS.md:
# FastAPI User Management API
## Overview
REST API for user management with JWT authentication.
## Tech Stack
- Python 3.11
- FastAPI 0.104
- PostgreSQL 15 with SQLAlchemy 2.0
- Pydantic v2 for validation
- pytest for testing
- Alembic for migrations
## Project Structuresrc/ api/ # API route handlers users.py auth.py models/ # SQLAlchemy models schemas/ # Pydantic schemas services/ # Business logic db/ # Database connection config.py # Configuration tests/ test_users.py test_auth.py
## Code Standards
### FastAPI Routes
\```python
# Pattern for all routes:
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
router = APIRouter(prefix="/api/v1/users", tags=["users"])
@router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(
user_in: UserCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
# Validate input (automatic with Pydantic)
# Check permissions
# Business logic via service layer
# Return response
\```
### Database Models
- All models inherit from Base
- Use `created_at` and `updated_at` timestamps
- Define clear relationships with back_populates
- Add indexes on commonly queried columns
### Pydantic Schemas
- Separate schemas for Create, Update, and Response
- Use ConfigDict for ORM mode
- Validate emails with EmailStr
- Document fields with Field(description="...")
## Commands
- `uvicorn src.main:app --reload` - Development server
- `pytest` - Run all tests with coverage
- `alembic revision --autogenerate -m "message"` - Create migration
- `alembic upgrade head` - Apply migrations
- `mypy src/` - Type checking
## Testing
Every route must have:
1. Happy path test
2. Validation error test (400)
3. Unauthorized test (401)
4. Not found test (404)
Use pytest fixtures for:
- Database session
- Test client
- Mock authenticated user
## Security
- All routes require authentication unless explicitly public
- Use `get_current_user` dependency
- Hash passwords with bcrypt
- JWT tokens expire in 30 minutes
- Rate limit: 100 requests/minute per IP
## Environment Variables
Required in .env:
- DATABASE_URL
- SECRET_KEY (for JWT)
- ALGORITHM="HS256"
## Common Patterns
Good example:
- `src/api/users.py` - Route structure
- `src/services/user_service.py` - Business logic separation
- `tests/test_users.py` - Comprehensive testing
Avoid:
- Putting business logic directly in routes
- Using dict instead of Pydantic models
- Skipping error handling.github/copilot-instructions.md:
# E-Commerce Frontend
## Overview
Next.js 14 e-commerce application with server and client components.
## Tech Stack
- Next.js 14 (App Router)
- React 18
- TypeScript 5
- Tailwind CSS
- Zustand (global state)
- Tanstack Query (data fetching)
- Zod (validation)
## Architecture
### Server vs Client Components
Default to server components unless you need:
- Event handlers (onClick, onChange)
- React hooks (useState, useEffect)
- Browser APIs (localStorage, etc.)
Mark client components with:
\```typescript
'use client';
\```
### Data Fetching
- Server Components: Fetch directly in component
- Client Components: Use Tanstack Query
Example server component:
\```typescript
// app/products/page.tsx
async function ProductsPage() {
const products = await fetchProducts(); // Direct fetch
return <ProductList products={products} />;
}
\```
Example client component:
\```typescript
// components/AddToCartButton.tsx
'use client';
export function AddToCartButton({ productId }: Props) {
const { mutate } = useMutation({
mutationFn: (id: string) => addToCart(id),
});
return <button onClick={() => mutate(productId)}>Add to Cart</button>;
}
\```
## Component Patterns
### File Structure
\```
components/
ProductCard/
ProductCard.tsx # Main component
ProductCard.test.tsx # Tests
index.ts # Re-export
\```
### Component Template
\```typescript
interface ProductCardProps {
product: Product;
onAddToCart?: (id: string) => void;
}
export function ProductCard({ product, onAddToCart }: ProductCardProps) {
return (
<div className="...">
{/* Implementation */}
</div>
);
}
\```
### TypeScript
- Props interfaces named `ComponentNameProps`
- Export interfaces if used elsewhere
- Use `React.FC` sparingly (prefer explicit typing)
- No `any` type without comment explanation
## Styling
### Tailwind
- Use Tailwind utility classes
- Custom styles in `app/globals.css` only when necessary
- Design tokens in `tailwind.config.ts`
### Responsive Design
- Mobile-first approach
- Use Tailwind breakpoints: `sm:`, `md:`, `lg:`, `xl:`
## State Management
### Local State (within component)
\```typescript
const [count, setCount] = useState(0);
\```
### Shared State (between components)
\```typescript
// stores/cartStore.ts
import { create } from 'zustand';
interface CartStore {
items: CartItem[];
addItem: (item: CartItem) => void;
removeItem: (id: string) => void;
}
export const useCartStore = create<CartStore>((set) => ({
items: [],
addItem: (item) => set((state) => ({
items: [...state.items, item]
})),
removeItem: (id) => set((state) => ({
items: state.items.filter(i => i.id !== id)
})),
}));
\```
## API Integration
### Client-Side Data Fetching
\```typescript
import { useQuery } from '@tanstack/react-query';
function useProducts() {
return useQuery({
queryKey: ['products'],
queryFn: async () => {
const res = await fetch('/api/products');
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
},
});
}
\```
### Form Handling
\```typescript
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
type FormData = z.infer<typeof schema>;
function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
resolver: zodResolver(schema),
});
const onSubmit = (data: FormData) => {
// Handle submission
};
return <form onSubmit={handleSubmit(onSubmit)}>...</form>;
}
\```
## Testing
### Component Tests (Vitest + React Testing Library)
\```typescript
import { render, screen, fireEvent } from '@testing-library/react';
import { ProductCard } from './ProductCard';
describe('ProductCard', () => {
it('displays product information', () => {
const product = { id: '1', name: 'Test', price: 100 };
render(<ProductCard product={product} />);
expect(screen.getByText('Test')).toBeInTheDocument();
});
it('calls onAddToCart when button clicked', () => {
const handleAdd = vi.fn();
const product = { id: '1', name: 'Test', price: 100 };
render(<ProductCard product={product} onAddToCart={handleAdd} />);
fireEvent.click(screen.getByRole('button'));
expect(handleAdd).toHaveBeenCalledWith('1');
});
});
\```
## File Organization
### Good Examples
- `app/(shop)/products/page.tsx` - Server component with data fetching
- `components/ProductCard/ProductCard.tsx` - Reusable component
- `lib/api-client.ts` - Centralized API calls
- `hooks/useProducts.ts` - Custom data fetching hook
### Patterns to Avoid
- `components/old/ClassComponent.tsx` - Class-based (legacy)
- Mixing server and client component code
- Prop drilling more than 2 levels (use context or Zustand)
## Commands
- `npm run dev` - Development server (port 3000)
- `npm run build` - Production build
- `npm run test` - Run tests
- `npm run test:watch` - Tests in watch mode
- `npm run lint` - ESLint
- `npm run type-check` - TypeScript validation
## Environment Variables
\```env
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_STRIPE_KEY=pk_test_...
\```
Variables prefixed with `NEXT_PUBLIC_` are exposed to the browser.Root AGENTS.md:
# Company Platform Monorepo
## Structure
- `/apps/web` - Customer-facing Next.js app
- `/apps/admin` - Internal admin dashboard
- `/apps/api` - Backend API (NestJS)
- `/packages/ui` - Shared UI components
- `/packages/db` - Database schema and client
- `/packages/config` - Shared configurations
Each subdirectory has its own AGENTS.md with specific instructions.
## Global Rules
- TypeScript everywhere
- Shared types in `/packages/types`
- Testing required (>80% coverage)
- Git: Feature branches from `develop`, PRs to `develop`
- Commits: Conventional commits (feat:, fix:, docs:, etc.)
## Commands (from root)
- `pnpm install` - Install all dependencies
- `pnpm build` - Build all packages
- `pnpm test` - Test all packages
- `pnpm dev --filter web` - Run web app only
- `pnpm dev --filter api` - Run API only
## Cross-Package Dependencies
When modifying shared packages:
1. Update package code
2. Run tests in package
3. Update dependent apps/packages
4. Run tests in dependentsapps/web/AGENTS.md:
# Web App (Customer Frontend)
Inherits rules from root AGENTS.md.
## Additional Rules
- All pages are server components by default
- Client components in `components/client/`
- Use `@workspace/ui` for shared components
- Use `@workspace/db` for data fetching
- Public-facing, must be accessible (WCAG AA)
## Specific Commands
- `pnpm dev` - Start at localhost:3000
- `pnpm build` - Production build
- `pnpm test:e2e` - Playwright E2E tests
## Feature Flags
Check `/lib/features.ts` before implementing features:
- newCheckout
- aiProductRecommendationsapps/api/AGENTS.md:
# API Backend
Inherits rules from root AGENTS.md.
## Additional Rules
- NestJS modules for each domain
- JWT auth on all routes except /health
- Swagger docs auto-generated
- Use `@workspace/db` Prisma client
## Commands
- `pnpm dev` - Start at localhost:8000
- `pnpm test` - Jest unit tests
- `pnpm test:e2e` - E2E API tests
- `pnpm migration:create` - New Prisma migration
## Security
- Rate limiting: 100 req/min per IP
- CORS: Only allow configured origins
- All inputs validated with class-validatorWeek 1:
Week 2: 4. Add tool-specific instructions (Cursor or Copilot) 5. Implement test-driven development with agent 6. Document 3 good examples in your codebase
Month 1: 7. Expand AGENTS.md based on agent behavior 8. Add path-specific instructions for key areas 9. Train team on agent best practices
Month 3: 10. Establish team workflows 11. Measure productivity improvements 12. Refine context files based on real usage
Documentation:
Communities:
Tools:
Success with agentic coding requires structured approaches to project organization, documentation, and workflows. The practices in this guide come from teams successfully using agentic tools in production environments.
Start small, iterate based on results, and gradually expand your use of AI agents. Focus on providing clear context, and you'll see immediate improvements in agent output quality.
Effective development now combines human creativity and architectural thinking with AI capability for rapid implementation. By mastering context engineering, you ensure this collaboration is productive, secure, and aligned with your goals.
Document Version: 1.0
License: CC BY 4.0 - Feel free to adapt and share with attribution