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.
@@ -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
- log(` ${green('✓')} ${ver}`);
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
- log(` ${green('✓')} Claude Code detected`);
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
- log(` ${green('✓')} Core engine installed`);
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
- log(` ${green('✓')} Core engine cloned`);
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
- log(` ${green('✓')} Pro modules installed (${artifact})`);
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
- log(` ${green('✓')} Python dependencies installed (isolated venv)`);
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
- log(` ${green('✓')} Python dependencies installed (global)`);
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
- log(` ${green('✓')} Delimit MCP already configured`);
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
- log(` ${green('✓')} Added delimit to ${MCP_CONFIG}`);
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
- log(` ${green('✓')} Delimit already in Codex config`);
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
- log(` ${green('✓')} Added delimit to Codex (${CODEX_CONFIG})`);
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
- log(` ${green('✓')} Delimit already in Cursor config`);
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
- log(` ${green('✓')} Added delimit to Cursor (${CURSOR_CONFIG})`);
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
- log(` ${green('✓')} Delimit already in Gemini CLI config`);
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
- log(` ${green('✓')} Added delimit to Gemini CLI (${GEMINI_CONFIG})`);
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
- log(` ${green('✓')} ${installed} agents installed (${Object.keys(agents).length - installed} already existed)`);
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
- log(` ${green('✓')} ${hooksInstalled} Git hooks installed to ${gitHooksDir}`);
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
- log(` ${green('✓')} Created ${claudeMd} with governance triggers`);
478
+ await logp(` ${green('✓')} Created ${claudeMd} with governance triggers`);
422
479
  } else if (claudeResult.action === 'updated') {
423
- log(` ${green('✓')} Updated Delimit section in ${claudeMd} (version changed)`);
480
+ await logp(` ${green('✓')} Updated Delimit section in ${claudeMd} (version changed)`);
424
481
  } else if (claudeResult.action === 'appended') {
425
- log(` ${green('✓')} Appended Delimit section to ${claudeMd} (user content preserved)`);
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.5",
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": [