AI Agents — Part 2

Build your own coding agent.
The same way Cursor does it.

Cursor, Claude Code, and GitHub Copilot all read a markdown file before touching your code. That file tells them what your project is, how it's structured, and what rules to follow. It's yours to write — and once you do, every session starts exactly the way you want it to.

Illustration: a coding agent configured by markdown files

From writing to code

Part 1 of this guide showed that an agent is just a text file — a system prompt saved to disk. A writing agent needs to know tone and vocabulary. A coding agent needs something different: it needs to understand your project.

The mechanism is identical. The content is not. When Cursor opens a project, it looks for a configuration file and reads it before it does anything else. That file describes the project in plain English. You write it once, and from that point on every AI interaction in that project starts with the right context — the right language, the right structure, the right constraints.

The key point: You are not configuring a piece of software. You are writing a briefing document — the kind you'd hand to a new developer joining the project. The AI reads it exactly the same way.

What your coding agent needs to know

A useful coding configuration covers five areas. You don't need all five to get started — even two or three make a significant difference.

Area What to describe Example
Tech stack Language, framework, major libraries TypeScript, React 18, Tailwind CSS
Project structure What lives where, what each folder means /components for UI, /lib for shared logic
Conventions Naming patterns, file organisation, style decisions PascalCase for components, kebab-case for files
Constraints What not to do — protected files, forbidden patterns Never modify db/schema.ts directly
Testing Testing framework, where tests live, what to cover Vitest, tests in __tests__/ next to the file

CLAUDE.md — the pattern Claude Code uses

Claude Code looks for a file called CLAUDE.md in the root of your project. If it exists, Claude reads it before responding to anything. The file has no required format — it's plain markdown, structured however you find useful. Here is a practical template:

CLAUDE.md — a working template
# Project overview
A customer dashboard built with Next.js and TypeScript.
Customers log in to view invoices, usage, and support tickets.

## Tech stack
- Language: TypeScript (strict mode)
- Framework: Next.js 14 (App Router)
- Styling: Tailwind CSS — use utility classes only, no custom CSS files
- Database: Postgres via Prisma ORM
- Testing: Vitest + React Testing Library

## Project structure
/app         — Next.js pages and layouts (App Router)
/components  — Shared UI components
/lib         — Business logic, utilities, API clients
/prisma      — Database schema and migrations

## Conventions
- Component files: PascalCase (UserCard.tsx)
- Utility files: camelCase (formatDate.ts)
- All components are functional — no class components
- Props interfaces named [ComponentName]Props

## Constraints
- Never modify /prisma/schema.prisma without asking first
- Do not introduce new dependencies without flagging it
- All user-facing strings must go through the i18n helper in lib/i18n.ts

## Testing
- Tests live in __tests__/ next to the file they test
- Cover happy path and one error case minimum
- Mock external API calls — never hit real endpoints in tests

That's 30 lines. It takes ten minutes to write. From that point on, Claude knows what it's working in — and you stop getting suggestions that introduce the wrong library, break the naming convention, or touch a protected file.

Subfolder CLAUDE.md files: Claude Code also reads CLAUDE.md files inside subfolders — and applies them only when working in that folder. A /api/CLAUDE.md can describe API-specific rules without cluttering the root file. More on this below.

How Cursor does the same thing

Cursor uses two mechanisms, depending on which version you're running. The older approach is a single .cursorrules file in the project root. The newer approach — and the one Cursor now recommends — is a folder called .cursor/rules/ containing one .mdc file per rule set.

The folder approach is more powerful because you can scope rules. A rule file can apply to the whole project, or only to specific file patterns:

Project-wide rule
Scoped to a file pattern
.cursor/rules/conventions.mdc

---
description: General coding conventions
alwaysApply: true
---

Use TypeScript strict mode.
PascalCase for components.
No default exports.
.cursor/rules/api-routes.mdc

---
description: API route rules
globs: app/api/**/*.ts
---

Always validate input with Zod.
Return typed responses.
Log errors with the logger
in lib/logger.ts.

The content of each rule file is identical to what you'd write in CLAUDE.md — plain English, structured with headings if you want them. The only difference is the frontmatter block at the top that tells Cursor when to apply it.

Scoping rules to where they matter

Both CLAUDE.md and Cursor's rule files support the same mental model: rules at the root apply everywhere, rules in a subfolder apply only there. This lets you keep the root file short and focused while handling special cases closer to where they occur.

A practical folder structure for a medium-sized project might look like this:

Folder structure — scoped rules
my-project/
  CLAUDE.md                   ← always read: stack, structure, conventions

  /api/
    CLAUDE.md                 ← read only in /api: auth patterns, rate limiting,
                                 response formats, error codes

  /components/
    CLAUDE.md                 ← read only in /components: design system tokens,
                                 accessibility rules, Storybook conventions

  /scripts/
    CLAUDE.md                 ← read only in /scripts: these are one-off tools,
                                 do not import from /lib, no tests needed

The root file handles what's always true. The subfolder files handle what's only true there. An AI working inside /api/ reads both — which means it gets the full picture without the root file having to cover every edge case in every corner of the codebase.

Less is more

The most common mistake when writing a coding configuration file is trying to document everything. You end up with a 400-line file that no human would read — and that the AI skims rather than follows. The file should fit in one screen. If it doesn't, it's doing too much.

A few principles that keep it useful:

  • Write constraints, not obvious facts. "Use TypeScript" is only useful if there's a risk someone might use JavaScript instead. "Never import from /internal — that package is deprecated" is always useful.
  • Update it when something breaks. The best time to add a rule is immediately after the AI did the wrong thing. That's the moment you know exactly what needs saying.
  • Delete rules that no longer apply. A stale rule is worse than no rule — it creates confusion about what's actually true.
  • One file per concern. If you're using Cursor's folder approach, keep each rule file to one topic. A file about API conventions should not also cover component naming.

A useful test: Read your configuration file out loud as if you were briefing a new developer. If any sentence sounds like something they'd already know, cut it. If any sentence would make them say "oh, I wouldn't have guessed that" — keep it. That's the content worth writing down.

Done right, a coding configuration file is something you write once, update occasionally, and rarely think about. It runs in the background and the AI behaves the way you expect it to. That's the goal — not a comprehensive specification, but a reliable briefing.

Further reading: Build your own agent with Markdown · Spec-driven development: the full workflow · Markdown as RAG — your own lightweight context layer