claude-cli-advanced-starter-pack 1.1.0 → 1.8.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 (56) hide show
  1. package/OVERVIEW.md +5 -1
  2. package/README.md +241 -132
  3. package/bin/gtask.js +53 -0
  4. package/package.json +1 -1
  5. package/src/cli/menu.js +27 -0
  6. package/src/commands/explore-mcp/mcp-registry.js +99 -0
  7. package/src/commands/init.js +306 -77
  8. package/src/commands/install-panel-hook.js +108 -0
  9. package/src/commands/install-scripts.js +232 -0
  10. package/src/commands/install-skill.js +220 -0
  11. package/src/commands/panel.js +297 -0
  12. package/src/commands/setup-wizard.js +4 -3
  13. package/src/commands/test-setup.js +4 -5
  14. package/src/data/releases.json +164 -0
  15. package/src/panel/queue.js +188 -0
  16. package/templates/commands/ask-claude.template.md +118 -0
  17. package/templates/commands/ccasp-panel.template.md +72 -0
  18. package/templates/commands/ccasp-setup.template.md +470 -79
  19. package/templates/commands/create-smoke-test.template.md +186 -0
  20. package/templates/commands/project-impl.template.md +9 -113
  21. package/templates/commands/refactor-check.template.md +112 -0
  22. package/templates/commands/refactor-cleanup.template.md +144 -0
  23. package/templates/commands/refactor-prep.template.md +192 -0
  24. package/templates/docs/AI_ARCHITECTURE_CONSTITUTION.template.md +198 -0
  25. package/templates/docs/DETAILED_GOTCHAS.template.md +347 -0
  26. package/templates/docs/PHASE-DEV-CHECKLIST.template.md +241 -0
  27. package/templates/docs/PROGRESS_JSON_TEMPLATE.json +117 -0
  28. package/templates/docs/background-agent.template.md +264 -0
  29. package/templates/hooks/autonomous-decision-logger.template.js +207 -0
  30. package/templates/hooks/branch-merge-checker.template.js +272 -0
  31. package/templates/hooks/git-commit-tracker.template.js +267 -0
  32. package/templates/hooks/issue-completion-detector.template.js +205 -0
  33. package/templates/hooks/panel-queue-reader.template.js +83 -0
  34. package/templates/hooks/phase-validation-gates.template.js +307 -0
  35. package/templates/hooks/session-id-generator.template.js +236 -0
  36. package/templates/hooks/token-usage-monitor.template.js +193 -0
  37. package/templates/patterns/README.md +129 -0
  38. package/templates/patterns/l1-l2-orchestration.md +189 -0
  39. package/templates/patterns/multi-phase-orchestration.md +258 -0
  40. package/templates/patterns/two-tier-query-pipeline.md +192 -0
  41. package/templates/scripts/README.md +109 -0
  42. package/templates/scripts/analyze-delegation-log.js +299 -0
  43. package/templates/scripts/autonomous-decision-logger.js +277 -0
  44. package/templates/scripts/git-history-analyzer.py +269 -0
  45. package/templates/scripts/phase-validation-gates.js +307 -0
  46. package/templates/scripts/poll-deployment-status.js +260 -0
  47. package/templates/scripts/roadmap-scanner.js +263 -0
  48. package/templates/scripts/validate-deployment.js +293 -0
  49. package/templates/skills/agent-creator/skill.json +18 -0
  50. package/templates/skills/agent-creator/skill.md +335 -0
  51. package/templates/skills/hook-creator/skill.json +18 -0
  52. package/templates/skills/hook-creator/skill.md +318 -0
  53. package/templates/skills/panel/skill.json +18 -0
  54. package/templates/skills/panel/skill.md +90 -0
  55. package/templates/skills/rag-agent-creator/skill.json +18 -0
  56. package/templates/skills/rag-agent-creator/skill.md +307 -0
@@ -93,6 +93,51 @@ const OPTIONAL_FEATURES = [
93
93
  default: false,
94
94
  requiresPostConfig: true,
95
95
  },
96
+ {
97
+ name: 'advancedHooks',
98
+ label: 'Advanced Hook Suite',
99
+ description: 'Extended hook system with session management, git commit tracking, branch validation, issue detection, token monitoring, autonomous logging, and phase validation gates.',
100
+ commands: [],
101
+ hooks: [
102
+ 'session-id-generator',
103
+ 'git-commit-tracker',
104
+ 'branch-merge-checker',
105
+ 'issue-completion-detector',
106
+ 'token-usage-monitor',
107
+ 'autonomous-decision-logger',
108
+ 'phase-validation-gates',
109
+ ],
110
+ default: false,
111
+ requiresPostConfig: false,
112
+ },
113
+ {
114
+ name: 'skillTemplates',
115
+ label: 'Skill Creator Templates',
116
+ description: 'Pre-built skills for agent creation, hook creation, and RAG-enhanced agent building. Provides best-practice templates for extending Claude Code.',
117
+ commands: [],
118
+ hooks: [],
119
+ skills: ['agent-creator', 'hook-creator', 'rag-agent-creator', 'panel'],
120
+ default: true,
121
+ requiresPostConfig: false,
122
+ },
123
+ {
124
+ name: 'refactoring',
125
+ label: 'Refactoring Tools',
126
+ description: 'Code quality commands for linting, cleanup, and safe refactoring. Includes pre-commit checks, auto-fix, and safety checklists.',
127
+ commands: ['refactor-check', 'refactor-cleanup', 'refactor-prep'],
128
+ hooks: [],
129
+ default: false,
130
+ requiresPostConfig: false,
131
+ },
132
+ {
133
+ name: 'testing',
134
+ label: 'Advanced Testing',
135
+ description: 'Extended testing capabilities including smoke test generation and test coverage analysis.',
136
+ commands: ['create-smoke-test'],
137
+ hooks: [],
138
+ default: false,
139
+ requiresPostConfig: false,
140
+ },
96
141
  ];
97
142
 
98
143
  /**
@@ -106,6 +151,12 @@ const AVAILABLE_COMMANDS = [
106
151
  selected: true,
107
152
  required: true,
108
153
  },
154
+ {
155
+ name: 'ccasp-panel',
156
+ description: 'Launch control panel in new terminal (agents, skills, hooks, MCP)',
157
+ category: 'Navigation',
158
+ selected: true,
159
+ },
109
160
  {
110
161
  name: 'e2e-test',
111
162
  description: 'Run E2E tests with Playwright (ralph loop, headed, watch modes)',
@@ -266,6 +317,41 @@ const AVAILABLE_COMMANDS = [
266
317
  category: 'Maintenance',
267
318
  selected: true,
268
319
  },
320
+ // Refactoring commands (Phase 4)
321
+ {
322
+ name: 'refactor-check',
323
+ description: 'Fast pre-commit quality gate - lint, type-check, test affected files',
324
+ category: 'Refactoring',
325
+ selected: false,
326
+ feature: 'refactoring',
327
+ },
328
+ {
329
+ name: 'refactor-cleanup',
330
+ description: 'Daily maintenance automation - fix lint, remove unused imports, format',
331
+ category: 'Refactoring',
332
+ selected: false,
333
+ feature: 'refactoring',
334
+ },
335
+ {
336
+ name: 'refactor-prep',
337
+ description: 'Pre-refactoring safety checklist - ensure safe conditions',
338
+ category: 'Refactoring',
339
+ selected: false,
340
+ feature: 'refactoring',
341
+ },
342
+ {
343
+ name: 'ask-claude',
344
+ description: 'Natural language command discovery - find the right command for any task',
345
+ category: 'Discovery',
346
+ selected: true,
347
+ },
348
+ {
349
+ name: 'create-smoke-test',
350
+ description: 'Auto-generate Playwright smoke tests for critical user flows',
351
+ category: 'Testing',
352
+ selected: false,
353
+ feature: 'testing',
354
+ },
269
355
  ];
270
356
 
271
357
  /**
@@ -337,10 +423,19 @@ description: Interactive project menu - Quick access to all commands, agents, sk
337
423
 
338
424
  # ${projectName} - Project Menu
339
425
 
340
- ## IMPORTANT: Check Update State First
426
+ ## CRITICAL FIRST STEP: Check for Updates
427
+
428
+ **BEFORE doing anything else**, you MUST read the update state file:
429
+
430
+ \`\`\`
431
+ Read file: .claude/config/ccasp-state.json
432
+ \`\`\`
433
+
434
+ Use the Read tool NOW to read \`.claude/config/ccasp-state.json\`. If it doesn't exist, that's fine - proceed without update banner.
341
435
 
342
- Before displaying the menu, read \`.claude/config/ccasp-state.json\` to check for updates:
436
+ If the file exists and contains \`"updateAvailable": true\`, you MUST display the update banner BEFORE the menu.
343
437
 
438
+ Example state file contents:
344
439
  \`\`\`javascript
345
440
  {
346
441
  "currentVersion": "1.0.5",
@@ -412,6 +507,7 @@ On subsequent displays (when \`updateFirstDisplayed: true\`), show a compact ban
412
507
  ║ [T] Run Tests [G] GitHub Task [P] Phase Dev Plan ║
413
508
  ║ [A] Create Agent [H] Create Hook [S] Create Skill ║
414
509
  ║ [M] Explore MCP [C] Claude Audit [E] Explore Codebase ║
510
+ ║ [⚡] Launch Panel Open control panel in new terminal window ║
415
511
  ║ ║
416
512
  ║ Project Resources: ║
417
513
  ║ ────────────────── ║
@@ -455,6 +551,7 @@ When the user invokes \`/menu\`:
455
551
  | **M** | Explore MCP Servers | \`/explore-mcp\` |
456
552
  | **C** | Claude Audit | \`/claude-audit\` |
457
553
  | **E** | Explore Codebase | \`/codebase-explorer\` |
554
+ | **⚡** or **L** | Launch Panel | \`/ccasp-panel\` (opens in new terminal) |
458
555
  | **1** | List project agents | Read \`.claude/agents/\` |
459
556
  | **2** | List project skills | Read \`.claude/skills/\` |
460
557
  | **3** | List active hooks | Read \`.claude/hooks/\` |
@@ -535,6 +632,7 @@ Ask: "What would you like to do? Enter a key:"
535
632
  | **N** | **Update Now**: Run \`npm update -g claude-cli-advanced-starter-pack\` via Bash, then show: "Update complete! Restart Claude Code CLI to use new features." |
536
633
  | **U** | Invoke \`/update-check\` for detailed update info and feature management |
537
634
  | **I** | Invoke \`/project-impl\` for project implementation |
635
+ | **⚡** or **L** | **Launch Panel**: Run \`start powershell -NoExit -Command "ccasp panel"\` (Windows) or equivalent to open control panel in new terminal |
538
636
  | **R** | Re-invoke \`/menu\` (refresh) |
539
637
  | **Q** | End menu session |
540
638
  | **1-6** | Read and display the corresponding resource |
@@ -1599,20 +1697,23 @@ export async function runInit(options = {}) {
1599
1697
  console.log(chalk.dim(' Use --force flag to overwrite specific commands if needed.'));
1600
1698
  console.log('');
1601
1699
 
1602
- const { confirmProceed } = await inquirer.prompt([
1603
- {
1604
- type: 'confirm',
1605
- name: 'confirmProceed',
1606
- message: 'Continue with installation? (existing files are safe)',
1607
- default: true,
1608
- },
1609
- ]);
1700
+ // Skip prompt if called non-interactively (e.g., from wizard)
1701
+ if (!options.skipPrompts) {
1702
+ const { confirmProceed } = await inquirer.prompt([
1703
+ {
1704
+ type: 'confirm',
1705
+ name: 'confirmProceed',
1706
+ message: 'Continue with installation? (existing files are safe)',
1707
+ default: true,
1708
+ },
1709
+ ]);
1610
1710
 
1611
- if (!confirmProceed) {
1612
- console.log(chalk.dim('\nCancelled. No changes made.'));
1613
- return;
1711
+ if (!confirmProceed) {
1712
+ console.log(chalk.dim('\nCancelled. No changes made.'));
1713
+ return;
1714
+ }
1715
+ console.log('');
1614
1716
  }
1615
- console.log('');
1616
1717
  }
1617
1718
 
1618
1719
  // Step 1: Check and create folder structure
@@ -1786,46 +1887,63 @@ export async function runInit(options = {}) {
1786
1887
  console.log('');
1787
1888
 
1788
1889
  // Step 4: Select optional features
1789
- console.log(chalk.bold('Step 4: Select optional features\n'));
1790
- console.log(chalk.dim(' Each feature adds commands and hooks to your project.'));
1791
- console.log(chalk.dim(' Features marked with (*) require additional configuration via /menu after installation.\n'));
1792
-
1793
- // Display feature descriptions in a nice format
1794
- for (const feature of OPTIONAL_FEATURES) {
1795
- const marker = feature.default ? chalk.green('●') : chalk.dim('○');
1796
- const postConfig = feature.requiresPostConfig ? chalk.yellow(' (*)') : '';
1797
- console.log(` ${marker} ${chalk.bold(feature.label)}${postConfig}`);
1798
- console.log(chalk.dim(` ${feature.description}`));
1799
- if (feature.commands.length > 0) {
1800
- console.log(chalk.dim(` Adds: ${feature.commands.map(c => '/' + c).join(', ')}`));
1890
+ let selectedFeatures;
1891
+
1892
+ if (options.skipPrompts && options.features) {
1893
+ // Use features passed from wizard
1894
+ selectedFeatures = options.features;
1895
+ console.log(chalk.bold('Step 4: Using pre-selected features\n'));
1896
+ if (selectedFeatures.length > 0) {
1897
+ console.log(chalk.dim(` Features: ${selectedFeatures.join(', ')}`));
1898
+ } else {
1899
+ console.log(chalk.dim(' Minimal mode - essential commands only'));
1801
1900
  }
1802
1901
  console.log('');
1803
- }
1902
+ } else {
1903
+ console.log(chalk.bold('Step 4: Select optional features\n'));
1904
+ console.log(chalk.dim(' Each feature adds commands and hooks to your project.'));
1905
+ console.log(chalk.dim(' Features marked with (*) require additional configuration via /menu after installation.\n'));
1906
+
1907
+ // Display feature descriptions in a nice format
1908
+ for (const feature of OPTIONAL_FEATURES) {
1909
+ const marker = feature.default ? chalk.green('●') : chalk.dim('○');
1910
+ const postConfig = feature.requiresPostConfig ? chalk.yellow(' (*)') : '';
1911
+ console.log(` ${marker} ${chalk.bold(feature.label)}${postConfig}`);
1912
+ console.log(chalk.dim(` ${feature.description}`));
1913
+ if (feature.commands.length > 0) {
1914
+ console.log(chalk.dim(` Adds: ${feature.commands.map(c => '/' + c).join(', ')}`));
1915
+ }
1916
+ console.log('');
1917
+ }
1804
1918
 
1805
- const { selectedFeatures } = await inquirer.prompt([
1806
- {
1807
- type: 'checkbox',
1808
- name: 'selectedFeatures',
1809
- message: 'Select features to enable:',
1810
- choices: OPTIONAL_FEATURES.map((feature) => ({
1811
- name: `${feature.label}${feature.requiresPostConfig ? ' (*)' : ''} - ${feature.commands.length} commands, ${feature.hooks.length} hooks`,
1812
- value: feature.name,
1813
- checked: feature.default,
1814
- })),
1815
- pageSize: 10,
1816
- },
1817
- ]);
1919
+ const result = await inquirer.prompt([
1920
+ {
1921
+ type: 'checkbox',
1922
+ name: 'selectedFeatures',
1923
+ message: 'Select features to enable:',
1924
+ choices: OPTIONAL_FEATURES.map((feature) => ({
1925
+ name: `${feature.label}${feature.requiresPostConfig ? ' (*)' : ''} - ${feature.commands.length} commands, ${feature.hooks.length} hooks`,
1926
+ value: feature.name,
1927
+ checked: feature.default,
1928
+ })),
1929
+ pageSize: 10,
1930
+ },
1931
+ ]);
1932
+ selectedFeatures = result.selectedFeatures;
1933
+ }
1818
1934
 
1819
1935
  // Store selected features for later use
1820
1936
  const enabledFeatures = OPTIONAL_FEATURES.filter((f) => selectedFeatures.includes(f.name));
1821
1937
  const featuresRequiringConfig = enabledFeatures.filter((f) => f.requiresPostConfig);
1822
1938
 
1823
- // Collect feature-specific commands and hooks to deploy
1939
+ // Collect feature-specific commands, hooks, and skills to deploy
1824
1940
  const featureCommands = [];
1825
1941
  const featureHooks = [];
1942
+ const featureSkills = [];
1826
1943
  for (const feature of enabledFeatures) {
1827
1944
  featureCommands.push(...feature.commands);
1828
- featureHooks.push(...feature.hooks);
1945
+ featureHooks.push(...(feature.hooks || []));
1946
+ featureSkills.push(...(feature.skills || []));
1829
1947
  }
1830
1948
 
1831
1949
  if (featureCommands.length > 0) {
@@ -1839,6 +1957,11 @@ export async function runInit(options = {}) {
1839
1957
  console.log(chalk.dim(` ${featureHooks.join(', ')}`));
1840
1958
  }
1841
1959
 
1960
+ if (featureSkills.length > 0) {
1961
+ console.log(chalk.green(` ✓ Selected features will add ${featureSkills.length} skill(s):`));
1962
+ console.log(chalk.dim(` ${featureSkills.join(', ')}`));
1963
+ }
1964
+
1842
1965
  if (featuresRequiringConfig.length > 0) {
1843
1966
  console.log('');
1844
1967
  console.log(chalk.yellow(' ℹ The following features require configuration after installation:'));
@@ -1850,7 +1973,7 @@ export async function runInit(options = {}) {
1850
1973
 
1851
1974
  // Check for optional npm package installs from selected features
1852
1975
  const featuresWithNpm = enabledFeatures.filter((f) => f.npmPackage);
1853
- if (featuresWithNpm.length > 0) {
1976
+ if (featuresWithNpm.length > 0 && !options.skipPrompts) {
1854
1977
  console.log('');
1855
1978
  console.log(chalk.bold(' Optional Package Installation\n'));
1856
1979
 
@@ -1882,6 +2005,10 @@ export async function runInit(options = {}) {
1882
2005
  console.log(chalk.dim(` Skipped. Install later with: npm install -g ${feature.npmPackage}`));
1883
2006
  }
1884
2007
  }
2008
+ } else if (featuresWithNpm.length > 0) {
2009
+ // In skipPrompts mode, just inform about optional packages
2010
+ console.log(chalk.dim(` ℹ Optional packages available: ${featuresWithNpm.map(f => f.npmPackage).join(', ')}`));
2011
+ console.log(chalk.dim(' Install manually if needed.'));
1885
2012
  }
1886
2013
 
1887
2014
  console.log('');
@@ -1895,45 +2022,54 @@ export async function runInit(options = {}) {
1895
2022
  : [];
1896
2023
  const existingCmdNames = existingCmdFiles.map(f => f.replace('.md', ''));
1897
2024
 
1898
- if (existingCmdNames.length > 0) {
2025
+ if (existingCmdNames.length > 0 && !options.skipPrompts) {
1899
2026
  console.log(chalk.blue(` ℹ Found ${existingCmdNames.length} existing command(s) in your project:`));
1900
2027
  console.log(chalk.dim(` ${existingCmdNames.map(c => '/' + c).join(', ')}`));
1901
2028
  console.log(chalk.dim(' These will be preserved unless you choose to overwrite.\n'));
1902
2029
  }
1903
2030
 
1904
- const categories = [...new Set(AVAILABLE_COMMANDS.map((c) => c.category))];
2031
+ let selectedCommands;
1905
2032
 
1906
- for (const category of categories) {
1907
- console.log(chalk.cyan(` ${category}:`));
1908
- const cmds = AVAILABLE_COMMANDS.filter((c) => c.category === category);
1909
- for (const cmd of cmds) {
1910
- const isExisting = existingCmdNames.includes(cmd.name);
1911
- const marker = cmd.selected ? chalk.green('●') : chalk.dim('○');
1912
- const required = cmd.required ? chalk.yellow(' (required)') : '';
1913
- const existing = isExisting ? chalk.blue(' [exists]') : '';
1914
- console.log(` ${marker} /${cmd.name}${required}${existing} - ${chalk.dim(cmd.description)}`);
1915
- }
1916
- console.log('');
1917
- }
2033
+ if (options.skipPrompts) {
2034
+ // Use default selections when called non-interactively
2035
+ selectedCommands = AVAILABLE_COMMANDS.filter(c => c.selected).map(c => c.name);
2036
+ console.log(chalk.dim(` Auto-selecting ${selectedCommands.length} default command(s)`));
2037
+ } else {
2038
+ const categories = [...new Set(AVAILABLE_COMMANDS.map((c) => c.category))];
1918
2039
 
1919
- // Ask which commands to install
1920
- const { selectedCommands } = await inquirer.prompt([
1921
- {
1922
- type: 'checkbox',
1923
- name: 'selectedCommands',
1924
- message: 'Select commands to install (existing commands marked with [exists]):',
1925
- choices: AVAILABLE_COMMANDS.map((cmd) => {
2040
+ for (const category of categories) {
2041
+ console.log(chalk.cyan(` ${category}:`));
2042
+ const cmds = AVAILABLE_COMMANDS.filter((c) => c.category === category);
2043
+ for (const cmd of cmds) {
1926
2044
  const isExisting = existingCmdNames.includes(cmd.name);
1927
- return {
1928
- name: `/${cmd.name}${isExisting ? ' [exists]' : ''} - ${cmd.description}`,
1929
- value: cmd.name,
1930
- checked: cmd.selected,
1931
- disabled: cmd.required ? 'Required' : false,
1932
- };
1933
- }),
1934
- pageSize: 15,
1935
- },
1936
- ]);
2045
+ const marker = cmd.selected ? chalk.green('●') : chalk.dim('○');
2046
+ const required = cmd.required ? chalk.yellow(' (required)') : '';
2047
+ const existing = isExisting ? chalk.blue(' [exists]') : '';
2048
+ console.log(` ${marker} /${cmd.name}${required}${existing} - ${chalk.dim(cmd.description)}`);
2049
+ }
2050
+ console.log('');
2051
+ }
2052
+
2053
+ // Ask which commands to install
2054
+ const result = await inquirer.prompt([
2055
+ {
2056
+ type: 'checkbox',
2057
+ name: 'selectedCommands',
2058
+ message: 'Select commands to install (existing commands marked with [exists]):',
2059
+ choices: AVAILABLE_COMMANDS.map((cmd) => {
2060
+ const isExisting = existingCmdNames.includes(cmd.name);
2061
+ return {
2062
+ name: `/${cmd.name}${isExisting ? ' [exists]' : ''} - ${cmd.description}`,
2063
+ value: cmd.name,
2064
+ checked: cmd.selected,
2065
+ disabled: cmd.required ? 'Required' : false,
2066
+ };
2067
+ }),
2068
+ pageSize: 15,
2069
+ },
2070
+ ]);
2071
+ selectedCommands = result.selectedCommands;
2072
+ }
1937
2073
 
1938
2074
  // Always include required commands AND feature-specific commands
1939
2075
  const requiredCommands = AVAILABLE_COMMANDS.filter(c => c.required).map(c => c.name);
@@ -1960,6 +2096,17 @@ export async function runInit(options = {}) {
1960
2096
 
1961
2097
  let overwrite = options.force || false;
1962
2098
  if (commandsToOverwrite.length > 0 && !overwrite) {
2099
+ // In skipPrompts mode, preserve all existing commands (no overwrite)
2100
+ if (options.skipPrompts) {
2101
+ for (const cmd of commandsToOverwrite) {
2102
+ smartMergeDecisions[cmd] = 'skip';
2103
+ }
2104
+ // Filter out skipped commands
2105
+ const filtered = finalCommands.filter((c) => !commandsToOverwrite.includes(c) || requiredCommands.includes(c));
2106
+ finalCommands.length = 0;
2107
+ finalCommands.push(...filtered);
2108
+ console.log(chalk.dim(` Preserving ${commandsToOverwrite.length} existing command(s), installing ${finalCommands.length} new`));
2109
+ } else {
1963
2110
  // Check for customized assets that have been used
1964
2111
  const assetsNeedingMerge = getAssetsNeedingMerge(process.cwd());
1965
2112
  const customizedCommands = commandsToOverwrite.filter(cmd =>
@@ -2152,6 +2299,7 @@ export async function runInit(options = {}) {
2152
2299
  finalCommands.push(...filtered);
2153
2300
  }
2154
2301
  }
2302
+ } // end else (!options.skipPrompts)
2155
2303
  }
2156
2304
 
2157
2305
  // Track if we should create backups (set outside the if block for use later)
@@ -2254,9 +2402,10 @@ export async function runInit(options = {}) {
2254
2402
  for (const hookName of featureHooks) {
2255
2403
  try {
2256
2404
  const hookPath = join(hooksDir, `${hookName}.js`);
2405
+ const hookExists = existsSync(hookPath);
2257
2406
 
2258
- // Skip if already exists
2259
- if (existsSync(hookPath)) {
2407
+ // Respect overwrite setting for hooks (like commands)
2408
+ if (hookExists && !overwrite) {
2260
2409
  console.log(chalk.blue(` ○ hooks/${hookName}.js exists (preserved)`));
2261
2410
  continue;
2262
2411
  }
@@ -2264,10 +2413,18 @@ export async function runInit(options = {}) {
2264
2413
  // Try to load from templates/hooks/ folder
2265
2414
  const templatePath = join(__dirname, '..', '..', 'templates', 'hooks', `${hookName}.template.js`);
2266
2415
  if (existsSync(templatePath)) {
2416
+ // Create backup if overwriting existing hook
2417
+ if (hookExists && overwrite) {
2418
+ const backupPath = createBackup(hookPath);
2419
+ if (backupPath) {
2420
+ backedUpFiles.push({ original: hookPath, backup: backupPath });
2421
+ }
2422
+ }
2267
2423
  const hookContent = readFileSync(templatePath, 'utf8');
2268
2424
  writeFileSync(hookPath, hookContent, 'utf8');
2269
2425
  deployedHooks.push(hookName);
2270
- console.log(chalk.green(` ✓ Created hooks/${hookName}.js`));
2426
+ const action = hookExists ? 'Updated' : 'Created';
2427
+ console.log(chalk.green(` ✓ ${action} hooks/${hookName}.js`));
2271
2428
  } else {
2272
2429
  failedHooks.push({ name: hookName, error: 'No template found' });
2273
2430
  console.log(chalk.yellow(` ⚠ Skipped hooks/${hookName}.js (no template)`));
@@ -2283,6 +2440,56 @@ export async function runInit(options = {}) {
2283
2440
  }
2284
2441
  }
2285
2442
 
2443
+ // Step 6c: Deploy feature skills
2444
+ const deployedSkills = [];
2445
+ const failedSkills = [];
2446
+
2447
+ if (featureSkills.length > 0) {
2448
+ console.log(chalk.bold('\nStep 6c: Deploying feature skills\n'));
2449
+
2450
+ for (const skillName of featureSkills) {
2451
+ try {
2452
+ const skillPath = join(skillsDir, skillName);
2453
+ const skillExists = existsSync(skillPath);
2454
+
2455
+ // Respect overwrite setting for skills (like commands)
2456
+ if (skillExists && !overwrite) {
2457
+ console.log(chalk.blue(` ○ skills/${skillName}/ exists (preserved)`));
2458
+ continue;
2459
+ }
2460
+
2461
+ // Try to load from templates/skills/ folder
2462
+ const templatePath = join(__dirname, '..', '..', 'templates', 'skills', skillName);
2463
+ if (existsSync(templatePath)) {
2464
+ // Create backup if overwriting existing skill
2465
+ if (skillExists && overwrite) {
2466
+ const backupPath = createBackup(skillPath);
2467
+ if (backupPath) {
2468
+ backedUpFiles.push({ original: skillPath, backup: backupPath });
2469
+ }
2470
+ }
2471
+ // Create skill directory and copy recursively
2472
+ mkdirSync(skillPath, { recursive: true });
2473
+ const { cpSync } = await import('fs');
2474
+ cpSync(templatePath, skillPath, { recursive: true });
2475
+ deployedSkills.push(skillName);
2476
+ const action = skillExists ? 'Updated' : 'Created';
2477
+ console.log(chalk.green(` ✓ ${action} skills/${skillName}/`));
2478
+ } else {
2479
+ failedSkills.push({ name: skillName, error: 'No template found' });
2480
+ console.log(chalk.yellow(` ⚠ Skipped skills/${skillName}/ (no template)`));
2481
+ }
2482
+ } catch (error) {
2483
+ failedSkills.push({ name: skillName, error: error.message });
2484
+ console.log(chalk.red(` ✗ Failed: skills/${skillName}/ - ${error.message}`));
2485
+ }
2486
+ }
2487
+
2488
+ if (deployedSkills.length > 0) {
2489
+ console.log(chalk.green(`\n ✓ Deployed ${deployedSkills.length} feature skill(s)`));
2490
+ }
2491
+ }
2492
+
2286
2493
  // Step 7: Generate INDEX.md
2287
2494
  const indexPath = join(commandsDir, 'INDEX.md');
2288
2495
  const indexContent = generateIndexFile(installed, projectName);
@@ -2416,6 +2623,8 @@ export async function runInit(options = {}) {
2416
2623
  featureCommands: featureCommands.filter(c => installed.includes(c)),
2417
2624
  hooks: deployedHooks,
2418
2625
  featureHooks: featureHooks,
2626
+ skills: deployedSkills,
2627
+ featureSkills: featureSkills,
2419
2628
  enabledFeatures: selectedFeatures,
2420
2629
  timestamp: new Date().toISOString(),
2421
2630
  },
@@ -2428,6 +2637,26 @@ export async function runInit(options = {}) {
2428
2637
  console.log(chalk.blue(' ○ config/tech-stack.json exists (preserved)'));
2429
2638
  }
2430
2639
 
2640
+ // Update ccasp-state.json with current version (fixes version display in /menu)
2641
+ const ccaspStatePath = join(configDir, 'ccasp-state.json');
2642
+ const currentVersion = getVersion();
2643
+ let ccaspState = { currentVersion, lastCheckTimestamp: 0, updateAvailable: false };
2644
+
2645
+ if (existsSync(ccaspStatePath)) {
2646
+ try {
2647
+ ccaspState = JSON.parse(readFileSync(ccaspStatePath, 'utf8'));
2648
+ } catch {
2649
+ // Use default state if parse fails
2650
+ }
2651
+ }
2652
+
2653
+ // Always update the current version to match installed CCASP
2654
+ ccaspState.currentVersion = currentVersion;
2655
+ ccaspState.installedAt = new Date().toISOString();
2656
+
2657
+ writeFileSync(ccaspStatePath, JSON.stringify(ccaspState, null, 2), 'utf8');
2658
+ console.log(chalk.green(` ✓ Updated ccasp-state.json (v${currentVersion})`));
2659
+
2431
2660
  // Show next steps
2432
2661
  console.log(chalk.bold('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
2433
2662
  console.log(chalk.bold('Next Steps:\n'));
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Install Panel Hook Command
3
+ *
4
+ * Installs the panel queue reader hook to Claude Code's hooks directory.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'fs';
9
+ import { join, dirname } from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ import { homedir } from 'os';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ /**
17
+ * Install the panel queue reader hook
18
+ */
19
+ export async function runInstallPanelHook(options = {}) {
20
+ console.log(chalk.cyan('\n Installing CCASP Panel Hook...\n'));
21
+
22
+ // Determine target directory
23
+ const targetDir = options.global
24
+ ? join(homedir(), '.claude', 'hooks')
25
+ : join(process.cwd(), '.claude', 'hooks');
26
+
27
+ const hookPath = join(targetDir, 'panel-queue-reader.js');
28
+ const settingsPath = options.global
29
+ ? join(homedir(), '.claude', 'settings.json')
30
+ : join(process.cwd(), '.claude', 'settings.json');
31
+
32
+ // Check if hook already exists
33
+ if (existsSync(hookPath) && !options.force) {
34
+ console.log(chalk.yellow(' Hook already installed.'));
35
+ console.log(chalk.dim(` Use --force to overwrite\n`));
36
+ return;
37
+ }
38
+
39
+ // Ensure hooks directory exists
40
+ if (!existsSync(targetDir)) {
41
+ mkdirSync(targetDir, { recursive: true });
42
+ }
43
+
44
+ // Read template
45
+ const templatePath = join(__dirname, '..', '..', 'templates', 'hooks', 'panel-queue-reader.template.js');
46
+
47
+ if (!existsSync(templatePath)) {
48
+ console.log(chalk.red(' Template not found.'));
49
+ console.log(chalk.dim(` Expected: ${templatePath}\n`));
50
+ return;
51
+ }
52
+
53
+ // Copy template to hooks directory
54
+ const templateContent = readFileSync(templatePath, 'utf8');
55
+ writeFileSync(hookPath, templateContent, 'utf8');
56
+
57
+ console.log(chalk.green(` ✓ Hook installed: ${hookPath}`));
58
+
59
+ // Update settings.json to register the hook
60
+ let settings = {};
61
+ if (existsSync(settingsPath)) {
62
+ try {
63
+ settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
64
+ } catch {
65
+ settings = {};
66
+ }
67
+ }
68
+
69
+ // Ensure hooks array exists
70
+ if (!settings.hooks) {
71
+ settings.hooks = [];
72
+ }
73
+
74
+ // Check if hook already registered
75
+ const hookConfig = {
76
+ event: 'UserPromptSubmit',
77
+ command: `node ${hookPath}`
78
+ };
79
+
80
+ const existingHook = settings.hooks.find(h =>
81
+ h.event === 'UserPromptSubmit' &&
82
+ h.command?.includes('panel-queue-reader')
83
+ );
84
+
85
+ if (!existingHook) {
86
+ settings.hooks.push(hookConfig);
87
+
88
+ // Ensure settings directory exists
89
+ const settingsDir = dirname(settingsPath);
90
+ if (!existsSync(settingsDir)) {
91
+ mkdirSync(settingsDir, { recursive: true });
92
+ }
93
+
94
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
95
+ console.log(chalk.green(` ✓ Hook registered in settings.json`));
96
+ } else {
97
+ console.log(chalk.dim(' Hook already registered in settings.json'));
98
+ }
99
+
100
+ console.log('');
101
+ console.log(chalk.white.bold(' Setup complete!'));
102
+ console.log('');
103
+ console.log(chalk.dim(' How to use:'));
104
+ console.log(chalk.dim(' 1. Open a new terminal and run: ccasp panel'));
105
+ console.log(chalk.dim(' 2. Select commands from the panel'));
106
+ console.log(chalk.dim(' 3. In Claude Code, press Enter to execute'));
107
+ console.log('');
108
+ }