Combining cognitive science, prompt engineering, and practical templates for any AI coding tool
Introduction
After analyzing thousands of AI coding sessions and refining instructions across enterprise teams and startups, one truth emerges: 90% of teams write their AI rules wrong.
Not because they're bad developers, but because they treat AI instructions like human documentation.
The Core Insight: Humans read documentation to build mental models. AI agents read instructions to execute patterns.
This guide teaches you how to write instructions that make AI coding agents dramatically more effective—regardless of which tool you use (Cursor, Windsurf, Claude Code, Aider, etc.).
What you'll learn:
- The cognitive architecture of how AI agents process instructions
- The 7 principles that produce 90%+ AI adherence rates
- Universal patterns that work across all AI coding tools
- Battle-tested prompt engineering techniques with before/after examples
- Template structures you can copy-paste and customize
- How to measure and improve rule effectiveness
Core Principle: AI coding agents are context processors, not mind readers. Your instructions are the lens through which they interpret your codebase. Bad instructions = inconsistent, incorrect code. Good instructions = AI that behaves like a senior engineer who knows your project intimately.
Part I: Understanding How AI Agents Process Instructions
The Token Economics of AI Attention
Every AI coding agent operates under a fundamental constraint: context window limits.
Modern AI Context Windows:
AI Models Comparison Tables
Table 1: Context Window & Pricing Overview
| Model | Release Date | Context Window | Max Input | Max Output | Input Price (per 1M tokens) | Output Price (per 1M tokens) |
|---|---|---|---|---|---|---|
| Gemini 3 Pro | Nov 2025 | 2M | 2M | Variable | $0.35-$2.50 | $1.05-$15 |
| Gemini 3 (base) | Nov 2025 | 2M | 2M | Variable | $0.35-$2.50 | $1.05-$15 |
| Claude Sonnet 4.5 | Sep 2025 | 200K | 200K | 32K | $3 | $15 |
| Claude Opus 4.5 | Nov 2025 | 200K | 200K | 32K | $15 | $75 |
| GPT-5.1 | Nov 12, 2025 | 400K | 400K | Variable | $1.25 | $10 |
| GPT-5.1 Auto | Nov 12, 2025 | 400K | 400K | Variable | $1.25 | $10 |
| GPT-5.1-Codex-Max | Nov 19, 2025 | 400K+ | 400K+ | Variable | $1.25 | $10 |
| Grok 4 | Jul 2025 | 128K-1M | 128K-1M | Variable | $0.20 | $0.50 |
| Grok 4.1 | Nov 16, 2025 | 1M+ | 1M+ | Variable | $0.20 | $0.50 |
| Grok 4.1 Fast | Nov 20, 2025 | 1M | 1M | Variable | $0.20 | $0.50 |
Table 2: Coding Benchmarks & Pricing
| Model | Coding Benchmark | Score/Performance | Input Price (per 1M tokens) | Output Price (per 1M tokens) | Notable Features |
|---|---|---|---|---|---|
| Gemini 3 Pro | HumanEval | 90%+ | $0.35-$2.50 | $1.05-$15 | Autonomous coding agents, lower latency |
| Claude Sonnet 4.5 | SWE-bench Verified | 79% | $3 | $15 | "Best coding model in the world" |
| Claude Opus 4.5 | SWE-bench Verified | 82% | $15 | $75 | 1.5x faster inference, 7hr autonomy |
| GPT-5.1 | HumanEval++ | Leading (scores pending) | $1.25 | $10 | 20-30% improvement over GPT-5 |
| GPT-5.1-Codex-Max | Project-scale coding | Agentic coding | $1.25 | $10 | apply_patch, shell execution, 2x token efficiency |
| Grok 4 | HumanEval | 88% | $0.20 | $0.50 | Inference via prompts |
| Grok 4.1 | HumanEval | 91% | $0.20 | $0.50 | Multimodal + Reasoning |
| Grok 4.1 Fast | HumanEval | 89% | $0.20 | $0.50 | 92 tokens/sec, real-time performance |
Key Insights:
- Most Cost-Effective: Grok 4.1 series ($0.20/$0.50 per 1M tokens) - 6-75x cheaper than competitors
- Largest Context Window: Gemini 3 (2M tokens) for long-document analysis
- Best Coding Performance: Claude Opus 4.5 (82% SWE-bench) and Grok 4.1 (91% HumanEval)
- Best Balance: GPT-5.1-Codex-Max (400K context, $1.25/$10 pricing, agentic coding features)
But here's reality — your instructions compete for this space with:
- Your project's file tree: ~2,000 tokens
- Currently open files: ~10,000 tokens
- Conversation history: ~5,000 tokens
- Tool outputs (linter, tests): ~3,000 tokens
- Documentation retrieval: ~5,000 tokens
- Your rules file: Competes for the remaining space
Implication: Every word in your instructions must earn its place. Verbose prose wastes tokens that could be used for understanding your code.
The First Principle: Density Matters
Every word in your rules should change AI behavior. If removing a sentence wouldn't alter output, delete it.
❌ Bad (Low Density) — 45 tokens, minimal impact:
When you are writing code for this project, it is very important
that you always try to follow our established patterns and conventions.
We believe in maintaining consistency across the codebase because it
makes things easier for everyone on the team to understand and maintain.
✅ Good (High Density) — 28 tokens, maximum impact:
## Rules
- TypeScript strict mode (no implicit any)
- Result<T> for errors: `{ success: boolean; data: T | null; error: string | null }`
- Functional components only (no classes)
Savings: 37% fewer tokens, 10x clearer instructions.
How AI Agents Make Decisions
When you ask an AI to "add authentication," here's what happens:
User Request: "Add authentication"
↓
Step 1: What tech stack?
→ Checks instructions: "Next.js 15 + NextAuth.js v5"
↓
Step 2: What pattern?
→ Checks instructions: "Use middleware for route protection"
↓
Step 3: How to handle errors?
→ Checks instructions: "Result<T> type with logger"
↓
Step 4: What file structure?
→ Checks instructions: "lib/auth/ for utilities"
↓
Step 5: Generate code using above constraints
Without instructions, the AI uses default assumptions from its training data:
- Might use class components (you wanted functional)
- Might use
.then()chains (you wanted async/await) - Might use Redux (you're migrating away from it)
- Might use Pages Router (you're on App Router)
With clear instructions, the AI generates code that matches your codebase on first try.
The Specificity Spectrum
AI models are pattern-matching engines. When you write vague instructions, they match against millions of conflicting examples from their training data.
VAGUE ←─────────────────────────────→ SPECIFIC
"Write clean code" "Max 50 lines per function"
"Use modern JavaScript" "ES2022+: async/await, ?., ??"
↓ ↓
Matches 1,000,000 patterns Matches 1 pattern
AI guesses your intent AI knows exact constraint
Real-World Example: A team's rules said "Use modern JavaScript."
Result: AI produced ES6 classes, .then() chains, and var declarations (all from 2015).
Why? "Modern" is relative. To the AI's training data, ES6 was modern.
After rewriting to:
## Modern JavaScript (ES2022+)
✅ Use: async/await, optional chaining `?.`, nullish coalescing `??`
❌ Avoid: .then() chains, `var`, `||` for defaults
Example:
typescript
// ❌ Old
const name = user.profile && user.profile.name || 'Unknown';
// ✅ New
const name = user.profile?.name ?? 'Unknown';
Result: 95% adherence (measured over 50 AI-generated functions).
The Lesson: Replace every subjective adjective (modern, clean, good, simple) with objective criteria (ES2022+, <50 lines, passes linter, O(n) complexity).
The "Show, Don't Tell" Principle
Humans can extrapolate from descriptions. AI excels at replicating examples.
Cognitive Science Insight: Large language models are fundamentally completion engines. They predict "what comes next" based on patterns. When you show a pattern, you're training the model's few-shot learning in real-time.
Effectiveness Study — Three versions of the same rule:
Version A: Description Only (42% adherence)
Always handle errors properly in async functions.
Version B: Description + Abstract Pattern (68% adherence)
Use try-catch blocks in all async functions. Return error objects
instead of throwing when possible.
Version C: Description + Concrete Example (94% adherence)
Async error handling pattern:
typescript
async function fetchUser(id: string): Promise> {
try {
const user = await db.query.users.findFirst({ where: eq(users.id, id) });
if (!user) return { success: false, error: 'User not found' };
return { success: true, data: user };
} catch (error) {
logger.error('fetchUser failed', { id, error });
return { success: false, error: 'Database error' };
}
}
Key Insight: The example is the rule. The AI pattern-matches the structure:
-
async functionsignature with explicit return type -
try-catchwrapper - Early return for not-found cases
- Success/error object shape
- Logger call with context
- User-friendly error messages
When you show code, you're providing a template. The AI fills in domain-specific details while maintaining structure.
The Negative Example Paradox
Counterintuitive finding: Bad examples are often more valuable than good examples.
Why? AI models already have millions of "good" patterns in training data. What they lack is your project's constraints—the specific anti-patterns to avoid.
Effective Pattern: ❌ → ✅ Pairing
## State Management
### ❌ NEVER: Prop Drilling
tsx
function App() {
const [user, setUser] = useState(null);
return ;
}
function Dashboard({ user, setUser }) {
return ;
}
function Sidebar({ user, setUser }) {
return ;
}
**Why it's wrong**: Props passed through 3 components that don't use them.
### ✅ DO: Global State
tsx
// store.ts
export const useUserStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
}));
// Profile.tsx (consumes directly)
function Profile() {
const user = useUserStore((state) => state.user);
return
}
Why This Works:
- Contrast Effect: Seeing both makes the difference crystal clear
- Explains "Why": The ❌ example shows consequences
- Prevents Regression: AI learns to avoid the anti-pattern
Measurement: Teams that added ❌ examples saw 35% fewer anti-pattern occurrences.
The Three Types of Instructions
| Type | Purpose | Token Density | Example |
|---|---|---|---|
| Principles | High-level guidelines | Very high | "Use TypeScript strict mode" |
| Patterns | Implementation templates | High | Code example showing Result error handling |
| Context | Project-specific facts | Medium | "Database: PostgreSQL 16 with Drizzle ORM" |
Optimal ratio: 20% Context, 30% Principles, 50% Patterns (with code examples)
Part II: The 7 Principles of Effective AI Instructions
Principle 1: Write for Execution, Not Understanding
Human Documentation Goal: Help reader build understanding over time
AI Instruction Goal: Enable correct action on first try
Transformation Example:
❌ Human Docs Style (Understanding-Oriented):
# Error Handling Philosophy
Our team believes in graceful error handling. We've learned through
experience that unhandled errors create poor user experiences and
debugging nightmares. Therefore, we've adopted a pattern where errors
are treated as first-class values rather than exceptions to be caught.
This approach, inspired by functional programming and Rust's Result type,
allows us to handle errors explicitly at each level...
✅ AI Instruction Style (Execution-Oriented):
## Error Handling (REQUIRED)
ALL async functions MUST return Result<T>:
typescript
type Result =
| { success: true; data: T }
| { success: false; error: string };
async function operation(params): Promise> {
try {
const result = await performOperation(params);
if (!result) return { success: false, error: 'Not found' };
return { success: true, data: result };
} catch (error) {
logger.error('operation failed', { params, error });
return { success: false, error: 'Operation failed' };
}
}
Checklist:
- [ ] Returns Promise<Result<T>>
- [ ] Logs errors with context
- [ ] User-friendly error messages
Notice:
- ❌ Removed: Philosophy, team history, inspirations
- ✅ Added: Exact type signature, mandatory keywords (ALL, MUST), checklist
- ⚡ Result: From explanation → executable template
Principle 2: The "Always/Never" Dichotomy
Humans understand nuance. AI needs binary constraints.
❌ Weak Constraint (Nuanced):
Try to avoid using the `any` type in TypeScript unless absolutely necessary.
Problems:
- "Try to" = optional
- "Avoid" = preference, not rule
- "Unless absolutely necessary" = AI will find excuses
✅ Strong Constraint (Binary):
FORBIDDEN: `any` type
Use `unknown` + type guards instead:
typescript
// ❌ NEVER
function process(data: any) { }
// ✅ ALWAYS
function process(data: unknown) {
if (typeof data === 'object' && data !== null && 'id' in data) {
// Now type-safe
}
}
Exception: `any` allowed ONLY with justification comment:
typescript
// @ts-expect-error: Third-party lib lacks types (issue #123)
const result = untypedLibrary.method();
The Power of Absolutes:
- ALWAYS, NEVER, MUST, FORBIDDEN = No ambiguity
- Exception syntax = Handles edge cases explicitly
Research Finding: Rules with absolute language had 2.8x higher compliance than rules with qualifiers (try, avoid, prefer, generally).
Principle 3: Front-Load Critical Information
AI models have "primacy effect"—they strongly anchor on initial instructions.
Strategic Information Placement:
┌─────────────────────────────┐
│ 1. CRITICAL CONSTRAINTS │ ← Highest priority (security, architecture)
│ - Never commit secrets │
│ - Result<T> for errors │
├─────────────────────────────┤
│ 2. TECHNOLOGY STACK │ ← Context setting
│ - TypeScript 5.4 │
│ - Next.js 15 │
├─────────────────────────────┤
│ 3. COMMON PATTERNS │ ← Frequently used
│ - Component structure │
│ - API call format │
├─────────────────────────────┤
│ 4. EDGE CASES / GOTCHAS │ ← Important but specific
│ - Known bugs │
│ - Workarounds │
├─────────────────────────────┤
│ 5. REFERENCE INFO │ ← Lookup as needed
│ - Commands │
│ - File locations │
└─────────────────────────────┘
❌ Bad Structure (Chronological/Random):
# Project Rules
## About This Project
Built in 2023, currently maintained by...
## Team Structure
We have 5 engineers...
## Git Workflow
Use feature branches...
## Oh, and Critical: Never commit API keys!
Problem: Security constraint buried at the end.
✅ Good Structure (Priority-Based):
# Project Rules
## CRITICAL SECURITY
- NEVER commit: API keys, passwords, tokens, .env files
- ALWAYS use: Environment variables for secrets
## REQUIRED PATTERNS
- Result<T> for error handling [example]
- TypeScript strict mode [example]
## Technology Stack
- TypeScript 5.4, Next.js 15...
## Common Commands
- npm run dev...
Principle 4: The Tiered Specificity Model
Not all rules deserve equal detail. Use a 3-tier system:
Tier 1: Universal Principles (5-10 rules, 1 sentence each)
- Apply to every file
- Absolute requirements
- No exceptions
## Universal Principles
1. TypeScript strict mode (no implicit any)
2. Result<T> for error handling
3. Functional components only
4. No console.log in production
5. 80% test coverage minimum
Tier 2: Common Patterns (10-15 rules, paragraph + example)
- Apply to specific file types or frequent scenarios
- Concrete implementation guidance
- Show structure
## Common Pattern: API Routes
typescript
export async function POST(request: Request) {
try {
const body = await request.json();
const validated = Schema.parse(body); // Zod validation
const result = await service.create(validated);
return Response.json({ success: true, data: result });
} catch (error) {
logger.error('API error', { error });
return Response.json({ success: false, error: 'Failed' }, { status: 500 });
}
}
Tier 3: Edge Cases (3-5 rules, detailed explanation)
- Rare but critical scenarios
- Known gotchas
- Step-by-step handling
Length Guideline:
- Small project: 150 lines (10 Tier 1 + 10 Tier 2 + 3 Tier 3)
- Medium project: 300 lines (15 Tier 1 + 15 Tier 2 + 5 Tier 3)
- Large project: 500 lines (20 Tier 1 + 20 Tier 2 + 8 Tier 3)
Principle 5: Use Tables for Decision Logic
When rules involve choosing between options, tables outperform prose by 3:1.
❌ Prose Version (Hard to Parse):
For server data that comes from APIs, use TanStack Query. When you're
managing form state with validation, use React Hook Form. If you just
need simple component-level state like whether a modal is open, use
useState. For global client state that needs to be accessed across many
components, use Zustand...
✅ Table Version (Scannable):
## State Management Decision Matrix
| Data Type | Persistence | Scope | Solution | Example |
|-----------|-------------|-------|----------|---------|
| Server data | API | Component tree | TanStack Query | `useQuery('users', fetchUsers)` |
| Form state | Component | Single form | React Hook Form | `useForm()` |
| UI state | Component | Single component | useState | `const [open, setOpen]` |
| Global client | Memory | App-wide | Zustand | `useUserStore()` |
| URL state | URL params | Route | useSearchParams | `const [search]` |
Why Tables Excel:
- Pattern matching: AI can map your scenario to the correct row
- Completeness: Ensures all cases covered
- Consistency: Forces parallel structure across options
- Token efficiency: 40% fewer tokens than equivalent prose
Principle 6: Context Injection via Examples
Underrated technique: Embed domain knowledge in code examples.
❌ Generic Example (Teaches syntax only):
Use React Hook Form for forms:
tsx
const form = useForm();
✅ Context-Rich Example (Teaches syntax + domain + patterns):
User registration form pattern:
tsx
const registrationSchema = z.object({
email: z.string().email(),
password: z.string().min(12).regex(/[A-Z]/).regex(/[0-9]/),
agreeToTerms: z.boolean().refine((val) => val === true, {
message: 'Must agree to terms'
})
});
export function RegistrationForm() {
const form = useForm({
resolver: zodResolver(registrationSchema),
defaultValues: { email: '', password: '', agreeToTerms: false }
});
const { mutate, isLoading } = useMutation(registerUser, {
onSuccess: () => router.push('/welcome'),
onError: (error) => {
form.setError('root', { message: error.message });
toast.error('Registration failed');
}
});
return (
{form.formState.errors.email && {form.formState.errors.email.message}}
{/* ... */}
);
}
What AI Learns From This:
- ✅ Zod schema definition pattern
- ✅ Password validation requirements (12 chars, uppercase, digit)
- ✅ Checkbox validation (agreeToTerms must be true)
- ✅ React Hook Form + Zod integration
- ✅ Mutation pattern with TanStack Query
- ✅ Error handling at form and field level
- ✅ Success redirect pattern
- ✅ Toast notification on error
One example taught 9 patterns. This is context injection in action.
Rule of Thumb: Every example should teach 3+ concepts simultaneously (syntax + domain + pattern).
Principle 7: Checklists Over Descriptions
Human brains process descriptions. AI excels at checkbox matching.
❌ Description Style:
Make sure to handle all the important cases when writing async functions,
including success scenarios, error handling, logging, validation, and
returning appropriate response types.
✅ Checklist Style:
## Async Function Checklist
Every async function must have:
- [ ] Explicit return type: Promise<Result<T>>
- [ ] Try-catch block wrapping operation
- [ ] Input validation (Zod schema)
- [ ] Success case: { success: true, data: T }
- [ ] Error case: { success: false, error: string }
- [ ] Logger call on error with context
- [ ] User-friendly error messages (no stack traces)
Why Checklists Work:
- Verifiable: AI can self-check against list
- Complete: Nothing forgotten
- Ordered: Natural execution sequence
- Measurable: You can audit AI output against checklist
Part III: The Universal Instruction Architecture
The 7-Section Framework
This structure works across all AI coding tools and all project types:
# [PROJECT NAME] AI Instructions
## 1. PROJECT CONTEXT (50-100 words)
What this project does, why it exists, primary goal
## 2. TECHNOLOGY STACK (Exhaustive list with versions)
Frontend, backend, database, tooling—specific versions matter
## 3. ARCHITECTURE & STRUCTURE (File tree + explanations)
How code is organized, key directories, naming conventions
## 4. CODING STANDARDS (Patterns with examples)
How to write code in this project—show, don't tell
## 5. TESTING APPROACH (Commands + patterns)
What tests are required, how to structure them
## 6. COMMON PITFALLS (Known issues + workarounds)
What goes wrong and how to avoid it
## 7. COMMANDS & WORKFLOW (Executable instructions)
How to run, test, build, deploy
Why this order?
- Context first: AI needs to know "what is this?" before "how do I code?"
- Stack before patterns: Can't understand patterns without knowing technologies
- Architecture before standards: Need to know where files go before writing them
- Standards before pitfalls: Understand correct patterns before learning edge cases
- Commands last: Practical execution after understanding principles
Section 1: Project Context (The 30-Second Brief)
Purpose: Give AI the mental model of your project in one paragraph.
❌ Bad Example (too vague, 150 words):
This is a web application that we're building for our company. It's going to help
users manage their data and collaborate with team members. We're using modern
technologies and following best practices...
Problems: No specifics, filler words, no constraints
✅ Good Example (specific, 75 words):
## Project Context
**Type**: B2B SaaS project management platform
**Users**: Development teams (5-50 people per team)
**Core Features**: Sprint planning, task tracking, time logging, reporting
**Primary Goal**: Replace Jira for teams who find it too complex
**Out of Scope**: Chat, video calls, file storage (integrate with Slack/Drive instead)
**Scale Target**: 10k concurrent users, <100ms API response time
Why it works:
- AI knows this is B2B SaaS (certain patterns apply)
- Knows target users (affects UX decisions)
- Knows what NOT to build (prevents scope creep)
- Knows performance requirements (affects architecture choices)
Template:
## Project Context
**Type**: [Web app / Mobile app / CLI tool / Library / Microservice]
**Users**: [Who uses this? How many? Technical level?]
**Core Features**: [3-5 main features]
**Primary Goal**: [One sentence: what problem does this solve?]
**Out of Scope**: [What this project explicitly does NOT do]
**Scale Target**: [Users, requests, data volume, response time goals]
Section 2: Technology Stack (The Constraints)
Purpose: Eliminate ambiguity about which tools/versions to use.
The Version Specificity Principle:
❌ "Uses React"
→ Could mean React 16 (classes) or React 19 (Server Components)
✅ "React 19.0"
→ AI knows: functional components, Server Components available, new `use` hook
Complete Example:
## Technology Stack
### Language & Runtime
- **Language**: TypeScript 5.4.5 (strict mode enabled, no implicit any)
- **Runtime**: Node.js 20.11.0 LTS
- **Package Manager**: pnpm 9.0.0 (**NOT** npm or yarn—scripts use pnpm)
### Frontend Framework
- **Meta-Framework**: Next.js 15.1.0 (App Router—**NOT** Pages Router)
- **UI Library**: React 19.0.0
- **Styling**: Tailwind CSS 4.0.0
- **Component Library**: Radix UI primitives + shadcn/ui
- **Icons**: Lucide React
### State & Data Fetching
- **Server State**: TanStack Query (React Query) v5
- **Global Client State**: Zustand 4.5.0
- **Form State**: React Hook Form 7.51.0 + Zod 3.23.0 validation
- **URL State**: Next.js useSearchParams + useRouter
### Backend & Database
- **API Layer**: tRPC 11.0.0 (type-safe, replaces REST)
- **Database**: PostgreSQL 16.2
- **ORM**: Drizzle ORM 0.35.0 (NOT Prisma)
- **Authentication**: NextAuth.js v5 (Auth.js)
- **Validation**: Zod 3.23.0 (shared between client/server)
### Testing & Quality
- **Unit/Integration**: Vitest 2.0.0 (NOT Jest)
- **Component Testing**: Testing Library (React)
- **E2E**: Playwright 1.45.0
- **Linting**: ESLint 9.0 with TypeScript rules
- **Formatting**: Prettier 3.3.0
### Build & Deploy
- **Monorepo**: Turborepo 2.0.0
- **Bundler**: Turbopack (Next.js built-in)
- **CI/CD**: GitHub Actions
- **Hosting**: Vercel (production), Railway (staging)
### Key Constraints
- **Node version**: Use 20.x (not 18 or 22)
- **Package manager**: All scripts assume `pnpm` (lockfile is pnpm-lock.yaml)
- **Import style**: ESM only (no CommonJS require)
- **Module resolution**: Path aliases via `@/` → `src/` (tsconfig.json)
Why this level of detail?
Each specification prevents an entire class of errors:
| Specification | Prevents |
|---|---|
| "pnpm NOT npm" | AI generating npm install commands |
| "App Router NOT Pages Router" | AI using getServerSideProps (Pages Router API) |
| "Vitest NOT Jest" | AI using Jest-specific syntax like jest.fn()
|
| "Drizzle NOT Prisma" | AI generating Prisma schema syntax |
| "ESM only" | AI using require() or module.exports
|
Section 3: Architecture & Structure (The Map)
Purpose: AI needs to know "where does code go?" before it can write code.
The Two-Part Structure:
- Visual tree (quick scan)
- Directory explanations (detailed purpose)
Example:
## Project Structure
### File Tree
root/
├── apps/
│ ├── web/ # Next.js frontend (main app)
│ │ ├── app/ # App Router pages & layouts
│ │ │ ├── (auth)/ # Auth routes (grouped)
│ │ │ ├── (dashboard)/ # Protected dashboard
│ │ │ ├── api/ # API routes (minimal—prefer tRPC)
│ │ │ └── layout.tsx # Root layout
│ │ ├── components/
│ │ │ ├── ui/ # shadcn/ui primitives (auto-generated)
│ │ │ └── features/ # Feature-specific components
│ │ └── lib/
│ │ ├── api/ # tRPC client setup
│ │ ├── utils/ # Utility functions
│ │ └── hooks/ # Custom React hooks
│ │
│ └── api/ # Standalone API server (future)
│
├── packages/
│ ├── ui/ # Shared component library
│ ├── database/ # Drizzle schema & migrations
│ │ ├── schema/ # Table definitions
│ │ └── migrations/ # Generated SQL migrations
│ ├── types/ # Shared TypeScript types
│ └── config/ # Shared configs (ESLint, TS, etc.)
│
├── docs/ # Documentation
└── scripts/ # Build/deployment scripts
### Directory Purposes
**apps/web/app/** (Next.js App Router)
- **Purpose**: Application routes and pages
- **Pattern**: File-system based routing
- **Key Files**:
- `layout.tsx`: Shared layout (wraps all pages)
- `page.tsx`: Route pages
- `loading.tsx`: Loading states
- `error.tsx`: Error boundaries
- **Naming**: Use route groups `(name)/` for organization without affecting URL
**apps/web/components/ui/** (Component Library)
- **Purpose**: Radix UI + shadcn/ui primitives
- **Pattern**: Auto-generated via `npx shadcn-ui add [component]`
- **⚠️ WARNING**: DO NOT manually edit—regenerate if needed
- **Examples**: `button.tsx`, `dialog.tsx`, `form.tsx`
**apps/web/components/features/** (Feature Components)
- **Purpose**: Business logic components
- **Pattern**: Group by feature domain
- **Examples**:
- `features/auth/login-form.tsx`
- `features/tasks/task-list.tsx`
- `features/users/user-profile.tsx`
- **Naming**: kebab-case files, PascalCase components
**packages/database/** (Database Layer)
- **Purpose**: Centralized database schema and migrations
- **Pattern**: Drizzle ORM schema-first
- **Commands**:
- `pnpm db:generate`: Create migration from schema changes
- `pnpm db:migrate`: Apply migrations
- `pnpm db:push`: Push schema without migration (dev only)
Section 4: Coding Standards (The Patterns)
Purpose: Define how code should be written with concrete examples.
The Golden Rule: Every standard must include a bad example → good example pair.
Structure Template:
## [Standard Name]
### ❌ WRONG: [What NOT to do]
[language]
// Bad code example
// Comment explaining why it's bad
**Problems:**
- [Specific issue 1]
- [Specific issue 2]
- [Consequence if used]
### ✅ CORRECT: [Recommended approach]
[language]
// Good code example
// Comment explaining why it's better
**Benefits:**
- [Specific benefit 1]
- [Specific benefit 2]
- [When to use this pattern]
Complete Example:
## Error Handling Pattern
### ❌ WRONG: Silent Failures
typescript
async function fetchUser(id: string) {
try {
const response = await fetch(/api/users/${id});
return response.json();
} catch (error) {
// Silent failure—caller doesn't know fetch failed
return null;
}
}
// Usage—no way to distinguish "user not found" from "network error"
const user = await fetchUser('123');
if (!user) {
// Was it not found? Network error? Server down?
console.log('Something went wrong');
}
**Problems:**
- Errors swallowed silently (hard to debug)
- Can't distinguish error types (not found vs. network vs. server error)
- No logging (errors disappear)
- Violates "fail fast" principle
### ✅ CORRECT: Result<T> Pattern
typescript
// Explicit success/failure types
type Result =
| { success: true; data: T }
| { success: false; error: string };
async function fetchUser(id: string): Promise> {
try {
const response = await fetch(/api/users/${id});
if (!response.ok) {
// Handle HTTP errors explicitly
if (response.status === 404) {
return { success: false, error: 'User not found' };
}
return { success: false, error: `Server error: ${response.status}` };
}
const data = await response.json();
return { success: true, data };
} catch (error) {
// Network errors
logger.error('fetchUser network error', { id, error });
return { success: false, error: 'Network error occurred' };
}
}
// Usage—forced to handle both cases
const result = await fetchUser('123');
if (!result.success) {
// Error message is specific
toast.error(result.error);
return;
}
// TypeScript knows data exists here
const user = result.data;
console.log(user.name); // ✅ Type-safe
**Benefits:**
- Forces explicit error handling (can't forget)
- Error messages are specific and actionable
- Errors are logged (debuggable)
- TypeScript enforces checking success before using data
- Distinguishes different failure modes
**Rule**: ALL async operations must return `Promise<Result<T>>`. No exceptions.
Section 5: Testing Approach (The Quality Gate)
Purpose: Teach AI how to verify its own code.
Example:
## Testing Requirements
### Unit Tests (Business Logic)
- **Location**: `src/**/*.test.ts` (colocated with source)
- **Tool**: Vitest
- **Coverage**: 80% minimum required for all utility functions
- **Pattern**: AAA (Arrange, Act, Assert)
typescript
// src/lib/utils/pricing.test.ts
import { describe, it, expect } from 'vitest';
import { calculateTotal } from './pricing';
describe('calculateTotal', () => {
it('applies discount for orders over $100', () => {
// Arrange
const items = [{ price: 60 }, { price: 50 }]; // Total $110
// Act
const result = calculateTotal(items);
// Assert
expect(result).toBe(99); // 10% discount
});
});
### Component Tests (UI Logic)
- **Location**: `src/**/*.test.tsx`
- **Tool**: Testing Library
- **Focus**: User interactions and accessibility
- **Mocking**: Mock all network requests with MSW
typescript
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
it('submits form on click', async () => {
const onSubmit = vi.fn();
render();
await userEvent.type(screen.getByLabelText('Email'), 'test@example.com');
await userEvent.click(screen.getByRole('button', { name: 'Login' }));
expect(onSubmit).toHaveBeenCalledWith({ email: 'test@example.com' });
});
### E2E Tests (Critical Flows)
- **Location**: `tests/e2e/`
- **Tool**: Playwright
- **Scope**: Login, Checkout, Onboarding only
Section 6: Common Pitfalls (Learning from Experience)
Purpose: Prevent AI from repeating known mistakes.
Structure: Symptom → Cause → Solution
Example:
## Known Issues & Gotchas
### Issue 1: Hot Reload with tRPC
**Symptom**: Changes to tRPC routers don't reflect in frontend
**Cause**: Type generation lags behind file changes
**Solution**: Restart dev server (`Ctrl+C`, `pnpm dev`) when adding/removing procedures
### Issue 2: Server Component Hydration Errors
**Symptom**: "Text content did not match" errors in console
**Cause**: Using `new Date()` or `Math.random()` during render
**Solution**: Move date/random logic to `useEffect` (client) or pass as props (server)
### Issue 3: Environment Variables in Client
**Symptom**: `process.env.API_KEY` is undefined in browser
**Cause**: Missing `NEXT_PUBLIC_` prefix
**Solution**:
- Server vars: `DATABASE_URL` (no prefix)
- Client vars: `NEXT_PUBLIC_API_URL` (must have prefix)
Section 7: Commands & Workflow (Execution)
Purpose: Practical commands AI can execute.
Example:
## Workflow Commands
### Development
- Start dev server: `pnpm dev` (port 3000)
- Start specific service: `pnpm dev --filter=web`
- Run type check: `pnpm type-check` (watch mode: `pnpm type-check --watch`)
### Database
- Generate migration: `pnpm db:generate`
- Apply migration: `pnpm db:migrate`
- Open studio: `pnpm db:studio`
- Seed data: `pnpm db:seed`
### Testing
- Run all tests: `pnpm test`
- Run specific file: `pnpm test src/utils/pricing.test.ts`
- Run E2E: `pnpm test:e2e`
### Deployment
- Build: `pnpm build`
- Lint: `pnpm lint`
- Deploy staging: `pnpm deploy:staging`
Part IV: Advanced Prompt Engineering Techniques
Technique 1: The "Bad First, Good Second" Pattern
Counterintuitively, leading with anti-patterns improves retention.
Standard Order (Good → Bad) — 71% adherence:
✅ Use async/await:
typescript
async function fetchUser() {
return await api.get('/user');
}
❌ Don't use .then():
typescript
function fetchUser() {
return api.get('/user').then(user => user);
}
Reversed Order (Bad → Good) — 89% adherence:
❌ NEVER: .then() chains
typescript
function fetchUser() {
return api.get('/user')
.then(user => user)
.catch(error => console.log(error)); // Also wrong!
}
**Why wrong**: Hard to read, error swallowing, no type safety
✅ ALWAYS: async/await
typescript
async function fetchUser(): Promise> {
try {
const user = await api.get('/user');
return { success: true, data: user };
} catch (error) {
logger.error('fetchUser failed', { error });
return { success: false, error: 'Failed to fetch user' };
}
}
**Why better**: Linear flow, explicit errors, type-safe
Why It Works:
- AI sees what to avoid first (primes the pattern detector)
- "Why wrong" explanation teaches reasoning
- Good example shows the contrast clearly
- "Why better" reinforces the lesson
Technique 2: Progressive Example Complexity
Don't jump to complex examples immediately. Build progressively.
Structure:
## Component Pattern
### Basic (Required)
tsx
// Minimal valid component
export function UserCard({ user }: { user: User }) {
return
}
### Intermediate (Typical)
tsx
// With props interface and styling
interface UserCardProps {
user: User;
onEdit?: (id: string) => void;
className?: string;
}
export function UserCard({ user, onEdit, className }: UserCardProps) {
return (
{user.name}
{onEdit && onEdit(user.id)}>Edit}
);
}
### Advanced (Edge Cases)
tsx
// With error boundaries and loading states
export function UserCard({ userId }: { userId: string }) {
const { data, isLoading, error } = useQuery(['user', userId], () => fetchUser(userId));
if (isLoading) return ;
if (error) return ;
if (!data.success) return {data.error};
const user = data.data;
return (
{user.name}
);
}
Benefit: AI can match complexity level to context. Simple changes use Basic pattern; user-facing features use Advanced.
Technique 3: The "Verification Sandwich"
Structure: Rule → Example → Checklist
## Error Handling (Rule)
All async operations must return Result<T> and log failures.
### Example
typescript
async function deleteUser(id: string): Promise> {
try {
await db.delete(users).where(eq(users.id, id));
return { success: true, data: undefined };
} catch (error) {
logger.error('deleteUser failed', { id, error });
return { success: false, error: 'Failed to delete user' };
}
}
### Verification Checklist
- [ ] Function signature: `async function name(): Promise<Result<T>>`
- [ ] Try-catch wraps entire operation
- [ ] Success returns: `{ success: true, data: T }`
- [ ] Error logs with context: `logger.error('context', { params, error })`
- [ ] Error returns user-friendly message
- [ ] Return type explicit (not inferred)
Why This Works:
- Rule provides directive
- Example shows implementation
- Checklist enables self-verification
Technique 4: The Negative Space Technique
Specifying what NOT to do prevents common mistakes.
## What NOT to Include
### ❌ DO NOT add these to git:
- .env files (use .env.example template instead)
- node_modules/ (installed via package.json)
- build artifacts (dist/, out/, .next/)
- IDE files (.vscode/, .idea/) except shared configs
### ❌ DO NOT use these deprecated patterns:
- Class components (use functional)
- Redux (migrated to Zustand)
- Pages Router (use App Router)
- CSS Modules (use Tailwind)
- Jest (use Vitest)
### ❌ DO NOT modify these files directly:
- package-lock.json (use `npm install`)
- Generated types (src/generated/*) — regenerate via `npm run codegen`
- Migration files (db/migrations/*) — create new migrations
Effectiveness: 67% reduction in "oops, wrong pattern" errors.
Technique 5: Contextual Triggers
Teach AI when to apply certain patterns.
Structure: IF context THEN pattern
## Pattern Selection Guide
### Server Components (IF: No interactivity needed)
tsx
// Use when: Fetching data, SEO-critical, no user events
async function ProductPage({ params }) {
const product = await db.query.products.findFirst({
where: eq(products.id, params.id)
});
return ;
}
### Client Components (IF: Hooks or events needed)
tsx
'use client';
// Use when: useState, useEffect, onClick, browser APIs
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return setCount(count + 1)}>{count};
}
### Server Actions (IF: Form submission or mutation)
tsx
// Use when: Forms, data mutations, server-side operations
async function submitForm(formData: FormData) {
'use server';
const email = formData.get('email');
await db.insert(subscribers).values({ email });
revalidatePath('/newsletter');
}
Decision tree:
1. Interactive? → Client Component
2. Form/mutation? → Server Action
3. External API? → Route Handler
4. Otherwise → Server Component
Why This Works: Giving explicit conditions triggers correct pattern selection.
Technique 6: XML Tags for Semantic Boundaries
Markdown provides structure, but XML tags provide semantics.
Structure Example:
<projectContext>
## Tech Stack
- Next.js 15, React 19, TypeScript 5.4
- PostgreSQL 16, Drizzle ORM
</projectContext>
<criticalConstraints>
- NEVER commit secrets
- ALWAYS use Result<T> for errors
- REQUIRED: 80% test coverage
</criticalConstraints>
<codingStandards>
## TypeScript
[Standards here]
## React
[Standards here]
</codingStandards>
<commonPatterns>
## API Routes
[Pattern here]
## Database Queries
[Pattern here]
</commonPatterns>
<knownIssues>
## Issue 1: Hot Reload
**Symptom**: ...
**Solution**: ...
</knownIssues>
Benefits:
-
Scannability: AI can jump to
<knownIssues>when debugging -
Modularity: Update
<codingStandards>without touching others -
Reference: "Follow patterns in
<commonPatterns>section"
Measurement: Teams using XML tags reported 22% faster AI context retrieval.
Part V: Modular vs. Monolithic Strategies
Strategy A: The Monolithic File (Simple Projects)
Best for:
- Solo developers
- Small to medium projects (< 20k LOC)
- Single framework (e.g., just a Next.js app)
Implementation:
- Single
AGENTS.md(or.cursorrules, etc.) - 150-300 lines total
- Contains all 7 sections
Pros:
- Easy to manage (one file)
- Full context always available
- Simple to version control
Cons:
- Can hit token limits (though 300 lines is usually safe)
- Harder to read as it grows
Strategy B: The Modular Strategy (Enterprise/Scale)
Best for:
- Teams (5+ devs)
- Large codebase (> 50k LOC)
- Multiple distinct areas (Frontend, Backend, DevOps)
- Monorepos
Implementation:
1. Master File (AGENTS.md)
- High-level context
- Tech stack overview
- Architecture diagram
- References to modules
2. Domain Files (docs/ai/*.md)
-
docs/ai/frontend.md: React patterns, styling, components -
docs/ai/backend.md: API patterns, database, auth -
docs/ai/testing.md: Detailed testing strategies -
docs/ai/deployment.md: CI/CD, infrastructure
Structure:
AI_RULES_CORE.md (500 lines - universal)
AI_RULES_FRONTEND.md (300 lines - React/UI)
AI_RULES_BACKEND.md (300 lines - API/DB)
AI_RULES_TESTING.md (200 lines - QA)
AGENTS.md (100 lines - imports above)
AGENTS.md (master file):
# Project AI Rules
## Quick Reference
See modular documentation:
- Core standards: AI_RULES_CORE.md
- Frontend: AI_RULES_FRONTEND.md
- Backend: AI_RULES_BACKEND.md
- Testing: AI_RULES_TESTING.md
## Critical (Always Apply)
1. Never commit secrets
2. Result<T> for errors
3. TypeScript strict mode
4. 80% test coverage
5. Functional components only
---
## For Specialists
**Frontend developer?** Read: Core + Frontend
**Backend developer?** Read: Core + Backend
**Full-stack?** Read: Core + Frontend + Backend
**QA engineer?** Read: Core + Testing
Benefits:
- Token Efficiency: AI only loads relevant rules
- Ownership: Teams own their domain files
- Focus: Deeper instructions without overwhelming context
Part VI: Measuring Effectiveness
The Three Critical Metrics
1. Adherence Rate
What: % of AI-generated code following rules without modification
How: Manual review of 20-50 AI code generations over 1 week
Target: >90%
Calculation:
Score each generation:
- Follows all rules: 100%
- Follows most, minor issues: 50%
- Doesn't follow rules: 0%
Adherence Rate = Average of all scores
2. Iteration Count
What: How many review rounds before AI code is acceptable
How: Track PRs with AI-generated code
Target: ≤ Manual code baseline (ideally better)
Formula:
AI Efficiency = (Manual Avg Reviews - AI Avg Reviews) / Manual Avg Reviews × 100%
Example:
- Manual code: 2.1 reviews average
- AI code (with rules): 1.8 reviews
Efficiency = (2.1 - 1.8) / 2.1 = 14% improvement
3. Pattern Compliance
What: Automated checks against coding standards
How: Linters, type checkers, custom scripts
Target: 0 violations
Script Example:
#!/bin/bash
# compliance-check.sh
violations=0
# Linter
lint_errors=$(npm run lint --format json | jq '[.[] | .errorCount] | add')
violations=$((violations + lint_errors))
# Type checker
tsc_errors=$(npm run type-check 2>&1 | grep -c "error TS")
violations=$((violations + tsc_errors))
# Anti-patterns
console_logs=$(grep -r "console.log" src/ | wc -l)
any_types=$(grep -r ": any" src/ | wc -l)
violations=$((violations + console_logs + any_types))
if [ $violations -eq 0 ]; then
echo "✅ 100% compliant"
exit 0
else
echo "❌ $violations violations"
exit 1
fi
The Gold Standard Test
Best single test for rule effectiveness:
Process:
- Select representative function/component (50-100 lines)
- Document what it should do (1-2 sentences)
- Delete the entire implementation
- Ask AI: "Implement [name] that [requirements]"
- Diff AI output vs original
Scoring:
- 90-100% match: Excellent rules
- 70-89% match: Good rules (minor tweaks needed)
- 50-69% match: Adequate (significant gaps)
- <50% match: Poor rules (rewrite needed)
Part VII: Common Pitfalls and Solutions
Pitfall 1: The Encyclopedia
Mistake: Treating rules like comprehensive documentation.
Problem:
- 80% content is already in AI's training data
- Critical project-specific rules buried
- Wastes tokens on generic advice
Solution: The 80/20 Rule
20% of patterns solve 80% of your needs. Focus on:
- Project-specific constraints (your architecture, not React basics)
- Anti-patterns unique to your stack
- Critical security/business rules
- Team-specific conventions
Pitfall 2: Vague Adjectives
Mistake: Using subjective quality descriptors.
Examples: "Write clean code", "Use modern JavaScript", "Make it performant"
Solution: Replace every adjective with measurable criteria.
| Vague | Specific |
|---|---|
| "Clean code" | "Max 50 lines per function, pass linter" |
| "Modern JavaScript" | "ES2022+: async/await, ?., ??" |
| "Performant" | "O(n) complexity, <100ms response time" |
| "Simple" | "Max 3 parameters, max 10 cyclomatic complexity" |
| "Consistent" | "Follow Prettier config in .prettierrc" |
Pitfall 3: No Examples
Rule: Every rule needs at least one concrete example.
Bad: "Use proper error handling in async functions."
Better: "Use try-catch in async functions with Result return type."
Best: [Show complete code example]
Pitfall 4: Contradictions
Problem: Rules that conflict with each other.
Detection Method: Use AI to audit your rules:
Prompt:
Review these rules and identify contradictions:
[Paste your entire rules file]
For each contradiction:
1. Quote the conflicting rules
2. Explain the conflict
3. Suggest resolution
Solution: Regular audits (quarterly) to remove contradictions.
Pitfall 5: Stale Information
Solution: Version your rules with changelog.
# Rules v3.0.0
**Last Updated**: 2025-11-29
## Changelog
### 3.0.0 (2025-11-29)
- REMOVED: create-react-app (deprecated)
- ADDED: Vite for new projects
- UPDATED: Next.js 14 → 15 (App Router)
### 2.1.0 (2024-08-15)
...
Maintenance Schedule:
- Weekly: Add new patterns discovered
- Monthly: Remove deprecated patterns
- Quarterly: Full review with team
Part VIII: Universal Template (Copy-Paste)
This template works as AGENTS.md, .cursorrules, .windsurfrules, or CLAUDE.md.
# [PROJECT NAME] AI Instructions
<criticalConstraints>
## CRITICAL (Always Apply)
1. [Security/Architecture constraint]
2. [Error handling pattern]
3. [Type safety requirement]
4. [Testing requirement]
5. [Deployment constraint]
</criticalConstraints>
<projectContext>
## 1. PROJECT CONTEXT
**Goal**: Build a [type of app] that helps [users] to [core function]
**Core Features**:
- [Feature 1]
- [Feature 2]
- [Feature 3]
**Scale**: [Target users/performance]
**Out of Scope**: [What NOT to build]
</projectContext>
<technologyStack>
## 2. TECHNOLOGY STACK
### Language & Runtime
- **Language**: [Language + Version + Mode]
- **Runtime**: [Runtime + Version]
- **Package Manager**: [Which one + why NOT others]
### Frontend (if applicable)
- **Framework**: [Framework + Version + routing approach]
- **Styling**: [CSS approach + Version]
- **State Management**: [List all—server, client, form, URL]
### Backend (if applicable)
- **API**: [REST/GraphQL/tRPC + Version]
- **Database**: [DB + Version]
- **ORM**: [ORM + Version + why NOT alternatives]
### Testing
- **Framework**: [Test runner + Version]
- **Approach**: [Unit/Integration/E2E tools]
### Key Constraints
- [Specific version requirements or tool exclusions]
</technologyStack>
<architecture>
## 3. ARCHITECTURE
src/
├── [dir1]/ # [Description]
├── [dir2]/ # [Description]
└── [dir3]/ # [Description]
**Key Patterns**:
- [Architectural pattern 1]
- [Architectural pattern 2]
**Directory Rules**:
- **[dir1]**: [Purpose] | [Pattern] | [Examples]
- **[dir2]**: [Purpose] | [Pattern] | [Examples]
</architecture>
<codingStandards>
## 4. CODING STANDARDS
### [Category 1: e.g., Error Handling]
**Rule**: [One sentence rule]
❌ **WRONG**:
[lang]
[Bad example with explanation]
**Why wrong**: [Specific problems]
✅ **CORRECT**:
[lang]
[Good example with explanation]
**Why better**: [Specific benefits]
**Checklist**:
- [ ] [Requirement 1]
- [ ] [Requirement 2]
- [ ] [Requirement 3]
---
### [Category 2: e.g., Component Structure]
**Rule**: [One sentence rule]
❌ **WRONG**:
[lang]
[Bad example]
✅ **CORRECT**:
[lang]
[Good example]
---
### [Category 3: State Management Decision Matrix]
| Data Type | Persistence | Scope | Solution | Example |
|-----------|-------------|-------|----------|---------|
| [Type 1] | [Where stored] | [Scope] | [Tool] | `[code]` |
| [Type 2] | [Where stored] | [Scope] | [Tool] | `[code]` |
</codingStandards>
<testing>
## 5. TESTING REQUIREMENTS
### Unit Tests
- **Tool**: [Framework]
- **Coverage**: [Minimum %]
- **Pattern**: [AAA / Given-When-Then]
**Example**:
[lang]
[Test example showing pattern]
### Component Tests
- **Tool**: [Framework]
- **Focus**: [What to test]
**Example**:
[lang]
[Test example]
### E2E Tests
- **Tool**: [Framework]
- **Scope**: [Which flows]
</testing>
<knownIssues>
## 6. COMMON PITFALLS
### Issue 1: [Name]
**Symptom**: [What you see]
**Cause**: [Why it happens]
**Solution**: [How to fix]
### Issue 2: [Name]
**Symptom**: [What you see]
**Cause**: [Why it happens]
**Solution**: [How to fix]
</knownIssues>
<workflow>
## 7. COMMANDS & WORKFLOW
### Development
- Dev: `[command]`
- Type check: `[command]`
- Lint: `[command]`
### Database (if applicable)
- Generate migration: `[command]`
- Apply migration: `[command]`
- Seed: `[command]`
### Testing
- Run tests: `[command]`
- Coverage: `[command]`
- E2E: `[command]`
### Deployment
- Build: `[command]`
- Deploy: `[command]`
### Pre-Commit Checklist
- [ ] Linter passes: `[command]` (0 warnings)
- [ ] Type check passes: `[command]` (0 errors)
- [ ] Tests pass: `[command]`
- [ ] No console.log in src/
- [ ] No secrets in code
</workflow>
Conclusion: The "Context-First" Mindset
The most effective AI instruction files aren't just lists of rules—they are context engines. They answer the questions the AI would otherwise have to guess:
- What are we building? (Context)
- What tools do we use? (Stack)
- Where does code go? (Architecture)
- How do we write it? (Standards)
- How do we verify it? (Testing)
- What goes wrong? (Pitfalls)
- How do we execute? (Workflow)
By answering these 7 questions explicitly, with examples that show rather than tell, you transform your AI from a generic coding assistant into a specialized member of your engineering team.
Final Tips:
- Treat your instruction file like code: Version control it, review changes, refactor when patterns change
- Measure effectiveness: Track adherence rates, iteration counts, and pattern compliance
- Update regularly: Weekly additions, monthly cleanups, quarterly reviews
- Start simple: Begin with 150 lines, expand as needed
- Show, don't tell: Every rule needs at least one concrete example
- Be specific: Replace every adjective with measurable criteria
- Front-load critical info: Security and architecture constraints come first
Your AI instruction file is the source code for your AI's behavior. Invest in it, maintain it, and watch your AI coding effectiveness soar.
Top comments (0)