@nolrm/contextkit 0.13.5 → 0.14.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.
@@ -1,9 +1,8 @@
1
1
  const chalk = require('chalk');
2
- const ora = require('ora');
3
2
  const inquirer = require('inquirer');
4
3
  const fs = require('fs-extra');
5
4
  const path = require('path');
6
- const axios = require('axios');
5
+ const childProcess = require('child_process');
7
6
 
8
7
  const DownloadManager = require('../utils/download');
9
8
  const ProjectDetector = require('../utils/project-detector');
@@ -22,7 +21,7 @@ class InstallCommand {
22
21
 
23
22
  async install(options = {}) {
24
23
  // Migrate legacy .vibe-kit/ directory
25
- if (await fs.pathExists('.vibe-kit') && !await fs.pathExists('.contextkit')) {
24
+ if ((await fs.pathExists('.vibe-kit')) && !(await fs.pathExists('.contextkit'))) {
26
25
  console.log(chalk.yellow('Found legacy .vibe-kit/ directory'));
27
26
  console.log(chalk.yellow('Renaming to .contextkit/...'));
28
27
  await fs.move('.vibe-kit', '.contextkit');
@@ -41,8 +40,12 @@ class InstallCommand {
41
40
  const hasGit = await this._findFileUpward('.git', 3);
42
41
  const hasPkg = await fs.pathExists('package.json');
43
42
  if (!hasGit && !hasPkg) {
44
- console.log(chalk.yellow('⚠️ No project detected (no .git or package.json found in this directory).'));
45
- console.log(chalk.yellow(' Make sure you are inside your project before running `ck install`.'));
43
+ console.log(
44
+ chalk.yellow('⚠️ No project detected (no .git or package.json found in this directory).')
45
+ );
46
+ console.log(
47
+ chalk.yellow(' Make sure you are inside your project before running `ck install`.')
48
+ );
46
49
  console.log('');
47
50
  }
48
51
 
@@ -87,7 +90,9 @@ class InstallCommand {
87
90
  const { shouldContinue } = await this.promptReinstall();
88
91
  if (!shouldContinue) {
89
92
  console.log(chalk.yellow('⏭️ Installation cancelled'));
90
- console.log(chalk.dim('💡 To get the latest command and squad files, run: ') + chalk.cyan('ck update'));
93
+ console.log(
94
+ chalk.dim('💡 To get the latest command and squad files, run: ') + chalk.cyan('ck update')
95
+ );
91
96
  return;
92
97
  }
93
98
  }
@@ -114,6 +119,11 @@ class InstallCommand {
114
119
  await this.gitHooksManager.installHooks(packageManager, hookChoices);
115
120
  }
116
121
 
122
+ // Offer quality tooling scaffold for Node.js projects with pre-push enabled
123
+ if (hookChoices.prePush && !options.nonInteractive) {
124
+ await this.promptQualityTooling(packageManager, options);
125
+ }
126
+
117
127
  // Ask about GitHub Actions CI squad workflow
118
128
  let squadCi = false;
119
129
  if (!options.nonInteractive) {
@@ -123,6 +133,9 @@ class InstallCommand {
123
133
  await this.installGitHubActionsWorkflow();
124
134
  }
125
135
 
136
+ // Create quality gates config
137
+ await this.createQualityGatesConfig();
138
+
126
139
  // Create configuration
127
140
  await this.createConfiguration(projectType, hookChoices, squadCi);
128
141
 
@@ -151,7 +164,11 @@ class InstallCommand {
151
164
 
152
165
  if (!integration) {
153
166
  console.log(chalk.red(`❌ Unknown platform: ${platform}`));
154
- console.log(chalk.yellow('💡 Available: claude, cursor, copilot, codex, opencode, gemini, aider, continue, windsurf'));
167
+ console.log(
168
+ chalk.yellow(
169
+ '💡 Available: claude, cursor, copilot, codex, opencode, gemini, aider, continue, windsurf'
170
+ )
171
+ );
155
172
  return;
156
173
  }
157
174
 
@@ -161,7 +178,6 @@ class InstallCommand {
161
178
  console.log(chalk.green(`🎉 ${integration.displayName} integration installed!`));
162
179
 
163
180
  integration.showUsage();
164
-
165
181
  } catch (error) {
166
182
  console.log(chalk.red(`❌ Failed to install ${platform} integration`));
167
183
  console.log(chalk.yellow(error.message));
@@ -186,30 +202,32 @@ class InstallCommand {
186
202
  type: 'confirm',
187
203
  name: 'shouldContinue',
188
204
  message: 'ContextKit is already installed. Do you want to reinstall?',
189
- default: false
190
- }
205
+ default: false,
206
+ },
191
207
  ]);
192
208
  return { shouldContinue };
193
209
  }
194
210
 
195
211
  async promptPlatformChoice() {
196
- const { platform } = await inquirer.prompt([{
197
- type: 'list',
198
- name: 'platform',
199
- message: 'Which AI tool are you using?',
200
- choices: [
201
- { name: 'Claude Code', value: 'claude' },
202
- { name: 'Cursor', value: 'cursor' },
203
- { name: 'Copilot (GitHub)', value: 'copilot' },
204
- { name: 'Codex (OpenAI)', value: 'codex' },
205
- { name: 'OpenCode', value: 'opencode' },
206
- { name: 'Gemini', value: 'gemini' },
207
- { name: 'Windsurf', value: 'windsurf' },
208
- { name: 'Aider', value: 'aider' },
209
- { name: 'Continue', value: 'continue' },
210
- { name: 'Skip (base only)', value: null },
211
- ]
212
- }]);
212
+ const { platform } = await inquirer.prompt([
213
+ {
214
+ type: 'list',
215
+ name: 'platform',
216
+ message: 'Which AI tool are you using?',
217
+ choices: [
218
+ { name: 'Claude Code', value: 'claude' },
219
+ { name: 'Cursor', value: 'cursor' },
220
+ { name: 'Copilot (GitHub)', value: 'copilot' },
221
+ { name: 'Codex (OpenAI)', value: 'codex' },
222
+ { name: 'OpenCode', value: 'opencode' },
223
+ { name: 'Gemini', value: 'gemini' },
224
+ { name: 'Windsurf', value: 'windsurf' },
225
+ { name: 'Aider', value: 'aider' },
226
+ { name: 'Continue', value: 'continue' },
227
+ { name: 'Skip (base only)', value: null },
228
+ ],
229
+ },
230
+ ]);
213
231
  return platform;
214
232
  }
215
233
 
@@ -257,7 +275,9 @@ class InstallCommand {
257
275
  `${this.repoUrl}/templates/github-actions/squad-issue.yml`,
258
276
  '.github/workflows/squad-issue.yml'
259
277
  );
260
- console.log(chalk.green('✅ CI squad workflow installed → .github/workflows/squad-issue.yml'));
278
+ console.log(
279
+ chalk.green('✅ CI squad workflow installed → .github/workflows/squad-issue.yml')
280
+ );
261
281
  } catch (error) {
262
282
  console.log(chalk.yellow('⚠️ Could not install CI squad workflow:'), error.message);
263
283
  }
@@ -270,7 +290,7 @@ class InstallCommand {
270
290
  return { prePush: false, commitMsg: false };
271
291
  }
272
292
 
273
- if (!await fs.pathExists('.git')) {
293
+ if (!(await fs.pathExists('.git'))) {
274
294
  console.log(chalk.yellow('⚠️ Skipping Git hooks setup (not a git repository)'));
275
295
  return { prePush: false, commitMsg: false };
276
296
  }
@@ -291,8 +311,8 @@ class InstallCommand {
291
311
  type: 'confirm',
292
312
  name: 'prePush',
293
313
  message: 'Enable pre-push hook? (runs quality checks before push)',
294
- default: false
295
- }
314
+ default: false,
315
+ },
296
316
  ]);
297
317
 
298
318
  if (prePush) {
@@ -314,8 +334,8 @@ class InstallCommand {
314
334
  type: 'confirm',
315
335
  name: 'commitMsg',
316
336
  message: 'Enable commit-msg hook? (enforces conventional commit format)',
317
- default: false
318
- }
337
+ default: false,
338
+ },
319
339
  ]);
320
340
 
321
341
  if (commitMsg) {
@@ -336,7 +356,7 @@ class InstallCommand {
336
356
 
337
357
  async createDirectoryStructure() {
338
358
  console.log(chalk.blue('📁 Creating structure...'));
339
-
359
+
340
360
  const directories = [
341
361
  '.contextkit/standards',
342
362
  '.contextkit/standards/code-style', // Granular code style files
@@ -350,7 +370,7 @@ class InstallCommand {
350
370
  '.contextkit/templates',
351
371
  '.contextkit/scripts',
352
372
  '.contextkit/integrations',
353
- '.contextkit/policies' // Policy enforcement configs
373
+ '.contextkit/policies', // Policy enforcement configs
354
374
  ];
355
375
 
356
376
  for (const dir of directories) {
@@ -393,7 +413,7 @@ Use conditional loading tags:
393
413
  [TypeScript-specific content]
394
414
  \`\`\`
395
415
  `,
396
-
416
+
397
417
  'standards/testing.md': `# Testing Standards
398
418
 
399
419
  <!-- Content will be generated by running: /analyze -->
@@ -428,7 +448,7 @@ describe("ComponentName", () => {
428
448
  - Consistent organization across all test files
429
449
  - Quick debugging and maintenance
430
450
  `,
431
-
451
+
432
452
  'standards/architecture.md': `# Architecture
433
453
 
434
454
  ## Documentation Levels
@@ -476,22 +496,54 @@ Documentation for a single component or a small, cohesive set of components.
476
496
  Your architecture patterns will be documented based on your project structure and organization.
477
497
 
478
498
  Run \`/analyze\` to generate this content.`,
479
-
499
+
480
500
  'standards/ai-guidelines.md': `# AI Guidelines
481
501
 
482
- <!-- Content will be generated by running: /analyze -->
502
+ > Run \`/analyze\` to add project-specific rules to this file.
483
503
 
484
- Guidelines for AI assistance will be defined based on your project's needs and patterns.
504
+ ## Agentic Workflow
505
+
506
+ When working as an agent in this project:
507
+
508
+ - **Read standards first** — load \`code-style.md\` and \`testing.md\` before writing code
509
+ - **Before pushing** — run through \`.contextkit/commands/agents/agent-push-checklist.md\`
510
+ - **Commit format** — all commits must follow Conventional Commits: \`type(scope): description\`
511
+ - Valid types: \`feat\`, \`fix\`, \`improve\`, \`docs\`, \`chore\`, \`refactor\`, \`test\`
512
+ - **When to proceed** — proceed if the task is clear and standards cover it
513
+ - **When to ask** — ask if the task is ambiguous, contradicts existing standards, or requires an architecture decision
514
+ - **No debug statements** — do not leave \`console.log\`, \`print\`, or equivalent debug output in production code
515
+
516
+ ## Context Budget
517
+
518
+ Load standards files in this priority order to use your context window efficiently:
519
+
520
+ 1. **Always load:** \`code-style.md\`, \`testing.md\` — highest signal, always relevant
521
+ 2. **Load at session start:** \`ai-guidelines.md\` (this file) — behaviour rules
522
+ 3. **Load on demand:** \`architecture.md\` — only when making structural decisions
523
+ 4. **Load on demand:** \`workflows.md\` — only for process questions
524
+ 5. **Load selectively:** \`code-style/typescript-style.md\`, \`code-style/css-style.md\` — only for the file type you are editing
525
+ 6. **Skip unless needed:** \`glossary.md\` — only when the task involves domain-specific terms
526
+
527
+ If a standards file is longer than 200 lines, read the sections relevant to your task — not the whole file.
528
+
529
+ ## Standards Loop
530
+
531
+ This project follows a continuous standards loop:
532
+
533
+ 1. Standards files define what correct looks like
534
+ 2. Quality gates enforce it at every push (human or agent)
535
+ 3. Agents read standards before writing code and write to standards when new patterns emerge
536
+
537
+ When you discover a pattern worth standardising, use \`/standards-aware\` to decide whether and how to add it.
538
+ Without the standards, agents guess. Without the gates, the guesses reach the repo unchecked.`,
485
539
 
486
- Run \`/analyze\` to generate this content.`,
487
-
488
540
  'standards/workflows.md': `# Workflows
489
541
 
490
542
  <!-- Content will be generated by running: /analyze -->
491
543
 
492
544
  Development workflows and processes will be documented based on your project's practices.
493
545
 
494
- Run \`/analyze\` to generate this content.`
546
+ Run \`/analyze\` to generate this content.`,
495
547
  };
496
548
 
497
549
  // Create granular code-style skeleton files
@@ -562,7 +614,7 @@ This file is loaded when HTML-related tasks are detected:
562
614
  <!-- when:html -->
563
615
  [HTML-specific content]
564
616
  \`\`\`
565
- `
617
+ `,
566
618
  };
567
619
 
568
620
  for (const [relativePath, content] of Object.entries(skeletonFiles)) {
@@ -688,7 +740,7 @@ Main paths through this feature:
688
740
  ## Notes
689
741
 
690
742
  Any design decisions, trade-offs, or open questions to resolve before coding.
691
- `
743
+ `,
692
744
  };
693
745
 
694
746
  for (const [relativePath, content] of Object.entries(skeletonFiles)) {
@@ -696,22 +748,22 @@ Any design decisions, trade-offs, or open questions to resolve before coding.
696
748
  }
697
749
  }
698
750
 
699
- async downloadFiles(projectType, options = {}) {
751
+ async downloadFiles(projectType, _options = {}) {
700
752
  try {
701
753
  // Create skeleton standards files (will be customized by analyze)
702
754
  console.log(chalk.blue('📝 Creating skeleton standards files...'));
703
755
  await this.createSkeletonStandards();
704
-
756
+
705
757
  console.log(chalk.green('✅ Skeleton files created'));
706
758
  console.log(chalk.yellow('💡 Run: /analyze to generate content based on your codebase'));
707
759
  console.log('');
708
-
760
+
709
761
  // Download base files
710
762
  await this.downloadManager.downloadFile(
711
763
  `${this.repoUrl}/standards/README.md`,
712
764
  '.contextkit/standards/README.md'
713
765
  );
714
-
766
+
715
767
  // Download the actual glossary (keep it as-is, universal across all projects)
716
768
  await this.downloadManager.downloadFile(
717
769
  `${this.repoUrl}/standards/glossary.md`,
@@ -720,104 +772,118 @@ Any design decisions, trade-offs, or open questions to resolve before coding.
720
772
 
721
773
  // Download commands
722
774
  await this.downloadManager.downloadFile(
723
- `${this.repoUrl}/commands/analyze.md`,
724
- '.contextkit/commands/analyze.md'
775
+ `${this.repoUrl}/commands/dev/analyze.md`,
776
+ '.contextkit/commands/dev/analyze.md'
725
777
  );
726
778
  await this.downloadManager.downloadFile(
727
- `${this.repoUrl}/commands/review.md`,
728
- '.contextkit/commands/review.md'
779
+ `${this.repoUrl}/commands/dev/review.md`,
780
+ '.contextkit/commands/dev/review.md'
729
781
  );
730
782
  await this.downloadManager.downloadFile(
731
- `${this.repoUrl}/commands/fix.md`,
732
- '.contextkit/commands/fix.md'
783
+ `${this.repoUrl}/commands/dev/fix.md`,
784
+ '.contextkit/commands/dev/fix.md'
733
785
  );
734
786
  await this.downloadManager.downloadFile(
735
- `${this.repoUrl}/commands/refactor.md`,
736
- '.contextkit/commands/refactor.md'
787
+ `${this.repoUrl}/commands/dev/refactor.md`,
788
+ '.contextkit/commands/dev/refactor.md'
737
789
  );
738
790
  await this.downloadManager.downloadFile(
739
- `${this.repoUrl}/commands/run-tests.md`,
740
- '.contextkit/commands/run-tests.md'
791
+ `${this.repoUrl}/commands/dev/run-tests.md`,
792
+ '.contextkit/commands/dev/run-tests.md'
741
793
  );
742
794
  await this.downloadManager.downloadFile(
743
- `${this.repoUrl}/commands/add-documentation.md`,
744
- '.contextkit/commands/add-documentation.md'
795
+ `${this.repoUrl}/commands/docs/add-documentation.md`,
796
+ '.contextkit/commands/docs/add-documentation.md'
745
797
  );
746
798
  await this.downloadManager.downloadFile(
747
- `${this.repoUrl}/commands/quality-check.md`,
748
- '.contextkit/commands/quality-check.md'
799
+ `${this.repoUrl}/commands/dev/quality-check.md`,
800
+ '.contextkit/commands/dev/quality-check.md'
749
801
  );
750
802
  await this.downloadManager.downloadFile(
751
- `${this.repoUrl}/commands/create-feature.md`,
752
- '.contextkit/commands/create-feature.md'
803
+ `${this.repoUrl}/commands/dev/create-feature.md`,
804
+ '.contextkit/commands/dev/create-feature.md'
753
805
  );
754
806
  await this.downloadManager.downloadFile(
755
- `${this.repoUrl}/commands/create-component.md`,
756
- '.contextkit/commands/create-component.md'
807
+ `${this.repoUrl}/commands/dev/create-component.md`,
808
+ '.contextkit/commands/dev/create-component.md'
757
809
  );
758
810
  await this.downloadManager.downloadFile(
759
- `${this.repoUrl}/commands/spec.md`,
760
- '.contextkit/commands/spec.md'
811
+ `${this.repoUrl}/commands/dev/spec.md`,
812
+ '.contextkit/commands/dev/spec.md'
761
813
  );
762
814
 
763
815
  // Download squad commands
764
816
  await this.downloadManager.downloadFile(
765
- `${this.repoUrl}/commands/squad.md`,
766
- '.contextkit/commands/squad.md'
817
+ `${this.repoUrl}/commands/squad/squad.md`,
818
+ '.contextkit/commands/squad/squad.md'
767
819
  );
768
820
  await this.downloadManager.downloadFile(
769
- `${this.repoUrl}/commands/squad-architect.md`,
770
- '.contextkit/commands/squad-architect.md'
821
+ `${this.repoUrl}/commands/squad/squad-architect.md`,
822
+ '.contextkit/commands/squad/squad-architect.md'
771
823
  );
772
824
  await this.downloadManager.downloadFile(
773
- `${this.repoUrl}/commands/squad-dev.md`,
774
- '.contextkit/commands/squad-dev.md'
825
+ `${this.repoUrl}/commands/squad/squad-dev.md`,
826
+ '.contextkit/commands/squad/squad-dev.md'
775
827
  );
776
828
  await this.downloadManager.downloadFile(
777
- `${this.repoUrl}/commands/squad-test.md`,
778
- '.contextkit/commands/squad-test.md'
829
+ `${this.repoUrl}/commands/squad/squad-test.md`,
830
+ '.contextkit/commands/squad/squad-test.md'
779
831
  );
780
832
  await this.downloadManager.downloadFile(
781
- `${this.repoUrl}/commands/squad-review.md`,
782
- '.contextkit/commands/squad-review.md'
833
+ `${this.repoUrl}/commands/squad/squad-review.md`,
834
+ '.contextkit/commands/squad/squad-review.md'
783
835
  );
784
836
  await this.downloadManager.downloadFile(
785
- `${this.repoUrl}/commands/squad-auto.md`,
786
- '.contextkit/commands/squad-auto.md'
837
+ `${this.repoUrl}/commands/squad/squad-auto.md`,
838
+ '.contextkit/commands/squad/squad-auto.md'
787
839
  );
788
840
  await this.downloadManager.downloadFile(
789
- `${this.repoUrl}/commands/squad-auto-parallel.md`,
790
- '.contextkit/commands/squad-auto-parallel.md'
841
+ `${this.repoUrl}/commands/squad/squad-auto-parallel.md`,
842
+ '.contextkit/commands/squad/squad-auto-parallel.md'
791
843
  );
792
844
  await this.downloadManager.downloadFile(
793
- `${this.repoUrl}/commands/squad-reset.md`,
794
- '.contextkit/commands/squad-reset.md'
845
+ `${this.repoUrl}/commands/squad/squad-reset.md`,
846
+ '.contextkit/commands/squad/squad-reset.md'
795
847
  );
796
848
  await this.downloadManager.downloadFile(
797
- `${this.repoUrl}/commands/squad-doc.md`,
798
- '.contextkit/commands/squad-doc.md'
849
+ `${this.repoUrl}/commands/squad/squad-doc.md`,
850
+ '.contextkit/commands/squad/squad-doc.md'
799
851
  );
800
852
  await this.downloadManager.downloadFile(
801
- `${this.repoUrl}/commands/squad-ci.md`,
802
- '.contextkit/commands/squad-ci.md'
853
+ `${this.repoUrl}/commands/squad/squad-ci.md`,
854
+ '.contextkit/commands/squad/squad-ci.md'
803
855
  );
804
856
  await this.downloadManager.downloadFile(
805
- `${this.repoUrl}/commands/health-check.md`,
806
- '.contextkit/commands/health-check.md'
857
+ `${this.repoUrl}/commands/dev/health-check.md`,
858
+ '.contextkit/commands/dev/health-check.md'
807
859
  );
808
860
 
809
861
  // Download doc family commands
810
862
  await this.downloadManager.downloadFile(
811
- `${this.repoUrl}/commands/doc-arch.md`,
812
- '.contextkit/commands/doc-arch.md'
863
+ `${this.repoUrl}/commands/docs/doc-arch.md`,
864
+ '.contextkit/commands/docs/doc-arch.md'
865
+ );
866
+ await this.downloadManager.downloadFile(
867
+ `${this.repoUrl}/commands/docs/doc-feature.md`,
868
+ '.contextkit/commands/docs/doc-feature.md'
813
869
  );
814
870
  await this.downloadManager.downloadFile(
815
- `${this.repoUrl}/commands/doc-feature.md`,
816
- '.contextkit/commands/doc-feature.md'
871
+ `${this.repoUrl}/commands/docs/doc-component.md`,
872
+ '.contextkit/commands/docs/doc-component.md'
873
+ );
874
+
875
+ // Download agentic workflow commands
876
+ await this.downloadManager.downloadFile(
877
+ `${this.repoUrl}/commands/agents/context-budget.md`,
878
+ '.contextkit/commands/agents/context-budget.md'
879
+ );
880
+ await this.downloadManager.downloadFile(
881
+ `${this.repoUrl}/commands/agents/agent-push-checklist.md`,
882
+ '.contextkit/commands/agents/agent-push-checklist.md'
817
883
  );
818
884
  await this.downloadManager.downloadFile(
819
- `${this.repoUrl}/commands/doc-component.md`,
820
- '.contextkit/commands/doc-component.md'
885
+ `${this.repoUrl}/commands/agents/standards-aware.md`,
886
+ '.contextkit/commands/agents/standards-aware.md'
821
887
  );
822
888
 
823
889
  // Download hooks (pre-push and commit-msg only, no pre-commit)
@@ -920,15 +986,15 @@ claude "read .contextkit/context.md to see available standards, then create a bu
920
986
  - \`.contextkit/product/context.md\` - Domain-specific context
921
987
 
922
988
  ### Commands
923
- - \`.contextkit/commands/analyze.md\` - Analyze & customize standards
924
- - \`.contextkit/commands/review.md\` - Code review
925
- - \`.contextkit/commands/fix.md\` - Diagnose and fix bugs
926
- - \`.contextkit/commands/refactor.md\` - Refactor code structure
927
- - \`.contextkit/commands/run-tests.md\` - Generate or run tests
928
- - \`.contextkit/commands/add-documentation.md\` - Add documentation
929
- - \`.contextkit/commands/quality-check.md\` - Quality checks
930
- - \`.contextkit/commands/create-component.md\` - Create component
931
- - \`.contextkit/commands/create-feature.md\` - Create feature
989
+ - \`.contextkit/commands/dev/analyze.md\` - Analyze & customize standards
990
+ - \`.contextkit/commands/dev/review.md\` - Code review
991
+ - \`.contextkit/commands/dev/fix.md\` - Diagnose and fix bugs
992
+ - \`.contextkit/commands/dev/refactor.md\` - Refactor code structure
993
+ - \`.contextkit/commands/dev/run-tests.md\` - Generate or run tests
994
+ - \`.contextkit/commands/docs/add-documentation.md\` - Add documentation
995
+ - \`.contextkit/commands/dev/quality-check.md\` - Quality checks
996
+ - \`.contextkit/commands/dev/create-component.md\` - Create component
997
+ - \`.contextkit/commands/dev/create-feature.md\` - Create feature
932
998
 
933
999
  ### Instructions
934
1000
  - \`.contextkit/instructions/meta/pre-flight.md\` - Pre-flight checks
@@ -982,7 +1048,7 @@ claude "read .contextkit/standards/README.md .contextkit/standards/glossary.md a
982
1048
  claude "read .contextkit/product/mission-lite.md .contextkit/standards/code-style.md and create a feature"
983
1049
  \`\`\`
984
1050
  `;
985
-
1051
+
986
1052
  await fs.writeFile('.contextkit/context.md', context);
987
1053
  await fs.writeFile('.contextkit/CONTEXT.md', context); // Keep uppercase for backward compatibility
988
1054
 
@@ -993,14 +1059,14 @@ claude "read .contextkit/product/mission-lite.md .contextkit/standards/code-styl
993
1059
 
994
1060
  CONTEXT_FILE=".contextkit/context.md"
995
1061
  AI_TOOL="\${AI_TOOL:-aider}"
996
- PROMPT="\$@"
1062
+ PROMPT="$@"
997
1063
 
998
1064
  if [ ! -f "$CONTEXT_FILE" ]; then
999
1065
  echo "❌ ContextKit not initialized. Run: contextkit install"
1000
1066
  exit 1
1001
1067
  fi
1002
1068
 
1003
- CONTEXT=\$(cat "$CONTEXT_FILE")
1069
+ CONTEXT=$(cat "$CONTEXT_FILE")
1004
1070
 
1005
1071
  case "$AI_TOOL" in
1006
1072
  "aider")
@@ -1021,7 +1087,7 @@ esac
1021
1087
 
1022
1088
  await fs.writeFile('.contextkit/scripts/ai-cli.sh', cliScript);
1023
1089
  await fs.chmod('.contextkit/scripts/ai-cli.sh', '755');
1024
-
1090
+
1025
1091
  console.log(chalk.green('✅ CLI helpers installed'));
1026
1092
  }
1027
1093
 
@@ -1046,27 +1112,30 @@ esac
1046
1112
  components: 'src/components',
1047
1113
  tests: 'src/__tests__',
1048
1114
  stories: 'src/stories',
1049
- docs: 'docs'
1115
+ docs: 'docs',
1050
1116
  },
1051
1117
  commands: {
1052
- analyze: '@.contextkit/commands/analyze.md',
1053
- review: '@.contextkit/commands/review.md',
1054
- fix: '@.contextkit/commands/fix.md',
1055
- refactor: '@.contextkit/commands/refactor.md',
1056
- run_tests: '@.contextkit/commands/run-tests.md',
1057
- add_docs: '@.contextkit/commands/add-documentation.md',
1058
- quality_check: '@.contextkit/commands/quality-check.md',
1059
- create_component: '@.contextkit/commands/create-component.md',
1060
- create_feature: '@.contextkit/commands/create-feature.md'
1061
- }
1118
+ analyze: '@.contextkit/commands/dev/analyze.md',
1119
+ review: '@.contextkit/commands/dev/review.md',
1120
+ fix: '@.contextkit/commands/dev/fix.md',
1121
+ refactor: '@.contextkit/commands/dev/refactor.md',
1122
+ run_tests: '@.contextkit/commands/dev/run-tests.md',
1123
+ add_docs: '@.contextkit/commands/docs/add-documentation.md',
1124
+ quality_check: '@.contextkit/commands/dev/quality-check.md',
1125
+ create_component: '@.contextkit/commands/dev/create-component.md',
1126
+ create_feature: '@.contextkit/commands/dev/create-feature.md',
1127
+ },
1062
1128
  };
1063
1129
 
1064
1130
  const now = new Date().toISOString();
1065
- const isMonorepo = await fs.pathExists('packages') || await fs.pathExists('apps') ||
1066
- (await fs.pathExists('package.json') &&
1067
- (await fs.readJson('package.json').catch(() => ({}))).workspaces);
1068
-
1069
- await fs.writeFile('.contextkit/config.yml',
1131
+ const isMonorepo =
1132
+ (await fs.pathExists('packages')) ||
1133
+ (await fs.pathExists('apps')) ||
1134
+ ((await fs.pathExists('package.json')) &&
1135
+ (await fs.readJson('package.json').catch(() => ({}))).workspaces);
1136
+
1137
+ await fs.writeFile(
1138
+ '.contextkit/config.yml',
1070
1139
  `# ContextKit Configuration
1071
1140
  _source:
1072
1141
  tool: "@nolrm/contextkit"
@@ -1165,7 +1234,7 @@ https://www.npmjs.com/package/@nolrm/contextkit
1165
1234
  status.features.pre_push_hook = hookChoices.prePush;
1166
1235
  status.features.commit_msg_hook = hookChoices.commitMsg;
1167
1236
  status.features.squad_ci_workflow = squadCi;
1168
-
1237
+
1169
1238
  await this.statusManager.saveStatus(status);
1170
1239
  console.log(chalk.green('✅ Status tracking initialized'));
1171
1240
  } catch (error) {
@@ -1175,7 +1244,7 @@ https://www.npmjs.com/package/@nolrm/contextkit
1175
1244
 
1176
1245
  async createProductContext() {
1177
1246
  console.log(chalk.blue('📦 Creating product context files...'));
1178
-
1247
+
1179
1248
  const missionContent = `# Product Mission
1180
1249
 
1181
1250
  <!-- Content will be generated by running: ck analyze or manually fill this in -->
@@ -1373,13 +1442,13 @@ Unlike [COMPETITOR_OR_ALTERNATIVE], we provide [SPECIFIC_ADVANTAGE]. This result
1373
1442
  await fs.writeFile('.contextkit/product/roadmap.md', roadmapContent);
1374
1443
  await fs.writeFile('.contextkit/product/decisions.md', decisionsContent);
1375
1444
  await fs.writeFile('.contextkit/product/context.md', contextContent);
1376
-
1445
+
1377
1446
  console.log(chalk.green('✅ Product context files created'));
1378
1447
  }
1379
1448
 
1380
1449
  async createCorrectionsLog() {
1381
1450
  console.log(chalk.blue('📝 Creating corrections log system...'));
1382
-
1451
+
1383
1452
  const correctionsContent = `# ContextKit Corrections Log
1384
1453
 
1385
1454
  ## Description
@@ -1565,14 +1634,17 @@ Automatically track and log ContextKit performance issues during development ses
1565
1634
  `;
1566
1635
 
1567
1636
  await fs.writeFile('.contextkit/corrections.md', correctionsContent);
1568
- await fs.writeFile('.contextkit/instructions/core/auto-corrections-log.md', autoCorrectionsContent);
1569
-
1637
+ await fs.writeFile(
1638
+ '.contextkit/instructions/core/auto-corrections-log.md',
1639
+ autoCorrectionsContent
1640
+ );
1641
+
1570
1642
  console.log(chalk.green('✅ Corrections log system created'));
1571
1643
  }
1572
1644
 
1573
1645
  async createMetaInstructions() {
1574
1646
  console.log(chalk.blue('📋 Creating meta instructions...'));
1575
-
1647
+
1576
1648
  const preFlightContent = `---
1577
1649
  description: Common Pre-Flight Steps for ContextKit Instructions
1578
1650
  globs:
@@ -1646,13 +1718,13 @@ After completing any development session, automatically update the corrections l
1646
1718
 
1647
1719
  await fs.writeFile('.contextkit/instructions/meta/pre-flight.md', preFlightContent);
1648
1720
  await fs.writeFile('.contextkit/instructions/meta/post-flight.md', postFlightContent);
1649
-
1721
+
1650
1722
  console.log(chalk.green('✅ Meta instructions created'));
1651
1723
  }
1652
1724
 
1653
1725
  async createPolicyFile() {
1654
1726
  console.log(chalk.blue('⚖️ Creating policy file...'));
1655
-
1727
+
1656
1728
  const policyContent = `# ContextKit Policy Configuration
1657
1729
 
1658
1730
  ## Enforcement Levels
@@ -1676,11 +1748,11 @@ enforcement:
1676
1748
  `;
1677
1749
 
1678
1750
  await fs.writeFile('.contextkit/policies/policy.yml', policyContent);
1679
-
1751
+
1680
1752
  console.log(chalk.green('✅ Policy file created'));
1681
1753
  }
1682
1754
 
1683
- showSuccessMessage(hookChoices, platform = null, projectType = '', packageManager = '') {
1755
+ showSuccessMessage(hookChoices, platform = null, _projectType = '', _packageManager = '') {
1684
1756
  console.log('');
1685
1757
  console.log(chalk.green('🎉 ContextKit v1.0.0 successfully installed!'));
1686
1758
  console.log('');
@@ -1702,7 +1774,9 @@ enforcement:
1702
1774
  console.log(chalk.bold('📖 Quick Reference'));
1703
1775
  console.log(''.padEnd(48, '─'));
1704
1776
  console.log(`ck status → Check installation & integrations`);
1705
- console.log(`ck <platform> → Add platform (claude, cursor, copilot, codex, opencode, gemini, aider, continue, windsurf)`);
1777
+ console.log(
1778
+ `ck <platform> → Add platform (claude, cursor, copilot, codex, opencode, gemini, aider, continue, windsurf)`
1779
+ );
1706
1780
  console.log('');
1707
1781
  console.log(`Docs → ${chalk.blue('https://contextkit-docs.vercel.app')}`);
1708
1782
  console.log(`Issues → ${chalk.blue('https://github.com/nolrm/contextkit/issues')}`);
@@ -1715,7 +1789,7 @@ enforcement:
1715
1789
 
1716
1790
  if (platform === 'cursor') {
1717
1791
  console.log(chalk.bold('In Cursor Chat:'));
1718
- console.log(` @.contextkit/commands/analyze.md`);
1792
+ console.log(` @.contextkit/commands/dev/analyze.md`);
1719
1793
  console.log('');
1720
1794
  console.log('Or via CLI:');
1721
1795
  console.log(chalk.yellow('👉'), `/analyze`);
@@ -1741,19 +1815,23 @@ enforcement:
1741
1815
 
1742
1816
  if (platform === 'cursor') {
1743
1817
  console.log(chalk.bold('In Cursor Chat'));
1744
- console.log(`@.contextkit/commands/create-component.md`);
1818
+ console.log(`@.contextkit/commands/dev/create-component.md`);
1745
1819
  console.log(chalk.dim('"Create a Button component for customer checkout"'));
1746
1820
  console.log('');
1747
1821
  }
1748
1822
 
1749
1823
  console.log(chalk.bold('In CLI'));
1750
- console.log(chalk.dim('Use your AI tool\'s slash command, e.g. /analyze or @.contextkit/commands/create-component.md'));
1824
+ console.log(
1825
+ chalk.dim(
1826
+ "Use your AI tool's slash command, e.g. /analyze or @.contextkit/commands/dev/create-component.md"
1827
+ )
1828
+ );
1751
1829
  console.log('');
1752
1830
 
1753
1831
  if (platform === 'claude' || platform === 'gemini') {
1754
1832
  const toolName = platform === 'claude' ? 'Claude' : 'Gemini';
1755
1833
  console.log(chalk.bold(`In ${toolName} CLI`));
1756
- console.log(`read .contextkit/commands/analyze.md and execute`);
1834
+ console.log(`read .contextkit/commands/dev/analyze.md and execute`);
1757
1835
  console.log('');
1758
1836
  }
1759
1837
 
@@ -1761,6 +1839,179 @@ enforcement:
1761
1839
  console.log('');
1762
1840
  }
1763
1841
 
1842
+ async promptQualityTooling(packageManager, _options = {}) {
1843
+ // Only relevant for Node.js projects
1844
+ if (!(await fs.pathExists('package.json'))) return;
1845
+
1846
+ // Skip in CI / non-interactive mode
1847
+ if (process.env.CI === 'true' || process.env.NON_INTERACTIVE === 'true') return;
1848
+
1849
+ const pkg = await fs.readJson('package.json').catch(() => null);
1850
+ if (!pkg) return;
1851
+
1852
+ const hasFormat = !!(pkg.scripts && pkg.scripts.format);
1853
+ const hasLint = !!(pkg.scripts && pkg.scripts.lint);
1854
+
1855
+ // Both already present — nothing to do
1856
+ if (hasFormat && hasLint) return;
1857
+
1858
+ console.log('');
1859
+ console.log('──────────────────────────────────────────────');
1860
+ console.log(chalk.blue('🛠️ Format + Lint Quality Gates'));
1861
+ console.log('──────────────────────────────────────────────');
1862
+ console.log(chalk.dim('The pre-push hook runs format and lint scripts automatically'));
1863
+ console.log(chalk.dim('when present. Your project has none — add a minimal setup now?'));
1864
+ console.log('');
1865
+
1866
+ const { scaffold } = await inquirer.prompt([
1867
+ {
1868
+ type: 'confirm',
1869
+ name: 'scaffold',
1870
+ message: 'Add prettier + eslint setup? (adds scripts + config files)',
1871
+ default: false,
1872
+ },
1873
+ ]);
1874
+
1875
+ if (scaffold) {
1876
+ await this.scaffoldQualityTooling(pkg, packageManager);
1877
+ } else {
1878
+ console.log(chalk.dim('💡 Add format/lint scripts later to activate these quality gates'));
1879
+ }
1880
+ console.log('');
1881
+ }
1882
+
1883
+ async scaffoldQualityTooling(pkg, packageManager) {
1884
+ const pmInstallFlags = {
1885
+ npm: 'install --save-dev',
1886
+ yarn: 'add --dev',
1887
+ pnpm: 'add -D',
1888
+ bun: 'add -d',
1889
+ };
1890
+ const installFlag = pmInstallFlags[packageManager] || 'install --save-dev';
1891
+ const pm = packageManager === 'none' ? 'npm' : packageManager;
1892
+
1893
+ try {
1894
+ const created = [];
1895
+
1896
+ // 1. Add missing scripts to package.json
1897
+ if (!pkg.scripts) pkg.scripts = {};
1898
+ if (!pkg.scripts.format) {
1899
+ pkg.scripts.format = 'prettier --write .';
1900
+ created.push('format script');
1901
+ }
1902
+ if (!pkg.scripts.lint) {
1903
+ pkg.scripts.lint = 'eslint .';
1904
+ created.push('lint script');
1905
+ }
1906
+ await fs.writeFile('package.json', JSON.stringify(pkg, null, 2) + '\n');
1907
+
1908
+ // 2. Create .prettierrc if no existing config
1909
+ if (!(await this._hasExistingPrettierConfig(pkg))) {
1910
+ await fs.writeFile(
1911
+ '.prettierrc',
1912
+ JSON.stringify(
1913
+ { singleQuote: true, semi: true, tabWidth: 2, printWidth: 100, trailingComma: 'es5' },
1914
+ null,
1915
+ 2
1916
+ ) + '\n'
1917
+ );
1918
+ created.push('.prettierrc');
1919
+ }
1920
+
1921
+ // 3. Create .prettierignore if absent
1922
+ if (!(await fs.pathExists('.prettierignore'))) {
1923
+ await fs.writeFile('.prettierignore', 'node_modules/\ncoverage/\ndist/\nbuild/\n');
1924
+ created.push('.prettierignore');
1925
+ }
1926
+
1927
+ // 4. Create eslint.config.js if no existing config
1928
+ if (!(await this._hasExistingEslintConfig(pkg))) {
1929
+ await fs.writeFile(
1930
+ 'eslint.config.js',
1931
+ `const js = require('@eslint/js');
1932
+ const globals = require('globals');
1933
+
1934
+ module.exports = [
1935
+ js.configs.recommended,
1936
+ {
1937
+ languageOptions: {
1938
+ ecmaVersion: 2022,
1939
+ globals: {
1940
+ ...globals.node,
1941
+ },
1942
+ },
1943
+ rules: {
1944
+ 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
1945
+ },
1946
+ },
1947
+ {
1948
+ files: ['**/__tests__/**/*.js', '**/*.test.js'],
1949
+ languageOptions: {
1950
+ globals: {
1951
+ ...globals.jest,
1952
+ },
1953
+ },
1954
+ },
1955
+ ];\n`
1956
+ );
1957
+ created.push('eslint.config.js');
1958
+ }
1959
+
1960
+ // 5. Install devDependencies
1961
+ console.log(chalk.blue(`\n📦 Installing prettier + eslint...`));
1962
+ childProcess.execSync(`${pm} ${installFlag} prettier eslint @eslint/js globals`, {
1963
+ stdio: 'inherit',
1964
+ });
1965
+
1966
+ console.log('');
1967
+ console.log(chalk.green('✅ Quality tooling ready:'));
1968
+ created.forEach((item) => console.log(chalk.dim(` • ${item}`)));
1969
+ console.log(chalk.dim(' Run npm run format to apply formatting to existing files'));
1970
+ } catch (error) {
1971
+ console.log(chalk.yellow('⚠️ Could not complete quality tooling setup:'), error.message);
1972
+ console.log(chalk.dim(' You can set this up manually later'));
1973
+ }
1974
+ }
1975
+
1976
+ async _hasExistingPrettierConfig(pkg) {
1977
+ if (pkg.prettier) return true;
1978
+ const configs = [
1979
+ '.prettierrc',
1980
+ '.prettierrc.json',
1981
+ '.prettierrc.js',
1982
+ '.prettierrc.mjs',
1983
+ '.prettierrc.cjs',
1984
+ '.prettierrc.yaml',
1985
+ '.prettierrc.yml',
1986
+ '.prettierrc.toml',
1987
+ 'prettier.config.js',
1988
+ 'prettier.config.mjs',
1989
+ 'prettier.config.cjs',
1990
+ ];
1991
+ for (const f of configs) {
1992
+ if (await fs.pathExists(f)) return true;
1993
+ }
1994
+ return false;
1995
+ }
1996
+
1997
+ async _hasExistingEslintConfig(pkg) {
1998
+ if (pkg.eslintConfig) return true;
1999
+ const configs = [
2000
+ 'eslint.config.js',
2001
+ 'eslint.config.mjs',
2002
+ 'eslint.config.cjs',
2003
+ '.eslintrc',
2004
+ '.eslintrc.js',
2005
+ '.eslintrc.json',
2006
+ '.eslintrc.yml',
2007
+ '.eslintrc.yaml',
2008
+ ];
2009
+ for (const f of configs) {
2010
+ if (await fs.pathExists(f)) return true;
2011
+ }
2012
+ return false;
2013
+ }
2014
+
1764
2015
  async _findFileUpward(name, maxLevels) {
1765
2016
  let dir = process.cwd();
1766
2017
  for (let i = 0; i <= maxLevels; i++) {
@@ -1771,6 +2022,59 @@ enforcement:
1771
2022
  }
1772
2023
  return false;
1773
2024
  }
2025
+
2026
+ async createQualityGatesConfig() {
2027
+ const configPath = '.contextkit/quality-gates.yml';
2028
+ if (await fs.pathExists(configPath)) return;
2029
+ const content = `# Quality Gates Configuration
2030
+ # Disable specific gates by uncommenting keys below.
2031
+ # All gates are enabled by default.
2032
+ # Reference: https://contextkit-docs.vercel.app/docs/quality-gates
2033
+
2034
+ disabled:
2035
+ # Node.js gates
2036
+ # - typescript # skip TypeScript type checking
2037
+ # - eslint # skip ESLint (direct, not via script)
2038
+ # - prettier # skip Prettier (direct, not via script)
2039
+ # - format # skip npm run format
2040
+ # - lint # skip npm run lint
2041
+ # - build # skip npm run build
2042
+ # - test # skip npm test
2043
+ # - e2e # skip npm run e2e
2044
+ # Python gates
2045
+ # - ruff-lint # skip ruff/flake8 lint
2046
+ # - typecheck # skip mypy
2047
+ # - ruff-format # skip ruff/black format check
2048
+ # - pytest # skip pytest
2049
+ # Rust gates
2050
+ # - cargo-check # skip cargo check
2051
+ # - clippy # skip cargo clippy
2052
+ # - cargo-test # skip cargo test
2053
+ # Go gates
2054
+ # - go-vet # skip go vet
2055
+ # - golangci-lint # skip golangci-lint
2056
+ # - go-test # skip go test
2057
+ # PHP gates
2058
+ # - phpstan # skip PHPStan
2059
+ # - phpunit # skip PHPUnit
2060
+ # Ruby gates
2061
+ # - rubocop # skip RuboCop
2062
+ # - rspec # skip RSpec / rake test
2063
+ # Java / Kotlin gates
2064
+ # - maven-verify # skip mvn verify
2065
+ # - gradle-check # skip gradle check
2066
+ # - ktlint # skip ktlint
2067
+ # - kotlin-test # skip gradle test
2068
+ # Swift gates
2069
+ # - swiftlint # skip SwiftLint
2070
+ # - swift-test # skip swift test
2071
+ # .NET gates
2072
+ # - dotnet-build # skip dotnet build
2073
+ # - dotnet-test # skip dotnet test
2074
+ `;
2075
+ await fs.writeFile(configPath, content);
2076
+ console.log(chalk.green('✅ Created .contextkit/quality-gates.yml'));
2077
+ }
1774
2078
  }
1775
2079
 
1776
2080
  async function install(options) {
@@ -1779,3 +2083,4 @@ async function install(options) {
1779
2083
  }
1780
2084
 
1781
2085
  module.exports = install;
2086
+ module.exports.InstallCommand = InstallCommand;