claude-code-templates 1.12.0 → 1.12.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 +33 -26
- package/package.json +1 -1
- package/src/agents.js +262 -0
- package/src/command-scanner.js +5 -5
- package/src/index.js +13 -6
- package/src/prompts.js +40 -3
- package/src/templates.js +1 -4
- package/templates/javascript-typescript/examples/react-app/agents/react-performance-optimization.md +530 -0
- package/templates/javascript-typescript/examples/react-app/agents/react-state-management.md +295 -0
- package/templates/python/examples/django-app/agents/django-api-security.md +642 -0
- package/templates/python/examples/django-app/agents/django-database-optimization.md +752 -0
|
@@ -5,32 +5,39 @@ const chalk = require('chalk');
|
|
|
5
5
|
const boxen = require('boxen');
|
|
6
6
|
const { createClaudeConfig } = require('../src/index');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.log(
|
|
8
|
+
const pkg = require('../package.json');
|
|
9
|
+
|
|
10
|
+
const title = 'Claude Code Templates';
|
|
11
|
+
const subtitle = 'Your starting point for Claude Code projects';
|
|
12
|
+
|
|
13
|
+
const colorGradient = ['#EA580C', '#F97316', '#FB923C', '#FDBA74', '#FED7AA', '#FFEBD6'];
|
|
14
|
+
|
|
15
|
+
function colorizeTitle(text) {
|
|
16
|
+
const chars = text.split('');
|
|
17
|
+
const steps = colorGradient.length;
|
|
18
|
+
return chars
|
|
19
|
+
.map((char, i) => {
|
|
20
|
+
const color = colorGradient[i % steps];
|
|
21
|
+
return chalk.hex(color)(char);
|
|
22
|
+
})
|
|
23
|
+
.join('');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.clear();
|
|
27
|
+
console.log(chalk.hex('#F97316')('════════════════════════════════════════════════════════════════'));
|
|
28
|
+
console.log('\n');
|
|
29
|
+
console.log(' 🔮 ' + colorizeTitle(title));
|
|
30
|
+
console.log('\n');
|
|
31
|
+
console.log(' ' + chalk.hex('#FDBA74')(subtitle));
|
|
32
|
+
console.log('\n');
|
|
33
|
+
console.log(chalk.hex('#F97316')('════════════════════════════════════════════════════════════════\n'));
|
|
34
|
+
|
|
35
|
+
console.log(
|
|
36
|
+
chalk.hex('#D97706')('🚀 Setup Claude Code for any project language 🚀') +
|
|
37
|
+
chalk.gray(`\n v${pkg.version}\n\n`) +
|
|
38
|
+
chalk.blue('🌐 Templates: ') + chalk.underline('https://davila7.github.io/claude-code-templates/') + '\n' +
|
|
39
|
+
chalk.blue('📖 Documentation: ') + chalk.underline('https://davila7.github.io/claude-code-templates/docu/')
|
|
40
|
+
);
|
|
34
41
|
|
|
35
42
|
program
|
|
36
43
|
.name('create-claude-config')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-templates",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.2",
|
|
4
4
|
"description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/agents.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get all available agents from the templates directory structure
|
|
9
|
+
* @returns {Array} Array of agent objects with name, description, and color
|
|
10
|
+
*/
|
|
11
|
+
function getAvailableAgents() {
|
|
12
|
+
const agents = [];
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
// Scan all language directories
|
|
16
|
+
const languageDirs = fs.readdirSync(TEMPLATES_DIR)
|
|
17
|
+
.filter(dir => {
|
|
18
|
+
const dirPath = path.join(TEMPLATES_DIR, dir);
|
|
19
|
+
return fs.statSync(dirPath).isDirectory() && dir !== 'common';
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
for (const langDir of languageDirs) {
|
|
23
|
+
const frameworksPath = path.join(TEMPLATES_DIR, langDir, 'examples');
|
|
24
|
+
|
|
25
|
+
if (fs.existsSync(frameworksPath)) {
|
|
26
|
+
const frameworks = fs.readdirSync(frameworksPath)
|
|
27
|
+
.filter(dir => {
|
|
28
|
+
const dirPath = path.join(frameworksPath, dir);
|
|
29
|
+
return fs.statSync(dirPath).isDirectory();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
for (const framework of frameworks) {
|
|
33
|
+
const agentsPath = path.join(frameworksPath, framework, 'agents');
|
|
34
|
+
|
|
35
|
+
if (fs.existsSync(agentsPath)) {
|
|
36
|
+
const agentFiles = fs.readdirSync(agentsPath)
|
|
37
|
+
.filter(file => file.endsWith('.md'));
|
|
38
|
+
|
|
39
|
+
for (const file of agentFiles) {
|
|
40
|
+
const filePath = path.join(agentsPath, file);
|
|
41
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
42
|
+
const agent = parseAgentFile(content, file);
|
|
43
|
+
|
|
44
|
+
if (agent) {
|
|
45
|
+
agent.language = langDir;
|
|
46
|
+
agent.framework = framework;
|
|
47
|
+
agent.filePath = filePath;
|
|
48
|
+
agents.push(agent);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return agents;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.log(chalk.yellow('⚠️ No agents templates found'));
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Parse agent markdown file to extract frontmatter
|
|
65
|
+
* @param {string} content - File content
|
|
66
|
+
* @param {string} filename - File name
|
|
67
|
+
* @returns {Object|null} Agent object or null if parsing fails
|
|
68
|
+
*/
|
|
69
|
+
function parseAgentFile(content, filename) {
|
|
70
|
+
try {
|
|
71
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
72
|
+
if (!frontmatterMatch) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const frontmatter = frontmatterMatch[1];
|
|
77
|
+
const lines = frontmatter.split('\n');
|
|
78
|
+
const agent = { filename };
|
|
79
|
+
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
const [key, ...valueParts] = line.split(':');
|
|
82
|
+
if (key && valueParts.length > 0) {
|
|
83
|
+
const value = valueParts.join(':').trim();
|
|
84
|
+
agent[key.trim()] = value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Extract description without examples for display
|
|
89
|
+
if (agent.description) {
|
|
90
|
+
const shortDesc = agent.description.split('Examples:')[0].trim();
|
|
91
|
+
agent.shortDescription = shortDesc;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return agent;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.log(chalk.yellow(`⚠️ Failed to parse agent file: ${filename}`));
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get agents that are relevant for a specific language/framework
|
|
103
|
+
* @param {string} language - Programming language
|
|
104
|
+
* @param {string} framework - Framework (optional)
|
|
105
|
+
* @returns {Array} Array of relevant agents
|
|
106
|
+
*/
|
|
107
|
+
function getAgentsForLanguageAndFramework(language, framework) {
|
|
108
|
+
const allAgents = getAvailableAgents();
|
|
109
|
+
|
|
110
|
+
// Filter agents based on language and framework
|
|
111
|
+
return allAgents.filter(agent => {
|
|
112
|
+
// First check exact language match
|
|
113
|
+
if (agent.language !== language) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// If framework is specified and not 'none', check framework match
|
|
118
|
+
if (framework && framework !== 'none') {
|
|
119
|
+
// Extract framework name from framework path (e.g., 'react-app' -> 'react')
|
|
120
|
+
const frameworkName = framework.includes('-') ? framework.split('-')[0] : framework;
|
|
121
|
+
const agentFrameworkName = agent.framework.includes('-') ? agent.framework.split('-')[0] : agent.framework;
|
|
122
|
+
|
|
123
|
+
return agentFrameworkName.toLowerCase().includes(frameworkName.toLowerCase());
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// If no specific framework, return all agents for this language
|
|
127
|
+
return true;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Install selected agents to the project's .claude/agents directory
|
|
133
|
+
* @param {Array} selectedAgents - Array of agent names to install
|
|
134
|
+
* @param {string} projectPath - Project directory path
|
|
135
|
+
* @returns {Promise<boolean>} Success status
|
|
136
|
+
*/
|
|
137
|
+
async function installAgents(selectedAgents, projectPath = process.cwd()) {
|
|
138
|
+
try {
|
|
139
|
+
const claudeDir = path.join(projectPath, '.claude');
|
|
140
|
+
const agentsDir = path.join(claudeDir, 'agents');
|
|
141
|
+
|
|
142
|
+
// Create .claude/agents directory if it doesn't exist
|
|
143
|
+
await fs.ensureDir(agentsDir);
|
|
144
|
+
|
|
145
|
+
let installedCount = 0;
|
|
146
|
+
const allAgents = getAvailableAgents();
|
|
147
|
+
|
|
148
|
+
for (const agentName of selectedAgents) {
|
|
149
|
+
// Find the agent by name in the available agents
|
|
150
|
+
const agent = allAgents.find(a => a.name === agentName);
|
|
151
|
+
|
|
152
|
+
if (agent && agent.filePath) {
|
|
153
|
+
const targetFile = path.join(agentsDir, `${agentName}.md`);
|
|
154
|
+
|
|
155
|
+
if (await fs.pathExists(agent.filePath)) {
|
|
156
|
+
await fs.copy(agent.filePath, targetFile);
|
|
157
|
+
installedCount++;
|
|
158
|
+
console.log(chalk.green(`✓ Installed agent: ${agentName} (${agent.language}/${agent.framework})`));
|
|
159
|
+
} else {
|
|
160
|
+
console.log(chalk.yellow(`⚠️ Agent source file not found: ${agent.filePath}`));
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
console.log(chalk.yellow(`⚠️ Agent not found: ${agentName}`));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (installedCount > 0) {
|
|
168
|
+
console.log(chalk.green(`\n🎉 Successfully installed ${installedCount} agent(s) to .claude/agents/`));
|
|
169
|
+
console.log(chalk.blue(' You can now use these agents in your Claude Code conversations!'));
|
|
170
|
+
return true;
|
|
171
|
+
} else {
|
|
172
|
+
console.log(chalk.yellow('⚠️ No agents were installed'));
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error(chalk.red('❌ Failed to install agents:'), error.message);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Check if project already has agents installed
|
|
184
|
+
* @param {string} projectPath - Project directory path
|
|
185
|
+
* @returns {Promise<Array>} Array of installed agent names
|
|
186
|
+
*/
|
|
187
|
+
async function getInstalledAgents(projectPath = process.cwd()) {
|
|
188
|
+
try {
|
|
189
|
+
const agentsDir = path.join(projectPath, '.claude', 'agents');
|
|
190
|
+
|
|
191
|
+
if (!(await fs.pathExists(agentsDir))) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const agentFiles = await fs.readdir(agentsDir);
|
|
196
|
+
return agentFiles
|
|
197
|
+
.filter(file => file.endsWith('.md'))
|
|
198
|
+
.map(file => path.basename(file, '.md'));
|
|
199
|
+
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Format agent choices for inquirer prompt
|
|
207
|
+
* @param {Array} agents - Array of agent objects
|
|
208
|
+
* @param {Array} installedAgents - Array of already installed agent names
|
|
209
|
+
* @returns {Array} Formatted choices for inquirer
|
|
210
|
+
*/
|
|
211
|
+
function formatAgentChoices(agents, installedAgents = []) {
|
|
212
|
+
return agents.map(agent => {
|
|
213
|
+
const isInstalled = installedAgents.includes(agent.name);
|
|
214
|
+
const colorFn = getColorFunction(agent.color);
|
|
215
|
+
|
|
216
|
+
const name = isInstalled
|
|
217
|
+
? `${colorFn(agent.name)} ${chalk.dim('(already installed)')}`
|
|
218
|
+
: colorFn(agent.name);
|
|
219
|
+
|
|
220
|
+
const description = agent.shortDescription || agent.description || 'No description available';
|
|
221
|
+
// Truncate description if too long
|
|
222
|
+
const truncatedDesc = description.length > 80
|
|
223
|
+
? description.substring(0, 80) + '...'
|
|
224
|
+
: description;
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
name: `${name}\n ${chalk.dim(truncatedDesc)}`,
|
|
228
|
+
value: agent.name,
|
|
229
|
+
short: agent.name,
|
|
230
|
+
disabled: isInstalled ? 'Already installed' : false
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get chalk color function based on color name
|
|
237
|
+
* @param {string} colorName - Color name
|
|
238
|
+
* @returns {Function} Chalk color function
|
|
239
|
+
*/
|
|
240
|
+
function getColorFunction(colorName) {
|
|
241
|
+
const colorMap = {
|
|
242
|
+
red: chalk.red,
|
|
243
|
+
green: chalk.green,
|
|
244
|
+
yellow: chalk.yellow,
|
|
245
|
+
blue: chalk.blue,
|
|
246
|
+
magenta: chalk.magenta,
|
|
247
|
+
cyan: chalk.cyan,
|
|
248
|
+
white: chalk.white,
|
|
249
|
+
gray: chalk.gray,
|
|
250
|
+
grey: chalk.gray
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
return colorMap[colorName] || chalk.white;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = {
|
|
257
|
+
getAvailableAgents,
|
|
258
|
+
getAgentsForLanguageAndFramework,
|
|
259
|
+
installAgents,
|
|
260
|
+
getInstalledAgents,
|
|
261
|
+
formatAgentChoices
|
|
262
|
+
};
|
package/src/command-scanner.js
CHANGED
|
@@ -25,14 +25,14 @@ function getAvailableCommands(language) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Scan framework-specific commands in examples
|
|
28
|
-
const
|
|
29
|
-
if (fs.existsSync(
|
|
30
|
-
const frameworkDirs = fs.readdirSync(
|
|
31
|
-
return fs.statSync(path.join(
|
|
28
|
+
const frameworksDir = path.join(languageDir, 'examples');
|
|
29
|
+
if (fs.existsSync(frameworksDir)) {
|
|
30
|
+
const frameworkDirs = fs.readdirSync(frameworksDir).filter(dir => {
|
|
31
|
+
return fs.statSync(path.join(frameworksDir, dir)).isDirectory();
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
frameworkDirs.forEach(framework => {
|
|
35
|
-
const frameworkCommandsDir = path.join(
|
|
35
|
+
const frameworkCommandsDir = path.join(frameworksDir, framework, '.claude', 'commands');
|
|
36
36
|
if (fs.existsSync(frameworkCommandsDir)) {
|
|
37
37
|
const frameworkCommands = scanCommandsInDirectory(frameworkCommandsDir, framework);
|
|
38
38
|
commands.push(...frameworkCommands);
|
package/src/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const { getTemplateConfig, TEMPLATES_CONFIG } = require('./templates');
|
|
|
8
8
|
const { createPrompts, interactivePrompts } = require('./prompts');
|
|
9
9
|
const { copyTemplateFiles, runPostInstallationValidation } = require('./file-operations');
|
|
10
10
|
const { getHooksForLanguage, getMCPsForLanguage } = require('./hook-scanner');
|
|
11
|
+
const { installAgents } = require('./agents');
|
|
11
12
|
const { runCommandStats } = require('./command-stats');
|
|
12
13
|
const { runHookStats } = require('./hook-stats');
|
|
13
14
|
const { runMCPStats } = require('./mcp-stats');
|
|
@@ -15,7 +16,6 @@ const { runAnalytics } = require('./analytics');
|
|
|
15
16
|
const { runHealthCheck } = require('./health-check');
|
|
16
17
|
|
|
17
18
|
async function showMainMenu() {
|
|
18
|
-
console.log(chalk.blue('🚀 Welcome to Claude Code Templates!'));
|
|
19
19
|
console.log('');
|
|
20
20
|
|
|
21
21
|
const initialChoice = await inquirer.prompt([{
|
|
@@ -33,15 +33,15 @@ async function showMainMenu() {
|
|
|
33
33
|
value: 'chats',
|
|
34
34
|
short: 'Chats Dashboard'
|
|
35
35
|
},
|
|
36
|
-
{
|
|
37
|
-
name: '🔍 Health Check - Verify your Claude Code setup and configuration',
|
|
38
|
-
value: 'health',
|
|
39
|
-
short: 'Health Check'
|
|
40
|
-
},
|
|
41
36
|
{
|
|
42
37
|
name: '⚙️ Project Setup - Configure Claude Code for your project',
|
|
43
38
|
value: 'setup',
|
|
44
39
|
short: 'Project Setup'
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: '🔍 Health Check - Verify your Claude Code setup and configuration',
|
|
43
|
+
value: 'health',
|
|
44
|
+
short: 'Health Check'
|
|
45
45
|
}
|
|
46
46
|
],
|
|
47
47
|
default: 'analytics'
|
|
@@ -193,6 +193,12 @@ async function createClaudeConfig(options = {}) {
|
|
|
193
193
|
templateConfig.language = config.language; // Ensure language is available for MCP filtering
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
// Install selected agents
|
|
197
|
+
if (config.agents && config.agents.length > 0) {
|
|
198
|
+
console.log(chalk.blue('🤖 Installing Claude Code agents...'));
|
|
199
|
+
await installAgents(config.agents, targetDir);
|
|
200
|
+
}
|
|
201
|
+
|
|
196
202
|
if (options.dryRun) {
|
|
197
203
|
console.log(chalk.yellow('🔍 Dry run - showing what would be copied:'));
|
|
198
204
|
templateConfig.files.forEach(file => {
|
|
@@ -223,6 +229,7 @@ async function createClaudeConfig(options = {}) {
|
|
|
223
229
|
console.log(chalk.white(' 3. Start using Claude Code with: claude'));
|
|
224
230
|
console.log('');
|
|
225
231
|
console.log(chalk.blue('🌐 View all available templates at: https://davila7.github.io/claude-code-templates/'));
|
|
232
|
+
console.log(chalk.blue('📖 Read the complete documentation at: https://davila7.github.io/claude-code-templates/docu/'));
|
|
226
233
|
|
|
227
234
|
if (config.language !== 'common') {
|
|
228
235
|
console.log(chalk.yellow(`💡 Language-specific features for ${config.language} have been configured`));
|
package/src/prompts.js
CHANGED
|
@@ -6,6 +6,7 @@ const inquirer = require('inquirer');
|
|
|
6
6
|
const { getAvailableLanguages, getFrameworksForLanguage } = require('./templates');
|
|
7
7
|
const { getCommandsForLanguageAndFramework } = require('./command-scanner');
|
|
8
8
|
const { getHooksForLanguage, getMCPsForLanguage } = require('./hook-scanner');
|
|
9
|
+
const { getAgentsForLanguageAndFramework, getInstalledAgents, formatAgentChoices } = require('./agents');
|
|
9
10
|
|
|
10
11
|
async function interactivePrompts(projectInfo, options = {}) {
|
|
11
12
|
const state = {
|
|
@@ -17,7 +18,7 @@ async function interactivePrompts(projectInfo, options = {}) {
|
|
|
17
18
|
// Build steps array based on options
|
|
18
19
|
if (!options.language) state.steps.push('language');
|
|
19
20
|
if (!options.framework) state.steps.push('framework');
|
|
20
|
-
state.steps.push('commands', 'hooks', 'mcps', 'analytics', 'confirm');
|
|
21
|
+
state.steps.push('commands', 'hooks', 'mcps', 'agents', 'analytics', 'confirm');
|
|
21
22
|
|
|
22
23
|
while (state.currentStep < state.steps.length) {
|
|
23
24
|
const stepName = state.steps[state.currentStep];
|
|
@@ -41,7 +42,13 @@ async function interactivePrompts(projectInfo, options = {}) {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
async function showStep(stepName, currentAnswers, projectInfo, options) {
|
|
44
|
-
|
|
45
|
+
// Handle async data fetching for agents step
|
|
46
|
+
let additionalData = {};
|
|
47
|
+
if (stepName === 'agents') {
|
|
48
|
+
additionalData.installedAgents = await getInstalledAgents();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const stepConfig = getStepConfig(stepName, currentAnswers, projectInfo, options, additionalData);
|
|
45
52
|
|
|
46
53
|
if (!stepConfig) {
|
|
47
54
|
return { action: 'next', value: null };
|
|
@@ -69,7 +76,7 @@ async function showStep(stepName, currentAnswers, projectInfo, options) {
|
|
|
69
76
|
return { action: 'next', value };
|
|
70
77
|
}
|
|
71
78
|
|
|
72
|
-
function getStepConfig(stepName, currentAnswers, projectInfo, options) {
|
|
79
|
+
function getStepConfig(stepName, currentAnswers, projectInfo, options, additionalData = {}) {
|
|
73
80
|
switch (stepName) {
|
|
74
81
|
case 'language':
|
|
75
82
|
return {
|
|
@@ -188,6 +195,32 @@ function getStepConfig(stepName, currentAnswers, projectInfo, options) {
|
|
|
188
195
|
pageSize: 15
|
|
189
196
|
};
|
|
190
197
|
|
|
198
|
+
case 'agents':
|
|
199
|
+
const agentLanguage = currentAnswers.language || options.language;
|
|
200
|
+
const agentFramework = currentAnswers.framework || options.framework;
|
|
201
|
+
|
|
202
|
+
if (!agentLanguage) {
|
|
203
|
+
return null; // Skip if no language selected
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const availableAgents = getAgentsForLanguageAndFramework(agentLanguage, agentFramework);
|
|
207
|
+
|
|
208
|
+
if (availableAgents.length === 0) {
|
|
209
|
+
return null; // Skip if no agents available
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const installedAgents = additionalData.installedAgents || [];
|
|
213
|
+
const agentChoices = formatAgentChoices(availableAgents, installedAgents);
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
type: 'checkbox',
|
|
217
|
+
name: 'agents',
|
|
218
|
+
message: 'Select Claude Code agents to install (use space to select):',
|
|
219
|
+
choices: agentChoices,
|
|
220
|
+
prefix: chalk.magenta('🤖'),
|
|
221
|
+
pageSize: 10
|
|
222
|
+
};
|
|
223
|
+
|
|
191
224
|
case 'analytics':
|
|
192
225
|
return {
|
|
193
226
|
type: 'confirm',
|
|
@@ -203,6 +236,7 @@ function getStepConfig(stepName, currentAnswers, projectInfo, options) {
|
|
|
203
236
|
const commandCount = currentAnswers.commands ? currentAnswers.commands.length : 0;
|
|
204
237
|
const hookCount = currentAnswers.hooks ? currentAnswers.hooks.length : 0;
|
|
205
238
|
const mcpCount = currentAnswers.mcps ? currentAnswers.mcps.length : 0;
|
|
239
|
+
const agentCount = currentAnswers.agents ? currentAnswers.agents.length : 0;
|
|
206
240
|
|
|
207
241
|
let message = `Setup Claude Code for ${chalk.cyan(confirmLanguage)}`;
|
|
208
242
|
if (confirmFramework !== 'none') {
|
|
@@ -217,6 +251,9 @@ function getStepConfig(stepName, currentAnswers, projectInfo, options) {
|
|
|
217
251
|
if (mcpCount > 0) {
|
|
218
252
|
message += ` (${chalk.blue(mcpCount)} MCP)`;
|
|
219
253
|
}
|
|
254
|
+
if (agentCount > 0) {
|
|
255
|
+
message += ` (${chalk.magenta(agentCount)} agents)`;
|
|
256
|
+
}
|
|
220
257
|
message += '?';
|
|
221
258
|
|
|
222
259
|
return {
|
package/src/templates.js
CHANGED
|
@@ -6,10 +6,7 @@ const TEMPLATES_CONFIG = {
|
|
|
6
6
|
name: 'Common (Language-agnostic)',
|
|
7
7
|
description: 'Universal configuration for any project',
|
|
8
8
|
files: [
|
|
9
|
-
{ source: 'common/CLAUDE.md', destination: 'CLAUDE.md' }
|
|
10
|
-
{ source: 'common/.claude', destination: '.claude' },
|
|
11
|
-
{ source: 'common/.claude/settings.json', destination: '.claude/settings.json' },
|
|
12
|
-
{ source: 'common/.mcp.json', destination: '.mcp.json' }
|
|
9
|
+
{ source: 'common/CLAUDE.md', destination: 'CLAUDE.md' }
|
|
13
10
|
]
|
|
14
11
|
},
|
|
15
12
|
'javascript-typescript': {
|