cc4pm 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 (108) hide show
  1. package/.claude-plugin/README.md +17 -0
  2. package/.claude-plugin/plugin.json +25 -0
  3. package/LICENSE +21 -0
  4. package/README.md +157 -0
  5. package/README.zh-CN.md +134 -0
  6. package/contexts/dev.md +20 -0
  7. package/contexts/research.md +26 -0
  8. package/contexts/review.md +22 -0
  9. package/examples/CLAUDE.md +100 -0
  10. package/examples/statusline.json +19 -0
  11. package/examples/user-CLAUDE.md +109 -0
  12. package/install.sh +17 -0
  13. package/manifests/install-components.json +173 -0
  14. package/manifests/install-modules.json +335 -0
  15. package/manifests/install-profiles.json +75 -0
  16. package/package.json +117 -0
  17. package/schemas/ecc-install-config.schema.json +58 -0
  18. package/schemas/hooks.schema.json +197 -0
  19. package/schemas/install-components.schema.json +56 -0
  20. package/schemas/install-modules.schema.json +105 -0
  21. package/schemas/install-profiles.schema.json +45 -0
  22. package/schemas/install-state.schema.json +210 -0
  23. package/schemas/package-manager.schema.json +23 -0
  24. package/schemas/plugin.schema.json +58 -0
  25. package/scripts/ci/catalog.js +83 -0
  26. package/scripts/ci/validate-agents.js +81 -0
  27. package/scripts/ci/validate-commands.js +135 -0
  28. package/scripts/ci/validate-hooks.js +239 -0
  29. package/scripts/ci/validate-install-manifests.js +211 -0
  30. package/scripts/ci/validate-no-personal-paths.js +63 -0
  31. package/scripts/ci/validate-rules.js +81 -0
  32. package/scripts/ci/validate-skills.js +54 -0
  33. package/scripts/claw.js +468 -0
  34. package/scripts/doctor.js +110 -0
  35. package/scripts/ecc.js +194 -0
  36. package/scripts/hooks/auto-tmux-dev.js +88 -0
  37. package/scripts/hooks/check-console-log.js +71 -0
  38. package/scripts/hooks/check-hook-enabled.js +12 -0
  39. package/scripts/hooks/cost-tracker.js +78 -0
  40. package/scripts/hooks/doc-file-warning.js +63 -0
  41. package/scripts/hooks/evaluate-session.js +100 -0
  42. package/scripts/hooks/insaits-security-monitor.py +269 -0
  43. package/scripts/hooks/insaits-security-wrapper.js +88 -0
  44. package/scripts/hooks/post-bash-build-complete.js +27 -0
  45. package/scripts/hooks/post-bash-pr-created.js +36 -0
  46. package/scripts/hooks/post-edit-console-warn.js +54 -0
  47. package/scripts/hooks/post-edit-format.js +109 -0
  48. package/scripts/hooks/post-edit-typecheck.js +96 -0
  49. package/scripts/hooks/pre-bash-dev-server-block.js +187 -0
  50. package/scripts/hooks/pre-bash-git-push-reminder.js +28 -0
  51. package/scripts/hooks/pre-bash-tmux-reminder.js +33 -0
  52. package/scripts/hooks/pre-compact.js +48 -0
  53. package/scripts/hooks/pre-write-doc-warn.js +9 -0
  54. package/scripts/hooks/quality-gate.js +168 -0
  55. package/scripts/hooks/run-with-flags-shell.sh +32 -0
  56. package/scripts/hooks/run-with-flags.js +120 -0
  57. package/scripts/hooks/session-end-marker.js +15 -0
  58. package/scripts/hooks/session-end.js +299 -0
  59. package/scripts/hooks/session-start.js +97 -0
  60. package/scripts/hooks/suggest-compact.js +80 -0
  61. package/scripts/install-apply.js +137 -0
  62. package/scripts/install-plan.js +254 -0
  63. package/scripts/lib/hook-flags.js +74 -0
  64. package/scripts/lib/install/apply.js +23 -0
  65. package/scripts/lib/install/config.js +82 -0
  66. package/scripts/lib/install/request.js +113 -0
  67. package/scripts/lib/install/runtime.js +42 -0
  68. package/scripts/lib/install-executor.js +605 -0
  69. package/scripts/lib/install-lifecycle.js +763 -0
  70. package/scripts/lib/install-manifests.js +305 -0
  71. package/scripts/lib/install-state.js +120 -0
  72. package/scripts/lib/install-targets/antigravity-project.js +9 -0
  73. package/scripts/lib/install-targets/claude-home.js +10 -0
  74. package/scripts/lib/install-targets/codex-home.js +10 -0
  75. package/scripts/lib/install-targets/cursor-project.js +10 -0
  76. package/scripts/lib/install-targets/helpers.js +89 -0
  77. package/scripts/lib/install-targets/opencode-home.js +10 -0
  78. package/scripts/lib/install-targets/registry.js +64 -0
  79. package/scripts/lib/orchestration-session.js +299 -0
  80. package/scripts/lib/package-manager.d.ts +119 -0
  81. package/scripts/lib/package-manager.js +431 -0
  82. package/scripts/lib/project-detect.js +428 -0
  83. package/scripts/lib/resolve-formatter.js +185 -0
  84. package/scripts/lib/session-adapters/canonical-session.js +138 -0
  85. package/scripts/lib/session-adapters/claude-history.js +149 -0
  86. package/scripts/lib/session-adapters/dmux-tmux.js +80 -0
  87. package/scripts/lib/session-adapters/registry.js +111 -0
  88. package/scripts/lib/session-aliases.d.ts +136 -0
  89. package/scripts/lib/session-aliases.js +481 -0
  90. package/scripts/lib/session-manager.d.ts +131 -0
  91. package/scripts/lib/session-manager.js +464 -0
  92. package/scripts/lib/shell-split.js +86 -0
  93. package/scripts/lib/skill-improvement/amendify.js +89 -0
  94. package/scripts/lib/skill-improvement/evaluate.js +59 -0
  95. package/scripts/lib/skill-improvement/health.js +118 -0
  96. package/scripts/lib/skill-improvement/observations.js +108 -0
  97. package/scripts/lib/tmux-worktree-orchestrator.js +491 -0
  98. package/scripts/lib/utils.d.ts +183 -0
  99. package/scripts/lib/utils.js +543 -0
  100. package/scripts/list-installed.js +90 -0
  101. package/scripts/orchestrate-codex-worker.sh +92 -0
  102. package/scripts/orchestrate-worktrees.js +108 -0
  103. package/scripts/orchestration-status.js +62 -0
  104. package/scripts/repair.js +97 -0
  105. package/scripts/session-inspect.js +150 -0
  106. package/scripts/setup-package-manager.js +204 -0
  107. package/scripts/skill-create-output.js +244 -0
  108. package/scripts/uninstall.js +96 -0
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Package Manager Setup Script
4
+ *
5
+ * Interactive script to configure preferred package manager.
6
+ * Can be run directly or via the /setup-pm command.
7
+ *
8
+ * Usage:
9
+ * node scripts/setup-package-manager.js [pm-name]
10
+ * node scripts/setup-package-manager.js --detect
11
+ * node scripts/setup-package-manager.js --global pnpm
12
+ * node scripts/setup-package-manager.js --project bun
13
+ */
14
+
15
+ const {
16
+ PACKAGE_MANAGERS,
17
+ getPackageManager,
18
+ setPreferredPackageManager,
19
+ setProjectPackageManager,
20
+ getAvailablePackageManagers,
21
+ detectFromLockFile,
22
+ detectFromPackageJson
23
+ } = require('./lib/package-manager');
24
+
25
+ function showHelp() {
26
+ console.log(`
27
+ Package Manager Setup for Claude Code
28
+
29
+ Usage:
30
+ node scripts/setup-package-manager.js [options] [package-manager]
31
+
32
+ Options:
33
+ --detect Detect and show current package manager
34
+ --global <pm> Set global preference (saves to ~/.claude/package-manager.json)
35
+ --project <pm> Set project preference (saves to .claude/package-manager.json)
36
+ --list List available package managers
37
+ --help Show this help message
38
+
39
+ Package Managers:
40
+ npm Node Package Manager (default with Node.js)
41
+ pnpm Fast, disk space efficient package manager
42
+ yarn Classic Yarn package manager
43
+ bun All-in-one JavaScript runtime & toolkit
44
+
45
+ Examples:
46
+ # Detect current package manager
47
+ node scripts/setup-package-manager.js --detect
48
+
49
+ # Set pnpm as global preference
50
+ node scripts/setup-package-manager.js --global pnpm
51
+
52
+ # Set bun for current project
53
+ node scripts/setup-package-manager.js --project bun
54
+
55
+ # List available package managers
56
+ node scripts/setup-package-manager.js --list
57
+ `);
58
+ }
59
+
60
+ function detectAndShow() {
61
+ const pm = getPackageManager();
62
+ const available = getAvailablePackageManagers();
63
+ const fromLock = detectFromLockFile();
64
+ const fromPkg = detectFromPackageJson();
65
+
66
+ console.log('\n=== Package Manager Detection ===\n');
67
+
68
+ console.log('Current selection:');
69
+ console.log(` Package Manager: ${pm.name}`);
70
+ console.log(` Source: ${pm.source}`);
71
+ console.log('');
72
+
73
+ console.log('Detection results:');
74
+ console.log(` From package.json: ${fromPkg || 'not specified'}`);
75
+ console.log(` From lock file: ${fromLock || 'not found'}`);
76
+ console.log(` Environment var: ${process.env.CLAUDE_PACKAGE_MANAGER || 'not set'}`);
77
+ console.log('');
78
+
79
+ console.log('Available package managers:');
80
+ for (const pmName of Object.keys(PACKAGE_MANAGERS)) {
81
+ const installed = available.includes(pmName);
82
+ const indicator = installed ? '✓' : '✗';
83
+ const current = pmName === pm.name ? ' (current)' : '';
84
+ console.log(` ${indicator} ${pmName}${current}`);
85
+ }
86
+
87
+ console.log('');
88
+ console.log('Commands:');
89
+ console.log(` Install: ${pm.config.installCmd}`);
90
+ console.log(` Run script: ${pm.config.runCmd} [script-name]`);
91
+ console.log(` Execute binary: ${pm.config.execCmd} [binary-name]`);
92
+ console.log('');
93
+ }
94
+
95
+ function listAvailable() {
96
+ const available = getAvailablePackageManagers();
97
+ const pm = getPackageManager();
98
+
99
+ console.log('\nAvailable Package Managers:\n');
100
+
101
+ for (const pmName of Object.keys(PACKAGE_MANAGERS)) {
102
+ const config = PACKAGE_MANAGERS[pmName];
103
+ const installed = available.includes(pmName);
104
+ const current = pmName === pm.name ? ' (current)' : '';
105
+
106
+ console.log(`${pmName}${current}`);
107
+ console.log(` Installed: ${installed ? 'Yes' : 'No'}`);
108
+ console.log(` Lock file: ${config.lockFile}`);
109
+ console.log(` Install: ${config.installCmd}`);
110
+ console.log(` Run: ${config.runCmd}`);
111
+ console.log('');
112
+ }
113
+ }
114
+
115
+ function setGlobal(pmName) {
116
+ if (!PACKAGE_MANAGERS[pmName]) {
117
+ console.error(`Error: Unknown package manager "${pmName}"`);
118
+ console.error(`Available: ${Object.keys(PACKAGE_MANAGERS).join(', ')}`);
119
+ process.exit(1);
120
+ }
121
+
122
+ const available = getAvailablePackageManagers();
123
+ if (!available.includes(pmName)) {
124
+ console.warn(`Warning: ${pmName} is not installed on your system`);
125
+ }
126
+
127
+ try {
128
+ setPreferredPackageManager(pmName);
129
+ console.log(`\n✓ Global preference set to: ${pmName}`);
130
+ console.log(' Saved to: ~/.claude/package-manager.json');
131
+ console.log('');
132
+ } catch (err) {
133
+ console.error(`Error: ${err.message}`);
134
+ process.exit(1);
135
+ }
136
+ }
137
+
138
+ function setProject(pmName) {
139
+ if (!PACKAGE_MANAGERS[pmName]) {
140
+ console.error(`Error: Unknown package manager "${pmName}"`);
141
+ console.error(`Available: ${Object.keys(PACKAGE_MANAGERS).join(', ')}`);
142
+ process.exit(1);
143
+ }
144
+
145
+ try {
146
+ setProjectPackageManager(pmName);
147
+ console.log(`\n✓ Project preference set to: ${pmName}`);
148
+ console.log(' Saved to: .claude/package-manager.json');
149
+ console.log('');
150
+ } catch (err) {
151
+ console.error(`Error: ${err.message}`);
152
+ process.exit(1);
153
+ }
154
+ }
155
+
156
+ // Main
157
+ const args = process.argv.slice(2);
158
+
159
+ if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
160
+ showHelp();
161
+ process.exit(0);
162
+ }
163
+
164
+ if (args.includes('--detect')) {
165
+ detectAndShow();
166
+ process.exit(0);
167
+ }
168
+
169
+ if (args.includes('--list')) {
170
+ listAvailable();
171
+ process.exit(0);
172
+ }
173
+
174
+ const globalIdx = args.indexOf('--global');
175
+ if (globalIdx !== -1) {
176
+ const pmName = args[globalIdx + 1];
177
+ if (!pmName || pmName.startsWith('-')) {
178
+ console.error('Error: --global requires a package manager name');
179
+ process.exit(1);
180
+ }
181
+ setGlobal(pmName);
182
+ process.exit(0);
183
+ }
184
+
185
+ const projectIdx = args.indexOf('--project');
186
+ if (projectIdx !== -1) {
187
+ const pmName = args[projectIdx + 1];
188
+ if (!pmName || pmName.startsWith('-')) {
189
+ console.error('Error: --project requires a package manager name');
190
+ process.exit(1);
191
+ }
192
+ setProject(pmName);
193
+ process.exit(0);
194
+ }
195
+
196
+ // If just a package manager name is provided, set it globally
197
+ const pmName = args[0];
198
+ if (PACKAGE_MANAGERS[pmName]) {
199
+ setGlobal(pmName);
200
+ } else {
201
+ console.error(`Error: Unknown option or package manager "${pmName}"`);
202
+ showHelp();
203
+ process.exit(1);
204
+ }
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Skill Creator - Pretty Output Formatter
4
+ *
5
+ * Creates beautiful terminal output for the /skill-create command
6
+ * similar to @mvanhorn's /last30days skill
7
+ */
8
+
9
+ // ANSI color codes - no external dependencies
10
+ const chalk = {
11
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
12
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
13
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
14
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
15
+ magenta: (s) => `\x1b[35m${s}\x1b[0m`,
16
+ gray: (s) => `\x1b[90m${s}\x1b[0m`,
17
+ white: (s) => `\x1b[37m${s}\x1b[0m`,
18
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
19
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
20
+ bgCyan: (s) => `\x1b[46m${s}\x1b[0m`,
21
+ };
22
+
23
+ // Box drawing characters
24
+ const BOX = {
25
+ topLeft: '╭',
26
+ topRight: '╮',
27
+ bottomLeft: '╰',
28
+ bottomRight: '╯',
29
+ horizontal: '─',
30
+ vertical: '│',
31
+ verticalRight: '├',
32
+ verticalLeft: '┤',
33
+ };
34
+
35
+ // Progress spinner frames
36
+ const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
37
+
38
+ // Helper functions
39
+ function box(title, content, width = 60) {
40
+ const lines = content.split('\n');
41
+ const top = `${BOX.topLeft}${BOX.horizontal} ${chalk.bold(chalk.cyan(title))} ${BOX.horizontal.repeat(Math.max(0, width - title.length - 5))}${BOX.topRight}`;
42
+ const bottom = `${BOX.bottomLeft}${BOX.horizontal.repeat(width - 2)}${BOX.bottomRight}`;
43
+ const middle = lines.map(line => {
44
+ const padding = width - 4 - stripAnsi(line).length;
45
+ return `${BOX.vertical} ${line}${' '.repeat(Math.max(0, padding))} ${BOX.vertical}`;
46
+ }).join('\n');
47
+ return `${top}\n${middle}\n${bottom}`;
48
+ }
49
+
50
+ function stripAnsi(str) {
51
+ // eslint-disable-next-line no-control-regex
52
+ return str.replace(/\x1b\[[0-9;]*m/g, '');
53
+ }
54
+
55
+ function progressBar(percent, width = 30) {
56
+ const filled = Math.min(width, Math.max(0, Math.round(width * percent / 100)));
57
+ const empty = width - filled;
58
+ const bar = chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
59
+ return `${bar} ${chalk.bold(percent)}%`;
60
+ }
61
+
62
+ function sleep(ms) {
63
+ return new Promise(resolve => setTimeout(resolve, ms));
64
+ }
65
+
66
+ async function animateProgress(label, steps, callback) {
67
+ process.stdout.write(`\n${chalk.cyan('⏳')} ${label}...\n`);
68
+
69
+ for (let i = 0; i < steps.length; i++) {
70
+ const step = steps[i];
71
+ process.stdout.write(` ${chalk.gray(SPINNER[i % SPINNER.length])} ${step.name}`);
72
+ await sleep(step.duration || 500);
73
+ process.stdout.clearLine?.(0) || process.stdout.write('\r');
74
+ process.stdout.cursorTo?.(0) || process.stdout.write('\r');
75
+ process.stdout.write(` ${chalk.green('✓')} ${step.name}\n`);
76
+ if (callback) callback(step, i);
77
+ }
78
+ }
79
+
80
+ // Main output formatter
81
+ class SkillCreateOutput {
82
+ constructor(repoName, options = {}) {
83
+ this.repoName = repoName;
84
+ this.options = options;
85
+ this.width = options.width || 70;
86
+ }
87
+
88
+ header() {
89
+ const subtitle = `Extracting patterns from ${chalk.cyan(this.repoName)}`;
90
+
91
+ console.log('\n');
92
+ console.log(chalk.bold(chalk.magenta('╔════════════════════════════════════════════════════════════════╗')));
93
+ console.log(chalk.bold(chalk.magenta('║')) + chalk.bold(' 🔮 cc4pm Skill Creator ') + chalk.bold(chalk.magenta('║')));
94
+ console.log(chalk.bold(chalk.magenta('║')) + ` ${subtitle}${' '.repeat(Math.max(0, 59 - stripAnsi(subtitle).length))}` + chalk.bold(chalk.magenta('║')));
95
+ console.log(chalk.bold(chalk.magenta('╚════════════════════════════════════════════════════════════════╝')));
96
+ console.log('');
97
+ }
98
+
99
+ async analyzePhase(data) {
100
+ const steps = [
101
+ { name: 'Parsing git history...', duration: 300 },
102
+ { name: `Found ${chalk.yellow(data.commits)} commits`, duration: 200 },
103
+ { name: 'Analyzing commit patterns...', duration: 400 },
104
+ { name: 'Detecting file co-changes...', duration: 300 },
105
+ { name: 'Identifying workflows...', duration: 400 },
106
+ { name: 'Extracting architecture patterns...', duration: 300 },
107
+ ];
108
+
109
+ await animateProgress('Analyzing Repository', steps);
110
+ }
111
+
112
+ analysisResults(data) {
113
+ console.log('\n');
114
+ console.log(box('📊 Analysis Results', `
115
+ ${chalk.bold('Commits Analyzed:')} ${chalk.yellow(data.commits)}
116
+ ${chalk.bold('Time Range:')} ${chalk.gray(data.timeRange)}
117
+ ${chalk.bold('Contributors:')} ${chalk.cyan(data.contributors)}
118
+ ${chalk.bold('Files Tracked:')} ${chalk.green(data.files)}
119
+ `));
120
+ }
121
+
122
+ patterns(patterns) {
123
+ console.log('\n');
124
+ console.log(chalk.bold(chalk.cyan('🔍 Key Patterns Discovered:')));
125
+ console.log(chalk.gray('─'.repeat(50)));
126
+
127
+ patterns.forEach((pattern, i) => {
128
+ const confidence = pattern.confidence ?? 0.8;
129
+ const confidenceBar = progressBar(Math.round(confidence * 100), 15);
130
+ console.log(`
131
+ ${chalk.bold(chalk.yellow(`${i + 1}.`))} ${chalk.bold(pattern.name)}
132
+ ${chalk.gray('Trigger:')} ${pattern.trigger}
133
+ ${chalk.gray('Confidence:')} ${confidenceBar}
134
+ ${chalk.dim(pattern.evidence)}`);
135
+ });
136
+ }
137
+
138
+ instincts(instincts) {
139
+ console.log('\n');
140
+ console.log(box('🧠 Instincts Generated', instincts.map((inst, i) =>
141
+ `${chalk.yellow(`${i + 1}.`)} ${chalk.bold(inst.name)} ${chalk.gray(`(${Math.round(inst.confidence * 100)}%)`)}`
142
+ ).join('\n')));
143
+ }
144
+
145
+ output(skillPath, instinctsPath) {
146
+ console.log('\n');
147
+ console.log(chalk.bold(chalk.green('✨ Generation Complete!')));
148
+ console.log(chalk.gray('─'.repeat(50)));
149
+ console.log(`
150
+ ${chalk.green('📄')} ${chalk.bold('Skill File:')}
151
+ ${chalk.cyan(skillPath)}
152
+
153
+ ${chalk.green('🧠')} ${chalk.bold('Instincts File:')}
154
+ ${chalk.cyan(instinctsPath)}
155
+ `);
156
+ }
157
+
158
+ nextSteps() {
159
+ console.log(box('📋 Next Steps', `
160
+ ${chalk.yellow('1.')} Review the generated SKILL.md
161
+ ${chalk.yellow('2.')} Import instincts: ${chalk.cyan('/instinct-import <path>')}
162
+ ${chalk.yellow('3.')} View learned patterns: ${chalk.cyan('/instinct-status')}
163
+ ${chalk.yellow('4.')} Evolve into skills: ${chalk.cyan('/evolve')}
164
+ `));
165
+ console.log('\n');
166
+ }
167
+
168
+ footer() {
169
+ console.log(chalk.gray('─'.repeat(60)));
170
+ console.log(chalk.dim(` Powered by cc4pm • ecc.tools`));
171
+ console.log(chalk.dim(` GitHub App: github.com/apps/skill-creator`));
172
+ console.log('\n');
173
+ }
174
+ }
175
+
176
+ // Demo function to show the output
177
+ async function demo() {
178
+ const output = new SkillCreateOutput('PMX');
179
+
180
+ output.header();
181
+
182
+ await output.analyzePhase({
183
+ commits: 200,
184
+ });
185
+
186
+ output.analysisResults({
187
+ commits: 200,
188
+ timeRange: 'Nov 2024 - Jan 2025',
189
+ contributors: 4,
190
+ files: 847,
191
+ });
192
+
193
+ output.patterns([
194
+ {
195
+ name: 'Conventional Commits',
196
+ trigger: 'when writing commit messages',
197
+ confidence: 0.85,
198
+ evidence: 'Found in 150/200 commits (feat:, fix:, refactor:)',
199
+ },
200
+ {
201
+ name: 'Client/Server Component Split',
202
+ trigger: 'when creating Next.js pages',
203
+ confidence: 0.90,
204
+ evidence: 'Observed in markets/, premarkets/, portfolio/',
205
+ },
206
+ {
207
+ name: 'Service Layer Architecture',
208
+ trigger: 'when adding backend logic',
209
+ confidence: 0.85,
210
+ evidence: 'Business logic in services/, not routes/',
211
+ },
212
+ {
213
+ name: 'TDD with E2E Tests',
214
+ trigger: 'when adding features',
215
+ confidence: 0.75,
216
+ evidence: '9 E2E test files, test(e2e) commits common',
217
+ },
218
+ ]);
219
+
220
+ output.instincts([
221
+ { name: 'pmx-conventional-commits', confidence: 0.85 },
222
+ { name: 'pmx-client-component-pattern', confidence: 0.90 },
223
+ { name: 'pmx-service-layer', confidence: 0.85 },
224
+ { name: 'pmx-e2e-test-location', confidence: 0.90 },
225
+ { name: 'pmx-package-manager', confidence: 0.95 },
226
+ { name: 'pmx-hot-path-caution', confidence: 0.90 },
227
+ ]);
228
+
229
+ output.output(
230
+ '.claude/skills/pmx-patterns/SKILL.md',
231
+ '.claude/homunculus/instincts/inherited/pmx-instincts.yaml'
232
+ );
233
+
234
+ output.nextSteps();
235
+ output.footer();
236
+ }
237
+
238
+ // Export for use in other scripts
239
+ module.exports = { SkillCreateOutput, demo };
240
+
241
+ // Run demo if executed directly
242
+ if (require.main === module) {
243
+ demo().catch(console.error);
244
+ }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { uninstallInstalledStates } = require('./lib/install-lifecycle');
4
+ const { SUPPORTED_INSTALL_TARGETS } = require('./lib/install-manifests');
5
+
6
+ function showHelp(exitCode = 0) {
7
+ console.log(`
8
+ Usage: node scripts/uninstall.js [--target <${SUPPORTED_INSTALL_TARGETS.join('|')}>] [--dry-run] [--json]
9
+
10
+ Remove ECC-managed files recorded in install-state for the current context.
11
+ `);
12
+ process.exit(exitCode);
13
+ }
14
+
15
+ function parseArgs(argv) {
16
+ const args = argv.slice(2);
17
+ const parsed = {
18
+ targets: [],
19
+ dryRun: false,
20
+ json: false,
21
+ help: false,
22
+ };
23
+
24
+ for (let index = 0; index < args.length; index += 1) {
25
+ const arg = args[index];
26
+
27
+ if (arg === '--target') {
28
+ parsed.targets.push(args[index + 1] || null);
29
+ index += 1;
30
+ } else if (arg === '--dry-run') {
31
+ parsed.dryRun = true;
32
+ } else if (arg === '--json') {
33
+ parsed.json = true;
34
+ } else if (arg === '--help' || arg === '-h') {
35
+ parsed.help = true;
36
+ } else {
37
+ throw new Error(`Unknown argument: ${arg}`);
38
+ }
39
+ }
40
+
41
+ return parsed;
42
+ }
43
+
44
+ function printHuman(result) {
45
+ if (result.results.length === 0) {
46
+ console.log('No cc4pm install-state files found for the current home/project context.');
47
+ return;
48
+ }
49
+
50
+ console.log('Uninstall summary:\n');
51
+ for (const entry of result.results) {
52
+ console.log(`- ${entry.adapter.id}`);
53
+ console.log(` Status: ${entry.status.toUpperCase()}`);
54
+ console.log(` Install-state: ${entry.installStatePath}`);
55
+
56
+ if (entry.error) {
57
+ console.log(` Error: ${entry.error}`);
58
+ continue;
59
+ }
60
+
61
+ const paths = result.dryRun ? entry.plannedRemovals : entry.removedPaths;
62
+ console.log(` ${result.dryRun ? 'Planned removals' : 'Removed paths'}: ${paths.length}`);
63
+ }
64
+
65
+ console.log(`\nSummary: checked=${result.summary.checkedCount}, ${result.dryRun ? 'planned' : 'uninstalled'}=${result.dryRun ? result.summary.plannedRemovalCount : result.summary.uninstalledCount}, errors=${result.summary.errorCount}`);
66
+ }
67
+
68
+ function main() {
69
+ try {
70
+ const options = parseArgs(process.argv);
71
+ if (options.help) {
72
+ showHelp(0);
73
+ }
74
+
75
+ const result = uninstallInstalledStates({
76
+ homeDir: process.env.HOME,
77
+ projectRoot: process.cwd(),
78
+ targets: options.targets,
79
+ dryRun: options.dryRun,
80
+ });
81
+ const hasErrors = result.summary.errorCount > 0;
82
+
83
+ if (options.json) {
84
+ console.log(JSON.stringify(result, null, 2));
85
+ } else {
86
+ printHuman(result);
87
+ }
88
+
89
+ process.exitCode = hasErrors ? 1 : 0;
90
+ } catch (error) {
91
+ console.error(`Error: ${error.message}`);
92
+ process.exit(1);
93
+ }
94
+ }
95
+
96
+ main();