delimit-cli 3.14.5 → 3.14.7
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/bin/delimit-setup.js +77 -20
- package/package.json +1 -1
package/bin/delimit-setup.js
CHANGED
|
@@ -28,6 +28,8 @@ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
|
28
28
|
|
|
29
29
|
function log(msg) { console.log(msg); }
|
|
30
30
|
function step(n, msg) { log(`\n${blue(`[${n}]`)} ${msg}`); }
|
|
31
|
+
function pause(ms = 150) { return new Promise(r => setTimeout(r, ms)); }
|
|
32
|
+
async function logp(msg, ms = 180) { console.log(msg); await pause(ms); }
|
|
31
33
|
|
|
32
34
|
function findGitDir(startDir) {
|
|
33
35
|
let dir = startDir;
|
|
@@ -89,7 +91,7 @@ async function main() {
|
|
|
89
91
|
const match = ver.match(/(\d+)\.(\d+)/);
|
|
90
92
|
if (match && (parseInt(match[1]) >= 3 && parseInt(match[2]) >= 9)) {
|
|
91
93
|
python = cmd;
|
|
92
|
-
|
|
94
|
+
await logp(` ${green('✓')} ${ver}`);
|
|
93
95
|
break;
|
|
94
96
|
}
|
|
95
97
|
} catch {}
|
|
@@ -104,11 +106,39 @@ async function main() {
|
|
|
104
106
|
try {
|
|
105
107
|
execSync('claude --version 2>/dev/null', { encoding: 'utf-8' });
|
|
106
108
|
hasClaude = true;
|
|
107
|
-
|
|
109
|
+
await logp(` ${green('✓')} Claude Code detected`);
|
|
108
110
|
} catch {
|
|
109
111
|
log(` ${yellow('!')} Claude Code not detected — MCP config will still be created`);
|
|
110
112
|
}
|
|
111
113
|
|
|
114
|
+
// Show what we're about to do and ask for confirmation
|
|
115
|
+
log('');
|
|
116
|
+
log(` ${blue('What Delimit will do:')}`);
|
|
117
|
+
log(` • Install MCP server to ${dim('~/.delimit/')}`);
|
|
118
|
+
log(` • Configure ${hasClaude ? 'Claude Code' : 'your AI assistant'} to use Delimit`);
|
|
119
|
+
log(` • Install governance agents + hooks`);
|
|
120
|
+
log(` • Set up CLAUDE.md instruction file`);
|
|
121
|
+
log('');
|
|
122
|
+
log(` ${dim('Undo anytime:')} rm -rf ~/.delimit && delimit uninstall`);
|
|
123
|
+
log('');
|
|
124
|
+
|
|
125
|
+
const inquirerTop = (() => { try { return require('inquirer'); } catch { return null; } })();
|
|
126
|
+
if (inquirerTop && process.stdin.isTTY) {
|
|
127
|
+
try {
|
|
128
|
+
const { proceed } = await inquirerTop.prompt([{
|
|
129
|
+
type: 'confirm',
|
|
130
|
+
name: 'proceed',
|
|
131
|
+
message: 'Continue with setup? (Enter = Yes)',
|
|
132
|
+
default: true,
|
|
133
|
+
}]);
|
|
134
|
+
if (!proceed) {
|
|
135
|
+
log(`\n ${dim('Setup cancelled. Nothing was changed.')}\n`);
|
|
136
|
+
process.exit(0);
|
|
137
|
+
}
|
|
138
|
+
} catch {}
|
|
139
|
+
}
|
|
140
|
+
log('');
|
|
141
|
+
|
|
112
142
|
// Step 2: Install Delimit MCP server
|
|
113
143
|
step(2, 'Installing Delimit MCP server...');
|
|
114
144
|
|
|
@@ -123,13 +153,13 @@ async function main() {
|
|
|
123
153
|
const gatewaySource = path.join(__dirname, '..', 'gateway');
|
|
124
154
|
if (fs.existsSync(gatewaySource)) {
|
|
125
155
|
copyDir(gatewaySource, path.join(DELIMIT_HOME, 'server'));
|
|
126
|
-
|
|
156
|
+
await logp(` ${green('✓')} Core engine installed`);
|
|
127
157
|
} else {
|
|
128
158
|
// Fallback: try to clone from GitHub
|
|
129
159
|
log(` ${dim(' Downloading from GitHub...')}`);
|
|
130
160
|
try {
|
|
131
161
|
execSync(`git clone --depth 1 https://github.com/delimit-ai/delimit-gateway.git "${path.join(DELIMIT_HOME, 'server')}" 2>/dev/null`, { stdio: 'pipe' });
|
|
132
|
-
|
|
162
|
+
await logp(` ${green('✓')} Core engine cloned`);
|
|
133
163
|
} catch {
|
|
134
164
|
log(` ${yellow('!')} Could not download. Clone manually: git clone https://github.com/delimit-ai/delimit-gateway.git ~/.delimit/server`);
|
|
135
165
|
}
|
|
@@ -156,7 +186,7 @@ async function main() {
|
|
|
156
186
|
execSync(`curl -sL "${proUrl}" -o "${proTarball}" --fail`, { stdio: 'pipe', timeout: 30000 });
|
|
157
187
|
execSync(`tar -xzf "${proTarball}" -C "${proDir}"`, { stdio: 'pipe' });
|
|
158
188
|
fs.unlinkSync(proTarball);
|
|
159
|
-
|
|
189
|
+
await logp(` ${green('✓')} Pro modules installed (${artifact})`);
|
|
160
190
|
} catch {
|
|
161
191
|
log(` ${dim(' Pro modules not available for ${artifact} — free tools work fine')}`);
|
|
162
192
|
}
|
|
@@ -178,12 +208,12 @@ async function main() {
|
|
|
178
208
|
execSync(`"${venvPy}" -m pip install --quiet fastmcp==3.1.0 pyyaml==6.0.3 pydantic==2.12.5 packaging==26.0 2>/dev/null`, { stdio: 'pipe' });
|
|
179
209
|
}
|
|
180
210
|
python = venvPy; // Use venv python for MCP config
|
|
181
|
-
|
|
211
|
+
await logp(` ${green('✓')} Python dependencies installed (isolated venv)`);
|
|
182
212
|
} catch {
|
|
183
213
|
log(` ${yellow('!')} venv install failed — trying global pip`);
|
|
184
214
|
try {
|
|
185
215
|
execSync(`${python} -m pip install --quiet fastmcp==3.1.0 pyyaml==6.0.3 pydantic==2.12.5 packaging==26.0 2>/dev/null`, { stdio: 'pipe' });
|
|
186
|
-
|
|
216
|
+
await logp(` ${green('✓')} Python dependencies installed (global)`);
|
|
187
217
|
} catch {
|
|
188
218
|
log(` ${yellow('!')} pip install failed — run manually: pip install fastmcp pyyaml pydantic packaging`);
|
|
189
219
|
}
|
|
@@ -205,7 +235,7 @@ async function main() {
|
|
|
205
235
|
const actualServer = fs.existsSync(serverPath) ? serverPath : serverPathAlt;
|
|
206
236
|
|
|
207
237
|
if (mcpConfig.mcpServers.delimit) {
|
|
208
|
-
|
|
238
|
+
await logp(` ${green('✓')} Delimit MCP already configured`);
|
|
209
239
|
} else {
|
|
210
240
|
mcpConfig.mcpServers.delimit = {
|
|
211
241
|
type: 'stdio',
|
|
@@ -218,7 +248,7 @@ async function main() {
|
|
|
218
248
|
description: 'Delimit — AI agent guardrails'
|
|
219
249
|
};
|
|
220
250
|
fs.writeFileSync(MCP_CONFIG, JSON.stringify(mcpConfig, null, 2));
|
|
221
|
-
|
|
251
|
+
await logp(` ${green('✓')} Added delimit to ${MCP_CONFIG}`);
|
|
222
252
|
}
|
|
223
253
|
|
|
224
254
|
// Step 3b: Configure Codex MCP (if installed)
|
|
@@ -227,13 +257,13 @@ async function main() {
|
|
|
227
257
|
try {
|
|
228
258
|
let toml = fs.readFileSync(CODEX_CONFIG, 'utf-8');
|
|
229
259
|
if (toml.includes('[mcp_servers.delimit]')) {
|
|
230
|
-
|
|
260
|
+
await logp(` ${green('✓')} Delimit already in Codex config`);
|
|
231
261
|
} else {
|
|
232
262
|
const serverDir = path.join(DELIMIT_HOME, 'server');
|
|
233
263
|
const codexEntry = `\n[mcp_servers.delimit]\ncommand = "${python}"\nargs = ["${actualServer}"]\ncwd = "${serverDir}"\n\n[mcp_servers.delimit.env]\nPYTHONPATH = "${serverDir}:${path.join(serverDir, 'ai')}"\n`;
|
|
234
264
|
toml += codexEntry;
|
|
235
265
|
fs.writeFileSync(CODEX_CONFIG, toml);
|
|
236
|
-
|
|
266
|
+
await logp(` ${green('✓')} Added delimit to Codex (${CODEX_CONFIG})`);
|
|
237
267
|
}
|
|
238
268
|
} catch (e) {
|
|
239
269
|
log(` ${yellow('!')} Could not configure Codex: ${e.message}`);
|
|
@@ -250,7 +280,7 @@ async function main() {
|
|
|
250
280
|
}
|
|
251
281
|
if (!cursorConfig.mcpServers) cursorConfig.mcpServers = {};
|
|
252
282
|
if (cursorConfig.mcpServers.delimit) {
|
|
253
|
-
|
|
283
|
+
await logp(` ${green('✓')} Delimit already in Cursor config`);
|
|
254
284
|
} else {
|
|
255
285
|
cursorConfig.mcpServers.delimit = {
|
|
256
286
|
command: python,
|
|
@@ -259,7 +289,7 @@ async function main() {
|
|
|
259
289
|
env: { PYTHONPATH: path.join(DELIMIT_HOME, 'server') }
|
|
260
290
|
};
|
|
261
291
|
fs.writeFileSync(CURSOR_CONFIG, JSON.stringify(cursorConfig, null, 2));
|
|
262
|
-
|
|
292
|
+
await logp(` ${green('✓')} Added delimit to Cursor (${CURSOR_CONFIG})`);
|
|
263
293
|
}
|
|
264
294
|
} catch (e) {
|
|
265
295
|
log(` ${yellow('!')} Could not configure Cursor: ${e.message}`);
|
|
@@ -277,7 +307,7 @@ async function main() {
|
|
|
277
307
|
}
|
|
278
308
|
if (!geminiConfig.mcpServers) geminiConfig.mcpServers = {};
|
|
279
309
|
if (geminiConfig.mcpServers.delimit) {
|
|
280
|
-
|
|
310
|
+
await logp(` ${green('✓')} Delimit already in Gemini CLI config`);
|
|
281
311
|
} else {
|
|
282
312
|
geminiConfig.mcpServers.delimit = {
|
|
283
313
|
command: python,
|
|
@@ -286,7 +316,7 @@ async function main() {
|
|
|
286
316
|
env: { PYTHONPATH: path.join(DELIMIT_HOME, 'server') }
|
|
287
317
|
};
|
|
288
318
|
fs.writeFileSync(GEMINI_CONFIG, JSON.stringify(geminiConfig, null, 2));
|
|
289
|
-
|
|
319
|
+
await logp(` ${green('✓')} Added delimit to Gemini CLI (${GEMINI_CONFIG})`);
|
|
290
320
|
}
|
|
291
321
|
// Add governance instructions
|
|
292
322
|
if (!geminiConfig.customInstructions || !geminiConfig.customInstructions.includes('delimit_ledger_context')) {
|
|
@@ -298,6 +328,33 @@ async function main() {
|
|
|
298
328
|
}
|
|
299
329
|
}
|
|
300
330
|
|
|
331
|
+
// Checkpoint: MCP is configured, now ask before modifying project files
|
|
332
|
+
log('');
|
|
333
|
+
log(` ${green('✓')} MCP server installed and configured`);
|
|
334
|
+
log('');
|
|
335
|
+
log(` ${blue('Next: project-level setup')}`);
|
|
336
|
+
log(` • Install governance agents (lint, engineering, governance)`);
|
|
337
|
+
log(` • Update CLAUDE.md with Delimit instructions`);
|
|
338
|
+
log(` • Optional: governance wrapping + hooks`);
|
|
339
|
+
log('');
|
|
340
|
+
|
|
341
|
+
const inquirerMid = (() => { try { return require('inquirer'); } catch { return null; } })();
|
|
342
|
+
if (inquirerMid && process.stdin.isTTY) {
|
|
343
|
+
try {
|
|
344
|
+
const { proceed } = await inquirerMid.prompt([{
|
|
345
|
+
type: 'confirm',
|
|
346
|
+
name: 'proceed',
|
|
347
|
+
message: 'Continue with project setup? (Enter = Yes)',
|
|
348
|
+
default: true,
|
|
349
|
+
}]);
|
|
350
|
+
if (!proceed) {
|
|
351
|
+
log(`\n ${green('MCP is ready.')} Skipped project-level setup.`);
|
|
352
|
+
log(` ${dim('Run')} delimit setup ${dim('again to complete project setup.')}\n`);
|
|
353
|
+
process.exit(0);
|
|
354
|
+
}
|
|
355
|
+
} catch {}
|
|
356
|
+
}
|
|
357
|
+
|
|
301
358
|
// Step 4: Install default agents
|
|
302
359
|
step(4, 'Installing governance agents...');
|
|
303
360
|
|
|
@@ -375,7 +432,7 @@ Run full governance compliance checks. Verify security, policy compliance, evide
|
|
|
375
432
|
installed++;
|
|
376
433
|
}
|
|
377
434
|
}
|
|
378
|
-
|
|
435
|
+
await logp(` ${green('✓')} ${installed} agents installed (${Object.keys(agents).length - installed} already existed)`);
|
|
379
436
|
|
|
380
437
|
// Step 4b: Install Git hooks if inside a git repository
|
|
381
438
|
const gitDir = findGitDir(process.cwd());
|
|
@@ -403,7 +460,7 @@ Run full governance compliance checks. Verify security, policy compliance, evide
|
|
|
403
460
|
}
|
|
404
461
|
}
|
|
405
462
|
if (hooksInstalled > 0) {
|
|
406
|
-
|
|
463
|
+
await logp(` ${green('✓')} ${hooksInstalled} Git hooks installed to ${gitHooksDir}`);
|
|
407
464
|
} else {
|
|
408
465
|
log(` ${dim(' Git hooks already present (non-Delimit hooks preserved)')}`);
|
|
409
466
|
}
|
|
@@ -418,11 +475,11 @@ Run full governance compliance checks. Verify security, policy compliance, evide
|
|
|
418
475
|
const claudeMd = path.join(os.homedir(), 'CLAUDE.md');
|
|
419
476
|
const claudeResult = upsertDelimitSection(claudeMd);
|
|
420
477
|
if (claudeResult.action === 'created') {
|
|
421
|
-
|
|
478
|
+
await logp(` ${green('✓')} Created ${claudeMd} with governance triggers`);
|
|
422
479
|
} else if (claudeResult.action === 'updated') {
|
|
423
|
-
|
|
480
|
+
await logp(` ${green('✓')} Updated Delimit section in ${claudeMd} (version changed)`);
|
|
424
481
|
} else if (claudeResult.action === 'appended') {
|
|
425
|
-
|
|
482
|
+
await logp(` ${green('✓')} Appended Delimit section to ${claudeMd} (user content preserved)`);
|
|
426
483
|
} else {
|
|
427
484
|
log(` ${dim(' CLAUDE.md already up to date')}`);
|
|
428
485
|
}
|
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": "3.14.
|
|
4
|
+
"version": "3.14.7",
|
|
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": [
|