Skip to content

Commit 5875e7b

Browse files
committed
Don't sync env vars when updating keys
1 parent 65e03d3 commit 5875e7b

File tree

4 files changed

+6
-207
lines changed

4 files changed

+6
-207
lines changed

src/install.ts

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -126,34 +126,6 @@ export const buildMcpConfig = (options: {
126126
};
127127
};
128128

129-
/**
130-
* Merge selected env flags with key metadata env (if provided), preferring the key's
131-
* persisted values. This ensures the written MCP configs reflect the authoritative
132-
* values saved to the key after any updates in the setup flow.
133-
*/
134-
export function resolveFinalMcpEnv(
135-
selectedEnv: Record<string, string>,
136-
keyEnv?: Record<string, string>
137-
): Record<string, string> {
138-
const normalize = (v?: string) => (v === "true" ? "true" : "false");
139-
const result = { ...selectedEnv } as Record<string, string>;
140-
if (keyEnv) {
141-
result.ITERABLE_USER_PII = normalize(
142-
keyEnv.ITERABLE_USER_PII ?? result.ITERABLE_USER_PII
143-
);
144-
result.ITERABLE_ENABLE_WRITES = normalize(
145-
keyEnv.ITERABLE_ENABLE_WRITES ?? result.ITERABLE_ENABLE_WRITES
146-
);
147-
result.ITERABLE_ENABLE_SENDS = normalize(
148-
keyEnv.ITERABLE_ENABLE_SENDS ?? result.ITERABLE_ENABLE_SENDS
149-
);
150-
}
151-
result.ITERABLE_USER_PII = normalize(result.ITERABLE_USER_PII);
152-
result.ITERABLE_ENABLE_WRITES = normalize(result.ITERABLE_ENABLE_WRITES);
153-
result.ITERABLE_ENABLE_SENDS = normalize(result.ITERABLE_ENABLE_SENDS);
154-
return result;
155-
}
156-
157129
/**
158130
* Pick only permission-related env flags for persistence into key metadata.
159131
*/
@@ -795,24 +767,13 @@ export const setupMcpServer = async (): Promise<void> => {
795767
}
796768
console.log();
797769

798-
// If we used an existing key, update its env overrides with chosen settings
770+
// If we used an existing key, persist the chosen settings to it
799771
if (usedKeyName) {
800772
try {
801773
await keyManager.updateKeyEnv(
802774
usedKeyName,
803775
pickPersistablePermissionEnv(mcpEnv)
804776
);
805-
806-
// Re-read the key metadata and prefer its persisted env when writing
807-
// tool configurations. This addresses cases where the key was activated
808-
// during setup and ensures configs reflect the updated values.
809-
const keys = await keyManager.listKeys();
810-
const updatedMeta = keys.find(
811-
(k) => k.name === usedKeyName || k.id === usedKeyName
812-
);
813-
if (updatedMeta?.env) {
814-
mcpEnv = resolveFinalMcpEnv(mcpEnv, updatedMeta.env);
815-
}
816777
} catch (err) {
817778
if (process.env.ITERABLE_DEBUG === "true") {
818779
console.warn(
@@ -822,8 +783,6 @@ export const setupMcpServer = async (): Promise<void> => {
822783
}
823784
}
824785
}
825-
// Enforce again after merging persisted key env
826-
mcpEnv = enforceSendsRequiresWrites(mcpEnv, (msg) => showWarning(msg));
827786

828787
// Step 5: Configure AI Tools
829788
console.log();

src/keys-cli.ts

Lines changed: 5 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,17 @@
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";
87
import inquirer from "inquirer";
9-
import os from "os";
108
import path from "path";
119
import { fileURLToPath } from "url";
12-
import { promisify } from "util";
1310

1411
const { dirname, join } = path;
1512

1613
import { getSpinner, loadUi } from "./utils/cli-env.js";
1714
import { getKeyStorageMessage } from "./utils/formatting.js";
1815
import { promptForApiKey } from "./utils/password-prompt.js";
1916

20-
const execFileAsync = promisify(execFile);
21-
2217
// Get package version
2318
const 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
);

tests/unit/env-permissions-enforcement.test.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { describe, expect, it, jest } from "@jest/globals";
33
import {
44
enforceSendsRequiresWrites,
55
pickPersistablePermissionEnv,
6-
resolveFinalMcpEnv,
76
} from "../../src/install.js";
87

98
describe("permission env enforcement and filtering", () => {
@@ -46,21 +45,4 @@ describe("permission env enforcement and filtering", () => {
4645
expect(persisted.ITERABLE_USER_PII).toBe("false"); // normalized
4746
expect((persisted as any).ITERABLE_DEBUG).toBeUndefined();
4847
});
49-
50-
it("resolveFinalMcpEnv normalizes and prefers key env values", () => {
51-
const selected = {
52-
ITERABLE_USER_PII: "false",
53-
ITERABLE_ENABLE_WRITES: "false",
54-
ITERABLE_ENABLE_SENDS: "false",
55-
} as Record<string, string>;
56-
const keyEnv = {
57-
ITERABLE_USER_PII: "true",
58-
ITERABLE_ENABLE_WRITES: "true",
59-
ITERABLE_ENABLE_SENDS: "true",
60-
} as Record<string, string>;
61-
const finalEnv = resolveFinalMcpEnv(selected, keyEnv);
62-
expect(finalEnv.ITERABLE_USER_PII).toBe("true");
63-
expect(finalEnv.ITERABLE_ENABLE_WRITES).toBe("true");
64-
expect(finalEnv.ITERABLE_ENABLE_SENDS).toBe("true");
65-
});
6648
});

tests/unit/install-existing-key-env-sync.test.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)