building your cursor ide stdlib
2025-04-07
In the rapidly evolving landscape of AI-powered development tools, Cursor IDE stands out with its unique ability to learn and adapt to your codebase. This post is some of my notes on my attempts to leverage Cursor’s .cursor/rules
system to build your own “stdlib” - a standard library of knowledge that makes your AI assistant smarter and more effective over time.
What is Cursor?
Cursor is a VSCode fork that integrates an LLM agent with access to all the files in your workspace as a sidebar in the IDE interface. This is more powerful than copy/paste-ing into Anthropic’s or OpenAI’s web interface, Cursor provides a mechanism for executing commands within the default shell environment, as well as hooks to read, create, and edit existing files.
Something that wasn’t obvious to me for my first week of using cursor was that the AI component has 3 modes:
- Ask Mode: User-initiated queries for explanations, refactoring, or problem-solving
- Manual Mode: Traditional coding with AI assistance on demand
- Agent Mode (⌘I): Proactive AI that suggests improvements and learns from your codebase
I had been working in the ask
mode, and hadn’t been terribly enthused with the results. It seemed to be nothing much different than using the web interfaces and copying results into my editor. Once I discovered the agent
mode however, I discovered the agent/tool integrations and I started to see some of the magic that Cursor can offer.
Uncovering the agent
mode is when I starting seeing the AI model read my code base, implement a change to the code base, run a test suite, read the test results, and iterate on any bugs or failures. It did all this on its own just from an initial prompt to implement some feature.
Note: For all of the Cursor interactions, you can select between an “auto” model selection mode and selecting a specific model to service your conversation. The bulk of this article is written from the perspective of using the “auto” model selection mode. With the business account that I have access to, using a specified model incurs “usage-based-pricing” so I generally don’t use this mode.
Understanding Cursor Rules
The heart of Cursor’s learning capability lies in its .cursor/rules
system. Think of it as your AI’s personal knowledge base - a collection of guidelines, patterns, and best practices specific to your project.
Once you uncover this superpower, you will probably start to notice some odd behavior though. The AI model sometimes has quirky ways of interacting with tools, or uses code patterns that you don’t want to use.
For example when adding a dependency, instead of using the package manager tooling e.g. yarn add <dependency>
, the first tendency seems to be to directly modify the package manifest file and write the dependencies into the appropriate part of the file. It does this in a syntactically correct way, but relies on the pre-trained memory as to which package versions to add. The result is that the versions are almost universally out of date, sometimes not even the same major version as the latest version.
You can type a message with feedback to try and correct the undesired behavior via the interface and you’ll probably see a decent result come out from that, but that feedback won’t be stored anywhere long term. When you open Cursor the following day to resume working, its apt to make the same mistake again!
Luckily Cursor rules give us a way to provide Cursor with a long term “memory” and teach it to behave the way we want to.
Rule Types
Cursor rules come in four flavors:
Auto-attached Rules
- Triggered automatically based on file patterns
- Example: Rules for
*.js
,*.toml
, orcontent/*.md
files - Applied whenever matching files are being worked with
Agent-requested Rules
- Used contextually when relevant
- The Cursor agent reads rule descriptions to decide when to apply them
- Helps maintain consistency across similar scenarios
Always Rules
- Global rules applied to every interaction
- Perfect for project-wide conventions and standards
Manual Rules
- Explicitly referenced in agent chat or other rules
- Used for specific scenarios or complex workflows
Anatomy of a Rule
A Cursor rule is a Markdown file (.mdc
) with a specific structure, located in the .cursor/rules/
folder of a workspace.
There is a yaml-header followed by markdown content. Thats all that is required. You can put whatever markdown content you want into the rule. If the rule gets applied, the content of the rule is read into the context window, ensuring the agent is aware of the rule when acting and responding.
---
description: Clear purpose of the rule
globs: ["*.ts", "*.tsx"]
alwaysApply: false
---
# Rule Title
There is no requirement on the structure of a rule's content, but this is a good pattern to follow.
## Context
Description of what the rule addresses
## Guidelines
Specific instructions for the AI to follow
## Examples
Concrete code samples showing the rule in action, both good and bad examples.
The yaml-header has 4 patterns, depending on which of the 4 modes was selected.
- Auto-attached rules - ❌
description
, ✅globs
, ❌alwaysApply
.
---
description:
globs: content/**/*.md,*.scss
alwaysApply: false
---
- Agent requested rules - ✅
description
, ❌globs
, ❌alwaysApply
.
---
description: Rule description
globs:
alwaysApply: false
---
- Always apply rules - ❌
description
, ❌globs
, ✅alwaysApply
.
---
description:
globs:
alwaysApply: true
---
- Manual rules - ❌
description
, ❌globs
, ❌alwaysApply
.
---
description:
globs:
alwaysApply: false
---
With these building blocks you can start to write out your own rules to modify the long term behavior of the AI agent in Cursor.
Writing rules by hand works, and I encourage you to give it a try, but wouldn’t it be better if Cursor could write the rules itself?
The Power of Self-Learning
What makes Cursor’s rule system truly powerful is its ability to evolve with your project. The self-learning process follows a simple cycle:
- Pattern Recognition: Identify common issues or patterns
- Documentation: Find solutions and best practices
- Rule Creation: Formalize knowledge into rules
- Refinement: Apply, test, and improve rules over time
There isn’t anything about this framework that is built into Cursor. This is behavior that we can give to Cursor by using a rule.
A rule to rule all rules
This is an example of a rule I have implemented in a project to give Cursor this self-learning capability. I haven’t settled on the best type of rule to use, this is implemented as a “agent_requested” rule type.
1 ---
2 description: Mandatory framework for learning from errors and building new rules to improve the knowledge base.
3 globs:
4 alwaysApply: false
5 ---
6 # Self-Learning and Error Correction
7
8 ## Overview
9 This rule establishes a framework for Cursor to learn from its mistakes and build a growing knowledge base about this codebase. When Cursor makes an error that requires correction, it should analyze the error, understand the correct solution, and update its knowledge base accordingly. This includes strict rules for where to place new rules.
10
11 ## Error Analysis Process
12 When a code suggestion generates an error or requires manual correction:
13
14 1. Identify the specific error type and root cause
15 2. Document the incorrect approach that was taken
16 3. Document the correct solution that fixed the issue
17 4. Create or update rules with this new knowledge
18
19 ## Automatic Learning
20 Cursor should maintain a registry of common errors it has encountered and their solutions in the `.cursor/rules/registry` directory. Each time a new pattern is identified follow these rules:
21
22 1. Always place rule files in PROJECT_ROOT/.cursor/rules/registry:
23 .cursor/rules/registry
24 ├── your-rule-name.mdc
25 ├── another-rule.mdc
26 └── ...
27
28 2. Follow the naming convention:
29 - Use kebab-case for filenames
30 - Always use .mdc extension
31 - Make names descriptive of the rule's purpose
32
33 3. Directory structure:
34 PROJECT_ROOT/
35 ├── .cursor/
36 │ └── rules/
37 │ └── registry/
38 │ ├── your-rule-name.mdc
39 │ └── ...
40 └── ...
41
42 4. Never place rule files:
43 - In the project root
44 - In subdirectories outside .cursor/rules
45 - In any other location
46
47 5. Determine which type of rule it should be:
48 - `auto_attached`, characterized by a `glob` value which is a list of filename glob patterns which should invoke the rule.
49 - `agent_requested`, characterized by a `description` which is read by the agent to determine if the rule should be invoked.
50 - `always`, characterized by always including the rule into every agent context.
51 - `manual`, characterized by requiring direct reference to the file for the rule to be invoked by another rule.
52 6. Add YAML frontmatter metadata with `description`, `type`, and `glob` if this will be an `auto_attached` rule.
53 7. Include examples of both incorrect and correct implementations.
54 8. Reference any related rules that might apply.
55
56 NOTE: The rule files that are located in `.cursor/rules/` and not inside of `.cursor/rules/registry/` are the anchor rules that seeded this project with its guidelines.
57
58 examples:
59 - input: |
60 # Bad: Rule file in wrong location
61 rules/my-rule.mdc
62 my-rule.mdc
63 .rules/my-rule.mdc
64
65 # Good: Rule file in correct location
66 .cursor/rules/my-rule.mdc
67 output: "Correctly placed Cursor rule file"
68
69 ## How to define which rule type
70
71 The yaml-header for a rule file has 4 patterns, depending on which of the 4 modes was selected.
72
73 1. Auto-attached rules - ❌ `description`, ✅ `globs`, ❌ `alwaysApply`.
74 ```yaml
75 ---
76 description:
77 globs: content/**/*.md,*.scss
78 alwaysApply: false
79 ---
80 ```
81 2. Agent requested rules - ✅ `description`, ❌ `globs`, ❌ `alwaysApply`.
82
83 ```yaml
84 ---
85 description: Rule description
86 globs:
87 alwaysApply: false
88 ---
89 ```
90 3. Always apply rules - ❌ `description`, ❌ `globs`, ✅ `alwaysApply`.
91 ```yaml
92 ---
93 description:
94 globs:
95 alwaysApply: true
96 ---
97 ```
98 4. Manual rules - ❌ `description`, ❌ `globs`, ❌ `alwaysApply`.
99 ```yaml
100 ---
101 description:
102 globs:
103 alwaysApply: false
104 ---
105 ```
106
107 ## Error Categories
108 Maintain specific sections for different error types.
109
110 ### Type Errors
111 Document common type errors specific to this codebase and how to properly type definitions.
112
113 ### Integration Errors
114 Track errors related to integration tests and their resolution.
115
116 ### Performance Issues
117 Document patterns that lead to performance issues and their optimized alternatives.
118
119 ### Dependency Management
120 Track uv and yarn/package management issues and their solutions.
121
122 ## Continuous Improvement
123 This rule should evolve over time as new errors are encountered and resolved. When implementing a fix that's been seen before, reference the relevant rule. When implementing a fix for a new type of error, create a new rule or update existing ones.
124
125 ## Example Learning Pattern
126
127 ````
128 ---
129 description: Type Error in Redpanda Connect Pipeline
130 globs: *.py
131 alwaysApply: false
132 ---
133
134 # TypeScript Type Error in Pipeline Configuration
135
136 ## Incorrect Pattern
137 ```typescript
138 const pipeline = createPipeline({
139 input: {
140 // Missing required type information
141 topic: "input-topic",
142 config: {}
143 },
144 // Other configuration
145 });
146 ```
147
148 ## Correct Pattern
149 ```typescript
150 const pipeline = createPipeline<InputSchema, OutputSchema>({
151 input: {
152 // Properly typed with required interface
153 topic: "input-topic",
154 config: {
155 consumerGroup: "my-group"
156 }
157 },
158 // Other configuration
159 });
160 ```
161
162 ## Explanation
163 Redpanda Connect pipelines require explicit type parameters and proper configuration of consumer groups to function correctly.
164 ````
165
166 ## Implementation Instructions
167 When you encounter a pattern that seems to repeat or an error that occurs more than once, ask Cursor to create a new rule file documenting this pattern in the `.cursor/rules/registry` directory.
Error Analysis Framework
When encountering issues, Cursor can help build new rules using this framework:
- Identify the root cause of the error
- Document the incorrect approach that led to it
- Record the correct solution
- Create or update rules to prevent similar issues
Common rule categories include:
- Type system errors
- Tool usage issues
- Avoiding low performance patterns
- Dependency management
- Project-specific conventions
Getting Started with Rules
Ready to build your own stdlib? Here’s how to begin:
- Install Cursor IDE from cursor.sh
- Create a
.cursor/rules
directory in your project - Add your self-learning rule
- Let cursor add rules organically as you work
Start small - create rules for patterns you encounter frequently. Over time, your rule collection will grow into a comprehensive knowledge base that makes your development process more efficient and consistent.
Resources
To learn more about Cursor and rules:
Happy coding!