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,481 @@
1
+ /**
2
+ * Codebase Analysis Module
3
+ *
4
+ * Finds relevant files, functions, and patterns for issue documentation
5
+ */
6
+
7
+ import { execCommand } from '../utils.js';
8
+ import { readFileSync, existsSync, statSync } from 'fs';
9
+ import { join, relative, extname } from 'path';
10
+ import { glob } from 'glob';
11
+
12
+ /**
13
+ * File extensions to analyze by language
14
+ */
15
+ const LANGUAGE_EXTENSIONS = {
16
+ javascript: ['.js', '.jsx', '.mjs', '.cjs'],
17
+ typescript: ['.ts', '.tsx', '.mts', '.cts'],
18
+ python: ['.py', '.pyw'],
19
+ rust: ['.rs'],
20
+ go: ['.go'],
21
+ java: ['.java'],
22
+ csharp: ['.cs'],
23
+ cpp: ['.cpp', '.cc', '.cxx', '.c', '.h', '.hpp'],
24
+ ruby: ['.rb'],
25
+ php: ['.php'],
26
+ swift: ['.swift'],
27
+ kotlin: ['.kt', '.kts'],
28
+ };
29
+
30
+ /**
31
+ * Common source directories to search
32
+ */
33
+ const SOURCE_DIRS = [
34
+ 'src',
35
+ 'lib',
36
+ 'app',
37
+ 'apps',
38
+ 'packages',
39
+ 'components',
40
+ 'views',
41
+ 'pages',
42
+ 'services',
43
+ 'utils',
44
+ 'helpers',
45
+ 'hooks',
46
+ 'store',
47
+ 'stores',
48
+ 'api',
49
+ 'routes',
50
+ 'routers',
51
+ 'controllers',
52
+ 'models',
53
+ 'schemas',
54
+ 'types',
55
+ ];
56
+
57
+ /**
58
+ * Directories to ignore
59
+ */
60
+ const IGNORE_DIRS = [
61
+ 'node_modules',
62
+ '.git',
63
+ 'dist',
64
+ 'build',
65
+ 'out',
66
+ '.next',
67
+ '.nuxt',
68
+ 'coverage',
69
+ '__pycache__',
70
+ '.pytest_cache',
71
+ 'venv',
72
+ '.venv',
73
+ 'target',
74
+ 'vendor',
75
+ ];
76
+
77
+ /**
78
+ * Search for files matching keywords
79
+ */
80
+ export async function searchFiles(keywords, options = {}) {
81
+ const { cwd = process.cwd(), maxResults = 20, extensions } = options;
82
+
83
+ const results = [];
84
+ const searchPatterns = keywords.map((k) => k.toLowerCase());
85
+
86
+ // Determine which extensions to search
87
+ let extsToSearch = [];
88
+ if (extensions) {
89
+ extsToSearch = extensions;
90
+ } else {
91
+ // Search all code extensions
92
+ for (const exts of Object.values(LANGUAGE_EXTENSIONS)) {
93
+ extsToSearch.push(...exts);
94
+ }
95
+ }
96
+
97
+ // Build glob pattern
98
+ const extPattern =
99
+ extsToSearch.length === 1
100
+ ? extsToSearch[0]
101
+ : `{${extsToSearch.join(',')}}`;
102
+
103
+ const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);
104
+
105
+ try {
106
+ const files = await glob(`**/*${extPattern}`, {
107
+ cwd,
108
+ ignore: ignorePattern,
109
+ nodir: true,
110
+ absolute: false,
111
+ });
112
+
113
+ // Score files by keyword matches
114
+ for (const file of files) {
115
+ const fileLower = file.toLowerCase();
116
+ let score = 0;
117
+
118
+ for (const pattern of searchPatterns) {
119
+ // File path contains keyword
120
+ if (fileLower.includes(pattern)) {
121
+ score += 10;
122
+ }
123
+
124
+ // File name starts with keyword
125
+ const fileName = file.split(/[/\\]/).pop().toLowerCase();
126
+ if (fileName.startsWith(pattern)) {
127
+ score += 5;
128
+ }
129
+ }
130
+
131
+ if (score > 0) {
132
+ results.push({ file, score });
133
+ }
134
+ }
135
+
136
+ // Sort by score and limit
137
+ results.sort((a, b) => b.score - a.score);
138
+ return results.slice(0, maxResults).map((r) => r.file);
139
+ } catch (error) {
140
+ return [];
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Search file contents using grep/ripgrep
146
+ */
147
+ export function searchContent(pattern, options = {}) {
148
+ const { cwd = process.cwd(), maxResults = 20, contextLines = 2 } = options;
149
+
150
+ // Try ripgrep first (faster)
151
+ let cmd = `rg -n -C ${contextLines} --max-count 50 "${pattern}"`;
152
+ let result = execCommand(cmd, { cwd });
153
+
154
+ // Fall back to grep
155
+ if (!result.success) {
156
+ cmd = `grep -rn -C ${contextLines} "${pattern}" .`;
157
+ result = execCommand(cmd, { cwd });
158
+ }
159
+
160
+ if (result.success && result.output) {
161
+ const matches = parseGrepOutput(result.output);
162
+ return matches.slice(0, maxResults);
163
+ }
164
+
165
+ return [];
166
+ }
167
+
168
+ /**
169
+ * Parse grep/ripgrep output into structured results
170
+ */
171
+ function parseGrepOutput(output) {
172
+ const results = [];
173
+ const lines = output.split('\n');
174
+
175
+ let currentFile = null;
176
+ let currentMatches = [];
177
+
178
+ for (const line of lines) {
179
+ // Match format: file:line:content or file-line-content (context)
180
+ const match = line.match(/^([^:]+):(\d+)[:-](.*)$/);
181
+
182
+ if (match) {
183
+ const [, file, lineNum, content] = match;
184
+
185
+ if (file !== currentFile) {
186
+ if (currentFile && currentMatches.length > 0) {
187
+ results.push({
188
+ file: currentFile,
189
+ matches: currentMatches,
190
+ });
191
+ }
192
+ currentFile = file;
193
+ currentMatches = [];
194
+ }
195
+
196
+ currentMatches.push({
197
+ line: parseInt(lineNum, 10),
198
+ content: content.trim(),
199
+ });
200
+ }
201
+ }
202
+
203
+ // Don't forget the last file
204
+ if (currentFile && currentMatches.length > 0) {
205
+ results.push({
206
+ file: currentFile,
207
+ matches: currentMatches,
208
+ });
209
+ }
210
+
211
+ return results;
212
+ }
213
+
214
+ /**
215
+ * Find function/class definitions in a file
216
+ */
217
+ export function findDefinitions(filePath, options = {}) {
218
+ const { cwd = process.cwd() } = options;
219
+ const fullPath = join(cwd, filePath);
220
+
221
+ if (!existsSync(fullPath)) {
222
+ return [];
223
+ }
224
+
225
+ const ext = extname(filePath).toLowerCase();
226
+ const content = readFileSync(fullPath, 'utf8');
227
+ const lines = content.split('\n');
228
+ const definitions = [];
229
+
230
+ // Patterns for different languages
231
+ const patterns = {
232
+ // JavaScript/TypeScript
233
+ '.js': [
234
+ /^(?:export\s+)?(?:async\s+)?function\s+(\w+)/,
235
+ /^(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s+)?\(?/,
236
+ /^(?:export\s+)?class\s+(\w+)/,
237
+ /^\s*(\w+)\s*\([^)]*\)\s*\{/, // Method in object
238
+ ],
239
+ '.ts': [
240
+ /^(?:export\s+)?(?:async\s+)?function\s+(\w+)/,
241
+ /^(?:export\s+)?const\s+(\w+)\s*=\s*(?:async\s+)?\(?/,
242
+ /^(?:export\s+)?class\s+(\w+)/,
243
+ /^(?:export\s+)?interface\s+(\w+)/,
244
+ /^(?:export\s+)?type\s+(\w+)/,
245
+ ],
246
+ '.py': [
247
+ /^(?:async\s+)?def\s+(\w+)/,
248
+ /^class\s+(\w+)/,
249
+ ],
250
+ '.go': [
251
+ /^func\s+(?:\([^)]+\)\s+)?(\w+)/,
252
+ /^type\s+(\w+)\s+(?:struct|interface)/,
253
+ ],
254
+ '.rs': [
255
+ /^(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/,
256
+ /^(?:pub\s+)?struct\s+(\w+)/,
257
+ /^(?:pub\s+)?enum\s+(\w+)/,
258
+ /^(?:pub\s+)?trait\s+(\w+)/,
259
+ ],
260
+ '.java': [
261
+ /^(?:public|private|protected)?\s*(?:static\s+)?(?:class|interface|enum)\s+(\w+)/,
262
+ /^(?:public|private|protected)?\s*(?:static\s+)?[\w<>,\s]+\s+(\w+)\s*\(/,
263
+ ],
264
+ };
265
+
266
+ // Use JavaScript patterns for JSX/TSX
267
+ const extPatterns =
268
+ patterns[ext] ||
269
+ patterns['.js'.includes(ext) ? '.js' : '.ts'.includes(ext) ? '.ts' : '.js'];
270
+
271
+ if (!extPatterns) {
272
+ return definitions;
273
+ }
274
+
275
+ for (let i = 0; i < lines.length; i++) {
276
+ const line = lines[i];
277
+
278
+ for (const pattern of extPatterns) {
279
+ const match = line.match(pattern);
280
+ if (match && match[1]) {
281
+ definitions.push({
282
+ name: match[1],
283
+ line: i + 1,
284
+ type: guessDefinitionType(line),
285
+ snippet: line.trim(),
286
+ });
287
+ break;
288
+ }
289
+ }
290
+ }
291
+
292
+ return definitions;
293
+ }
294
+
295
+ /**
296
+ * Guess the type of definition from the line
297
+ */
298
+ function guessDefinitionType(line) {
299
+ const lower = line.toLowerCase();
300
+
301
+ if (lower.includes('class ')) return 'class';
302
+ if (lower.includes('interface ')) return 'interface';
303
+ if (lower.includes('type ')) return 'type';
304
+ if (lower.includes('struct ')) return 'struct';
305
+ if (lower.includes('enum ')) return 'enum';
306
+ if (lower.includes('trait ')) return 'trait';
307
+ if (lower.includes('function ') || lower.includes('def ') || lower.includes('fn '))
308
+ return 'function';
309
+ if (lower.includes('const ')) return 'constant';
310
+
311
+ return 'unknown';
312
+ }
313
+
314
+ /**
315
+ * Extract a code snippet from a file
316
+ */
317
+ export function extractSnippet(filePath, startLine, endLine, options = {}) {
318
+ const { cwd = process.cwd(), maxLines = 30 } = options;
319
+ const fullPath = join(cwd, filePath);
320
+
321
+ if (!existsSync(fullPath)) {
322
+ return null;
323
+ }
324
+
325
+ const content = readFileSync(fullPath, 'utf8');
326
+ const lines = content.split('\n');
327
+
328
+ // Clamp line numbers
329
+ const start = Math.max(0, startLine - 1);
330
+ const end = Math.min(lines.length, endLine || start + maxLines);
331
+
332
+ const snippet = lines.slice(start, end).join('\n');
333
+
334
+ return {
335
+ file: filePath,
336
+ startLine: start + 1,
337
+ endLine: end,
338
+ content: snippet,
339
+ };
340
+ }
341
+
342
+ /**
343
+ * Analyze codebase for issue context
344
+ */
345
+ export async function analyzeForIssue(keywords, options = {}) {
346
+ const { cwd = process.cwd(), maxFiles = 5, maxFunctions = 10 } = options;
347
+
348
+ const analysis = {
349
+ relevantFiles: [],
350
+ keyFunctions: [],
351
+ patterns: [],
352
+ codeSnippets: [],
353
+ };
354
+
355
+ // 1. Search for relevant files
356
+ const files = await searchFiles(keywords, { cwd, maxResults: maxFiles * 2 });
357
+
358
+ // 2. For each file, find relevant definitions
359
+ for (const file of files.slice(0, maxFiles)) {
360
+ const definitions = findDefinitions(file, { cwd });
361
+
362
+ analysis.relevantFiles.push({
363
+ file,
364
+ definitions: definitions.slice(0, 5),
365
+ });
366
+
367
+ // Add key functions
368
+ for (const def of definitions) {
369
+ if (
370
+ def.type === 'function' ||
371
+ def.type === 'class' ||
372
+ def.type === 'component'
373
+ ) {
374
+ // Check if function name matches any keyword
375
+ const defLower = def.name.toLowerCase();
376
+ const isRelevant = keywords.some(
377
+ (k) => defLower.includes(k.toLowerCase()) || k.toLowerCase().includes(defLower)
378
+ );
379
+
380
+ if (isRelevant) {
381
+ analysis.keyFunctions.push({
382
+ file,
383
+ ...def,
384
+ });
385
+ }
386
+ }
387
+ }
388
+ }
389
+
390
+ // 3. Search content for specific patterns
391
+ for (const keyword of keywords) {
392
+ const contentMatches = searchContent(keyword, {
393
+ cwd,
394
+ maxResults: 5,
395
+ contextLines: 1,
396
+ });
397
+
398
+ for (const match of contentMatches) {
399
+ analysis.patterns.push({
400
+ keyword,
401
+ file: match.file,
402
+ matches: match.matches.slice(0, 3),
403
+ });
404
+ }
405
+ }
406
+
407
+ // 4. Extract code snippets for key functions
408
+ for (const func of analysis.keyFunctions.slice(0, 3)) {
409
+ const snippet = extractSnippet(func.file, func.line, func.line + 15, { cwd });
410
+ if (snippet) {
411
+ analysis.codeSnippets.push(snippet);
412
+ }
413
+ }
414
+
415
+ return analysis;
416
+ }
417
+
418
+ /**
419
+ * Detect project type and tech stack
420
+ */
421
+ export function detectProjectType(cwd = process.cwd()) {
422
+ const stack = {
423
+ languages: [],
424
+ frameworks: [],
425
+ tools: [],
426
+ };
427
+
428
+ // Check package.json for JS/TS projects
429
+ const packageJsonPath = join(cwd, 'package.json');
430
+ if (existsSync(packageJsonPath)) {
431
+ try {
432
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
433
+ stack.languages.push('javascript');
434
+
435
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
436
+
437
+ if (deps.typescript) stack.languages.push('typescript');
438
+ if (deps.react) stack.frameworks.push('react');
439
+ if (deps.vue) stack.frameworks.push('vue');
440
+ if (deps.angular) stack.frameworks.push('angular');
441
+ if (deps.next) stack.frameworks.push('nextjs');
442
+ if (deps.express) stack.frameworks.push('express');
443
+ if (deps.fastify) stack.frameworks.push('fastify');
444
+ if (deps.jest || deps.vitest) stack.tools.push('testing');
445
+ if (deps.playwright) stack.tools.push('e2e-testing');
446
+ } catch {}
447
+ }
448
+
449
+ // Check for Python
450
+ if (existsSync(join(cwd, 'requirements.txt')) || existsSync(join(cwd, 'pyproject.toml'))) {
451
+ stack.languages.push('python');
452
+ }
453
+
454
+ // Check for Rust
455
+ if (existsSync(join(cwd, 'Cargo.toml'))) {
456
+ stack.languages.push('rust');
457
+ }
458
+
459
+ // Check for Go
460
+ if (existsSync(join(cwd, 'go.mod'))) {
461
+ stack.languages.push('go');
462
+ }
463
+
464
+ return stack;
465
+ }
466
+
467
+ /**
468
+ * Find similar patterns in codebase (for "patterns to follow")
469
+ */
470
+ export async function findSimilarPatterns(pattern, options = {}) {
471
+ const { cwd = process.cwd(), maxResults = 3 } = options;
472
+
473
+ const matches = searchContent(pattern, { cwd, maxResults: maxResults * 2 });
474
+
475
+ // Filter to most relevant matches
476
+ return matches.slice(0, maxResults).map((match) => ({
477
+ file: match.file,
478
+ line: match.matches[0]?.line,
479
+ snippet: match.matches.map((m) => m.content).join('\n'),
480
+ }));
481
+ }