6 min read
Agent Rules
Writing AGENTS.md, Cursor rules, and Copilot instructions that actually change agent output instead of being politely ignored.
Principles
State the constraint, not the aspiration
'Write clean code' changes nothing — every model already believes it does. 'Never use `any`; use `unknown` and narrow' is checkable, and an agent can tell whether it complied.
Rules must correct the default, not restate it
An agent already writes functional components and already uses hooks. Every line spent confirming defaults dilutes the lines that matter. Write down only what the model would otherwise get wrong in *your* codebase.
Version-pin anything that changed recently
Models carry stale API knowledge. If your framework had breaking changes — async `params`, a new directive, a renamed config — say so explicitly and point at the local docs. This single practice prevents most confidently wrong output.
Show a correct example instead of describing one
A five-line snippet of your actual convention outperforms a paragraph describing it. Agents pattern-match on code far more reliably than on prose.
Keep it short enough to survive a long session
A 2,000-line rules file competes with the task for attention and gets progressively ignored. Keep the always-on file tight; push detail into skills that load on demand.
Patterns
What goes wrong, what to do instead, and why the difference matters.
Rule specificity
Avoid
# Coding Standards
- Write clean, maintainable code
- Follow best practices
- Use TypeScript properly
- Make sure components are reusable
- Handle errors appropriatelyEvery line is unfalsifiable. An agent cannot check compliance, so nothing about the output changes.
Prefer
# Coding Standards
- No `any`. Use `unknown` at boundaries and narrow it.
- Async state is a discriminated union on `status`, never
parallel `isLoading`/`error` booleans.
- Server data goes through React Query. Never Redux.
- Files import from a feature's `index.ts`, never its internals.
- Every new component gets a test asserting user-visible
behaviour, queried by role.Each rule is a check an agent can apply to its own diff before returning it.
Version-pinning framework knowledge
Avoid
# Project
Next.js app using the App Router.The model fills the gap from training data, which may be several major versions stale.
Prefer
# This is NOT the Next.js you know
Next.js 16 with breaking changes from earlier versions.
Read `node_modules/next/dist/docs/` before writing code.
Known traps:
- `params` is a Promise. Always `await params`.
- Route handler context params are also a Promise.
- Check deprecation notices in the bundled docs, not memory.Names the specific traps and points at ground truth that ships with the repo.
Layering always-on rules against on-demand skills
Avoid
.cursor/rules/everything.mdc # 2,400 lines, alwaysApply: true
# Architecture, testing, styling, git conventions, API design,
# accessibility, performance — all loaded on every request.Most of it is irrelevant to any given task, and the volume crowds out the parts that matter.
Prefer
.cursor/rules/project.mdc # ~40 lines, alwaysApply: true
# structure, stack, hard constraints
.cursor/skills/
react-native-performance/SKILL.md # loads when profiling
react-testing/SKILL.md # loads when writing tests
typescript-conventions/SKILL.md # loads when typing
AGENTS.md # same content, tool-agnostic
.github/copilot-instructions.md # same rules, Copilot's formatA small always-on core, with depth loaded only when the task calls for it.
Review checklist
What I look for when reviewing a pull request that touches this area.
- Every rule is specific enough that compliance is checkable.
- No rule restates a default the model already follows.
- Framework versions with breaking changes are called out explicitly.
- Local documentation is referenced by path.
- The always-on file stays under roughly 50 lines.
- Rules were validated by watching real agent output change.
Take the skill
Everything above, generated into a skill file your agent can load. Copy it, or download it and commit it to your repo.
.claude/skills/agent-rules-authoring/SKILL.mdDrop into .claude/skills/ or .cursor/skills/ — the frontmatter drives when the skill loads.
---
name: agent-rules-authoring
description: >-
Write AGENTS.md, Cursor rules, and Copilot instructions that measurably
change agent output: specific constraints, version-pinned framework notes,
and a small always-on core with on-demand skills. Use when setting up or
auditing agent configuration.
argument-hint: "[repo or tool]"
license: MIT
metadata:
author: John Felix Lim
version: "1.0.0"
---
# Agent Rules
Apply when creating or auditing agent configuration. The test for any rule is simple: could an agent check its own diff against it? If not, rewrite it until it can.
## Rules
1. **State the constraint, not the aspiration** — 'Write clean code' changes nothing — every model already believes it does. 'Never use `any`; use `unknown` and narrow' is checkable, and an agent can tell whether it complied.
2. **Rules must correct the default, not restate it** — An agent already writes functional components and already uses hooks. Every line spent confirming defaults dilutes the lines that matter. Write down only what the model would otherwise get wrong in *your* codebase.
3. **Version-pin anything that changed recently** — Models carry stale API knowledge. If your framework had breaking changes — async `params`, a new directive, a renamed config — say so explicitly and point at the local docs. This single practice prevents most confidently wrong output.
4. **Show a correct example instead of describing one** — A five-line snippet of your actual convention outperforms a paragraph describing it. Agents pattern-match on code far more reliably than on prose.
5. **Keep it short enough to survive a long session** — A 2,000-line rules file competes with the task for attention and gets progressively ignored. Keep the always-on file tight; push detail into skills that load on demand.
## Patterns
### Rule specificity
**Avoid** — Every line is unfalsifiable. An agent cannot check compliance, so nothing about the output changes.
```md
# Coding Standards
- Write clean, maintainable code
- Follow best practices
- Use TypeScript properly
- Make sure components are reusable
- Handle errors appropriately
```
**Prefer** — Each rule is a check an agent can apply to its own diff before returning it.
```md
# Coding Standards
- No `any`. Use `unknown` at boundaries and narrow it.
- Async state is a discriminated union on `status`, never
parallel `isLoading`/`error` booleans.
- Server data goes through React Query. Never Redux.
- Files import from a feature's `index.ts`, never its internals.
- Every new component gets a test asserting user-visible
behaviour, queried by role.
```
### Version-pinning framework knowledge
**Avoid** — The model fills the gap from training data, which may be several major versions stale.
```md
# Project
Next.js app using the App Router.
```
**Prefer** — Names the specific traps and points at ground truth that ships with the repo.
```md
# This is NOT the Next.js you know
Next.js 16 with breaking changes from earlier versions.
Read `node_modules/next/dist/docs/` before writing code.
Known traps:
- `params` is a Promise. Always `await params`.
- Route handler context params are also a Promise.
- Check deprecation notices in the bundled docs, not memory.
```
### Layering always-on rules against on-demand skills
**Avoid** — Most of it is irrelevant to any given task, and the volume crowds out the parts that matter.
```bash
.cursor/rules/everything.mdc # 2,400 lines, alwaysApply: true
# Architecture, testing, styling, git conventions, API design,
# accessibility, performance — all loaded on every request.
```
**Prefer** — A small always-on core, with depth loaded only when the task calls for it.
```bash
.cursor/rules/project.mdc # ~40 lines, alwaysApply: true
# structure, stack, hard constraints
.cursor/skills/
react-native-performance/SKILL.md # loads when profiling
react-testing/SKILL.md # loads when writing tests
typescript-conventions/SKILL.md # loads when typing
AGENTS.md # same content, tool-agnostic
.github/copilot-instructions.md # same rules, Copilot's format
```
## Review checklist
- [ ] Every rule is specific enough that compliance is checkable.
- [ ] No rule restates a default the model already follows.
- [ ] Framework versions with breaking changes are called out explicitly.
- [ ] Local documentation is referenced by path.
- [ ] The always-on file stays under roughly 50 lines.
- [ ] Rules were validated by watching real agent output change.
---
From the John Felix Lim Frontend Engineering Playbook — https://github.com/JohnFelixLim