<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ned C</title>
    <description>The latest articles on DEV Community by Ned C (@nedcodes).</description>
    <link>https://dev.to/nedcodes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3765244%2F0d6184b8-d8bb-4f0d-a0ae-2190f562f9f6.png</url>
      <title>DEV Community: Ned C</title>
      <link>https://dev.to/nedcodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nedcodes"/>
    <language>en</language>
    <item>
      <title>How to vet Cursor rules before using them</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Thu, 05 Mar 2026 22:58:59 +0000</pubDate>
      <link>https://dev.to/nedcodes/how-to-vet-cursor-rules-before-using-them-a7c</link>
      <guid>https://dev.to/nedcodes/how-to-vet-cursor-rules-before-using-them-a7c</guid>
      <description>&lt;p&gt;You're browsing &lt;a href="https://github.com/PatrickJS/awesome-cursorrules" rel="noopener noreferrer"&gt;awesome-cursorrules&lt;/a&gt;, or someone shared a &lt;code&gt;.cursorrules&lt;/code&gt; file in Discord, or you found a repo on GitHub with rules that look perfect for your stack.&lt;/p&gt;

&lt;p&gt;Before you copy it into &lt;code&gt;.cursor/rules/&lt;/code&gt;, check if it actually works. Most community rules have at least one critical issue. Some are completely broken.&lt;/p&gt;

&lt;p&gt;I grabbed 4 popular rule sets from awesome-cursorrules and ran them through a linter. &lt;strong&gt;100% were missing frontmatter. 75% were too long. 50% used vague language that Cursor ignores.&lt;/strong&gt; They're good starting points, but none of them work correctly out of the box.&lt;/p&gt;

&lt;p&gt;Here's the checklist i use before adopting any rule set i find online.&lt;/p&gt;

&lt;h2&gt;
  
  
  the 5-point vetting checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Quick version:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✓ Does it have YAML frontmatter? (description, alwaysApply or globs)&lt;/li&gt;
&lt;li&gt;✓ Is the body under 2000 characters?&lt;/li&gt;
&lt;li&gt;✓ Does it cover one concern, not five?&lt;/li&gt;
&lt;li&gt;✓ Are instructions specific and imperative?&lt;/li&gt;
&lt;li&gt;✓ Does it conflict with your existing rules?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any of these fail, the rule either won't work at all, will waste your context window, or will confuse Cursor into ignoring you. Let's go through each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  check 1: does it have YAML frontmatter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to look for:&lt;/strong&gt; A block at the top of the file between &lt;code&gt;---&lt;/code&gt; markers with at least &lt;code&gt;description&lt;/code&gt; and either &lt;code&gt;alwaysApply&lt;/code&gt; or &lt;code&gt;globs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; Without frontmatter, Cursor doesn't know when to activate the rule, which files it applies to, or how to prioritize it. The rule might load unpredictably or never load at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ No frontmatter (won't work):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js 15, React 19, TypeScript best practices.

Code Style and Structure
- Write concise TypeScript code with accurate examples.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Has proper frontmatter:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Next.js + React + TypeScript best practices&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.ts"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.tsx"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app/**/*"&lt;/span&gt;
&lt;span class="na"&gt;alwaysApply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="s"&gt;Code Style and Structure&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Write concise TypeScript code with accurate examples.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; If there's no frontmatter, add it. If you want the rule to apply everywhere, use &lt;code&gt;alwaysApply: true&lt;/code&gt;. If you want it scoped to specific files, use &lt;code&gt;globs&lt;/code&gt; with patterns like &lt;code&gt;**/*.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real data:&lt;/strong&gt; All 4 rule sets i tested from awesome-cursorrules were missing frontmatter entirely. This was the #1 issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  check 2: is it under 2000 characters?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to look for:&lt;/strong&gt; Open the file in your editor. Check the character count or line count. If it's over 2000 characters (roughly 500+ tokens), it's probably too long.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; Every rule with &lt;code&gt;alwaysApply: true&lt;/code&gt; gets loaded into Cursor's context window on every request. Long rules waste tokens that could be used for your actual code. One 4,000-character rule burns ~1,100 tokens every time it loads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; Split long rules into focused ones. If a rule covers "naming conventions, error handling, and file structure," make three separate files: &lt;code&gt;naming.mdc&lt;/code&gt;, &lt;code&gt;errors.mdc&lt;/code&gt;, &lt;code&gt;structure.mdc&lt;/code&gt;. Use &lt;code&gt;globs&lt;/code&gt; to scope each one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real data:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 out of 4 rule sets i tested were over 2000 chars&lt;/li&gt;
&lt;li&gt;Longest was 3,914 bytes (~1,077 tokens)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; If a rule file has more than 50 lines, it's probably mixing concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  check 3: does it mix concerns?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to look for:&lt;/strong&gt; Read through the instructions. Does it cover naming conventions, types, architecture, styling, and error handling all in one file? That's five different rules pretending to be one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; When a rule tries to do everything, Cursor struggles to apply it correctly. One file covering "use camelCase for variables" and "implement error boundaries" and "structure components as feature folders" is confusing. Each instruction competes for attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; One rule, one concern. If you see multiple topics, split the file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ Mixing concerns:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;React standards&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src/**/*.tsx"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="s"&gt;Use PascalCase for components.&lt;/span&gt;
&lt;span class="s"&gt;Use camelCase for variables.&lt;/span&gt;
&lt;span class="s"&gt;Wrap route components in error boundaries.&lt;/span&gt;
&lt;span class="s"&gt;Keep components under 50 lines.&lt;/span&gt;
&lt;span class="s"&gt;Use CSS modules for styling.&lt;/span&gt;
&lt;span class="s"&gt;Store reusable logic in hooks/.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Focused on one concern:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;// naming.mdc&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;React component and variable naming&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src/**/*.tsx"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;Use PascalCase for components.&lt;/span&gt;
&lt;span class="s"&gt;Use camelCase for variables and functions.&lt;/span&gt;

&lt;span class="s"&gt;// error-handling.mdc&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Error boundaries for route components&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src/app/**/*.tsx"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src/pages/**/*.tsx"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;Wrap every route-level component in an error boundary.&lt;/span&gt;
&lt;span class="s"&gt;Provide a fallback UI with a retry button.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real data:&lt;/strong&gt; 3 out of 4 rule sets i tested mixed multiple concerns in one file. This makes rules harder to scope with globs and burns tokens on instructions that don't apply to the current file.&lt;/p&gt;

&lt;h2&gt;
  
  
  check 4: is the language specific?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to look for:&lt;/strong&gt; Scan for phrases like "try to," "consider," "you might want to," "follow best practices," "write clean code."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; AI models follow imperative commands better than suggestions. "Try to keep functions small" gives Cursor permission to ignore you. "Keep functions under 20 lines, extract helpers for longer logic" is a concrete instruction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ Vague language:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Consider using functional components.
Try to keep functions small.
It's recommended to handle errors properly.
Follow React best practices.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Specific language:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use functional components with hooks. No class components.
Keep functions under 20 lines. Extract helpers for longer logic.
Wrap all async route handlers in try-catch blocks.
Prefix custom hooks with "use". Prefix utility functions with the module name.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; Replace every "try to" with a direct command. Replace "follow best practices" with the actual practice. Replace "write clean code" with measurable rules like "max 20 lines per function."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real data:&lt;/strong&gt; 2 out of 4 rule sets i tested used weak language like "consider" or "try to." These instructions don't change model behavior. They just waste tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  check 5: does it conflict with your existing rules?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to look for:&lt;/strong&gt; If you already have rules in &lt;code&gt;.cursor/rules/&lt;/code&gt;, check for contradictions. Does the new rule say "use semicolons" while your existing rule says "omit semicolons"? Does it say "use double quotes" while you enforce single quotes?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; When two rules contradict each other, Cursor picks one unpredictably. You won't get a warning. The AI will just follow whichever rule it loaded first or weighted higher.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; Before adding a new rule, run &lt;code&gt;npx cursor-doctor lint&lt;/code&gt; to check for conflicts. If you find one, either delete the conflicting instruction from the new rule or remove the old rule entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; This is the hardest check to do manually. Automated linting catches conflicts you'd never spot by reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  the automated way (10 seconds)
&lt;/h2&gt;

&lt;p&gt;You can check all five of these manually, or you can run one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It scans every &lt;code&gt;.mdc&lt;/code&gt; file in your project and flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing or malformed frontmatter&lt;/li&gt;
&lt;li&gt;Rules over 2000 characters&lt;/li&gt;
&lt;li&gt;Vague language patterns ("try to", "consider", "best practices")&lt;/li&gt;
&lt;li&gt;Conflicting instructions between rules (48 semantic patterns)&lt;/li&gt;
&lt;li&gt;Empty globs arrays&lt;/li&gt;
&lt;li&gt;Windows-style backslashes in globs&lt;/li&gt;
&lt;li&gt;YAML syntax errors and boolean strings&lt;/li&gt;
&lt;li&gt;100+ other checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you paste a rule you found online, save it to &lt;code&gt;.cursor/rules/test-rule.mdc&lt;/code&gt; and run the linter. Fix what it flags, then decide if it's worth keeping.&lt;/p&gt;

&lt;h2&gt;
  
  
  real example: vetting a rule from awesome-cursorrules
&lt;/h2&gt;

&lt;p&gt;I grabbed the Next.js + React + TypeScript + Tailwind rule from awesome-cursorrules. Here's what cursor-doctor found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cursor-doctor v1.10.24 -- lint

nextjs-react-tailwind.mdc  (3 warnings)
  ⚠ Missing YAML frontmatter
    → Add description, alwaysApply or globs so Cursor knows
      when to load this rule.
  ⚠ Rule body is very long (3,914 bytes)
    → Shorter, specific rules outperform long generic ones.
      Consider splitting into focused rules.
  ⚠ Rule uses weak language: "try to/maybe/consider"
    → AI models follow commands better than suggestions. Use
      imperative mood: "Do X" instead of "try to do X".

──────────────────────────────────────────────────
3 warnings, 0 passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three warnings from one file. And that's just what the linter catches automatically. Reading through the rule manually, i also noticed it mixes naming conventions, architecture patterns, and styling rules all in one file.&lt;/p&gt;

&lt;p&gt;After fixing the frontmatter, splitting it into 3 focused rules, and replacing vague language with concrete commands, it passed with no warnings.&lt;/p&gt;

&lt;h2&gt;
  
  
  when to skip a rule entirely
&lt;/h2&gt;

&lt;p&gt;Some rules aren't worth fixing. Skip the rule if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's over 5,000 characters. That's 1,250+ tokens. Not worth it.&lt;/li&gt;
&lt;li&gt;It starts with "You are an expert in..." These preambles waste 10-15 tokens and don't improve output.&lt;/li&gt;
&lt;li&gt;It's mostly examples. One or two examples are fine. Eight examples are token waste.&lt;/li&gt;
&lt;li&gt;It uses JavaScript/JSON syntax instead of markdown. Cursor reads markdown, not code.&lt;/li&gt;
&lt;li&gt;It's a list of technologies with no actual instructions. "Next.js 15, React 19, TypeScript, Tailwind" tells Cursor nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If more than half the file is noise, don't bother. Write your own rule from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  rules worth using without modification
&lt;/h2&gt;

&lt;p&gt;A few patterns i've found that usually work out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rules under 1,000 characters with proper frontmatter&lt;/li&gt;
&lt;li&gt;Rules scoped to a specific framework or library (e.g., "Svelte component conventions")&lt;/li&gt;
&lt;li&gt;Rules that provide concrete examples for complex patterns (e.g., "How to structure tRPC routers")&lt;/li&gt;
&lt;li&gt;Rules with clear, imperative language and no fluff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are rare. Most rules need at least some cleanup.&lt;/p&gt;

&lt;h2&gt;
  
  
  frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How do i know if a Cursor rule set is good?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check five things: (1) Does it have YAML frontmatter with &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;alwaysApply&lt;/code&gt;, and &lt;code&gt;globs&lt;/code&gt;? (2) Is the body under 2000 characters? (3) Does it cover one concern, not multiple? (4) Are instructions specific and imperative, not vague? (5) Does it conflict with your existing rules? You can check all five automatically with &lt;code&gt;npx cursor-doctor lint&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's wrong with rules from awesome-cursorrules?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When i tested 4 popular rule sets from awesome-cursorrules, 100% were missing YAML frontmatter, 75% were too long and wasted tokens, 75% mixed multiple concerns in one file, and 50% used weak language like "consider" or "try to." They're good starting points but need fixing before use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long should a Cursor rule be?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Under 2000 characters. Rules longer than 2000 chars burn 500+ tokens every time they load. If your rule is longer, split it into multiple focused rules with specific globs instead of one mega-rule with &lt;code&gt;alwaysApply: true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should i use alwaysApply true or globs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;globs&lt;/code&gt; to scope rules to specific file types. Reserve &lt;code&gt;alwaysApply: true&lt;/code&gt; for universal rules that apply to every file, like "no console.log in production." Most rules should use &lt;code&gt;globs&lt;/code&gt; to avoid wasting tokens on files where the rule doesn't apply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can i trust rules from GitHub repos?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most public Cursor rules have at least one issue. I scanned 50 real GitHub projects and found that 60% had a health score of C or lower. Always run &lt;code&gt;cursor-doctor lint&lt;/code&gt; on any rule you find before using it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Vet your rules in 10 seconds:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or paste a single rule into the &lt;a href="https://nedcodes.dev/playground" rel="noopener noreferrer"&gt;playground&lt;/a&gt; for instant feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;Full documentation&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


---

## Success Criteria Verification

✅ **Clearly different from the 50-projects article** (checklist format vs survey format)  
✅ **Actionable** (reader can vet rules after reading with 5-point checklist)  
✅ **Uses research data as supporting evidence** (stats cited as "Real data:" not main story)  
✅ **SEO optimized** (keywords, structured data, FAQPage schema, canonical URL)  
✅ **Lowercase headers** (all headers follow style guide)  
✅ **No em dashes** (used commas, periods, restructured)  
✅ **No buzzwords** (no "game-changer", "deep dive", "level up", etc.)  
✅ **No praise openers** (starts with problem statement)  
✅ **First person, casual** ("i grabbed", "i tested", "here's what")  
✅ **Every claim sourced** (research data cited with specific numbers)  
✅ **No dropped subjects** (all sentences have explicit subjects)  
✅ **Both HTML and Dev.to versions** (separated clearly in output file)

---

## Data Sources

All stats and claims trace to `scratch/overnight/rules-scan-article-result.md`:
- "100% were missing frontmatter" → All 4 rule sets in scan had no YAML frontmatter
- "75% were too long" → 3 out of 4 exceeded 2000 chars
- "75% mixed concerns" → 3 out of 4 flagged for multiple concerns
- "50% used weak language" → 2 out of 4 flagged for weak language
- "3,914 bytes (~1,077 tokens)" → Next.js React Tailwind rule size from scan
- "60% scored C or lower" → Referenced from 50-projects article data

---

**Status:** ✅ COMPLETE  
**Output Location:** `scratch/overnight/vet-cursor-rules-article.md` (this file)  
**Completion Time:** 2026-03-04 12:21 EST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>codeeditor</category>
      <category>devtools</category>
    </item>
    <item>
      <title>cursor-doctor v1.10: coverage gaps and README badges</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Wed, 04 Mar 2026 18:08:00 +0000</pubDate>
      <link>https://dev.to/nedcodes/cursor-doctor-v110-coverage-gaps-and-readme-badges-537a</link>
      <guid>https://dev.to/nedcodes/cursor-doctor-v110-coverage-gaps-and-readme-badges-537a</guid>
      <description>&lt;h2&gt;
  
  
  what's new
&lt;/h2&gt;

&lt;p&gt;I just shipped two features for cursor-doctor. One tells you what your rules are missing. The other gives you a badge to show off your health grade.&lt;/p&gt;

&lt;h2&gt;
  
  
  coverage gap detection (v1.10.25)
&lt;/h2&gt;

&lt;p&gt;You have rules. But do they cover what matters?&lt;/p&gt;

&lt;p&gt;cursor-doctor now scans your &lt;code&gt;package.json&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt; to detect your stack, then checks if your rules cover the categories that matter for that stack. Testing, error handling, accessibility, API patterns, security, performance.&lt;/p&gt;

&lt;p&gt;Here's what it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ▒▒ Cursor Health: A ▒▒

  █████████████████████████████░  98%

  ✓ Rules exist
  ✓ Rule syntax
  ✓ Token budget
  ✓ Coverage
  ✓ File sizes

  7 passed  

  ▓ Coverage Report

  Detected:  react, nextjs
  Covered:   styling
  Missing:   testing, error-handling, state-management, 
             accessibility, performance, api-data-fetching, 
             security

  Suggestions:
    • testing: Testing rules help maintain code quality 
      and catch bugs early
    • error-handling: Error handling rules ensure robust 
      error management
    • state-management: State management rules prevent 
      common pitfalls
    ... and 4 more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're building a React app with no testing rules, it tells you. If you're running Next.js with no API or security rules, it flags that. If you have 12 styling rules but nothing about error handling, you'll see it.&lt;/p&gt;

&lt;p&gt;The suggestions are specific to your stack. A Django project gets different recommendations than a React app. A Rust project won't get nagged about CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  README badge generator (v1.10.26)
&lt;/h2&gt;

&lt;p&gt;Your Cursor rules have a health grade. Now you can show it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor badge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cursor-doctor v1.10.26 -- badge generator

Markdown:
  ![Cursor Rules: A (98%)](https://img.shields.io/badge/Cursor%20Rules-A%20(98%25)-brightgreen)

HTML:
  &amp;lt;img src="https://img.shields.io/badge/Cursor%20Rules-A%20(98%25)-brightgreen" alt="Cursor Rules: A (98%)"&amp;gt;

Dynamic Badge (shields.io endpoint JSON):
  Save this JSON to your repo and reference it:
  npx cursor-doctor badge --json &amp;gt; cursor-rules-badge.json
  https://img.shields.io/endpoint?url=https://yourrepo/cursor-rules-badge.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the markdown snippet and paste it in your README. The badge shows your grade (A through F) with color coding. Green for A, yellow for C, red for F.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FCursor%2520Rules-A%2520%2898%2525%29-brightgreen" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FCursor%2520Rules-A%2520%2898%2525%29-brightgreen" alt="Cursor Rules: A (98%)" width="138" height="20"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The badge is static by default. It shows the grade at the time you ran the command. If you want a dynamic badge that updates automatically, use the &lt;code&gt;--json&lt;/code&gt; flag to generate a shields.io endpoint file, commit it to your repo, and reference it in your README.&lt;/p&gt;

&lt;h2&gt;
  
  
  why this matters
&lt;/h2&gt;

&lt;p&gt;Most Cursor rules are written once and never looked at again. You add a rule for React hooks. Then you add Express. Then you add auth logic. The rules grow organically, and gaps emerge.&lt;/p&gt;

&lt;p&gt;Coverage gap detection surfaces those gaps. It's not about telling you to write more rules. It's about telling you which rules would actually help.&lt;/p&gt;

&lt;p&gt;The badge is a forcing function. If you put it in your README, you'll see when your health grade drops. If you're sharing rules with your team or in open source, it's a signal that someone is paying attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  try it
&lt;/h2&gt;

&lt;p&gt;Both features are free and available now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor scan    &lt;span class="c"&gt;# see coverage gaps&lt;/span&gt;
npx cursor-doctor badge   &lt;span class="c"&gt;# generate badge snippets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you find issues in your rules, the Pro version has 34 auto-fixers. $9 one-time at &lt;a href="https://nedcodes.gumroad.com/l/cursor-doctor-pro" rel="noopener noreferrer"&gt;nedcodes.gumroad.com/l/cursor-doctor-pro&lt;/a&gt;. If it doesn't find real, fixable problems, email &lt;a href="mailto:hello@nedcodes.dev"&gt;hello@nedcodes.dev&lt;/a&gt; for a refund.&lt;/p&gt;

&lt;p&gt;Full docs: &lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;github.com/nedcodes-ok/cursor-doctor&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Add cursor-doctor to your CI pipeline in 2 minutes</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Wed, 04 Mar 2026 16:55:07 +0000</pubDate>
      <link>https://dev.to/nedcodes/add-cursor-doctor-to-your-ci-pipeline-in-2-minutes-17c3</link>
      <guid>https://dev.to/nedcodes/add-cursor-doctor-to-your-ci-pipeline-in-2-minutes-17c3</guid>
      <description>&lt;p&gt;i built &lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;cursor-doctor&lt;/a&gt; after watching teams waste hours debugging Cursor rules that "stopped working." The problem is always the same: someone added a rule with broken YAML frontmatter, or two rules contradicted each other, or a glob pattern had a typo. Cursor doesn't warn you. The rule silently fails.&lt;/p&gt;

&lt;p&gt;Here's how to catch that in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;Add this to &lt;code&gt;.github/workflows/cursor-rules.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nedcodes-ok/cursor-doctor@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every PR now checks your Cursor rules for errors before merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Actions setup
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/cursor-rules.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cursor Rules Health Check&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lint-cursor-rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nedcodes-ok/cursor-doctor@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If cursor-doctor finds issues, the workflow fails and the PR can't merge.&lt;/p&gt;

&lt;p&gt;The action handles Node.js setup automatically. No &lt;code&gt;setup-node&lt;/code&gt; step needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  action inputs
&lt;/h3&gt;

&lt;p&gt;Two optional inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nedcodes-ok/cursor-doctor@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./my-project'&lt;/span&gt;       &lt;span class="c1"&gt;# Path to scan (default: '.')&lt;/span&gt;
    &lt;span class="na"&gt;fail-on-warning&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true'&lt;/span&gt;    &lt;span class="c1"&gt;# Fail on warnings too (default: 'false')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  only run when rules change
&lt;/h3&gt;

&lt;p&gt;Save CI minutes with a &lt;code&gt;paths&lt;/code&gt; filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.cursor/rules/**'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.cursorrules'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CLAUDE.md'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AGENTS.md'&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.cursor/rules/**'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.cursorrules'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CLAUDE.md'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AGENTS.md'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  what the output looks like
&lt;/h2&gt;

&lt;p&gt;Here's actual output from &lt;code&gt;cursor-doctor lint&lt;/code&gt; on a project with a few issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cursor-doctor v1.10.24 -- lint

.cursor/rules/testing.mdc  (3 warnings)
  ⚠ Vague rule detected: "follow best practices" (line 5)
    → Replace with a specific instruction. Say exactly what
      to do: what tool, what pattern, what format.
  ⚠ Description is very short (&amp;lt;10 chars)
    → A descriptive description helps Cursor decide when to
      apply this rule.
  ⚠ Description is identical to filename
    → Describe what the rule does, not just repeat the filename.

.cursor/rules/types.mdc  (1 warning, 1 info)
  ⚠ Rule uses weak language: "try to/maybe/consider"
    → AI models follow commands better than suggestions. Use
      imperative mood: "Do X" instead of "try to do X".

──────────────────────────────────────────────────
4 warnings, 1 info, 1 passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;check&lt;/code&gt; command (default in CI) gives a pass/fail health grade. Grades D and F fail the build.&lt;/p&gt;

&lt;h2&gt;
  
  
  pre-commit hook
&lt;/h2&gt;

&lt;p&gt;Catch issues before you even push. Create &lt;code&gt;.git/hooks/pre-commit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nv"&gt;STAGED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;--diff-filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ACM &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'\.mdc$|\.cursorrules$|CLAUDE\.md$|AGENTS\.md$'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STAGED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"cursor-doctor: checking staged rule files..."&lt;/span&gt;
npx cursor-doctor check
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;chmod +x .git/hooks/pre-commit&lt;/code&gt;. The hook only runs when you stage rule files.&lt;/p&gt;

&lt;h2&gt;
  
  
  what it catches
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Frontmatter errors:&lt;/strong&gt; Missing YAML blocks, parse errors, &lt;code&gt;alwaysApply: "true"&lt;/code&gt; (string instead of boolean, rule never activates).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Glob mistakes:&lt;/strong&gt; Windows backslashes that match nothing, typos in extensions, overly broad patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semantic conflicts:&lt;/strong&gt; "Use semicolons" vs "omit semicolons." cursor-doctor checks 48 conflict patterns across formatting, imports, error handling, and state management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vague instructions:&lt;/strong&gt; "Write clean code" and "follow best practices" waste tokens without changing model behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token budget waste:&lt;/strong&gt; Too many &lt;code&gt;alwaysApply&lt;/code&gt; rules burning context window, duplicate content across files, dead rules nobody references.&lt;/p&gt;

&lt;h2&gt;
  
  
  other CI platforms
&lt;/h2&gt;

&lt;p&gt;The GitHub Action runs &lt;code&gt;npx cursor-doctor check&lt;/code&gt; under the hood. Use the same command anywhere:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitLab CI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;lint-cursor-rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:20&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npx cursor-doctor check&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;merge_requests&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CircleCI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2.1&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lint-cursor-rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cimg/node:20.0&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx cursor-doctor check&lt;/span&gt;
&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;check-rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;lint-cursor-rules&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit code 0 = healthy. Exit code 1 = issues found.&lt;/p&gt;

&lt;h2&gt;
  
  
  testing locally
&lt;/h2&gt;

&lt;p&gt;Run the same check CI will run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cursor-doctor check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the detailed breakdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cursor-doctor lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix issues, push, CI passes on the first try.&lt;/p&gt;




&lt;p&gt;&lt;code&gt;npx cursor-doctor fix --preview&lt;/code&gt; shows available auto-fixes. Many issues can be fixed automatically. First fix is free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;cursor-doctor on GitHub&lt;/a&gt; · &lt;a href="https://nedcodes.dev/guides/cursor-doctor-ci-github-actions" rel="noopener noreferrer"&gt;Full guide on nedcodes.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>cicd</category>
      <category>github</category>
    </item>
    <item>
      <title>I ran cursor-doctor on 50 real projects. Here's what broke.</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Tue, 03 Mar 2026 19:02:52 +0000</pubDate>
      <link>https://dev.to/nedcodes/i-ran-cursor-doctor-on-50-real-projects-heres-what-broke-14ba</link>
      <guid>https://dev.to/nedcodes/i-ran-cursor-doctor-on-50-real-projects-heres-what-broke-14ba</guid>
      <description>&lt;p&gt;I wanted to know: how healthy are Cursor rules in the wild? Not in tutorials or curated examples, but in real GitHub repos where people are actually shipping code.&lt;/p&gt;

&lt;p&gt;So I cloned 50 random public repos that use Cursor rules and ran &lt;code&gt;npx cursor-doctor scan&lt;/code&gt; on every one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results: 60% of projects scored a C
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A:  3 ███                          (6%)
B: 15 ███████████████              (30%)
C: 30 ██████████████████████████████ (60%)
D:  2 ██                           (4%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Average health score: 67%.&lt;/strong&gt; Only 3 out of 50 projects had healthy Cursor rules. The median project scored 69%, which is a C. That means most Cursor setups have enough issues to noticeably affect how well the AI follows instructions.&lt;/p&gt;

&lt;p&gt;I dug deeper into 15 of those projects and categorized every issue cursor-doctor flagged. &lt;strong&gt;998 total issues.&lt;/strong&gt; Here are the five problems that kept showing up.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Rules that eat your context window (146 issues)
&lt;/h2&gt;

&lt;p&gt;This was the single most common problem. Nearly &lt;strong&gt;15% of all issues&lt;/strong&gt; were rules that are too long.&lt;/p&gt;

&lt;p&gt;Rules with 2,000+ characters each. Some over 5,000. Each one burns 500 to 1,250 tokens of your context window before Cursor even reads your code.&lt;/p&gt;

&lt;p&gt;One project had 12 rules averaging 4,000 characters each. That is roughly 12,000 tokens of instructions alone, leaving less room for the code Cursor needs to work with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Split long rules into focused ones. Remove the parts that repeat what Cursor already knows. Cut examples down to one or two instead of eight.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Rules that target nothing (36 issues)
&lt;/h2&gt;

&lt;p&gt;Empty globs arrays. The rule exists, has a description, has instructions, but the &lt;code&gt;globs&lt;/code&gt; field is &lt;code&gt;[]&lt;/code&gt;. Cursor doesn't know which files the rule applies to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;React&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;component&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;standards"&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Add the right glob pattern (&lt;code&gt;**/*.tsx&lt;/code&gt;) or set &lt;code&gt;alwaysApply: true&lt;/code&gt; if the rule should apply everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Vague instructions Cursor ignores (27 issues)
&lt;/h2&gt;

&lt;p&gt;"Try to keep functions small." "Consider using TypeScript." "Maybe add error handling."&lt;/p&gt;

&lt;p&gt;Cursor doesn't try, consider, or maybe. It either follows the instruction or it doesn't. Weak language gives the model permission to ignore you.&lt;/p&gt;

&lt;p&gt;Compare: &lt;em&gt;"Try to use TypeScript"&lt;/em&gt; vs &lt;em&gt;"All new files must use TypeScript. No .js files except config files in the project root."&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Dead code burning tokens (32 issues)
&lt;/h2&gt;

&lt;p&gt;Commented-out sections, TODO markers, notes-to-self. These all consume tokens and confuse the model about what is actually a rule and what is a draft.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- TODO: add React rules later --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- OLD: use class components --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it is commented out, delete it. Rules are not source code. There is no reason to keep old versions around.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Missing or broken frontmatter (48 issues)
&lt;/h2&gt;

&lt;p&gt;28 projects had rules with no description. 20 had rules with no YAML frontmatter at all. Without frontmatter, Cursor cannot properly categorize or prioritize the rule. Without a description, you have no idea what the rule does when you revisit your setup six months later.&lt;/p&gt;

&lt;p&gt;A properly formatted rule file needs at minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Enforces consistent error handling in API routes&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src/api/**/*.ts"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;All API route handlers must wrap their body in a try/catch block.&lt;/span&gt;
&lt;span class="s"&gt;Return a 500 status with a generic error message. Log the full error to the server console.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the healthy projects did differently
&lt;/h2&gt;

&lt;p&gt;The 3 projects that scored an A had a few things in common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Short, focused rules.&lt;/strong&gt; One concern per file. Under 1,000 characters each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correct frontmatter.&lt;/strong&gt; Every rule had a description, appropriate globs, and explicit &lt;code&gt;alwaysApply&lt;/code&gt; settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete instructions.&lt;/strong&gt; No "try to" or "consider." Direct statements with examples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No dead weight.&lt;/strong&gt; No commented code, no TODOs, no redundant instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Check your own Cursor rules
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Takes about 2 seconds. Gives you a health grade from A through F and tells you exactly what to fix. The scan and lint commands are free, no install needed.&lt;/p&gt;

&lt;p&gt;For a detailed breakdown of every issue, file by file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;cursor-doctor on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also available as a &lt;a href="https://marketplace.visualstudio.com/items?itemName=nedcodes.cursor-doctor" rel="noopener noreferrer"&gt;VS Code and Cursor extension&lt;/a&gt; with inline diagnostics.&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Fed My Entire Codebase to Gemini. It Wrote Better Cursor Rules Than I Did.</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Sat, 28 Feb 2026 14:03:03 +0000</pubDate>
      <link>https://dev.to/nedcodes/i-fed-my-entire-codebase-to-gemini-it-wrote-better-cursor-rules-than-i-did-57d2</link>
      <guid>https://dev.to/nedcodes/i-fed-my-entire-codebase-to-gemini-it-wrote-better-cursor-rules-than-i-did-57d2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most AI rule generators read your &lt;code&gt;package.json&lt;/code&gt; and spit out generic templates. "Use TypeScript strict mode." "Follow REST conventions." Thanks, I already knew that.&lt;/p&gt;

&lt;p&gt;I wanted something that actually reads code. Not config files, not dependency lists. The actual source files where patterns live. So I built &lt;a href="https://github.com/nedcodes-ok/rule-gen" rel="noopener noreferrer"&gt;rule-gen&lt;/a&gt;, a CLI that feeds your codebase into Gemini and generates coding rules based on what it finds.&lt;/p&gt;

&lt;p&gt;The entire thing runs on a Raspberry Pi. Zero dependencies. Free Gemini API tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;rule-gen is a Node.js CLI. You point it at a project directory, it scans your source files, sends them to Gemini, and writes rules in whatever format your AI coding assistant uses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx rulegen-ai ./my-project

Scanning ./my-project...
  Found 13 files
  Selected 13 files &lt;span class="k"&gt;for &lt;/span&gt;analysis
  Estimated tokens: ~8,346

Generating rules with gemini-2.5-flash...
  API usage: 11,233 input, 1,699 output tokens
  Generated 8 rules

Written 8 files:
  ✓ .cursor/rules/cli-command-structure.mdc
  ✓ .cursor/rules/new-parser-module-structure.mdc
  ✓ .cursor/rules/new-format-converter-module-structure.mdc
  ✓ .cursor/rules/rule-object-structure.mdc
  ✓ .cursor/rules/error-message-convention.mdc
  ✓ .cursor/rules/single-file-parser-convention.mdc
  ✓ .cursor/rules/cursor-output-directory.mdc
  ✓ .cursor/rules/scoping-loss-warning-convention.mdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It supports five output formats:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Output File&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--format cursor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.cursor/rules/*.mdc&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--format claude-md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Agents&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--format agents-md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--format copilot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windsurf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--format windsurf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.windsurfrules&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The whole thing is about 750 lines across five modules (scanner, budgeter, Gemini client, prompt + parser, writer). No SDK, no &lt;code&gt;node_modules&lt;/code&gt;. Just &lt;code&gt;node:https&lt;/code&gt;, &lt;code&gt;node:fs&lt;/code&gt;, and &lt;code&gt;node:path&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Gemini
&lt;/h2&gt;

&lt;p&gt;This is the part where the 1M token context window actually matters.&lt;/p&gt;

&lt;p&gt;I looked at existing rule generators before building this. They all do static analysis: read your &lt;code&gt;package.json&lt;/code&gt;, check for a &lt;code&gt;tsconfig.json&lt;/code&gt;, maybe peek at your directory structure. Then they match against a template library. "You have React? Here's the React rules." That's fine if you want generic framework guidance, but it misses everything specific to YOUR codebase.&lt;/p&gt;

&lt;p&gt;Gemini lets me send the actual source files. Not a summary, not an AST. The raw code. For a typical project (15-50 files, ~40K tokens), that's a fraction of the context window. The model reads every file and identifies patterns that span across modules.&lt;/p&gt;

&lt;p&gt;Here's a rule it generated for one of my projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;New parser modules must be placed in src/parsers/ and export a discover function.&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src/parsers/**/*.js"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;alwaysApply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# New Parser Module Structure&lt;/span&gt;

Any new parser module must reside within the &lt;span class="sb"&gt;`src/parsers/`&lt;/span&gt; directory. 
Each parser file should export a single &lt;span class="sb"&gt;`discover(dir)`&lt;/span&gt; function.
This function takes the current working directory as its sole argument.
If no relevant file is found, the function should return &lt;span class="sb"&gt;`null`&lt;/span&gt;.
If rules are found, it must return an object with &lt;span class="sb"&gt;`rules`&lt;/span&gt; (array) 
and &lt;span class="sb"&gt;`skipped`&lt;/span&gt; (array of objects with &lt;span class="sb"&gt;`file`&lt;/span&gt; and &lt;span class="sb"&gt;`reason`&lt;/span&gt;).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That rule references actual directory paths, actual function signatures, and actual return types from my code. No template library produces that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prompt engineering is 90% of the work
&lt;/h3&gt;

&lt;p&gt;The scanner and writer took maybe an hour each. The prompt went through four rewrites over two days.&lt;/p&gt;

&lt;p&gt;My first attempt asked Gemini to "analyze this codebase and generate rules." It came back with 75 rules. Most of them were documentation-style summaries of what each function does, which is useless as a coding rule.&lt;/p&gt;

&lt;p&gt;The fix was reframing the task. Instead of "generate rules for this codebase," I needed "write rules that tell an AI coding assistant how to write NEW code in this project." That distinction matters. The model needs to think about what a new developer would get wrong, not what the existing code does.&lt;/p&gt;

&lt;p&gt;I also learned that constraints placed AFTER the code files work better than constraints placed before. The model pays more attention to the last thing it reads, especially with long contexts. Moving "generate exactly 5-8 rules" to the end of the prompt (after all the source files) made the difference between 75 rules and 7.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured output changes everything
&lt;/h3&gt;

&lt;p&gt;I initially built a text parser to extract rules from Gemini's free-form response. It worked, but the model kept switching formats between runs. Sometimes YAML frontmatter, sometimes markdown bold headers, sometimes a mix.&lt;/p&gt;

&lt;p&gt;Switching to Gemini's structured output mode (&lt;code&gt;responseSchema&lt;/code&gt;) solved this completely AND made the API calls faster. The thinking model (&lt;code&gt;gemini-2.5-flash&lt;/code&gt;) went from 4+ minutes to 24 seconds on the same 52K token input. My guess is the model spends less time on formatting tokens when it knows the exact output schema.&lt;/p&gt;

&lt;p&gt;The lesson: if you need structured data from an LLM, don't parse text. Use the API's native structured output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Post-processing is your safety net
&lt;/h3&gt;

&lt;p&gt;Even with a good prompt, I couldn't guarantee the model would output exactly the right number of rules or use exactly the right format every time. So I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A hard cap at 8 rules (truncate if the model overproduces)&lt;/li&gt;
&lt;li&gt;A fallback parser that handles both YAML frontmatter and markdown-style output&lt;/li&gt;
&lt;li&gt;Filename generation from rule titles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't glamorous, but it's what makes the tool actually reliable. You can't ship a CLI that works 80% of the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gemini Feedback (The Honest Version)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What worked well:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The context window is the killer feature. Being able to send 50 source files in a single request, with no chunking or RAG pipeline, made the architecture dead simple. One prompt, one API call, done. I didn't need to build any summarization, embedding, or multi-step chain. That simplicity is directly because of the 1M token limit.&lt;/p&gt;

&lt;p&gt;The free tier is genuinely usable. I built and tested the entire tool without spending a cent on API calls. For a tool that generates 5-8 rules per run using ~50K tokens of input, the free tier rate limits never became an issue.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gemini-2.5-flash&lt;/code&gt; is fast enough to run on a Raspberry Pi. 24 seconds for a 52K token codebase. I expected to need a more powerful machine for development, but even the Pi 5 handles it fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What didn't work great (and how I fixed it):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My first approach was free-form text output: ask the model to generate rules in a specific YAML format, then parse the text. &lt;code&gt;flash-lite&lt;/code&gt; didn't follow structural constraints reliably. "Output exactly 5-8 rules in this YAML format" sometimes became "here's 12 rules in markdown with bold headers." I built a robust fallback parser, but it felt brittle.&lt;/p&gt;

&lt;p&gt;Then I discovered Gemini's structured output mode (&lt;code&gt;responseMimeType: "application/json"&lt;/code&gt; with a &lt;code&gt;responseSchema&lt;/code&gt;). I defined a JSON schema for the rule format and the model returns valid, parseable JSON every time. No text parsing needed. This also made the thinking model (&lt;code&gt;gemini-2.5-flash&lt;/code&gt;) dramatically faster, dropping from 4+ minutes to 24 seconds on the same input, probably because it doesn't waste tokens on formatting.&lt;/p&gt;

&lt;p&gt;If you're building anything with Gemini that needs structured data back, skip the text-parsing approach and go straight to &lt;code&gt;responseSchema&lt;/code&gt;. It saved me an entire class of bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ecosystem
&lt;/h2&gt;

&lt;p&gt;rule-gen fits into a pipeline I've been building:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/nedcodes-ok/rule-gen" rel="noopener noreferrer"&gt;rule-gen&lt;/a&gt;&lt;/strong&gt; generates rules from your codebase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;cursor-doctor&lt;/a&gt;&lt;/strong&gt; validates and fixes those rules
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/nedcodes-ok/rule-porter" rel="noopener noreferrer"&gt;rule-porter&lt;/a&gt;&lt;/strong&gt; converts them between formats&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Generate, validate, convert. Three tools, zero dependencies each, all on npm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-key   &lt;span class="c"&gt;# free at aistudio.google.com/apikey&lt;/span&gt;
npx rulegen-ai ./your-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It takes about 20-30 seconds. The rules it generates will be specific to your codebase, not generic templates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nedcodes-ok/rule-gen" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; | &lt;a href="https://www.npmjs.com/package/rulegen-ai" rel="noopener noreferrer"&gt;npm&lt;/a&gt; | &lt;a href="https://nedcodes.dev" rel="noopener noreferrer"&gt;nedcodes.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
      <category>ai</category>
    </item>
    <item>
      <title>rule-porter: Convert Cursor rules to CLAUDE.md, AGENTS.md, and Copilot</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Fri, 27 Feb 2026 20:54:59 +0000</pubDate>
      <link>https://dev.to/nedcodes/rule-porter-convert-cursor-rules-to-claudemd-agentsmd-and-copilot-4hjc</link>
      <guid>https://dev.to/nedcodes/rule-porter-convert-cursor-rules-to-claudemd-agentsmd-and-copilot-4hjc</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/weekend-2026-02-28"&gt;DEV Weekend Challenge: Community&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Community
&lt;/h2&gt;

&lt;p&gt;Cursor AI users who also use Claude Code, GitHub Copilot, or any combination of AI coding tools.&lt;/p&gt;

&lt;p&gt;Right now, if you've invested time writing good &lt;code&gt;.mdc&lt;/code&gt; rules in Cursor, those rules are locked in. Cursor uses its own format with YAML frontmatter, glob patterns, and &lt;code&gt;alwaysApply&lt;/code&gt; flags. None of that translates to Claude Code's &lt;code&gt;CLAUDE.md&lt;/code&gt;, Copilot's &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;, or the &lt;code&gt;AGENTS.md&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;People switching between tools (or using more than one) have to manually rewrite everything. I know because someone told me so directly. &lt;a href="https://dev.to/comment/3528m"&gt;Matthew Hou left a comment&lt;/a&gt; on my cursor-doctor launch post asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you thought about an export/convert feature? Something that could take validated Cursor rules and output an equivalent AGENTS.md or CLAUDE.md?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That comment kicked this off.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;rule-porter&lt;/strong&gt; is a zero-dependency CLI that reads your &lt;code&gt;.cursor/rules/&lt;/code&gt; directory and converts every &lt;code&gt;.mdc&lt;/code&gt; file into the format your target tool expects.&lt;/p&gt;

&lt;p&gt;Three target formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; (global vs conditional sections, glob patterns preserved as comments)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt; (flat markdown with file-specific rules separated)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt; (merged flat markdown)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It auto-detects your Cursor rules, handles edge cases (empty files, broken frontmatter, missing body content), and warns you about anything that can't convert cleanly. Glob patterns and &lt;code&gt;alwaysApply&lt;/code&gt; flags don't have equivalents in flat markdown formats, so rule-porter keeps them as human-readable annotations and tells you exactly what was lost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rule-porter &lt;span class="nt"&gt;--to&lt;/span&gt; agents-md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. No install, no config, no dependencies.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Here's rule-porter running against a real project with 6 Cursor rules (a Chrome extension with TypeScript, i18n, and UI rules):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  rule-porter v1.2.0

  Source:  .cursor/rules/ (6 rules)
  Target:  AGENTS.md

  ✓ 1 global  5 conditional

  Warnings:
  ⚠  comment: Glob pattern "*.tsx, *.js, *.ts" converted to comment.
     AGENTS.md has no native file scoping.
  ⚠  i18n: Glob pattern "locales/**/*.json" converted to comment.
     AGENTS.md has no native file scoping.
  ⚠  typescript: Glob pattern "*.tsx" converted to comment.
     AGENTS.md has no native file scoping.
  ⚠  ui: Glob pattern "*.tsx" converted to comment.
     AGENTS.md has no native file scoping.
  ⚠  ai: No glob pattern and not alwaysApply.
     This was a manual-attach rule in Cursor — review placement.

  ✓ Written to AGENTS.md

  6 rules converted · 5 warnings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The output preserves your rule structure:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# AGENTS.md&lt;/span&gt;
&lt;span class="gt"&gt;
&amp;gt; Generated by rule-porter from .cursor/rules/&lt;/span&gt;

&lt;span class="gu"&gt;## Global Rules&lt;/span&gt;

&lt;span class="gu"&gt;### Chrome extension development standards&lt;/span&gt;

You are an expert Chrome extension developer...
[full rule body preserved]

&lt;span class="gu"&gt;## Conditional Rules&lt;/span&gt;

&lt;span class="gu"&gt;### i18n, internationalization, translation&lt;/span&gt;

&lt;span class="ge"&gt;*Applies to: `locales/**/*&lt;/span&gt;.json&lt;span class="err"&gt;`*&lt;/span&gt;

Internationalization (i18n) Guidelines:
[full rule body preserved]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Global rules (ones marked &lt;code&gt;alwaysApply: true&lt;/code&gt; in Cursor) get their own section. Conditional rules keep their glob patterns as readable annotations. Code blocks, markdown formatting, even non-English content all come through intact.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--dry-run&lt;/code&gt; lets you preview without writing anything:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rule-porter &lt;span class="nt"&gt;--to&lt;/span&gt; claude-md &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nedcodes-ok" rel="noopener noreferrer"&gt;
        nedcodes-ok
      &lt;/a&gt; / &lt;a href="https://github.com/nedcodes-ok/rule-porter" rel="noopener noreferrer"&gt;
        rule-porter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Convert AI IDE rules between Cursor, Windsurf, CLAUDE.md, AGENTS.md, and Copilot. Bidirectional. Zero dependencies.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;rule-porter&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/eff8594e544a5b2f38630760aa59330d8656d7484b8d7f157753e8bbb402ad58/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f437572736f7225323052756c65732d76616c6964617465642d627269676874677265656e"&gt;&lt;img src="https://camo.githubusercontent.com/eff8594e544a5b2f38630760aa59330d8656d7484b8d7f157753e8bbb402ad58/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f437572736f7225323052756c65732d76616c6964617465642d627269676874677265656e" alt="Cursor Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/rule-porter" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fbda902ca643a09b417f331e3f91d7df5b1bca66e1941e3ea62eda0ee34149e2/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f72756c652d706f72746572" alt="npm version"&gt;&lt;/a&gt; &lt;a href="https://www.npmjs.com/package/rule-porter" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/40e3828862357d4b4260cd0192d8fa56a7d16f8d1840dd9769c62a2e61809d23/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64772f72756c652d706f72746572" alt="npm downloads"&gt;&lt;/a&gt; &lt;a href="https://github.com/nedcodes-ok/rule-porter/blob/main/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/48c6418322f280c3c6ad077de3f69821dfd9b17365a6dde9e9123d82b99d240a/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f6c2f72756c652d706f72746572" alt="license"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Switch AI editors without rewriting all your rules.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Convert Cursor rules to Claude Code, GitHub Copilot, Windsurf, or AGENTS.md. And back. Bidirectional. Zero dependencies.&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npx rule-porter --to agents-md&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The problem&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Your rules are locked into one tool's format. Cursor uses &lt;code&gt;.mdc&lt;/code&gt; files with YAML frontmatter and glob patterns. Claude Code uses &lt;code&gt;CLAUDE.md&lt;/code&gt;. Copilot uses &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;. None of them understand each other.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What you get&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ npx rule-porter --to agents-md

Converting 12 Cursor rules → AGENTS.md

  ✓ 9 rules converted cleanly
  ⚠ 3 rules had glob patterns (preserved as comments)

Written: AGENTS.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Converting back works too:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npx rule-porter --from agents-md --to cursor
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; → 12 individual .mdc files with frontmatter and globs restored&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Supported formats&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;Read&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;Write&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;tbody&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;.cursor/rules/*.mdc&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Cursor (legacy)&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;.cursorrules&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;AGENTS.md&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Windsurf&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;.windsurfrules&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/tbody&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Common conversions&lt;/h2&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nedcodes-ok/rule-porter" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;475 lines across 5 files. Zero dependencies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/parser.js&lt;/code&gt; — .mdc frontmatter parser and rule discovery&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/cli.js&lt;/code&gt; — argument parsing, output formatting, file writing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/formats/agents-md.js&lt;/code&gt; — AGENTS.md format writer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/formats/claude-md.js&lt;/code&gt; — CLAUDE.md format writer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/formats/copilot.js&lt;/code&gt; — Copilot instructions format writer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I already had a &lt;code&gt;.mdc&lt;/code&gt; parser from &lt;a href="https://www.npmjs.com/package/cursor-doctor" rel="noopener noreferrer"&gt;cursor-doctor&lt;/a&gt; (a linter/diagnostic tool for Cursor rules). The parser handles YAML frontmatter extraction, glob pattern reading, and &lt;code&gt;alwaysApply&lt;/code&gt; flag detection. I extracted the relevant parts and built the conversion layer on top.&lt;/p&gt;

&lt;p&gt;The core problem is that Cursor's &lt;code&gt;.mdc&lt;/code&gt; format is the only one with real structure. Every other format is just a flat markdown file. So converting from Cursor to anything else means making decisions about what to preserve and what to lose.&lt;/p&gt;

&lt;p&gt;My approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parse all &lt;code&gt;.mdc&lt;/code&gt; files into an intermediate representation (name, description, globs, alwaysApply, body)&lt;/li&gt;
&lt;li&gt;Split rules into global (alwaysApply) and conditional (everything else)&lt;/li&gt;
&lt;li&gt;Each format writer decides how to represent that split&lt;/li&gt;
&lt;li&gt;Anything that can't convert 1:1 produces a warning&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The tricky part was handling real-world rules honestly. I tested against three actual GitHub repos with &lt;code&gt;.cursor/rules/&lt;/code&gt; directories and found things like: empty description fields, conditional rules with no glob patterns (manual-attach only in Cursor), Chinese content in rule bodies, and files with only frontmatter and no body. All of those needed to either convert cleanly or fail loudly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech stack:&lt;/strong&gt; Node.js, zero dependencies, &lt;code&gt;var&lt;/code&gt; and &lt;code&gt;require&lt;/code&gt; (no build step, runs on Node 12+).&lt;/p&gt;




&lt;p&gt;🔧 Part of the &lt;a href="https://nedcodes.dev" rel="noopener noreferrer"&gt;nedcodes&lt;/a&gt; toolkit for Cursor AI developers.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I rewrote my Cursor linter into a full diagnostic tool (and added auto-fix)</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Fri, 27 Feb 2026 00:04:47 +0000</pubDate>
      <link>https://dev.to/nedcodes/i-rewrote-my-cursor-linter-into-a-full-diagnostic-tool-and-added-auto-fix-5ehb</link>
      <guid>https://dev.to/nedcodes/i-rewrote-my-cursor-linter-into-a-full-diagnostic-tool-and-added-auto-fix-5ehb</guid>
      <description>&lt;p&gt;cursor-lint started as a thing I built because my own &lt;code&gt;.mdc&lt;/code&gt; rules kept silently breaking. Missing frontmatter, bad YAML, &lt;code&gt;alwaysApply&lt;/code&gt; not set. Cursor doesn't tell you when a rule fails to load. It just... doesn't load it. No error, no warning, nothing.&lt;/p&gt;

&lt;p&gt;That tool ended up getting ~1,800 downloads, which was cool, but I kept running into problems it couldn't solve. Like, I had two rules that contradicted each other ("use semicolons" in one file, "avoid semicolons" in another) and the linter had no way to catch that. Or I'd have rules with 80% identical content because I'd copy-pasted and forgotten to clean up. The linter could tell me if individual rules were well-formed, but it couldn't tell me if my &lt;em&gt;setup&lt;/em&gt; was healthy.&lt;/p&gt;

&lt;p&gt;So I rebuilt it.&lt;/p&gt;

&lt;h2&gt;
  
  
  cursor-doctor
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cursor-doctor scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The free scan gives you a health grade (A through F) based on 8 checks: whether rules exist, legacy &lt;code&gt;.cursorrules&lt;/code&gt; conflicts, 20+ lint checks, token budget, file type coverage, file sizes, &lt;code&gt;alwaysApply&lt;/code&gt; usage, and whether you have agent skills set up.&lt;/p&gt;

&lt;p&gt;It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Cursor Health: C  (62%)
  ──────────────────────────────────

  ✓ Rules exist
  ✗ No legacy .cursorrules
  ! Token budget: ~4,200 tokens — getting heavy
  ✓ Coverage: Rules cover your project file types
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero dependencies, runs straight from npx.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stuff that was actually hard to build
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Conflict detection.&lt;/strong&gt; This was the main thing I wanted. The tool extracts directives from your rule bodies ("use X", "prefer X", "never X", "avoid X") and compares them across files. If one rule says "always use trailing commas" and another says "remove trailing commas," it flags it. It's not just 9 hardcoded regex patterns anymore. It understands the &lt;em&gt;intent&lt;/em&gt; of the instruction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redundancy detection.&lt;/strong&gt; Compares line overlap between rules. If two files share more than 60% of their content, that's wasted context window. Every redundant token is a token not being used for your actual code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack detection.&lt;/strong&gt; Reads your &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;requirements.txt&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;Cargo.toml&lt;/code&gt;, etc. and figures out what you're using. Knows about 12+ frameworks (React, Next.js, Django, Express, Vue, Svelte, and more) and 6 languages. If you're running a Next.js project with no Next.js-specific rules, it tells you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro ($9, one-time)
&lt;/h2&gt;

&lt;p&gt;The free scan shows you what's wrong. Pro fixes it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cursor-doctor audit&lt;/code&gt; gives you the full diagnostic: conflicts, redundancy analysis, token budget breakdown (always-loaded vs conditional), stack-specific gap analysis, and concrete fix instructions. &lt;code&gt;audit --md&lt;/code&gt; exports it as markdown you can share with your team or drop in a PR.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cursor-doctor fix&lt;/code&gt; actually repairs things. It auto-merges redundant rules, fixes broken YAML frontmatter, splits oversized files, and generates starter rules for your detected stack. There are templates for React, Next.js, Python, Django, Go, Rust, Vue, Svelte, Tailwind, Express, and testing. &lt;code&gt;fix --dry-run&lt;/code&gt; previews everything before writing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Activate after purchase&lt;/span&gt;
cursor-doctor activate &amp;lt;your-key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;a href="https://nedcodes.gumroad.com/l/cursor-doctor-pro" rel="noopener noreferrer"&gt;Get a Pro key&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://nedcodes.dev" rel="noopener noreferrer"&gt;nedcodes.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nedcodes.dev" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/cursor-doctor" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've been using cursor-lint, cursor-doctor includes everything it did plus all the diagnostic and repair stuff. Different package name though, so &lt;code&gt;npx cursor-doctor&lt;/code&gt; is what you want now.&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>"This has been the biggest shift in how we build software since the move from Tab autocomplete to working synchronously with agents. More than 30% of the PRs we merge at Cursor are now created by agents operating autonomously in cloud sandboxes." Thoughts?</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Tue, 24 Feb 2026 21:50:02 +0000</pubDate>
      <link>https://dev.to/nedcodes/this-has-been-the-biggest-shift-in-how-we-build-software-since-the-move-from-tab-autocomplete-to-3l8b</link>
      <guid>https://dev.to/nedcodes/this-has-been-the-biggest-shift-in-how-we-build-software-since-the-move-from-tab-autocomplete-to-3l8b</guid>
      <description></description>
    </item>
    <item>
      <title>Cursor rules vs skills — what's the actual difference?</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Tue, 24 Feb 2026 21:34:32 +0000</pubDate>
      <link>https://dev.to/nedcodes/cursor-rules-vs-skills-whats-the-actual-difference-383b</link>
      <guid>https://dev.to/nedcodes/cursor-rules-vs-skills-whats-the-actual-difference-383b</guid>
      <description>

&lt;p&gt;title: Cursor rules vs skills — what's the actual difference?&lt;br&gt;
published: true&lt;br&gt;
tags: cursor, ai, codequality, productivity&lt;/p&gt;
&lt;h2&gt;
  
  
  series: cursorrules-that-work
&lt;/h2&gt;

&lt;p&gt;Cursor has two ways to give the agent persistent instructions: rules and skills. The docs explain what each one is, but they don't really explain when you'd pick one over the other. I had about 20 &lt;code&gt;.mdc&lt;/code&gt; rules in a project and wasn't sure if I was supposed to migrate, so I ran some tests.&lt;/p&gt;

&lt;p&gt;Here's what I found, and what I wish someone had told me before I started.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rules: the short version
&lt;/h2&gt;

&lt;p&gt;Rules live in &lt;code&gt;.cursor/rules/&lt;/code&gt; as &lt;code&gt;.mdc&lt;/code&gt; files. They have YAML frontmatter at the top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use early returns when refactoring&lt;/span&gt;
&lt;span class="na"&gt;alwaysApply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;When refactoring code, always use early returns (guard clauses)&lt;/span&gt;
&lt;span class="s"&gt;instead of nested if/else blocks.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontmatter gives you control over when the rule loads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alwaysApply: true&lt;/code&gt; — loaded into every prompt, regardless of what you're working on&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;globs: "*.tsx"&lt;/code&gt; — only loads when working on matching files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; — helps the agent decide if the rule is relevant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without &lt;code&gt;alwaysApply&lt;/code&gt; or globs, rules aren't consistently picked up. In a previous test I ran, the agent didn't follow rules that were missing both. It can still find them through description matching or manual invocation, but don't count on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills: the short version
&lt;/h2&gt;

&lt;p&gt;Skills live in &lt;code&gt;.cursor/skills/&amp;lt;name&amp;gt;/SKILL.md&lt;/code&gt;. No frontmatter, no YAML, just markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;When refactoring code, always use early returns (guard clauses)
instead of nested if/else blocks.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each skill gets its own subdirectory. That's it. Simpler setup, less configuration. But also less control over when and where the skill loads.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's actually different?
&lt;/h2&gt;

&lt;p&gt;I put the same instruction in both formats and ran them through 15 tests on a real codebase (cursor-lint, ~900 lines across 4 files). Three runs per test, using the Cursor agent CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When the task matches the instruction, they're identical.&lt;/strong&gt; Rules followed 3/3, skills followed 3/3. Same output quality. The agent cited the rule by filename and the skill as a "system rule," but the generated code was the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neither one fires on unrelated tasks.&lt;/strong&gt; I kept the refactor instruction loaded but asked the agent to add a &lt;code&gt;--verbose&lt;/code&gt; flag instead. Both the rule and the skill stayed in context but the model ignored them. 3/3 runs just added the flag without touching the code structure.&lt;/p&gt;

&lt;p&gt;This actually corrects something I said in an earlier article. I claimed &lt;code&gt;alwaysApply: true&lt;/code&gt; meant the rule would fire on every task, even unrelated ones. That's not quite right. It means the rule is LOADED into every prompt, but the model is smart enough to skip it when the task doesn't match. Loaded into context isn't the same as applied to output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When they conflict, rules win.&lt;/strong&gt; I set up a direct contradiction: the rule said "use early returns," the skill said "use nested if/else." The rule won 3/3. The agent cited the &lt;code&gt;.mdc&lt;/code&gt; file in its reasoning and completely ignored the skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I'd use which
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rules if you want control.&lt;/strong&gt; The frontmatter lets you scope rules to specific file types, decide when they load, and give the agent context about what the rule is for. If you have a team or a big project with different conventions for different parts of the codebase, this matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills if you want simplicity.&lt;/strong&gt; No frontmatter to mess up, no &lt;code&gt;alwaysApply&lt;/code&gt; footgun, just write your instruction in markdown and drop it in a folder. If you have a small project or you're just starting with Cursor customization, skills are less to think about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't mix them for the same instruction.&lt;/strong&gt; If you have a rule and a skill that say different things, the rule wins. If they say the same thing, you're just wasting context window space.&lt;/p&gt;

&lt;p&gt;I'm sticking with rules because I already have 20+ of them and the frontmatter is useful. But if I were starting fresh today, I'd probably try skills first and only switch to rules if I needed the scoping.&lt;/p&gt;




&lt;p&gt;📋 I put together a free Cursor Safety Checklist based on stuff I've run into while testing all of this. Pre-flight checks for AI-assisted coding sessions, basically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nedcodes.gumroad.com/l/cursor-safety-checklist" rel="noopener noreferrer"&gt;Grab it here if you want →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>codequality</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I loaded 50 rules into Cursor and it followed every single one</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Mon, 23 Feb 2026 18:52:40 +0000</pubDate>
      <link>https://dev.to/nedcodes/i-loaded-50-rules-into-cursor-and-it-followed-every-single-one-3ceb</link>
      <guid>https://dev.to/nedcodes/i-loaded-50-rules-into-cursor-and-it-followed-every-single-one-3ceb</guid>
      <description>&lt;p&gt;I keep seeing people online worry about how many .cursorrules they can have before Cursor starts ignoring them. "Don't use too many rules," "keep it under 10," that kind of thing. But where was this coming from? Was there any truth to it?&lt;/p&gt;

&lt;p&gt;So I tested it. I made 50 rules, loaded them all at once, and ran the same refactoring task 18 times across different rule counts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I created rules for things that are easy to verify. &lt;code&gt;always-semicolons&lt;/code&gt;, &lt;code&gt;no-console-log&lt;/code&gt;, &lt;code&gt;interface-prefix&lt;/code&gt;, &lt;code&gt;early-return&lt;/code&gt;, stuff where you look at the output and can immediately tell if it was followed. I started at 1 rule and scaled up: 1, 5, 10, 20, 30, 50. Every rule had &lt;code&gt;alwaysApply: true&lt;/code&gt; and proper frontmatter. The same task, 3 runs at each level.&lt;/p&gt;

&lt;p&gt;I expected it to start falling off somewhere around 15-20 rules; that's what the online advice implies. Context windows have limits, models forget stuff, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rules&lt;/th&gt;
&lt;th&gt;Run 1&lt;/th&gt;
&lt;th&gt;Run 2&lt;/th&gt;
&lt;th&gt;Run 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1-50&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;100% compliance across all 18 runs. At every level. Including 50 rules at once(!)&lt;/p&gt;

&lt;p&gt;I honestly thought I'd messed up the test. I checked the output files manually, rule by rule, and every single one was addressed. Some rules got marked "N/A" when they didn't apply to the test file (like &lt;code&gt;cors-explicit&lt;/code&gt; when there's no API endpoint), but the model explicitly acknowledged them instead of silently skipping them.&lt;/p&gt;

&lt;h2&gt;
  
  
  You don't need to keep it under 10
&lt;/h2&gt;

&lt;p&gt;At least for the current version of Cursor with Auto mode. I can't speak for older versions or other tools, but right now, 50 rules with &lt;code&gt;alwaysApply: true&lt;/code&gt; and proper frontmatter all fire correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I think people are still saying to keep it low
&lt;/h2&gt;

&lt;p&gt;The people warning about "too many rules" are probably running into a different problem. Bad frontmatter, missing &lt;code&gt;alwaysApply&lt;/code&gt;, vague rules that the model interprets differently than intended. Those are real issues that look like "the model forgot my rule" but are actually structural failures.&lt;/p&gt;

&lt;p&gt;I've seen this pattern a lot. Someone has 15 rules, 3 of them aren't firing, and they assume it's a quantity problem when it's actually a formatting problem. The rule count isn't the bottleneck. The rule quality is.&lt;/p&gt;

&lt;h2&gt;
  
  
  But that was a toy project
&lt;/h2&gt;

&lt;p&gt;The test above used a single file with a straightforward refactoring task. Real projects are different. You've got thousands of lines across multiple files, complex prompts, and the model has to juggle your project context alongside all those rules.&lt;/p&gt;

&lt;p&gt;So I ran the same 50 rules against a real codebase: cursor-lint itself (4 files, ~900 lines). Instead of a simple single-file refactor, I asked Cursor to do a multi-file architectural change.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Run 1&lt;/th&gt;
&lt;th&gt;Run 2&lt;/th&gt;
&lt;th&gt;Run 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single file (50 rules)&lt;/td&gt;
&lt;td&gt;50/50&lt;/td&gt;
&lt;td&gt;50/50&lt;/td&gt;
&lt;td&gt;50/50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real project (50 rules)&lt;/td&gt;
&lt;td&gt;48/50&lt;/td&gt;
&lt;td&gt;49/50&lt;/td&gt;
&lt;td&gt;48/50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;96-98% compliance. Not 100%. One or two rules got silently dropped each run, and here's the interesting part: it wasn't the same rules every time. Different ones fell off in different runs. No pattern I could find.&lt;/p&gt;

&lt;p&gt;My read on this: with a toy file, the model has plenty of context budget for rules. In a real project, rules are competing with your actual code for attention. Most of them still fire. But if you're relying on every single rule hitting every single time, you might get surprised.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual takeaway
&lt;/h2&gt;

&lt;p&gt;50 rules works. Even in a real project, you're getting 96%+ compliance. The "keep it under 10" advice is still wrong. But "load 50 rules and forget about it" isn't quite right either. If you have rules that absolutely must fire every time, keep them specific, keep the frontmatter clean, and spot-check occasionally.&lt;/p&gt;




&lt;p&gt;🔧 &lt;strong&gt;Want to check your own setup?&lt;/strong&gt; Run &lt;code&gt;npx cursor-doctor scan&lt;/code&gt; to find broken frontmatter, conflicts, and token waste in your Cursor rules. Free, zero dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nedcodes.dev" rel="noopener noreferrer"&gt;nedcodes.dev →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>cursorrules</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Just shipped framework detection in cursor-lint — auto-detects your stack and suggests matching rule presets. Different rules for different setups. https://github.com/nedcodes-ok/cursor-lint</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Mon, 23 Feb 2026 17:08:17 +0000</pubDate>
      <link>https://dev.to/nedcodes/just-shipped-framework-detection-in-cursor-lint-auto-detects-your-stack-and-suggests-matching-5gf7</link>
      <guid>https://dev.to/nedcodes/just-shipped-framework-detection-in-cursor-lint-auto-detects-your-stack-and-suggests-matching-5gf7</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://github.com/nedcodes-ok/cursor-doctor" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F1159652092%2F24979878-55aa-4663-a91b-b0bdcdb943ad" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer" class="c-link"&gt;
            GitHub - nedcodes-ok/cursor-doctor: Cursor rules linter and auto-fixer. Find out why Cursor ignores your rules. 100+ checks, zero dependencies. · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Cursor rules linter and auto-fixer. Find out why Cursor ignores your rules. 100+ checks, zero dependencies. - nedcodes-ok/cursor-doctor
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>codequality</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Everything I've learned so far about .cursorrules after mass testing them</title>
      <dc:creator>Ned C</dc:creator>
      <pubDate>Sun, 22 Feb 2026 22:34:02 +0000</pubDate>
      <link>https://dev.to/nedcodes/everything-i-learned-about-cursorrules-after-mass-testing-them-for-2-months-31km</link>
      <guid>https://dev.to/nedcodes/everything-i-learned-about-cursorrules-after-mass-testing-them-for-2-months-31km</guid>
      <description>&lt;p&gt;I've been running experiments on Cursor's rule system for a while now. I started because my rules weren't working and I couldn't figure out why, and I ended up going way deeper than I planned.&lt;/p&gt;

&lt;p&gt;So if you're still using a &lt;code&gt;.cursorrules&lt;/code&gt; file in your project root, it works, but it's the old way. Cursor moved to &lt;code&gt;.cursor/rules/*.mdc&lt;/code&gt; files a while back. The .mdc format lets you scope rules to specific file types, set metadata in frontmatter, and organize rules into separate files instead of one giant blob. I tested both. If you have a &lt;code&gt;.cursorrules&lt;/code&gt; AND &lt;code&gt;.mdc&lt;/code&gt; files, the .mdc files win. The old file still loads in a clean directory with nothing else, but once you have the new format, that's what Cursor uses.&lt;/p&gt;

&lt;p&gt;Migrating takes maybe 10 minutes. I split my monolithic &lt;code&gt;.cursorrules&lt;/code&gt; into separate &lt;code&gt;.mdc&lt;/code&gt; files by concern. One for TypeScript conventions, one for testing patterns, whatever.&lt;/p&gt;

&lt;h2&gt;
  
  
  alwaysApply: true or nothing
&lt;/h2&gt;

&lt;p&gt;This one cost me WAY too much time...&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;.mdc&lt;/code&gt; file has YAML frontmatter at the top. There's a field called &lt;code&gt;alwaysApply&lt;/code&gt; and if you don't set it to &lt;code&gt;true&lt;/code&gt;, your rule just doesn't fire. I tested this 13 times because I was convinced something else was wrong. Nope. Without the flag? It got ignored. Every time. With it? It worked every time.&lt;/p&gt;

&lt;p&gt;Your frontmatter needs to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TypeScript&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;conventions&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project"&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.ts"&lt;/span&gt;
&lt;span class="na"&gt;alwaysApply&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without that last line, Cursor acts like the rule doesn't exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be specific or get ignored
&lt;/h2&gt;

&lt;p&gt;I tested vague rules vs specific ones at different lengths. Length doesn't matter AT ALL.&lt;/p&gt;

&lt;p&gt;"Write clean, maintainable code." Longer version? Nah. Shorter version? Nah. Doesn't matter how many paragraphs you write elaborating on it. Your 'clean and maintainable' means the most generic of the generic.&lt;/p&gt;

&lt;p&gt;"Use early returns instead of nested if blocks." That one it followed consistently, even as a single line.&lt;/p&gt;

&lt;p&gt;Cursor isn't reading between the lines. It's not going to interpret "clean code" (or anything else) the way you mean it. You have to spell out exactly what you want unless what you want is...a universal standard, I guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conflicting rules will stall the agent
&lt;/h2&gt;

&lt;p&gt;I had two rules in separate &lt;code&gt;.mdc&lt;/code&gt; files. One said "always add explicit type annotations." The other said "infer types when obvious." I didn't think this would be a big deal, I thought it could pick out the difference in context and use the right one when appropriate.&lt;/p&gt;

&lt;p&gt;Cursor couldn't resolve the contradiction. The agent just sat there. It didn't error, it didn't pick one, it didn't try to merge them. Just... nothing. I thought it was a performance issue before I even thought to check if my rules were fighting each other. We just expect this stuff to work and in reality its brain can break as easily as ours when we're frustrated.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Clean up this code" will delete your comments
&lt;/h2&gt;

&lt;p&gt;This one STILL bothers me. I ran "clean up this code" on 17 different files. Every single comment got stripped. It didn't matter if the comment explained a browser workaround, a compliance requirement, a deprecation timeline. Cursor treated them all as noise.&lt;/p&gt;

&lt;p&gt;Zero files kept their comments.&lt;/p&gt;

&lt;p&gt;I added a rule that says "preserve all existing comments unless they contain TODO, FIXME, or are clearly outdated" and ran it again. Even then it only kept maybe half of them. Cursor seems to have a strong bias toward "clean = fewer comments" and you have to actively fight it.&lt;/p&gt;

&lt;p&gt;I wrote a whole post about this one because I can see a lot of people not catching it in diffs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your frontmatter is probably broken
&lt;/h2&gt;

&lt;p&gt;This is what finally pushed me to build something. Malformed YAML in your &lt;code&gt;.mdc&lt;/code&gt; frontmatter fails completely silently. Missing colon, bad indentation, unclosed quote. No error, no warning. The rule just doesn't exist as far as Cursor is concerned.&lt;/p&gt;

&lt;p&gt;I had rules that looked fine but weren't doing anything, and the reason was a missing colon in the frontmatter. It wasn't a logic problem or a wording problem. It was a typo.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/nedcodes-ok/cursor-doctor" rel="noopener noreferrer"&gt;cursor-doctor&lt;/a&gt; to catch this stuff. I just run it as a pre-commit hook now so I don't waste another afternoon wondering why a rule isn't firing. It checks frontmatter, validates required fields, flags conflicts between rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules vs skills
&lt;/h2&gt;

&lt;p&gt;Cursor added "agent skills" (&lt;code&gt;.cursor/skills/*.md&lt;/code&gt;) recently. I tested both on the same tasks and they both work.&lt;/p&gt;

&lt;p&gt;The difference: rules with &lt;code&gt;alwaysApply: true&lt;/code&gt; load on EVERY task, even unrelated ones. You have a TypeScript formatting rule and you ask Cursor to write a Python script? That TS rule still loads and can confuse things. Skills only load when the task is relevant.&lt;/p&gt;

&lt;p&gt;Oh and one weird thing. &lt;code&gt;.claude/skills/&lt;/code&gt; files from Claude Code don't get discovered by Cursor's agent at all. Skills have to be in &lt;code&gt;.cursor/skills/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model choice doesn't matter for rule compliance
&lt;/h2&gt;

&lt;p&gt;I expected at least one model to be worse at following instructions but nope. I tested the same rules across Sonnet 4.5, Gemini 3 Flash, and GPT-5.1 Codex Mini. All three followed the rules at the same rate. Compliance is about rule quality, not model selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Negative vs positive framing doesn't matter either
&lt;/h2&gt;

&lt;p&gt;"Do NOT use nested ternaries" vs "Use if/else blocks instead of nested ternaries." I ran 30 tests on this. No difference. 30/30 compliance both ways.&lt;/p&gt;

&lt;p&gt;Write rules however feels natural to you. The framing doesn't matter, that's something that mattered for AIs a few years ago but not now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I use now
&lt;/h2&gt;

&lt;p&gt;I have about 8 &lt;code&gt;.mdc&lt;/code&gt; files in most projects. TypeScript conventions, comment preservation, testing patterns, a few framework-specific ones. Each file is short and specific. I run cursor-lint as a pre-commit hook and in CI through the &lt;a href="https://github.com/nedcodes-ok/cursor-lint-action" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The whole setup takes maybe 15 minutes for a new project and it saves me from the stuff I spent weeks debugging when I didn't know any of this.&lt;/p&gt;

&lt;p&gt;🔧 &lt;strong&gt;Want to check your own setup?&lt;/strong&gt; Run &lt;code&gt;npx cursor-doctor scan&lt;/code&gt; to find broken frontmatter, conflicts, and token waste in your Cursor rules. Free, zero dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nedcodes.dev" rel="noopener noreferrer"&gt;nedcodes.dev →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>cursorrules</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
