claude-cli-advanced-starter-pack 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/OVERVIEW.md +597 -0
  3. package/README.md +439 -0
  4. package/bin/gtask.js +282 -0
  5. package/bin/postinstall.js +53 -0
  6. package/package.json +69 -0
  7. package/src/agents/phase-dev-templates.js +1011 -0
  8. package/src/agents/templates.js +668 -0
  9. package/src/analysis/checklist-parser.js +414 -0
  10. package/src/analysis/codebase.js +481 -0
  11. package/src/cli/menu.js +958 -0
  12. package/src/commands/claude-audit.js +1482 -0
  13. package/src/commands/claude-settings.js +2243 -0
  14. package/src/commands/create-agent.js +681 -0
  15. package/src/commands/create-command.js +337 -0
  16. package/src/commands/create-hook.js +262 -0
  17. package/src/commands/create-phase-dev/codebase-analyzer.js +813 -0
  18. package/src/commands/create-phase-dev/documentation-generator.js +352 -0
  19. package/src/commands/create-phase-dev/post-completion.js +404 -0
  20. package/src/commands/create-phase-dev/scale-calculator.js +344 -0
  21. package/src/commands/create-phase-dev/wizard.js +492 -0
  22. package/src/commands/create-phase-dev.js +481 -0
  23. package/src/commands/create-skill.js +313 -0
  24. package/src/commands/create.js +446 -0
  25. package/src/commands/decompose.js +392 -0
  26. package/src/commands/detect-tech-stack.js +768 -0
  27. package/src/commands/explore-mcp/claude-md-updater.js +252 -0
  28. package/src/commands/explore-mcp/mcp-installer.js +346 -0
  29. package/src/commands/explore-mcp/mcp-registry.js +438 -0
  30. package/src/commands/explore-mcp.js +638 -0
  31. package/src/commands/gtask-init.js +641 -0
  32. package/src/commands/help.js +128 -0
  33. package/src/commands/init.js +1890 -0
  34. package/src/commands/install.js +250 -0
  35. package/src/commands/list.js +116 -0
  36. package/src/commands/roadmap.js +750 -0
  37. package/src/commands/setup-wizard.js +482 -0
  38. package/src/commands/setup.js +351 -0
  39. package/src/commands/sync.js +534 -0
  40. package/src/commands/test-run.js +456 -0
  41. package/src/commands/test-setup.js +456 -0
  42. package/src/commands/validate.js +67 -0
  43. package/src/config/tech-stack.defaults.json +182 -0
  44. package/src/config/tech-stack.schema.json +502 -0
  45. package/src/github/client.js +359 -0
  46. package/src/index.js +84 -0
  47. package/src/templates/claude-command.js +244 -0
  48. package/src/templates/issue-body.js +284 -0
  49. package/src/testing/config.js +411 -0
  50. package/src/utils/template-engine.js +398 -0
  51. package/src/utils/validate-templates.js +223 -0
  52. package/src/utils.js +396 -0
  53. package/templates/commands/ccasp-setup.template.md +113 -0
  54. package/templates/commands/context-audit.template.md +97 -0
  55. package/templates/commands/create-task-list.template.md +382 -0
  56. package/templates/commands/deploy-full.template.md +261 -0
  57. package/templates/commands/github-task-start.template.md +99 -0
  58. package/templates/commands/github-update.template.md +69 -0
  59. package/templates/commands/happy-start.template.md +117 -0
  60. package/templates/commands/phase-track.template.md +142 -0
  61. package/templates/commands/tunnel-start.template.md +127 -0
  62. package/templates/commands/tunnel-stop.template.md +106 -0
  63. package/templates/hooks/context-guardian.template.js +173 -0
  64. package/templates/hooks/deployment-orchestrator.template.js +219 -0
  65. package/templates/hooks/github-progress-hook.template.js +197 -0
  66. package/templates/hooks/happy-checkpoint-manager.template.js +222 -0
  67. package/templates/hooks/phase-dev-enforcer.template.js +183 -0
@@ -0,0 +1,252 @@
1
+ /**
2
+ * CLAUDE.md Updater
3
+ *
4
+ * Updates CLAUDE.md with MCP server documentation.
5
+ * Adds tool references and usage examples for installed MCPs.
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+ import ora from 'ora';
10
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
11
+ import { join } from 'path';
12
+
13
+ /**
14
+ * MCP section marker
15
+ */
16
+ const MCP_SECTION_START = '<!-- MCP-SERVERS-START -->';
17
+ const MCP_SECTION_END = '<!-- MCP-SERVERS-END -->';
18
+
19
+ /**
20
+ * Generate MCP documentation section
21
+ *
22
+ * @param {Array} installedMcps - Array of installed MCP definitions
23
+ * @returns {string} Markdown documentation
24
+ */
25
+ export function generateMcpDocumentation(installedMcps) {
26
+ if (installedMcps.length === 0) {
27
+ return `
28
+ ${MCP_SECTION_START}
29
+ ## MCP Servers
30
+
31
+ No MCP servers configured. Run \`gtask explore-mcp\` to discover and install MCP servers.
32
+ ${MCP_SECTION_END}
33
+ `;
34
+ }
35
+
36
+ const sections = installedMcps.map((mcp) => {
37
+ const tools = mcp.tools?.slice(0, 5).join(', ') || 'See documentation';
38
+ const hasMoreTools = mcp.tools?.length > 5;
39
+
40
+ return `### ${mcp.name}
41
+
42
+ **ID:** \`${mcp.id}\`
43
+ **Category:** ${mcp.category}
44
+
45
+ ${mcp.description}
46
+
47
+ **Key Tools:** ${tools}${hasMoreTools ? ` (+${mcp.tools.length - 5} more)` : ''}
48
+
49
+ ${mcp.note ? `> **Note:** ${mcp.note}` : ''}`;
50
+ });
51
+
52
+ // Group by category
53
+ const byCategory = {};
54
+ for (const mcp of installedMcps) {
55
+ const cat = mcp.category || 'other';
56
+ if (!byCategory[cat]) byCategory[cat] = [];
57
+ byCategory[cat].push(mcp);
58
+ }
59
+
60
+ const categorySections = Object.entries(byCategory)
61
+ .map(([category, mcps]) => {
62
+ const categoryName = category.charAt(0).toUpperCase() + category.slice(1);
63
+ const mcpDocs = mcps
64
+ .map((mcp) => {
65
+ const tools = mcp.tools?.slice(0, 3).join(', ') || 'See docs';
66
+ return `| ${mcp.name} | \`${mcp.id}\` | ${tools} |`;
67
+ })
68
+ .join('\n');
69
+
70
+ return `### ${categoryName}
71
+
72
+ | Server | ID | Key Tools |
73
+ |--------|----|-----------|
74
+ ${mcpDocs}`;
75
+ })
76
+ .join('\n\n');
77
+
78
+ return `
79
+ ${MCP_SECTION_START}
80
+ ## MCP Servers
81
+
82
+ MCP (Model Context Protocol) servers extend Claude's capabilities. These are configured in \`.mcp.json\`.
83
+
84
+ ${categorySections}
85
+
86
+ ### Usage
87
+
88
+ MCP tools are accessed via the \`ToolSearch\` tool or directly if loaded:
89
+
90
+ \`\`\`
91
+ # Search for MCP tools
92
+ ToolSearch query: "playwright screenshot"
93
+
94
+ # Use directly (after loading)
95
+ mcp__playwright__browser_screenshot
96
+ \`\`\`
97
+
98
+ ### Restart Required
99
+
100
+ After modifying \`.mcp.json\`, restart Claude Code for changes to take effect:
101
+
102
+ \`\`\`bash
103
+ # Exit and re-enter the project
104
+ cd .. && cd your-project
105
+ \`\`\`
106
+
107
+ *Generated by gtask explore-mcp*
108
+ ${MCP_SECTION_END}
109
+ `;
110
+ }
111
+
112
+ /**
113
+ * Load CLAUDE.md content
114
+ */
115
+ export function loadClaudeMd(cwd = process.cwd()) {
116
+ const claudeMdPath = join(cwd, 'CLAUDE.md');
117
+
118
+ if (existsSync(claudeMdPath)) {
119
+ return readFileSync(claudeMdPath, 'utf8');
120
+ }
121
+
122
+ return null;
123
+ }
124
+
125
+ /**
126
+ * Update CLAUDE.md with MCP documentation
127
+ *
128
+ * @param {Array} installedMcps - Array of installed MCP definitions
129
+ * @param {Object} options - Options
130
+ * @returns {Object} Update result
131
+ */
132
+ export async function updateClaudeMd(installedMcps, options = {}) {
133
+ const spinner = ora('Updating CLAUDE.md...').start();
134
+ const cwd = options.cwd || process.cwd();
135
+ const claudeMdPath = join(cwd, 'CLAUDE.md');
136
+
137
+ try {
138
+ // Generate new MCP section
139
+ const mcpSection = generateMcpDocumentation(installedMcps);
140
+
141
+ let content = loadClaudeMd(cwd);
142
+
143
+ if (!content) {
144
+ // No CLAUDE.md exists - create minimal one with MCP section
145
+ spinner.text = 'Creating CLAUDE.md...';
146
+ content = `# Project
147
+
148
+ <!-- Project-specific instructions for Claude Code -->
149
+
150
+ ${mcpSection}
151
+ `;
152
+ writeFileSync(claudeMdPath, content, 'utf8');
153
+ spinner.succeed('Created CLAUDE.md with MCP documentation');
154
+ return {
155
+ success: true,
156
+ action: 'created',
157
+ path: claudeMdPath,
158
+ };
159
+ }
160
+
161
+ // Check if MCP section exists
162
+ const hasStartMarker = content.includes(MCP_SECTION_START);
163
+ const hasEndMarker = content.includes(MCP_SECTION_END);
164
+
165
+ if (hasStartMarker && hasEndMarker) {
166
+ // Replace existing section
167
+ spinner.text = 'Replacing existing MCP section...';
168
+ const regex = new RegExp(
169
+ `${MCP_SECTION_START}[\\s\\S]*?${MCP_SECTION_END}`,
170
+ 'g'
171
+ );
172
+ content = content.replace(regex, mcpSection.trim());
173
+ } else {
174
+ // Append to end
175
+ spinner.text = 'Appending MCP section...';
176
+
177
+ // Find good insertion point (before any existing sections like "---" at end)
178
+ const lines = content.split('\n');
179
+ let insertIndex = lines.length;
180
+
181
+ // Look for common ending patterns
182
+ for (let i = lines.length - 1; i >= 0; i--) {
183
+ const line = lines[i].trim();
184
+ if (line === '---' || line.startsWith('*Generated') || line.startsWith('<!-- ')) {
185
+ insertIndex = i;
186
+ } else if (line.length > 0) {
187
+ break;
188
+ }
189
+ }
190
+
191
+ lines.splice(insertIndex, 0, '', mcpSection.trim(), '');
192
+ content = lines.join('\n');
193
+ }
194
+
195
+ writeFileSync(claudeMdPath, content, 'utf8');
196
+ spinner.succeed('Updated CLAUDE.md with MCP documentation');
197
+
198
+ return {
199
+ success: true,
200
+ action: hasStartMarker ? 'updated' : 'appended',
201
+ path: claudeMdPath,
202
+ };
203
+ } catch (error) {
204
+ spinner.fail(`Failed to update CLAUDE.md: ${error.message}`);
205
+ return {
206
+ success: false,
207
+ error: error.message,
208
+ };
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Remove MCP section from CLAUDE.md
214
+ */
215
+ export function removeMcpSection(cwd = process.cwd()) {
216
+ const claudeMdPath = join(cwd, 'CLAUDE.md');
217
+
218
+ if (!existsSync(claudeMdPath)) {
219
+ return false;
220
+ }
221
+
222
+ let content = readFileSync(claudeMdPath, 'utf8');
223
+
224
+ const hasStartMarker = content.includes(MCP_SECTION_START);
225
+ const hasEndMarker = content.includes(MCP_SECTION_END);
226
+
227
+ if (hasStartMarker && hasEndMarker) {
228
+ const regex = new RegExp(
229
+ `\\n?${MCP_SECTION_START}[\\s\\S]*?${MCP_SECTION_END}\\n?`,
230
+ 'g'
231
+ );
232
+ content = content.replace(regex, '\n');
233
+ writeFileSync(claudeMdPath, content, 'utf8');
234
+ return true;
235
+ }
236
+
237
+ return false;
238
+ }
239
+
240
+ /**
241
+ * Generate a quick-reference comment for MCP tools
242
+ */
243
+ export function generateMcpQuickRef(installedMcps) {
244
+ const lines = ['<!-- MCP Quick Reference'];
245
+
246
+ for (const mcp of installedMcps) {
247
+ lines.push(` ${mcp.id}: ${mcp.tools?.slice(0, 3).join(', ') || 'see docs'}`);
248
+ }
249
+
250
+ lines.push('-->');
251
+ return lines.join('\n');
252
+ }
@@ -0,0 +1,346 @@
1
+ /**
2
+ * MCP Installer
3
+ *
4
+ * Handles installation of MCP servers:
5
+ * - Generates .mcp.json configuration
6
+ * - Updates .claude/settings.json permissions
7
+ * - Supports Windows (cmd /c wrapper)
8
+ */
9
+
10
+ import chalk from 'chalk';
11
+ import ora from 'ora';
12
+ import inquirer from 'inquirer';
13
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
14
+ import { join } from 'path';
15
+ import { execSync } from 'child_process';
16
+
17
+ /**
18
+ * Check if running on Windows
19
+ */
20
+ export function isWindows() {
21
+ return process.platform === 'win32';
22
+ }
23
+
24
+ /**
25
+ * Generate MCP server configuration for .mcp.json
26
+ *
27
+ * @param {Object} mcp - MCP server definition from registry
28
+ * @param {Object} envValues - Environment variable values provided by user
29
+ * @returns {Object} Server configuration object
30
+ */
31
+ export function generateMcpConfig(mcp, envValues = {}) {
32
+ const config = {
33
+ env: { ...envValues },
34
+ };
35
+
36
+ // Handle different command types
37
+ if (mcp.command === 'uvx') {
38
+ // Python-based MCP (like claude-mem)
39
+ config.command = 'uvx';
40
+ config.args = [...(mcp.args || [])];
41
+ } else if (mcp.npmPackage) {
42
+ // NPM-based MCP
43
+ if (isWindows()) {
44
+ config.command = 'cmd';
45
+ config.args = ['/c', 'npx', '-y', mcp.npmPackage];
46
+ } else {
47
+ config.command = 'npx';
48
+ config.args = ['-y', mcp.npmPackage];
49
+ }
50
+
51
+ // Add any additional args
52
+ if (mcp.args) {
53
+ config.args.push(...mcp.args);
54
+ }
55
+ }
56
+
57
+ return config;
58
+ }
59
+
60
+ /**
61
+ * Load existing .mcp.json or create empty structure
62
+ */
63
+ export function loadMcpJson(cwd = process.cwd()) {
64
+ const mcpPath = join(cwd, '.mcp.json');
65
+
66
+ if (existsSync(mcpPath)) {
67
+ try {
68
+ const content = readFileSync(mcpPath, 'utf8');
69
+ return JSON.parse(content);
70
+ } catch {
71
+ return { mcpServers: {} };
72
+ }
73
+ }
74
+
75
+ return { mcpServers: {} };
76
+ }
77
+
78
+ /**
79
+ * Save .mcp.json
80
+ */
81
+ export function saveMcpJson(config, cwd = process.cwd()) {
82
+ const mcpPath = join(cwd, '.mcp.json');
83
+ const content = JSON.stringify(config, null, 2);
84
+ writeFileSync(mcpPath, content, 'utf8');
85
+ return mcpPath;
86
+ }
87
+
88
+ /**
89
+ * Load existing .claude/settings.json or create empty structure
90
+ */
91
+ export function loadClaudeSettings(cwd = process.cwd()) {
92
+ const settingsPath = join(cwd, '.claude', 'settings.json');
93
+
94
+ if (existsSync(settingsPath)) {
95
+ try {
96
+ const content = readFileSync(settingsPath, 'utf8');
97
+ return JSON.parse(content);
98
+ } catch {
99
+ return { permissions: { allow: [], deny: [] } };
100
+ }
101
+ }
102
+
103
+ return { permissions: { allow: [], deny: [] } };
104
+ }
105
+
106
+ /**
107
+ * Save .claude/settings.json
108
+ */
109
+ export function saveClaudeSettings(settings, cwd = process.cwd()) {
110
+ const claudeDir = join(cwd, '.claude');
111
+ const settingsPath = join(claudeDir, 'settings.json');
112
+
113
+ if (!existsSync(claudeDir)) {
114
+ mkdirSync(claudeDir, { recursive: true });
115
+ }
116
+
117
+ const content = JSON.stringify(settings, null, 2);
118
+ writeFileSync(settingsPath, content, 'utf8');
119
+ return settingsPath;
120
+ }
121
+
122
+ /**
123
+ * Add MCP permission to settings
124
+ */
125
+ export function addMcpPermission(settings, mcpId) {
126
+ if (!settings.permissions) {
127
+ settings.permissions = { allow: [], deny: [] };
128
+ }
129
+
130
+ if (!settings.permissions.allow) {
131
+ settings.permissions.allow = [];
132
+ }
133
+
134
+ const permission = `MCP(${mcpId}:*)`;
135
+
136
+ if (!settings.permissions.allow.includes(permission)) {
137
+ settings.permissions.allow.push(permission);
138
+ }
139
+
140
+ return settings;
141
+ }
142
+
143
+ /**
144
+ * Enable MCP server in settings
145
+ */
146
+ export function enableMcpServer(settings, mcpId) {
147
+ if (!settings.enableAllProjectMcpServers) {
148
+ if (!settings.enabledMcpjsonServers) {
149
+ settings.enabledMcpjsonServers = [];
150
+ }
151
+
152
+ if (!settings.enabledMcpjsonServers.includes(mcpId)) {
153
+ settings.enabledMcpjsonServers.push(mcpId);
154
+ }
155
+ }
156
+
157
+ return settings;
158
+ }
159
+
160
+ /**
161
+ * Prompt user for required environment variables
162
+ */
163
+ export async function promptForEnvVars(mcp) {
164
+ const envValues = {};
165
+ const required = mcp.requiredEnv || {};
166
+ const optional = mcp.optionalEnv || {};
167
+
168
+ // Prompt for required vars
169
+ for (const [key, info] of Object.entries(required)) {
170
+ const { value } = await inquirer.prompt([
171
+ {
172
+ type: 'password',
173
+ name: 'value',
174
+ message: `${key} (${info.description}):`,
175
+ mask: '*',
176
+ validate: (input) => input.length > 0 || 'This field is required',
177
+ },
178
+ ]);
179
+ envValues[key] = value;
180
+ }
181
+
182
+ // Ask about optional vars
183
+ if (Object.keys(optional).length > 0) {
184
+ const { configureOptional } = await inquirer.prompt([
185
+ {
186
+ type: 'confirm',
187
+ name: 'configureOptional',
188
+ message: 'Configure optional settings?',
189
+ default: false,
190
+ },
191
+ ]);
192
+
193
+ if (configureOptional) {
194
+ for (const [key, info] of Object.entries(optional)) {
195
+ const { value } = await inquirer.prompt([
196
+ {
197
+ type: 'input',
198
+ name: 'value',
199
+ message: `${key} (${info.description}):`,
200
+ default: info.default || '',
201
+ },
202
+ ]);
203
+ if (value) {
204
+ envValues[key] = value;
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ return envValues;
211
+ }
212
+
213
+ /**
214
+ * Install a single MCP server
215
+ *
216
+ * @param {Object} mcp - MCP definition from registry
217
+ * @param {Object} options - Installation options
218
+ * @returns {Object} Installation result
219
+ */
220
+ export async function installMcp(mcp, options = {}) {
221
+ const spinner = ora(`Installing ${mcp.name}...`).start();
222
+ const cwd = options.cwd || process.cwd();
223
+
224
+ try {
225
+ // 1. Get environment variables
226
+ spinner.text = 'Configuring environment variables...';
227
+ let envValues = options.envValues || {};
228
+
229
+ if (!options.skipEnvPrompt && Object.keys(mcp.requiredEnv || {}).length > 0) {
230
+ spinner.stop();
231
+ envValues = await promptForEnvVars(mcp);
232
+ spinner.start();
233
+ }
234
+
235
+ // 2. Generate MCP config
236
+ spinner.text = 'Generating configuration...';
237
+ const mcpConfig = generateMcpConfig(mcp, envValues);
238
+
239
+ // 3. Update .mcp.json
240
+ spinner.text = 'Updating .mcp.json...';
241
+ const mcpJson = loadMcpJson(cwd);
242
+ mcpJson.mcpServers = mcpJson.mcpServers || {};
243
+ mcpJson.mcpServers[mcp.id] = mcpConfig;
244
+
245
+ // Add helpful note
246
+ if (!mcpJson._NOTE) {
247
+ mcpJson._NOTE = 'MCP servers configured by gtask explore-mcp';
248
+ }
249
+
250
+ const mcpPath = saveMcpJson(mcpJson, cwd);
251
+
252
+ // 4. Update .claude/settings.json
253
+ spinner.text = 'Updating Claude settings...';
254
+ const settings = loadClaudeSettings(cwd);
255
+ addMcpPermission(settings, mcp.id);
256
+ enableMcpServer(settings, mcp.id);
257
+ const settingsPath = saveClaudeSettings(settings, cwd);
258
+
259
+ spinner.succeed(`Installed ${mcp.name}`);
260
+
261
+ return {
262
+ success: true,
263
+ mcp,
264
+ files: {
265
+ mcpJson: mcpPath,
266
+ settings: settingsPath,
267
+ },
268
+ config: mcpConfig,
269
+ };
270
+ } catch (error) {
271
+ spinner.fail(`Failed to install ${mcp.name}: ${error.message}`);
272
+ return {
273
+ success: false,
274
+ mcp,
275
+ error: error.message,
276
+ };
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Install multiple MCPs
282
+ */
283
+ export async function installMultipleMcps(mcps, options = {}) {
284
+ const results = [];
285
+
286
+ for (const mcp of mcps) {
287
+ const result = await installMcp(mcp, options);
288
+ results.push(result);
289
+ }
290
+
291
+ return results;
292
+ }
293
+
294
+ /**
295
+ * Check if an MCP is already installed
296
+ */
297
+ export function isMcpInstalled(mcpId, cwd = process.cwd()) {
298
+ const mcpJson = loadMcpJson(cwd);
299
+ return mcpJson.mcpServers && mcpId in mcpJson.mcpServers;
300
+ }
301
+
302
+ /**
303
+ * Get list of installed MCPs
304
+ */
305
+ export function getInstalledMcps(cwd = process.cwd()) {
306
+ const mcpJson = loadMcpJson(cwd);
307
+ return Object.keys(mcpJson.mcpServers || {});
308
+ }
309
+
310
+ /**
311
+ * Remove an MCP
312
+ */
313
+ export function removeMcp(mcpId, cwd = process.cwd()) {
314
+ // Remove from .mcp.json
315
+ const mcpJson = loadMcpJson(cwd);
316
+ if (mcpJson.mcpServers && mcpId in mcpJson.mcpServers) {
317
+ delete mcpJson.mcpServers[mcpId];
318
+ saveMcpJson(mcpJson, cwd);
319
+ }
320
+
321
+ // Remove from settings
322
+ const settings = loadClaudeSettings(cwd);
323
+ if (settings.enabledMcpjsonServers) {
324
+ settings.enabledMcpjsonServers = settings.enabledMcpjsonServers.filter(
325
+ (id) => id !== mcpId
326
+ );
327
+ saveClaudeSettings(settings, cwd);
328
+ }
329
+
330
+ return true;
331
+ }
332
+
333
+ /**
334
+ * Verify MCP installation by checking npm package exists
335
+ */
336
+ export async function verifyMcpPackage(npmPackage) {
337
+ try {
338
+ execSync(`npm view ${npmPackage.split('@')[0]} --json`, {
339
+ stdio: 'pipe',
340
+ encoding: 'utf8',
341
+ });
342
+ return true;
343
+ } catch {
344
+ return false;
345
+ }
346
+ }