@nolrm/contextkit 0.9.3 → 0.9.4

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.
package/README.md CHANGED
@@ -111,13 +111,17 @@ Each platform generates bridge files that the AI tool auto-reads. If a bridge fi
111
111
 
112
112
  ## Use it in your tool
113
113
 
114
- **Cursor** — rules auto-load from `.cursor/rules/`
114
+ **Cursor** — rules auto-load from `.cursor/rules/`, slash commands in `.cursor/prompts/`
115
115
  ```
116
- @.contextkit/commands/analyze.md
116
+ /analyze # scan codebase and generate standards
117
+ /review # code review with checklist
118
+ /fix # diagnose and fix bugs
117
119
  ```
118
120
 
119
- **Claude Code** — reads `CLAUDE.md` + `.claude/rules/` automatically
121
+ **Claude Code** — reads `CLAUDE.md` + `.claude/rules/`, slash commands in `.claude/commands/`
120
122
  ```bash
123
+ /analyze # scan codebase and generate standards
124
+ /review # code review with checklist
121
125
  claude "create checkout flow for customer"
122
126
  ```
123
127
 
@@ -133,14 +137,36 @@ codex "create checkout flow for customer"
133
137
 
134
138
  **CLI** (Chat with AI)
135
139
  ```bash
136
- ck ai "create checkout flow for customer"
140
+ ck ai "create a button"
137
141
  ```
138
142
 
139
143
  ---
140
144
 
145
+ ## Slash Commands
146
+
147
+ ContextKit installs reusable slash commands for supported platforms:
148
+
149
+ | Command | What it does |
150
+ |---------|-------------|
151
+ | `/analyze` | Scan codebase and generate standards content |
152
+ | `/review` | Code review with checklist |
153
+ | `/fix` | Diagnose and fix bugs |
154
+ | `/refactor` | Refactor code with safety checks |
155
+ | `/test` | Generate comprehensive tests |
156
+ | `/doc` | Add documentation |
157
+
158
+ **Claude Code** — available as `/analyze`, `/review`, etc. in `.claude/commands/`
159
+ **Cursor** — available as slash commands in Chat via `.cursor/prompts/`
160
+
161
+ Both platforms delegate to the universal command files in `.contextkit/commands/`, so you maintain one set of workflows.
162
+
163
+ ---
164
+
141
165
  ## Git Hooks & Quality Gates
142
166
 
143
- ContextKit can optionally install native Git hooks (`.git/hooks/`) during `ck install`. No external dependencies like Husky required works in any git repo, not just Node.js projects.
167
+ ContextKit can optionally install Git hooks during `ck install`. Uses `git config core.hooksPath` to point Git at `.contextkit/hooks/` — no external dependencies like Husky required. Works in any git repo, not just Node.js projects.
168
+
169
+ For **Node.js projects**, a `prepare` script is automatically added to `package.json` so hooks activate for all developers after `npm install` — no need for everyone to run `ck install`.
144
170
 
145
171
  | Hook | What it does |
146
172
  |------|-------------|
@@ -515,12 +515,20 @@ Run \`ck analyze\` to generate this content, or manually add your API pattern be
515
515
 
516
516
  // Download commands
517
517
  await this.downloadManager.downloadFile(
518
- `${this.repoUrl}/commands/create-feature.md`,
519
- '.contextkit/commands/create-feature.md'
518
+ `${this.repoUrl}/commands/analyze.md`,
519
+ '.contextkit/commands/analyze.md'
520
520
  );
521
521
  await this.downloadManager.downloadFile(
522
- `${this.repoUrl}/commands/create-component.md`,
523
- '.contextkit/commands/create-component.md'
522
+ `${this.repoUrl}/commands/review.md`,
523
+ '.contextkit/commands/review.md'
524
+ );
525
+ await this.downloadManager.downloadFile(
526
+ `${this.repoUrl}/commands/fix.md`,
527
+ '.contextkit/commands/fix.md'
528
+ );
529
+ await this.downloadManager.downloadFile(
530
+ `${this.repoUrl}/commands/refactor.md`,
531
+ '.contextkit/commands/refactor.md'
524
532
  );
525
533
  await this.downloadManager.downloadFile(
526
534
  `${this.repoUrl}/commands/run-tests.md`,
@@ -535,18 +543,22 @@ Run \`ck analyze\` to generate this content, or manually add your API pattern be
535
543
  '.contextkit/commands/quality-check.md'
536
544
  );
537
545
  await this.downloadManager.downloadFile(
538
- `${this.repoUrl}/commands/analyze.md`,
539
- '.contextkit/commands/analyze.md'
546
+ `${this.repoUrl}/commands/create-feature.md`,
547
+ '.contextkit/commands/create-feature.md'
548
+ );
549
+ await this.downloadManager.downloadFile(
550
+ `${this.repoUrl}/commands/create-component.md`,
551
+ '.contextkit/commands/create-component.md'
540
552
  );
541
553
 
542
554
  // Download hooks (pre-push and commit-msg only, no pre-commit)
543
555
  await this.downloadManager.downloadFile(
544
- `${this.repoUrl}/hooks/pre-push.sh`,
545
- '.contextkit/hooks/pre-push.sh'
556
+ `${this.repoUrl}/hooks/pre-push`,
557
+ '.contextkit/hooks/pre-push'
546
558
  );
547
559
  await this.downloadManager.downloadFile(
548
- `${this.repoUrl}/hooks/commit-msg.sh`,
549
- '.contextkit/hooks/commit-msg.sh'
560
+ `${this.repoUrl}/hooks/commit-msg`,
561
+ '.contextkit/hooks/commit-msg'
550
562
  );
551
563
  await this.downloadManager.downloadFile(
552
564
  `${this.repoUrl}/hooks/setup-hooks.sh`,
@@ -581,8 +593,8 @@ Run \`ck analyze\` to generate this content, or manually add your API pattern be
581
593
  );
582
594
 
583
595
  // Make scripts executable
584
- await fs.chmod('.contextkit/hooks/pre-push.sh', '755');
585
- await fs.chmod('.contextkit/hooks/commit-msg.sh', '755');
596
+ await fs.chmod('.contextkit/hooks/pre-push', '755');
597
+ await fs.chmod('.contextkit/hooks/commit-msg', '755');
586
598
  await fs.chmod('.contextkit/hooks/setup-hooks.sh', '755');
587
599
  await fs.chmod('.contextkit/types/type-check.sh', '755');
588
600
  await fs.chmod('.contextkit/scripts/update.sh', '755');
@@ -683,11 +695,14 @@ claude "read .contextkit/context.md to see available standards, then create a bu
683
695
 
684
696
  ### Commands
685
697
  - \`.contextkit/commands/analyze.md\` - Analyze & customize standards
698
+ - \`.contextkit/commands/review.md\` - Code review
699
+ - \`.contextkit/commands/fix.md\` - Diagnose and fix bugs
700
+ - \`.contextkit/commands/refactor.md\` - Refactor code structure
701
+ - \`.contextkit/commands/run-tests.md\` - Generate or run tests
702
+ - \`.contextkit/commands/add-documentation.md\` - Add documentation
703
+ - \`.contextkit/commands/quality-check.md\` - Quality checks
686
704
  - \`.contextkit/commands/create-component.md\` - Create component
687
705
  - \`.contextkit/commands/create-feature.md\` - Create feature
688
- - \`.contextkit/commands/run-tests.md\` - Run tests
689
- - \`.contextkit/commands/quality-check.md\` - Quality checks
690
- - \`.contextkit/commands/add-documentation.md\` - Add documentation
691
706
 
692
707
  ### Instructions
693
708
  - \`.contextkit/instructions/meta/pre-flight.md\` - Pre-flight checks
@@ -806,12 +821,15 @@ esac
806
821
  docs: 'docs'
807
822
  },
808
823
  commands: {
809
- create_component: '@.contextkit/commands/create-component.md',
810
- create_feature: '@.contextkit/commands/create-feature.md',
824
+ analyze: '@.contextkit/commands/analyze.md',
825
+ review: '@.contextkit/commands/review.md',
826
+ fix: '@.contextkit/commands/fix.md',
827
+ refactor: '@.contextkit/commands/refactor.md',
811
828
  run_tests: '@.contextkit/commands/run-tests.md',
812
829
  add_docs: '@.contextkit/commands/add-documentation.md',
813
830
  quality_check: '@.contextkit/commands/quality-check.md',
814
- analyze: '@.contextkit/commands/analyze.md'
831
+ create_component: '@.contextkit/commands/create-component.md',
832
+ create_feature: '@.contextkit/commands/create-feature.md'
815
833
  }
816
834
  };
817
835
 
@@ -213,12 +213,20 @@ class UpdateCommand {
213
213
 
214
214
  // Download commands
215
215
  await this.downloadManager.downloadFile(
216
- `${this.repoUrl}/commands/create-feature.md`,
217
- '.contextkit/commands/create-feature.md'
216
+ `${this.repoUrl}/commands/analyze.md`,
217
+ '.contextkit/commands/analyze.md'
218
218
  );
219
219
  await this.downloadManager.downloadFile(
220
- `${this.repoUrl}/commands/create-component.md`,
221
- '.contextkit/commands/create-component.md'
220
+ `${this.repoUrl}/commands/review.md`,
221
+ '.contextkit/commands/review.md'
222
+ );
223
+ await this.downloadManager.downloadFile(
224
+ `${this.repoUrl}/commands/fix.md`,
225
+ '.contextkit/commands/fix.md'
226
+ );
227
+ await this.downloadManager.downloadFile(
228
+ `${this.repoUrl}/commands/refactor.md`,
229
+ '.contextkit/commands/refactor.md'
222
230
  );
223
231
  await this.downloadManager.downloadFile(
224
232
  `${this.repoUrl}/commands/run-tests.md`,
@@ -233,18 +241,22 @@ class UpdateCommand {
233
241
  '.contextkit/commands/quality-check.md'
234
242
  );
235
243
  await this.downloadManager.downloadFile(
236
- `${this.repoUrl}/commands/analyze.md`,
237
- '.contextkit/commands/analyze.md'
244
+ `${this.repoUrl}/commands/create-feature.md`,
245
+ '.contextkit/commands/create-feature.md'
246
+ );
247
+ await this.downloadManager.downloadFile(
248
+ `${this.repoUrl}/commands/create-component.md`,
249
+ '.contextkit/commands/create-component.md'
238
250
  );
239
251
 
240
252
  // Download hooks (pre-push and commit-msg only, no pre-commit)
241
253
  await this.downloadManager.downloadFile(
242
- `${this.repoUrl}/hooks/pre-push.sh`,
243
- '.contextkit/hooks/pre-push.sh'
254
+ `${this.repoUrl}/hooks/pre-push`,
255
+ '.contextkit/hooks/pre-push'
244
256
  );
245
257
  await this.downloadManager.downloadFile(
246
- `${this.repoUrl}/hooks/commit-msg.sh`,
247
- '.contextkit/hooks/commit-msg.sh'
258
+ `${this.repoUrl}/hooks/commit-msg`,
259
+ '.contextkit/hooks/commit-msg'
248
260
  );
249
261
  await this.downloadManager.downloadFile(
250
262
  `${this.repoUrl}/hooks/setup-hooks.sh`,
@@ -278,8 +290,8 @@ class UpdateCommand {
278
290
  );
279
291
 
280
292
  // Make scripts executable
281
- await fs.chmod('.contextkit/hooks/pre-push.sh', '755');
282
- await fs.chmod('.contextkit/hooks/commit-msg.sh', '755');
293
+ await fs.chmod('.contextkit/hooks/pre-push', '755');
294
+ await fs.chmod('.contextkit/hooks/commit-msg', '755');
283
295
  await fs.chmod('.contextkit/hooks/setup-hooks.sh', '755');
284
296
  await fs.chmod('.contextkit/types/type-check.sh', '755');
285
297
  await fs.chmod('.contextkit/scripts/update.sh', '755');
@@ -317,12 +329,15 @@ paths:
317
329
 
318
330
  # Commands
319
331
  commands:
320
- create_component: "${config.commands?.create_component || '@.contextkit/commands/create-component.md'}"
321
- create_feature: "${config.commands?.create_feature || '@.contextkit/commands/create-feature.md'}"
332
+ analyze: "${config.commands?.analyze || '@.contextkit/commands/analyze.md'}"
333
+ review: "${config.commands?.review || '@.contextkit/commands/review.md'}"
334
+ fix: "${config.commands?.fix || '@.contextkit/commands/fix.md'}"
335
+ refactor: "${config.commands?.refactor || '@.contextkit/commands/refactor.md'}"
322
336
  run_tests: "${config.commands?.run_tests || '@.contextkit/commands/run-tests.md'}"
323
337
  add_docs: "${config.commands?.add_docs || '@.contextkit/commands/add-documentation.md'}"
324
338
  quality_check: "${config.commands?.quality_check || '@.contextkit/commands/quality-check.md'}"
325
- analyze: "${config.commands?.analyze || '@.contextkit/commands/analyze.md'}"
339
+ create_component: "${config.commands?.create_component || '@.contextkit/commands/create-component.md'}"
340
+ create_feature: "${config.commands?.create_feature || '@.contextkit/commands/create-feature.md'}"
326
341
  `;
327
342
 
328
343
  await fs.writeFile('.contextkit/config.yml', configContent);
@@ -12,6 +12,11 @@ class ClaudeIntegration extends BaseIntegration {
12
12
  '.claude/rules/contextkit-testing.md',
13
13
  '.claude/rules/contextkit-code-style.md',
14
14
  '.claude/commands/analyze.md',
15
+ '.claude/commands/review.md',
16
+ '.claude/commands/fix.md',
17
+ '.claude/commands/refactor.md',
18
+ '.claude/commands/test.md',
19
+ '.claude/commands/doc.md',
15
20
  ];
16
21
  this.platformDir = '.claude/rules';
17
22
  }
@@ -112,14 +117,48 @@ When writing or modifying source code, follow:
112
117
  `;
113
118
  await this.writeGeneratedFile('.claude/rules/contextkit-code-style.md', codeStyleRule);
114
119
 
115
- // Command: analyze
116
- const analyzeCommand = `# Analyze Project
120
+ // Slash commands — thin wrappers that delegate to .contextkit/commands/
121
+ await this.writeGeneratedFile('.claude/commands/analyze.md', `# Analyze Project
117
122
 
118
123
  Read \`.contextkit/commands/analyze.md\` and execute the analysis workflow for this project.
119
124
 
120
125
  Scan the codebase structure, detect frameworks and patterns, then generate customized standards files in \`.contextkit/standards/\`.
121
- `;
122
- await this.writeGeneratedFile('.claude/commands/analyze.md', analyzeCommand);
126
+ `);
127
+
128
+ await this.writeGeneratedFile('.claude/commands/review.md', `# Code Review
129
+
130
+ Read \`.contextkit/commands/review.md\` and execute the review workflow.
131
+
132
+ Review current changes for correctness, standards compliance, and potential issues.
133
+ `);
134
+
135
+ await this.writeGeneratedFile('.claude/commands/fix.md', `# Fix Bug
136
+
137
+ Read \`.contextkit/commands/fix.md\` and execute the bug fix workflow.
138
+
139
+ Diagnose the root cause, implement the minimal fix, and add a regression test.
140
+ `);
141
+
142
+ await this.writeGeneratedFile('.claude/commands/refactor.md', `# Refactor
143
+
144
+ Read \`.contextkit/commands/refactor.md\` and execute the refactoring workflow.
145
+
146
+ Improve code structure without changing behavior, keeping tests green at every step.
147
+ `);
148
+
149
+ await this.writeGeneratedFile('.claude/commands/test.md', `# Run Tests
150
+
151
+ Read \`.contextkit/commands/run-tests.md\` and execute the testing workflow.
152
+
153
+ Generate or run tests for the specified code, covering happy paths, edge cases, and errors.
154
+ `);
155
+
156
+ await this.writeGeneratedFile('.claude/commands/doc.md', `# Add Documentation
157
+
158
+ Read \`.contextkit/commands/add-documentation.md\` and execute the documentation workflow.
159
+
160
+ Add inline docs, README sections, and usage examples for the specified code.
161
+ `);
123
162
  }
124
163
 
125
164
  showUsage() {
@@ -127,14 +166,14 @@ Scan the codebase structure, detect frameworks and patterns, then generate custo
127
166
  console.log(chalk.bold(' Claude Code Usage:'));
128
167
  console.log(' CLAUDE.md is auto-loaded every session');
129
168
  console.log(' .claude/rules/ are loaded based on file context');
130
- console.log(' Use /analyze slash command for project analysis');
131
169
  console.log('');
132
- console.log(chalk.dim(' Files created:'));
133
- console.log(chalk.dim(' CLAUDE.md (bridge - auto-loaded)'));
134
- console.log(chalk.dim(' .claude/rules/contextkit-standards.md (always apply)'));
135
- console.log(chalk.dim(' .claude/rules/contextkit-testing.md (test files)'));
136
- console.log(chalk.dim(' .claude/rules/contextkit-code-style.md (source files)'));
137
- console.log(chalk.dim(' .claude/commands/analyze.md (slash command)'));
170
+ console.log(chalk.dim(' Slash commands:'));
171
+ console.log(chalk.dim(' /analyze — Analyze project and generate standards'));
172
+ console.log(chalk.dim(' /review — Review current changes'));
173
+ console.log(chalk.dim(' /fix — Diagnose and fix a bug'));
174
+ console.log(chalk.dim(' /refactor — Refactor code structure'));
175
+ console.log(chalk.dim(' /test — Generate or run tests'));
176
+ console.log(chalk.dim(' /doc — Add documentation'));
138
177
  }
139
178
  }
140
179
 
@@ -12,6 +12,12 @@ class CursorIntegration extends BaseIntegration {
12
12
  '.cursor/rules/contextkit-testing.mdc',
13
13
  '.cursor/rules/contextkit-components.mdc',
14
14
  '.cursor/rules/contextkit-api.mdc',
15
+ '.cursor/prompts/analyze.md',
16
+ '.cursor/prompts/review.md',
17
+ '.cursor/prompts/fix.md',
18
+ '.cursor/prompts/refactor.md',
19
+ '.cursor/prompts/test.md',
20
+ '.cursor/prompts/doc.md',
15
21
  ];
16
22
  this.bridgeFiles = [];
17
23
  this.platformDir = '.cursor/rules';
@@ -19,6 +25,7 @@ class CursorIntegration extends BaseIntegration {
19
25
 
20
26
  async install() {
21
27
  await super.install();
28
+ await fs.ensureDir('.cursor/prompts');
22
29
  // Remove old monolithic rule file if present
23
30
  await this.removeLegacyFiles();
24
31
  }
@@ -142,20 +149,63 @@ Reference: @.contextkit/standards/architecture.md
142
149
  - @.contextkit/commands/create-feature.md — Create feature workflow
143
150
  `;
144
151
  await this.writeGeneratedFile('.cursor/rules/contextkit-api.mdc', apiRule);
152
+
153
+ // Cursor prompts — reusable slash commands in Cursor Chat
154
+ await this.writeGeneratedFile('.cursor/prompts/analyze.md', `# Analyze Project
155
+
156
+ Read \`.contextkit/commands/analyze.md\` and execute the analysis workflow for this project.
157
+
158
+ Scan the codebase structure, detect frameworks and patterns, then generate customized standards files in \`.contextkit/standards/\`.
159
+ `);
160
+
161
+ await this.writeGeneratedFile('.cursor/prompts/review.md', `# Code Review
162
+
163
+ Read \`.contextkit/commands/review.md\` and execute the review workflow.
164
+
165
+ Review current changes for correctness, standards compliance, and potential issues. Flag bugs, security concerns, and standards violations.
166
+ `);
167
+
168
+ await this.writeGeneratedFile('.cursor/prompts/fix.md', `# Fix Bug
169
+
170
+ Read \`.contextkit/commands/fix.md\` and execute the bug fix workflow.
171
+
172
+ Diagnose the root cause, implement the minimal fix, and add a regression test.
173
+ `);
174
+
175
+ await this.writeGeneratedFile('.cursor/prompts/refactor.md', `# Refactor
176
+
177
+ Read \`.contextkit/commands/refactor.md\` and execute the refactoring workflow.
178
+
179
+ Improve code structure without changing behavior, keeping tests green at every step.
180
+ `);
181
+
182
+ await this.writeGeneratedFile('.cursor/prompts/test.md', `# Run Tests
183
+
184
+ Read \`.contextkit/commands/run-tests.md\` and execute the testing workflow.
185
+
186
+ Generate or run tests for the specified code, covering happy paths, edge cases, and errors.
187
+ `);
188
+
189
+ await this.writeGeneratedFile('.cursor/prompts/doc.md', `# Add Documentation
190
+
191
+ Read \`.contextkit/commands/add-documentation.md\` and execute the documentation workflow.
192
+
193
+ Add inline docs, README sections, and usage examples for the specified code.
194
+ `);
145
195
  }
146
196
 
147
197
  showUsage() {
148
198
  console.log('');
149
199
  console.log(chalk.bold(' Cursor Usage:'));
150
200
  console.log(' Rules auto-load based on file context');
151
- console.log(' In Cursor Chat: @.contextkit/commands/analyze.md');
152
- console.log(' Or: @.contextkit Create a button component');
153
201
  console.log('');
154
- console.log(chalk.dim(' Files created:'));
155
- console.log(chalk.dim(' .cursor/rules/contextkit-standards.mdc (always apply)'));
156
- console.log(chalk.dim(' .cursor/rules/contextkit-testing.mdc (test files)'));
157
- console.log(chalk.dim(' .cursor/rules/contextkit-components.mdc (components)'));
158
- console.log(chalk.dim(' .cursor/rules/contextkit-api.mdc (API/services)'));
202
+ console.log(chalk.dim(' Slash commands (in Cursor Chat):'));
203
+ console.log(chalk.dim(' /analyze — Analyze project and generate standards'));
204
+ console.log(chalk.dim(' /review — Review current changes'));
205
+ console.log(chalk.dim(' /fix — Diagnose and fix a bug'));
206
+ console.log(chalk.dim(' /refactor — Refactor code structure'));
207
+ console.log(chalk.dim(' /test — Generate or run tests'));
208
+ console.log(chalk.dim(' /doc — Add documentation'));
159
209
  }
160
210
  }
161
211
 
@@ -1,9 +1,10 @@
1
+ const { execSync } = require('child_process');
1
2
  const fs = require('fs-extra');
2
3
  const chalk = require('chalk');
3
4
 
4
5
  class GitHooksManager {
5
6
  constructor() {
6
- this.hooksDir = '.git/hooks';
7
+ this.hooksPath = '.contextkit/hooks';
7
8
  }
8
9
 
9
10
  async installHooks(packageManager, hookChoices = { prePush: true, commitMsg: true }) {
@@ -19,8 +20,24 @@ class GitHooksManager {
19
20
  // Clean up legacy Husky directory if present
20
21
  await this.cleanupLegacyHusky();
21
22
 
22
- // Add hooks
23
- await this.addHooks(hookChoices);
23
+ // Clean up legacy .git/hooks/ files from previous ContextKit versions
24
+ await this.cleanupLegacyGitHooks();
25
+
26
+ // Remove hooks the user didn't select
27
+ await this.removeUnselectedHooks(hookChoices);
28
+
29
+ // Set core.hooksPath so git uses .contextkit/hooks/ directly
30
+ execSync(`git config core.hooksPath ${this.hooksPath}`, { stdio: 'pipe' });
31
+ console.log(chalk.green(`✅ Git hooks path set to ${this.hooksPath}`));
32
+
33
+ // Add prepare script to package.json for automatic setup on npm install
34
+ await this.addPrepareScript();
35
+
36
+ // Show non-Node setup hint if no package.json
37
+ if (!fs.existsSync('package.json')) {
38
+ console.log(chalk.dim(' 💡 For other developers, add to your setup:'));
39
+ console.log(chalk.dim(` git config core.hooksPath ${this.hooksPath}`));
40
+ }
24
41
 
25
42
  console.log(chalk.green('✅ Git hooks setup complete'));
26
43
 
@@ -30,45 +47,49 @@ class GitHooksManager {
30
47
  }
31
48
  }
32
49
 
33
- async addHooks(hookChoices = { prePush: true, commitMsg: true }) {
34
- // Backup existing hooks
35
- await this.backupExistingHooks();
36
-
37
- // Remove legacy pre-commit hook if it exists (replaced by pre-push)
38
- const legacyPreCommitHook = `${this.hooksDir}/pre-commit`;
39
- if (fs.existsSync(legacyPreCommitHook)) {
40
- const content = await fs.readFile(legacyPreCommitHook, 'utf8');
41
- if (content.includes('.contextkit/') || content.includes('.vibe-kit/')) {
42
- await fs.remove(legacyPreCommitHook);
43
- console.log(chalk.yellow('🧹 Removed legacy pre-commit hook (replaced by pre-push)'));
50
+ async removeUnselectedHooks(hookChoices) {
51
+ // If user didn't select a hook, remove it from .contextkit/hooks/
52
+ // so core.hooksPath doesn't run hooks they didn't want
53
+ if (!hookChoices.prePush) {
54
+ const hookPath = `${this.hooksPath}/pre-push`;
55
+ if (fs.existsSync(hookPath)) {
56
+ await fs.remove(hookPath);
44
57
  }
45
58
  }
46
-
47
- // Add selected hooks
48
- if (hookChoices.prePush) {
49
- await this.addNativeHook('pre-push', '.contextkit/hooks/pre-push.sh');
50
- }
51
- if (hookChoices.commitMsg) {
52
- await this.addNativeHook('commit-msg', '.contextkit/hooks/commit-msg.sh');
59
+ if (!hookChoices.commitMsg) {
60
+ const hookPath = `${this.hooksPath}/commit-msg`;
61
+ if (fs.existsSync(hookPath)) {
62
+ await fs.remove(hookPath);
63
+ }
53
64
  }
54
65
  }
55
66
 
56
- async addNativeHook(hookName, scriptPath) {
57
- const hookPath = `${this.hooksDir}/${hookName}`;
67
+ async addPrepareScript() {
68
+ if (!fs.existsSync('package.json')) return;
69
+
70
+ try {
71
+ const pkg = await fs.readJson('package.json');
72
+ const prepareCmd = `git config core.hooksPath ${this.hooksPath}`;
58
73
 
59
- // Ensure .git/hooks directory exists
60
- await fs.ensureDir(this.hooksDir);
74
+ if (!pkg.scripts) pkg.scripts = {};
61
75
 
62
- // Write hook directly no Husky, just a shebang + delegation
63
- const hookContent = `#!/usr/bin/env sh
64
- # ContextKit managed hook — do not edit
65
- ${scriptPath} "$@"
66
- `;
76
+ // Don't overwrite if prepare already has our command
77
+ if (pkg.scripts.prepare && pkg.scripts.prepare.includes('core.hooksPath')) {
78
+ return;
79
+ }
67
80
 
68
- await fs.writeFile(hookPath, hookContent);
69
- await fs.chmod(hookPath, '755');
81
+ // Append to existing prepare script or create new one
82
+ if (pkg.scripts.prepare) {
83
+ pkg.scripts.prepare = `${pkg.scripts.prepare} && ${prepareCmd}`;
84
+ } else {
85
+ pkg.scripts.prepare = prepareCmd;
86
+ }
70
87
 
71
- console.log(chalk.green(`✅ Created hook: ${hookName}`));
88
+ await fs.writeJson('package.json', pkg, { spaces: 2 });
89
+ console.log(chalk.green('✅ Added prepare script to package.json'));
90
+ } catch (error) {
91
+ console.log(chalk.yellow('⚠️ Could not update package.json prepare script'));
92
+ }
72
93
  }
73
94
 
74
95
  async cleanupLegacyHusky() {
@@ -91,24 +112,21 @@ ${scriptPath} "$@"
91
112
 
92
113
  if (hasContextKitHooks) {
93
114
  await fs.remove('.husky');
94
- console.log(chalk.yellow('🧹 Removed legacy .husky/ directory (now using native .git/hooks/)'));
115
+ console.log(chalk.yellow('🧹 Removed legacy .husky/ directory'));
95
116
  console.log(chalk.dim(' 💡 You can also run: npm uninstall husky'));
96
117
  }
97
118
  }
98
119
 
99
- async backupExistingHooks() {
120
+ async cleanupLegacyGitHooks() {
121
+ // Remove wrapper hooks from .git/hooks/ left by previous ContextKit versions
100
122
  const hooks = ['pre-push', 'commit-msg'];
101
-
102
123
  for (const hook of hooks) {
103
- const hookPath = `${this.hooksDir}/${hook}`;
124
+ const hookPath = `.git/hooks/${hook}`;
104
125
  if (fs.existsSync(hookPath)) {
105
- // Don't back up our own hooks
106
126
  const content = await fs.readFile(hookPath, 'utf8');
107
- if (content.includes('ContextKit managed hook')) continue;
108
-
109
- const backupPath = `${hookPath}.backup`;
110
- await fs.copy(hookPath, backupPath);
111
- console.log(chalk.yellow(`📦 Backed up existing hook: ${hook}`));
127
+ if (content.includes('ContextKit managed hook')) {
128
+ await fs.remove(hookPath);
129
+ }
112
130
  }
113
131
  }
114
132
  }
@@ -116,19 +134,41 @@ ${scriptPath} "$@"
116
134
  async uninstallHooks() {
117
135
  console.log(chalk.yellow('🪝 Removing Git hooks...'));
118
136
 
119
- const hooks = ['pre-push', 'commit-msg'];
137
+ // Unset core.hooksPath
138
+ try {
139
+ execSync('git config --unset core.hooksPath', { stdio: 'pipe' });
140
+ console.log(chalk.green('✅ Removed core.hooksPath config'));
141
+ } catch (error) {
142
+ // Already unset, that's fine
143
+ }
120
144
 
121
- for (const hook of hooks) {
122
- const hookPath = `${this.hooksDir}/${hook}`;
123
- const backupPath = `${hookPath}.backup`;
145
+ // Remove prepare script from package.json
146
+ await this.removePrepareScript();
124
147
 
125
- if (fs.existsSync(backupPath)) {
126
- await fs.move(backupPath, hookPath);
127
- console.log(chalk.green(`✅ Restored original hook: ${hook}`));
128
- } else if (fs.existsSync(hookPath)) {
129
- await fs.remove(hookPath);
130
- console.log(chalk.green(`✅ Removed hook: ${hook}`));
148
+ console.log(chalk.green('✅ Git hooks removed'));
149
+ }
150
+
151
+ async removePrepareScript() {
152
+ if (!fs.existsSync('package.json')) return;
153
+
154
+ try {
155
+ const pkg = await fs.readJson('package.json');
156
+ if (!pkg.scripts?.prepare) return;
157
+
158
+ const prepareCmd = `git config core.hooksPath ${this.hooksPath}`;
159
+
160
+ if (pkg.scripts.prepare === prepareCmd) {
161
+ delete pkg.scripts.prepare;
162
+ } else if (pkg.scripts.prepare.includes(prepareCmd)) {
163
+ // Remove our command from a chained prepare script
164
+ pkg.scripts.prepare = pkg.scripts.prepare
165
+ .replace(` && ${prepareCmd}`, '')
166
+ .replace(`${prepareCmd} && `, '');
131
167
  }
168
+
169
+ await fs.writeJson('package.json', pkg, { spaces: 2 });
170
+ } catch (error) {
171
+ // Best effort
132
172
  }
133
173
  }
134
174
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolrm/contextkit",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "description": "ContextKit - Context Engineering for AI Development. Provide rich context to AI through structured MD files with standards, code guides, and documentation. Works with Cursor, Claude, Aider, VS Code Copilot, and more.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {