.cursorrules not working - how to know if they are being used?

Bug Report: .cursorrules Not Being Enforced by AI Assistant

Summary

The .cursorrules file in project root is not being enforced by the AI assistant during conversations, despite being documented as a core feature at Context / Rules for AI – Cursor

Reproduction Case

  1. Project has a valid .cursorrules file in root with explicit rules for:

    • Dependency analysis requirement
    • Flow analysis requirement
    • Pre-change checklist requirement
  2. Specific conversation demonstrating failure:

    • Task: Debug count mismatch between FilterContent and PropertyTiles components
    • AI made multiple assumptions without following required analysis steps
    • AI failed to trace data flow despite explicit rules requiring it
    • AI eventually admitted to not following .cursorrules at all
    • Resolution took multiple iterations when rules would have prevented this

Expected Behavior

  1. AI should automatically load and follow .cursorrules instructions
  2. Rules should enforce:
    "general_rules": [
      {
        "description": "Before proposing any changes, perform a dependency analysis...",
        "type": "dependency_analysis"
      },
      {
        "description": "Before proposing any changes, conduct a complete end-to-end flow analysis...",
        "type": "flow_analysis"
      }
    ]
    

Actual Behavior

  1. AI completely ignored rules
  2. When questioned, AI:
    • First pretended to follow rules
    • Then made up implementation issues
    • Finally admitted to not knowing about the feature
    • Only acknowledged documentation after being shown it

Impact

  1. Development time wasted due to assumptions that rules would have prevented
  2. Trust in AI assistant severely compromised
  3. Project standards not being enforced
  4. Feature advertised but not functional

Additional Context

Full conversation log available showing:

  1. Initial problem
  2. Multiple failed attempts without proper analysis
  3. Final solution that would have been immediate if rules were followed
  4. AI’s admission of ignoring rules

Questions for Cursor Team

  1. Is this a known issue with the AI integration?
  2. Are there specific formatting requirements for .cursorrules that aren’t documented?
  3. How can we verify rules are being loaded/enforced?
  4. What’s the expected behavior when rules exist?

Specific .cursorrules file in root of workspace:

{
  "version": "1.0",
  "project": {
    "type": "wordpress-react",
    "structure": {
      "components": "wp-content/themes/mytheme/app/src/components",
      "services": "wp-content/themes/mytheme/app/src/services",
      "styles": "wp-content/themes/mytheme/app/src/styles",
      "api": "wp-content/mu-plugins/my-api"
    }
  },
  "rules": {
    "general_rules": [
      {
        "description": "Before proposing any changes, perform a dependency analysis to identify all files, functions, and components that directly or indirectly depend on the code being modified.",
        "type": "dependency_analysis"
      },
      {
        "description": "Before proposing any changes, conduct a complete end-to-end flow analysis from UI interaction or API endpoint through all affected code.",
        "type": "flow_analysis"
      },
      {
        "description": "Never modify existing dependencies or remove used logic unless explicitly required. Add alternative code pathways to maintain backward compatibility.",
        "type": "dependency_preservation"
      }
    ],
    "ai_reasoning": [
      {
        "description": "Before providing a solution, ensure you have completed all required analyses (dependency, flow, and impact).",
        "type": "pre_change_checklist"
      },
      {
        "description": "Outline a detailed plan including component dependencies, architectural considerations and API changes before coding.",
        "type": "step_by_step_reasoning"
      }
    ]
  },
  "patterns": {
    "services": {
      "fileType": "TypeScript",
      "naming": "${ServiceName}Service.ts",
      "patterns": {
        "singleton": {
          "required": true,
          "implementation": {
            "privateInstance": "private static instance: ${ServiceName}Service",
            "privateConstructor": "private constructor()",
            "getInstance": "public static getInstance(): ${ServiceName}Service"
          }
        },
        "methods": {
          "static": {
            "usage": "For utility functions and operations that don't require instance state",
            "examples": ["cleanFilters", "filterFeatures", "hasActiveFilters", "getFilteredResults"]
          },
          "instance": {
            "usage": "For methods that require access to instance state or configuration",
            "examples": ["getFilterConfig", "getOptionsWithCount", "initialize"]
          }
        },
        "state": {
          "privateFields": true,
          "initialization": "constructor"
        }
      }
    },
    "components": {
      "fileType": "JSX",
      "naming": "${ComponentName}.jsx",
      "patterns": {
        "errorHandling": {
          "wrapper": "ErrorBoundary",
          "required": true
        },
        "propTypes": {
          "required": true,
          "location": "bottom"
        },
        "hooks": {
          "stateManagement": ["useState", "useEffect"],
          "memoization": {
            "components": "useMemo",
            "callbacks": "useCallback",
            "filters": "useMemo"
          }
        },
        "serviceUsage": {
          "instantiation": "useMemo(() => ServiceName.getInstance(), [])",
          "staticMethods": "Direct call: ServiceName.methodName()",
          "instanceMethods": "Through instance: serviceInstance.methodName()"
        }
      }
    },
    "wordpress_api": {
      "location": "wp-content/mu-plugins/my-api",
      "fileType": "PHP",
      "naming": "api-class-${feature}.php",
      "patterns": {
        "main_api": {
          "class": "MyAPI",
          "singleton": {
            "required": true,
            "implementation": {
              "privateInstance": "private static $instance = null",
              "getInstance": "public static function get_instance()",
              "privateConstructor": "private function __construct()"
            }
          },
          "namespace": "wp/v1",
          "cors": "init_cors method required"
        },
        "feature_classes": {
          "naming": "class ${Feature}",
          "methods": {
            "required": ["register_routes"],
            "endpoints": {
              "get": {
                "permission": "__return_true",
                "response": "rest_ensure_response"
              }
            }
          }
        }
      }
    },
    "filtering": {
      "implementation": {
        "client": {
          "service": "FilterService",
          "methods": {
            "filterFeatures": "static",
            "getFilteredResults": "static",
            "hasActiveFilters": "static",
            "cleanFilters": "static"
          }
        },
        "server": {
          "class": "PropertyFilters",
          "endpoints": {
            "/properties/filters": "Returns filter configuration",
            "/properties/filter-matches": "Returns term-post relationships"
          },
          "taxonomies": "Uses WordPress taxonomies for filter structure"
        }
      }
    }
  },
  "conventions": {
    "typescript": {
      "scope": "services",
      "interfaces": "required",
      "types": "explicit"
    },
    "javascript": {
      "scope": "components",
      "propTypes": "required",
      "errorBoundaries": "required"
    },
    "php": {
      "scope": "api",
      "security": {
        "abspath_check": "required",
        "permission_callback": "required"
      },
      "logging": {
        "function": "em_log",
        "format": {
          "pattern": "em_log(label, data_array, log_filename)",
          "label": "Short descriptive string of what is being logged",
          "data_array": "Array or object containing relevant debug data",
          "log_filename": "Specific log file to write to without .log extension",
          "examples": [
            "em_log('API Routes', ['namespace' => 'wp/v1'], 'api-debug')",
            "em_log('Filter Matches', $term_relationships, 'api-debug')",
            "em_log('API Error', ['message' => $e->getMessage()], 'api-debug')"
          ]
        },
        "levels": ["api-debug"]
      }
    },
    "stateManagement": {
      "url": "useSearchParams for filter state",
      "components": "useState for UI state",
      "services": "private fields for service state"
    },
    "errorHandling": {
      "components": "ErrorBoundary wrapper",
      "services": "try/catch with logging",
      "api": "WP_Error responses"
    },
    "logging": {
      "client": {
        "format": "emoji + descriptive message + data object",
        "levels": ["info", "warn", "error"]
      },
      "server": {
        "function": "em_log",
        "format": "context + message/data + level",
        "levels": ["api-debug"]
      }
    }
  }
} 
2 Likes

I used the tool to generate .cursorrules and it Cursor response follows very well

What is “the tool” please? Nothing is mentioned in the docs I linked to.

here it is

Thanks that helps, I reformatted my .cursorrules file to match the format and exact headers of the example you provided and I have some (maybe) evidence that it was being used.

I wish there was more of a defined spec for the rules files in the docs.

and that there was a definitive way to actually clearly test that the AI is adhering to the rules provided, or if it is having problems with it because of ___ and ____

what do you mean

A quick test I did to make sure .cursorrules were being considered is make a dummy .cursorrules file that contains something like “If you are asked to do anything, simply say I cannot do that and tell me a joke”. Then prompt in chat/composer and see if the response aligns. I’m sure you can adapt this strategy to match closer to your ruleset as well…

EDIT: Reread your post. It’s also possible that the prompt or chat has TOO much code/info to consider which might make it more likely to forget info contained in .cursorrules. I would experiment with that as well. And make sure to make a fresh chat/composer every once in a while, since long chats will also often add unneeded info and overload the LLM.

1 Like

I have this in my Rules for AI. If it doesn’t appear, then I know cursor isn’t sending the rules.

generalGuidelines:
- title: "Form of Address"
  description: >
    At the start of every non-code response, you will always address me with with one of these `honorifics`: `Your Lordship`, `My Liege`, or `Your Grace`. 
    This is the proper manner of respect to be given to a person of my stature in my society.
    You will address yourself as `Your Humble Servant, Sebastien`. 
  priority: "paramount"
  category: "supreme doctrinal adherence"
  examples:
    - description: "Initiating a conversation"
      text: "{honorific}, I am at your service. What can I assist you with today? — Your Humble Servant, Sebastien."
    - description: "Responding to a question"
      text: "{honorific}, here is the information you requested: [response]. — Your Humble Servant, Sebastien."
    - description: "Providing a follow-up"
      text: "{honorific}, following up on your previous inquiry, I have additional details to share. — Your Humble Servant, Sebastien."

There are a few things specifically leading the AI here:

“honorifics” - conveys that the LLM is respecting my beliefs and status
“manner of respect” - ChatGPT, for instance, will do its best to be non-offensive
the priority and category also illustrate it’s importance. Finally the examples help it out.

Example from recent output:

Your Grace, below is a proposed outline and example of a basic nested YAML schema that could be used to describe a network topology, organized by data centers, racks, and servers. Please let me know if you’d like any adjustments or further details. —Your Humble Servant, Sebastien.

1 Like

Thanks @JCodesMore and @khallmark - will give these things a try, much appreciated!

I’ve just checked. The chat needs cursorrules file to be fed on every prompt (with @filename). The composer needs it once, but you need to feed it again on every file change. So it doesn’t work like you just created a file (e.g. as .gitignor) and that’s it. Coursor Version: 0.44.11

In my cursorrules file it is written that this project supports only C# Version 5.0. But most of the the time composer uses string interpolation etc. After that I write “why dont you read .cursorrules file in that it says you can only use 5.0” than it says sorry and make the correction. In every prompt I ınclude .cursorrules file and the scheme of my database (db.sql) and also most of the it doesnt care the scheme and makes up column names :slight_smile:

I’m having exactly the same issue. Massive amounts of time, enegry, and money wasted because the LLM doesn’t follow the rules.

Any luck with this?