我花了2周把项目规范自动注入Cursor
Experience: I finally got Cursor Rules to auto-inject context and project conventions, and it's both amazing and 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.
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. My girlfriend woke up and asked why I was laughing. I wasn't laughing. I was having a breakdown.
What Cursor Rules actually does (ELI5 version)
Think of it as a pre-prompt that gets injected before your actual query. You define rules in .cursor/rules/ directory, and Cursor's AI reads them before processing whatever you type. The magic 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 tbh.
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 useReducerActually, wait—I should clarify that the globs pattern is a bit weird. It uses minimatch syntax, not 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." Super helpful.
The three examples that sold me on this
1. The "Stop Importing Lodash" Rule
We have a strict "no lodash" policy (bundle size wars, don't ask—our Staff Engineer is still mad about that one incident in Q3 2023). Before rules, I'd catch AI-generated code doing import _ from 'lodash' roughly 47 times per day. 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 had 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 capitalize 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 that handles caching, error states, loading states, and retry logic. Took our team 3 sprints to get right. Before rules, the AI would generate useEffect with fetch() calls like it was 2015. I wanted to scream.
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 scared. Like, 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.
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 6 months. Except this junior dev never sleeps, never takes PTO, and costs $20/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 4 hours to debug why our type safety went to shit. 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.
Another time, two rules conflicted. One said "prefer functional components" and another said "use class components for error boundaries." The AI had an existential crisis and generated a component that was somehow both. I'm not even mad—that's 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 realized what happened. Then I laughed. Then I cried a little.
The "oh no" moment
Yesterday morning—specifically at 10:47 AM while drinking my third coffee—I realized 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 6 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 4 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.
This is the same problem we had with linters 5 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.
What I've learned (YMMV)
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.
2. 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.
3. 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 3 regressions last week alone. I'll probably open-source it once it's less embarrassing.
4. 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.
5. 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."
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 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 magic. Until it doesn't, and you spend 3 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).
My therapist says I should find a hobby that doesn't involve YAML files. She might be right.
TL;DR: Cursor Rules auto-injects context before AI requests, and it's transformed how our team uses AI coding assistants. We've eliminated entire categories of common mistakes. But it's also created new problems: rule conflicts, AI over-reliance, and a 400-line config file that's becoming its own maintenance burden. Worth it? Yes. Terrifying? Also yes. I've aged approximately 3 years in the last 2 weeks.
Edit: Thanks for the gold! To answer the common question: yes, we're open-sourcing our rule templates. Give me a week to sanitize 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 art, honestly.
Edit 3: To the person who DM'd me saying "just write the code yourself then"—you're not wrong. But also, I shipped 3 features last week while 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?
#cursor #ai-coding #developer-tools #typescript #webdev
读者评论 5