@qazuor/claude-code-config 0.6.1 → 0.6.2
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/dist/bin.cjs +275 -178
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +275 -178
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -6042,29 +6042,6 @@ function showReplacementReport(report) {
|
|
|
6042
6042
|
// src/lib/scaffold/claude-md-generator.ts
|
|
6043
6043
|
init_esm_shims();
|
|
6044
6044
|
init_fs();
|
|
6045
|
-
|
|
6046
|
-
// src/lib/utils/paths.ts
|
|
6047
|
-
init_esm_shims();
|
|
6048
|
-
import fs3 from "fs";
|
|
6049
|
-
import path5 from "path";
|
|
6050
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6051
|
-
function getPackageRoot() {
|
|
6052
|
-
const currentFilePath = fileURLToPath2(import.meta.url);
|
|
6053
|
-
let currentDir = path5.dirname(currentFilePath);
|
|
6054
|
-
while (currentDir !== path5.dirname(currentDir)) {
|
|
6055
|
-
const packageJsonPath = path5.join(currentDir, "package.json");
|
|
6056
|
-
if (fs3.existsSync(packageJsonPath)) {
|
|
6057
|
-
return currentDir;
|
|
6058
|
-
}
|
|
6059
|
-
currentDir = path5.dirname(currentDir);
|
|
6060
|
-
}
|
|
6061
|
-
throw new Error("Could not find package root (no package.json found in parent directories)");
|
|
6062
|
-
}
|
|
6063
|
-
function getTemplatesPath() {
|
|
6064
|
-
return path5.join(getPackageRoot(), "templates");
|
|
6065
|
-
}
|
|
6066
|
-
|
|
6067
|
-
// src/lib/scaffold/claude-md-generator.ts
|
|
6068
6045
|
async function generateClaudeMd(projectPath, projectInfo, options) {
|
|
6069
6046
|
const claudeMdPath = joinPath(projectPath, "CLAUDE.md");
|
|
6070
6047
|
const exists = await pathExists(claudeMdPath);
|
|
@@ -6076,18 +6053,12 @@ async function generateClaudeMd(projectPath, projectInfo, options) {
|
|
|
6076
6053
|
};
|
|
6077
6054
|
}
|
|
6078
6055
|
try {
|
|
6079
|
-
let
|
|
6056
|
+
let content;
|
|
6080
6057
|
if (options?.customTemplate) {
|
|
6081
|
-
|
|
6058
|
+
content = processCustomTemplate(options.customTemplate, projectInfo);
|
|
6082
6059
|
} else {
|
|
6083
|
-
|
|
6084
|
-
if (await pathExists(templatePath)) {
|
|
6085
|
-
template = await readFile(templatePath);
|
|
6086
|
-
} else {
|
|
6087
|
-
template = getMinimalTemplate();
|
|
6088
|
-
}
|
|
6060
|
+
content = generateClaudeMdContent(projectInfo, options);
|
|
6089
6061
|
}
|
|
6090
|
-
const content = processTemplate(template, projectInfo, options);
|
|
6091
6062
|
await writeFile(claudeMdPath, content);
|
|
6092
6063
|
return {
|
|
6093
6064
|
created: true,
|
|
@@ -6112,41 +6083,165 @@ async function generateClaudeMdWithSpinner(projectPath, projectInfo, options) {
|
|
|
6112
6083
|
}
|
|
6113
6084
|
);
|
|
6114
6085
|
}
|
|
6115
|
-
function
|
|
6116
|
-
|
|
6086
|
+
function processCustomTemplate(template, projectInfo) {
|
|
6087
|
+
return template.replace(/\{\{PROJECT_NAME\}\}/g, projectInfo.name).replace(/\{\{PROJECT_DESCRIPTION\}\}/g, projectInfo.description).replace(/\{\{ORG\}\}/g, projectInfo.org).replace(/\{\{REPO\}\}/g, projectInfo.repo).replace(/\{\{ENTITY_TYPE\}\}/g, projectInfo.entityType).replace(/\{\{ENTITY_TYPE_PLURAL\}\}/g, projectInfo.entityTypePlural).replace(/\{\{DOMAIN\}\}/g, projectInfo.domain || "").replace(/\{\{LOCATION\}\}/g, projectInfo.location || "");
|
|
6088
|
+
}
|
|
6089
|
+
function generateClaudeMdContent(projectInfo, options) {
|
|
6117
6090
|
const techStack = options?.templateConfig?.techStack;
|
|
6118
6091
|
const commands = options?.templateConfig?.commands;
|
|
6119
6092
|
const targets = options?.templateConfig?.targets;
|
|
6120
6093
|
const preferences = options?.claudeConfig?.preferences;
|
|
6121
6094
|
const standards = options?.claudeConfig?.extras?.standards;
|
|
6122
|
-
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectInfo.name).replace(/\{\{PROJECT_DESCRIPTION\}\}/g, projectInfo.description).replace(/\{\{ORG\}\}/g, projectInfo.org).replace(/\{\{REPO\}\}/g, projectInfo.repo).replace(/\{\{ENTITY_TYPE\}\}/g, projectInfo.entityType).replace(/\{\{ENTITY_TYPE_PLURAL\}\}/g, projectInfo.entityTypePlural).replace(/\{\{LOCATION\}\}/g, projectInfo.location || "");
|
|
6123
6095
|
const packageManager = preferences?.packageManager || "pnpm";
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6096
|
+
const lines = [];
|
|
6097
|
+
lines.push("# CLAUDE.md");
|
|
6098
|
+
lines.push("");
|
|
6099
|
+
lines.push("## Project Overview");
|
|
6100
|
+
lines.push("");
|
|
6101
|
+
lines.push(`**${projectInfo.name}** - ${projectInfo.description}`);
|
|
6102
|
+
lines.push("");
|
|
6103
|
+
lines.push("## Repository");
|
|
6104
|
+
lines.push("");
|
|
6105
|
+
lines.push(`- **Organization:** ${projectInfo.org}`);
|
|
6106
|
+
lines.push(`- **Repository:** ${projectInfo.repo}`);
|
|
6107
|
+
lines.push(`- **GitHub:** https://github.com/${projectInfo.org}/${projectInfo.repo}`);
|
|
6128
6108
|
if (projectInfo.domain) {
|
|
6129
|
-
|
|
6130
|
-
} else {
|
|
6131
|
-
content = content.replace(/\{\{#if DOMAIN\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6109
|
+
lines.push(`- **Domain:** ${projectInfo.domain}`);
|
|
6132
6110
|
}
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6111
|
+
lines.push("");
|
|
6112
|
+
lines.push("## Tech Stack");
|
|
6113
|
+
lines.push("");
|
|
6114
|
+
lines.push(generateTechStackSection(techStack));
|
|
6115
|
+
lines.push("## Project Structure");
|
|
6116
|
+
lines.push("");
|
|
6117
|
+
lines.push("```text");
|
|
6118
|
+
lines.push(`${projectInfo.name}/`);
|
|
6119
|
+
lines.push("\u251C\u2500\u2500 src/ # Source code");
|
|
6120
|
+
lines.push("\u251C\u2500\u2500 tests/ # Test files");
|
|
6121
|
+
lines.push("\u251C\u2500\u2500 docs/ # Documentation");
|
|
6122
|
+
lines.push("\u2514\u2500\u2500 .claude/ # Claude configuration");
|
|
6123
|
+
lines.push(" \u251C\u2500\u2500 agents/ # AI agent definitions");
|
|
6124
|
+
lines.push(" \u251C\u2500\u2500 commands/ # Custom slash commands");
|
|
6125
|
+
lines.push(" \u251C\u2500\u2500 skills/ # Specialized skills");
|
|
6126
|
+
lines.push(" \u2514\u2500\u2500 docs/ # AI-specific documentation");
|
|
6127
|
+
lines.push("```");
|
|
6128
|
+
lines.push("");
|
|
6129
|
+
lines.push("## Quick Commands");
|
|
6130
|
+
lines.push("");
|
|
6131
|
+
lines.push(generateCommandsSection(commands, packageManager));
|
|
6132
|
+
lines.push("## Development Guidelines");
|
|
6133
|
+
lines.push("");
|
|
6134
|
+
lines.push("### Code Standards");
|
|
6135
|
+
lines.push("");
|
|
6136
|
+
lines.push("- Primary language: TypeScript");
|
|
6137
|
+
lines.push("- Follow TypeScript best practices");
|
|
6138
|
+
if (standards?.code?.namedExportsOnly) {
|
|
6139
|
+
lines.push("- Use named exports only (no default exports)");
|
|
6140
|
+
}
|
|
6141
|
+
const maxLines = standards?.code?.maxFileLines || 500;
|
|
6142
|
+
lines.push(`- Maximum ${maxLines} lines per file`);
|
|
6143
|
+
if (standards?.code?.jsDocRequired) {
|
|
6144
|
+
lines.push("- Document all exports with JSDoc");
|
|
6138
6145
|
}
|
|
6139
|
-
if (
|
|
6140
|
-
|
|
6141
|
-
|
|
6146
|
+
if (standards?.code?.roroPattern) {
|
|
6147
|
+
lines.push("- Use RO-RO pattern (Receive Object, Return Object)");
|
|
6148
|
+
}
|
|
6149
|
+
lines.push("");
|
|
6150
|
+
lines.push("### Testing");
|
|
6151
|
+
lines.push("");
|
|
6152
|
+
if (standards?.testing?.tddRequired) {
|
|
6153
|
+
lines.push("- Methodology: TDD (Test-Driven Development)");
|
|
6154
|
+
lines.push("- Write tests first: Red -> Green -> Refactor");
|
|
6142
6155
|
} else {
|
|
6143
|
-
|
|
6156
|
+
lines.push("- Write comprehensive tests for all features");
|
|
6144
6157
|
}
|
|
6145
|
-
|
|
6146
|
-
|
|
6158
|
+
const coverageTarget = standards?.testing?.coverageTarget || (targets && "coverage" in targets ? targets.coverage : 90);
|
|
6159
|
+
lines.push(`- Maintain ${coverageTarget}%+ code coverage`);
|
|
6160
|
+
const testPattern = standards?.testing?.testPattern === "gwt" ? "GWT (Given-When-Then)" : "AAA (Arrange, Act, Assert)";
|
|
6161
|
+
lines.push(`- Test pattern: ${testPattern}`);
|
|
6162
|
+
if (standards?.testing?.testLocation) {
|
|
6163
|
+
const testLocationText = standards.testing.testLocation === "colocated" ? "Co-located with source" : "Separate test directory";
|
|
6164
|
+
lines.push(`- Test location: ${testLocationText}`);
|
|
6165
|
+
}
|
|
6166
|
+
lines.push("");
|
|
6167
|
+
lines.push("### Git Workflow");
|
|
6168
|
+
lines.push("");
|
|
6169
|
+
lines.push("- Use conventional commits: `type(scope): description`");
|
|
6170
|
+
lines.push("- Types: feat, fix, docs, style, refactor, test, chore");
|
|
6171
|
+
lines.push("- Keep commits atomic and focused");
|
|
6172
|
+
if (preferences?.includeCoAuthor) {
|
|
6173
|
+
lines.push("");
|
|
6174
|
+
lines.push("#### Commit Attribution");
|
|
6175
|
+
lines.push("");
|
|
6176
|
+
lines.push("Include the following in commit messages:");
|
|
6177
|
+
lines.push("```");
|
|
6178
|
+
lines.push("\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)");
|
|
6179
|
+
lines.push("");
|
|
6180
|
+
lines.push("Co-Authored-By: Claude <noreply@anthropic.com>");
|
|
6181
|
+
lines.push("```");
|
|
6182
|
+
}
|
|
6183
|
+
lines.push("");
|
|
6184
|
+
lines.push("## Claude Behavior Guidelines");
|
|
6185
|
+
lines.push("");
|
|
6186
|
+
lines.push("### Critical Thinking");
|
|
6187
|
+
lines.push("");
|
|
6188
|
+
lines.push("- You are an expert who double-checks things, you are skeptical and do research");
|
|
6189
|
+
lines.push("- Neither the user nor you are always right, but both strive for accuracy");
|
|
6190
|
+
lines.push("- When the user asks something, reason with these questions:");
|
|
6191
|
+
lines.push(' - "Why might the user be wrong?"');
|
|
6192
|
+
lines.push(' - "What arguments exist against what the user thinks?"');
|
|
6193
|
+
lines.push(` - "Act as devil's advocate - why might this proposal fail?"`);
|
|
6194
|
+
lines.push(` - "Imagine you're in a debate - how would you refute this?"`);
|
|
6195
|
+
lines.push(
|
|
6196
|
+
"- Always ask to better understand the context of the requested change before implementing"
|
|
6197
|
+
);
|
|
6198
|
+
lines.push("");
|
|
6199
|
+
lines.push("### Communication Style");
|
|
6200
|
+
lines.push("");
|
|
6201
|
+
if (preferences?.responseLanguage) {
|
|
6202
|
+
const langDisplay = preferences.responseLanguage === "es" ? "Spanish" : preferences.responseLanguage === "en" ? "English" : preferences.responseLanguage;
|
|
6203
|
+
lines.push(`- Respond in ${langDisplay}`);
|
|
6204
|
+
}
|
|
6205
|
+
lines.push("- Code and comments should always be in English");
|
|
6206
|
+
lines.push("- Be direct and concise");
|
|
6207
|
+
lines.push('- Explain the "why" behind decisions when relevant');
|
|
6208
|
+
lines.push("");
|
|
6209
|
+
lines.push("### Writing Style");
|
|
6210
|
+
lines.push("");
|
|
6211
|
+
lines.push(
|
|
6212
|
+
'- Systematically replace em-dashes ("\u2014") with a period (".") to start a new sentence, or a comma (",") to continue the sentence'
|
|
6213
|
+
);
|
|
6214
|
+
lines.push("- Avoid unnecessary filler words");
|
|
6215
|
+
lines.push("- Use clear, technical language");
|
|
6216
|
+
lines.push("");
|
|
6217
|
+
lines.push("## Claude Configuration");
|
|
6218
|
+
lines.push("");
|
|
6219
|
+
lines.push("This project uses `@qazuor/claude-code-config` for AI-assisted development.");
|
|
6220
|
+
lines.push("");
|
|
6221
|
+
lines.push("### Available Commands");
|
|
6222
|
+
lines.push("");
|
|
6223
|
+
lines.push("Run `/help` in Claude to see all available commands.");
|
|
6224
|
+
lines.push("");
|
|
6225
|
+
lines.push("### Documentation");
|
|
6226
|
+
lines.push("");
|
|
6227
|
+
lines.push("- Quick Start: `.claude/docs/quick-start.md`");
|
|
6228
|
+
lines.push("- Workflows: `.claude/docs/workflows/README.md`");
|
|
6229
|
+
lines.push("- Standards: `.claude/docs/standards/`");
|
|
6230
|
+
lines.push("");
|
|
6231
|
+
lines.push("---");
|
|
6232
|
+
lines.push("");
|
|
6233
|
+
lines.push(
|
|
6234
|
+
"*Generated by [@qazuor/claude-code-config](https://github.com/qazuor/claude-code-config)*"
|
|
6235
|
+
);
|
|
6236
|
+
lines.push("");
|
|
6237
|
+
return lines.join("\n");
|
|
6147
6238
|
}
|
|
6148
6239
|
function generateTechStackSection(techStack) {
|
|
6240
|
+
if (!techStack) {
|
|
6241
|
+
return getDefaultTechStack();
|
|
6242
|
+
}
|
|
6149
6243
|
const lines = [];
|
|
6244
|
+
let hasContent = false;
|
|
6150
6245
|
if (techStack.frontendFramework && techStack.frontendFramework !== "None") {
|
|
6151
6246
|
lines.push("**Frontend:**");
|
|
6152
6247
|
lines.push(`- Framework: ${techStack.frontendFramework}`);
|
|
@@ -6154,6 +6249,7 @@ function generateTechStackSection(techStack) {
|
|
|
6154
6249
|
lines.push(`- State: ${techStack.stateManagement}`);
|
|
6155
6250
|
}
|
|
6156
6251
|
lines.push("");
|
|
6252
|
+
hasContent = true;
|
|
6157
6253
|
}
|
|
6158
6254
|
if (techStack.apiFramework && techStack.apiFramework !== "None") {
|
|
6159
6255
|
lines.push("**Backend:**");
|
|
@@ -6162,145 +6258,89 @@ function generateTechStackSection(techStack) {
|
|
|
6162
6258
|
lines.push(`- Validation: ${techStack.validationLibrary}`);
|
|
6163
6259
|
}
|
|
6164
6260
|
lines.push("");
|
|
6261
|
+
hasContent = true;
|
|
6165
6262
|
}
|
|
6166
6263
|
if (techStack.databaseOrm && techStack.databaseOrm !== "None") {
|
|
6167
6264
|
lines.push("**Database:**");
|
|
6168
6265
|
lines.push(`- ORM: ${techStack.databaseOrm}`);
|
|
6169
6266
|
lines.push("");
|
|
6267
|
+
hasContent = true;
|
|
6170
6268
|
}
|
|
6171
6269
|
if (techStack.authPattern && techStack.authPattern !== "None") {
|
|
6172
6270
|
lines.push("**Authentication:**");
|
|
6173
6271
|
lines.push(`- Provider: ${techStack.authPattern}`);
|
|
6174
6272
|
lines.push("");
|
|
6273
|
+
hasContent = true;
|
|
6175
6274
|
}
|
|
6176
6275
|
if (techStack.testFramework && techStack.testFramework !== "None") {
|
|
6177
6276
|
lines.push("**Testing:**");
|
|
6178
6277
|
lines.push(`- Framework: ${techStack.testFramework}`);
|
|
6179
6278
|
lines.push("");
|
|
6279
|
+
hasContent = true;
|
|
6180
6280
|
}
|
|
6181
6281
|
if (techStack.bundler && techStack.bundler !== "None") {
|
|
6182
6282
|
lines.push("**Build:**");
|
|
6183
6283
|
lines.push(`- Bundler: ${techStack.bundler}`);
|
|
6184
6284
|
lines.push("");
|
|
6285
|
+
hasContent = true;
|
|
6286
|
+
}
|
|
6287
|
+
if (!hasContent) {
|
|
6288
|
+
return getDefaultTechStack();
|
|
6185
6289
|
}
|
|
6186
6290
|
return lines.join("\n");
|
|
6187
6291
|
}
|
|
6188
|
-
function
|
|
6292
|
+
function getDefaultTechStack() {
|
|
6293
|
+
return `**Frontend:**
|
|
6294
|
+
- Framework: Not configured
|
|
6295
|
+
|
|
6296
|
+
**Backend:**
|
|
6297
|
+
- API: Not configured
|
|
6298
|
+
|
|
6299
|
+
**Database:**
|
|
6300
|
+
- ORM: Not configured
|
|
6301
|
+
|
|
6302
|
+
**Testing:**
|
|
6303
|
+
- Framework: Not configured
|
|
6304
|
+
|
|
6305
|
+
`;
|
|
6306
|
+
}
|
|
6307
|
+
function generateCommandsSection(commands, packageManager = "pnpm") {
|
|
6189
6308
|
const lines = ["```bash"];
|
|
6190
6309
|
lines.push("# Development");
|
|
6191
6310
|
lines.push(`${packageManager} dev # Start development server`);
|
|
6192
6311
|
lines.push("");
|
|
6193
6312
|
lines.push("# Testing");
|
|
6194
|
-
if (commands
|
|
6313
|
+
if (commands?.test) {
|
|
6195
6314
|
lines.push(`${commands.test} # Run tests`);
|
|
6196
6315
|
} else {
|
|
6197
6316
|
lines.push(`${packageManager} test # Run tests`);
|
|
6198
6317
|
}
|
|
6199
|
-
if (commands
|
|
6318
|
+
if (commands?.coverage) {
|
|
6200
6319
|
lines.push(`${commands.coverage} # Run tests with coverage`);
|
|
6201
6320
|
} else {
|
|
6202
6321
|
lines.push(`${packageManager} test:coverage # Run tests with coverage`);
|
|
6203
6322
|
}
|
|
6204
6323
|
lines.push("");
|
|
6205
6324
|
lines.push("# Quality");
|
|
6206
|
-
if (commands
|
|
6325
|
+
if (commands?.lint) {
|
|
6207
6326
|
lines.push(`${commands.lint} # Run linter`);
|
|
6208
6327
|
} else {
|
|
6209
6328
|
lines.push(`${packageManager} lint # Run linter`);
|
|
6210
6329
|
}
|
|
6211
|
-
if (commands
|
|
6330
|
+
if (commands?.typecheck) {
|
|
6212
6331
|
lines.push(`${commands.typecheck} # Type checking`);
|
|
6213
6332
|
} else {
|
|
6214
6333
|
lines.push(`${packageManager} typecheck # Type checking`);
|
|
6215
6334
|
}
|
|
6216
|
-
if (commands
|
|
6335
|
+
if (commands?.build) {
|
|
6217
6336
|
lines.push("");
|
|
6218
6337
|
lines.push("# Build");
|
|
6219
6338
|
lines.push(`${commands.build} # Build for production`);
|
|
6220
6339
|
}
|
|
6221
6340
|
lines.push("```");
|
|
6341
|
+
lines.push("");
|
|
6222
6342
|
return lines.join("\n");
|
|
6223
6343
|
}
|
|
6224
|
-
function processStandardsPlaceholders(content, standards, preferences) {
|
|
6225
|
-
let result = content;
|
|
6226
|
-
const primaryLanguage = "TypeScript";
|
|
6227
|
-
result = result.replace(/\{\{PRIMARY_LANGUAGE\}\}/g, primaryLanguage);
|
|
6228
|
-
const maxFileLines = standards?.code?.maxFileLines?.toString() || "500";
|
|
6229
|
-
result = result.replace(/\{\{MAX_FILE_LINES\}\}/g, maxFileLines);
|
|
6230
|
-
const testPattern = standards?.testing?.testPattern === "gwt" ? "GWT (Given-When-Then)" : "AAA (Arrange, Act, Assert)";
|
|
6231
|
-
result = result.replace(/\{\{TEST_PATTERN\}\}/g, testPattern);
|
|
6232
|
-
const responseLanguage = preferences?.responseLanguage === "es" ? "Spanish" : preferences?.responseLanguage === "en" ? "English" : "Spanish";
|
|
6233
|
-
result = result.replace(/\{\{RESPONSE_LANGUAGE\}\}/g, responseLanguage);
|
|
6234
|
-
if (standards?.code?.namedExportsOnly) {
|
|
6235
|
-
result = result.replace(/\{\{#if NAMED_EXPORTS_ONLY\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6236
|
-
} else {
|
|
6237
|
-
result = result.replace(/\{\{#if NAMED_EXPORTS_ONLY\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6238
|
-
}
|
|
6239
|
-
if (standards?.code?.jsDocRequired) {
|
|
6240
|
-
result = result.replace(/\{\{#if JSDOC_REQUIRED\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6241
|
-
} else {
|
|
6242
|
-
result = result.replace(/\{\{#if JSDOC_REQUIRED\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6243
|
-
}
|
|
6244
|
-
if (standards?.code?.roroPattern) {
|
|
6245
|
-
result = result.replace(/\{\{#if RORO_PATTERN\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6246
|
-
} else {
|
|
6247
|
-
result = result.replace(/\{\{#if RORO_PATTERN\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6248
|
-
}
|
|
6249
|
-
if (standards?.testing?.tddRequired) {
|
|
6250
|
-
result = result.replace(/\{\{#if TDD_REQUIRED\}\}/g, "").replace(/\{\{else\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6251
|
-
} else {
|
|
6252
|
-
result = result.replace(/\{\{#if TDD_REQUIRED\}\}[\s\S]*?\{\{else\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6253
|
-
}
|
|
6254
|
-
const testLocation = standards?.testing?.testLocation;
|
|
6255
|
-
if (testLocation) {
|
|
6256
|
-
const testLocationText = testLocation === "colocated" ? "Co-located with source" : "Separate test directory";
|
|
6257
|
-
result = result.replace(/\{\{#if TEST_LOCATION\}\}/g, "").replace(/\{\{\/if\}\}/g, "").replace(/\{\{TEST_LOCATION\}\}/g, testLocationText);
|
|
6258
|
-
} else {
|
|
6259
|
-
result = result.replace(/\{\{#if TEST_LOCATION\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6260
|
-
}
|
|
6261
|
-
if (preferences?.includeCoAuthor) {
|
|
6262
|
-
result = result.replace(/\{\{#if INCLUDE_CO_AUTHOR\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6263
|
-
} else {
|
|
6264
|
-
result = result.replace(/\{\{#if INCLUDE_CO_AUTHOR\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6265
|
-
}
|
|
6266
|
-
if (preferences?.responseLanguage) {
|
|
6267
|
-
result = result.replace(/\{\{#if RESPONSE_LANGUAGE\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6268
|
-
} else {
|
|
6269
|
-
result = result.replace(/\{\{#if RESPONSE_LANGUAGE\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6270
|
-
}
|
|
6271
|
-
return result;
|
|
6272
|
-
}
|
|
6273
|
-
function getMinimalTemplate() {
|
|
6274
|
-
return `# CLAUDE.md
|
|
6275
|
-
|
|
6276
|
-
## Project Overview
|
|
6277
|
-
|
|
6278
|
-
**{{PROJECT_NAME}}** - {{PROJECT_DESCRIPTION}}
|
|
6279
|
-
|
|
6280
|
-
## Repository
|
|
6281
|
-
|
|
6282
|
-
- **GitHub:** https://github.com/{{ORG}}/{{REPO}}
|
|
6283
|
-
|
|
6284
|
-
## Quick Commands
|
|
6285
|
-
|
|
6286
|
-
\`\`\`bash
|
|
6287
|
-
{{PACKAGE_MANAGER}} dev # Start development
|
|
6288
|
-
{{PACKAGE_MANAGER}} test # Run tests
|
|
6289
|
-
{{PACKAGE_MANAGER}} lint # Run linter
|
|
6290
|
-
{{PACKAGE_MANAGER}} build # Build project
|
|
6291
|
-
\`\`\`
|
|
6292
|
-
|
|
6293
|
-
## Claude Configuration
|
|
6294
|
-
|
|
6295
|
-
This project uses \`@qazuor/claude-code-config\` for AI-assisted development.
|
|
6296
|
-
|
|
6297
|
-
See \`.claude/docs/quick-start.md\` for getting started.
|
|
6298
|
-
|
|
6299
|
-
---
|
|
6300
|
-
|
|
6301
|
-
*Generated by [@qazuor/claude-code-config](https://github.com/qazuor/claude-code-config)*
|
|
6302
|
-
`;
|
|
6303
|
-
}
|
|
6304
6344
|
|
|
6305
6345
|
// src/lib/scaffold/index.ts
|
|
6306
6346
|
init_esm_shims();
|
|
@@ -7053,8 +7093,8 @@ function buildSettingsLocalJson(options) {
|
|
|
7053
7093
|
|
|
7054
7094
|
// src/lib/templates/config-replacer.ts
|
|
7055
7095
|
init_esm_shims();
|
|
7056
|
-
import * as
|
|
7057
|
-
import * as
|
|
7096
|
+
import * as fs3 from "fs/promises";
|
|
7097
|
+
import * as path5 from "path";
|
|
7058
7098
|
import ora2 from "ora";
|
|
7059
7099
|
|
|
7060
7100
|
// src/constants/template-placeholders.ts
|
|
@@ -7962,7 +8002,7 @@ function flattenTemplateConfig(config) {
|
|
|
7962
8002
|
return flattened;
|
|
7963
8003
|
}
|
|
7964
8004
|
function shouldProcessFile(filePath) {
|
|
7965
|
-
const ext =
|
|
8005
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
7966
8006
|
return PROCESSABLE_EXTENSIONS.includes(ext);
|
|
7967
8007
|
}
|
|
7968
8008
|
function shouldSkipDirectory(dirName) {
|
|
@@ -7971,9 +8011,9 @@ function shouldSkipDirectory(dirName) {
|
|
|
7971
8011
|
async function getAllFiles(dir) {
|
|
7972
8012
|
const files = [];
|
|
7973
8013
|
try {
|
|
7974
|
-
const entries = await
|
|
8014
|
+
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
7975
8015
|
for (const entry of entries) {
|
|
7976
|
-
const fullPath =
|
|
8016
|
+
const fullPath = path5.join(dir, entry.name);
|
|
7977
8017
|
if (entry.isDirectory()) {
|
|
7978
8018
|
if (!shouldSkipDirectory(entry.name)) {
|
|
7979
8019
|
const subFiles = await getAllFiles(fullPath);
|
|
@@ -7990,7 +8030,7 @@ async function getAllFiles(dir) {
|
|
|
7990
8030
|
async function replaceInFile2(filePath, replacements) {
|
|
7991
8031
|
const changes = [];
|
|
7992
8032
|
try {
|
|
7993
|
-
let content = await
|
|
8033
|
+
let content = await fs3.readFile(filePath, "utf-8");
|
|
7994
8034
|
let modified = false;
|
|
7995
8035
|
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
7996
8036
|
if (content.includes(placeholder)) {
|
|
@@ -8000,7 +8040,7 @@ async function replaceInFile2(filePath, replacements) {
|
|
|
8000
8040
|
}
|
|
8001
8041
|
}
|
|
8002
8042
|
if (modified) {
|
|
8003
|
-
await
|
|
8043
|
+
await fs3.writeFile(filePath, content, "utf-8");
|
|
8004
8044
|
}
|
|
8005
8045
|
} catch {
|
|
8006
8046
|
}
|
|
@@ -8021,7 +8061,7 @@ async function replaceTemplatePlaceholders(dir, config) {
|
|
|
8021
8061
|
report.filesModified++;
|
|
8022
8062
|
for (const change of changes) {
|
|
8023
8063
|
report.replacements.push({
|
|
8024
|
-
file:
|
|
8064
|
+
file: path5.relative(dir, file),
|
|
8025
8065
|
placeholder: change.placeholder,
|
|
8026
8066
|
value: change.value
|
|
8027
8067
|
});
|
|
@@ -8092,11 +8132,11 @@ async function previewReplacements(dir, config) {
|
|
|
8092
8132
|
const preview = [];
|
|
8093
8133
|
for (const file of files) {
|
|
8094
8134
|
try {
|
|
8095
|
-
const content = await
|
|
8135
|
+
const content = await fs3.readFile(file, "utf-8");
|
|
8096
8136
|
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
8097
8137
|
if (content.includes(placeholder)) {
|
|
8098
8138
|
preview.push({
|
|
8099
|
-
file:
|
|
8139
|
+
file: path5.relative(dir, file),
|
|
8100
8140
|
placeholder,
|
|
8101
8141
|
value
|
|
8102
8142
|
});
|
|
@@ -8111,6 +8151,27 @@ async function previewReplacements(dir, config) {
|
|
|
8111
8151
|
// src/cli/commands/init.ts
|
|
8112
8152
|
init_fs();
|
|
8113
8153
|
|
|
8154
|
+
// src/lib/utils/paths.ts
|
|
8155
|
+
init_esm_shims();
|
|
8156
|
+
import fs4 from "fs";
|
|
8157
|
+
import path6 from "path";
|
|
8158
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8159
|
+
function getPackageRoot() {
|
|
8160
|
+
const currentFilePath = fileURLToPath2(import.meta.url);
|
|
8161
|
+
let currentDir = path6.dirname(currentFilePath);
|
|
8162
|
+
while (currentDir !== path6.dirname(currentDir)) {
|
|
8163
|
+
const packageJsonPath = path6.join(currentDir, "package.json");
|
|
8164
|
+
if (fs4.existsSync(packageJsonPath)) {
|
|
8165
|
+
return currentDir;
|
|
8166
|
+
}
|
|
8167
|
+
currentDir = path6.dirname(currentDir);
|
|
8168
|
+
}
|
|
8169
|
+
throw new Error("Could not find package root (no package.json found in parent directories)");
|
|
8170
|
+
}
|
|
8171
|
+
function getTemplatesPath() {
|
|
8172
|
+
return path6.join(getPackageRoot(), "templates");
|
|
8173
|
+
}
|
|
8174
|
+
|
|
8114
8175
|
// src/lib/utils/prompt-cancel.ts
|
|
8115
8176
|
init_esm_shims();
|
|
8116
8177
|
import * as readline from "readline";
|
|
@@ -10647,6 +10708,61 @@ async function promptMcpConfig(options) {
|
|
|
10647
10708
|
const installedServers = await getInstalledMcpServers(projectPath);
|
|
10648
10709
|
const userInstalledSet = new Set(installedServers.user);
|
|
10649
10710
|
const projectInstalledSet = new Set(installedServers.project);
|
|
10711
|
+
const availableServers = MCP_SERVERS.filter(
|
|
10712
|
+
(s) => !userInstalledSet.has(s.id) && !projectInstalledSet.has(s.id)
|
|
10713
|
+
);
|
|
10714
|
+
if (availableServers.length === 0) {
|
|
10715
|
+
logger.newline();
|
|
10716
|
+
logger.success("All MCP servers are already installed!");
|
|
10717
|
+
const parts = [];
|
|
10718
|
+
if (userInstalledSet.size > 0) {
|
|
10719
|
+
parts.push(`${userInstalledSet.size} at user level`);
|
|
10720
|
+
}
|
|
10721
|
+
if (projectInstalledSet.size > 0) {
|
|
10722
|
+
parts.push(`${projectInstalledSet.size} at project level`);
|
|
10723
|
+
}
|
|
10724
|
+
logger.info(colors.muted(` (${parts.join(", ")})`));
|
|
10725
|
+
logger.newline();
|
|
10726
|
+
const wantCustom2 = await confirm({
|
|
10727
|
+
message: "Do you want to add a custom MCP server?",
|
|
10728
|
+
default: false
|
|
10729
|
+
});
|
|
10730
|
+
if (wantCustom2) {
|
|
10731
|
+
const level2 = await select({
|
|
10732
|
+
message: "Where should the custom server be configured?",
|
|
10733
|
+
choices: [
|
|
10734
|
+
{
|
|
10735
|
+
name: "Project level (.claude/settings.local.json)",
|
|
10736
|
+
value: "project",
|
|
10737
|
+
description: "Specific to this project"
|
|
10738
|
+
},
|
|
10739
|
+
{
|
|
10740
|
+
name: "User level (~/.claude/settings.json)",
|
|
10741
|
+
value: "user",
|
|
10742
|
+
description: "Available in all projects"
|
|
10743
|
+
}
|
|
10744
|
+
],
|
|
10745
|
+
default: options?.defaults?.level || "project"
|
|
10746
|
+
});
|
|
10747
|
+
const customInstallation = await promptCustomServer(level2);
|
|
10748
|
+
if (customInstallation) {
|
|
10749
|
+
return {
|
|
10750
|
+
config: {
|
|
10751
|
+
level: level2,
|
|
10752
|
+
servers: [customInstallation]
|
|
10753
|
+
},
|
|
10754
|
+
skippedConfigs: []
|
|
10755
|
+
};
|
|
10756
|
+
}
|
|
10757
|
+
}
|
|
10758
|
+
return {
|
|
10759
|
+
config: {
|
|
10760
|
+
level: "project",
|
|
10761
|
+
servers: []
|
|
10762
|
+
},
|
|
10763
|
+
skippedConfigs: []
|
|
10764
|
+
};
|
|
10765
|
+
}
|
|
10650
10766
|
const level = await select({
|
|
10651
10767
|
message: "Where should MCP servers be configured?",
|
|
10652
10768
|
choices: [
|
|
@@ -10680,37 +10796,18 @@ async function promptMcpConfig(options) {
|
|
|
10680
10796
|
}
|
|
10681
10797
|
logger.newline();
|
|
10682
10798
|
for (const [category, servers] of Object.entries(serversByCategory)) {
|
|
10683
|
-
const
|
|
10684
|
-
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
return {
|
|
10688
|
-
name: `${s.name} - ${s.description} ${colors.muted("(already installed at user level)")}`,
|
|
10689
|
-
value: s.id,
|
|
10690
|
-
checked: false,
|
|
10691
|
-
disabled: "already installed at user level"
|
|
10692
|
-
};
|
|
10693
|
-
}
|
|
10694
|
-
if (isInstalledAtProjectLevel) {
|
|
10695
|
-
return {
|
|
10696
|
-
name: `${s.name} - ${s.description} ${colors.muted("(already installed at project level)")}`,
|
|
10697
|
-
value: s.id,
|
|
10698
|
-
checked: false,
|
|
10699
|
-
disabled: "already installed at project level"
|
|
10700
|
-
};
|
|
10701
|
-
}
|
|
10702
|
-
return {
|
|
10703
|
-
name: `${s.name} - ${s.description}`,
|
|
10704
|
-
value: s.id,
|
|
10705
|
-
checked: options?.defaults?.servers?.some((i) => i.serverId === s.id) ?? false
|
|
10706
|
-
};
|
|
10707
|
-
});
|
|
10708
|
-
const hasEnabledChoices = choices.some((choice) => !choice.disabled);
|
|
10709
|
-
const categoryLabel = formatCategory(category);
|
|
10710
|
-
if (!hasEnabledChoices) {
|
|
10711
|
-
logger.info(colors.muted(`${categoryLabel}: All servers already installed`));
|
|
10799
|
+
const availableInCategory = servers.filter(
|
|
10800
|
+
(s) => !userInstalledSet.has(s.id) && !projectInstalledSet.has(s.id)
|
|
10801
|
+
);
|
|
10802
|
+
if (availableInCategory.length === 0) {
|
|
10712
10803
|
continue;
|
|
10713
10804
|
}
|
|
10805
|
+
const choices = availableInCategory.map((s) => ({
|
|
10806
|
+
name: `${s.name} - ${s.description}`,
|
|
10807
|
+
value: s.id,
|
|
10808
|
+
checked: options?.defaults?.servers?.some((i) => i.serverId === s.id) ?? false
|
|
10809
|
+
}));
|
|
10810
|
+
const categoryLabel = formatCategory(category);
|
|
10714
10811
|
const selected = await checkbox({
|
|
10715
10812
|
message: `${categoryLabel}:`,
|
|
10716
10813
|
choices
|