@nolrm/contextkit 0.8.1 → 0.8.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 +31 -0
- package/lib/commands/install.js +60 -26
- package/lib/commands/status.js +9 -1
- package/lib/commands/update.js +15 -3
- package/lib/utils/git-hooks.js +10 -12
- package/lib/utils/status-manager.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -138,6 +138,37 @@ ck ai "create checkout flow for customer"
|
|
|
138
138
|
|
|
139
139
|
---
|
|
140
140
|
|
|
141
|
+
## Git Hooks
|
|
142
|
+
|
|
143
|
+
ContextKit can optionally install Git hooks during `ck install`:
|
|
144
|
+
|
|
145
|
+
| Hook | What it does |
|
|
146
|
+
|------|-------------|
|
|
147
|
+
| **pre-push** | Runs tests, linting, and type checks before pushing |
|
|
148
|
+
| **commit-msg** | Enforces [Conventional Commits](https://www.conventionalcommits.org/) format |
|
|
149
|
+
|
|
150
|
+
### Commit Message Format
|
|
151
|
+
|
|
152
|
+
When the `commit-msg` hook is enabled, all commits must follow this format:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
<type>(<scope>): <description>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
|
|
159
|
+
|
|
160
|
+
**Examples:**
|
|
161
|
+
```bash
|
|
162
|
+
git commit -m "feat(auth): add login page"
|
|
163
|
+
git commit -m "fix: resolve null pointer in checkout"
|
|
164
|
+
git commit -m "docs: update API reference"
|
|
165
|
+
git commit -m "test(cart): add edge case coverage"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Hooks are optional and can be skipped with `ck install --no-hooks`.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
141
172
|
## Key Features
|
|
142
173
|
|
|
143
174
|
- 🧠 **Context Engineering** - Structured MD files your AI reads automatically
|
package/lib/commands/install.js
CHANGED
|
@@ -101,24 +101,26 @@ class InstallCommand {
|
|
|
101
101
|
await this.downloadFiles(projectType, options, detectedTools);
|
|
102
102
|
|
|
103
103
|
// Ask about Git hooks
|
|
104
|
-
let
|
|
104
|
+
let hookChoices = { prePush: true, commitMsg: true };
|
|
105
105
|
if (!options.nonInteractive && !options.noHooks) {
|
|
106
|
-
|
|
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 (
|
|
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,
|
|
117
|
+
await this.createConfiguration(projectType, hookChoices);
|
|
116
118
|
|
|
117
119
|
// Create status tracking
|
|
118
|
-
await this.createStatusFile(projectType, packageManager,
|
|
120
|
+
await this.createStatusFile(projectType, packageManager, hookChoices);
|
|
119
121
|
|
|
120
122
|
// Success message
|
|
121
|
-
this.showSuccessMessage(
|
|
123
|
+
this.showSuccessMessage(hookChoices, detectedTools, projectType, packageManager);
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
async installPlatformIntegration(platform) {
|
|
@@ -173,41 +175,70 @@ 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
181
|
if (!await fs.pathExists('package.json')) {
|
|
180
182
|
console.log(chalk.yellow('⚠️ Skipping Git hooks setup (no package.json found)'));
|
|
181
|
-
return false;
|
|
183
|
+
return { prePush: false, commitMsg: false };
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
console.log('');
|
|
185
187
|
console.log('──────────────────────────────────────────────');
|
|
186
188
|
console.log(chalk.blue('⚙️ Git Hooks Setup'));
|
|
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 hook'));
|
|
194
|
+
console.log(chalk.dim('Runs tests, linting, and type checks before pushing.'));
|
|
195
|
+
console.log('');
|
|
196
|
+
const { prePush } = await inquirer.prompt([
|
|
197
|
+
{
|
|
198
|
+
type: 'confirm',
|
|
199
|
+
name: 'prePush',
|
|
200
|
+
message: 'Enable pre-push hook? (runs quality checks before push)',
|
|
201
|
+
default: false
|
|
202
|
+
}
|
|
203
|
+
]);
|
|
204
|
+
|
|
205
|
+
if (prePush) {
|
|
206
|
+
console.log(chalk.green(' ✅ Pre-push hook enabled'));
|
|
207
|
+
} else {
|
|
208
|
+
console.log(chalk.yellow(' ⏭️ Skipping pre-push hook'));
|
|
209
|
+
}
|
|
191
210
|
console.log('');
|
|
192
211
|
|
|
193
|
-
|
|
212
|
+
// Ask about commit-msg hook
|
|
213
|
+
console.log(chalk.bold('Commit message hook'));
|
|
214
|
+
console.log(chalk.dim('Enforces conventional commit format:'));
|
|
215
|
+
console.log(chalk.dim(' <type>(<scope>): <description>'));
|
|
216
|
+
console.log(chalk.dim(' types: feat, fix, docs, style, refactor, test, chore'));
|
|
217
|
+
console.log(chalk.dim(' example: feat(auth): add login page'));
|
|
218
|
+
console.log('');
|
|
219
|
+
const { commitMsg } = await inquirer.prompt([
|
|
194
220
|
{
|
|
195
221
|
type: 'confirm',
|
|
196
|
-
name: '
|
|
197
|
-
message: '
|
|
222
|
+
name: 'commitMsg',
|
|
223
|
+
message: 'Enable commit-msg hook? (enforces conventional commit format)',
|
|
198
224
|
default: false
|
|
199
225
|
}
|
|
200
226
|
]);
|
|
201
227
|
|
|
202
|
-
if (
|
|
203
|
-
console.log(chalk.green('✅
|
|
228
|
+
if (commitMsg) {
|
|
229
|
+
console.log(chalk.green(' ✅ Commit message hook enabled'));
|
|
230
|
+
console.log(chalk.blue(' 💡 Commits must use: <type>(scope): description'));
|
|
204
231
|
} else {
|
|
205
|
-
console.log(chalk.yellow('⏭️ Skipping
|
|
206
|
-
console.log(chalk.blue('💡 You can enable them anytime with: `ck update --hooks`'));
|
|
232
|
+
console.log(chalk.yellow(' ⏭️ Skipping commit message hook'));
|
|
207
233
|
}
|
|
208
234
|
console.log('');
|
|
209
235
|
|
|
210
|
-
|
|
236
|
+
if (!prePush && !commitMsg) {
|
|
237
|
+
console.log(chalk.blue('💡 You can enable hooks anytime with: `ck update --hooks`'));
|
|
238
|
+
console.log('');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return { prePush, commitMsg };
|
|
211
242
|
}
|
|
212
243
|
|
|
213
244
|
async createDirectoryStructure() {
|
|
@@ -751,9 +782,9 @@ esac
|
|
|
751
782
|
console.log(chalk.green('✅ CLI helpers installed'));
|
|
752
783
|
}
|
|
753
784
|
|
|
754
|
-
async createConfiguration(projectType,
|
|
785
|
+
async createConfiguration(projectType, hookChoices) {
|
|
755
786
|
const projectName = path.basename(process.cwd());
|
|
756
|
-
|
|
787
|
+
|
|
757
788
|
const config = {
|
|
758
789
|
version: '1.0.0',
|
|
759
790
|
project_name: projectName,
|
|
@@ -764,7 +795,8 @@ esac
|
|
|
764
795
|
code_review: true,
|
|
765
796
|
linting: true,
|
|
766
797
|
type_safety: true,
|
|
767
|
-
|
|
798
|
+
pre_push_hook: hookChoices.prePush,
|
|
799
|
+
commit_msg_hook: hookChoices.commitMsg
|
|
768
800
|
},
|
|
769
801
|
paths: {
|
|
770
802
|
components: 'src/components',
|
|
@@ -830,7 +862,8 @@ features:
|
|
|
830
862
|
code_review: ${config.features.code_review}
|
|
831
863
|
linting: ${config.features.linting}
|
|
832
864
|
type_safety: ${config.features.type_safety}
|
|
833
|
-
|
|
865
|
+
pre_push_hook: ${config.features.pre_push_hook}
|
|
866
|
+
commit_msg_hook: ${config.features.commit_msg_hook}
|
|
834
867
|
|
|
835
868
|
# Paths (customize for your project)
|
|
836
869
|
paths:
|
|
@@ -857,12 +890,13 @@ metadata:
|
|
|
857
890
|
);
|
|
858
891
|
}
|
|
859
892
|
|
|
860
|
-
async createStatusFile(projectType, packageManager,
|
|
893
|
+
async createStatusFile(projectType, packageManager, hookChoices) {
|
|
861
894
|
try {
|
|
862
895
|
const status = this.statusManager.getDefaultStatus();
|
|
863
896
|
status.project_type = projectType;
|
|
864
897
|
status.package_manager = packageManager;
|
|
865
|
-
status.features.
|
|
898
|
+
status.features.pre_push_hook = hookChoices.prePush;
|
|
899
|
+
status.features.commit_msg_hook = hookChoices.commitMsg;
|
|
866
900
|
|
|
867
901
|
await this.statusManager.saveStatus(status);
|
|
868
902
|
console.log(chalk.green('✅ Status tracking initialized'));
|
|
@@ -1378,7 +1412,7 @@ enforcement:
|
|
|
1378
1412
|
console.log(chalk.green('✅ Policy file created'));
|
|
1379
1413
|
}
|
|
1380
1414
|
|
|
1381
|
-
showSuccessMessage(
|
|
1415
|
+
showSuccessMessage(hookChoices, detectedTools = {}, projectType = '', packageManager = '') {
|
|
1382
1416
|
console.log('');
|
|
1383
1417
|
console.log(chalk.green('🎉 ContextKit v1.0.0 successfully installed!'));
|
|
1384
1418
|
console.log('');
|
package/lib/commands/status.js
CHANGED
|
@@ -48,7 +48,8 @@ class StatusCommand {
|
|
|
48
48
|
console.log('');
|
|
49
49
|
|
|
50
50
|
console.log(chalk.blue('✅ Features:'));
|
|
51
|
-
console.log(`
|
|
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
|
|
package/lib/commands/update.js
CHANGED
|
@@ -59,8 +59,12 @@ class UpdateCommand {
|
|
|
59
59
|
await this.restoreUserConfig(config);
|
|
60
60
|
|
|
61
61
|
// Update Git hooks if they were enabled
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
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:
|
package/lib/utils/git-hooks.js
CHANGED
|
@@ -7,7 +7,7 @@ class GitHooksManager {
|
|
|
7
7
|
this.hooksDir = '.husky';
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
async installHooks(packageManager) {
|
|
10
|
+
async installHooks(packageManager, hookChoices = { prePush: true, commitMsg: true }) {
|
|
11
11
|
console.log(chalk.yellow('🪝 Setting up Git hooks...'));
|
|
12
12
|
|
|
13
13
|
// Check if Node.js is available
|
|
@@ -24,7 +24,7 @@ class GitHooksManager {
|
|
|
24
24
|
await this.initializeHusky(packageManager);
|
|
25
25
|
|
|
26
26
|
// Add hooks
|
|
27
|
-
await this.addHooks(packageManager);
|
|
27
|
+
await this.addHooks(packageManager, hookChoices);
|
|
28
28
|
|
|
29
29
|
console.log(chalk.green('✅ Git hooks setup complete'));
|
|
30
30
|
|
|
@@ -148,7 +148,7 @@ fi
|
|
|
148
148
|
console.log(chalk.green('✅ Husky initialized'));
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
async addHooks(packageManager) {
|
|
151
|
+
async addHooks(packageManager, hookChoices = { prePush: true, commitMsg: true }) {
|
|
152
152
|
// Backup existing hooks
|
|
153
153
|
await this.backupExistingHooks();
|
|
154
154
|
|
|
@@ -162,14 +162,12 @@ fi
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
// Add
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
for (const hook of hooks) {
|
|
172
|
-
await this.addHook(packageManager, hook.name, hook.script);
|
|
165
|
+
// Add selected hooks
|
|
166
|
+
if (hookChoices.prePush) {
|
|
167
|
+
await this.addHook(packageManager, 'pre-push', '.contextkit/hooks/pre-push.sh');
|
|
168
|
+
}
|
|
169
|
+
if (hookChoices.commitMsg) {
|
|
170
|
+
await this.addHook(packageManager, 'commit-msg', '.contextkit/hooks/commit-msg.sh');
|
|
173
171
|
}
|
|
174
172
|
}
|
|
175
173
|
|
|
@@ -183,7 +181,7 @@ fi
|
|
|
183
181
|
const hookContent = `#!/usr/bin/env sh
|
|
184
182
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
185
183
|
|
|
186
|
-
${scriptPath}
|
|
184
|
+
${scriptPath} "$@"
|
|
187
185
|
`;
|
|
188
186
|
|
|
189
187
|
await fs.writeFile(hookPath, hookContent);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nolrm/contextkit",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.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": {
|