Random Thoughts

Developer tooling

Rules as project memory

Thursday, April 23, 2026

  • ai-assisted
  • #ai
  • #ai-agents
  • #vibecoding
  • #developer-experience
  • #yaml
  • #glob
  • #configuration
  • #markdown
  • #cursor
  • #claude
Isometric technical illustration in confident pen-and-ink line work with deliberate cross-hatching for shading, on a warm cream paper background. A tall wooden filing cabinet sits in three-quarter isometric perspective on a thin hatched plinth. The cabinet has six drawers stacked vertically, each drawer subtly different from the next: different handle styles (round brass knob, horizontal pull bar, recessed cup pull, ringed loop) and different label-frame shapes on each drawer front (small rectangle, oval, hexagon, rounded square, lozenge, circle), with different drawer-face hatching densities. The label frames are empty — small hand-drawn frames containing nothing. Two drawers are slightly pulled open, revealing folded sheets of paper inside, and on each visible sheet a single small icon is drawn — one bears a tiny pencil-tip motif, the other a tiny padlock motif — to suggest different kinds of guidance. Around the cabinet, several small empty rounded chat-bubble shapes hover in the air, each connected to one specific drawer's label frame by a thin pen-line route, the lines curving with the precision of a vintage how-things-work textbook. Soft hatched shadow pools beneath the cabinet. Sepia and warm grey ink on cream paper, confident outlines, generous whitespace, no readable text or letters anywhere in the composition.
Each drawer has its own opening pattern. The agent only opens the drawers that match what it's working on right now.

An AI coding agent starts every conversation with the same problem: it has no idea how your project works. It knows generic Python, generic React, generic Markdown — but it doesn’t know that your codebase puts utility functions in helpers/, or that this particular service uses Pydantic v2, or that all your blog posts must end with a “Further reading” section.

You can teach it those things in chat, every single session, forever. Or you can write rules.

This post is about rules — what they are, how they get loaded, when to use them versus other tools, and what makes a good one. The examples are from this blog’s own setup, because that’s the most concrete one I have.

The smallest possible rule

A rule is a Markdown file with YAML frontmatter, sitting in a folder the agent watches. The frontmatter is config. The body is guidance.

---
description: Voice and tone guide for blog posts
globs:
  - "src/content/posts/**/*.md"
  - "src/content/posts/**/*.mdx"
alwaysApply: false
---

# Blog writing conventions

When editing a post, prefer short paragraphs in casual posts.
Don't over-polish — leave the author's voice intact.

That’s the whole shape. Three frontmatter fields, a body in Markdown, save it as .cursor/rules/blog-writing-conventions.mdc (or CLAUDE.md in a folder, or whatever your tool calls it — the file format varies, the idea doesn’t), and the agent will load it the next time it touches a matching file.

Most modern AI coding agents have some version of this. Cursor calls them rules. Claude Code calls them CLAUDE.md. Other tools have their own names. The file format isn’t standardized yet, but the underlying concept is: per-project, per-file-pattern guidance, loaded automatically into the agent’s context.

I’m going to write this post in Cursor’s .mdc format because that’s what I use. The patterns transfer. If you’re on a different tool, the equivalent files will look slightly different but the thinking is the same.

The frontmatter does the routing

The body of a rule is just guidance — pretty straightforward Markdown. The interesting part is the frontmatter, because it controls when the rule attaches.

There are roughly three modes:

---
alwaysApply: true
---

This rule is loaded into every conversation in the project. Use sparingly. The agent’s context window has a budget, and rules that are always loaded burn it up whether or not they’re relevant. Reserve alwaysApply: true for things that genuinely apply to every file — coding standards, behavioral guardrails, security policies.

---
description: Voice guide for blog posts
globs:
  - "src/content/posts/**/*.md"
alwaysApply: false
---

This rule loads only when the agent is touching a file that matches one of the globs. Editing src/content/posts/2026-04-24-rules-as-project-memory.md? The rule attaches automatically. Editing src/components/Button.astro? The rule stays out of the way.

This is the mode I use most. It scales. You can have a dozen rules in a project, each scoped to a different folder or filetype, and only the relevant ones load for any given task.

---
description: Add a new search filter to the AI agent pipeline
alwaysApply: false
---

No globs, not always-applied. This rule shows up in the agent’s catalog of available rules, but it only attaches when the agent decides it’s relevant — usually because the user’s request matches the description. Use this for procedural rules that aren’t tied to a file, like “the steps to add a new feature of type X.”

The three modes together let you build a rule library where each rule is loaded only when it’s useful. That sounds obvious. It’s not what most projects do. Most projects either dump everything into one giant always-on file (which costs tokens on every request and makes the agent’s instructions mushy) or skip rules entirely (which leaves the agent to reinvent the project conventions every session). Routed rules are the middle path.

Isometric technical illustration in confident pen-and-ink line work with cross-hatching for shading, on a warm cream paper background. A long horizontal rounded-rectangle lane runs across the middle of the composition, drawn in three-dimensional isometric perspective with subtle hatched shading beneath it — this is the active working context. To the upper left, a vertical column of six small folded paper sheets floats in the air, each sheet rendered with a corner fold and a single tiny icon stamped at its top (a quill, a small key, a gear, a brushstroke, a tag, a gauge — no two icons alike, no text on any sheet). From each sheet, a thin curving pen-line arrow descends toward the central lane: only three of the six lines actually connect to the lane and ride along its top surface; the other three fade into dotted dashes that thin out and dissolve before reaching it. Below the central lane, a small inset cross-section shows a single piece of paper being touched by a small drawn hand, indicating the file the agent is currently working on. Cross-hatched textbook shading throughout, sepia and warm grey ink on cream paper, no readable text or letters anywhere in the composition.
The glob is the routing slip. The rule waits in the cabinet until the agent opens a file that matches its pattern.

What rules are good for

Rules are good for conventions that apply to a file or folder, that don’t change session to session, and that the agent would not figure out on its own.

Concretely:

  • Project-specific conventions. “All API routes go in apps/api/routes/. Use FastAPI dependency injection for auth. Pydantic v2 schemas live in schemas/.”
  • Voice or style guides. This blog’s writing-conventions rule is exactly that. The agent has no way to infer my voice. The rule tells it.
  • Decision logic that the agent should follow. “Use category X for posts about A, category Y for posts about B.” A few lines that save dozens of “actually it should be Y” follow-ups.
  • Safety rails. “Don’t include real client names in any file under .cursor/rules/.” This is the kind of constraint that, once written, prevents a recurring mistake forever.
  • Required structure. “Every blog post must end with a ## Further reading section.” Without the rule, the agent forgets one out of three times. With it, the agent doesn’t forget.

What rules are not good for

This is the part that took me a while to understand.

Rules are not for one-off tasks. If you find yourself writing a rule for a thing you’re going to do once, you’ve written a prompt instead. Just put that text in your message.

Rules are not for things that depend on live state. If the answer changes session to session — “what’s the current open job count in the system?” — that’s not a rule. That’s a tool call or a skill (which I’ll write about later).

Rules are not for code. If you’re tempted to put a function inside a rule body and have the agent paste it everywhere, write a code utility instead and let the agent import it. Rules are for guidance the agent should follow when generating code, not for code itself.

Rules are not for replacing review. A rule that says “always validate inputs” is useful but doesn’t substitute for actually reading what the agent produces. Rules raise the floor; they don’t ceiling-cap what can go wrong.

The biggest mistake I see — including from myself, repeatedly — is reaching for a rule when the better tool is a different abstraction. Rules are one mechanism among several. They’re not always the answer.

A rule is best when it’s small

The temptation, once you’ve started writing rules, is to make them long. Big detailed rule files that cover every edge case. Rules with subsections and sub-subsections. Rules that try to be the project’s full design doc.

That fights the way the agent uses them. The agent reads the rule and treats every sentence as guidance. Long rules dilute the important guidance with low-priority guidance. Long rules also burn more of the context budget, which means less room for the actual file you’re editing.

The rules that actually changed the agent’s behavior, for me, were the short, opinionated ones. A page of tight prose. A few headed sections. A list of things to avoid. A list of things to keep. That’s enough.

When a rule grows past two pages, I start asking whether it’s two rules trying to be one. Most of the time it is.

Rules and skills, in one sentence

A few people will read this and ask: how is a rule different from an “agent skill” or a “subagent”? Both of those will get their own posts. The very short version:

  • Rules load automatically when files match. They steer the agent’s behavior on existing tasks.
  • Skills are loaded on demand by name. They’re more like reusable procedures or playbooks.
  • Subagents are isolated invocations of a smaller agent for a specific task. They keep work out of your main context.

You’ll usually need all three. Rules are the foundation because they’re cheap and ambient. The other two come into play when you’ve outgrown what rules alone can do.

Isometric technical illustration diptych in pen-and-ink with cross-hatching, on a warm cream paper background. The scene is split down the middle by a thin vertical pen line. The left panel shows a small drawn figure standing at a desk in three-quarter isometric perspective, in front of a screen on which a long scroll of paper unfurls from the top edge and pools onto the desk; the scroll is blocked out as densely stacked horizontal hatch-bars suggesting many lines of instructions, with no readable text. To the side of the desk, a small output tray holds a stack of papers; the topmost paper carries a tiny pen-drawn flag with an X-mark stamped on it. The right panel shows the same isometric workbench, but the scroll falling from the screen is now only a small folded card with two short hatch-lines on it. Above the screen on this side, a small folded rule-paper shape with a corner fold floats in the air and feeds into the screen via a thin pen line. The output tray here holds a clean stack of papers, the topmost carrying a small check-mark flourish stamp. Cross-hatched textbook shading, sepia and warm grey ink on cream paper, vintage how-things-work feel, no readable text or letters anywhere in the composition.
The rule moves the conventions out of every prompt and into a file the agent reads automatically. The chat gets shorter; the output gets steadier.

How I write a new rule

When I sit down to write a new rule, I roughly follow this:

  1. What’s the recurring problem? A rule is worth writing when the agent has made the same mistake twice. Once is bad luck; twice is a pattern.
  2. What’s the smallest sentence that fixes it? Try to write the rule in one sentence first. If that’s enough, you have your rule. If not, expand only as much as you need.
  3. What’s the right glob? Where will the agent be when this guidance matters? That’s the glob. Resist the urge to make it **/* — narrow scope produces sharper steering.
  4. Will I want to find this six months from now? Give it a clear filename. blog-writing-conventions.mdc is greppable in a way that style.mdc isn’t.
  5. Run it for a session and edit afterwards. The first version is always slightly off. Use it on a real task, watch where the agent still misses, edit the rule. Two or three iterations is normal.

That’s the whole loop. Most of my rules took thirty minutes of writing and another hour of editing across the next few sessions of using them.

They compound

The thing I didn’t predict, when I started writing rules a few months ago, was how much they’d compound.

Each rule, by itself, is a small steering. A nudge. The output gets a little better in one specific way. The first few rules feel almost not worth writing — I’m doing all this metawork to save a few seconds per session.

Then you have a dozen rules. The agent now knows your voice, your project structure, your security policy, your testing conventions, your category logic, your image format, your safety rails, your further-reading pattern. Every session starts with all of that already in place. The conversation isn’t less rich — it’s the same kind of conversation as before, but now the bottom layer is solved. Your prompts can be shorter. The agent’s outputs can be sharper. The mistakes you used to correct over and over have stopped happening.

That’s the moment when rules feel less like configuration and more like memory. The project remembers how it works. The agent picks up that memory automatically. Your conversation can be about the actual problem, not about reminding the agent of last week’s decisions.

That’s not nothing. That’s most of why I write them.

Further reading