claude-code-templates 1.1.0 → 1.1.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/bin/create-claude-config.js +3 -4
- package/package.json +7 -2
- package/scripts/sync-templates.js +182 -0
- package/src/file-operations.js +56 -13
- package/src/index.js +3 -6
- package/src/prompts.js +164 -30
- package/src/templates.js +12 -20
- package/templates/go/README.md +25 -0
- package/templates/javascript-typescript/.claude/commands/api-endpoint.md +51 -1
- package/templates/javascript-typescript/.claude/commands/debug.md +52 -1
- package/templates/javascript-typescript/.claude/commands/lint.md +48 -1
- package/templates/javascript-typescript/.claude/commands/npm-scripts.md +48 -1
- package/templates/javascript-typescript/.claude/commands/refactor.md +55 -1
- package/templates/javascript-typescript/.claude/commands/test.md +61 -1
- package/templates/javascript-typescript/.claude/commands/typescript-migrate.md +51 -1
- package/templates/javascript-typescript/.claude/settings.json +41 -2
- package/templates/javascript-typescript/.mcp.json +13 -0
- package/templates/javascript-typescript/README.md +213 -187
- package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +63 -0
- package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +62 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +46 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +56 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +61 -1
- package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +57 -1
- package/templates/javascript-typescript/examples/node-api/CLAUDE.md +102 -1
- package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +29 -1
- package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +44 -1
- package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +45 -0
- package/templates/javascript-typescript/examples/react-app/CLAUDE.md +81 -1
- package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +46 -0
- package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +51 -0
- package/templates/rust/README.md +26 -0
- package/templates/javascript-typescript/.claude/commands/react-component.md +0 -1
- package/templates/javascript-typescript/.claude/commands/route.md +0 -193
- package/templates/javascript-typescript/.claude/hooks/format-on-save.json +0 -1
- package/templates/javascript-typescript/.claude/hooks/lint-on-save.json +0 -1
- package/templates/javascript-typescript/.claude/hooks/typescript-check.json +0 -1
|
@@ -6,7 +6,7 @@ const boxen = require('boxen');
|
|
|
6
6
|
const createClaudeConfig = require('../src/index');
|
|
7
7
|
|
|
8
8
|
// ASCII Art for Claude Code Templates
|
|
9
|
-
const banner = chalk.
|
|
9
|
+
const banner = chalk.hex('#D97706')(`
|
|
10
10
|
██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗
|
|
11
11
|
██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝
|
|
12
12
|
██║ ██║ ███████║██║ ██║██║ ██║█████╗
|
|
@@ -27,9 +27,8 @@ const banner = chalk.cyan(`
|
|
|
27
27
|
██║ ██╔══╝ ██║╚██╔╝██║██╔═══╝ ██║ ██╔══██║ ██║ ██╔══╝ ╚════██║
|
|
28
28
|
██║ ███████╗██║ ╚═╝ ██║██║ ███████╗██║ ██║ ██║ ███████╗███████║
|
|
29
29
|
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝
|
|
30
|
-
`) +
|
|
31
|
-
|
|
32
|
-
`);
|
|
30
|
+
`) +
|
|
31
|
+
chalk.yellow('\n 🚀 Setup Claude Code for any project language 🚀');
|
|
33
32
|
|
|
34
33
|
console.log(banner);
|
|
35
34
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-templates",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "CLI tool to setup Claude Code configurations for different programming languages",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"start": "node bin/create-claude-config.js",
|
|
14
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
15
|
+
"sync": "node scripts/sync-templates.js",
|
|
16
|
+
"presync": "echo \"🔄 Starting template synchronization...\"",
|
|
17
|
+
"postsync": "echo \"✅ Synchronization completed. Ready to publish!\"",
|
|
18
|
+
"prepublishOnly": "npm run sync"
|
|
15
19
|
},
|
|
16
20
|
"keywords": [
|
|
17
21
|
"claude",
|
|
@@ -46,6 +50,7 @@
|
|
|
46
50
|
"files": [
|
|
47
51
|
"bin/",
|
|
48
52
|
"src/",
|
|
53
|
+
"scripts/",
|
|
49
54
|
"templates/",
|
|
50
55
|
"README.md"
|
|
51
56
|
]
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Script to synchronize templates from root folders
|
|
9
|
+
* to cli-tool/templates/
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
async function syncTemplates() {
|
|
13
|
+
console.log(chalk.blue('🔄 Synchronizing templates...'));
|
|
14
|
+
|
|
15
|
+
const rootDir = path.join(__dirname, '..', '..');
|
|
16
|
+
const templatesDir = path.join(__dirname, '..', 'templates');
|
|
17
|
+
|
|
18
|
+
// Languages to synchronize
|
|
19
|
+
const languages = ['common', 'javascript-typescript', 'python', 'rust', 'go'];
|
|
20
|
+
|
|
21
|
+
let totalCopied = 0;
|
|
22
|
+
let totalSkipped = 0;
|
|
23
|
+
|
|
24
|
+
for (const language of languages) {
|
|
25
|
+
const sourceDir = path.join(rootDir, language);
|
|
26
|
+
const targetDir = path.join(templatesDir, language);
|
|
27
|
+
|
|
28
|
+
if (!await fs.pathExists(sourceDir)) {
|
|
29
|
+
console.log(chalk.yellow(`⚠️ Source folder does not exist: ${language}`));
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log(chalk.cyan(`\n📂 Synchronizing ${language}...`));
|
|
34
|
+
|
|
35
|
+
// Clean destination directory
|
|
36
|
+
if (await fs.pathExists(targetDir)) {
|
|
37
|
+
await fs.remove(targetDir);
|
|
38
|
+
console.log(chalk.gray(` 🗑️ Previous directory removed`));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Copy everything from source
|
|
42
|
+
try {
|
|
43
|
+
await fs.copy(sourceDir, targetDir, {
|
|
44
|
+
filter: (src, dest) => {
|
|
45
|
+
// Filter files we don't want to copy
|
|
46
|
+
const relativePath = path.relative(sourceDir, src);
|
|
47
|
+
|
|
48
|
+
// Exclude specific directories and files
|
|
49
|
+
if (relativePath.includes('node_modules')) return false;
|
|
50
|
+
if (relativePath.includes('.git')) return false;
|
|
51
|
+
if (relativePath.includes('package-lock.json')) return false;
|
|
52
|
+
if (relativePath.endsWith('.log')) return false;
|
|
53
|
+
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Count copied files
|
|
59
|
+
const stats = await getDirectoryStats(targetDir);
|
|
60
|
+
totalCopied += stats.files;
|
|
61
|
+
|
|
62
|
+
console.log(chalk.green(` ✅ ${stats.files} files copied`));
|
|
63
|
+
|
|
64
|
+
// Show copied structure
|
|
65
|
+
if (stats.files > 0) {
|
|
66
|
+
await showDirectoryStructure(targetDir, ' ');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(chalk.red(` ❌ Error copying ${language}:`), error.message);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(chalk.green(`\n🎉 Synchronization completed!`));
|
|
75
|
+
console.log(chalk.white(`📊 Total synchronized files: ${totalCopied}`));
|
|
76
|
+
|
|
77
|
+
// Verify that no hook files exist
|
|
78
|
+
await cleanupOldReferences();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function getDirectoryStats(dir) {
|
|
82
|
+
let files = 0;
|
|
83
|
+
let dirs = 0;
|
|
84
|
+
|
|
85
|
+
if (!await fs.pathExists(dir)) {
|
|
86
|
+
return { files: 0, dirs: 0 };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const items = await fs.readdir(dir);
|
|
90
|
+
|
|
91
|
+
for (const item of items) {
|
|
92
|
+
const itemPath = path.join(dir, item);
|
|
93
|
+
const stat = await fs.stat(itemPath);
|
|
94
|
+
|
|
95
|
+
if (stat.isDirectory()) {
|
|
96
|
+
dirs++;
|
|
97
|
+
const subStats = await getDirectoryStats(itemPath);
|
|
98
|
+
files += subStats.files;
|
|
99
|
+
dirs += subStats.dirs;
|
|
100
|
+
} else {
|
|
101
|
+
files++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { files, dirs };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function showDirectoryStructure(dir, prefix = '') {
|
|
109
|
+
const items = await fs.readdir(dir);
|
|
110
|
+
|
|
111
|
+
for (let i = 0; i < items.length; i++) {
|
|
112
|
+
const item = items[i];
|
|
113
|
+
const itemPath = path.join(dir, item);
|
|
114
|
+
const stat = await fs.stat(itemPath);
|
|
115
|
+
const isLast = i === items.length - 1;
|
|
116
|
+
const connector = isLast ? '└── ' : '├── ';
|
|
117
|
+
|
|
118
|
+
if (stat.isDirectory()) {
|
|
119
|
+
console.log(chalk.blue(`${prefix}${connector}${item}/`));
|
|
120
|
+
if (item === '.claude' || item === 'commands') {
|
|
121
|
+
// Show only one more level for .claude and commands
|
|
122
|
+
const subItems = await fs.readdir(itemPath);
|
|
123
|
+
const newPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
124
|
+
for (let j = 0; j < Math.min(subItems.length, 3); j++) {
|
|
125
|
+
const subItem = subItems[j];
|
|
126
|
+
const subConnector = j === Math.min(subItems.length, 3) - 1 ? '└── ' : '├── ';
|
|
127
|
+
console.log(chalk.gray(`${newPrefix}${subConnector}${subItem}`));
|
|
128
|
+
}
|
|
129
|
+
if (subItems.length > 3) {
|
|
130
|
+
console.log(chalk.gray(`${newPrefix}└── ... and ${subItems.length - 3} more`));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
console.log(chalk.gray(`${prefix}${connector}${item}`));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function cleanupOldReferences() {
|
|
140
|
+
console.log(chalk.yellow('\n🧹 Cleaning up obsolete references...'));
|
|
141
|
+
|
|
142
|
+
const templatesDir = path.join(__dirname, '..', 'templates');
|
|
143
|
+
|
|
144
|
+
// Search and remove hooks directories
|
|
145
|
+
const languages = ['javascript-typescript', 'python', 'common'];
|
|
146
|
+
|
|
147
|
+
for (const language of languages) {
|
|
148
|
+
const hooksDir = path.join(templatesDir, language, '.claude', 'hooks');
|
|
149
|
+
if (await fs.pathExists(hooksDir)) {
|
|
150
|
+
await fs.remove(hooksDir);
|
|
151
|
+
console.log(chalk.yellow(` 🗑️ Removed: ${language}/.claude/hooks/`));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Check for empty files in commands
|
|
156
|
+
for (const language of languages) {
|
|
157
|
+
const commandsDir = path.join(templatesDir, language, '.claude', 'commands');
|
|
158
|
+
if (await fs.pathExists(commandsDir)) {
|
|
159
|
+
const files = await fs.readdir(commandsDir);
|
|
160
|
+
for (const file of files) {
|
|
161
|
+
const filePath = path.join(commandsDir, file);
|
|
162
|
+
const stat = await fs.stat(filePath);
|
|
163
|
+
if (stat.size < 50) { // Very small files are probably empty
|
|
164
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
165
|
+
if (content.trim().length < 10) {
|
|
166
|
+
console.log(chalk.yellow(` ⚠️ Possibly empty file: ${language}/.claude/commands/${file} (${stat.size} bytes)`));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Function to execute synchronization
|
|
175
|
+
if (require.main === module) {
|
|
176
|
+
syncTemplates().catch(error => {
|
|
177
|
+
console.error(chalk.red('❌ Error during synchronization:'), error);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports = { syncTemplates };
|
package/src/file-operations.js
CHANGED
|
@@ -23,25 +23,68 @@ async function copyTemplateFiles(templateConfig, targetDir) {
|
|
|
23
23
|
console.log(chalk.yellow(`📁 Existing .claude directory backed up to .claude.backup`));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// Copy base files
|
|
26
|
+
// Copy base files and framework-specific files
|
|
27
27
|
for (const file of templateConfig.files) {
|
|
28
28
|
const sourcePath = path.join(templateDir, file.source);
|
|
29
29
|
const destPath = path.join(targetDir, file.destination);
|
|
30
30
|
|
|
31
31
|
try {
|
|
32
|
-
//
|
|
33
|
-
if (file.source.includes('.claude/commands')) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
// Handle framework-specific command files specially
|
|
33
|
+
if (file.source.includes('.claude/commands') && file.source.includes('examples/')) {
|
|
34
|
+
// This is a framework-specific commands directory - merge with existing commands
|
|
35
|
+
await fs.ensureDir(destPath);
|
|
36
|
+
|
|
37
|
+
// Copy framework-specific commands to the commands directory
|
|
38
|
+
const frameworkFiles = await fs.readdir(sourcePath);
|
|
39
|
+
for (const frameworkFile of frameworkFiles) {
|
|
40
|
+
const srcFile = path.join(sourcePath, frameworkFile);
|
|
41
|
+
const destFile = path.join(destPath, frameworkFile);
|
|
42
|
+
await fs.copy(srcFile, destFile, { overwrite: true });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(chalk.green(`✓ Copied framework commands ${file.source} → ${file.destination}`));
|
|
46
|
+
} else if (file.source.includes('.claude') && !file.source.includes('examples/')) {
|
|
47
|
+
// This is base .claude directory - copy it but handle commands specially
|
|
48
|
+
await fs.copy(sourcePath, destPath, {
|
|
49
|
+
overwrite: true,
|
|
50
|
+
filter: (src) => {
|
|
51
|
+
// Skip the commands directory itself - we'll handle it separately
|
|
52
|
+
return !src.endsWith('.claude/commands');
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Now handle base commands specifically
|
|
57
|
+
const baseCommandsPath = path.join(sourcePath, 'commands');
|
|
58
|
+
const destCommandsPath = path.join(destPath, 'commands');
|
|
59
|
+
|
|
60
|
+
if (await fs.pathExists(baseCommandsPath)) {
|
|
61
|
+
await fs.ensureDir(destCommandsPath);
|
|
62
|
+
|
|
63
|
+
// Copy base commands, but exclude framework-specific ones that were moved
|
|
64
|
+
const baseCommands = await fs.readdir(baseCommandsPath);
|
|
65
|
+
const excludeCommands = ['react-component.md', 'route.md', 'api-endpoint.md']; // Commands moved to framework dirs
|
|
66
|
+
|
|
67
|
+
for (const baseCommand of baseCommands) {
|
|
68
|
+
if (!excludeCommands.includes(baseCommand)) {
|
|
69
|
+
const srcFile = path.join(baseCommandsPath, baseCommand);
|
|
70
|
+
const destFile = path.join(destCommandsPath, baseCommand);
|
|
71
|
+
await fs.copy(srcFile, destFile, { overwrite: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
42
74
|
}
|
|
43
|
-
|
|
44
|
-
|
|
75
|
+
|
|
76
|
+
console.log(chalk.green(`✓ Copied base configuration and commands ${file.source} → ${file.destination}`));
|
|
77
|
+
} else {
|
|
78
|
+
// Copy regular files (CLAUDE.md, settings.json, etc.)
|
|
79
|
+
await fs.copy(sourcePath, destPath, {
|
|
80
|
+
overwrite: true,
|
|
81
|
+
filter: (src) => {
|
|
82
|
+
// Skip commands directory during regular copy - we handle them above
|
|
83
|
+
return !src.includes('.claude/commands');
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
console.log(chalk.green(`✓ Copied ${file.source} → ${file.destination}`));
|
|
87
|
+
}
|
|
45
88
|
} catch (error) {
|
|
46
89
|
console.error(chalk.red(`✗ Failed to copy ${file.source}:`), error.message);
|
|
47
90
|
throw error;
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const ora = require('ora');
|
|
6
6
|
const { detectProject } = require('./utils');
|
|
7
7
|
const { getTemplateConfig } = require('./templates');
|
|
8
|
-
const { createPrompts } = require('./prompts');
|
|
8
|
+
const { createPrompts, interactivePrompts } = require('./prompts');
|
|
9
9
|
const { copyTemplateFiles } = require('./file-operations');
|
|
10
10
|
|
|
11
11
|
async function createClaudeConfig(options = {}) {
|
|
@@ -19,9 +19,6 @@ async function createClaudeConfig(options = {}) {
|
|
|
19
19
|
const projectInfo = await detectProject(targetDir);
|
|
20
20
|
spinner.succeed('Project detection complete');
|
|
21
21
|
|
|
22
|
-
// Create interactive prompts
|
|
23
|
-
const prompts = createPrompts(projectInfo, options);
|
|
24
|
-
|
|
25
22
|
let config;
|
|
26
23
|
if (options.yes) {
|
|
27
24
|
// Use defaults
|
|
@@ -31,8 +28,8 @@ async function createClaudeConfig(options = {}) {
|
|
|
31
28
|
features: []
|
|
32
29
|
};
|
|
33
30
|
} else {
|
|
34
|
-
// Interactive prompts
|
|
35
|
-
config = await
|
|
31
|
+
// Interactive prompts with back navigation
|
|
32
|
+
config = await interactivePrompts(projectInfo, options);
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
// Check if user confirmed the setup
|
package/src/prompts.js
CHANGED
|
@@ -1,7 +1,169 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
2
3
|
const { getAvailableLanguages, getFrameworksForLanguage } = require('./templates');
|
|
3
4
|
const { getCommandsForLanguageAndFramework } = require('./command-scanner');
|
|
4
5
|
|
|
6
|
+
async function interactivePrompts(projectInfo, options = {}) {
|
|
7
|
+
const state = {
|
|
8
|
+
currentStep: 0,
|
|
9
|
+
answers: {},
|
|
10
|
+
steps: []
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Build steps array based on options
|
|
14
|
+
if (!options.language) state.steps.push('language');
|
|
15
|
+
if (!options.framework) state.steps.push('framework');
|
|
16
|
+
state.steps.push('commands', 'confirm');
|
|
17
|
+
|
|
18
|
+
while (state.currentStep < state.steps.length) {
|
|
19
|
+
const stepName = state.steps[state.currentStep];
|
|
20
|
+
const result = await showStep(stepName, state.answers, projectInfo, options);
|
|
21
|
+
|
|
22
|
+
if (result.action === 'back') {
|
|
23
|
+
if (state.currentStep > 0) {
|
|
24
|
+
state.currentStep--;
|
|
25
|
+
// Clear the answer for the step we're going back from
|
|
26
|
+
delete state.answers[stepName];
|
|
27
|
+
}
|
|
28
|
+
} else if (result.action === 'next') {
|
|
29
|
+
state.answers[stepName] = result.value;
|
|
30
|
+
state.currentStep++;
|
|
31
|
+
} else if (result.action === 'exit') {
|
|
32
|
+
return { confirm: false };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return state.answers;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function showStep(stepName, currentAnswers, projectInfo, options) {
|
|
40
|
+
const stepConfig = getStepConfig(stepName, currentAnswers, projectInfo, options);
|
|
41
|
+
|
|
42
|
+
if (!stepConfig) {
|
|
43
|
+
return { action: 'next', value: null };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Add back option if not first step
|
|
47
|
+
const isFirstStep = stepName === 'language' || (options.language && stepName === 'framework') ||
|
|
48
|
+
(options.language && options.framework && stepName === 'commands');
|
|
49
|
+
|
|
50
|
+
if (!isFirstStep && stepConfig.type === 'list') {
|
|
51
|
+
stepConfig.choices = [
|
|
52
|
+
{ value: '__back__', name: chalk.gray('← Back') },
|
|
53
|
+
new inquirer.Separator(),
|
|
54
|
+
...stepConfig.choices
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const answer = await inquirer.prompt([stepConfig]);
|
|
59
|
+
const value = answer[stepName];
|
|
60
|
+
|
|
61
|
+
if (value === '__back__') {
|
|
62
|
+
return { action: 'back' };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return { action: 'next', value };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getStepConfig(stepName, currentAnswers, projectInfo, options) {
|
|
69
|
+
switch (stepName) {
|
|
70
|
+
case 'language':
|
|
71
|
+
return {
|
|
72
|
+
type: 'list',
|
|
73
|
+
name: 'language',
|
|
74
|
+
message: 'Select your programming language:',
|
|
75
|
+
choices: getAvailableLanguages(),
|
|
76
|
+
default: projectInfo.detectedLanguage || 'common',
|
|
77
|
+
prefix: chalk.blue('🔤')
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
case 'framework':
|
|
81
|
+
const selectedLanguage = currentAnswers.language || options.language;
|
|
82
|
+
const frameworks = getFrameworksForLanguage(selectedLanguage);
|
|
83
|
+
|
|
84
|
+
if (frameworks.length === 0) {
|
|
85
|
+
return null; // Skip this step
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
type: 'list',
|
|
90
|
+
name: 'framework',
|
|
91
|
+
message: 'Select your framework (optional):',
|
|
92
|
+
choices: [
|
|
93
|
+
{ value: 'none', name: 'None / Generic' },
|
|
94
|
+
...frameworks
|
|
95
|
+
],
|
|
96
|
+
default: projectInfo.detectedFramework || 'none',
|
|
97
|
+
prefix: chalk.green('🎯')
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
case 'commands':
|
|
101
|
+
const commandLanguage = currentAnswers.language || options.language;
|
|
102
|
+
const commandFramework = currentAnswers.framework || options.framework;
|
|
103
|
+
|
|
104
|
+
if (!commandLanguage || commandLanguage === 'common') {
|
|
105
|
+
return {
|
|
106
|
+
type: 'checkbox',
|
|
107
|
+
name: 'commands',
|
|
108
|
+
message: 'Select commands to include (use space to select):',
|
|
109
|
+
choices: [
|
|
110
|
+
{
|
|
111
|
+
value: 'basic-commands',
|
|
112
|
+
name: 'Basic development commands',
|
|
113
|
+
checked: true
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
prefix: chalk.cyan('📋')
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const availableCommands = getCommandsForLanguageAndFramework(commandLanguage, commandFramework);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
type: 'checkbox',
|
|
124
|
+
name: 'commands',
|
|
125
|
+
message: 'Select commands to include (use space to select, enter to continue):',
|
|
126
|
+
choices: availableCommands.map(cmd => ({
|
|
127
|
+
value: cmd.name,
|
|
128
|
+
name: `${cmd.displayName} - ${cmd.description}`,
|
|
129
|
+
checked: cmd.checked
|
|
130
|
+
})),
|
|
131
|
+
prefix: chalk.cyan('📋')
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
case 'confirm':
|
|
135
|
+
const confirmLanguage = currentAnswers.language || options.language || 'common';
|
|
136
|
+
const confirmFramework = currentAnswers.framework || options.framework || 'none';
|
|
137
|
+
const commandCount = currentAnswers.commands ? currentAnswers.commands.length : 0;
|
|
138
|
+
|
|
139
|
+
let message = `Setup Claude Code for ${chalk.cyan(confirmLanguage)}`;
|
|
140
|
+
if (confirmFramework !== 'none') {
|
|
141
|
+
message += ` with ${chalk.green(confirmFramework)}`;
|
|
142
|
+
}
|
|
143
|
+
if (commandCount > 0) {
|
|
144
|
+
message += ` (${chalk.yellow(commandCount)} commands)`;
|
|
145
|
+
}
|
|
146
|
+
message += '?';
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
type: 'list',
|
|
150
|
+
name: 'confirm',
|
|
151
|
+
message,
|
|
152
|
+
choices: [
|
|
153
|
+
{ value: '__back__', name: chalk.gray('← Back to modify settings') },
|
|
154
|
+
new inquirer.Separator(),
|
|
155
|
+
{ value: true, name: chalk.green('✅ Yes, proceed with setup') },
|
|
156
|
+
{ value: false, name: chalk.red('❌ No, cancel setup') }
|
|
157
|
+
],
|
|
158
|
+
default: true,
|
|
159
|
+
prefix: chalk.red('🚀')
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
default:
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
5
167
|
function createPrompts(projectInfo, options = {}) {
|
|
6
168
|
const prompts = [];
|
|
7
169
|
|
|
@@ -76,35 +238,6 @@ function createPrompts(projectInfo, options = {}) {
|
|
|
76
238
|
}
|
|
77
239
|
});
|
|
78
240
|
|
|
79
|
-
// Features selection
|
|
80
|
-
prompts.push({
|
|
81
|
-
type: 'checkbox',
|
|
82
|
-
name: 'features',
|
|
83
|
-
message: 'Select additional features:',
|
|
84
|
-
choices: [
|
|
85
|
-
{
|
|
86
|
-
value: 'git-hooks',
|
|
87
|
-
name: 'Git hooks integration',
|
|
88
|
-
checked: false
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
value: 'testing',
|
|
92
|
-
name: 'Enhanced testing commands',
|
|
93
|
-
checked: true
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
value: 'linting',
|
|
97
|
-
name: 'Code linting and formatting',
|
|
98
|
-
checked: true
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
value: 'debugging',
|
|
102
|
-
name: 'Debugging helpers',
|
|
103
|
-
checked: false
|
|
104
|
-
}
|
|
105
|
-
],
|
|
106
|
-
prefix: chalk.yellow('⚙️')
|
|
107
|
-
});
|
|
108
241
|
|
|
109
242
|
// Confirmation
|
|
110
243
|
prompts.push({
|
|
@@ -152,5 +285,6 @@ function createProjectTypePrompt(detectedTypes) {
|
|
|
152
285
|
|
|
153
286
|
module.exports = {
|
|
154
287
|
createPrompts,
|
|
155
|
-
createProjectTypePrompt
|
|
288
|
+
createProjectTypePrompt,
|
|
289
|
+
interactivePrompts
|
|
156
290
|
};
|
package/src/templates.js
CHANGED
|
@@ -15,7 +15,8 @@ const TEMPLATES_CONFIG = {
|
|
|
15
15
|
description: 'Optimized for modern JS/TS development',
|
|
16
16
|
files: [
|
|
17
17
|
{ source: 'javascript-typescript/CLAUDE.md', destination: 'CLAUDE.md' },
|
|
18
|
-
{ source: 'javascript-typescript/.claude', destination: '.claude' }
|
|
18
|
+
{ source: 'javascript-typescript/.claude', destination: '.claude' },
|
|
19
|
+
{ source: 'javascript-typescript/.mcp.json', destination: '.mcp.json' }
|
|
19
20
|
],
|
|
20
21
|
frameworks: {
|
|
21
22
|
'react': {
|
|
@@ -26,11 +27,15 @@ const TEMPLATES_CONFIG = {
|
|
|
26
27
|
},
|
|
27
28
|
'vue': {
|
|
28
29
|
name: 'Vue.js',
|
|
29
|
-
additionalFiles: [
|
|
30
|
+
additionalFiles: [
|
|
31
|
+
{ source: 'javascript-typescript/examples/vue-app/.claude/commands', destination: '.claude/commands' }
|
|
32
|
+
]
|
|
30
33
|
},
|
|
31
34
|
'angular': {
|
|
32
35
|
name: 'Angular',
|
|
33
|
-
additionalFiles: [
|
|
36
|
+
additionalFiles: [
|
|
37
|
+
{ source: 'javascript-typescript/examples/angular-app/.claude/commands', destination: '.claude/commands' }
|
|
38
|
+
]
|
|
34
39
|
},
|
|
35
40
|
'node': {
|
|
36
41
|
name: 'Node.js',
|
|
@@ -42,25 +47,12 @@ const TEMPLATES_CONFIG = {
|
|
|
42
47
|
},
|
|
43
48
|
'python': {
|
|
44
49
|
name: 'Python',
|
|
45
|
-
description: '
|
|
50
|
+
description: 'Configuration for Python projects (Coming Soon)',
|
|
46
51
|
files: [
|
|
47
|
-
{ source: '
|
|
48
|
-
{ source: '
|
|
52
|
+
{ source: 'common/CLAUDE.md', destination: 'CLAUDE.md' },
|
|
53
|
+
{ source: 'common/.claude', destination: '.claude' }
|
|
49
54
|
],
|
|
50
|
-
|
|
51
|
-
'django': {
|
|
52
|
-
name: 'Django',
|
|
53
|
-
additionalFiles: []
|
|
54
|
-
},
|
|
55
|
-
'flask': {
|
|
56
|
-
name: 'Flask',
|
|
57
|
-
additionalFiles: []
|
|
58
|
-
},
|
|
59
|
-
'fastapi': {
|
|
60
|
-
name: 'FastAPI',
|
|
61
|
-
additionalFiles: []
|
|
62
|
-
}
|
|
63
|
-
}
|
|
55
|
+
comingSoon: true
|
|
64
56
|
},
|
|
65
57
|
'rust': {
|
|
66
58
|
name: 'Rust',
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Go Claude Code Templates
|
|
2
|
+
|
|
3
|
+
## Coming Soon! 🚧
|
|
4
|
+
|
|
5
|
+
We're actively working on creating comprehensive Claude Code templates for Go development.
|
|
6
|
+
|
|
7
|
+
### What to Expect
|
|
8
|
+
- Best practices for Go project structure
|
|
9
|
+
- Integration with popular Go tools and frameworks
|
|
10
|
+
- Workflow optimizations for Go development
|
|
11
|
+
- Testing and benchmarking configurations
|
|
12
|
+
- Deployment and build automation
|
|
13
|
+
|
|
14
|
+
### Meanwhile...
|
|
15
|
+
You can use the [common templates](../common/README.md) as a starting point for your Go projects. The universal guidelines and git workflows will work well with Go development.
|
|
16
|
+
|
|
17
|
+
### Stay Updated
|
|
18
|
+
⭐ Star this repository to get notified when the Go templates are released!
|
|
19
|
+
|
|
20
|
+
### Contributing
|
|
21
|
+
Interested in helping build these templates? We welcome contributions! Please check the main repository's contribution guidelines and feel free to open an issue or pull request.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
*Expected release: Coming soon*
|