@nolrm/contextkit 0.8.2 → 0.9.3

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
@@ -138,6 +138,51 @@ ck ai "create checkout flow for customer"
138
138
 
139
139
  ---
140
140
 
141
+ ## Git Hooks & Quality Gates
142
+
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.
144
+
145
+ | Hook | What it does |
146
+ |------|-------------|
147
+ | **pre-push** | **Quality Gates** — auto-detects your project framework and runs the appropriate checks |
148
+ | **commit-msg** | Enforces [Conventional Commits](https://www.conventionalcommits.org/) format |
149
+
150
+ ### Framework-Aware Quality Gates
151
+
152
+ The pre-push hook detects your project type and runs the right quality checks automatically. All gates skip gracefully when tools aren't installed.
153
+
154
+ | Framework | Checks |
155
+ |-----------|--------|
156
+ | **Node.js** | TypeScript, ESLint, Prettier, build, test (auto-detects npm/yarn/pnpm/bun) |
157
+ | **Python** | ruff/flake8, mypy, black/ruff format, pytest |
158
+ | **Rust** | cargo check, clippy, cargo test |
159
+ | **Go** | go vet, golangci-lint, go test |
160
+ | **PHP** | PHPStan, PHPUnit |
161
+ | **Ruby** | RuboCop, RSpec/rake test |
162
+ | **Java** | Maven verify / Gradle check |
163
+
164
+ ### Commit Message Format
165
+
166
+ When the `commit-msg` hook is enabled, all commits must follow this format:
167
+
168
+ ```
169
+ <type>(<scope>): <description>
170
+ ```
171
+
172
+ **Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
173
+
174
+ **Examples:**
175
+ ```bash
176
+ git commit -m "feat(auth): add login page"
177
+ git commit -m "fix: resolve null pointer in checkout"
178
+ git commit -m "docs: update API reference"
179
+ git commit -m "test(cart): add edge case coverage"
180
+ ```
181
+
182
+ Hooks are optional and can be skipped with `ck install --no-hooks`.
183
+
184
+ ---
185
+
141
186
  ## Key Features
142
187
 
143
188
  - 🧠 **Context Engineering** - Structured MD files your AI reads automatically
@@ -101,24 +101,26 @@ class InstallCommand {
101
101
  await this.downloadFiles(projectType, options, detectedTools);
102
102
 
103
103
  // Ask about Git hooks
104
- let installHooks = true;
104
+ let hookChoices = { prePush: true, commitMsg: true };
105
105
  if (!options.nonInteractive && !options.noHooks) {
106
- installHooks = await this.promptGitHooks();
106
+ hookChoices = await this.promptGitHooks();
107
+ } else if (options.noHooks) {
108
+ hookChoices = { prePush: false, commitMsg: false };
107
109
  }
108
110
 
109
111
  // Install Git hooks if requested
110
- if (installHooks) {
111
- await this.gitHooksManager.installHooks(packageManager);
112
+ if (hookChoices.prePush || hookChoices.commitMsg) {
113
+ await this.gitHooksManager.installHooks(packageManager, hookChoices);
112
114
  }
113
115
 
114
116
  // Create configuration
115
- await this.createConfiguration(projectType, installHooks);
117
+ await this.createConfiguration(projectType, hookChoices);
116
118
 
117
119
  // Create status tracking
118
- await this.createStatusFile(projectType, packageManager, installHooks);
120
+ await this.createStatusFile(projectType, packageManager, hookChoices);
119
121
 
120
122
  // Success message
121
- this.showSuccessMessage(installHooks, detectedTools, projectType, packageManager);
123
+ this.showSuccessMessage(hookChoices, detectedTools, projectType, packageManager);
122
124
  }
123
125
 
124
126
  async installPlatformIntegration(platform) {
@@ -173,41 +175,71 @@ class InstallCommand {
173
175
  // Check for non-interactive mode
174
176
  if (process.env.CI === 'true' || process.env.NON_INTERACTIVE === 'true') {
175
177
  console.log(chalk.yellow('🤖 Non-interactive mode detected, skipping Git hooks'));
176
- return false;
178
+ return { prePush: false, commitMsg: false };
177
179
  }
178
180
 
179
- if (!await fs.pathExists('package.json')) {
180
- console.log(chalk.yellow('⚠️ Skipping Git hooks setup (no package.json found)'));
181
- return false;
181
+ if (!await fs.pathExists('.git')) {
182
+ console.log(chalk.yellow('⚠️ Skipping Git hooks setup (not a git repository)'));
183
+ return { prePush: false, commitMsg: false };
182
184
  }
183
185
 
184
186
  console.log('');
185
187
  console.log('──────────────────────────────────────────────');
186
- console.log(chalk.blue('⚙️ Git Hooks Setup'));
188
+ console.log(chalk.blue('⚙️ Quality Gates — Git Hooks'));
187
189
  console.log('──────────────────────────────────────────────');
188
- console.log('ContextKit can install **pre-push** and **commit-msg** hooks');
189
- console.log('to automatically run tests, linting, and type checks before pushing.');
190
190
  console.log('');
191
+
192
+ // Ask about pre-push hook
193
+ console.log(chalk.bold('Pre-push Quality Gates'));
194
+ console.log(chalk.dim('Auto-detects your framework (Node, Python, Rust, Go, etc.)'));
195
+ console.log(chalk.dim('and runs the right checks before pushing.'));
196
+ console.log('');
197
+ const { prePush } = await inquirer.prompt([
198
+ {
199
+ type: 'confirm',
200
+ name: 'prePush',
201
+ message: 'Enable pre-push hook? (runs quality checks before push)',
202
+ default: false
203
+ }
204
+ ]);
205
+
206
+ if (prePush) {
207
+ console.log(chalk.green(' ✅ Pre-push hook enabled'));
208
+ } else {
209
+ console.log(chalk.yellow(' ⏭️ Skipping pre-push hook'));
210
+ }
191
211
  console.log('');
192
212
 
193
- const { installHooks } = await inquirer.prompt([
213
+ // Ask about commit-msg hook
214
+ console.log(chalk.bold('Commit message hook'));
215
+ console.log(chalk.dim('Enforces conventional commit format:'));
216
+ console.log(chalk.dim(' <type>(<scope>): <description>'));
217
+ console.log(chalk.dim(' types: feat, fix, docs, style, refactor, test, chore'));
218
+ console.log(chalk.dim(' example: feat(auth): add login page'));
219
+ console.log('');
220
+ const { commitMsg } = await inquirer.prompt([
194
221
  {
195
222
  type: 'confirm',
196
- name: 'installHooks',
197
- message: 'Do you want to enable Git hooks?',
223
+ name: 'commitMsg',
224
+ message: 'Enable commit-msg hook? (enforces conventional commit format)',
198
225
  default: false
199
226
  }
200
227
  ]);
201
228
 
202
- if (installHooks) {
203
- console.log(chalk.green('✅ Git hooks enabled'));
229
+ if (commitMsg) {
230
+ console.log(chalk.green(' Commit message hook enabled'));
231
+ console.log(chalk.blue(' 💡 Commits must use: <type>(scope): description'));
204
232
  } else {
205
- console.log(chalk.yellow('⏭️ Skipping Git hooks for now'));
206
- console.log(chalk.blue('💡 You can enable them anytime with: `ck update --hooks`'));
233
+ console.log(chalk.yellow(' ⏭️ Skipping commit message hook'));
207
234
  }
208
235
  console.log('');
209
236
 
210
- return installHooks;
237
+ if (!prePush && !commitMsg) {
238
+ console.log(chalk.blue('💡 You can enable hooks anytime with: `ck update --hooks`'));
239
+ console.log('');
240
+ }
241
+
242
+ return { prePush, commitMsg };
211
243
  }
212
244
 
213
245
  async createDirectoryStructure() {
@@ -751,9 +783,9 @@ esac
751
783
  console.log(chalk.green('✅ CLI helpers installed'));
752
784
  }
753
785
 
754
- async createConfiguration(projectType, gitHooksEnabled) {
786
+ async createConfiguration(projectType, hookChoices) {
755
787
  const projectName = path.basename(process.cwd());
756
-
788
+
757
789
  const config = {
758
790
  version: '1.0.0',
759
791
  project_name: projectName,
@@ -764,7 +796,8 @@ esac
764
796
  code_review: true,
765
797
  linting: true,
766
798
  type_safety: true,
767
- git_hooks: gitHooksEnabled
799
+ pre_push_hook: hookChoices.prePush,
800
+ commit_msg_hook: hookChoices.commitMsg
768
801
  },
769
802
  paths: {
770
803
  components: 'src/components',
@@ -830,7 +863,8 @@ features:
830
863
  code_review: ${config.features.code_review}
831
864
  linting: ${config.features.linting}
832
865
  type_safety: ${config.features.type_safety}
833
- git_hooks: ${config.features.git_hooks}
866
+ pre_push_hook: ${config.features.pre_push_hook}
867
+ commit_msg_hook: ${config.features.commit_msg_hook}
834
868
 
835
869
  # Paths (customize for your project)
836
870
  paths:
@@ -857,12 +891,13 @@ metadata:
857
891
  );
858
892
  }
859
893
 
860
- async createStatusFile(projectType, packageManager, gitHooksEnabled) {
894
+ async createStatusFile(projectType, packageManager, hookChoices) {
861
895
  try {
862
896
  const status = this.statusManager.getDefaultStatus();
863
897
  status.project_type = projectType;
864
898
  status.package_manager = packageManager;
865
- status.features.git_hooks = gitHooksEnabled;
899
+ status.features.pre_push_hook = hookChoices.prePush;
900
+ status.features.commit_msg_hook = hookChoices.commitMsg;
866
901
 
867
902
  await this.statusManager.saveStatus(status);
868
903
  console.log(chalk.green('✅ Status tracking initialized'));
@@ -1378,7 +1413,7 @@ enforcement:
1378
1413
  console.log(chalk.green('✅ Policy file created'));
1379
1414
  }
1380
1415
 
1381
- showSuccessMessage(gitHooksEnabled, detectedTools = {}, projectType = '', packageManager = '') {
1416
+ showSuccessMessage(hookChoices, detectedTools = {}, projectType = '', packageManager = '') {
1382
1417
  console.log('');
1383
1418
  console.log(chalk.green('🎉 ContextKit v1.0.0 successfully installed!'));
1384
1419
  console.log('');
@@ -48,7 +48,8 @@ class StatusCommand {
48
48
  console.log('');
49
49
 
50
50
  console.log(chalk.blue('✅ Features:'));
51
- console.log(` Git Hooks: ${status.features.git_hooks ? '✅' : '❌'}`);
51
+ console.log(` Pre-push hook: ${status.features.pre_push_hook ? '✅' : '❌'}`);
52
+ console.log(` Commit-msg hook: ${status.features.commit_msg_hook ? '✅' : '❌'}`);
52
53
  console.log(` Standards: ${status.features.standards ? '✅' : '❌'}`);
53
54
  console.log(` Templates: ${status.features.templates ? '✅' : '❌'}`);
54
55
  console.log('');
@@ -121,8 +122,15 @@ class StatusCommand {
121
122
  config.features = config.features || {};
122
123
  config.features.type_safety = trimmed.split('type_safety:')[1].trim() === 'true';
123
124
  } else if (trimmed.startsWith('git_hooks:')) {
125
+ // Legacy single-flag compat
124
126
  config.features = config.features || {};
125
127
  config.features.git_hooks = trimmed.split('git_hooks:')[1].trim() === 'true';
128
+ } else if (trimmed.startsWith('pre_push_hook:')) {
129
+ config.features = config.features || {};
130
+ config.features.pre_push_hook = trimmed.split('pre_push_hook:')[1].trim() === 'true';
131
+ } else if (trimmed.startsWith('commit_msg_hook:')) {
132
+ config.features = config.features || {};
133
+ config.features.commit_msg_hook = trimmed.split('commit_msg_hook:')[1].trim() === 'true';
126
134
  }
127
135
  }
128
136
 
@@ -59,8 +59,12 @@ class UpdateCommand {
59
59
  await this.restoreUserConfig(config);
60
60
 
61
61
  // Update Git hooks if they were enabled
62
- if (config.features?.git_hooks) {
63
- await this.gitHooksManager.installHooks(packageManager);
62
+ const hookChoices = {
63
+ prePush: config.features?.pre_push_hook || config.features?.git_hooks || false,
64
+ commitMsg: config.features?.commit_msg_hook || config.features?.git_hooks || false
65
+ };
66
+ if (hookChoices.prePush || hookChoices.commitMsg) {
67
+ await this.gitHooksManager.installHooks(packageManager, hookChoices);
64
68
  }
65
69
 
66
70
  // Refresh installed platform integrations
@@ -176,8 +180,15 @@ class UpdateCommand {
176
180
  config.features = config.features || {};
177
181
  config.features.type_safety = trimmed.split('type_safety:')[1].trim() === 'true';
178
182
  } else if (trimmed.startsWith('git_hooks:')) {
183
+ // Legacy single-flag compat
179
184
  config.features = config.features || {};
180
185
  config.features.git_hooks = trimmed.split('git_hooks:')[1].trim() === 'true';
186
+ } else if (trimmed.startsWith('pre_push_hook:')) {
187
+ config.features = config.features || {};
188
+ config.features.pre_push_hook = trimmed.split('pre_push_hook:')[1].trim() === 'true';
189
+ } else if (trimmed.startsWith('commit_msg_hook:')) {
190
+ config.features = config.features || {};
191
+ config.features.commit_msg_hook = trimmed.split('commit_msg_hook:')[1].trim() === 'true';
181
192
  }
182
193
  }
183
194
 
@@ -294,7 +305,8 @@ features:
294
305
  code_review: ${config.features?.code_review || true}
295
306
  linting: ${config.features?.linting || true}
296
307
  type_safety: ${config.features?.type_safety || true}
297
- git_hooks: ${config.features?.git_hooks || false}
308
+ pre_push_hook: ${config.features?.pre_push_hook || config.features?.git_hooks || false}
309
+ commit_msg_hook: ${config.features?.commit_msg_hook || config.features?.git_hooks || false}
298
310
 
299
311
  # Paths (customize for your project)
300
312
  paths:
@@ -1,30 +1,26 @@
1
- const { execSync } = require('child_process');
2
1
  const fs = require('fs-extra');
3
2
  const chalk = require('chalk');
4
3
 
5
4
  class GitHooksManager {
6
5
  constructor() {
7
- this.hooksDir = '.husky';
6
+ this.hooksDir = '.git/hooks';
8
7
  }
9
8
 
10
- async installHooks(packageManager) {
9
+ async installHooks(packageManager, hookChoices = { prePush: true, commitMsg: true }) {
11
10
  console.log(chalk.yellow('🪝 Setting up Git hooks...'));
12
11
 
13
- // Check if Node.js is available
14
- if (!this.checkCommandExists('node')) {
15
- console.log(chalk.yellow('⚠️ Node.js not found, skipping Git hooks setup'));
12
+ // Check if this is a git repo
13
+ if (!fs.existsSync('.git')) {
14
+ console.log(chalk.yellow('⚠️ Not a git repository, skipping Git hooks setup'));
16
15
  return;
17
16
  }
18
17
 
19
18
  try {
20
- // Install Husky based on package manager
21
- await this.installHusky(packageManager);
22
-
23
- // Initialize Husky
24
- await this.initializeHusky(packageManager);
19
+ // Clean up legacy Husky directory if present
20
+ await this.cleanupLegacyHusky();
25
21
 
26
22
  // Add hooks
27
- await this.addHooks(packageManager);
23
+ await this.addHooks(hookChoices);
28
24
 
29
25
  console.log(chalk.green('✅ Git hooks setup complete'));
30
26
 
@@ -34,121 +30,7 @@ class GitHooksManager {
34
30
  }
35
31
  }
36
32
 
37
- async installHusky(packageManager) {
38
- const huskyInstalled = await this.checkHuskyInstalled(packageManager);
39
-
40
- if (!huskyInstalled) {
41
- console.log(chalk.blue(`📦 Installing Husky with ${packageManager}...`));
42
-
43
- try {
44
- switch (packageManager) {
45
- case 'yarn':
46
- execSync('yarn add --dev husky', { stdio: 'inherit' });
47
- break;
48
- case 'pnpm':
49
- execSync('pnpm add --save-dev husky', { stdio: 'inherit' });
50
- break;
51
- case 'npm':
52
- default:
53
- execSync('npm install --save-dev husky', { stdio: 'inherit' });
54
- break;
55
- }
56
- console.log(chalk.green(`✅ Husky installed with ${packageManager}`));
57
- } catch (error) {
58
- console.log(chalk.yellow(`⚠️ Failed to install Husky with ${packageManager}, trying fallback...`));
59
- // Fallback to npm if the detected package manager fails
60
- if (packageManager !== 'npm') {
61
- try {
62
- execSync('npm install --save-dev husky', { stdio: 'inherit' });
63
- console.log(chalk.green('✅ Husky installed with npm (fallback)'));
64
- } catch (fallbackError) {
65
- console.log(chalk.red('❌ Failed to install Husky with any package manager'));
66
- throw new Error(`Failed to install Husky: ${fallbackError.message}`);
67
- }
68
- } else {
69
- throw error;
70
- }
71
- }
72
- } else {
73
- console.log(chalk.green('✅ Husky already installed'));
74
- }
75
- }
76
-
77
- async checkHuskyInstalled(packageManager) {
78
- try {
79
- // Check if husky is in package.json dependencies
80
- const packageJson = await fs.readJson('package.json').catch(() => ({}));
81
- const allDeps = {
82
- ...packageJson.dependencies,
83
- ...packageJson.devDependencies,
84
- ...packageJson.peerDependencies
85
- };
86
-
87
- if (allDeps.husky) {
88
- return true;
89
- }
90
-
91
- // Fallback: try package manager specific commands
92
- switch (packageManager) {
93
- case 'yarn':
94
- execSync('yarn list --pattern husky', { stdio: 'pipe' });
95
- return true;
96
- case 'pnpm':
97
- execSync('pnpm list husky', { stdio: 'pipe' });
98
- return true;
99
- case 'npm':
100
- default:
101
- execSync('npm list husky', { stdio: 'pipe' });
102
- return true;
103
- }
104
- } catch (error) {
105
- return false;
106
- }
107
- }
108
-
109
- async initializeHusky(packageManager) {
110
- // Modern Husky doesn't need explicit initialization
111
- // Just ensure .husky directory exists
112
- await fs.ensureDir(this.hooksDir);
113
-
114
- // Create husky.sh if it doesn't exist (for compatibility)
115
- const huskyShPath = `${this.hooksDir}/_/husky.sh`;
116
- if (!await fs.pathExists(huskyShPath)) {
117
- await fs.ensureDir(`${this.hooksDir}/_`);
118
- const huskyShContent = `#!/usr/bin/env sh
119
- if [ -z "$husky_skip_init" ]; then
120
- debug () {
121
- if [ "$HUSKY_DEBUG" = "1" ]; then
122
- echo "husky (debug) - $1"
123
- fi
124
- }
125
-
126
- readonly hook_name="$(basename -- "$0")"
127
- debug "starting $hook_name..."
128
-
129
- if [ "$HUSKY" = "0" ]; then
130
- debug "HUSKY env variable is set to 0, skipping hook"
131
- exit 0
132
- fi
133
-
134
- if [ -f ~/.huskyrc ]; then
135
- debug "sourcing ~/.huskyrc"
136
- . ~/.huskyrc
137
- fi
138
-
139
- readonly husky_skip_init=1
140
- export husky_skip_init
141
- sh -e "$0" "$@"
142
- fi
143
- `;
144
- await fs.writeFile(huskyShPath, huskyShContent);
145
- await fs.chmod(huskyShPath, '755');
146
- }
147
-
148
- console.log(chalk.green('✅ Husky initialized'));
149
- }
150
-
151
- async addHooks(packageManager) {
33
+ async addHooks(hookChoices = { prePush: true, commitMsg: true }) {
152
34
  // Backup existing hooks
153
35
  await this.backupExistingHooks();
154
36
 
@@ -162,42 +44,68 @@ fi
162
44
  }
163
45
  }
164
46
 
165
- // Add new hooks
166
- const hooks = [
167
- { name: 'pre-push', script: '.contextkit/hooks/pre-push.sh' },
168
- { name: 'commit-msg', script: '.contextkit/hooks/commit-msg.sh' }
169
- ];
170
-
171
- for (const hook of hooks) {
172
- await this.addHook(packageManager, hook.name, hook.script);
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');
173
53
  }
174
54
  }
175
55
 
176
- async addHook(packageManager, hookName, scriptPath) {
56
+ async addNativeHook(hookName, scriptPath) {
177
57
  const hookPath = `${this.hooksDir}/${hookName}`;
178
-
179
- // Ensure .husky directory exists
58
+
59
+ // Ensure .git/hooks directory exists
180
60
  await fs.ensureDir(this.hooksDir);
181
-
182
- // Create hook file directly (modern Husky approach)
183
- const hookContent = `#!/usr/bin/env sh
184
- . "$(dirname -- "$0")/_/husky.sh"
185
61
 
62
+ // Write hook directly — no Husky, just a shebang + delegation
63
+ const hookContent = `#!/usr/bin/env sh
64
+ # ContextKit managed hook — do not edit
186
65
  ${scriptPath} "$@"
187
66
  `;
188
-
67
+
189
68
  await fs.writeFile(hookPath, hookContent);
190
69
  await fs.chmod(hookPath, '755');
191
-
70
+
192
71
  console.log(chalk.green(`✅ Created hook: ${hookName}`));
193
72
  }
194
73
 
74
+ async cleanupLegacyHusky() {
75
+ if (!fs.existsSync('.husky')) return;
76
+
77
+ // Check if the .husky dir contains ContextKit/Vibe Kit markers
78
+ const huskyHooks = ['pre-push', 'commit-msg', 'pre-commit'];
79
+ let hasContextKitHooks = false;
80
+
81
+ for (const hook of huskyHooks) {
82
+ const hookPath = `.husky/${hook}`;
83
+ if (fs.existsSync(hookPath)) {
84
+ const content = await fs.readFile(hookPath, 'utf8');
85
+ if (content.includes('.contextkit/') || content.includes('.vibe-kit/')) {
86
+ hasContextKitHooks = true;
87
+ break;
88
+ }
89
+ }
90
+ }
91
+
92
+ if (hasContextKitHooks) {
93
+ await fs.remove('.husky');
94
+ console.log(chalk.yellow('🧹 Removed legacy .husky/ directory (now using native .git/hooks/)'));
95
+ console.log(chalk.dim(' 💡 You can also run: npm uninstall husky'));
96
+ }
97
+ }
98
+
195
99
  async backupExistingHooks() {
196
100
  const hooks = ['pre-push', 'commit-msg'];
197
101
 
198
102
  for (const hook of hooks) {
199
103
  const hookPath = `${this.hooksDir}/${hook}`;
200
104
  if (fs.existsSync(hookPath)) {
105
+ // Don't back up our own hooks
106
+ const content = await fs.readFile(hookPath, 'utf8');
107
+ if (content.includes('ContextKit managed hook')) continue;
108
+
201
109
  const backupPath = `${hookPath}.backup`;
202
110
  await fs.copy(hookPath, backupPath);
203
111
  console.log(chalk.yellow(`📦 Backed up existing hook: ${hook}`));
@@ -205,24 +113,15 @@ ${scriptPath} "$@"
205
113
  }
206
114
  }
207
115
 
208
- checkCommandExists(command) {
209
- try {
210
- execSync(`which ${command}`, { stdio: 'pipe' });
211
- return true;
212
- } catch (error) {
213
- return false;
214
- }
215
- }
216
-
217
116
  async uninstallHooks() {
218
117
  console.log(chalk.yellow('🪝 Removing Git hooks...'));
219
-
118
+
220
119
  const hooks = ['pre-push', 'commit-msg'];
221
120
 
222
121
  for (const hook of hooks) {
223
122
  const hookPath = `${this.hooksDir}/${hook}`;
224
123
  const backupPath = `${hookPath}.backup`;
225
-
124
+
226
125
  if (fs.existsSync(backupPath)) {
227
126
  await fs.move(backupPath, hookPath);
228
127
  console.log(chalk.green(`✅ Restored original hook: ${hook}`));
@@ -31,7 +31,8 @@ class StatusManager {
31
31
  package_manager: null
32
32
  },
33
33
  features: {
34
- git_hooks: false,
34
+ pre_push_hook: false,
35
+ commit_msg_hook: false,
35
36
  standards: true,
36
37
  templates: true
37
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolrm/contextkit",
3
- "version": "0.8.2",
3
+ "version": "0.9.3",
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": {