delimit-cli 1.0.0 ā 2.1.1
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/.github/workflows/api-governance.yml +43 -0
- package/README.md +70 -113
- package/adapters/codex-skill.js +87 -0
- package/adapters/cursor-extension.js +190 -0
- package/adapters/gemini-action.js +93 -0
- package/adapters/openai-function.js +112 -0
- package/adapters/xai-plugin.js +151 -0
- package/bin/delimit-cli.js +921 -0
- package/bin/delimit.js +237 -1
- package/delimit.yml +19 -0
- package/hooks/evidence-status.sh +12 -0
- package/hooks/git/commit-msg +4 -0
- package/hooks/git/pre-commit +4 -0
- package/hooks/git/pre-push +4 -0
- package/hooks/install-hooks.sh +583 -0
- package/hooks/message-auth-hook.js +9 -0
- package/hooks/message-governance-hook.js +9 -0
- package/hooks/models/claude-post.js +4 -0
- package/hooks/models/claude-pre.js +4 -0
- package/hooks/models/codex-post.js +4 -0
- package/hooks/models/codex-pre.js +4 -0
- package/hooks/models/cursor-post.js +4 -0
- package/hooks/models/cursor-pre.js +4 -0
- package/hooks/models/gemini-post.js +4 -0
- package/hooks/models/gemini-pre.js +4 -0
- package/hooks/models/openai-post.js +4 -0
- package/hooks/models/openai-pre.js +4 -0
- package/hooks/models/windsurf-post.js +4 -0
- package/hooks/models/windsurf-pre.js +4 -0
- package/hooks/models/xai-post.js +4 -0
- package/hooks/models/xai-pre.js +4 -0
- package/hooks/post-bash-hook.js +13 -0
- package/hooks/post-mcp-hook.js +13 -0
- package/hooks/post-response-hook.js +4 -0
- package/hooks/post-tool-hook.js +126 -0
- package/hooks/post-write-hook.js +13 -0
- package/hooks/pre-bash-hook.js +30 -0
- package/hooks/pre-mcp-hook.js +13 -0
- package/hooks/pre-read-hook.js +13 -0
- package/hooks/pre-search-hook.js +13 -0
- package/hooks/pre-submit-hook.js +4 -0
- package/hooks/pre-task-hook.js +13 -0
- package/hooks/pre-tool-hook.js +121 -0
- package/hooks/pre-web-hook.js +13 -0
- package/hooks/pre-write-hook.js +31 -0
- package/hooks/test-hooks.sh +12 -0
- package/hooks/update-delimit.sh +6 -0
- package/lib/agent.js +509 -0
- package/lib/api-engine.js +156 -0
- package/lib/auth-setup.js +891 -0
- package/lib/decision-engine.js +474 -0
- package/lib/hooks-installer.js +416 -0
- package/lib/platform-adapters.js +353 -0
- package/lib/proxy-handler.js +114 -0
- package/package.json +38 -30
- package/scripts/infect.js +128 -0
- package/test-decision-engine.js +181 -0
- package/test-hook.js +27 -0
- package/dist/commands/validate.d.ts +0 -2
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/validate.js +0 -106
- package/dist/commands/validate.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -71
- package/dist/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -39
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
- package/dist/utils/api.d.ts +0 -3
- package/dist/utils/api.d.ts.map +0 -1
- package/dist/utils/api.js +0 -64
- package/dist/utils/api.js.map +0 -1
- package/dist/utils/file.d.ts +0 -7
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/file.js +0 -69
- package/dist/utils/file.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -14
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -28
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/masker.d.ts +0 -14
- package/dist/utils/masker.d.ts.map +0 -1
- package/dist/utils/masker.js +0 -89
- package/dist/utils/masker.js.map +0 -1
- package/src/commands/validate.ts +0 -150
- package/src/index.ts +0 -80
- package/src/types/index.ts +0 -41
- package/src/utils/api.ts +0 -68
- package/src/utils/file.ts +0 -71
- package/src/utils/logger.ts +0 -27
- package/src/utils/masker.ts +0 -101
- package/test-sensitive.yaml +0 -109
- package/tsconfig.json +0 -23
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Delimit Auto-Hooks Installer
|
|
5
|
+
* Automatically installs Delimit governance hooks for all AI models and tools
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
|
|
13
|
+
class DelimitHooksInstaller {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.hooksDir = path.join(process.env.HOME, '.delimit', 'hooks');
|
|
16
|
+
this.aiToolsDir = path.join(process.env.HOME, '.delimit', 'ai-hooks');
|
|
17
|
+
this.mcpHooksDir = path.join(process.env.HOME, '.delimit', 'mcp-hooks');
|
|
18
|
+
|
|
19
|
+
// AI models and tools to hook
|
|
20
|
+
this.aiTools = {
|
|
21
|
+
'claude': {
|
|
22
|
+
name: 'Claude (Anthropic)',
|
|
23
|
+
configPaths: [
|
|
24
|
+
'~/.claude.json',
|
|
25
|
+
'~/.config/claude/config.json'
|
|
26
|
+
],
|
|
27
|
+
hookType: 'wrapper'
|
|
28
|
+
},
|
|
29
|
+
'codex': {
|
|
30
|
+
name: 'GitHub Copilot/Codex',
|
|
31
|
+
configPaths: [
|
|
32
|
+
'~/.config/github-copilot',
|
|
33
|
+
'~/.codex/config.json'
|
|
34
|
+
],
|
|
35
|
+
hookType: 'wrapper'
|
|
36
|
+
},
|
|
37
|
+
'gemini': {
|
|
38
|
+
name: 'Google Gemini',
|
|
39
|
+
configPaths: [
|
|
40
|
+
'~/.config/gemini',
|
|
41
|
+
'~/.gemini/config.json'
|
|
42
|
+
],
|
|
43
|
+
hookType: 'wrapper'
|
|
44
|
+
},
|
|
45
|
+
'openai': {
|
|
46
|
+
name: 'OpenAI GPT',
|
|
47
|
+
configPaths: [
|
|
48
|
+
'~/.config/openai',
|
|
49
|
+
'~/.openai/config.json'
|
|
50
|
+
],
|
|
51
|
+
hookType: 'wrapper'
|
|
52
|
+
},
|
|
53
|
+
'cursor': {
|
|
54
|
+
name: 'Cursor IDE',
|
|
55
|
+
configPaths: [
|
|
56
|
+
'~/.cursor/config.json',
|
|
57
|
+
'~/.config/cursor'
|
|
58
|
+
],
|
|
59
|
+
hookType: 'extension'
|
|
60
|
+
},
|
|
61
|
+
'windsurf': {
|
|
62
|
+
name: 'Windsurf',
|
|
63
|
+
configPaths: [
|
|
64
|
+
'~/.windsurf/config.json'
|
|
65
|
+
],
|
|
66
|
+
hookType: 'wrapper'
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Git hooks to install
|
|
71
|
+
this.gitHooks = [
|
|
72
|
+
'pre-commit',
|
|
73
|
+
'pre-push',
|
|
74
|
+
'commit-msg',
|
|
75
|
+
'pre-merge-commit',
|
|
76
|
+
'prepare-commit-msg',
|
|
77
|
+
'post-commit',
|
|
78
|
+
'post-merge',
|
|
79
|
+
'pre-rebase'
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
// MCP hooks for governance integration
|
|
83
|
+
this.mcpHooks = [
|
|
84
|
+
'pre-mcp-call',
|
|
85
|
+
'post-mcp-call',
|
|
86
|
+
'mcp-auth',
|
|
87
|
+
'mcp-audit'
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async install() {
|
|
92
|
+
console.log(chalk.blue.bold('\nšµ Delimit Multi-Model Hooks Installer\n'));
|
|
93
|
+
|
|
94
|
+
// Create directories
|
|
95
|
+
this.ensureDirectories();
|
|
96
|
+
|
|
97
|
+
// Install Git hooks
|
|
98
|
+
console.log(chalk.yellow('š¦ Installing Git hooks...'));
|
|
99
|
+
await this.installGitHooks();
|
|
100
|
+
|
|
101
|
+
// Install AI tool hooks
|
|
102
|
+
console.log(chalk.yellow('š¤ Installing AI model hooks...'));
|
|
103
|
+
await this.installAIToolHooks();
|
|
104
|
+
|
|
105
|
+
// Install MCP hooks
|
|
106
|
+
console.log(chalk.yellow('š Installing MCP integration hooks...'));
|
|
107
|
+
await this.installMCPHooks();
|
|
108
|
+
|
|
109
|
+
// Configure Claude Code integration
|
|
110
|
+
console.log(chalk.yellow('ā” Configuring Claude Code integration...'));
|
|
111
|
+
await this.configureClaudeCode();
|
|
112
|
+
|
|
113
|
+
// Setup environment
|
|
114
|
+
console.log(chalk.yellow('š Setting up environment...'));
|
|
115
|
+
await this.setupEnvironment();
|
|
116
|
+
|
|
117
|
+
console.log(chalk.green.bold('\nā
Delimit hooks installed successfully!\n'));
|
|
118
|
+
this.printSummary();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
ensureDirectories() {
|
|
122
|
+
const dirs = [this.hooksDir, this.aiToolsDir, this.mcpHooksDir];
|
|
123
|
+
dirs.forEach(dir => {
|
|
124
|
+
if (!fs.existsSync(dir)) {
|
|
125
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async installGitHooks() {
|
|
131
|
+
for (const hook of this.gitHooks) {
|
|
132
|
+
const hookPath = path.join(this.hooksDir, hook);
|
|
133
|
+
const hookContent = this.generateGitHook(hook);
|
|
134
|
+
|
|
135
|
+
fs.writeFileSync(hookPath, hookContent);
|
|
136
|
+
fs.chmodSync(hookPath, '755');
|
|
137
|
+
console.log(chalk.green(` ā ${hook}`));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Set global Git hooks path
|
|
141
|
+
try {
|
|
142
|
+
execSync(`git config --global core.hooksPath ${this.hooksDir}`);
|
|
143
|
+
console.log(chalk.green(' ā Git global hooks path configured'));
|
|
144
|
+
} catch (e) {
|
|
145
|
+
console.log(chalk.yellow(' ā Could not set global Git hooks (may need sudo)'));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async installAIToolHooks() {
|
|
150
|
+
for (const [tool, config] of Object.entries(this.aiTools)) {
|
|
151
|
+
const hookPath = path.join(this.aiToolsDir, tool);
|
|
152
|
+
const wrapperPath = path.join(this.aiToolsDir, `${tool}-wrapper`);
|
|
153
|
+
|
|
154
|
+
// Check if tool is installed
|
|
155
|
+
const isInstalled = this.checkToolInstalled(tool);
|
|
156
|
+
|
|
157
|
+
if (isInstalled) {
|
|
158
|
+
// Create wrapper script
|
|
159
|
+
const wrapperContent = this.generateAIToolWrapper(tool, config);
|
|
160
|
+
fs.writeFileSync(wrapperPath, wrapperContent);
|
|
161
|
+
fs.chmodSync(wrapperPath, '755');
|
|
162
|
+
|
|
163
|
+
// Create hook configuration
|
|
164
|
+
const hookContent = this.generateAIToolHook(tool, config);
|
|
165
|
+
fs.writeFileSync(hookPath, hookContent);
|
|
166
|
+
fs.chmodSync(hookPath, '755');
|
|
167
|
+
|
|
168
|
+
console.log(chalk.green(` ā ${config.name}`));
|
|
169
|
+
} else {
|
|
170
|
+
console.log(chalk.gray(` - ${config.name} (not installed)`));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async installMCPHooks() {
|
|
176
|
+
for (const hook of this.mcpHooks) {
|
|
177
|
+
const hookPath = path.join(this.mcpHooksDir, hook);
|
|
178
|
+
const hookContent = this.generateMCPHook(hook);
|
|
179
|
+
|
|
180
|
+
fs.writeFileSync(hookPath, hookContent);
|
|
181
|
+
fs.chmodSync(hookPath, '755');
|
|
182
|
+
console.log(chalk.green(` ā ${hook}`));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async configureClaudeCode() {
|
|
187
|
+
const claudeConfigPath = path.join(process.env.HOME, '.claude.json');
|
|
188
|
+
|
|
189
|
+
if (fs.existsSync(claudeConfigPath)) {
|
|
190
|
+
try {
|
|
191
|
+
const config = JSON.parse(fs.readFileSync(claudeConfigPath, 'utf8'));
|
|
192
|
+
|
|
193
|
+
// Add Delimit governance hooks
|
|
194
|
+
if (!config.hooks) {
|
|
195
|
+
config.hooks = {};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
config.hooks.preCommand = path.join(this.mcpHooksDir, 'pre-mcp-call');
|
|
199
|
+
config.hooks.postCommand = path.join(this.mcpHooksDir, 'post-mcp-call');
|
|
200
|
+
config.hooks.authentication = path.join(this.mcpHooksDir, 'mcp-auth');
|
|
201
|
+
config.hooks.audit = path.join(this.mcpHooksDir, 'mcp-audit');
|
|
202
|
+
|
|
203
|
+
// Add Delimit governance settings
|
|
204
|
+
config.delimitGovernance = {
|
|
205
|
+
enabled: true,
|
|
206
|
+
agent: 'http://127.0.0.1:7823',
|
|
207
|
+
mode: 'auto',
|
|
208
|
+
hooks: this.mcpHooks.map(h => path.join(this.mcpHooksDir, h))
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
fs.writeFileSync(claudeConfigPath, JSON.stringify(config, null, 2));
|
|
212
|
+
console.log(chalk.green(' ā Claude Code configuration updated'));
|
|
213
|
+
} catch (e) {
|
|
214
|
+
console.log(chalk.yellow(' ā Could not update Claude Code config'));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async setupEnvironment() {
|
|
220
|
+
const envFile = path.join(process.env.HOME, '.delimit', 'env');
|
|
221
|
+
const envContent = `
|
|
222
|
+
# Delimit Governance Environment
|
|
223
|
+
export DELIMIT_HOOKS_DIR="${this.hooksDir}"
|
|
224
|
+
export DELIMIT_AI_HOOKS_DIR="${this.aiToolsDir}"
|
|
225
|
+
export DELIMIT_MCP_HOOKS_DIR="${this.mcpHooksDir}"
|
|
226
|
+
export DELIMIT_AGENT_URL="http://127.0.0.1:7823"
|
|
227
|
+
export DELIMIT_GOVERNANCE_ENABLED=true
|
|
228
|
+
|
|
229
|
+
# AI Tool Governance
|
|
230
|
+
export CLAUDE_GOVERNANCE_HOOK="${path.join(this.aiToolsDir, 'claude')}"
|
|
231
|
+
export CODEX_GOVERNANCE_HOOK="${path.join(this.aiToolsDir, 'codex')}"
|
|
232
|
+
export GEMINI_GOVERNANCE_HOOK="${path.join(this.aiToolsDir, 'gemini')}"
|
|
233
|
+
`;
|
|
234
|
+
|
|
235
|
+
fs.writeFileSync(envFile, envContent);
|
|
236
|
+
console.log(chalk.green(' ā Environment configuration created'));
|
|
237
|
+
|
|
238
|
+
// Add to bashrc if not already present
|
|
239
|
+
const bashrcPath = path.join(process.env.HOME, '.bashrc');
|
|
240
|
+
const sourceLine = 'source ~/.delimit/env';
|
|
241
|
+
|
|
242
|
+
if (fs.existsSync(bashrcPath)) {
|
|
243
|
+
const bashrc = fs.readFileSync(bashrcPath, 'utf8');
|
|
244
|
+
if (!bashrc.includes(sourceLine)) {
|
|
245
|
+
fs.appendFileSync(bashrcPath, `\n# Delimit Governance Environment\n${sourceLine}\n`);
|
|
246
|
+
console.log(chalk.green(' ā Added to .bashrc'));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
generateGitHook(hookName) {
|
|
252
|
+
return `#!/bin/sh
|
|
253
|
+
# Delimit Dynamic Governance Hook - ${hookName}
|
|
254
|
+
# Auto-generated by Delimit Hooks Installer
|
|
255
|
+
|
|
256
|
+
# Ensure agent is running
|
|
257
|
+
if ! curl -s http://127.0.0.1:7823/status > /dev/null 2>&1; then
|
|
258
|
+
echo "Starting Delimit Agent..."
|
|
259
|
+
nohup node /home/delimit/npm-delimit/lib/agent.js > /dev/null 2>&1 &
|
|
260
|
+
sleep 2
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
# Execute governance check
|
|
264
|
+
node /home/delimit/npm-delimit/bin/delimit-cli.js hook ${hookName} "$@"
|
|
265
|
+
`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
generateAIToolWrapper(tool, config) {
|
|
269
|
+
return `#!/bin/sh
|
|
270
|
+
# Delimit Governance Wrapper for ${config.name}
|
|
271
|
+
# Auto-generated by Delimit Hooks Installer
|
|
272
|
+
|
|
273
|
+
# Log the invocation
|
|
274
|
+
echo "[\$(date '+%Y-%m-%d %H:%M:%S')] ${tool} invoked with args: $*" >> ~/.delimit/audit/${tool}.log
|
|
275
|
+
|
|
276
|
+
# Check governance before execution
|
|
277
|
+
node /home/delimit/npm-delimit/bin/delimit-cli.js proxy ${tool} "$@"
|
|
278
|
+
|
|
279
|
+
# If governance passes, execute the real tool
|
|
280
|
+
if [ $? -eq 0 ]; then
|
|
281
|
+
# Find and execute the original binary
|
|
282
|
+
ORIGINAL_PATH=\$(echo \$PATH | sed "s|$HOME/.delimit/shims:||g")
|
|
283
|
+
PATH="\$ORIGINAL_PATH" command ${tool} "$@"
|
|
284
|
+
else
|
|
285
|
+
echo "Governance check failed for ${tool}"
|
|
286
|
+
exit 1
|
|
287
|
+
fi
|
|
288
|
+
`;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
generateAIToolHook(tool, config) {
|
|
292
|
+
return `#!/usr/bin/env node
|
|
293
|
+
// Delimit Governance Hook for ${config.name}
|
|
294
|
+
// Auto-generated by Delimit Hooks Installer
|
|
295
|
+
|
|
296
|
+
const { execSync } = require('child_process');
|
|
297
|
+
const path = require('path');
|
|
298
|
+
|
|
299
|
+
// Governance check
|
|
300
|
+
async function checkGovernance() {
|
|
301
|
+
try {
|
|
302
|
+
const result = execSync('curl -s http://127.0.0.1:7823/status');
|
|
303
|
+
return JSON.parse(result.toString());
|
|
304
|
+
} catch (e) {
|
|
305
|
+
return { mode: 'advisory' };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Main execution
|
|
310
|
+
(async () => {
|
|
311
|
+
const governance = await checkGovernance();
|
|
312
|
+
console.log(\`[Delimit] ${config.name} governance mode: \${governance.mode}\`);
|
|
313
|
+
|
|
314
|
+
// Log invocation
|
|
315
|
+
const args = process.argv.slice(2).join(' ');
|
|
316
|
+
console.log(\`[Delimit] Command: ${tool} \${args}\`);
|
|
317
|
+
|
|
318
|
+
// Execute based on governance mode
|
|
319
|
+
if (governance.mode === 'enforce') {
|
|
320
|
+
console.log('[Delimit] Enforce mode - checking permissions...');
|
|
321
|
+
// Add enforce logic here
|
|
322
|
+
}
|
|
323
|
+
})();
|
|
324
|
+
`;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
generateMCPHook(hookName) {
|
|
328
|
+
return `#!/usr/bin/env node
|
|
329
|
+
// Delimit MCP Integration Hook - ${hookName}
|
|
330
|
+
// Auto-generated by Delimit Hooks Installer
|
|
331
|
+
|
|
332
|
+
const axios = require('axios');
|
|
333
|
+
const fs = require('fs');
|
|
334
|
+
const path = require('path');
|
|
335
|
+
|
|
336
|
+
async function ${hookName.replace(/-/g, '_')}(context) {
|
|
337
|
+
const agentUrl = process.env.DELIMIT_AGENT_URL || 'http://127.0.0.1:7823';
|
|
338
|
+
|
|
339
|
+
try {
|
|
340
|
+
// Send governance check
|
|
341
|
+
const response = await axios.post(\`\${agentUrl}/evaluate\`, {
|
|
342
|
+
hook: '${hookName}',
|
|
343
|
+
timestamp: new Date().toISOString(),
|
|
344
|
+
...context
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Log to audit trail
|
|
348
|
+
const auditLog = path.join(process.env.HOME, '.delimit', 'audit', 'mcp.jsonl');
|
|
349
|
+
const logEntry = JSON.stringify({
|
|
350
|
+
hook: '${hookName}',
|
|
351
|
+
timestamp: new Date().toISOString(),
|
|
352
|
+
decision: response.data,
|
|
353
|
+
context
|
|
354
|
+
}) + '\\n';
|
|
355
|
+
|
|
356
|
+
fs.appendFileSync(auditLog, logEntry);
|
|
357
|
+
|
|
358
|
+
return response.data;
|
|
359
|
+
} catch (error) {
|
|
360
|
+
console.error('[Delimit] MCP hook error:', error.message);
|
|
361
|
+
return { action: 'allow', mode: 'advisory' };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Export for use as module
|
|
366
|
+
module.exports = { ${hookName.replace(/-/g, '_')} };
|
|
367
|
+
|
|
368
|
+
// Execute if called directly
|
|
369
|
+
if (require.main === module) {
|
|
370
|
+
const context = {
|
|
371
|
+
args: process.argv.slice(2),
|
|
372
|
+
env: process.env,
|
|
373
|
+
pwd: process.cwd()
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
${hookName.replace(/-/g, '_')}(context).then(result => {
|
|
377
|
+
console.log(JSON.stringify(result));
|
|
378
|
+
process.exit(result.action === 'block' ? 1 : 0);
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
`;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
checkToolInstalled(tool) {
|
|
385
|
+
try {
|
|
386
|
+
execSync(`which ${tool}`, { stdio: 'ignore' });
|
|
387
|
+
return true;
|
|
388
|
+
} catch {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
printSummary() {
|
|
394
|
+
console.log(chalk.cyan('\nš Installation Summary:'));
|
|
395
|
+
console.log(chalk.white(` ⢠Git hooks installed: ${this.gitHooks.length}`));
|
|
396
|
+
console.log(chalk.white(` ⢠AI tool hooks configured: ${Object.keys(this.aiTools).length}`));
|
|
397
|
+
console.log(chalk.white(` ⢠MCP integration hooks: ${this.mcpHooks.length}`));
|
|
398
|
+
console.log(chalk.white(` ⢠Hooks directory: ${this.hooksDir}`));
|
|
399
|
+
console.log(chalk.white(` ⢠Agent URL: http://127.0.0.1:7823`));
|
|
400
|
+
|
|
401
|
+
console.log(chalk.cyan('\nšÆ Next Steps:'));
|
|
402
|
+
console.log(chalk.white(' 1. Restart your shell to load environment'));
|
|
403
|
+
console.log(chalk.white(' 2. Run "delimit status" to verify installation'));
|
|
404
|
+
console.log(chalk.white(' 3. Test with "git commit" or AI tool commands'));
|
|
405
|
+
console.log(chalk.white(' 4. Configure policies in delimit.yml'));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Export for use as module
|
|
410
|
+
module.exports = DelimitHooksInstaller;
|
|
411
|
+
|
|
412
|
+
// Run if executed directly
|
|
413
|
+
if (require.main === module) {
|
|
414
|
+
const installer = new DelimitHooksInstaller();
|
|
415
|
+
installer.install().catch(console.error);
|
|
416
|
+
}
|