Home / Blog / I Wired Cursor Rules Into Our Production Codebase ...

I Wired Cursor Rules Into Our Production Codebase — Now I Can't Tell if It's Brilliant or Terrifying

By CaelLee | | 9 min read

I Wired Cursor Rules Into Our Production Codebase — Now I Can't Tell if It's Brilliant or Terrifying

TIL that Cursor Rules isn't just some glorified .cursorrules file — it's basically a prompt injection system that silently feeds your AI assistant context before every single request. And I've spent the last two weeks wiring it into our production codebase. I'm not entirely sure if I've made our team more productive or accidentally built a paperclip maximiser.

The "aha" moment came at 2 AM last Tuesday. I'd been manually pasting the same 200 lines of "remember to use our custom React hooks, don't import from lodash directly, and for the love of god use the shared Button component" into every. single. chat. session. Like some kind of digital peasant performing a ritual to appease the AI gods. My girlfriend woke up and asked why I was laughing. I wasn't laughing. I was having a quiet breakdown whilst staring at a screen full of linting errors.

What Cursor Rules actually does (the coffee-shop explanation)

Think of it as a pre-prompt that gets injected before your actual query. You define rules in the .cursor/rules/ directory, and Cursor's AI reads them before processing whatever you type. The clever bit is that it's contextual — you can scope rules to specific file patterns, directories, or even git branches. I think. I'm still figuring out the branch scoping, to be honest.

Here's the basic structure:


globs: "src/components/**/*.tsx"
alwaysApply: false
# Component Rules
- All components must use 'use client' directive
- Props interfaces must be exported
- Use our custom useFormState hook, not React's useReducer

Wait — I should clarify that the globs pattern is a bit weird. It uses minimatch syntax, not actual glob. Took me an embarrassing 45 minutes to figure out why src/*/components/ wasn't matching anything. The error message was just "no files matched." Cheers for that. Super helpful.

The three examples that completely sold me on this

1. The "Stop Importing Lodash" Rule

We have a strict "no lodash" policy at work. Bundle size wars, don't ask — our Staff Engineer is still fuming about that one incident in Q3 2023. Before rules, I'd catch AI-generated code doing import _ from 'lodash' roughly 47 times per day. I counted. After adding a rule that says "Never import lodash. Use our utils/helpers.ts instead," it dropped to...

Zero.

ZERO.

I literally checked the git history three times because I didn't believe it. Even made our intern spot-check a few PRs. Nothing. The rule looks like:


globs: "**/*.{ts,tsx}"
- NEVER import from 'lodash' or 'lodash/*'
- Use '@/utils/helpers' for array/object utilities
- Prefer native Array methods (map, filter, reduce)

The only downside? The AI now suggests our @/utils/helpers for literally everything. Need to capitalise a string? helpers.capitalize(). Need to check if something is null? helpers.isNull(). We're basically building our own lodash. The irony is not lost on me.

2. The "Our Custom Hooks Exist, Please Use Them" Debacle

We have this beautiful useApiQuery hook. Handles caching, error states, loading states, retry logic — the works. Took our team three sprints to get right. Before rules, the AI would generate useEffect with fetch() calls like it was 2015 and React Hooks hadn't been invented yet. I wanted to scream into a pillow.

After adding a rule scoped to our src/hooks/ directory:


globs: "src/**/*.tsx"
- Data fetching MUST use useApiQuery from '@/hooks/useApiQuery'
- Never use useEffect + fetch for API calls
- useApiQuery returns { data, isLoading, error, refetch }

The AI started generating code that actually looked like a senior dev wrote it. Even better — it started suggesting refactors of old code to use the hook. That's when I got properly unsettled. It found a 14-month-old component in our billing feature that was using raw fetch, and the AI was like "hey, want me to fix this?"

I said yes.

It worked.

I closed my laptop and went for a walk around the block. Twice.

3. The "Project Structure Amnesia" Fix

This one's subtle but devastating. Our project uses a feature-based folder structure:


src/features/[feature-name]/
 components/
 hooks/
 utils/
 types/

The AI kept creating files in src/components/ like a lost puppy. Added a rule:


globs: "src/**/*"
- New components go in src/features/[feature]/components/
- Feature directories contain: components, hooks, utils, types
- Shared code goes in src/shared/, not src/common/ or src/utils/

Now the AI actually asks "which feature does this belong to?" before generating file paths. It's like watching a junior dev finally understand the codebase after six months. Except this junior dev never sleeps, never takes annual leave, and costs roughly £16/month.

The dark side nobody talks about

Here's where I get honest. This system is basically prompt injection at scale, and it's fragile as hell.

Last week, I had a rule that said "Use TypeScript strict mode conventions." The AI interpreted this as "add as any to everything because strict mode is hard." Took me four hours to debug why our type safety had gone completely pear-shaped. The worst part? It was in our payment processing module. Four hours of "wait, why is this returning any?" followed by increasingly desperate console.log statements. I aged about six months that afternoon.

Another time, two rules conflicted. One said "prefer functional components" and another said "use class components for error boundaries." The AI had some kind of existential crisis and generated a component that was somehow both. I'm not even mad — that's genuinely impressive. It was a functional component that returned a class component constructor. I wish I was joking. The error message was something like:


TypeError: Component is not a constructor
 at renderWithHooks (react-dom.development.js:16352)

Took me 20 minutes of staring at it before I realised what happened. Then I laughed. Then I cried a little. It's art, honestly.

The "oh no" moment

Yesterday morning — specifically at 10:47 AM whilst drinking my third coffee of the day — I realised our rules file has grown to 400 lines. It's become its own configuration hell. We're essentially maintaining a parallel codebase of AI instructions. The junior devs (we have two, both hired in the last six months) treat it like gospel and don't question the AI's output anymore. I caught someone merging AI-generated code that passed all the rules but was objectively terrible architecture.

Like, the rules said "use useApiQuery for data fetching" so they did. But they also fetched the same endpoint four times in a single render because "the rules didn't say I couldn't."

Well... that's complicated. The rules shouldn't have to say that. That's just... knowing how React works. But here we are.

Nope.

This is the same problem we had with linters five years ago. "ESLint didn't complain, so it must be fine!" Now it's "Cursor Rules didn't flag it, ship it!" Remember when we all thought Prettier would solve our formatting arguments? It did — and created a whole new class of "well the formatter did this weird thing but I'm not going to fix it" problems. Plot twist: the tools we build to save us from ourselves just create new ways for us to be lazy.

What I've learned (your mileage may vary)

  1. Rules are not a substitute for code review. They're guardrails, not architects. Our team learned this the hard way during the Great as any Incident of January 2025. I still have Slack threads I can't bring myself to delete.
  1. Keep rules atomic and minimal. Each rule should do one thing. When they get long, the AI starts ignoring parts. I've found ~10-15 lines per rule is the sweet spot. Probably. I'm still experimenting, if I'm honest.
  1. Test your rules. Seriously. We now have a test suite of prompts and verify the output in CI. It's janky as hell — basically a bash script that pipes prompts into the Cursor CLI and greps for patterns. But it caught three regressions last week alone. I'll probably open-source it once it's less embarrassing. Give me a month or two.
  1. The alwaysApply: false setting is your friend. Some rules should only fire when you're in specific contexts. Don't blast your entire codebase with every rule. Learned this after the AI started suggesting our React patterns in our Python scripts. That was a weird PR review. "Why is the data pipeline using useEffect?" — a question I never want to ask again.
  1. Version your rules. We treat .cursor/rules/ like any other config — it's in git, reviewed in PRs, and has changelog entries. Our changelog for v2.3.1 literally says "stopped AI from suggesting var in 2025." We're living in the future and it's weird.

The existential question

Are we just building increasingly elaborate prompt templates? At what point does the rules file become more complex than just writing the damn code ourselves? I've asked myself this at 3 AM more times than I'd like to admit.

I don't have an answer. But I do know that watching the AI generate a perfectly structured feature with proper hooks, no lodash imports, and correct file placement feels like actual magic. Until it doesn't, and you spend three hours debugging why it decided useState is deprecated (it's not — the AI hallucinated that from a rule about avoiding legacy patterns). The rule said "avoid class component lifecycle methods" and somehow the AI mapped that to "useState is legacy" and started using some weird useReducer pattern for everything from form inputs to boolean toggles. I wish I were making this up.

My therapist says I should find a hobby that doesn't involve YAML files. She might be right.

Key Takeaways

Worth it? Yes. Terrifying? Also yes. I've aged approximately three years in the last two weeks.

Edit: Thanks for the gold! To answer the common question: yes, we're open-sourcing our rule templates. Give me a week to sanitise them. Need to remove all the comments where I wrote "DO NOT TOUCH THIS OR EVERYTHING BREAKS" at 3 AM.

Edit 2: Several people asked about the "class component + functional component hybrid" the AI generated. It was a functional component that returned a class component constructor. The diff is in my comment history somewhere. It's genuinely art.

Edit 3: To the person who DM'd me saying "just write the code yourself then" — you're not wrong. But also, I shipped three features last week whilst you were still writing your first useEffect. Just saying.

What's your experience with AI coding rules? Anyone else accidentally create a Skynet configuration file, or is that just me? Drop a comment below — I need to know I'm not alone in this beautiful disaster.

cursor #ai-coding #developer-tools #typescript #webdev

C

Cael Lee

Full-stack developer with 8+ years of experience. Currently building AI-powered developer tools. I've tested 20+ AI API providers and coding assistants.

Ready to get started?

Get your API key and start building with 180+ AI models.

Get API Key Free