cursor-lint 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # cursor-lint
2
2
 
3
+ [![npm](https://img.shields.io/npm/dw/cursor-lint)](https://www.npmjs.com/package/cursor-lint)
4
+ [![npm version](https://img.shields.io/npm/v/cursor-lint)](https://www.npmjs.com/package/cursor-lint)
5
+
3
6
  Lint your [Cursor](https://cursor.com) rules. Catch common mistakes before they silently break your workflow.
4
7
 
5
8
  ```bash
@@ -81,10 +84,22 @@ cursor-lint --version Show version
81
84
 
82
85
  Every check in cursor-lint comes from [actual experiments](https://dev.to/nedcodes) testing what Cursor does and doesn't follow. Not guesswork — data.
83
86
 
87
+ ## Need a deeper review?
88
+
89
+ cursor-lint catches structural issues. For a full review of your rules, project structure, and model settings, I offer [$50 async setup audits](https://cursorrulespacks.gumroad.com/l/cursor-setup-audit). You get a written report with specific fixes, not generic advice.
90
+
84
91
  ## License
85
92
 
86
93
  MIT
87
94
 
88
95
  ---
89
96
 
90
- Made by [nedcodes](https://dev.to/nedcodes)
97
+ Made by [nedcodes](https://dev.to/nedcodes) · [Free rules collection](https://github.com/cursorrulespacks/cursorrules-collection) · [Setup audits](https://cursorrulespacks.gumroad.com/l/cursor-setup-audit)
98
+
99
+ ---
100
+
101
+ ## Related
102
+
103
+ - [cursorrules-collection](https://github.com/cursorrulespacks/cursorrules-collection) — 77+ free .mdc rules
104
+ - [Cursor Setup Audit](https://cursorrulespacks.gumroad.com/l/cursor-setup-audit) — Professional review of your rules setup ($50)
105
+ - [Articles on Dev.to](https://dev.to/nedcodes) — Guides on writing effective Cursor rules
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cursor-lint",
3
- "version": "0.3.0",
4
- "description": "Lint your Cursor rules catch common mistakes before they break your workflow",
3
+ "version": "0.4.0",
4
+ "description": "Lint your Cursor rules \u2014 catch common mistakes before they break your workflow",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
7
  "cursor-lint": "src/cli.js"
@@ -12,7 +12,12 @@
12
12
  "cursorrules",
13
13
  "mdc",
14
14
  "linter",
15
- "developer-tools"
15
+ "developer-tools",
16
+ "cursor-rules",
17
+ "lint",
18
+ "validate",
19
+ "ai-coding",
20
+ "code-quality"
16
21
  ],
17
22
  "author": "nedcodes",
18
23
  "license": "MIT",
@@ -26,4 +31,4 @@
26
31
  "files": [
27
32
  "src/"
28
33
  ]
29
- }
34
+ }
package/src/cli.js CHANGED
@@ -4,8 +4,9 @@ const path = require('path');
4
4
  const { lintProject } = require('./index');
5
5
  const { verifyProject } = require('./verify');
6
6
  const { initProject } = require('./init');
7
+ const { fixProject } = require('./fix');
7
8
 
8
- const VERSION = '0.3.0';
9
+ const VERSION = '0.4.0';
9
10
 
10
11
  const RED = '\x1b[31m';
11
12
  const YELLOW = '\x1b[33m';
@@ -28,6 +29,7 @@ ${YELLOW}Options:${RESET}
28
29
  --version, -v Show version number
29
30
  --verify Check if code follows rules with verify: blocks
30
31
  --init Generate starter .mdc rules (auto-detects your stack)
32
+ --fix Auto-fix common issues (missing frontmatter, alwaysApply)
31
33
 
32
34
  ${YELLOW}What it checks (default):${RESET}
33
35
  • .cursorrules files (warns about agent mode compatibility)
@@ -81,8 +83,43 @@ async function main() {
81
83
  const cwd = process.cwd();
82
84
  const isVerify = args.includes('--verify');
83
85
  const isInit = args.includes('--init');
86
+ const isFix = args.includes('--fix');
84
87
 
85
- if (isInit) {
88
+ if (isFix) {
89
+ console.log(`\n🔧 cursor-lint v${VERSION} --fix\n`);
90
+ console.log(`Scanning ${cwd} for fixable issues...\n`);
91
+
92
+ const results = await fixProject(cwd);
93
+
94
+ if (results.length === 0) {
95
+ console.log(`${YELLOW}No .mdc files found in .cursor/rules/${RESET}\n`);
96
+ process.exit(0);
97
+ }
98
+
99
+ let totalFixed = 0;
100
+ for (const result of results) {
101
+ const relPath = path.relative(cwd, result.file) || result.file;
102
+ if (result.changes.length > 0) {
103
+ console.log(`${GREEN}✓${RESET} ${relPath}`);
104
+ for (const change of result.changes) {
105
+ console.log(` ${DIM}→ ${change}${RESET}`);
106
+ }
107
+ totalFixed++;
108
+ } else {
109
+ console.log(`${DIM} ${relPath} — nothing to fix${RESET}`);
110
+ }
111
+ }
112
+
113
+ console.log();
114
+ console.log('─'.repeat(50));
115
+ if (totalFixed > 0) {
116
+ console.log(`${GREEN}Fixed ${totalFixed} file(s)${RESET}. Run cursor-lint to verify.\n`);
117
+ } else {
118
+ console.log(`${GREEN}All files look good — nothing to fix${RESET}\n`);
119
+ }
120
+ process.exit(0);
121
+
122
+ } else if (isInit) {
86
123
  console.log(`\n🔍 cursor-lint v${VERSION} --init\n`);
87
124
  console.log(`Detecting stack in ${cwd}...\n`);
88
125
 
@@ -206,6 +243,11 @@ async function main() {
206
243
  if (totalPassed > 0) parts.push(`${GREEN}${totalPassed} passed${RESET}`);
207
244
  console.log(parts.join(', ') + '\n');
208
245
 
246
+ if (totalErrors > 0) {
247
+ console.log(`${DIM}Need help fixing these? Get a full setup review:${RESET}`);
248
+ console.log(`${CYAN}https://cursorrulespacks.gumroad.com/l/cursor-setup-audit${RESET}\n`);
249
+ }
250
+
209
251
  process.exit(totalErrors > 0 ? 1 : 0);
210
252
  }
211
253
  }
package/src/fix.js ADDED
@@ -0,0 +1,89 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function addFrontmatter(content, filePath) {
5
+ const name = path.basename(filePath, '.mdc');
6
+ const frontmatter = `---
7
+ description: ${name} rules
8
+ alwaysApply: true
9
+ ---
10
+ `;
11
+ return { fixed: frontmatter + content, changes: ['Added YAML frontmatter with alwaysApply: true'] };
12
+ }
13
+
14
+ function addAlwaysApply(content) {
15
+ // Insert alwaysApply: true after the first ---
16
+ const match = content.match(/^(---\n)([\s\S]*?)(---)/);
17
+ if (!match) return { fixed: content, changes: [] };
18
+
19
+ const frontmatterBody = match[2];
20
+ if (frontmatterBody.includes('alwaysApply')) return { fixed: content, changes: [] };
21
+
22
+ const newFm = match[1] + 'alwaysApply: true\n' + frontmatterBody + match[3];
23
+ const rest = content.slice(match[0].length);
24
+ return { fixed: newFm + rest, changes: ['Added alwaysApply: true to frontmatter'] };
25
+ }
26
+
27
+ function addDescription(content, filePath) {
28
+ const match = content.match(/^(---\n)([\s\S]*?)(---)/);
29
+ if (!match) return { fixed: content, changes: [] };
30
+
31
+ const frontmatterBody = match[2];
32
+ if (frontmatterBody.includes('description')) return { fixed: content, changes: [] };
33
+
34
+ const name = path.basename(filePath, '.mdc');
35
+ const newFm = match[1] + `description: ${name} rules\n` + frontmatterBody + match[3];
36
+ const rest = content.slice(match[0].length);
37
+ return { fixed: newFm + rest, changes: [`Added description: "${name} rules" to frontmatter`] };
38
+ }
39
+
40
+ async function fixFile(filePath) {
41
+ let content = fs.readFileSync(filePath, 'utf-8');
42
+ const allChanges = [];
43
+
44
+ // Check if frontmatter exists
45
+ const hasFm = content.match(/^---\n[\s\S]*?\n---/);
46
+
47
+ if (!hasFm) {
48
+ const result = addFrontmatter(content, filePath);
49
+ content = result.fixed;
50
+ allChanges.push(...result.changes);
51
+ } else {
52
+ // Fix missing alwaysApply
53
+ const r1 = addAlwaysApply(content);
54
+ if (r1.changes.length) {
55
+ content = r1.fixed;
56
+ allChanges.push(...r1.changes);
57
+ }
58
+
59
+ // Fix missing description
60
+ const r2 = addDescription(content, filePath);
61
+ if (r2.changes.length) {
62
+ content = r2.fixed;
63
+ allChanges.push(...r2.changes);
64
+ }
65
+ }
66
+
67
+ if (allChanges.length > 0) {
68
+ fs.writeFileSync(filePath, content, 'utf-8');
69
+ }
70
+
71
+ return { file: filePath, changes: allChanges };
72
+ }
73
+
74
+ async function fixProject(dir) {
75
+ const results = [];
76
+ const rulesDir = path.join(dir, '.cursor', 'rules');
77
+
78
+ if (fs.existsSync(rulesDir) && fs.statSync(rulesDir).isDirectory()) {
79
+ for (const entry of fs.readdirSync(rulesDir)) {
80
+ if (entry.endsWith('.mdc')) {
81
+ results.push(await fixFile(path.join(rulesDir, entry)));
82
+ }
83
+ }
84
+ }
85
+
86
+ return results;
87
+ }
88
+
89
+ module.exports = { fixProject, fixFile };