33 * CLI commands for API key management with beautiful modern UI
44 */
55
6- import { execFile , spawn } from "child_process" ;
7- import { promises as fs , readFileSync } from "fs" ;
6+ import { readFileSync } from "fs" ;
87import inquirer from "inquirer" ;
9- import os from "os" ;
108import path from "path" ;
119import { fileURLToPath } from "url" ;
12- import { promisify } from "util" ;
1310
1411const { dirname, join } = path ;
1512
1613import { getSpinner , loadUi } from "./utils/cli-env.js" ;
1714import { getKeyStorageMessage } from "./utils/formatting.js" ;
1815import { promptForApiKey } from "./utils/password-prompt.js" ;
1916
20- const execFileAsync = promisify ( execFile ) ;
21-
2217// Get package version
2318const packageJson = JSON . parse (
2419 readFileSync (
@@ -415,108 +410,7 @@ export async function handleKeysCommand(): Promise<void> {
415410 console . log ( formatKeyValue ( "User PII" , pii ) ) ;
416411 console . log ( formatKeyValue ( "Writes" , writes ) ) ;
417412 console . log ( formatKeyValue ( "Sends" , sends ) ) ;
418-
419- // Sync configured AI tool JSON files to reflect the active key's flags
420- try {
421- const {
422- resolveFinalMcpEnv,
423- enforceSendsRequiresWrites,
424- buildMcpConfig,
425- } = await import ( "./install.js" ) ;
426- let mcpEnv = resolveFinalMcpEnv (
427- {
428- ITERABLE_USER_PII : "false" ,
429- ITERABLE_ENABLE_WRITES : "false" ,
430- ITERABLE_ENABLE_SENDS : "false" ,
431- } ,
432- meta . env as Record < string , string > | undefined
433- ) ;
434- mcpEnv = enforceSendsRequiresWrites ( mcpEnv ) ;
435-
436- // Determine file-based tool config locations (Cursor, Claude Desktop)
437- const cursorPath = path . join ( os . homedir ( ) , ".cursor" , "mcp.json" ) ;
438- // macOS-only path (we already guard the command to run only on darwin)
439- const claudeDesktopPath = path . join (
440- os . homedir ( ) ,
441- "Library" ,
442- "Application Support" ,
443- "Claude" ,
444- "claude_desktop_config.json"
445- ) ;
446-
447- const targets = [
448- { name : "Cursor" , file : cursorPath } ,
449- { name : "Claude Desktop" , file : claudeDesktopPath } ,
450- ] ;
451-
452- const { updateToolConfig } = await import ( "./utils/tool-config.js" ) ;
453- for ( const t of targets ) {
454- try {
455- const raw = await fs . readFile ( t . file , "utf8" ) . catch ( ( ) => "" ) ;
456- if ( ! raw ) continue ;
457- const existing = JSON . parse ( raw || "{}" ) ;
458- if ( ! existing ?. mcpServers ?. iterable ) continue ;
459-
460- const iterableMcpConfig = buildMcpConfig ( {
461- env : {
462- ...( existing . mcpServers . iterable . env || { } ) ,
463- ...mcpEnv ,
464- } ,
465- } ) ;
466- await updateToolConfig ( t . file , iterableMcpConfig ) ;
467- showSuccess (
468- `${ t . name } configuration synced to active key permissions`
469- ) ;
470- } catch {
471- // Non-fatal: skip if cannot read/parse/write
472- }
473- }
474-
475- // Update Claude Code CLI registry if available
476- try {
477- await execFileAsync ( "claude" , [ "--version" ] ) ;
478-
479- // Build config using existing helper (keeps local/npx logic consistent)
480- const iterableMcpConfig = buildMcpConfig ( { env : mcpEnv } ) ;
481- const configJson = JSON . stringify ( iterableMcpConfig ) ;
482-
483- // Remove existing registration (ignore errors)
484- await execFileAsync ( "claude" , [
485- "mcp" ,
486- "remove" ,
487- "iterable" ,
488- ] ) . catch ( ( ) => { } ) ;
489-
490- // Add new registration with inherited stdio to show Claude CLI output
491- await new Promise < void > ( ( resolve , reject ) => {
492- const child = spawn (
493- "claude" ,
494- [ "mcp" , "add-json" , "iterable" , configJson ] ,
495- {
496- stdio : "inherit" ,
497- }
498- ) ;
499- child . on ( "close" , ( code ) => {
500- if ( code === 0 ) resolve ( ) ;
501- else
502- reject (
503- new Error (
504- `claude mcp add-json exited with code ${ code ?? "unknown" } `
505- )
506- ) ;
507- } ) ;
508- child . on ( "error" , reject ) ;
509- } ) ;
510-
511- showSuccess (
512- "Claude Code configuration synced to active key permissions"
513- ) ;
514- } catch {
515- // If Claude CLI not installed or update fails, skip silently
516- }
517- } catch {
518- // Non-fatal: if syncing fails, continue
519- }
413+ console . log ( ) ;
520414 } else {
521415 console . log ( ) ;
522416 showSuccess ( `"${ idOrName } " is now your active API key` ) ;
@@ -527,10 +421,9 @@ export async function handleKeysCommand(): Promise<void> {
527421 [
528422 chalk . yellow ( "Restart your AI tools to use this key" ) ,
529423 "" ,
530- chalk . gray ( "The new key will be used after restarting:" ) ,
531- chalk . white ( " • Cursor" ) ,
532- chalk . white ( " • Claude Desktop" ) ,
533- chalk . white ( " • Claude Code" ) ,
424+ chalk . gray (
425+ "The MCP server will automatically load the active key when it starts"
426+ ) ,
534427 ] ,
535428 { icon : icons . zap , theme : "warning" }
536429 ) ;
0 commit comments