@wundr.io/cli 1.0.1 ā 1.0.2-dev.20260530174250.ef0ec927
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/wundr.js +13 -5
- package/package.json +30 -9
- package/src/ai/ai-service.ts +6 -4
- package/src/ai/claude-client.ts +6 -2
- package/src/ai/conversation-manager.ts +12 -5
- package/src/cli.ts +42 -13
- package/src/commands/ai.ts +340 -64
- package/src/commands/alignment.ts +1212 -0
- package/src/commands/analyze-optimized.ts +371 -33
- package/src/commands/analyze.ts +8 -6
- package/src/commands/batch.ts +166 -26
- package/src/commands/chat.ts +20 -10
- package/src/commands/claude-init.ts +31 -27
- package/src/commands/claude-setup.ts +761 -81
- package/src/commands/computer-setup.ts +524 -12
- package/src/commands/create-command.ts +3 -3
- package/src/commands/create.ts +9 -6
- package/src/commands/dashboard.ts +11 -6
- package/src/commands/govern.ts +11 -6
- package/src/commands/governance.ts +1005 -0
- package/src/commands/guardian.ts +887 -0
- package/src/commands/init.ts +104 -11
- package/src/commands/orchestrator.ts +789 -0
- package/src/commands/performance-optimizer.ts +15 -10
- package/src/commands/plugins.ts +8 -5
- package/src/commands/project-update.ts +1156 -0
- package/src/commands/rag.ts +1011 -0
- package/src/commands/session.ts +631 -0
- package/src/commands/setup.ts +42 -344
- package/src/commands/test-init.ts +3 -2
- package/src/commands/test.ts +3 -2
- package/src/commands/watch.ts +21 -11
- package/src/commands/worktree.ts +1057 -0
- package/src/context/context-manager.ts +5 -2
- package/src/context/session-manager.ts +18 -7
- package/src/framework/command-interface.ts +520 -0
- package/src/framework/command-registry.ts +942 -0
- package/src/framework/completion-exporter.ts +383 -0
- package/src/framework/debug-logger.ts +519 -0
- package/src/framework/error-handler.ts +867 -0
- package/src/framework/help-generator.ts +540 -0
- package/src/framework/index.ts +169 -0
- package/src/framework/interactive-repl.ts +703 -0
- package/src/framework/output-formatter.ts +834 -0
- package/src/framework/progress-manager.ts +539 -0
- package/src/index.ts +3 -2
- package/src/interactive/interactive-mode.ts +14 -7
- package/src/lib/conflict-resolution.ts +818 -0
- package/src/lib/merge-strategy.ts +550 -0
- package/src/lib/safety-mechanisms.ts +451 -0
- package/src/lib/state-detection.ts +1030 -0
- package/src/nlp/command-mapper.ts +8 -3
- package/src/nlp/command-parser.ts +5 -2
- package/src/nlp/intent-parser.ts +23 -9
- package/src/plugins/plugin-manager.ts +50 -24
- package/src/tests/computer-setup-integration.test.ts +46 -15
- package/src/types/index.ts +1 -1
- package/src/types/modules.d.ts +425 -1
- package/src/utils/backup-rollback-manager.ts +19 -14
- package/src/utils/claude-config-installer.ts +119 -28
- package/src/utils/config-manager.ts +9 -6
- package/src/utils/error-handler.ts +3 -1
- package/src/utils/logger.ts +35 -12
- package/templates/batch/ci-cd.yaml +7 -7
- package/test-suites/api/health.spec.ts +20 -23
- package/test-suites/helpers/test-config.ts +14 -13
- package/test-suites/ui/accessibility.spec.ts +27 -22
- package/test-suites/ui/smoke.spec.ts +26 -21
- package/src/commands/computer-setup-commands.ts +0 -869
|
@@ -1,13 +1,53 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import ora from 'ora';
|
|
4
1
|
import { execSync, spawn } from 'child_process';
|
|
5
|
-
import * as path from 'path';
|
|
6
2
|
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
|
|
9
|
+
import type { Ora } from 'ora';
|
|
10
|
+
|
|
11
|
+
// Type for ora spinner
|
|
12
|
+
type OraSpinner = Ora;
|
|
13
|
+
|
|
14
|
+
// Type definitions
|
|
15
|
+
interface SetupOptions {
|
|
16
|
+
global?: boolean;
|
|
17
|
+
skipMcp?: boolean;
|
|
18
|
+
skipFlow?: boolean;
|
|
19
|
+
skipChrome?: boolean;
|
|
20
|
+
skipAgents?: boolean;
|
|
21
|
+
template?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface McpOptions {
|
|
25
|
+
tool?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface AgentOptions {
|
|
29
|
+
list?: boolean;
|
|
30
|
+
enable?: string;
|
|
31
|
+
profile?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface ValidateOptions {
|
|
35
|
+
fix?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface OptimizeOptions {
|
|
39
|
+
force?: boolean;
|
|
40
|
+
}
|
|
7
41
|
|
|
8
42
|
/**
|
|
9
43
|
* Claude Setup Commands
|
|
10
|
-
* Comprehensive setup for Claude Code,
|
|
44
|
+
* Comprehensive setup for Claude Code, Ruflo, and MCP tools
|
|
45
|
+
*
|
|
46
|
+
* Consolidated from:
|
|
47
|
+
* - /src/cli/commands/claude-setup.ts (374 lines) - function-based approach
|
|
48
|
+
* - /packages/@wundr/cli/src/commands/claude-setup.ts (697 lines) - class-based approach
|
|
49
|
+
*
|
|
50
|
+
* This version preserves ALL functionality from both implementations.
|
|
11
51
|
*/
|
|
12
52
|
export class ClaudeSetupCommands {
|
|
13
53
|
constructor(private program: Command) {
|
|
@@ -18,50 +58,71 @@ export class ClaudeSetupCommands {
|
|
|
18
58
|
const claudeSetup = this.program
|
|
19
59
|
.command('claude-setup')
|
|
20
60
|
.alias('cs')
|
|
21
|
-
.description('Setup Claude Code,
|
|
61
|
+
.description('Setup Claude Code, Ruflo, and MCP tools')
|
|
22
62
|
.addHelpText(
|
|
23
63
|
'after',
|
|
24
64
|
chalk.gray(`
|
|
25
65
|
Examples:
|
|
26
66
|
${chalk.green('wundr claude-setup')} Interactive Claude setup
|
|
67
|
+
${chalk.green('wundr claude-setup install')} Complete ecosystem installation
|
|
27
68
|
${chalk.green('wundr claude-setup mcp')} Install all MCP tools
|
|
28
69
|
${chalk.green('wundr claude-setup agents')} Configure all 54 agents
|
|
29
70
|
${chalk.green('wundr claude-setup optimize')} Setup hardware-adaptive optimizations
|
|
30
71
|
${chalk.green('wundr claude-setup validate')} Validate Claude installation
|
|
72
|
+
${chalk.green('wundr claude-setup project')} Setup project with templates
|
|
31
73
|
`)
|
|
32
74
|
);
|
|
33
75
|
|
|
34
|
-
// Main setup command
|
|
76
|
+
// Main setup command (default)
|
|
35
77
|
claudeSetup
|
|
36
78
|
.command('install', { isDefault: true })
|
|
37
79
|
.description('Complete Claude ecosystem installation')
|
|
38
80
|
.option('--skip-chrome', 'Skip Chrome installation')
|
|
39
81
|
.option('--skip-mcp', 'Skip MCP tools installation')
|
|
40
82
|
.option('--skip-agents', 'Skip agent configuration')
|
|
41
|
-
.
|
|
83
|
+
.option('--skip-flow', 'Skip Ruflo setup')
|
|
84
|
+
.option('-g, --global', 'Install tools globally')
|
|
85
|
+
.action(async (options: SetupOptions) => {
|
|
42
86
|
await this.runCompleteSetup(options);
|
|
43
87
|
});
|
|
44
88
|
|
|
89
|
+
// Project setup with templates (from /src/cli/commands/claude-setup.ts)
|
|
90
|
+
claudeSetup
|
|
91
|
+
.command('project [path]')
|
|
92
|
+
.description(
|
|
93
|
+
'Setup Claude Code in a project directory with optional template'
|
|
94
|
+
)
|
|
95
|
+
.option('-g, --global', 'Install tools globally')
|
|
96
|
+
.option('--skip-mcp', 'Skip MCP tools installation')
|
|
97
|
+
.option('--skip-flow', 'Skip Ruflo setup')
|
|
98
|
+
.option(
|
|
99
|
+
'-t, --template <name>',
|
|
100
|
+
'Use specific project template (typescript, react, nodejs, monorepo)'
|
|
101
|
+
)
|
|
102
|
+
.action(async (projectPath: string = '.', options: SetupOptions) => {
|
|
103
|
+
await this.runProjectSetup(projectPath, options);
|
|
104
|
+
});
|
|
105
|
+
|
|
45
106
|
// MCP tools installation
|
|
46
107
|
claudeSetup
|
|
47
108
|
.command('mcp')
|
|
48
109
|
.description('Install and configure MCP tools')
|
|
49
110
|
.option(
|
|
50
111
|
'--tool <tool>',
|
|
51
|
-
'Install specific tool (firecrawl, context7, playwright, browser, sequentialthinking)'
|
|
112
|
+
'Install specific tool (firecrawl, context7, playwright, browser, sequentialthinking, ruflo)'
|
|
52
113
|
)
|
|
53
|
-
.action(async options => {
|
|
114
|
+
.action(async (options: McpOptions) => {
|
|
54
115
|
await this.installMcpTools(options);
|
|
55
116
|
});
|
|
56
117
|
|
|
57
118
|
// Agent configuration
|
|
58
119
|
claudeSetup
|
|
59
120
|
.command('agents')
|
|
60
|
-
.description('Configure
|
|
121
|
+
.description('Configure Ruflo agents')
|
|
61
122
|
.option('--list', 'List available agents')
|
|
62
123
|
.option('--enable <agents>', 'Enable specific agents (comma-separated)')
|
|
63
124
|
.option('--profile <profile>', 'Use profile-specific agents')
|
|
64
|
-
.action(async options => {
|
|
125
|
+
.action(async (options: AgentOptions) => {
|
|
65
126
|
await this.configureAgents(options);
|
|
66
127
|
});
|
|
67
128
|
|
|
@@ -70,7 +131,7 @@ Examples:
|
|
|
70
131
|
.command('validate')
|
|
71
132
|
.description('Validate Claude installation')
|
|
72
133
|
.option('--fix', 'Attempt to fix issues')
|
|
73
|
-
.action(async options => {
|
|
134
|
+
.action(async (options: ValidateOptions) => {
|
|
74
135
|
await this.validateInstallation(options);
|
|
75
136
|
});
|
|
76
137
|
|
|
@@ -87,12 +148,28 @@ Examples:
|
|
|
87
148
|
.command('optimize')
|
|
88
149
|
.description('Setup hardware-adaptive Claude Code optimizations')
|
|
89
150
|
.option('--force', 'Force reinstallation of optimization scripts')
|
|
90
|
-
.action(async options => {
|
|
151
|
+
.action(async (options: OptimizeOptions) => {
|
|
91
152
|
await this.setupOptimizations(options);
|
|
92
153
|
});
|
|
154
|
+
|
|
155
|
+
// Generate CLAUDE.md
|
|
156
|
+
claudeSetup
|
|
157
|
+
.command('config')
|
|
158
|
+
.description('Generate or update CLAUDE.md configuration')
|
|
159
|
+
.argument(
|
|
160
|
+
'[path]',
|
|
161
|
+
'Path to repository (defaults to current directory)',
|
|
162
|
+
'.'
|
|
163
|
+
)
|
|
164
|
+
.action(async (repoPath: string) => {
|
|
165
|
+
await this.generateClaudeConfig(repoPath);
|
|
166
|
+
});
|
|
93
167
|
}
|
|
94
168
|
|
|
95
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Complete setup - combines both implementations' main flows
|
|
171
|
+
*/
|
|
172
|
+
private async runCompleteSetup(options: SetupOptions): Promise<void> {
|
|
96
173
|
const spinner = ora();
|
|
97
174
|
console.log(chalk.cyan.bold('\nš¤ Claude Ecosystem Setup\n'));
|
|
98
175
|
|
|
@@ -113,19 +190,24 @@ Examples:
|
|
|
113
190
|
spinner.succeed('Chrome installed');
|
|
114
191
|
}
|
|
115
192
|
|
|
116
|
-
// Step 3:
|
|
193
|
+
// Step 3: Ruflo setup
|
|
194
|
+
if (!options.skipFlow) {
|
|
195
|
+
await this.setupRuflo(spinner, process.cwd(), options.global);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Step 4: Install MCP tools (if not skipped)
|
|
117
199
|
if (!options.skipMcp) {
|
|
118
200
|
await this.installMcpTools({});
|
|
119
201
|
}
|
|
120
202
|
|
|
121
|
-
// Step
|
|
203
|
+
// Step 5: Configure agents (if not skipped)
|
|
122
204
|
if (!options.skipAgents) {
|
|
123
205
|
await this.configureAgents({ profile: 'fullstack' });
|
|
124
206
|
}
|
|
125
207
|
|
|
126
|
-
// Step
|
|
208
|
+
// Step 6: Setup Claude configuration
|
|
127
209
|
spinner.start('Configuring Claude settings...');
|
|
128
|
-
await this.
|
|
210
|
+
await this.setupClaudeSettings();
|
|
129
211
|
spinner.succeed('Claude configured');
|
|
130
212
|
|
|
131
213
|
console.log(chalk.green.bold('\nā
Claude ecosystem setup complete!\n'));
|
|
@@ -137,21 +219,190 @@ Examples:
|
|
|
137
219
|
}
|
|
138
220
|
}
|
|
139
221
|
|
|
140
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Project setup - from /src/cli/commands/claude-setup.ts
|
|
224
|
+
*/
|
|
225
|
+
private async runProjectSetup(
|
|
226
|
+
projectPath: string,
|
|
227
|
+
options: SetupOptions
|
|
228
|
+
): Promise<void> {
|
|
229
|
+
const spinner = ora('Starting Claude Code project setup...').start();
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
const repoPath = path.resolve(projectPath);
|
|
233
|
+
|
|
234
|
+
// Verify git repository
|
|
235
|
+
if (!fs.existsSync(path.join(repoPath, '.git'))) {
|
|
236
|
+
spinner.stop();
|
|
237
|
+
const inquirer = await import('inquirer');
|
|
238
|
+
const { shouldInitGit } = await inquirer.default.prompt([
|
|
239
|
+
{
|
|
240
|
+
type: 'confirm',
|
|
241
|
+
name: 'shouldInitGit',
|
|
242
|
+
message: 'Not a git repository. Initialize git?',
|
|
243
|
+
default: true,
|
|
244
|
+
},
|
|
245
|
+
]);
|
|
246
|
+
|
|
247
|
+
if (shouldInitGit) {
|
|
248
|
+
spinner.start('Initializing git repository...');
|
|
249
|
+
execSync('git init', { cwd: repoPath });
|
|
250
|
+
spinner.succeed('Git repository initialized');
|
|
251
|
+
} else {
|
|
252
|
+
console.log(chalk.yellow('Continuing without git...'));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Step 1: Ruflo setup
|
|
257
|
+
if (!options.skipFlow) {
|
|
258
|
+
await this.setupRuflo(spinner, repoPath, options.global);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Step 2: MCP Tools setup
|
|
262
|
+
if (!options.skipMcp) {
|
|
263
|
+
await this.setupMCPToolsDirectory(spinner, repoPath);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Step 3: Generate CLAUDE.md
|
|
267
|
+
await this.generateClaudeConfigForPath(spinner, repoPath);
|
|
268
|
+
|
|
269
|
+
// Step 4: Setup project template if specified
|
|
270
|
+
if (options.template) {
|
|
271
|
+
await this.setupProjectTemplate(spinner, repoPath, options.template);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Step 5: Initialize swarm if Ruflo is available
|
|
275
|
+
if (!options.skipFlow) {
|
|
276
|
+
await this.initializeSwarm(spinner, repoPath);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Step 6: Validation
|
|
280
|
+
await this.validateProjectSetup(spinner, repoPath);
|
|
281
|
+
|
|
282
|
+
spinner.succeed('Claude Code project setup completed successfully!');
|
|
283
|
+
|
|
284
|
+
// Final instructions
|
|
285
|
+
this.displayProjectFinalInstructions(repoPath, options);
|
|
286
|
+
} catch (error) {
|
|
287
|
+
spinner.stop();
|
|
288
|
+
console.error(chalk.red('ā Setup failed:'));
|
|
289
|
+
console.error(
|
|
290
|
+
chalk.red(error instanceof Error ? error.message : String(error))
|
|
291
|
+
);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Setup Ruflo - from /src/cli/commands/claude-setup.ts
|
|
298
|
+
*/
|
|
299
|
+
private async setupRuflo(
|
|
300
|
+
spinner: OraSpinner,
|
|
301
|
+
repoPath: string,
|
|
302
|
+
global?: boolean
|
|
303
|
+
): Promise<void> {
|
|
304
|
+
spinner.text = 'Setting up Ruflo...';
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
// Check if Ruflo is already installed
|
|
308
|
+
execSync('npx ruflo@latest --version', { stdio: 'ignore' });
|
|
309
|
+
spinner.text = 'Ruflo already available, configuring...';
|
|
310
|
+
} catch {
|
|
311
|
+
spinner.text = 'Installing Ruflo...';
|
|
312
|
+
|
|
313
|
+
if (global) {
|
|
314
|
+
execSync('npm install -g ruflo@latest', { stdio: 'inherit' });
|
|
315
|
+
} else {
|
|
316
|
+
// Add to package.json dev dependencies if it exists
|
|
317
|
+
if (fs.existsSync(path.join(repoPath, 'package.json'))) {
|
|
318
|
+
execSync('npm install --save-dev ruflo@latest', {
|
|
319
|
+
cwd: repoPath,
|
|
320
|
+
stdio: 'inherit',
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Add MCP server configuration
|
|
327
|
+
spinner.text = 'Configuring Claude MCP server...';
|
|
328
|
+
try {
|
|
329
|
+
execSync('claude mcp add ruflo npx ruflo@latest mcp start', {
|
|
330
|
+
cwd: repoPath,
|
|
331
|
+
stdio: 'pipe',
|
|
332
|
+
});
|
|
333
|
+
} catch {
|
|
334
|
+
// MCP configuration might fail if Claude Desktop isn't installed
|
|
335
|
+
console.log(
|
|
336
|
+
chalk.yellow('\nā ļø Could not configure MCP server automatically.')
|
|
337
|
+
);
|
|
338
|
+
console.log(
|
|
339
|
+
chalk.yellow(
|
|
340
|
+
'Please run manually: claude mcp add ruflo npx ruflo@latest mcp start'
|
|
341
|
+
)
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
spinner.text = 'Ruflo setup completed';
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Setup MCP Tools directory - from /src/cli/commands/claude-setup.ts
|
|
350
|
+
*/
|
|
351
|
+
private async setupMCPToolsDirectory(
|
|
352
|
+
spinner: OraSpinner,
|
|
353
|
+
repoPath: string
|
|
354
|
+
): Promise<void> {
|
|
355
|
+
spinner.text = 'Setting up MCP Tools directory...';
|
|
356
|
+
|
|
357
|
+
const mcpToolsPath = path.join(repoPath, 'mcp-tools');
|
|
358
|
+
|
|
359
|
+
// Create mcp-tools directory if it doesn't exist
|
|
360
|
+
if (!fs.existsSync(mcpToolsPath)) {
|
|
361
|
+
fs.mkdirSync(mcpToolsPath, { recursive: true });
|
|
362
|
+
|
|
363
|
+
// Create basic install script
|
|
364
|
+
const installScript = `#!/bin/bash
|
|
365
|
+
# MCP Tools Installation Script
|
|
366
|
+
echo "Installing Wundr MCP Tools..."
|
|
367
|
+
|
|
368
|
+
# Add your MCP tool installations here
|
|
369
|
+
echo "ā
MCP Tools installation template created"
|
|
370
|
+
echo "Customize this script with your specific MCP tools"
|
|
371
|
+
`;
|
|
372
|
+
|
|
373
|
+
fs.writeFileSync(path.join(mcpToolsPath, 'install.sh'), installScript);
|
|
374
|
+
execSync(`chmod +x ${path.join(mcpToolsPath, 'install.sh')}`);
|
|
375
|
+
|
|
376
|
+
// Create package.json for MCP tools
|
|
377
|
+
const mcpPackageJson = {
|
|
378
|
+
name: 'mcp-tools',
|
|
379
|
+
version: '1.0.0',
|
|
380
|
+
description: 'MCP Tools for Claude Code integration',
|
|
381
|
+
private: true,
|
|
382
|
+
scripts: {
|
|
383
|
+
install: './install.sh',
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
fs.writeFileSync(
|
|
388
|
+
path.join(mcpToolsPath, 'package.json'),
|
|
389
|
+
JSON.stringify(mcpPackageJson, null, 2)
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
spinner.text = 'MCP Tools directory setup completed';
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Install MCP tools via script or specific tool
|
|
398
|
+
*/
|
|
399
|
+
private async installMcpTools(options: McpOptions): Promise<void> {
|
|
141
400
|
const spinner = ora();
|
|
142
401
|
const scriptPath = path.join(
|
|
143
402
|
__dirname,
|
|
144
403
|
'../../../../scripts/install-mcp-tools.sh'
|
|
145
404
|
);
|
|
146
405
|
|
|
147
|
-
if (!fs.existsSync(scriptPath)) {
|
|
148
|
-
console.error(chalk.red('ā MCP tools installation script not found'));
|
|
149
|
-
console.log(
|
|
150
|
-
chalk.yellow('Please ensure the script exists at: ' + scriptPath)
|
|
151
|
-
);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
406
|
console.log(chalk.cyan('\nš¦ Installing MCP Tools...\n'));
|
|
156
407
|
|
|
157
408
|
if (options.tool) {
|
|
@@ -166,6 +417,7 @@ Examples:
|
|
|
166
417
|
browser: 'npx claude mcp add browser npx @browser/mcp-server',
|
|
167
418
|
sequentialthinking:
|
|
168
419
|
'npm install -g @modelcontextprotocol/server-sequentialthinking',
|
|
420
|
+
ruflo: 'claude mcp add ruflo npx ruflo@latest mcp start',
|
|
169
421
|
};
|
|
170
422
|
|
|
171
423
|
const command = installCommands[options.tool];
|
|
@@ -174,38 +426,62 @@ Examples:
|
|
|
174
426
|
spinner.succeed(`${options.tool} MCP installed`);
|
|
175
427
|
} else {
|
|
176
428
|
spinner.fail(`Unknown tool: ${options.tool}`);
|
|
429
|
+
console.log(
|
|
430
|
+
chalk.yellow(
|
|
431
|
+
`Available tools: ${Object.keys(installCommands).join(', ')}`
|
|
432
|
+
)
|
|
433
|
+
);
|
|
177
434
|
}
|
|
178
435
|
} catch (error) {
|
|
179
436
|
spinner.fail(`Failed to install ${options.tool}`);
|
|
180
437
|
console.error(error);
|
|
181
438
|
}
|
|
182
439
|
} else {
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
440
|
+
// Try to install all tools using the script if it exists
|
|
441
|
+
if (fs.existsSync(scriptPath)) {
|
|
442
|
+
console.log(
|
|
443
|
+
chalk.gray('Running comprehensive MCP tools installation...')
|
|
444
|
+
);
|
|
187
445
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
446
|
+
const install = spawn('bash', [scriptPath], {
|
|
447
|
+
stdio: 'inherit',
|
|
448
|
+
shell: true,
|
|
449
|
+
});
|
|
192
450
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
451
|
+
return new Promise((resolve, reject) => {
|
|
452
|
+
install.on('close', code => {
|
|
453
|
+
if (code === 0) {
|
|
454
|
+
console.log(
|
|
455
|
+
chalk.green('\nā
All MCP tools installed successfully')
|
|
456
|
+
);
|
|
457
|
+
resolve();
|
|
458
|
+
} else {
|
|
459
|
+
reject(new Error(`Installation failed with code ${code}`));
|
|
460
|
+
}
|
|
461
|
+
});
|
|
203
462
|
});
|
|
204
|
-
}
|
|
463
|
+
} else {
|
|
464
|
+
// Fallback: install core tools
|
|
465
|
+
console.log(chalk.gray('Installing core MCP tools...'));
|
|
466
|
+
|
|
467
|
+
const coreTools = ['ruflo', 'sequentialthinking'];
|
|
468
|
+
for (const tool of coreTools) {
|
|
469
|
+
try {
|
|
470
|
+
await this.installMcpTools({ tool });
|
|
471
|
+
} catch {
|
|
472
|
+
console.log(chalk.yellow(`ā ļø Could not install ${tool}`));
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
console.log(chalk.green('\nā
Core MCP tools installed'));
|
|
477
|
+
}
|
|
205
478
|
}
|
|
206
479
|
}
|
|
207
480
|
|
|
208
|
-
|
|
481
|
+
/**
|
|
482
|
+
* Configure Ruflo agents
|
|
483
|
+
*/
|
|
484
|
+
private async configureAgents(options: AgentOptions): Promise<void> {
|
|
209
485
|
const spinner = ora();
|
|
210
486
|
|
|
211
487
|
if (options.list) {
|
|
@@ -213,14 +489,14 @@ Examples:
|
|
|
213
489
|
return;
|
|
214
490
|
}
|
|
215
491
|
|
|
216
|
-
spinner.start('Configuring
|
|
492
|
+
spinner.start('Configuring Ruflo agents...');
|
|
217
493
|
|
|
218
494
|
const agents = options.enable
|
|
219
495
|
? options.enable.split(',')
|
|
220
496
|
: this.getProfileAgents(options.profile || 'fullstack');
|
|
221
497
|
|
|
222
498
|
// Create agent configurations
|
|
223
|
-
const homeDir = process.env
|
|
499
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
224
500
|
const agentsDir = path.join(homeDir, '.claude', 'agents');
|
|
225
501
|
|
|
226
502
|
try {
|
|
@@ -241,12 +517,15 @@ Examples:
|
|
|
241
517
|
}
|
|
242
518
|
}
|
|
243
519
|
|
|
244
|
-
|
|
520
|
+
/**
|
|
521
|
+
* Validate Claude installation
|
|
522
|
+
*/
|
|
523
|
+
private async validateInstallation(options: ValidateOptions): Promise<void> {
|
|
245
524
|
console.log(chalk.cyan('\nš Validating Claude Installation...\n'));
|
|
246
525
|
|
|
247
526
|
const checks = [
|
|
248
527
|
{ name: 'Claude CLI', check: () => this.isClaudeInstalled() },
|
|
249
|
-
{ name: '
|
|
528
|
+
{ name: 'Ruflo', check: () => this.isRufloInstalled() },
|
|
250
529
|
{ name: 'Chrome Browser', check: () => this.isChromeInstalled() },
|
|
251
530
|
{ name: 'Claude Directory', check: () => this.claudeDirExists() },
|
|
252
531
|
{ name: 'Agent Configurations', check: () => this.agentsConfigured() },
|
|
@@ -279,10 +558,13 @@ Examples:
|
|
|
279
558
|
}
|
|
280
559
|
}
|
|
281
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Install Chrome extension instructions
|
|
563
|
+
*/
|
|
282
564
|
private async installChromeExtension(): Promise<void> {
|
|
283
565
|
console.log(chalk.cyan('\nš Browser MCP Chrome Extension Setup\n'));
|
|
284
566
|
|
|
285
|
-
const homeDir = process.env
|
|
567
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
286
568
|
const extensionDir = path.join(homeDir, '.claude', 'browser-extension');
|
|
287
569
|
|
|
288
570
|
console.log(chalk.white('Extension location: ' + extensionDir));
|
|
@@ -294,14 +576,17 @@ Examples:
|
|
|
294
576
|
console.log('\nā
The extension will then be active!');
|
|
295
577
|
}
|
|
296
578
|
|
|
297
|
-
|
|
579
|
+
/**
|
|
580
|
+
* Setup hardware-adaptive optimizations
|
|
581
|
+
*/
|
|
582
|
+
private async setupOptimizations(options: OptimizeOptions): Promise<void> {
|
|
298
583
|
const spinner = ora();
|
|
299
584
|
console.log(
|
|
300
585
|
chalk.cyan.bold('\nā” Claude Code Hardware-Adaptive Optimization Setup\n')
|
|
301
586
|
);
|
|
302
587
|
|
|
303
588
|
try {
|
|
304
|
-
const homeDir = process.env
|
|
589
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
305
590
|
const scriptsDir = path.join(homeDir, '.claude', 'scripts');
|
|
306
591
|
const resourcesDir = path.join(
|
|
307
592
|
__dirname,
|
|
@@ -311,9 +596,8 @@ Examples:
|
|
|
311
596
|
// Check if optimization scripts already exist
|
|
312
597
|
const scriptsExist = fs.existsSync(scriptsDir);
|
|
313
598
|
if (scriptsExist && !options.force) {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
).default.prompt([
|
|
599
|
+
const inquirer = await import('inquirer');
|
|
600
|
+
const { overwrite } = await inquirer.default.prompt([
|
|
317
601
|
{
|
|
318
602
|
type: 'confirm',
|
|
319
603
|
name: 'overwrite',
|
|
@@ -406,7 +690,9 @@ Examples:
|
|
|
406
690
|
chalk.white(' ⢠claude - Hardware-optimized Claude wrapper')
|
|
407
691
|
);
|
|
408
692
|
console.log(chalk.white(' ⢠claude-stats - Show hardware statistics'));
|
|
409
|
-
console.log(
|
|
693
|
+
console.log(
|
|
694
|
+
chalk.white(' ⢠claude-cleanup - Clean up zombie processes')
|
|
695
|
+
);
|
|
410
696
|
console.log(
|
|
411
697
|
chalk.white(' ⢠claude-orchestrate - Run multi-task orchestrator')
|
|
412
698
|
);
|
|
@@ -425,6 +711,285 @@ Examples:
|
|
|
425
711
|
}
|
|
426
712
|
}
|
|
427
713
|
|
|
714
|
+
/**
|
|
715
|
+
* Generate CLAUDE.md configuration
|
|
716
|
+
*/
|
|
717
|
+
private async generateClaudeConfig(repoPath: string): Promise<void> {
|
|
718
|
+
const spinner = ora('Generating CLAUDE.md configuration...').start();
|
|
719
|
+
|
|
720
|
+
try {
|
|
721
|
+
const resolvedPath = path.resolve(repoPath);
|
|
722
|
+
await this.generateClaudeConfigForPath(spinner, resolvedPath);
|
|
723
|
+
spinner.succeed('CLAUDE.md generated successfully');
|
|
724
|
+
console.log(
|
|
725
|
+
chalk.green(
|
|
726
|
+
`\nā
CLAUDE.md created at: ${path.join(resolvedPath, 'CLAUDE.md')}`
|
|
727
|
+
)
|
|
728
|
+
);
|
|
729
|
+
} catch (error) {
|
|
730
|
+
spinner.fail('Failed to generate CLAUDE.md');
|
|
731
|
+
console.error(
|
|
732
|
+
chalk.red(error instanceof Error ? error.message : String(error))
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Generate CLAUDE.md for a specific path
|
|
739
|
+
*/
|
|
740
|
+
private async generateClaudeConfigForPath(
|
|
741
|
+
spinner: OraSpinner,
|
|
742
|
+
repoPath: string
|
|
743
|
+
): Promise<void> {
|
|
744
|
+
spinner.text = 'Generating CLAUDE.md configuration...';
|
|
745
|
+
|
|
746
|
+
try {
|
|
747
|
+
// Try to use the ClaudeConfigGenerator if available
|
|
748
|
+
// Use path.resolve to construct the path at runtime to avoid TypeScript rootDir issues
|
|
749
|
+
const generatorPath = path.resolve(
|
|
750
|
+
__dirname,
|
|
751
|
+
'../../../../../src/claude-generator/claude-config-generator.js'
|
|
752
|
+
);
|
|
753
|
+
const { ClaudeConfigGenerator } = await import(
|
|
754
|
+
/* @vite-ignore */ generatorPath
|
|
755
|
+
);
|
|
756
|
+
const generator = new ClaudeConfigGenerator(repoPath);
|
|
757
|
+
|
|
758
|
+
const claudeContent = await generator.generateClaudeMarkdown();
|
|
759
|
+
const claudeFilePath = path.join(repoPath, 'CLAUDE.md');
|
|
760
|
+
|
|
761
|
+
fs.writeFileSync(claudeFilePath, claudeContent, 'utf-8');
|
|
762
|
+
} catch {
|
|
763
|
+
// Fallback: Create a basic CLAUDE.md
|
|
764
|
+
spinner.text = 'Creating basic CLAUDE.md...';
|
|
765
|
+
const basicContent = this.generateBasicClaudeConfig(repoPath);
|
|
766
|
+
fs.writeFileSync(path.join(repoPath, 'CLAUDE.md'), basicContent, 'utf-8');
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
spinner.text = 'CLAUDE.md generated successfully';
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Generate basic CLAUDE.md content as fallback
|
|
774
|
+
*/
|
|
775
|
+
private generateBasicClaudeConfig(repoPath: string): string {
|
|
776
|
+
const projectName = path.basename(repoPath);
|
|
777
|
+
return `# Claude Code Configuration - ${projectName}
|
|
778
|
+
|
|
779
|
+
## Project Overview
|
|
780
|
+
This project uses Claude Code for AI-assisted development.
|
|
781
|
+
|
|
782
|
+
## Commands
|
|
783
|
+
- \`npm run build\` - Build the project
|
|
784
|
+
- \`npm run test\` - Run tests
|
|
785
|
+
- \`npm run lint\` - Run linting
|
|
786
|
+
|
|
787
|
+
## Code Style
|
|
788
|
+
- Follow existing patterns in the codebase
|
|
789
|
+
- Write clear, descriptive commit messages
|
|
790
|
+
- Add tests for new features
|
|
791
|
+
|
|
792
|
+
## MCP Tools
|
|
793
|
+
Ruflo is configured for enhanced AI coordination.
|
|
794
|
+
Run \`npx ruflo@latest sparc modes\` to see available modes.
|
|
795
|
+
`;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Setup project template - from /src/cli/commands/claude-setup.ts
|
|
800
|
+
*/
|
|
801
|
+
private async setupProjectTemplate(
|
|
802
|
+
spinner: OraSpinner,
|
|
803
|
+
repoPath: string,
|
|
804
|
+
templateName: string
|
|
805
|
+
): Promise<void> {
|
|
806
|
+
spinner.text = `Applying ${templateName} template...`;
|
|
807
|
+
|
|
808
|
+
const templates: Record<string, () => void> = {
|
|
809
|
+
typescript: () => this.setupTypeScriptTemplate(repoPath),
|
|
810
|
+
react: () => this.setupReactTemplate(repoPath),
|
|
811
|
+
nodejs: () => this.setupNodeTemplate(repoPath),
|
|
812
|
+
monorepo: () => this.setupMonorepoTemplate(repoPath),
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
const setupFunction = templates[templateName];
|
|
816
|
+
if (!setupFunction) {
|
|
817
|
+
throw new Error(
|
|
818
|
+
`Unknown template: ${templateName}. Available: ${Object.keys(templates).join(', ')}`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
setupFunction();
|
|
823
|
+
|
|
824
|
+
spinner.text = `${templateName} template applied`;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
private setupTypeScriptTemplate(repoPath: string): void {
|
|
828
|
+
// Create basic TypeScript configuration if not exists
|
|
829
|
+
const tsconfigPath = path.join(repoPath, 'tsconfig.json');
|
|
830
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
831
|
+
const tsconfig = {
|
|
832
|
+
compilerOptions: {
|
|
833
|
+
target: 'ES2020',
|
|
834
|
+
module: 'ESNext',
|
|
835
|
+
moduleResolution: 'node',
|
|
836
|
+
strict: true,
|
|
837
|
+
esModuleInterop: true,
|
|
838
|
+
skipLibCheck: true,
|
|
839
|
+
forceConsistentCasingInFileNames: true,
|
|
840
|
+
declaration: true,
|
|
841
|
+
outDir: 'dist',
|
|
842
|
+
rootDir: 'src',
|
|
843
|
+
},
|
|
844
|
+
include: ['src/**/*'],
|
|
845
|
+
exclude: ['node_modules', 'dist'],
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2));
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// Create src directory
|
|
852
|
+
const srcPath = path.join(repoPath, 'src');
|
|
853
|
+
if (!fs.existsSync(srcPath)) {
|
|
854
|
+
fs.mkdirSync(srcPath, { recursive: true });
|
|
855
|
+
fs.writeFileSync(
|
|
856
|
+
path.join(srcPath, 'index.ts'),
|
|
857
|
+
'// Your TypeScript code here\n'
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
private setupReactTemplate(repoPath: string): void {
|
|
863
|
+
// Ensure React-specific structure
|
|
864
|
+
const srcPath = path.join(repoPath, 'src');
|
|
865
|
+
if (!fs.existsSync(srcPath)) {
|
|
866
|
+
fs.mkdirSync(srcPath, { recursive: true });
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// Create components directory
|
|
870
|
+
const componentsPath = path.join(srcPath, 'components');
|
|
871
|
+
if (!fs.existsSync(componentsPath)) {
|
|
872
|
+
fs.mkdirSync(componentsPath, { recursive: true });
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// Create hooks directory
|
|
876
|
+
const hooksPath = path.join(srcPath, 'hooks');
|
|
877
|
+
if (!fs.existsSync(hooksPath)) {
|
|
878
|
+
fs.mkdirSync(hooksPath, { recursive: true });
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
private setupNodeTemplate(repoPath: string): void {
|
|
883
|
+
// Create basic Node.js structure
|
|
884
|
+
const srcPath = path.join(repoPath, 'src');
|
|
885
|
+
if (!fs.existsSync(srcPath)) {
|
|
886
|
+
fs.mkdirSync(srcPath, { recursive: true });
|
|
887
|
+
fs.writeFileSync(
|
|
888
|
+
path.join(srcPath, 'index.js'),
|
|
889
|
+
'// Your Node.js code here\n'
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// Create routes directory
|
|
894
|
+
const routesPath = path.join(srcPath, 'routes');
|
|
895
|
+
if (!fs.existsSync(routesPath)) {
|
|
896
|
+
fs.mkdirSync(routesPath, { recursive: true });
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
private setupMonorepoTemplate(repoPath: string): void {
|
|
901
|
+
// Create packages directory
|
|
902
|
+
const packagesPath = path.join(repoPath, 'packages');
|
|
903
|
+
if (!fs.existsSync(packagesPath)) {
|
|
904
|
+
fs.mkdirSync(packagesPath, { recursive: true });
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Create apps directory
|
|
908
|
+
const appsPath = path.join(repoPath, 'apps');
|
|
909
|
+
if (!fs.existsSync(appsPath)) {
|
|
910
|
+
fs.mkdirSync(appsPath, { recursive: true });
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Create workspace package.json if not exists
|
|
914
|
+
const packageJsonPath = path.join(repoPath, 'package.json');
|
|
915
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
916
|
+
const packageJson = {
|
|
917
|
+
name: 'monorepo-workspace',
|
|
918
|
+
version: '1.0.0',
|
|
919
|
+
private: true,
|
|
920
|
+
workspaces: ['packages/*', 'apps/*'],
|
|
921
|
+
devDependencies: {
|
|
922
|
+
turbo: '^2.0.0',
|
|
923
|
+
},
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Initialize swarm - from /src/cli/commands/claude-setup.ts
|
|
932
|
+
*/
|
|
933
|
+
private async initializeSwarm(
|
|
934
|
+
spinner: OraSpinner,
|
|
935
|
+
repoPath: string
|
|
936
|
+
): Promise<void> {
|
|
937
|
+
spinner.text = 'Initializing Ruflo swarm...';
|
|
938
|
+
|
|
939
|
+
try {
|
|
940
|
+
// Initialize basic swarm configuration
|
|
941
|
+
execSync('npx ruflo@latest init', {
|
|
942
|
+
cwd: repoPath,
|
|
943
|
+
stdio: 'pipe',
|
|
944
|
+
});
|
|
945
|
+
} catch {
|
|
946
|
+
// Swarm init might fail if not properly configured
|
|
947
|
+
console.log(
|
|
948
|
+
chalk.yellow('\nā ļø Could not initialize swarm automatically.')
|
|
949
|
+
);
|
|
950
|
+
console.log(
|
|
951
|
+
chalk.yellow(
|
|
952
|
+
'You can initialize manually later with: npx ruflo@latest init'
|
|
953
|
+
)
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
spinner.text = 'Swarm initialization completed';
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Validate project setup - from /src/cli/commands/claude-setup.ts
|
|
962
|
+
*/
|
|
963
|
+
private async validateProjectSetup(
|
|
964
|
+
spinner: OraSpinner,
|
|
965
|
+
repoPath: string
|
|
966
|
+
): Promise<void> {
|
|
967
|
+
spinner.text = 'Validating setup...';
|
|
968
|
+
|
|
969
|
+
const validations = [
|
|
970
|
+
{ name: 'CLAUDE.md', path: path.join(repoPath, 'CLAUDE.md') },
|
|
971
|
+
{ name: 'MCP Tools', path: path.join(repoPath, 'mcp-tools') },
|
|
972
|
+
{ name: 'Git repository', path: path.join(repoPath, '.git') },
|
|
973
|
+
];
|
|
974
|
+
|
|
975
|
+
const results = validations.map(validation => ({
|
|
976
|
+
...validation,
|
|
977
|
+
exists: fs.existsSync(validation.path),
|
|
978
|
+
}));
|
|
979
|
+
|
|
980
|
+
const failures = results.filter(r => !r.exists);
|
|
981
|
+
if (failures.length > 0) {
|
|
982
|
+
throw new Error(
|
|
983
|
+
`Setup validation failed: Missing ${failures.map(f => f.name).join(', ')}`
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
spinner.text = 'Setup validation passed';
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Add shell optimization configuration
|
|
992
|
+
*/
|
|
428
993
|
private async addOptimizationToShell(homeDir: string): Promise<void> {
|
|
429
994
|
const shellConfigs = [
|
|
430
995
|
path.join(homeDir, '.zshrc'),
|
|
@@ -501,6 +1066,9 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
501
1066
|
}
|
|
502
1067
|
}
|
|
503
1068
|
|
|
1069
|
+
/**
|
|
1070
|
+
* Install Chrome browser
|
|
1071
|
+
*/
|
|
504
1072
|
private async installChrome(): Promise<void> {
|
|
505
1073
|
if (process.platform === 'darwin') {
|
|
506
1074
|
execSync(
|
|
@@ -519,14 +1087,17 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
519
1087
|
}
|
|
520
1088
|
}
|
|
521
1089
|
|
|
522
|
-
|
|
523
|
-
|
|
1090
|
+
/**
|
|
1091
|
+
* Setup Claude settings.json
|
|
1092
|
+
*/
|
|
1093
|
+
private async setupClaudeSettings(): Promise<void> {
|
|
1094
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
524
1095
|
const configPath = path.join(homeDir, '.claude', 'settings.json');
|
|
525
1096
|
|
|
526
1097
|
const config = {
|
|
527
1098
|
claudeCodeOptions: {
|
|
528
1099
|
enabledMcpjsonServers: [
|
|
529
|
-
'
|
|
1100
|
+
'ruflo',
|
|
530
1101
|
'firecrawl',
|
|
531
1102
|
'context7',
|
|
532
1103
|
'playwright',
|
|
@@ -546,6 +1117,8 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
546
1117
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
547
1118
|
}
|
|
548
1119
|
|
|
1120
|
+
// ==================== Helper Methods ====================
|
|
1121
|
+
|
|
549
1122
|
private isClaudeInstalled(): boolean {
|
|
550
1123
|
try {
|
|
551
1124
|
execSync('claude --version', { stdio: 'ignore' });
|
|
@@ -555,9 +1128,9 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
555
1128
|
}
|
|
556
1129
|
}
|
|
557
1130
|
|
|
558
|
-
private
|
|
1131
|
+
private isRufloInstalled(): boolean {
|
|
559
1132
|
try {
|
|
560
|
-
execSync('npx
|
|
1133
|
+
execSync('npx ruflo@latest --version', { stdio: 'ignore' });
|
|
561
1134
|
return true;
|
|
562
1135
|
} catch {
|
|
563
1136
|
return false;
|
|
@@ -572,24 +1145,28 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
572
1145
|
}
|
|
573
1146
|
|
|
574
1147
|
private claudeDirExists(): boolean {
|
|
575
|
-
const homeDir = process.env
|
|
1148
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
576
1149
|
return fs.existsSync(path.join(homeDir, '.claude'));
|
|
577
1150
|
}
|
|
578
1151
|
|
|
579
1152
|
private agentsConfigured(): boolean {
|
|
580
|
-
const homeDir = process.env
|
|
1153
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
581
1154
|
const agentsDir = path.join(homeDir, '.claude', 'agents');
|
|
582
|
-
if (!fs.existsSync(agentsDir))
|
|
1155
|
+
if (!fs.existsSync(agentsDir)) {
|
|
1156
|
+
return false;
|
|
1157
|
+
}
|
|
583
1158
|
|
|
584
1159
|
const files = fs.readdirSync(agentsDir);
|
|
585
1160
|
return files.length > 0;
|
|
586
1161
|
}
|
|
587
1162
|
|
|
588
1163
|
private mcpServersConfigured(): boolean {
|
|
589
|
-
const homeDir = process.env
|
|
1164
|
+
const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || '';
|
|
590
1165
|
const settingsPath = path.join(homeDir, '.claude', 'settings.json');
|
|
591
1166
|
|
|
592
|
-
if (!fs.existsSync(settingsPath))
|
|
1167
|
+
if (!fs.existsSync(settingsPath)) {
|
|
1168
|
+
return false;
|
|
1169
|
+
}
|
|
593
1170
|
|
|
594
1171
|
try {
|
|
595
1172
|
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
@@ -600,9 +1177,9 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
600
1177
|
}
|
|
601
1178
|
|
|
602
1179
|
private listAgents(): void {
|
|
603
|
-
console.log(chalk.cyan('\nš Available
|
|
1180
|
+
console.log(chalk.cyan('\nš Available Ruflo Agents:\n'));
|
|
604
1181
|
|
|
605
|
-
const categories = {
|
|
1182
|
+
const categories: Record<string, string[]> = {
|
|
606
1183
|
'Core Development': [
|
|
607
1184
|
'coder',
|
|
608
1185
|
'reviewer',
|
|
@@ -614,19 +1191,56 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
614
1191
|
'hierarchical-coordinator',
|
|
615
1192
|
'mesh-coordinator',
|
|
616
1193
|
'adaptive-coordinator',
|
|
1194
|
+
'collective-intelligence-coordinator',
|
|
1195
|
+
'swarm-memory-manager',
|
|
617
1196
|
],
|
|
618
|
-
'
|
|
1197
|
+
'Consensus & Distributed': [
|
|
1198
|
+
'byzantine-coordinator',
|
|
1199
|
+
'raft-manager',
|
|
1200
|
+
'gossip-coordinator',
|
|
1201
|
+
'consensus-builder',
|
|
1202
|
+
'crdt-synchronizer',
|
|
1203
|
+
'quorum-manager',
|
|
1204
|
+
'security-manager',
|
|
1205
|
+
],
|
|
1206
|
+
'Performance & Optimization': [
|
|
1207
|
+
'perf-analyzer',
|
|
1208
|
+
'performance-benchmarker',
|
|
1209
|
+
'task-orchestrator',
|
|
1210
|
+
'memory-coordinator',
|
|
1211
|
+
'smart-agent',
|
|
1212
|
+
],
|
|
1213
|
+
'GitHub & Repository': [
|
|
619
1214
|
'github-modes',
|
|
620
1215
|
'pr-manager',
|
|
1216
|
+
'code-review-swarm',
|
|
621
1217
|
'issue-tracker',
|
|
622
1218
|
'release-manager',
|
|
1219
|
+
'workflow-automation',
|
|
1220
|
+
'project-board-sync',
|
|
1221
|
+
'repo-architect',
|
|
1222
|
+
'multi-repo-swarm',
|
|
1223
|
+
],
|
|
1224
|
+
'SPARC Methodology': [
|
|
1225
|
+
'sparc-coord',
|
|
1226
|
+
'sparc-coder',
|
|
1227
|
+
'specification',
|
|
1228
|
+
'pseudocode',
|
|
1229
|
+
'architecture',
|
|
1230
|
+
'refinement',
|
|
623
1231
|
],
|
|
624
|
-
Specialized: [
|
|
1232
|
+
'Specialized Development': [
|
|
625
1233
|
'backend-dev',
|
|
626
1234
|
'mobile-dev',
|
|
627
1235
|
'ml-developer',
|
|
1236
|
+
'cicd-engineer',
|
|
1237
|
+
'api-docs',
|
|
628
1238
|
'system-architect',
|
|
1239
|
+
'code-analyzer',
|
|
1240
|
+
'base-template-generator',
|
|
629
1241
|
],
|
|
1242
|
+
'Testing & Validation': ['tdd-london-swarm', 'production-validator'],
|
|
1243
|
+
'Migration & Planning': ['migration-planner', 'swarm-init'],
|
|
630
1244
|
};
|
|
631
1245
|
|
|
632
1246
|
for (const [category, agents] of Object.entries(categories)) {
|
|
@@ -634,17 +1248,20 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
634
1248
|
agents.forEach(agent => console.log(` ⢠${agent}`));
|
|
635
1249
|
console.log();
|
|
636
1250
|
}
|
|
1251
|
+
|
|
1252
|
+
console.log(chalk.gray('Total: 54 agents available'));
|
|
637
1253
|
}
|
|
638
1254
|
|
|
639
1255
|
private getProfileAgents(profile: string): string[] {
|
|
640
1256
|
const profileAgents: Record<string, string[]> = {
|
|
641
|
-
frontend: ['coder', 'reviewer', 'tester', 'mobile-dev'],
|
|
1257
|
+
frontend: ['coder', 'reviewer', 'tester', 'mobile-dev', 'ui-designer'],
|
|
642
1258
|
backend: [
|
|
643
1259
|
'coder',
|
|
644
1260
|
'reviewer',
|
|
645
1261
|
'tester',
|
|
646
1262
|
'backend-dev',
|
|
647
1263
|
'system-architect',
|
|
1264
|
+
'api-docs',
|
|
648
1265
|
],
|
|
649
1266
|
fullstack: [
|
|
650
1267
|
'coder',
|
|
@@ -653,21 +1270,29 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
653
1270
|
'planner',
|
|
654
1271
|
'researcher',
|
|
655
1272
|
'system-architect',
|
|
1273
|
+
'backend-dev',
|
|
656
1274
|
],
|
|
657
|
-
devops: [
|
|
1275
|
+
devops: [
|
|
1276
|
+
'planner',
|
|
1277
|
+
'cicd-engineer',
|
|
1278
|
+
'perf-analyzer',
|
|
1279
|
+
'github-modes',
|
|
1280
|
+
'workflow-automation',
|
|
1281
|
+
],
|
|
1282
|
+
ml: ['ml-developer', 'coder', 'tester', 'perf-analyzer', 'researcher'],
|
|
658
1283
|
};
|
|
659
1284
|
|
|
660
1285
|
return (
|
|
661
1286
|
profileAgents[profile] ||
|
|
662
|
-
profileAgents
|
|
1287
|
+
profileAgents['fullstack'] || ['coder', 'reviewer', 'tester']
|
|
663
1288
|
);
|
|
664
1289
|
}
|
|
665
1290
|
|
|
666
|
-
private generateAgentConfig(agentName: string):
|
|
1291
|
+
private generateAgentConfig(agentName: string): Record<string, unknown> {
|
|
667
1292
|
return {
|
|
668
1293
|
name: agentName,
|
|
669
1294
|
enabled: true,
|
|
670
|
-
description: `${agentName} agent for
|
|
1295
|
+
description: `${agentName} agent for Ruflo`,
|
|
671
1296
|
configuration: {
|
|
672
1297
|
maxTokens: 8000,
|
|
673
1298
|
temperature: 0.7,
|
|
@@ -678,6 +1303,48 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
678
1303
|
};
|
|
679
1304
|
}
|
|
680
1305
|
|
|
1306
|
+
/**
|
|
1307
|
+
* Display final instructions for project setup
|
|
1308
|
+
*/
|
|
1309
|
+
private displayProjectFinalInstructions(
|
|
1310
|
+
repoPath: string,
|
|
1311
|
+
options: SetupOptions
|
|
1312
|
+
): void {
|
|
1313
|
+
console.log(chalk.green('\nš Claude Code Setup Complete!'));
|
|
1314
|
+
console.log(chalk.blue('================================'));
|
|
1315
|
+
|
|
1316
|
+
console.log(chalk.yellow('\nš What was set up:'));
|
|
1317
|
+
console.log('ā
CLAUDE.md configuration generated');
|
|
1318
|
+
if (!options.skipFlow) {
|
|
1319
|
+
console.log('ā
Ruflo installed and configured');
|
|
1320
|
+
}
|
|
1321
|
+
if (!options.skipMcp) {
|
|
1322
|
+
console.log('ā
MCP Tools directory created');
|
|
1323
|
+
}
|
|
1324
|
+
console.log('ā
Project structure validated');
|
|
1325
|
+
|
|
1326
|
+
console.log(chalk.yellow('\nš Next Steps:'));
|
|
1327
|
+
console.log('1. Review and customize CLAUDE.md as needed');
|
|
1328
|
+
console.log('2. Install MCP tools: cd mcp-tools && ./install.sh');
|
|
1329
|
+
console.log('3. Verify Claude Desktop MCP connection');
|
|
1330
|
+
|
|
1331
|
+
if (!options.skipFlow) {
|
|
1332
|
+
console.log('4. Test Ruflo: npx ruflo@latest sparc modes');
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
console.log('5. Start coding with optimized Claude Code integration!');
|
|
1336
|
+
|
|
1337
|
+
console.log(chalk.yellow('\nš Resources:'));
|
|
1338
|
+
console.log('⢠Ruflo: https://github.com/ruvnet/ruflo');
|
|
1339
|
+
console.log('⢠MCP Documentation: https://modelcontextprotocol.io/docs');
|
|
1340
|
+
console.log('⢠Wundr Documentation: ./docs/');
|
|
1341
|
+
|
|
1342
|
+
console.log(chalk.green('\n⨠Happy coding with Claude!'));
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
* Print next steps after complete setup
|
|
1347
|
+
*/
|
|
681
1348
|
private printNextSteps(): void {
|
|
682
1349
|
console.log(chalk.cyan('š Next Steps:'));
|
|
683
1350
|
console.log('1. Configure API keys for MCP tools (if needed)');
|
|
@@ -685,13 +1352,26 @@ alias claude-orchestrate='node $HOME/.claude/scripts/orchestrator.js'
|
|
|
685
1352
|
'2. Install Browser MCP Chrome extension: wundr claude-setup extension'
|
|
686
1353
|
);
|
|
687
1354
|
console.log('3. Restart Claude Desktop to load new configurations');
|
|
688
|
-
console.log('4. Initialize a project: wundr claude-
|
|
1355
|
+
console.log('4. Initialize a project: wundr claude-setup project');
|
|
689
1356
|
console.log(
|
|
690
|
-
'5. Start coding with
|
|
1357
|
+
'5. Start coding with Ruflo: npx ruflo@latest sparc tdd "feature"'
|
|
691
1358
|
);
|
|
692
1359
|
}
|
|
693
1360
|
}
|
|
694
1361
|
|
|
695
|
-
|
|
1362
|
+
/**
|
|
1363
|
+
* Factory function for backwards compatibility with function-based approach
|
|
1364
|
+
* This allows both import patterns to work:
|
|
1365
|
+
* - import claudeSetupCommand from './claude-setup' (class-based)
|
|
1366
|
+
* - import { createClaudeSetupCommand } from './claude-setup' (function-based)
|
|
1367
|
+
*/
|
|
1368
|
+
export function createClaudeSetupCommand(): Command {
|
|
1369
|
+
const program = new Command();
|
|
696
1370
|
new ClaudeSetupCommands(program);
|
|
1371
|
+
return program.commands.find(cmd => cmd.name() === 'claude-setup') || program;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
const createClaudeSetupCommands = (program: Command): ClaudeSetupCommands =>
|
|
1375
|
+
new ClaudeSetupCommands(program);
|
|
1376
|
+
|
|
697
1377
|
export default createClaudeSetupCommands;
|