ccraft 1.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.
Files changed (40) hide show
  1. package/bin/claude-craft.js +85 -0
  2. package/package.json +39 -0
  3. package/src/commands/auth.js +43 -0
  4. package/src/commands/create.js +543 -0
  5. package/src/commands/install.js +480 -0
  6. package/src/commands/logout.js +24 -0
  7. package/src/commands/update.js +339 -0
  8. package/src/constants.js +299 -0
  9. package/src/generators/directories.js +30 -0
  10. package/src/generators/metadata.js +57 -0
  11. package/src/generators/security.js +39 -0
  12. package/src/prompts/gather.js +308 -0
  13. package/src/ui/brand.js +62 -0
  14. package/src/ui/cards.js +179 -0
  15. package/src/ui/format.js +55 -0
  16. package/src/ui/phase-header.js +20 -0
  17. package/src/ui/prompts.js +56 -0
  18. package/src/ui/tables.js +89 -0
  19. package/src/ui/tasks.js +258 -0
  20. package/src/ui/theme.js +83 -0
  21. package/src/utils/analysis-cache.js +519 -0
  22. package/src/utils/api-client.js +253 -0
  23. package/src/utils/api-file-writer.js +197 -0
  24. package/src/utils/bootstrap-runner.js +148 -0
  25. package/src/utils/claude-analyzer.js +255 -0
  26. package/src/utils/claude-optimizer.js +341 -0
  27. package/src/utils/claude-rewriter.js +553 -0
  28. package/src/utils/claude-scorer.js +101 -0
  29. package/src/utils/description-analyzer.js +116 -0
  30. package/src/utils/detect-project.js +1276 -0
  31. package/src/utils/existing-setup.js +341 -0
  32. package/src/utils/file-writer.js +64 -0
  33. package/src/utils/json-extract.js +56 -0
  34. package/src/utils/logger.js +27 -0
  35. package/src/utils/mcp-setup.js +461 -0
  36. package/src/utils/preflight.js +112 -0
  37. package/src/utils/prompt-api-key.js +59 -0
  38. package/src/utils/run-claude.js +152 -0
  39. package/src/utils/security.js +82 -0
  40. package/src/utils/toolkit-rule-generator.js +364 -0
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Update command — re-analyzes the project, compares to the last install snapshot,
3
+ * calls /api/update to get delta components, and installs only what's new.
4
+ *
5
+ * Flow:
6
+ * 1. Load stored user profile + analysis from .claude/.claude-craft/
7
+ * 2. Re-run project analysis (detectProject + analyzeWithClaude)
8
+ * 3. Extract installed relative paths from manifest
9
+ * 4. Call /api/update — server returns only new/unlocked components
10
+ * 5. Show change summary + new component counts
11
+ * 6. Confirm, write files, merge manifest
12
+ */
13
+ import { resolve, sep } from 'path';
14
+ import chalk from 'chalk';
15
+ import ora from 'ora';
16
+ import { detectProject } from '../utils/detect-project.js';
17
+ import { analyzeWithClaude } from '../utils/claude-analyzer.js';
18
+ import {
19
+ readUserProfile,
20
+ readPermanentAnalysis,
21
+ readInstalledManifest,
22
+ mergePermanentManifest,
23
+ } from '../utils/analysis-cache.js';
24
+ import { callUpdate, ApiError } from '../utils/api-client.js';
25
+ import { runPreflight } from '../utils/preflight.js';
26
+ import { writeApiFiles, buildFileList } from '../utils/api-file-writer.js';
27
+ import { colors, icons } from '../ui/theme.js';
28
+ import { dotPad } from '../ui/format.js';
29
+ import { renderFileResults } from '../ui/tables.js';
30
+ import { themedConfirm } from '../ui/prompts.js';
31
+ import * as logger from '../utils/logger.js';
32
+
33
+ // ── Helpers ──────────────────────────────────────────────────────────────────
34
+
35
+ /**
36
+ * Extract normalized relative paths from the installed manifest.
37
+ * Strips the targetDir prefix so paths are relative (e.g. ".claude/agents/orchestrator.md").
38
+ */
39
+ function extractRelativePaths(manifest, targetDir) {
40
+ if (!manifest?.files) return [];
41
+
42
+ const prefix = targetDir.endsWith(sep) ? targetDir : targetDir + sep;
43
+ // Also handle forward-slash variant on Windows
44
+ const prefixFwd = prefix.replace(/\\/g, '/');
45
+
46
+ return manifest.files
47
+ .map((f) => {
48
+ let p = (f.relativePath || '').replace(/\\/g, '/');
49
+ if (p.startsWith(prefixFwd)) p = p.slice(prefixFwd.length);
50
+ return p;
51
+ })
52
+ .filter(Boolean);
53
+ }
54
+
55
+ /**
56
+ * Render the detected stack changes to the console.
57
+ */
58
+ function renderChanges(changes, currentAnalysis) {
59
+ const { addedFrameworks, removedFrameworks, addedLanguages, addedSubprojects,
60
+ testFrameworkChanged, packageManagerChanged, hasChanges } = changes;
61
+
62
+ if (!hasChanges) {
63
+ console.log(chalk.dim(' No stack changes detected since last install.'));
64
+ return;
65
+ }
66
+
67
+ console.log(chalk.bold(' Stack changes'));
68
+ console.log();
69
+
70
+ if (addedFrameworks.length > 0) {
71
+ for (const fw of addedFrameworks) {
72
+ console.log(` ${icons.plus} ${colors.success(fw)} ${chalk.dim('(new framework)')}`);
73
+ }
74
+ }
75
+ if (removedFrameworks.length > 0) {
76
+ for (const fw of removedFrameworks) {
77
+ console.log(` ${chalk.dim('─')} ${chalk.dim(fw)} ${chalk.dim('(removed)')}`);
78
+ }
79
+ }
80
+ if (addedLanguages.length > 0) {
81
+ for (const lang of addedLanguages) {
82
+ console.log(` ${icons.plus} ${colors.success(lang)} ${chalk.dim('(new language)')}`);
83
+ }
84
+ }
85
+ if (addedSubprojects.length > 0) {
86
+ for (const sub of addedSubprojects) {
87
+ console.log(` ${icons.plus} ${colors.success(sub)} ${chalk.dim('(new subproject)')}`);
88
+ }
89
+ }
90
+ if (testFrameworkChanged && currentAnalysis.testFramework) {
91
+ console.log(
92
+ ` ${icons.plus} ${colors.success(currentAnalysis.testFramework)} ${chalk.dim('(test framework detected)')}`,
93
+ );
94
+ }
95
+ if (packageManagerChanged) {
96
+ console.log(
97
+ ` ${icons.tilde} ${colors.warning('package manager changed')} ${chalk.dim(`→ ${currentAnalysis.packageManager}`)}`,
98
+ );
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Render the delta component counts.
104
+ */
105
+ function renderDeltaSummary(delta) {
106
+ const total = Object.values(delta).reduce((s, n) => s + n, 0);
107
+ if (total === 0) {
108
+ console.log(chalk.dim(' No new components to install.'));
109
+ return false;
110
+ }
111
+
112
+ console.log(chalk.bold(` New components: ${colors.success(String(total))}`));
113
+ const entries = Object.entries(delta).filter(([, n]) => n > 0);
114
+ for (const [cat, count] of entries) {
115
+ console.log(chalk.dim(` ${dotPad(cat, colors.success(String(count)))}`));
116
+ }
117
+ return true;
118
+ }
119
+
120
+ // ── Main command ─────────────────────────────────────────────────────────────
121
+
122
+ /**
123
+ * @param {object} options - { dir, yes }
124
+ */
125
+ export async function runUpdate(options = {}) {
126
+ try {
127
+ const targetDir = resolve(options.dir || process.cwd());
128
+
129
+ // ── Pre-flight checks (Claude Code + project marker + API key + server)
130
+ await runPreflight({
131
+ interactive: !options.yes,
132
+ requireClaude: true,
133
+ requireCraftProject: true,
134
+ targetDir,
135
+ });
136
+
137
+ // ── Guard: must have a previous install ───────────────────────────
138
+ const storedProfile = readUserProfile(targetDir);
139
+ const previousAnalysis = readPermanentAnalysis(targetDir);
140
+ const installedManifest = readInstalledManifest(targetDir);
141
+
142
+ if (!storedProfile) {
143
+ logger.error(
144
+ 'No stored user profile found. Re-run: ' + chalk.bold('claude-craft install') +
145
+ ' to rebuild the profile cache.',
146
+ );
147
+ process.exit(1);
148
+ }
149
+
150
+ if (!previousAnalysis) {
151
+ logger.error(
152
+ 'No stored project analysis found. Re-run: ' + chalk.bold('claude-craft install') +
153
+ ' to rebuild the analysis cache.',
154
+ );
155
+ process.exit(1);
156
+ }
157
+
158
+ console.log(chalk.bold(' claude-craft update'));
159
+ console.log(chalk.dim(' Re-analyzing project and checking for new components...'));
160
+ console.log();
161
+
162
+ // ── Phase 1: Re-analyze project ───────────────────────────────────
163
+ let currentProjectInfo;
164
+ let fsDetected;
165
+
166
+ const spinner = ora('Analyzing project...').start();
167
+ try {
168
+ fsDetected = await detectProject(targetDir);
169
+
170
+ let claudeAnalysis = null;
171
+ try {
172
+ const result = await analyzeWithClaude(targetDir);
173
+ claudeAnalysis = result.analysis;
174
+ } catch {
175
+ // Claude unavailable — fall back to filesystem detection only
176
+ }
177
+
178
+ if (claudeAnalysis) {
179
+ currentProjectInfo = {
180
+ name: claudeAnalysis.name || fsDetected.name || previousAnalysis.name || 'my-project',
181
+ description: claudeAnalysis.description || fsDetected.description || '',
182
+ projectType: claudeAnalysis.projectType || fsDetected.projectType || 'monolith',
183
+ languages: claudeAnalysis.languages?.length ? claudeAnalysis.languages : fsDetected.languages,
184
+ frameworks: claudeAnalysis.frameworks?.length ? claudeAnalysis.frameworks : fsDetected.frameworks,
185
+ codeStyle: claudeAnalysis.codeStyle?.length ? claudeAnalysis.codeStyle : fsDetected.codeStyle,
186
+ cicd: claudeAnalysis.cicd?.length ? claudeAnalysis.cicd : fsDetected.cicd,
187
+ subprojects: claudeAnalysis.subprojects?.length ? claudeAnalysis.subprojects : fsDetected.subprojects,
188
+ architecture: claudeAnalysis.architecture || '',
189
+ buildCommands: claudeAnalysis.buildCommands || {},
190
+ complexity: claudeAnalysis.complexity ?? 0.5,
191
+ metrics: claudeAnalysis.metrics || null,
192
+ entryPoints: claudeAnalysis.entryPoints || [],
193
+ coreModules: claudeAnalysis.coreModules || [],
194
+ testFramework: claudeAnalysis.testFramework || '',
195
+ packageManager: claudeAnalysis.packageManager || fsDetected.packageManager || '',
196
+ languageDistribution: claudeAnalysis.languageDistribution || fsDetected.languageDistribution || null,
197
+ };
198
+ } else {
199
+ currentProjectInfo = {
200
+ name: fsDetected.name || previousAnalysis.name || 'my-project',
201
+ description: fsDetected.description || '',
202
+ projectType: fsDetected.projectType || 'monolith',
203
+ languages: fsDetected.languages?.length ? fsDetected.languages : previousAnalysis.languages,
204
+ frameworks: fsDetected.frameworks,
205
+ codeStyle: fsDetected.codeStyle,
206
+ cicd: fsDetected.cicd,
207
+ subprojects: fsDetected.subprojects,
208
+ architecture: '',
209
+ buildCommands: {},
210
+ complexity: 0.5,
211
+ metrics: null,
212
+ entryPoints: [],
213
+ coreModules: [],
214
+ testFramework: '',
215
+ packageManager: fsDetected.packageManager || '',
216
+ languageDistribution: fsDetected.languageDistribution || null,
217
+ };
218
+ }
219
+
220
+ spinner.succeed('Project analyzed.');
221
+ } catch (err) {
222
+ spinner.fail('Analysis failed: ' + err.message);
223
+ process.exit(1);
224
+ }
225
+
226
+ // ── Phase 2: Build installed path list ────────────────────────────
227
+ const installedRelativePaths = extractRelativePaths(installedManifest, targetDir);
228
+
229
+ // ── Phase 3: Call /api/update ─────────────────────────────────────
230
+ const spinner2 = ora('Checking for new components...').start();
231
+ let updateResponse;
232
+ try {
233
+ updateResponse = await callUpdate(
234
+ storedProfile,
235
+ currentProjectInfo,
236
+ previousAnalysis,
237
+ installedRelativePaths,
238
+ );
239
+ spinner2.succeed('Server responded.');
240
+ } catch (err) {
241
+ spinner2.fail('Server request failed.');
242
+ if (err instanceof ApiError) {
243
+ logger.error(err.message);
244
+ process.exit(1);
245
+ }
246
+ throw err;
247
+ }
248
+
249
+ const { changes, summary } = updateResponse;
250
+
251
+ // ── Display results ───────────────────────────────────────────────
252
+ console.log();
253
+ renderChanges(changes, currentProjectInfo);
254
+ console.log();
255
+
256
+ const hasNewComponents = renderDeltaSummary(summary?.delta || {});
257
+
258
+ if (!changes.hasChanges && !hasNewComponents) {
259
+ console.log();
260
+ logger.success('Already up to date. Nothing to install.');
261
+ console.log();
262
+ process.exit(0);
263
+ }
264
+
265
+ if (!hasNewComponents) {
266
+ console.log();
267
+ logger.success('Stack changes noted — no new components needed.');
268
+ console.log();
269
+ process.exit(0);
270
+ }
271
+
272
+ // ── Confirm + install ─────────────────────────────────────────────
273
+ console.log();
274
+
275
+ let proceed = true;
276
+ if (!options.yes) {
277
+ proceed = await themedConfirm({ message: 'Install new components?', default: true });
278
+ }
279
+
280
+ if (!proceed) {
281
+ console.log();
282
+ logger.info('Cancelled.');
283
+ process.exit(0);
284
+ }
285
+
286
+ // ── Write new files ───────────────────────────────────────────────
287
+ const filesToWrite = buildFileList(updateResponse, null);
288
+
289
+ if (filesToWrite.length === 0) {
290
+ console.log();
291
+ logger.success('No files to write. Already up to date.');
292
+ process.exit(0);
293
+ }
294
+
295
+ const writeSpinner = ora('Writing new components...').start();
296
+ let results;
297
+ try {
298
+ results = await writeApiFiles(filesToWrite, targetDir, {
299
+ force: true,
300
+ selectedMcpIds: [],
301
+ detected: { ...fsDetected, ...currentProjectInfo },
302
+ });
303
+ writeSpinner.succeed('Components installed.');
304
+ } catch (err) {
305
+ writeSpinner.fail('Write failed: ' + err.message);
306
+ throw err;
307
+ }
308
+
309
+ // ── Display written files ─────────────────────────────────────────
310
+ console.log();
311
+ renderFileResults(results);
312
+
313
+ // ── Update manifest ───────────────────────────────────────────────
314
+ try {
315
+ mergePermanentManifest(targetDir, results, filesToWrite);
316
+ } catch (err) {
317
+ logger.debug(`Manifest merge failed: ${err.message}`);
318
+ }
319
+
320
+ console.log();
321
+ logger.success('Done! New components installed.');
322
+ console.log();
323
+ } catch (err) {
324
+ if (
325
+ err &&
326
+ (err.name === 'ExitPromptError' ||
327
+ err.constructor?.name === 'ExitPromptError' ||
328
+ err.message?.includes('User force closed'))
329
+ ) {
330
+ console.log();
331
+ logger.info('Cancelled.');
332
+ process.exit(0);
333
+ }
334
+
335
+ console.log();
336
+ logger.error(err.message || String(err));
337
+ process.exit(1);
338
+ }
339
+ }
@@ -0,0 +1,299 @@
1
+ import { readFileSync } from 'fs';
2
+ import { fileURLToPath } from 'url';
3
+ import { dirname, join } from 'path';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
8
+
9
+ export const VERSION = pkg.version;
10
+ export const TOOL_NAME = 'claude-craft';
11
+
12
+ // ── Step 1: User roles & intents ──────────────────────────────────────
13
+
14
+ export const ROLES = [
15
+ {
16
+ name: 'Developer',
17
+ value: 'developer',
18
+ description: 'Build and ship software across the stack',
19
+ children: [
20
+ { name: 'Web', value: 'web', description: 'Frontend and backend development' },
21
+ { name: 'Mobile', value: 'mobile', description: 'iOS, Android, and cross-platform apps' },
22
+ { name: 'Game', value: 'game', description: 'Game engines, rendering, and gameplay' },
23
+ { name: 'Blockchain', value: 'blockchain', description: 'Smart contracts, DApps, and Web3' },
24
+ { name: 'Embedded', value: 'embedded', description: 'Firmware, IoT, and low-level systems' },
25
+ ],
26
+ },
27
+ { name: 'DevOps', value: 'devops', description: 'Infrastructure, CI/CD, and deployment pipelines' },
28
+ {
29
+ name: 'Data & Analytics',
30
+ value: 'data-analytics',
31
+ description: 'Data pipelines, analysis, ML, and visualization',
32
+ children: [
33
+ { name: 'Data Scientist', value: 'data-scientist', description: 'ML models, experiments, and research' },
34
+ { name: 'Data Engineer', value: 'data-engineer', description: 'Pipelines, ETL, and data infrastructure' },
35
+ { name: 'Data Analyst', value: 'data-analyst', description: 'Queries, dashboards, and reporting' },
36
+ ],
37
+ },
38
+ { name: 'Quality Assurance', value: 'qa', description: 'Testing strategy, automation, and quality gates' },
39
+ { name: 'Cybersecurity', value: 'cybersecurity', description: 'Security audits, vulnerability analysis, hardening' },
40
+ { name: 'Product & Design', value: 'product-design', description: 'Product specs, design systems, UX workflows' },
41
+ ];
42
+
43
+ export const ROLE_DISPLAY_NAMES = {
44
+ web: 'Web Developer',
45
+ mobile: 'Mobile Developer',
46
+ game: 'Game Developer',
47
+ blockchain: 'Blockchain Developer',
48
+ embedded: 'Embedded Developer',
49
+ devops: 'DevOps / Infrastructure',
50
+ 'data-scientist': 'Data Scientist',
51
+ 'data-engineer': 'Data Engineer',
52
+ 'data-analyst': 'Data Analyst',
53
+ qa: 'Quality Assurance',
54
+ cybersecurity: 'Cybersecurity',
55
+ 'product-design': 'Product & Design',
56
+ };
57
+
58
+ export const INTENTS = [
59
+ { name: 'Implementing new features', value: 'implementing', description: 'Build features from specs, tickets, or ideas' },
60
+ { name: 'Debugging & troubleshooting', value: 'debugging', description: 'Track down bugs, analyze stack traces, fix issues' },
61
+ { name: 'Refactoring & cleanup', value: 'refactoring', description: 'Improve code structure without changing behavior' },
62
+ { name: 'Writing documentation', value: 'documentation', description: 'READMEs, API docs, architecture decisions' },
63
+ { name: 'Testing & QA', value: 'testing', description: 'Unit, integration, and e2e tests' },
64
+ { name: 'Code review', value: 'reviewing', description: 'Review PRs, suggest improvements, catch issues' },
65
+ ];
66
+
67
+ // ── Source control platforms ─────────────────────────────────────────
68
+
69
+ export const SOURCE_CONTROLS = [
70
+ { name: 'GitHub', value: 'github', description: 'GitHub.com or GitHub Enterprise' },
71
+ { name: 'GitLab', value: 'gitlab', description: 'GitLab.com or self-hosted' },
72
+ { name: 'Bitbucket', value: 'bitbucket', description: 'Bitbucket Cloud or Data Center' },
73
+ { name: 'Azure DevOps', value: 'azure-devops', description: 'Azure Repos and Pipelines' },
74
+ { name: 'None / Git only', value: 'none', description: 'Local git without a hosting platform' },
75
+ ];
76
+
77
+ // ── Document & project management tools ─────────────────────────────
78
+
79
+ export const DOCUMENT_TOOLS = [
80
+ { name: 'None', value: 'none' },
81
+ { name: 'Notion', value: 'notion' },
82
+ { name: 'Linear', value: 'linear' },
83
+ { name: 'Google Docs', value: 'google-docs' },
84
+ { name: 'Confluence', value: 'confluence' },
85
+ { name: 'Jira', value: 'jira' },
86
+ { name: 'Azure DevOps', value: 'azure-devops' },
87
+ { name: 'ClickUp', value: 'clickup' },
88
+ { name: 'Asana', value: 'asana' },
89
+ { name: 'Shortcut', value: 'shortcut' },
90
+ { name: 'Monday.com', value: 'monday' },
91
+ { name: 'YouTrack', value: 'youtrack' },
92
+ { name: 'Trello', value: 'trello' },
93
+ { name: 'Todoist', value: 'todoist' },
94
+ { name: 'Plane', value: 'plane' },
95
+ { name: 'Other', value: 'other' },
96
+ ];
97
+
98
+ // ── Step 2: Project types ─────────────────────────────────────────────
99
+
100
+ export const PROJECT_TYPES = [
101
+ { name: 'Monorepo (multiple packages/apps)', value: 'monorepo' },
102
+ { name: 'Microservices', value: 'microservice' },
103
+ { name: 'Monolith', value: 'monolith' },
104
+ { name: 'Library / Package', value: 'library' },
105
+ { name: 'CLI Tool', value: 'cli' },
106
+ { name: 'Other / Unknown', value: 'other' },
107
+ ];
108
+
109
+ // ── Languages & Frameworks ────────────────────────────────────────────
110
+
111
+ export const SUPPORTED_LANGUAGES = [
112
+ 'JavaScript',
113
+ 'TypeScript',
114
+ 'Python',
115
+ 'Go',
116
+ 'Rust',
117
+ 'Java',
118
+ 'C#',
119
+ 'Ruby',
120
+ 'PHP',
121
+ 'Swift',
122
+ 'Kotlin',
123
+ 'Dart',
124
+ 'SQL',
125
+ 'Solidity',
126
+ 'C',
127
+ 'C++',
128
+ ];
129
+
130
+ export const SUPPORTED_FRAMEWORKS = [
131
+ // Web frameworks
132
+ 'Next.js',
133
+ 'React',
134
+ 'Vue',
135
+ 'Angular',
136
+ 'Express',
137
+ 'Fastify',
138
+ 'Django',
139
+ 'Flask',
140
+ 'FastAPI',
141
+ 'Gin',
142
+ 'Echo',
143
+ 'Actix',
144
+ 'Spring Boot',
145
+ 'ASP.NET Core',
146
+ 'Rails',
147
+ 'Laravel',
148
+ 'Tailwind CSS',
149
+ // Expanded web frameworks
150
+ 'SvelteKit',
151
+ 'Nuxt',
152
+ 'Astro',
153
+ 'Gatsby',
154
+ 'NestJS',
155
+ 'Remix',
156
+ 'Socket.io',
157
+ // Desktop / Mobile
158
+ 'Electron',
159
+ 'React Native',
160
+ 'Expo',
161
+ 'Tauri',
162
+ 'Flutter',
163
+ // Blockchain
164
+ 'Hardhat',
165
+ 'Foundry',
166
+ 'Web3',
167
+ // Data / AI
168
+ 'GraphQL',
169
+ 'LangChain',
170
+ 'OpenAI SDK',
171
+ 'PyTorch',
172
+ 'TensorFlow',
173
+ 'scikit-learn',
174
+ 'Streamlit',
175
+ 'Airflow',
176
+ 'Pandas',
177
+ 'Pydantic',
178
+ 'Hugging Face',
179
+ // Game
180
+ 'Phaser',
181
+ 'Three.js',
182
+ 'Unity',
183
+ 'Godot',
184
+ 'Babylon.js',
185
+ // ORM / DB
186
+ 'Prisma',
187
+ 'Drizzle',
188
+ // Go frameworks
189
+ 'Go API',
190
+ 'Cobra',
191
+ 'Fiber',
192
+ // Rust frameworks
193
+ 'Tokio',
194
+ 'Axum',
195
+ 'Warp',
196
+ 'Clap',
197
+ // Infrastructure
198
+ 'Terraform',
199
+ 'Serverless Framework',
200
+ // Static sites
201
+ 'Hugo',
202
+ 'Jekyll',
203
+ 'Docusaurus',
204
+ // Mobile / Desktop (extended)
205
+ 'Jetpack Compose',
206
+ '.NET MAUI',
207
+ // Data
208
+ 'dbt',
209
+ 'Dash',
210
+ // AI (extended)
211
+ 'LlamaIndex',
212
+ 'Vercel AI SDK',
213
+ // Testing
214
+ 'Playwright',
215
+ // Bot
216
+ 'Discord.js',
217
+ // .NET variants
218
+ 'Razor',
219
+ 'Blazor',
220
+ 'Graphene',
221
+ 'HotChocolate',
222
+ 'SignalR',
223
+ // CMS / E-commerce
224
+ 'WordPress',
225
+ 'Shopify',
226
+ // Other
227
+ 'Single-SPA',
228
+ 'CLI Framework',
229
+ 'Scrapy',
230
+ 'Browser Extension',
231
+ // C / C++ build systems
232
+ 'CMake',
233
+ 'Meson',
234
+ 'Bazel',
235
+ // C / C++ GUI
236
+ 'Qt',
237
+ 'GTK',
238
+ 'wxWidgets',
239
+ 'Dear ImGui',
240
+ // C / C++ multimedia / game
241
+ 'SDL',
242
+ 'SFML',
243
+ 'Unreal Engine',
244
+ // C / C++ web / networking
245
+ 'Boost',
246
+ 'Drogon',
247
+ 'Crow',
248
+ 'gRPC',
249
+ // C / C++ embedded / IoT
250
+ 'FreeRTOS',
251
+ 'ESP-IDF',
252
+ 'Zephyr',
253
+ // C / C++ ML / vision
254
+ 'OpenCV',
255
+ // C / C++ testing
256
+ 'Google Test',
257
+ 'Catch2',
258
+ ];
259
+
260
+ // ── Components (now auto-selected by scoring) ─────────────────────────
261
+
262
+ export const COMPONENTS = [
263
+ { name: 'CLAUDE.md', value: 'claude-md', checked: true },
264
+ { name: 'Agents (.claude/agents/)', value: 'agents', checked: true },
265
+ { name: 'Rules (.claude/rules/)', value: 'rules', checked: true },
266
+ { name: 'Hooks (.claude/settings.json)', value: 'hooks', checked: true },
267
+ { name: 'Skills (.claude/skills/)', value: 'skills', checked: true },
268
+ { name: 'Commands (.claude/commands/)', value: 'commands', checked: true },
269
+ { name: 'MCP Servers (.claude/settings.json)', value: 'mcps', checked: true },
270
+ { name: 'Workflows (.claude/workflows/)', value: 'workflows', checked: true },
271
+ { name: 'User Guide', value: 'user-guide', checked: true },
272
+ ];
273
+
274
+ export const PRESET_ALIASES = {
275
+ nextjs: { frameworks: ['Next.js'], languages: ['TypeScript'] },
276
+ 'go-api': { frameworks: ['Go API'], languages: ['Go'] },
277
+ python: { frameworks: [], languages: ['Python'] },
278
+ rust: { frameworks: [], languages: ['Rust'] },
279
+ aspnet: { frameworks: ['ASP.NET Core'], languages: ['C#'] },
280
+ cmake: { frameworks: ['CMake'], languages: ['C++'] },
281
+ };
282
+
283
+ // ── Security defaults ─────────────────────────────────────────────────
284
+
285
+ // ── Component types ──────────────────────────────────────────────────
286
+
287
+ export const COMPONENT_TYPES = {
288
+ CORE: 'core',
289
+ OPTIONAL: 'optional',
290
+ PLUGIN: 'plugin',
291
+ };
292
+
293
+ export const SENSITIVE_PATTERNS = [
294
+ '.env', '.env.*', '*.pem', '*.key', '*.cert',
295
+ 'credentials.json', 'secrets.yaml', 'secrets.yml',
296
+ '*.secret', 'id_rsa', 'id_ed25519',
297
+ '.aws/credentials', '.gcp/credentials.json',
298
+ 'serviceAccountKey.json', 'firebase-adminsdk*.json',
299
+ ];
@@ -0,0 +1,30 @@
1
+ import { join } from 'path';
2
+ import { ensureDir, outputFile } from 'fs-extra/esm';
3
+ import { pathExists } from 'fs-extra/esm';
4
+
5
+ const directories = [
6
+ '.claude/scripts',
7
+ '.claude/mcps',
8
+ '.claude/workflows',
9
+ ];
10
+
11
+ export async function generate(config, targetDir, opts = {}) {
12
+ const results = [];
13
+
14
+ for (const dir of directories) {
15
+ const dirPath = join(targetDir, dir);
16
+ await ensureDir(dirPath);
17
+
18
+ const gitkeepPath = join(dirPath, '.gitkeep');
19
+ const exists = await pathExists(gitkeepPath);
20
+
21
+ if (!exists) {
22
+ await outputFile(gitkeepPath, '');
23
+ results.push({ path: gitkeepPath, status: 'created' });
24
+ } else {
25
+ results.push({ path: gitkeepPath, status: 'exists' });
26
+ }
27
+ }
28
+
29
+ return results;
30
+ }