rebar-mcp 2.0.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/.claude/agents/template-writer.md +43 -0
- package/.claude/agents/test-runner.md +47 -0
- package/.claude/mcp.json +9 -0
- package/.claude/settings.json +29 -0
- package/.claude/skills/ /SKILL.md +21 -0
- package/.claude/skills/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SKILL.md +21 -0
- package/.claude/skills/bmmibwetxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibwjgvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibwsesxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibwxufxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibx3r9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmji0lrkxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjiniphxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjio86zxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjiolfbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjit1lvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjita1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibweu3/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibwjh4/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibwsey/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibwxup/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibx3rg/SKILL.md +21 -0
- package/.claude/skills/bnd-mmji0lrp/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjinipm/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjio875/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjiolfg/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjit1m3/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjita1x/SKILL.md +21 -0
- package/.claude/skills/coercion-test/SKILL.md +50 -0
- package/.claude/skills/large-skill/SKILL.md +21 -0
- package/.claude/skills/long-desc-skill/SKILL.md +21 -0
- package/.claude/skills/mcp-dev/SKILL.md +61 -0
- package/.claude/skills/nl-mmibweus/SKILL.md +25 -0
- package/.claude/skills/nl-mmibwjhf/SKILL.md +25 -0
- package/.claude/skills/nl-mmibwsf7/SKILL.md +25 -0
- package/.claude/skills/nl-mmibwxvq/SKILL.md +25 -0
- package/.claude/skills/nl-mmibx3rt/SKILL.md +25 -0
- package/.claude/skills/nl-mmji0lrz/SKILL.md +25 -0
- package/.claude/skills/nl-mmjinipx/SKILL.md +25 -0
- package/.claude/skills/nl-mmjio87f/SKILL.md +25 -0
- package/.claude/skills/nl-mmjiolfs/SKILL.md +25 -0
- package/.claude/skills/nl-mmjit1mc/SKILL.md +25 -0
- package/.claude/skills/nl-mmjita26/SKILL.md +25 -0
- package/.claude/skills/rapid-1/SKILL.md +21 -0
- package/.claude/skills/rapid-2/SKILL.md +21 -0
- package/.claude/skills/rapid-3/SKILL.md +21 -0
- package/.claude/skills/rapid-4/SKILL.md +21 -0
- package/.claude/skills/rapid-5/SKILL.md +21 -0
- package/.claude/skills/test/", /"malicious/": /"true/SKILL.md" +69 -0
- package/.claude/skills/test-emoji-/360/237/230/200-skill/SKILL.md +69 -0
- package/.claude/skills/test-skill/SKILL.md +69 -0
- package/.claude/skills/test; rm -rf /; skill/SKILL.md +69 -0
- package/.claude/skills/test<script>alert(1)</script>skill/SKILL.md +69 -0
- package/.claudeignore +5 -0
- package/.mcp.json +3 -0
- package/CHANGELOG.md +29 -0
- package/CLAUDE.md +76 -0
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/ROADMAP.md +526 -0
- package/ccboot-PRD-v1.0.docx.md +732 -0
- package/ccboot-v1.2.0-enforcement-spec.md +1272 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +674 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +25 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +118 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +62 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +15 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/scaffolding.d.ts +277 -0
- package/dist/schemas/scaffolding.d.ts.map +1 -0
- package/dist/schemas/scaffolding.js +133 -0
- package/dist/schemas/scaffolding.js.map +1 -0
- package/dist/services/claudemd-generator.d.ts +16 -0
- package/dist/services/claudemd-generator.d.ts.map +1 -0
- package/dist/services/claudemd-generator.js +426 -0
- package/dist/services/claudemd-generator.js.map +1 -0
- package/dist/services/codex-generator.d.ts +6 -0
- package/dist/services/codex-generator.d.ts.map +1 -0
- package/dist/services/codex-generator.js +35 -0
- package/dist/services/codex-generator.js.map +1 -0
- package/dist/services/cursor-generator.d.ts +15 -0
- package/dist/services/cursor-generator.d.ts.map +1 -0
- package/dist/services/cursor-generator.js +134 -0
- package/dist/services/cursor-generator.js.map +1 -0
- package/dist/services/file-ops.d.ts +48 -0
- package/dist/services/file-ops.d.ts.map +1 -0
- package/dist/services/file-ops.js +153 -0
- package/dist/services/file-ops.js.map +1 -0
- package/dist/services/output-formatter.d.ts +57 -0
- package/dist/services/output-formatter.d.ts.map +1 -0
- package/dist/services/output-formatter.js +88 -0
- package/dist/services/output-formatter.js.map +1 -0
- package/dist/services/platform-detect.d.ts +14 -0
- package/dist/services/platform-detect.d.ts.map +1 -0
- package/dist/services/platform-detect.js +63 -0
- package/dist/services/platform-detect.js.map +1 -0
- package/dist/services/project-analyzer.d.ts +71 -0
- package/dist/services/project-analyzer.d.ts.map +1 -0
- package/dist/services/project-analyzer.js +595 -0
- package/dist/services/project-analyzer.js.map +1 -0
- package/dist/services/rules-engine.d.ts +41 -0
- package/dist/services/rules-engine.d.ts.map +1 -0
- package/dist/services/rules-engine.js +304 -0
- package/dist/services/rules-engine.js.map +1 -0
- package/dist/services/strictness.d.ts +37 -0
- package/dist/services/strictness.d.ts.map +1 -0
- package/dist/services/strictness.js +182 -0
- package/dist/services/strictness.js.map +1 -0
- package/dist/services/template-engine.d.ts +16 -0
- package/dist/services/template-engine.d.ts.map +1 -0
- package/dist/services/template-engine.js +85 -0
- package/dist/services/template-engine.js.map +1 -0
- package/dist/services/validation.d.ts +41 -0
- package/dist/services/validation.d.ts.map +1 -0
- package/dist/services/validation.js +104 -0
- package/dist/services/validation.js.map +1 -0
- package/dist/services/windsurf-generator.d.ts +15 -0
- package/dist/services/windsurf-generator.d.ts.map +1 -0
- package/dist/services/windsurf-generator.js +127 -0
- package/dist/services/windsurf-generator.js.map +1 -0
- package/dist/tests/enforcement.test.d.ts +2 -0
- package/dist/tests/enforcement.test.d.ts.map +1 -0
- package/dist/tests/enforcement.test.js +541 -0
- package/dist/tests/enforcement.test.js.map +1 -0
- package/dist/tests/enterprise.test.d.ts +2 -0
- package/dist/tests/enterprise.test.d.ts.map +1 -0
- package/dist/tests/enterprise.test.js +353 -0
- package/dist/tests/enterprise.test.js.map +1 -0
- package/dist/tests/fuzzing.test.d.ts +2 -0
- package/dist/tests/fuzzing.test.d.ts.map +1 -0
- package/dist/tests/fuzzing.test.js +596 -0
- package/dist/tests/fuzzing.test.js.map +1 -0
- package/dist/tests/knowledge.test.d.ts +2 -0
- package/dist/tests/knowledge.test.d.ts.map +1 -0
- package/dist/tests/knowledge.test.js +292 -0
- package/dist/tests/knowledge.test.js.map +1 -0
- package/dist/tests/management.test.d.ts +2 -0
- package/dist/tests/management.test.d.ts.map +1 -0
- package/dist/tests/management.test.js +338 -0
- package/dist/tests/management.test.js.map +1 -0
- package/dist/tests/scaffolding.test.d.ts +2 -0
- package/dist/tests/scaffolding.test.d.ts.map +1 -0
- package/dist/tests/scaffolding.test.js +419 -0
- package/dist/tests/scaffolding.test.js.map +1 -0
- package/dist/tests/test-utils.d.ts +76 -0
- package/dist/tests/test-utils.d.ts.map +1 -0
- package/dist/tests/test-utils.js +171 -0
- package/dist/tests/test-utils.js.map +1 -0
- package/dist/tests/tool-harness.d.ts +18 -0
- package/dist/tests/tool-harness.d.ts.map +1 -0
- package/dist/tests/tool-harness.js +51 -0
- package/dist/tests/tool-harness.js.map +1 -0
- package/dist/tools/enterprise.d.ts +8 -0
- package/dist/tools/enterprise.d.ts.map +1 -0
- package/dist/tools/enterprise.js +571 -0
- package/dist/tools/enterprise.js.map +1 -0
- package/dist/tools/knowledge.d.ts +7 -0
- package/dist/tools/knowledge.d.ts.map +1 -0
- package/dist/tools/knowledge.js +120 -0
- package/dist/tools/knowledge.js.map +1 -0
- package/dist/tools/management.d.ts +10 -0
- package/dist/tools/management.d.ts.map +1 -0
- package/dist/tools/management.js +1541 -0
- package/dist/tools/management.js.map +1 -0
- package/dist/tools/scaffolding.d.ts +8 -0
- package/dist/tools/scaffolding.d.ts.map +1 -0
- package/dist/tools/scaffolding.js +736 -0
- package/dist/tools/scaffolding.js.map +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/landing/app/layout.tsx +30 -0
- package/landing/app/page.tsx +944 -0
- package/landing/next-env.d.ts +6 -0
- package/landing/next.config.js +6 -0
- package/landing/package-lock.json +896 -0
- package/landing/package.json +20 -0
- package/landing/tsconfig.json +40 -0
- package/package.json +49 -0
- package/rebar-v2.0.0-platform-spec.md +1567 -0
- package/server.json +20 -0
- package/src/cli.ts +735 -0
- package/src/constants.ts +131 -0
- package/src/index.ts +54 -0
- package/src/schemas/common.ts +22 -0
- package/src/schemas/scaffolding.ts +161 -0
- package/src/services/claudemd-generator.ts +481 -0
- package/src/services/codex-generator.ts +44 -0
- package/src/services/cursor-generator.ts +153 -0
- package/src/services/file-ops.ts +172 -0
- package/src/services/platform-detect.ts +80 -0
- package/src/services/project-analyzer.ts +690 -0
- package/src/services/rules-engine.ts +353 -0
- package/src/services/strictness.ts +202 -0
- package/src/services/template-engine.ts +119 -0
- package/src/services/validation.ts +138 -0
- package/src/services/windsurf-generator.ts +145 -0
- package/src/tests/enforcement.test.ts +794 -0
- package/src/tests/enterprise.test.ts +483 -0
- package/src/tests/fuzzing.test.ts +690 -0
- package/src/tests/knowledge.test.ts +371 -0
- package/src/tests/management.test.ts +451 -0
- package/src/tests/scaffolding.test.ts +575 -0
- package/src/tests/test-utils.ts +206 -0
- package/src/tests/tool-harness.ts +70 -0
- package/src/tools/enterprise.ts +666 -0
- package/src/tools/knowledge.ts +162 -0
- package/src/tools/management.ts +1706 -0
- package/src/tools/scaffolding.ts +909 -0
- package/src/types.ts +93 -0
- package/supabase/.temp/cli-latest +1 -0
- package/supabase/.temp/gotrue-version +1 -0
- package/supabase/.temp/pooler-url +1 -0
- package/supabase/.temp/postgres-version +1 -0
- package/supabase/.temp/project-ref +1 -0
- package/supabase/.temp/rest-version +1 -0
- package/supabase/.temp/storage-migration +1 -0
- package/supabase/.temp/storage-version +1 -0
- package/templates/agents/explore.md +41 -0
- package/templates/agents/plan.md +73 -0
- package/templates/agents/security-auditor.md +77 -0
- package/templates/agents/test-runner.md +60 -0
- package/templates/claudemd/fastapi.md +49 -0
- package/templates/claudemd/monorepo.md +48 -0
- package/templates/claudemd/nextjs.md +52 -0
- package/templates/claudemd/react-spa.md +50 -0
- package/templates/claudemd/springboot.md +50 -0
- package/templates/hooks/danger-blocker.json +11 -0
- package/templates/hooks/format-on-write.json +17 -0
- package/templates/hooks/lint-on-write.json +16 -0
- package/templates/hooks/secret-detector.json +11 -0
- package/templates/skills/code-review.md +68 -0
- package/templates/skills/documentation.md +62 -0
- package/templates/skills/performance-audit.md +80 -0
- package/templates/skills/security-scan.md +66 -0
- package/templates/skills/test-writer.md +56 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intelligent CLAUDE.md generator.
|
|
3
|
+
*
|
|
4
|
+
* Unlike a dumb template fill, this reads the actual project analysis
|
|
5
|
+
* and generates a CLAUDE.md that reflects the real project — with real
|
|
6
|
+
* build commands, real dependencies, real architecture rules.
|
|
7
|
+
*
|
|
8
|
+
* The output should feel like a senior engineer sat down and wrote it
|
|
9
|
+
* by hand after spending 30 minutes understanding the project.
|
|
10
|
+
*/
|
|
11
|
+
import type { ProjectAnalysis } from "./project-analyzer.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generates a production-quality CLAUDE.md from project analysis.
|
|
15
|
+
*/
|
|
16
|
+
export function generateClaudeMD(analysis: ProjectAnalysis, compliance: string[] = []): string {
|
|
17
|
+
const sections: string[] = [];
|
|
18
|
+
|
|
19
|
+
// ── Header ────────────────────────────────────────────────────
|
|
20
|
+
sections.push(`# ${analysis.name}\n`);
|
|
21
|
+
if (analysis.description) {
|
|
22
|
+
sections.push(`${analysis.description}\n`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ── Tech Stack ────────────────────────────────────────────────
|
|
26
|
+
sections.push(generateTechStackSection(analysis));
|
|
27
|
+
|
|
28
|
+
// ── Architecture Rules ────────────────────────────────────────
|
|
29
|
+
sections.push(generateArchitectureRules(analysis));
|
|
30
|
+
|
|
31
|
+
// ── Build & Test ──────────────────────────────────────────────
|
|
32
|
+
sections.push(generateBuildSection(analysis));
|
|
33
|
+
|
|
34
|
+
// ── File Structure ────────────────────────────────────────────
|
|
35
|
+
if (analysis.sourceDirs.length > 0) {
|
|
36
|
+
sections.push(generateFileStructure(analysis));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ── Code Conventions ──────────────────────────────────────────
|
|
40
|
+
sections.push(generateCodeConventions(analysis));
|
|
41
|
+
|
|
42
|
+
// ── Database ──────────────────────────────────────────────────
|
|
43
|
+
if (analysis.database) {
|
|
44
|
+
sections.push(generateDatabaseSection(analysis));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ── Environment ───────────────────────────────────────────────
|
|
48
|
+
if (analysis.envVarNames.length > 0) {
|
|
49
|
+
sections.push(generateEnvSection(analysis));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ── Compliance ────────────────────────────────────────────────
|
|
53
|
+
if (compliance.length > 0) {
|
|
54
|
+
sections.push(generateComplianceSection(compliance));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return sections.join("\n");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function generateTechStackSection(a: ProjectAnalysis): string {
|
|
61
|
+
const lines = ["## Tech Stack"];
|
|
62
|
+
|
|
63
|
+
// Primary language and version
|
|
64
|
+
if (a.language === "typescript") {
|
|
65
|
+
lines.push("- TypeScript (strict mode)");
|
|
66
|
+
} else if (a.language === "javascript") {
|
|
67
|
+
lines.push("- JavaScript (ES2022+)");
|
|
68
|
+
} else if (a.language === "python") {
|
|
69
|
+
lines.push("- Python 3.11+");
|
|
70
|
+
} else if (a.language === "go") {
|
|
71
|
+
lines.push("- Go 1.21+");
|
|
72
|
+
} else if (a.language === "rust") {
|
|
73
|
+
lines.push("- Rust (latest stable)");
|
|
74
|
+
} else if (a.language === "java") {
|
|
75
|
+
lines.push("- Java 17+ / Spring Boot 3.x");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (a.nodeVersion) {
|
|
79
|
+
lines.push(`- Node.js ${a.nodeVersion}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Frameworks
|
|
83
|
+
for (const dep of a.keyDependencies.filter((d) => d.category === "framework")) {
|
|
84
|
+
lines.push(`- ${dep.name} — ${dep.description}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Database/ORM
|
|
88
|
+
for (const dep of a.keyDependencies.filter((d) => d.category === "orm")) {
|
|
89
|
+
lines.push(`- ${dep.name} — ${dep.description}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Styling
|
|
93
|
+
if (a.cssFramework) {
|
|
94
|
+
lines.push(`- ${a.cssFramework} for styling`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Testing
|
|
98
|
+
if (a.testFramework) {
|
|
99
|
+
lines.push(`- ${a.testFramework} for testing`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Linting
|
|
103
|
+
if (a.linter && a.formatter && a.linter === a.formatter) {
|
|
104
|
+
lines.push(`- ${a.linter} for linting and formatting`);
|
|
105
|
+
} else {
|
|
106
|
+
if (a.linter) lines.push(`- ${a.linter} for linting`);
|
|
107
|
+
if (a.formatter) lines.push(`- ${a.formatter} for formatting`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// State management, auth, API
|
|
111
|
+
for (const dep of a.keyDependencies.filter((d) => ["state", "auth", "api"].includes(d.category))) {
|
|
112
|
+
lines.push(`- ${dep.name} — ${dep.description}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Deploy
|
|
116
|
+
if (a.deployTarget) {
|
|
117
|
+
lines.push(`- Deployed to ${a.deployTarget}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Monitoring
|
|
121
|
+
for (const dep of a.keyDependencies.filter((d) => d.category === "monitoring")) {
|
|
122
|
+
lines.push(`- ${dep.name} — ${dep.description}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Monorepo
|
|
126
|
+
if (a.isMonorepo && a.monorepoTool) {
|
|
127
|
+
lines.push(`- Monorepo managed with ${a.monorepoTool}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return lines.join("\n") + "\n";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function generateArchitectureRules(a: ProjectAnalysis): string {
|
|
134
|
+
const rules: string[] = ["## Architecture Rules"];
|
|
135
|
+
|
|
136
|
+
// ── Framework-specific rules ──────────────────────────────────
|
|
137
|
+
|
|
138
|
+
if (a.stacks.includes("nextjs")) {
|
|
139
|
+
const appRouter = a.patterns.some((p) => p.name === "app-router");
|
|
140
|
+
if (appRouter) {
|
|
141
|
+
rules.push("- Use App Router conventions: `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`");
|
|
142
|
+
rules.push("- Server Components by default; add `\"use client\"` only when client interactivity is needed");
|
|
143
|
+
rules.push("- All data fetching in Server Components or Route Handlers — never use `getServerSideProps`");
|
|
144
|
+
rules.push("- Use `next/image` for images, `next/link` for navigation, `next/font` for fonts");
|
|
145
|
+
} else {
|
|
146
|
+
rules.push("- Follow Pages Router conventions: `pages/`, `getStaticProps`, `getServerSideProps`");
|
|
147
|
+
rules.push("- Use `next/image` for images, `next/link` for navigation");
|
|
148
|
+
}
|
|
149
|
+
rules.push("- Environment variables: `NEXT_PUBLIC_` prefix for client-side only");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (a.stacks.includes("react") && !a.stacks.includes("nextjs")) {
|
|
153
|
+
rules.push("- Functional components only — no class components");
|
|
154
|
+
rules.push("- Custom hooks for reusable logic (`useXxx` naming convention)");
|
|
155
|
+
rules.push("- Use `React.lazy()` for code splitting at route level");
|
|
156
|
+
rules.push("- Colocate related files: component, styles, tests, types in same directory");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (a.stacks.includes("express")) {
|
|
160
|
+
rules.push("- Controllers handle HTTP concerns only — business logic goes in services/");
|
|
161
|
+
rules.push("- Use middleware for cross-cutting concerns (auth, logging, validation)");
|
|
162
|
+
rules.push("- All route handlers must have error handling (try/catch or error middleware)");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (a.stacks.includes("fastapi")) {
|
|
166
|
+
rules.push("- Use dependency injection via `Depends()` for shared logic");
|
|
167
|
+
rules.push("- All endpoints return Pydantic models — never return raw dicts");
|
|
168
|
+
rules.push("- Use `async/await` for all I/O operations");
|
|
169
|
+
rules.push("- Keep route handlers thin; business logic in `services/`");
|
|
170
|
+
rules.push("- Use `HTTPException` for error responses with proper status codes");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (a.stacks.includes("django")) {
|
|
174
|
+
rules.push("- Follow Django conventions: models → views → serializers → urls");
|
|
175
|
+
rules.push("- Use Django ORM for all database operations — no raw SQL unless performance-critical");
|
|
176
|
+
rules.push("- Class-based views for CRUD, function-based for custom logic");
|
|
177
|
+
rules.push("- All settings via `django.conf.settings` — never `os.environ` directly");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (a.stacks.includes("springboot")) {
|
|
181
|
+
rules.push("- Follow layered architecture: Controller → Service → Repository");
|
|
182
|
+
rules.push("- Use constructor injection — never field injection with `@Autowired`");
|
|
183
|
+
rules.push("- All REST controllers return `ResponseEntity<T>`");
|
|
184
|
+
rules.push("- Use `@Valid` and Jakarta Bean Validation for input validation");
|
|
185
|
+
rules.push("- Use DTOs for API boundaries — never expose JPA entities directly");
|
|
186
|
+
rules.push("- `@Transactional` at service layer, not controller layer");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (a.stacks.includes("go")) {
|
|
190
|
+
rules.push("- Follow standard Go project layout: `cmd/`, `internal/`, `pkg/`");
|
|
191
|
+
rules.push("- Errors are values — always check and propagate errors, never ignore");
|
|
192
|
+
rules.push("- Use `context.Context` as first parameter for cancellation and deadlines");
|
|
193
|
+
rules.push("- Interfaces should be small (1-3 methods) and defined at point of use");
|
|
194
|
+
rules.push("- Use `go vet`, `staticcheck`, and `golangci-lint` before committing");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (a.stacks.includes("rust")) {
|
|
198
|
+
rules.push("- Use `Result<T, E>` for fallible operations — avoid `.unwrap()` in production code");
|
|
199
|
+
rules.push("- Prefer `&str` over `String` in function parameters where ownership isn't needed");
|
|
200
|
+
rules.push("- Use `thiserror` for library errors, `anyhow` for application errors");
|
|
201
|
+
rules.push("- Run `cargo clippy` and `cargo fmt` before committing");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ── API-specific rules ────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
if (a.apiStyle === "trpc") {
|
|
207
|
+
rules.push("- Define all API routes as tRPC procedures with full input/output validation");
|
|
208
|
+
rules.push("- Share types between client and server via the tRPC router type");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (a.apiStyle === "graphql") {
|
|
212
|
+
rules.push("- All GraphQL resolvers must handle errors gracefully (never throw unhandled)");
|
|
213
|
+
rules.push("- Use DataLoader pattern to prevent N+1 query issues");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ── General rules ─────────────────────────────────────────────
|
|
217
|
+
|
|
218
|
+
if (a.usesTypeScript) {
|
|
219
|
+
rules.push("- No use of `any` type — use `unknown` with type narrowing or proper generics");
|
|
220
|
+
rules.push("- Prefer `interface` for object shapes, `type` for unions and intersections");
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
rules.push("- Never store secrets in code, config files, or version control");
|
|
224
|
+
rules.push("- All external data (user input, API responses, env vars) must be validated before use");
|
|
225
|
+
|
|
226
|
+
if (a.isMonorepo) {
|
|
227
|
+
rules.push("- Each package has its own `package.json`, `tsconfig.json`, and tests");
|
|
228
|
+
rules.push("- Shared code goes in a `packages/shared` or `packages/common` package");
|
|
229
|
+
rules.push("- Apps depend on packages; packages NEVER depend on apps");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return rules.join("\n") + "\n";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function generateBuildSection(a: ProjectAnalysis): string {
|
|
236
|
+
const lines = ["## Build & Test"];
|
|
237
|
+
const pm = a.packageManager;
|
|
238
|
+
const run = pm === "yarn" ? "yarn" : pm === "pnpm" ? "pnpm" : pm === "bun" ? "bun" : "npm run";
|
|
239
|
+
|
|
240
|
+
// Build commands — prefer real detected commands
|
|
241
|
+
if (Object.keys(a.buildCommands).length > 0) {
|
|
242
|
+
for (const [key, value] of Object.entries(a.buildCommands)) {
|
|
243
|
+
if (key === "build") {
|
|
244
|
+
lines.push(`- Build: \`${run} build\` (runs: \`${value}\`)`);
|
|
245
|
+
} else if (key === "dev") {
|
|
246
|
+
lines.push(`- Dev: \`${run} dev\` (runs: \`${value}\`)`);
|
|
247
|
+
} else {
|
|
248
|
+
lines.push(`- ${key}: \`${run} ${key}\``);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
// Fallback to language-specific defaults
|
|
253
|
+
if (a.language === "typescript" || a.language === "javascript") {
|
|
254
|
+
lines.push(`- Build: \`${run} build\``);
|
|
255
|
+
lines.push(`- Dev: \`${run} dev\``);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Test commands
|
|
260
|
+
if (Object.keys(a.testCommands).length > 0) {
|
|
261
|
+
for (const [key, value] of Object.entries(a.testCommands)) {
|
|
262
|
+
if (key === "test") {
|
|
263
|
+
lines.push(`- Test: \`${run} test\` (runs: \`${value}\`)`);
|
|
264
|
+
} else {
|
|
265
|
+
lines.push(`- ${key}: \`${run} ${key}\``);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} else if (a.testFramework) {
|
|
269
|
+
if (a.language === "python") {
|
|
270
|
+
lines.push("- Test: `pytest`");
|
|
271
|
+
} else {
|
|
272
|
+
lines.push(`- Test: \`${run} test\``);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Lint/format
|
|
277
|
+
if (a.linter) {
|
|
278
|
+
if (a.language === "typescript" || a.language === "javascript") {
|
|
279
|
+
lines.push(`- Lint: \`${run} lint\``);
|
|
280
|
+
lines.push("- Type check: `npx tsc --noEmit`");
|
|
281
|
+
} else if (a.language === "python") {
|
|
282
|
+
if (a.linter === "Ruff") {
|
|
283
|
+
lines.push("- Lint: `ruff check .`");
|
|
284
|
+
lines.push("- Format: `ruff format .`");
|
|
285
|
+
}
|
|
286
|
+
lines.push("- Type check: `mypy .`");
|
|
287
|
+
} else if (a.language === "go") {
|
|
288
|
+
lines.push("- Lint: `golangci-lint run`");
|
|
289
|
+
lines.push("- Format: `gofmt -w .`");
|
|
290
|
+
} else if (a.language === "rust") {
|
|
291
|
+
lines.push("- Lint: `cargo clippy`");
|
|
292
|
+
lines.push("- Format: `cargo fmt`");
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return lines.join("\n") + "\n";
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function generateFileStructure(a: ProjectAnalysis): string {
|
|
300
|
+
const lines = ["## File Structure"];
|
|
301
|
+
|
|
302
|
+
// Use detected source dirs to build an accurate picture
|
|
303
|
+
const dirDescriptions: Record<string, string> = {
|
|
304
|
+
src: "Source code",
|
|
305
|
+
app: a.stacks.includes("nextjs") ? "Pages and API routes (App Router)" : "Application code",
|
|
306
|
+
lib: "Shared libraries and utilities",
|
|
307
|
+
pages: "Page components / routes",
|
|
308
|
+
components: "Reusable UI components",
|
|
309
|
+
api: "API routes and handlers",
|
|
310
|
+
server: "Server-side code",
|
|
311
|
+
client: "Client-side code",
|
|
312
|
+
packages: "Monorepo packages",
|
|
313
|
+
apps: "Monorepo applications",
|
|
314
|
+
tests: "Test files",
|
|
315
|
+
test: "Test files",
|
|
316
|
+
__tests__: "Test files",
|
|
317
|
+
spec: "Test specifications",
|
|
318
|
+
services: "Business logic services",
|
|
319
|
+
models: "Data models",
|
|
320
|
+
hooks: "Custom React hooks",
|
|
321
|
+
utils: "Utility functions",
|
|
322
|
+
types: "TypeScript type definitions",
|
|
323
|
+
config: "Configuration files",
|
|
324
|
+
public: "Static assets",
|
|
325
|
+
prisma: "Prisma schema and migrations",
|
|
326
|
+
migrations: "Database migrations",
|
|
327
|
+
middleware: "Middleware functions",
|
|
328
|
+
styles: "Stylesheets",
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
for (const dir of a.sourceDirs) {
|
|
332
|
+
const desc = dirDescriptions[dir] || dir;
|
|
333
|
+
lines.push(`- \`${dir}/\` — ${desc}`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return lines.join("\n") + "\n";
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function generateCodeConventions(a: ProjectAnalysis): string {
|
|
340
|
+
const rules: string[] = ["## Code Conventions"];
|
|
341
|
+
|
|
342
|
+
if (a.usesTypeScript) {
|
|
343
|
+
rules.push("- TypeScript strict mode with no `any` types");
|
|
344
|
+
rules.push("- Prefer named exports over default exports");
|
|
345
|
+
rules.push("- Interface names: `PascalCase` (no `I` prefix)");
|
|
346
|
+
rules.push("- Constants: `UPPER_SNAKE_CASE`");
|
|
347
|
+
rules.push("- Zod schemas for runtime validation of external data");
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (a.language === "python") {
|
|
351
|
+
rules.push("- Type hints on all function signatures");
|
|
352
|
+
rules.push("- Docstrings on all public functions (Google style)");
|
|
353
|
+
rules.push("- Use `from __future__ import annotations` for modern type syntax");
|
|
354
|
+
rules.push("- Pydantic models for all external data validation");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (a.language === "go") {
|
|
358
|
+
rules.push("- Export only what's needed — keep interfaces small");
|
|
359
|
+
rules.push("- Comments on all exported functions (godoc format)");
|
|
360
|
+
rules.push("- Table-driven tests as default test pattern");
|
|
361
|
+
rules.push("- No package-level `init()` unless absolutely necessary");
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (a.language === "rust") {
|
|
365
|
+
rules.push("- Use `clippy::pedantic` lint level for new code");
|
|
366
|
+
rules.push("- Document all public items with `///` doc comments");
|
|
367
|
+
rules.push("- Prefer `impl Trait` over `dyn Trait` where possible");
|
|
368
|
+
rules.push("- Use `#[must_use]` on functions returning important values");
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (a.language === "java") {
|
|
372
|
+
rules.push("- Use records for DTOs where applicable (Java 16+)");
|
|
373
|
+
rules.push("- Use `Optional<T>` return types for nullable queries");
|
|
374
|
+
rules.push("- Log with SLF4J (`@Slf4j` annotation)");
|
|
375
|
+
rules.push("- Never catch generic `Exception` — catch specific types");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (a.testFramework) {
|
|
379
|
+
rules.push(`- Test files colocated with source or in dedicated test directories`);
|
|
380
|
+
rules.push("- Test names describe the scenario and expected outcome");
|
|
381
|
+
rules.push("- Arrange-Act-Assert pattern for all unit tests");
|
|
382
|
+
rules.push("- Mock external dependencies — never make real API calls in unit tests");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (a.cssFramework === "Tailwind CSS") {
|
|
386
|
+
rules.push("- Use Tailwind utility classes — no custom CSS unless absolutely necessary");
|
|
387
|
+
rules.push("- Extract repeated class combinations into components, not `@apply`");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return rules.join("\n") + "\n";
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function generateDatabaseSection(a: ProjectAnalysis): string {
|
|
394
|
+
const lines = ["## Database"];
|
|
395
|
+
|
|
396
|
+
if (a.database === "Prisma") {
|
|
397
|
+
lines.push("- Schema defined in `prisma/schema.prisma`");
|
|
398
|
+
lines.push("- Run `npx prisma generate` after schema changes");
|
|
399
|
+
lines.push("- Run `npx prisma db push` for dev, `npx prisma migrate deploy` for production");
|
|
400
|
+
lines.push("- Never commit `.env` files containing `DATABASE_URL`");
|
|
401
|
+
lines.push("- Use Prisma Client for all database operations — no raw SQL unless performance-critical");
|
|
402
|
+
} else if (a.database === "Drizzle") {
|
|
403
|
+
lines.push("- Schema defined in `src/db/schema.ts`");
|
|
404
|
+
lines.push("- Run `npx drizzle-kit generate` for migrations");
|
|
405
|
+
lines.push("- Run `npx drizzle-kit push` to sync schema");
|
|
406
|
+
} else if (a.database === "SQLAlchemy") {
|
|
407
|
+
lines.push("- Models defined in `app/models/`");
|
|
408
|
+
lines.push("- Use Alembic for all schema migrations: `alembic revision --autogenerate`");
|
|
409
|
+
lines.push("- Always use async session for database operations");
|
|
410
|
+
lines.push("- Never commit database credentials");
|
|
411
|
+
} else if (a.database === "Spring Data JPA") {
|
|
412
|
+
lines.push("- JPA entities in `src/main/java/.../model/`");
|
|
413
|
+
lines.push("- Use Spring Data repositories — no manual query implementations unless needed");
|
|
414
|
+
lines.push("- Flyway migrations in `src/main/resources/db/migration/`");
|
|
415
|
+
lines.push("- Use `@Transactional` at service layer");
|
|
416
|
+
} else if (a.database) {
|
|
417
|
+
lines.push(`- Using ${a.database} for data access`);
|
|
418
|
+
lines.push("- Never commit database credentials or connection strings");
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return lines.join("\n") + "\n";
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function generateEnvSection(a: ProjectAnalysis): string {
|
|
425
|
+
const lines = ["## Environment Variables"];
|
|
426
|
+
lines.push(`Required environment variables (see \`.env.example\`):`);
|
|
427
|
+
for (const name of a.envVarNames) {
|
|
428
|
+
lines.push(`- \`${name}\``);
|
|
429
|
+
}
|
|
430
|
+
lines.push("");
|
|
431
|
+
lines.push("Never commit `.env` files. Use `.env.example` as a template.");
|
|
432
|
+
return lines.join("\n") + "\n";
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function generateComplianceSection(standards: string[]): string {
|
|
436
|
+
const lines = ["## Compliance Requirements"];
|
|
437
|
+
|
|
438
|
+
for (const standard of standards) {
|
|
439
|
+
switch (standard) {
|
|
440
|
+
case "hipaa":
|
|
441
|
+
lines.push("");
|
|
442
|
+
lines.push("### HIPAA");
|
|
443
|
+
lines.push("- All PHI must be encrypted at rest (AES-256) and in transit (TLS 1.2+)");
|
|
444
|
+
lines.push("- Never log PHI in application logs, console output, or error messages");
|
|
445
|
+
lines.push("- Access to PHI requires authentication and authorization checks");
|
|
446
|
+
lines.push("- All PHI access must be logged for audit purposes");
|
|
447
|
+
lines.push("- Use de-identified data for development and testing");
|
|
448
|
+
lines.push("- Data classification: PHI includes patient names, SSN, medical records, insurance IDs, dates of service");
|
|
449
|
+
break;
|
|
450
|
+
case "soc2":
|
|
451
|
+
lines.push("");
|
|
452
|
+
lines.push("### SOC2");
|
|
453
|
+
lines.push("- All changes require code review before merge");
|
|
454
|
+
lines.push("- Access follows principle of least privilege");
|
|
455
|
+
lines.push("- Audit logging enabled for all state-changing operations");
|
|
456
|
+
lines.push("- Encryption required for all sensitive data");
|
|
457
|
+
lines.push("- Regular dependency vulnerability scanning required");
|
|
458
|
+
lines.push("- Incident response procedures documented and tested");
|
|
459
|
+
break;
|
|
460
|
+
case "pci-dss":
|
|
461
|
+
lines.push("");
|
|
462
|
+
lines.push("### PCI-DSS");
|
|
463
|
+
lines.push("- Never store full card numbers in code, logs, or comments");
|
|
464
|
+
lines.push("- Use tokenization for all payment card data references");
|
|
465
|
+
lines.push("- All cardholder data must be encrypted in transit and at rest");
|
|
466
|
+
lines.push("- Follow OWASP secure coding guidelines");
|
|
467
|
+
lines.push("- Quarterly vulnerability scans required");
|
|
468
|
+
break;
|
|
469
|
+
case "sox":
|
|
470
|
+
lines.push("");
|
|
471
|
+
lines.push("### SOX");
|
|
472
|
+
lines.push("- All changes to financial calculations require dual review");
|
|
473
|
+
lines.push("- Complete audit trail for all data modifications");
|
|
474
|
+
lines.push("- Separation of duties in deployment pipeline");
|
|
475
|
+
lines.push("- Change management documentation required for all releases");
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return lines.join("\n") + "\n";
|
|
481
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI configuration generator.
|
|
3
|
+
*
|
|
4
|
+
* OpenAI's Codex CLI uses an AGENTS.md file at the project root,
|
|
5
|
+
* which is functionally equivalent to CLAUDE.md.
|
|
6
|
+
*
|
|
7
|
+
* Codex does NOT support skills, agents, or hooks - just AGENTS.md.
|
|
8
|
+
*/
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { atomicWrite } from "./file-ops.js";
|
|
11
|
+
import type { GeneratedFile } from "../types.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generates Codex CLI configuration (AGENTS.md) from CLAUDE.md content.
|
|
15
|
+
*/
|
|
16
|
+
export async function generateCodexConfig(
|
|
17
|
+
projectPath: string,
|
|
18
|
+
projectName: string,
|
|
19
|
+
claudeMdContent: string
|
|
20
|
+
): Promise<GeneratedFile[]> {
|
|
21
|
+
const files: GeneratedFile[] = [];
|
|
22
|
+
|
|
23
|
+
// Codex uses AGENTS.md with a specific header format
|
|
24
|
+
const header = `# ${projectName} — Agent Instructions
|
|
25
|
+
|
|
26
|
+
> Generated by Rebar (https://github.com/RCOLKITT/rebar-mcp)
|
|
27
|
+
> These rules apply to all AI coding agents working in this repository.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const agentsMdContent = header + claudeMdContent;
|
|
34
|
+
const agentsMdPath = path.join(projectPath, "AGENTS.md");
|
|
35
|
+
await atomicWrite(agentsMdPath, agentsMdContent);
|
|
36
|
+
|
|
37
|
+
files.push({
|
|
38
|
+
path: "AGENTS.md",
|
|
39
|
+
content: agentsMdContent,
|
|
40
|
+
description: "Codex CLI agent instructions",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return files;
|
|
44
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor configuration generator.
|
|
3
|
+
*
|
|
4
|
+
* Cursor uses .cursor/rules/*.md files that are functionally equivalent
|
|
5
|
+
* to Claude Code's skills. The format is different:
|
|
6
|
+
* - Uses YAML frontmatter with 'description' and 'globs' fields
|
|
7
|
+
* - Uses 'alwaysApply: true' for project-wide rules
|
|
8
|
+
*/
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { ensureDir, atomicWrite } from "./file-ops.js";
|
|
11
|
+
import type { GeneratedFile } from "../types.js";
|
|
12
|
+
|
|
13
|
+
export interface CursorRuleTemplate {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
content: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Converts CLAUDE.md content to Cursor project-rules.md format.
|
|
21
|
+
*/
|
|
22
|
+
function convertToProjectRules(claudeMdContent: string, projectName: string): string {
|
|
23
|
+
// Cursor rules use a different frontmatter format
|
|
24
|
+
const frontmatter = `---
|
|
25
|
+
description: Project rules and coding standards for ${projectName}
|
|
26
|
+
globs:
|
|
27
|
+
alwaysApply: true
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
> Note: Cursor does not support enforcement hooks. The guardrails below rely on
|
|
31
|
+
> you following these rules. For automated enforcement, use Rebar with Claude Code
|
|
32
|
+
> or run \`npx rebar-mcp audit\` in your CI pipeline.
|
|
33
|
+
|
|
34
|
+
`;
|
|
35
|
+
return frontmatter + claudeMdContent;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Converts a Claude Code skill to Cursor rule format.
|
|
40
|
+
*/
|
|
41
|
+
function convertSkillToCursorRule(skill: CursorRuleTemplate): string {
|
|
42
|
+
const frontmatter = `---
|
|
43
|
+
description: ${skill.description}
|
|
44
|
+
globs:
|
|
45
|
+
alwaysApply: false
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
`;
|
|
49
|
+
return frontmatter + skill.content;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Generates Cursor configuration files from CLAUDE.md and skills.
|
|
54
|
+
*/
|
|
55
|
+
export async function generateCursorConfig(
|
|
56
|
+
projectPath: string,
|
|
57
|
+
projectName: string,
|
|
58
|
+
claudeMdContent: string,
|
|
59
|
+
skills: CursorRuleTemplate[]
|
|
60
|
+
): Promise<GeneratedFile[]> {
|
|
61
|
+
const files: GeneratedFile[] = [];
|
|
62
|
+
const rulesDir = path.join(projectPath, ".cursor", "rules");
|
|
63
|
+
|
|
64
|
+
await ensureDir(rulesDir);
|
|
65
|
+
|
|
66
|
+
// Generate project-rules.md from CLAUDE.md
|
|
67
|
+
const projectRulesContent = convertToProjectRules(claudeMdContent, projectName);
|
|
68
|
+
const projectRulesPath = path.join(rulesDir, "project-rules.md");
|
|
69
|
+
await atomicWrite(projectRulesPath, projectRulesContent);
|
|
70
|
+
files.push({
|
|
71
|
+
path: ".cursor/rules/project-rules.md",
|
|
72
|
+
content: projectRulesContent,
|
|
73
|
+
description: "Main project rules (from CLAUDE.md)",
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Convert skills to Cursor rules
|
|
77
|
+
for (const skill of skills) {
|
|
78
|
+
const ruleContent = convertSkillToCursorRule(skill);
|
|
79
|
+
const rulePath = path.join(rulesDir, `${skill.name}.md`);
|
|
80
|
+
await atomicWrite(rulePath, ruleContent);
|
|
81
|
+
files.push({
|
|
82
|
+
path: `.cursor/rules/${skill.name}.md`,
|
|
83
|
+
content: ruleContent,
|
|
84
|
+
description: `${skill.name} rule`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return files;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Default skills to convert to Cursor rules.
|
|
93
|
+
*/
|
|
94
|
+
export function getDefaultCursorSkills(): CursorRuleTemplate[] {
|
|
95
|
+
return [
|
|
96
|
+
{
|
|
97
|
+
name: "code-review",
|
|
98
|
+
description: "Code review guidelines for quality and security",
|
|
99
|
+
content: `# Code Review
|
|
100
|
+
|
|
101
|
+
When reviewing code changes:
|
|
102
|
+
|
|
103
|
+
1. **Security First**: Check for injection vulnerabilities, auth issues, data exposure
|
|
104
|
+
2. **Error Handling**: Ensure errors are properly caught and handled
|
|
105
|
+
3. **Type Safety**: Verify types are correct and 'any' is avoided
|
|
106
|
+
4. **Performance**: Watch for N+1 queries, memory leaks, unnecessary re-renders
|
|
107
|
+
5. **Tests**: Ensure tests exist and pass for changed code
|
|
108
|
+
`,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "test-writer",
|
|
112
|
+
description: "Test writing guidelines",
|
|
113
|
+
content: `# Test Writing
|
|
114
|
+
|
|
115
|
+
When writing tests:
|
|
116
|
+
|
|
117
|
+
1. Test behavior, not implementation
|
|
118
|
+
2. Use descriptive test names
|
|
119
|
+
3. Follow the Arrange-Act-Assert pattern
|
|
120
|
+
4. Mock external dependencies
|
|
121
|
+
5. Aim for edge cases, not just happy paths
|
|
122
|
+
`,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "security-scan",
|
|
126
|
+
description: "Security scanning guidelines",
|
|
127
|
+
content: `# Security Scan
|
|
128
|
+
|
|
129
|
+
Check for:
|
|
130
|
+
|
|
131
|
+
1. Hardcoded secrets (API keys, passwords)
|
|
132
|
+
2. SQL injection vulnerabilities
|
|
133
|
+
3. XSS in rendered HTML
|
|
134
|
+
4. Insecure direct object references
|
|
135
|
+
5. Missing authentication/authorization
|
|
136
|
+
`,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "documentation",
|
|
140
|
+
description: "Documentation guidelines",
|
|
141
|
+
content: `# Documentation
|
|
142
|
+
|
|
143
|
+
When documenting:
|
|
144
|
+
|
|
145
|
+
1. Document the WHY, not the WHAT
|
|
146
|
+
2. Keep documentation close to code
|
|
147
|
+
3. Update docs when changing code
|
|
148
|
+
4. Use examples liberally
|
|
149
|
+
5. Document public APIs thoroughly
|
|
150
|
+
`,
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
}
|