knowzcode 0.1.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 (73) hide show
  1. package/.claude-plugin/marketplace.json +55 -0
  2. package/.claude-plugin/plugin.json +8 -0
  3. package/LICENSE +121 -0
  4. package/README.md +223 -0
  5. package/agents/analyst.md +121 -0
  6. package/agents/architect.md +121 -0
  7. package/agents/builder.md +155 -0
  8. package/agents/closer.md +148 -0
  9. package/agents/knowledge-migrator.md +349 -0
  10. package/agents/microfix-specialist.md +140 -0
  11. package/agents/reviewer.md +220 -0
  12. package/agents/update-coordinator.md +405 -0
  13. package/bin/knowzcode.mjs +869 -0
  14. package/commands/audit.md +108 -0
  15. package/commands/connect-mcp.md +507 -0
  16. package/commands/fix.md +107 -0
  17. package/commands/init.md +320 -0
  18. package/commands/learn.md +308 -0
  19. package/commands/plan.md +125 -0
  20. package/commands/register.md +724 -0
  21. package/commands/status.md +291 -0
  22. package/commands/telemetry-setup.md +368 -0
  23. package/commands/telemetry.md +188 -0
  24. package/commands/work.md +390 -0
  25. package/knowzcode/automation_manifest.md +59 -0
  26. package/knowzcode/claude_code_execution.md +133 -0
  27. package/knowzcode/enterprise/compliance_manifest.md +132 -0
  28. package/knowzcode/enterprise/compliance_status.md +30 -0
  29. package/knowzcode/enterprise/guidelines/code-quality.md +67 -0
  30. package/knowzcode/enterprise/guidelines/custom/.gitkeep +0 -0
  31. package/knowzcode/enterprise/guidelines/security.md +355 -0
  32. package/knowzcode/enterprise/reports/.gitkeep +0 -0
  33. package/knowzcode/enterprise/templates/guideline-template.md +55 -0
  34. package/knowzcode/gitignore.template +13 -0
  35. package/knowzcode/knowzcode_architecture.md +51 -0
  36. package/knowzcode/knowzcode_log.md +142 -0
  37. package/knowzcode/knowzcode_loop.md +515 -0
  38. package/knowzcode/knowzcode_project.md +233 -0
  39. package/knowzcode/knowzcode_tracker.md +40 -0
  40. package/knowzcode/knowzcode_vaults.md +104 -0
  41. package/knowzcode/mcp_config.md +166 -0
  42. package/knowzcode/planning/Readme.md +6 -0
  43. package/knowzcode/platform_adapters.md +388 -0
  44. package/knowzcode/prompts/Execute_Micro_Fix.md +57 -0
  45. package/knowzcode/prompts/Investigate_Codebase.md +227 -0
  46. package/knowzcode/prompts/Migrate_Knowledge.md +301 -0
  47. package/knowzcode/prompts/Refactor_Node.md +72 -0
  48. package/knowzcode/prompts/Spec_Verification_Checkpoint.md +59 -0
  49. package/knowzcode/prompts/[LOOP_1A]__Propose_Change_Set.md +52 -0
  50. package/knowzcode/prompts/[LOOP_1B]__Draft_Specs.md +75 -0
  51. package/knowzcode/prompts/[LOOP_2A]__Implement_Change_Set.md +55 -0
  52. package/knowzcode/prompts/[LOOP_2B]__Verify_Implementation.md +72 -0
  53. package/knowzcode/prompts/[LOOP_3]__Finalize_And_Commit.md +67 -0
  54. package/knowzcode/specs/Readme.md +10 -0
  55. package/knowzcode/telemetry_config.md +89 -0
  56. package/knowzcode/user_preferences.md +120 -0
  57. package/package.json +53 -0
  58. package/skills/alias-resolver.json +15 -0
  59. package/skills/architecture-diff.json +12 -0
  60. package/skills/check-installation-status.json +14 -0
  61. package/skills/continue.md +105 -0
  62. package/skills/environment-guard.json +12 -0
  63. package/skills/generate-workgroup-id.json +25 -0
  64. package/skills/install-knowzcode.json +21 -0
  65. package/skills/load-core-context.json +18 -0
  66. package/skills/log-entry-builder.json +15 -0
  67. package/skills/spec-quality-check.json +14 -0
  68. package/skills/spec-template.json +15 -0
  69. package/skills/spec-validator.json +25 -0
  70. package/skills/start-work.md +224 -0
  71. package/skills/tracker-scan.json +12 -0
  72. package/skills/tracker-update.json +28 -0
  73. package/skills/validate-installation.json +14 -0
@@ -0,0 +1,869 @@
1
+ #!/usr/bin/env node
2
+
3
+ // KnowzCode CLI — Zero-dependency Node.js installer
4
+ // Usage: npx knowzcode [install|uninstall|upgrade|detect] [options]
5
+
6
+ import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, readdirSync, rmSync, statSync } from 'fs';
7
+ import { join, resolve, dirname, basename } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import { createInterface } from 'readline/promises';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ const PKG_ROOT = resolve(__dirname, '..');
14
+ const VERSION = JSON.parse(readFileSync(join(PKG_ROOT, 'package.json'), 'utf8')).version;
15
+
16
+ // ─── Colors ──────────────────────────────────────────────────────────────────
17
+
18
+ const c = {
19
+ reset: '\x1b[0m',
20
+ bold: '\x1b[1m',
21
+ dim: '\x1b[2m',
22
+ red: '\x1b[31m',
23
+ green: '\x1b[32m',
24
+ yellow: '\x1b[33m',
25
+ blue: '\x1b[34m',
26
+ cyan: '\x1b[36m',
27
+ };
28
+
29
+ const log = {
30
+ info: (msg) => console.log(`${c.blue}[INFO]${c.reset} ${msg}`),
31
+ ok: (msg) => console.log(`${c.green}[OK]${c.reset} ${msg}`),
32
+ warn: (msg) => console.log(`${c.yellow}[WARN]${c.reset} ${msg}`),
33
+ err: (msg) => console.error(`${c.red}[ERROR]${c.reset} ${msg}`),
34
+ };
35
+
36
+ // ─── Platform Definitions ────────────────────────────────────────────────────
37
+
38
+ const PLATFORMS = {
39
+ claude: {
40
+ name: 'Claude Code',
41
+ detect: (dir) => existsSync(join(dir, '.claude')) || existsSync(join(dir, '.claude-plugin')),
42
+ adapterPath: null, // Claude uses .claude/ dir structure, not a single adapter file
43
+ },
44
+ codex: {
45
+ name: 'OpenAI Codex',
46
+ detect: (dir) => existsSync(join(dir, 'AGENTS.md')) || existsSync(join(dir, 'AGENTS.override.md')) || existsSync(join(dir, '.codex')),
47
+ adapterPath: (dir) => join(dir, 'AGENTS.md'),
48
+ templateHeader: '## OpenAI Codex (AGENTS.md)',
49
+ },
50
+ gemini: {
51
+ name: 'Gemini CLI',
52
+ detect: (dir) => existsSync(join(dir, 'GEMINI.md')) || existsSync(join(dir, '.gemini')),
53
+ adapterPath: (dir) => join(dir, 'GEMINI.md'),
54
+ templateHeader: '## Google Gemini CLI (GEMINI.md)',
55
+ },
56
+ cursor: {
57
+ name: 'Cursor',
58
+ detect: (dir) => existsSync(join(dir, '.cursor', 'rules')) || existsSync(join(dir, '.cursorrules')),
59
+ adapterPath: (dir) => join(dir, '.cursor', 'rules', 'knowzcode.mdc'),
60
+ templateHeader: '## Cursor (`.cursor/rules/knowzcode.mdc`)',
61
+ },
62
+ copilot: {
63
+ name: 'GitHub Copilot',
64
+ detect: (dir) => existsSync(join(dir, '.github', 'copilot-instructions.md')) || existsSync(join(dir, '.github')),
65
+ adapterPath: (dir) => join(dir, '.github', 'copilot-instructions.md'),
66
+ templateHeader: '## GitHub Copilot (.github/copilot-instructions.md)',
67
+ },
68
+ windsurf: {
69
+ name: 'Windsurf',
70
+ detect: (dir) => existsSync(join(dir, '.windsurf', 'rules')) || existsSync(join(dir, '.windsurfrules')),
71
+ adapterPath: (dir) => join(dir, '.windsurf', 'rules', 'knowzcode.md'),
72
+ templateHeader: '## Windsurf (`.windsurf/rules/knowzcode.md`)',
73
+ },
74
+ };
75
+
76
+ // ─── CLI Argument Parser ─────────────────────────────────────────────────────
77
+
78
+ function parseArgs(argv) {
79
+ const args = argv.slice(2);
80
+ const opts = {
81
+ command: null,
82
+ target: process.cwd(),
83
+ platforms: [],
84
+ force: false,
85
+ global: false,
86
+ verbose: false,
87
+ agentTeams: false,
88
+ };
89
+
90
+ let i = 0;
91
+ while (i < args.length) {
92
+ const arg = args[i];
93
+ if (arg === '--target' && i + 1 < args.length) {
94
+ opts.target = resolve(args[++i]);
95
+ } else if (arg === '--platforms' && i + 1 < args.length) {
96
+ opts.platforms = args[++i].split(',').map((p) => p.trim().toLowerCase());
97
+ } else if (arg === '--force') {
98
+ opts.force = true;
99
+ } else if (arg === '--global') {
100
+ opts.global = true;
101
+ } else if (arg === '--agent-teams') {
102
+ opts.agentTeams = true;
103
+ } else if (arg === '--verbose') {
104
+ opts.verbose = true;
105
+ } else if (arg === '--help' || arg === '-h') {
106
+ opts.command = 'help';
107
+ } else if (arg === '--version' || arg === '-v') {
108
+ opts.command = 'version';
109
+ } else if (!arg.startsWith('-') && !opts.command) {
110
+ opts.command = arg.toLowerCase();
111
+ }
112
+ i++;
113
+ }
114
+
115
+ return opts;
116
+ }
117
+
118
+ // ─── Platform Detection ──────────────────────────────────────────────────────
119
+
120
+ function detectPlatforms(dir) {
121
+ const detected = [];
122
+ for (const [id, platform] of Object.entries(PLATFORMS)) {
123
+ if (platform.detect(dir)) {
124
+ detected.push(id);
125
+ }
126
+ }
127
+ return detected;
128
+ }
129
+
130
+ // ─── Adapter Template Parser ─────────────────────────────────────────────────
131
+
132
+ function parseAdapterTemplates() {
133
+ const adaptersPath = join(PKG_ROOT, 'knowzcode', 'platform_adapters.md');
134
+ if (!existsSync(adaptersPath)) {
135
+ log.warn('platform_adapters.md not found — adapter generation will be skipped');
136
+ return new Map();
137
+ }
138
+
139
+ const content = readFileSync(adaptersPath, 'utf8');
140
+ const templates = new Map();
141
+
142
+ for (const [id, platform] of Object.entries(PLATFORMS)) {
143
+ if (!platform.templateHeader) continue;
144
+
145
+ const headerIdx = content.indexOf(platform.templateHeader);
146
+ if (headerIdx === -1) continue;
147
+
148
+ // Find the code fence after this header
149
+ const afterHeader = content.slice(headerIdx);
150
+ const fenceStart = afterHeader.indexOf('```markdown');
151
+ if (fenceStart === -1) continue;
152
+
153
+ const contentStart = afterHeader.indexOf('\n', fenceStart) + 1;
154
+ const fenceEnd = afterHeader.indexOf('\n```', contentStart);
155
+ if (fenceEnd === -1) continue;
156
+
157
+ templates.set(id, afterHeader.slice(contentStart, fenceEnd));
158
+ }
159
+
160
+ return templates;
161
+ }
162
+
163
+ // ─── File Copy Helpers ───────────────────────────────────────────────────────
164
+
165
+ function ensureDir(dir) {
166
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
167
+ }
168
+
169
+ function copyDirContents(src, dst) {
170
+ ensureDir(dst);
171
+ if (!existsSync(src)) return;
172
+
173
+ for (const entry of readdirSync(src, { withFileTypes: true })) {
174
+ const srcPath = join(src, entry.name);
175
+ const dstPath = join(dst, entry.name);
176
+ if (entry.isDirectory()) {
177
+ copyDirContents(srcPath, dstPath);
178
+ } else {
179
+ writeFileSync(dstPath, readFileSync(srcPath));
180
+ }
181
+ }
182
+ }
183
+
184
+ function listFilesRecursive(dir, base = dir) {
185
+ const files = [];
186
+ if (!existsSync(dir)) return files;
187
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
188
+ const full = join(dir, entry.name);
189
+ if (entry.isDirectory()) {
190
+ files.push(...listFilesRecursive(full, base));
191
+ } else {
192
+ files.push(full);
193
+ }
194
+ }
195
+ return files;
196
+ }
197
+
198
+ // ─── Tracker & Log Initializers ──────────────────────────────────────────────
199
+
200
+ function initTracker(filePath) {
201
+ writeFileSync(filePath, `# KnowzCode - Status Map
202
+
203
+ **Purpose:** This document tracks the development status of all implementable components (NodeIDs) defined in \`knowzcode_architecture.md\`.
204
+
205
+ ---
206
+ **Progress: 0%**
207
+ ---
208
+
209
+ | Status | WorkGroupID | Node ID | Label | Dependencies | Logical Grouping | Spec Link | Classification | Notes / Issues |
210
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
211
+ | | | | | | | | | |
212
+
213
+ ---
214
+ ### Status Legend:
215
+
216
+ * ⚪️ **\`[TODO]\`**: Task is defined and ready to be picked up if dependencies are met.
217
+ * 📝 **\`[NEEDS_SPEC]\`**: Node has been identified but requires a detailed specification.
218
+ * ◆ **\`[WIP]\`**: Work In Progress. The KnowzCode AI Agent is currently working on this node.
219
+ * 🟢 **\`[VERIFIED]\`**: Node has been implemented and verified.
220
+ * ❗ **\`[ISSUE]\`**: A significant issue or blocker has been identified.
221
+
222
+ ---
223
+ *(This table will be populated as you define your architecture and NodeIDs.)*
224
+ `);
225
+ }
226
+
227
+ function initLog(filePath) {
228
+ const ts = new Date().toISOString().replace('T', ' ').slice(0, 19);
229
+ writeFileSync(filePath, `# KnowzCode - Operational Record
230
+
231
+ **Purpose:** Chronological record of significant events, decisions, and verification outcomes.
232
+
233
+ ---
234
+
235
+ ## Section 1: Operational Log
236
+
237
+ ---
238
+ **[NEWEST ENTRIES APPEAR HERE - DO NOT REMOVE THIS MARKER]**
239
+ ---
240
+ **Type:** SystemInitialization
241
+ **Timestamp:** ${ts}
242
+ **NodeID(s):** Project-Wide
243
+ **Logged By:** knowzcode-cli
244
+ **Details:**
245
+ KnowzCode framework installed via \`npx knowzcode\`.
246
+ - Framework files initialized
247
+ - Ready for first feature
248
+ ---
249
+
250
+ ## Section 2: Reference Quality Criteria (ARC-Based Verification)
251
+
252
+ ### Core Quality Criteria
253
+ 1. **Maintainability:** Ease of modification, clarity of code and design.
254
+ 2. **Reliability:** Robustness of error handling, fault tolerance.
255
+ 3. **Testability:** Adequacy of unit test coverage, ease of testing.
256
+ 4. **Performance:** Responsiveness, efficiency in resource utilization.
257
+ 5. **Security:** Resistance to common vulnerabilities.
258
+
259
+ ### Structural Criteria
260
+ 6. **Readability:** Code clarity, adherence to naming conventions.
261
+ 7. **Complexity Management:** Avoidance of overly complex logic.
262
+ 8. **Modularity:** Adherence to Single Responsibility Principle.
263
+ 9. **Code Duplication (DRY):** Minimization of redundant code.
264
+ 10. **Standards Compliance:** Adherence to language best practices.
265
+
266
+ *(Refer to these criteria during ARC-Based Verification.)*
267
+ `);
268
+ }
269
+
270
+ // ─── Interactive Prompt ──────────────────────────────────────────────────────
271
+
272
+ async function promptPlatforms(detected) {
273
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
274
+ const ids = Object.keys(PLATFORMS);
275
+
276
+ console.log('');
277
+ console.log(`${c.bold}Select platforms to generate adapters for:${c.reset}`);
278
+ console.log('');
279
+ ids.forEach((id, i) => {
280
+ const p = PLATFORMS[id];
281
+ const tag = detected.includes(id) ? ` ${c.green}(detected)${c.reset}` : '';
282
+ console.log(` [${i + 1}] ${p.name}${tag}`);
283
+ });
284
+ console.log(` [A] All platforms`);
285
+ console.log(` [S] Skip adapters (core framework only)`);
286
+ console.log('');
287
+
288
+ const answer = await rl.question('Select platforms (comma-separated, e.g. 1,2): ');
289
+ rl.close();
290
+
291
+ const trimmed = answer.trim().toUpperCase();
292
+ if (trimmed === 'S' || trimmed === '') return [];
293
+ if (trimmed === 'A') return ids;
294
+
295
+ const selected = [];
296
+ for (const part of trimmed.split(',')) {
297
+ const num = parseInt(part.trim(), 10);
298
+ if (num >= 1 && num <= ids.length) {
299
+ selected.push(ids[num - 1]);
300
+ }
301
+ }
302
+ return [...new Set(selected)];
303
+ }
304
+
305
+ async function promptConfirm(message) {
306
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
307
+ const answer = await rl.question(`${message} [y/N]: `);
308
+ rl.close();
309
+ return answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes';
310
+ }
311
+
312
+ // ─── Agent Teams Enablement ──────────────────────────────────────────────────
313
+
314
+ function enableAgentTeams(dir) {
315
+ const claudeDir = join(dir, '.claude');
316
+ ensureDir(claudeDir);
317
+ const settingsFile = join(claudeDir, 'settings.local.json');
318
+
319
+ let settings = {};
320
+ if (existsSync(settingsFile)) {
321
+ try {
322
+ settings = JSON.parse(readFileSync(settingsFile, 'utf8'));
323
+ } catch {
324
+ settings = {};
325
+ }
326
+ }
327
+
328
+ if (!settings.env) settings.env = {};
329
+ settings.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = '1';
330
+
331
+ writeFileSync(settingsFile, JSON.stringify(settings, null, 2) + '\n');
332
+ log.ok('Agent Teams enabled in .claude/settings.local.json');
333
+ }
334
+
335
+ // ─── Commands ────────────────────────────────────────────────────────────────
336
+
337
+ // DETECT
338
+ function cmdDetect(opts) {
339
+ const dir = opts.target;
340
+ console.log('');
341
+ console.log(`${c.bold}KnowzCode Platform Detection${c.reset}`);
342
+ console.log(`${c.dim}Scanning: ${dir}${c.reset}`);
343
+ console.log('');
344
+
345
+ const detected = detectPlatforms(dir);
346
+ const hasKnowzcode = existsSync(join(dir, 'knowzcode'));
347
+
348
+ console.log(` KnowzCode framework: ${hasKnowzcode ? `${c.green}installed${c.reset}` : `${c.dim}not found${c.reset}`}`);
349
+
350
+ if (hasKnowzcode) {
351
+ const versionFile = join(dir, 'knowzcode', '.knowzcode-version');
352
+ if (existsSync(versionFile)) {
353
+ const ver = readFileSync(versionFile, 'utf8').trim();
354
+ console.log(` Installed version: ${c.cyan}${ver}${c.reset}`);
355
+ }
356
+ }
357
+
358
+ console.log('');
359
+ console.log(` ${c.bold}Platforms:${c.reset}`);
360
+
361
+ for (const [id, platform] of Object.entries(PLATFORMS)) {
362
+ const found = detected.includes(id);
363
+ const indicator = found ? `${c.green}detected${c.reset}` : `${c.dim}not detected${c.reset}`;
364
+ console.log(` ${platform.name.padEnd(18)} ${indicator}`);
365
+ }
366
+
367
+ console.log('');
368
+ if (detected.length === 0) {
369
+ console.log(` No platforms detected. Run ${c.cyan}npx knowzcode install${c.reset} to set up.`);
370
+ } else {
371
+ console.log(` ${detected.length} platform(s) detected.`);
372
+ }
373
+ console.log('');
374
+ }
375
+
376
+ // INSTALL
377
+ async function cmdInstall(opts) {
378
+ const dir = opts.target;
379
+ const kcDir = join(dir, 'knowzcode');
380
+
381
+ console.log('');
382
+ console.log(`${c.bold}KnowzCode Install${c.reset}`);
383
+ console.log(`${c.dim}Target: ${dir}${c.reset}`);
384
+ console.log('');
385
+
386
+ // Check for existing installation
387
+ if (existsSync(kcDir) && !opts.force) {
388
+ log.warn('KnowzCode already installed at ' + kcDir);
389
+ log.warn('Use --force to overwrite.');
390
+ process.exit(1);
391
+ }
392
+
393
+ if (!existsSync(dir)) {
394
+ log.err('Target directory does not exist: ' + dir);
395
+ process.exit(1);
396
+ }
397
+
398
+ // 1. Copy knowzcode/ template directory
399
+ log.info('Installing core framework...');
400
+ const srcKc = join(PKG_ROOT, 'knowzcode');
401
+ ensureDir(kcDir);
402
+ ensureDir(join(kcDir, 'specs'));
403
+ ensureDir(join(kcDir, 'workgroups'));
404
+ ensureDir(join(kcDir, 'prompts'));
405
+
406
+ // Create workgroups/README.md (workgroups/ is gitignored and excluded from npm)
407
+ writeFileSync(join(kcDir, 'workgroups', 'README.md'), '# WorkGroups\n\nSession-specific WorkGroup files are stored here.\nThis directory is gitignored — contents are local to each checkout.\n');
408
+
409
+ // Copy .md files (skip tracker and log — generate fresh)
410
+ for (const entry of readdirSync(srcKc)) {
411
+ const srcPath = join(srcKc, entry);
412
+ const stat = statSync(srcPath);
413
+ if (stat.isFile() && entry.endsWith('.md') && entry !== 'knowzcode_tracker.md' && entry !== 'knowzcode_log.md') {
414
+ writeFileSync(join(kcDir, entry), readFileSync(srcPath));
415
+ } else if (stat.isFile() && !entry.endsWith('.md')) {
416
+ // Copy non-md files, handling gitignore.template → .gitignore rename
417
+ if (entry === 'gitignore.template') {
418
+ writeFileSync(join(kcDir, '.gitignore'), readFileSync(srcPath));
419
+ } else {
420
+ writeFileSync(join(kcDir, entry), readFileSync(srcPath));
421
+ }
422
+ }
423
+ }
424
+
425
+ // Copy prompts/
426
+ if (existsSync(join(srcKc, 'prompts'))) {
427
+ copyDirContents(join(srcKc, 'prompts'), join(kcDir, 'prompts'));
428
+ }
429
+
430
+ // Copy specs readme
431
+ if (existsSync(join(srcKc, 'specs', 'Readme.md'))) {
432
+ writeFileSync(join(kcDir, 'specs', 'Readme.md'), readFileSync(join(srcKc, 'specs', 'Readme.md')));
433
+ }
434
+
435
+ // Copy enterprise/ if exists
436
+ if (existsSync(join(srcKc, 'enterprise'))) {
437
+ copyDirContents(join(srcKc, 'enterprise'), join(kcDir, 'enterprise'));
438
+ }
439
+
440
+ // Initialize fresh tracker and log
441
+ initTracker(join(kcDir, 'knowzcode_tracker.md'));
442
+ initLog(join(kcDir, 'knowzcode_log.md'));
443
+
444
+ // Write version marker
445
+ writeFileSync(join(kcDir, '.knowzcode-version'), VERSION + '\n');
446
+
447
+ log.ok('Core framework installed');
448
+
449
+ // 2. Platform detection + selection
450
+ const detected = detectPlatforms(dir);
451
+ let selectedPlatforms;
452
+
453
+ if (opts.platforms.length > 0) {
454
+ if (opts.platforms.includes('all')) {
455
+ selectedPlatforms = Object.keys(PLATFORMS);
456
+ } else {
457
+ selectedPlatforms = opts.platforms.filter((p) => p in PLATFORMS);
458
+ }
459
+ } else if (opts.force) {
460
+ // Non-interactive mode with --force: install for detected platforms only
461
+ selectedPlatforms = detected;
462
+ } else {
463
+ selectedPlatforms = await promptPlatforms(detected);
464
+ }
465
+
466
+ // 3. Generate adapters
467
+ const templates = parseAdapterTemplates();
468
+ const adapterFiles = [];
469
+
470
+ for (const platformId of selectedPlatforms) {
471
+ const platform = PLATFORMS[platformId];
472
+
473
+ if (platformId === 'claude') {
474
+ // Claude Code: copy agents, commands, skills
475
+ const claudeDir = opts.global ? join(process.env.HOME || process.env.USERPROFILE || '~', '.claude') : join(dir, '.claude');
476
+
477
+ log.info(`Installing Claude Code components to ${claudeDir}/`);
478
+ copyDirContents(join(PKG_ROOT, 'commands'), join(claudeDir, 'commands'));
479
+ copyDirContents(join(PKG_ROOT, 'agents'), join(claudeDir, 'agents'));
480
+ copyDirContents(join(PKG_ROOT, 'skills'), join(claudeDir, 'skills'));
481
+ adapterFiles.push(claudeDir + '/commands/', claudeDir + '/agents/', claudeDir + '/skills/');
482
+ } else {
483
+ // Other platforms: extract template and write adapter file
484
+ const template = templates.get(platformId);
485
+ if (!template) {
486
+ log.warn(`No adapter template found for ${platform.name} — skipping`);
487
+ continue;
488
+ }
489
+
490
+ const adapterFile = platform.adapterPath(dir);
491
+ ensureDir(dirname(adapterFile));
492
+ writeFileSync(adapterFile, template);
493
+ adapterFiles.push(adapterFile);
494
+ log.ok(`${platform.name} adapter: ${adapterFile}`);
495
+ }
496
+ }
497
+
498
+ // 4. Agent Teams enablement
499
+ let agentTeamsEnabled = false;
500
+ if (opts.agentTeams) {
501
+ enableAgentTeams(dir);
502
+ agentTeamsEnabled = true;
503
+ } else if (selectedPlatforms.includes('claude') && !opts.force) {
504
+ // Interactive prompt for Claude Code users
505
+ console.log('');
506
+ console.log(`${c.bold}Agent Teams${c.reset} enables multi-agent coordination where specialized`);
507
+ console.log(`teammates handle each workflow phase. ${c.dim}(experimental)${c.reset}`);
508
+ const wantTeams = await promptConfirm('Enable Agent Teams? (recommended for Claude Code)');
509
+ if (wantTeams) {
510
+ enableAgentTeams(dir);
511
+ agentTeamsEnabled = true;
512
+ }
513
+ }
514
+
515
+ // 5. Summary
516
+ console.log('');
517
+ console.log(`${c.green}${c.bold}Installation complete!${c.reset}`);
518
+ console.log('');
519
+ console.log(' Framework: ' + kcDir + '/');
520
+ if (adapterFiles.length > 0) {
521
+ console.log(' Adapters:');
522
+ for (const f of adapterFiles) {
523
+ console.log(' ' + f);
524
+ }
525
+ }
526
+ if (agentTeamsEnabled) {
527
+ console.log(' Agent Teams: enabled');
528
+ }
529
+ console.log('');
530
+ console.log(`${c.bold}Next steps:${c.reset}`);
531
+ console.log(' 1. Edit knowzcode/knowzcode_project.md — set project name, stack, standards');
532
+ console.log(' 2. Edit knowzcode/environment_context.md — configure build/test commands');
533
+ if (selectedPlatforms.includes('claude')) {
534
+ console.log(' 3. Start building: /kc:work "Your first feature"');
535
+ } else {
536
+ console.log(' 3. Start building: use knowzcode/prompts/[LOOP_1A]__Propose_Change_Set.md');
537
+ }
538
+ console.log('');
539
+ }
540
+
541
+ // UNINSTALL
542
+ async function cmdUninstall(opts) {
543
+ const dir = opts.target;
544
+ const kcDir = join(dir, 'knowzcode');
545
+
546
+ console.log('');
547
+ console.log(`${c.bold}KnowzCode Uninstall${c.reset}`);
548
+ console.log(`${c.dim}Target: ${dir}${c.reset}`);
549
+ console.log('');
550
+
551
+ // Scan for installed components
552
+ const components = [];
553
+
554
+ if (existsSync(kcDir)) {
555
+ components.push({ label: 'Core framework', path: kcDir });
556
+ }
557
+
558
+ // Claude Code components
559
+ const claudeDir = join(dir, '.claude');
560
+ for (const sub of ['commands', 'agents', 'skills']) {
561
+ const p = join(claudeDir, sub);
562
+ if (existsSync(p)) {
563
+ components.push({ label: `Claude Code ${sub}`, path: p });
564
+ }
565
+ }
566
+
567
+ // Platform adapter files
568
+ const adapterChecks = {
569
+ codex: join(dir, 'AGENTS.md'),
570
+ gemini: join(dir, 'GEMINI.md'),
571
+ cursor: join(dir, '.cursor', 'rules', 'knowzcode.mdc'),
572
+ copilot: join(dir, '.github', 'copilot-instructions.md'),
573
+ windsurf: join(dir, '.windsurf', 'rules', 'knowzcode.md'),
574
+ };
575
+
576
+ for (const [id, path] of Object.entries(adapterChecks)) {
577
+ if (existsSync(path)) {
578
+ components.push({ label: `${PLATFORMS[id].name} adapter`, path });
579
+ }
580
+ }
581
+
582
+ if (components.length === 0) {
583
+ log.info('No KnowzCode installation found.');
584
+ return;
585
+ }
586
+
587
+ console.log(' Components found:');
588
+ for (const comp of components) {
589
+ console.log(` ${comp.label}: ${comp.path}`);
590
+ }
591
+ console.log('');
592
+
593
+ // Ask about preserving user data
594
+ let preserveUserData = false;
595
+ if (existsSync(kcDir) && !opts.force) {
596
+ preserveUserData = await promptConfirm('Preserve user data (specs/, architecture, tracker, log)?');
597
+ }
598
+
599
+ if (!opts.force) {
600
+ const confirmed = await promptConfirm('Remove all listed components?');
601
+ if (!confirmed) {
602
+ log.info('Uninstall cancelled.');
603
+ return;
604
+ }
605
+ }
606
+
607
+ const removed = [];
608
+
609
+ // Remove components
610
+ for (const comp of components) {
611
+ if (comp.path === kcDir && preserveUserData) {
612
+ // Selective removal — keep user data
613
+ const preserve = ['specs', 'knowzcode_architecture.md', 'knowzcode_tracker.md', 'knowzcode_log.md', 'knowzcode_project.md'];
614
+
615
+ for (const entry of readdirSync(kcDir)) {
616
+ if (preserve.includes(entry)) continue;
617
+ const entryPath = join(kcDir, entry);
618
+ rmSync(entryPath, { recursive: true, force: true });
619
+ }
620
+ removed.push(comp.label + ' (user data preserved)');
621
+ } else {
622
+ rmSync(comp.path, { recursive: true, force: true });
623
+ removed.push(comp.label);
624
+ }
625
+ }
626
+
627
+ console.log('');
628
+ log.ok('Uninstall complete');
629
+ console.log(' Removed:');
630
+ for (const r of removed) {
631
+ console.log(` ${r}`);
632
+ }
633
+ console.log('');
634
+ }
635
+
636
+ // UPGRADE
637
+ async function cmdUpgrade(opts) {
638
+ const dir = opts.target;
639
+ const kcDir = join(dir, 'knowzcode');
640
+
641
+ console.log('');
642
+ console.log(`${c.bold}KnowzCode Upgrade${c.reset}`);
643
+ console.log(`${c.dim}Target: ${dir}${c.reset}`);
644
+ console.log('');
645
+
646
+ if (!existsSync(kcDir)) {
647
+ log.err('No KnowzCode installation found. Run `npx knowzcode install` first.');
648
+ process.exit(1);
649
+ }
650
+
651
+ // Read current version
652
+ const versionFile = join(kcDir, '.knowzcode-version');
653
+ const currentVersion = existsSync(versionFile) ? readFileSync(versionFile, 'utf8').trim() : 'unknown';
654
+
655
+ if (currentVersion === VERSION && !opts.force) {
656
+ log.info(`Already at version ${VERSION}. Use --force to reinstall.`);
657
+ return;
658
+ }
659
+
660
+ log.info(`Upgrading: ${currentVersion} → ${VERSION}`);
661
+
662
+ // Files to preserve (never overwrite)
663
+ const preserveFiles = new Set([
664
+ 'knowzcode_tracker.md',
665
+ 'knowzcode_log.md',
666
+ 'knowzcode_architecture.md',
667
+ 'knowzcode_project.md',
668
+ 'environment_context.md',
669
+ 'user_preferences.md',
670
+ ]);
671
+ const preserveDirs = new Set(['specs', 'workgroups']);
672
+
673
+ // Files to replace (always update)
674
+ const srcKc = join(PKG_ROOT, 'knowzcode');
675
+
676
+ // Update .md files
677
+ for (const entry of readdirSync(srcKc)) {
678
+ const srcPath = join(srcKc, entry);
679
+ const dstPath = join(kcDir, entry);
680
+ const stat = statSync(srcPath);
681
+
682
+ if (stat.isFile()) {
683
+ if (preserveFiles.has(entry)) {
684
+ if (opts.verbose) log.info(`Preserved: ${entry}`);
685
+ continue;
686
+ }
687
+ // Handle gitignore.template → .gitignore rename
688
+ if (entry === 'gitignore.template') {
689
+ writeFileSync(join(kcDir, '.gitignore'), readFileSync(srcPath));
690
+ if (opts.verbose) log.info('Updated: .gitignore (from gitignore.template)');
691
+ } else {
692
+ writeFileSync(dstPath, readFileSync(srcPath));
693
+ if (opts.verbose) log.info(`Updated: ${entry}`);
694
+ }
695
+ }
696
+ }
697
+
698
+ // Update prompts/ (always replace)
699
+ if (existsSync(join(srcKc, 'prompts'))) {
700
+ const promptsDst = join(kcDir, 'prompts');
701
+ // Remove old prompts, copy new ones
702
+ if (existsSync(promptsDst)) rmSync(promptsDst, { recursive: true, force: true });
703
+ copyDirContents(join(srcKc, 'prompts'), promptsDst);
704
+ if (opts.verbose) log.info('Updated: prompts/');
705
+ }
706
+
707
+ // Update enterprise/ (always replace)
708
+ if (existsSync(join(srcKc, 'enterprise'))) {
709
+ const entDst = join(kcDir, 'enterprise');
710
+ if (existsSync(entDst)) rmSync(entDst, { recursive: true, force: true });
711
+ copyDirContents(join(srcKc, 'enterprise'), entDst);
712
+ if (opts.verbose) log.info('Updated: enterprise/');
713
+ }
714
+
715
+ // Update Claude Code components if present
716
+ const claudeDir = join(dir, '.claude');
717
+ if (existsSync(join(claudeDir, 'commands')) || existsSync(join(claudeDir, 'agents'))) {
718
+ log.info('Updating Claude Code components...');
719
+ copyDirContents(join(PKG_ROOT, 'commands'), join(claudeDir, 'commands'));
720
+ copyDirContents(join(PKG_ROOT, 'agents'), join(claudeDir, 'agents'));
721
+ copyDirContents(join(PKG_ROOT, 'skills'), join(claudeDir, 'skills'));
722
+ }
723
+
724
+ // Regenerate adapters for detected platforms
725
+ const detected = detectPlatforms(dir);
726
+ const templates = parseAdapterTemplates();
727
+ const regenerated = [];
728
+
729
+ for (const platformId of detected) {
730
+ if (platformId === 'claude') continue; // Already handled above
731
+ const platform = PLATFORMS[platformId];
732
+ if (!platform.adapterPath) continue;
733
+
734
+ const adapterFile = platform.adapterPath(dir);
735
+ if (!existsSync(adapterFile)) continue; // Only update existing adapters
736
+
737
+ const template = templates.get(platformId);
738
+ if (!template) continue;
739
+
740
+ writeFileSync(adapterFile, template);
741
+ regenerated.push(platform.name);
742
+ }
743
+
744
+ // Write new version
745
+ writeFileSync(versionFile, VERSION + '\n');
746
+
747
+ console.log('');
748
+ log.ok(`Upgraded to ${VERSION}`);
749
+ console.log('');
750
+ console.log(` ${c.bold}Preserved:${c.reset} specs/, tracker, log, architecture, project config`);
751
+ console.log(` ${c.bold}Updated:${c.reset} loop, prompts, adapters, enterprise templates`);
752
+ if (regenerated.length > 0) {
753
+ console.log(` ${c.bold}Adapters:${c.reset} ${regenerated.join(', ')}`);
754
+ }
755
+ console.log('');
756
+ }
757
+
758
+ // HELP
759
+ function cmdHelp() {
760
+ console.log(`
761
+ ${c.bold}KnowzCode CLI${c.reset} v${VERSION}
762
+ Platform-agnostic AI development methodology
763
+
764
+ ${c.bold}Usage:${c.reset}
765
+ npx knowzcode Interactive mode
766
+ npx knowzcode install [options] Install to current/target directory
767
+ npx knowzcode uninstall [options] Remove KnowzCode
768
+ npx knowzcode upgrade [options] Upgrade preserving user data
769
+ npx knowzcode detect Show detected platforms (dry run)
770
+
771
+ ${c.bold}Options:${c.reset}
772
+ --target <path> Target directory (default: current directory)
773
+ --platforms <list> Comma-separated: claude,codex,gemini,cursor,copilot,windsurf,all
774
+ --force Skip confirmation prompts
775
+ --global Install Claude Code components to ~/.claude/
776
+ --agent-teams Enable Agent Teams in .claude/settings.local.json
777
+ --verbose Show detailed output
778
+ -h, --help Show this help
779
+ -v, --version Show version
780
+
781
+ ${c.bold}Examples:${c.reset}
782
+ npx knowzcode install --platforms claude,cursor
783
+ npx knowzcode install --platforms all --force
784
+ npx knowzcode upgrade --target ./my-project
785
+ npx knowzcode uninstall --force
786
+ npx knowzcode detect
787
+ `);
788
+ }
789
+
790
+ // INTERACTIVE
791
+ async function cmdInteractive(opts) {
792
+ console.log('');
793
+ console.log(`${c.bold} ╔═══════════════════════════════════════╗${c.reset}`);
794
+ console.log(`${c.bold} ║ KnowzCode v${VERSION.padEnd(14)} ║${c.reset}`);
795
+ console.log(`${c.bold} ║ AI Development Methodology Installer ║${c.reset}`);
796
+ console.log(`${c.bold} ╚═══════════════════════════════════════╝${c.reset}`);
797
+ console.log('');
798
+
799
+ const dir = opts.target;
800
+ const kcDir = join(dir, 'knowzcode');
801
+ const detected = detectPlatforms(dir);
802
+
803
+ if (detected.length > 0) {
804
+ log.info('Detected platforms: ' + detected.map((d) => PLATFORMS[d].name).join(', '));
805
+ }
806
+
807
+ if (existsSync(kcDir)) {
808
+ const versionFile = join(kcDir, '.knowzcode-version');
809
+ const currentVersion = existsSync(versionFile) ? readFileSync(versionFile, 'utf8').trim() : 'unknown';
810
+
811
+ if (currentVersion !== VERSION) {
812
+ log.info(`Installed version: ${currentVersion}, available: ${VERSION}`);
813
+ const doUpgrade = await promptConfirm('Upgrade to latest version?');
814
+ if (doUpgrade) {
815
+ return cmdUpgrade(opts);
816
+ }
817
+ } else {
818
+ log.info(`KnowzCode ${currentVersion} already installed.`);
819
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
820
+ console.log('');
821
+ console.log(' [1] Reinstall (overwrite)');
822
+ console.log(' [2] Uninstall');
823
+ console.log(' [3] Detect platforms');
824
+ console.log(' [4] Exit');
825
+ console.log('');
826
+ const answer = await rl.question('Select action: ');
827
+ rl.close();
828
+
829
+ const choice = answer.trim();
830
+ if (choice === '1') return cmdInstall({ ...opts, force: true });
831
+ if (choice === '2') return cmdUninstall(opts);
832
+ if (choice === '3') return cmdDetect(opts);
833
+ return;
834
+ }
835
+ } else {
836
+ log.info('No existing installation found. Starting install...');
837
+ console.log('');
838
+ return cmdInstall(opts);
839
+ }
840
+ }
841
+
842
+ // ─── Main ────────────────────────────────────────────────────────────────────
843
+
844
+ async function main() {
845
+ const opts = parseArgs(process.argv);
846
+
847
+ switch (opts.command) {
848
+ case 'install':
849
+ return cmdInstall(opts);
850
+ case 'uninstall':
851
+ return cmdUninstall(opts);
852
+ case 'upgrade':
853
+ return cmdUpgrade(opts);
854
+ case 'detect':
855
+ return cmdDetect(opts);
856
+ case 'help':
857
+ return cmdHelp();
858
+ case 'version':
859
+ console.log(VERSION);
860
+ return;
861
+ default:
862
+ return cmdInteractive(opts);
863
+ }
864
+ }
865
+
866
+ main().catch((err) => {
867
+ log.err(err.message);
868
+ process.exit(1);
869
+ });