delimit-cli 4.1.9 → 4.1.11
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/lib/cross-model-hooks.js +111 -29
- package/package.json +1 -1
package/lib/cross-model-hooks.js
CHANGED
|
@@ -321,28 +321,73 @@ function installClaudeHooks(tool, hookConfig) {
|
|
|
321
321
|
}
|
|
322
322
|
const changes = [];
|
|
323
323
|
|
|
324
|
-
// --- SessionStart hook
|
|
325
|
-
//
|
|
324
|
+
// --- SessionStart hook ---
|
|
325
|
+
// Write a standalone bash script so it works without npm in PATH
|
|
326
326
|
if (hookConfig.session_start) {
|
|
327
|
+
const hooksDir = path.join(home, '.claude', 'hooks');
|
|
328
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
329
|
+
const hookScript = path.join(hooksDir, 'delimit');
|
|
330
|
+
const delimitHome = path.join(home, '.delimit');
|
|
331
|
+
fs.writeFileSync(hookScript, `#!/bin/bash
|
|
332
|
+
# Delimit SessionStart — generated by delimit-cli setup
|
|
333
|
+
DELIMIT_HOME="\${DELIMIT_HOME:-${delimitHome}}"
|
|
334
|
+
echo "=== Delimit Status ==="
|
|
335
|
+
# Governance
|
|
336
|
+
if [ -f "./delimit.yml" ] || [ -f "./.delimit/policies.yml" ]; then
|
|
337
|
+
echo "Governance: active | policy=project"
|
|
338
|
+
elif [ -f "$DELIMIT_HOME/delimit.yml" ]; then
|
|
339
|
+
echo "Governance: active | policy=user"
|
|
340
|
+
else
|
|
341
|
+
echo "Governance: not initialized -- run npx delimit-cli init"
|
|
342
|
+
fi
|
|
343
|
+
# Server + tools
|
|
344
|
+
SERVER="$DELIMIT_HOME/server/ai/server.py"
|
|
345
|
+
if [ -f "$SERVER" ]; then
|
|
346
|
+
TOOLS=$(grep -c '@mcp.tool' "$SERVER" 2>/dev/null || echo "0")
|
|
347
|
+
echo "Server: ready ($TOOLS tools)"
|
|
348
|
+
else
|
|
349
|
+
echo "Server: not installed -- run npx delimit-cli setup"
|
|
350
|
+
fi
|
|
351
|
+
# Hooks + audit
|
|
352
|
+
[ -f "${home}/.claude/settings.json" ] && grep -q '"hooks"' "${home}/.claude/settings.json" 2>/dev/null && HOOKS="enabled" || HOOKS="disabled"
|
|
353
|
+
[ -d "$DELIMIT_HOME/audit" ] && AUDIT="on" || AUDIT="off"
|
|
354
|
+
echo "Hooks: $HOOKS | Audit: $AUDIT"
|
|
355
|
+
# MCP
|
|
356
|
+
[ -f "${home}/.mcp.json" ] && grep -q "delimit" "${home}/.mcp.json" 2>/dev/null && echo "MCP: delimit registered" || echo "MCP: not registered"
|
|
357
|
+
# Models
|
|
358
|
+
MODELS=""
|
|
359
|
+
[ -n "$XAI_API_KEY" ] && MODELS="\${MODELS}Grok + "
|
|
360
|
+
[ -n "$GOOGLE_APPLICATION_CREDENTIALS" ] && MODELS="\${MODELS}Gemini + "
|
|
361
|
+
[ -n "$OPENAI_API_KEY" ] && MODELS="\${MODELS}Codex + "
|
|
362
|
+
[ -f "$DELIMIT_HOME/models.json" ] && MODELS=$(python3 -c "import json; d=json.load(open('$DELIMIT_HOME/models.json')); print(' + '.join(v.get('name',k) for k,v in d.items() if v.get('enabled')))" 2>/dev/null) || true
|
|
363
|
+
[ -n "$MODELS" ] && echo "Deliberation: \${MODELS% + }"
|
|
364
|
+
# Last session
|
|
365
|
+
SESSIONS="$DELIMIT_HOME/sessions"
|
|
366
|
+
if [ -d "$SESSIONS" ]; then
|
|
367
|
+
LATEST=$(ls -t "$SESSIONS"/session_*.json 2>/dev/null | head -1)
|
|
368
|
+
[ -n "$LATEST" ] && python3 -c "import json; d=json.load(open('$LATEST')); s=d.get('summary','')[:150]; print(f'Last session: {s}')" 2>/dev/null
|
|
369
|
+
fi
|
|
370
|
+
echo "=== Delimit Ready ==="
|
|
371
|
+
`);
|
|
372
|
+
fs.chmodSync(hookScript, '755');
|
|
373
|
+
|
|
327
374
|
if (!config.hooks.SessionStart) {
|
|
328
375
|
config.hooks.SessionStart = [];
|
|
329
376
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
changes.push('SessionStart');
|
|
345
|
-
}
|
|
377
|
+
// Remove any old delimit hooks (both script and npm command variants)
|
|
378
|
+
config.hooks.SessionStart = config.hooks.SessionStart.filter(group => {
|
|
379
|
+
const cmds = (group.hooks || []).map(h => h.command || '');
|
|
380
|
+
return !cmds.some(c => c.includes('delimit'));
|
|
381
|
+
});
|
|
382
|
+
config.hooks.SessionStart.push({
|
|
383
|
+
matcher: '',
|
|
384
|
+
hooks: [{
|
|
385
|
+
type: 'command',
|
|
386
|
+
command: hookScript,
|
|
387
|
+
timeout: 10,
|
|
388
|
+
}],
|
|
389
|
+
});
|
|
390
|
+
changes.push('SessionStart');
|
|
346
391
|
}
|
|
347
392
|
|
|
348
393
|
// --- PreToolUse: pre-tool hook scoped to Edit/Write on spec files ---
|
|
@@ -802,9 +847,23 @@ async function hookSessionStart() {
|
|
|
802
847
|
const lines = [];
|
|
803
848
|
lines.push('=== Delimit Status ===');
|
|
804
849
|
|
|
805
|
-
// Server status + tool count
|
|
806
850
|
const home = getHome();
|
|
807
|
-
const
|
|
851
|
+
const delimitHome = path.join(home, '.delimit');
|
|
852
|
+
const cwd = process.cwd();
|
|
853
|
+
|
|
854
|
+
// Governance status + policy source
|
|
855
|
+
const projectPolicy = fs.existsSync(path.join(cwd, 'delimit.yml')) || fs.existsSync(path.join(cwd, '.delimit', 'policies.yml'));
|
|
856
|
+
const userPolicy = fs.existsSync(path.join(delimitHome, 'delimit.yml'));
|
|
857
|
+
if (projectPolicy) {
|
|
858
|
+
lines.push('Governance: active | policy=project');
|
|
859
|
+
} else if (userPolicy) {
|
|
860
|
+
lines.push('Governance: active | policy=user');
|
|
861
|
+
} else {
|
|
862
|
+
lines.push('Governance: not initialized -- run npx delimit-cli init');
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// Server status + tool count
|
|
866
|
+
const serverFile = path.join(delimitHome, 'server', 'ai', 'server.py');
|
|
808
867
|
if (fs.existsSync(serverFile)) {
|
|
809
868
|
try {
|
|
810
869
|
const content = fs.readFileSync(serverFile, 'utf-8');
|
|
@@ -817,20 +876,43 @@ async function hookSessionStart() {
|
|
|
817
876
|
lines.push('Server: not installed -- run npx delimit-cli setup');
|
|
818
877
|
}
|
|
819
878
|
|
|
820
|
-
//
|
|
821
|
-
const
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
879
|
+
// Hooks + audit
|
|
880
|
+
const settingsFile = path.join(home, '.claude', 'settings.json');
|
|
881
|
+
const hooksEnabled = fs.existsSync(settingsFile) && fs.readFileSync(settingsFile, 'utf-8').includes('"hooks"');
|
|
882
|
+
const auditOn = fs.existsSync(path.join(delimitHome, 'audit'));
|
|
883
|
+
lines.push(`Hooks: ${hooksEnabled ? 'enabled' : 'disabled'} | Audit: ${auditOn ? 'on' : 'off'}`);
|
|
825
884
|
|
|
826
|
-
|
|
827
|
-
|
|
885
|
+
// MCP registration
|
|
886
|
+
const mcpFile = path.join(home, '.mcp.json');
|
|
887
|
+
const mcpRegistered = fs.existsSync(mcpFile) && fs.readFileSync(mcpFile, 'utf-8').includes('delimit');
|
|
888
|
+
lines.push(`MCP: ${mcpRegistered ? 'delimit registered' : 'not registered -- run npx delimit-cli setup'}`);
|
|
889
|
+
|
|
890
|
+
// Deliberation models
|
|
891
|
+
const modelsFile = path.join(delimitHome, 'models.json');
|
|
892
|
+
const modelNames = [];
|
|
893
|
+
try {
|
|
894
|
+
if (fs.existsSync(modelsFile)) {
|
|
895
|
+
const models = JSON.parse(fs.readFileSync(modelsFile, 'utf-8'));
|
|
896
|
+
for (const [key, val] of Object.entries(models)) {
|
|
897
|
+
if (val && val.enabled) modelNames.push(val.name || key);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
} catch {}
|
|
901
|
+
// Also check env vars for available models
|
|
902
|
+
if (modelNames.length === 0) {
|
|
903
|
+
const envModels = [];
|
|
904
|
+
if (process.env.XAI_API_KEY) envModels.push('Grok');
|
|
905
|
+
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) envModels.push('Gemini');
|
|
906
|
+
if (process.env.OPENAI_API_KEY) envModels.push('Codex');
|
|
907
|
+
if (envModels.length > 0) {
|
|
908
|
+
lines.push(`Deliberation: ${envModels.join(' + ')}`);
|
|
909
|
+
}
|
|
828
910
|
} else {
|
|
829
|
-
lines.push(
|
|
911
|
+
lines.push(`Deliberation: ${modelNames.join(' + ')}`);
|
|
830
912
|
}
|
|
831
913
|
|
|
832
914
|
// Last session context (prevents cross-session drift)
|
|
833
|
-
const sessionsDir = path.join(
|
|
915
|
+
const sessionsDir = path.join(delimitHome, 'sessions');
|
|
834
916
|
try {
|
|
835
917
|
if (fs.existsSync(sessionsDir)) {
|
|
836
918
|
const sessions = fs.readdirSync(sessionsDir).filter(f => f.startsWith('session_')).sort().reverse();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "delimit-cli",
|
|
3
3
|
"mcpName": "io.github.delimit-ai/delimit-mcp-server",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.11",
|
|
5
5
|
"description": "Unify Claude Code, Codex, Cursor, and Gemini CLI with persistent context, governance, and multi-model debate.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|