theclawbay 0.3.55 → 0.3.56

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.
@@ -27,6 +27,13 @@ const SHELL_START = "# theclawbay-shell-managed:start";
27
27
  const SHELL_END = "# theclawbay-shell-managed:end";
28
28
  const ENV_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "env");
29
29
  const ENV_KEY_NAME = "THECLAWBAY_API_KEY";
30
+ const CLAUDE_ENV_API_KEY_NAME = "ANTHROPIC_API_KEY";
31
+ const CLAUDE_ENV_BASE_URL_NAME = "ANTHROPIC_BASE_URL";
32
+ const CLAUDE_ENV_SIMPLE_MODE_NAME = "CLAUDE_CODE_SIMPLE";
33
+ const CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME = "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC";
34
+ const CLAUDE_ENV_ENABLE_TELEMETRY_NAME = "CLAUDE_CODE_ENABLE_TELEMETRY";
35
+ const CLAUDE_CODE_EDITOR_ENV_SETTING = "claudeCode.environmentVariables";
36
+ const CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING = "claudeCode.disableLoginPrompt";
30
37
  const CONTINUE_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".continue", "config.yaml");
31
38
  const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "globalState.json");
32
39
  const CLINE_SECRETS_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "secrets.json");
@@ -40,6 +47,9 @@ const GSD_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateD
40
47
  const OPENCODE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "opencode.restore.json");
41
48
  const KILO_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "kilo.restore.json");
42
49
  const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
50
+ const EDITOR_TERMINAL_ENV_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "editor-terminal-env.restore.json");
51
+ const CLAUDE_EDITOR_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "claude-editor-settings.restore.json");
52
+ const CODEX_FEATURE_FLAGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "codex-features.restore.json");
43
53
  const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
44
54
  const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
45
55
  const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set([
@@ -126,6 +136,118 @@ function removeTopLevelProviderSelection(source) {
126
136
  }
127
137
  return `${filtered.join("\n").trimEnd()}\n`;
128
138
  }
139
+ function removeTopLevelKeyLineIf(source, key, shouldRemove) {
140
+ const lines = source.split(/\r?\n/);
141
+ const filtered = [];
142
+ let removed = false;
143
+ for (let i = 0; i < lines.length; i++) {
144
+ const line = lines[i] ?? "";
145
+ if (/^\s*\[/.test(line)) {
146
+ filtered.push(...lines.slice(i));
147
+ break;
148
+ }
149
+ if (/^\s*#/.test(line) || !line.trim()) {
150
+ filtered.push(line);
151
+ continue;
152
+ }
153
+ const match = line.match(new RegExp(`^\\s*${key}\\s*=\\s*\"([^\"]*)\"\\s*$`));
154
+ if (!match) {
155
+ filtered.push(line);
156
+ continue;
157
+ }
158
+ if (shouldRemove(match[1] ?? "")) {
159
+ removed = true;
160
+ continue;
161
+ }
162
+ filtered.push(line);
163
+ }
164
+ if (!removed)
165
+ return source;
166
+ return `${filtered.join("\n").trimEnd()}\n`;
167
+ }
168
+ function setTopLevelTableKey(source, tableName, key, tomlValue) {
169
+ const header = `[${tableName}]`;
170
+ const lines = source.split(/\r?\n/);
171
+ let tableStart = -1;
172
+ for (let i = 0; i < lines.length; i++) {
173
+ if ((lines[i] ?? "").trim() === header) {
174
+ tableStart = i;
175
+ break;
176
+ }
177
+ }
178
+ if (tableStart < 0) {
179
+ const block = `${header}\n${key} = ${tomlValue}\n`;
180
+ if (!source.trim())
181
+ return block;
182
+ return `${source.trimEnd()}\n\n${block}`;
183
+ }
184
+ let tableEnd = lines.length;
185
+ for (let i = tableStart + 1; i < lines.length; i++) {
186
+ if (/^\s*\[[^\]]+\]\s*$/.test(lines[i] ?? "")) {
187
+ tableEnd = i;
188
+ break;
189
+ }
190
+ }
191
+ for (let i = tableStart + 1; i < tableEnd; i++) {
192
+ const line = lines[i] ?? "";
193
+ if (/^\s*#/.test(line))
194
+ continue;
195
+ if (new RegExp(`^\\s*${key}\\s*=`).test(line)) {
196
+ lines[i] = `${key} = ${tomlValue}`;
197
+ return `${lines.join("\n").trimEnd()}\n`;
198
+ }
199
+ }
200
+ lines.splice(tableEnd, 0, `${key} = ${tomlValue}`);
201
+ return `${lines.join("\n").trimEnd()}\n`;
202
+ }
203
+ function removeTopLevelTableKey(source, tableName, key) {
204
+ const header = `[${tableName}]`;
205
+ const lines = source.split(/\r?\n/);
206
+ let tableStart = -1;
207
+ for (let i = 0; i < lines.length; i++) {
208
+ if ((lines[i] ?? "").trim() === header) {
209
+ tableStart = i;
210
+ break;
211
+ }
212
+ }
213
+ if (tableStart < 0)
214
+ return source;
215
+ let tableEnd = lines.length;
216
+ for (let i = tableStart + 1; i < lines.length; i++) {
217
+ if (/^\s*\[[^\]]+\]\s*$/.test(lines[i] ?? "")) {
218
+ tableEnd = i;
219
+ break;
220
+ }
221
+ }
222
+ let removed = false;
223
+ const nextLines = [...lines];
224
+ for (let i = tableStart + 1; i < tableEnd; i++) {
225
+ const line = nextLines[i] ?? "";
226
+ if (/^\s*#/.test(line))
227
+ continue;
228
+ if (new RegExp(`^\\s*${key}\\s*=`).test(line)) {
229
+ nextLines.splice(i, 1);
230
+ removed = true;
231
+ break;
232
+ }
233
+ }
234
+ if (!removed)
235
+ return source;
236
+ return `${nextLines.join("\n").trimEnd()}\n`;
237
+ }
238
+ function isTheClawBayChatgptBaseUrl(value) {
239
+ const trimmed = value.trim().replace(/\/+$/g, "");
240
+ if (!trimmed)
241
+ return false;
242
+ try {
243
+ const parsed = new URL(trimmed);
244
+ const hostname = parsed.hostname.toLowerCase();
245
+ return hostname === THECLAWBAY_CANONICAL_API_HOST || THECLAWBAY_WEBSITE_HOSTS.has(hostname);
246
+ }
247
+ catch {
248
+ return false;
249
+ }
250
+ }
129
251
  async function readFileIfExists(filePath) {
130
252
  try {
131
253
  return await promises_1.default.readFile(filePath, "utf8");
@@ -321,6 +443,7 @@ async function cleanupCodexConfig() {
321
443
  next = removeManagedBlock(next, MANAGED_START, MANAGED_END);
322
444
  next = removeProviderTable(next, DEFAULT_PROVIDER_ID);
323
445
  next = removeTopLevelProviderSelection(next);
446
+ next = removeTopLevelKeyLineIf(next, "chatgpt_base_url", isTheClawBayChatgptBaseUrl);
324
447
  return writeIfChanged(configPath, next, existing);
325
448
  }
326
449
  async function cleanupContinueConfig() {
@@ -675,6 +798,131 @@ async function cleanupVsCodeHooks() {
675
798
  }
676
799
  return updated;
677
800
  }
801
+ function terminalIntegratedEnvSettingsKey() {
802
+ if (node_os_1.default.platform() === "darwin")
803
+ return "terminal.integrated.env.osx";
804
+ if (node_os_1.default.platform() === "win32")
805
+ return "terminal.integrated.env.windows";
806
+ return "terminal.integrated.env.linux";
807
+ }
808
+ async function cleanupEditorTerminalEnvSettings() {
809
+ const snapshotRaw = await readFileIfExists(EDITOR_TERMINAL_ENV_STATE_PATH);
810
+ if (snapshotRaw === null || !snapshotRaw.trim())
811
+ return [];
812
+ let entries = [];
813
+ try {
814
+ entries = JSON.parse(snapshotRaw);
815
+ }
816
+ catch {
817
+ return [];
818
+ }
819
+ const settingsKey = terminalIntegratedEnvSettingsKey();
820
+ const updated = [];
821
+ for (const entry of entries) {
822
+ const settings = await readJsonObjectFile(entry.settingsPath);
823
+ if (!entry.hadKey) {
824
+ if (Object.prototype.hasOwnProperty.call(settings, settingsKey)) {
825
+ delete settings[settingsKey];
826
+ }
827
+ }
828
+ else {
829
+ settings[settingsKey] = entry.previousValue;
830
+ }
831
+ if (entry.existed || Object.keys(settings).length > 0) {
832
+ const next = `${JSON.stringify(settings, null, 2)}\n`;
833
+ const existing = await readFileIfExists(entry.settingsPath);
834
+ if (existing !== next) {
835
+ await promises_1.default.mkdir(node_path_1.default.dirname(entry.settingsPath), { recursive: true });
836
+ await promises_1.default.writeFile(entry.settingsPath, next, "utf8");
837
+ updated.push(entry.settingsPath);
838
+ }
839
+ continue;
840
+ }
841
+ if (await removeFileIfExists(entry.settingsPath)) {
842
+ updated.push(entry.settingsPath);
843
+ }
844
+ }
845
+ await removeFileIfExists(EDITOR_TERMINAL_ENV_STATE_PATH);
846
+ return updated;
847
+ }
848
+ async function cleanupClaudeEditorSettings() {
849
+ const snapshotRaw = await readFileIfExists(CLAUDE_EDITOR_SETTINGS_STATE_PATH);
850
+ if (snapshotRaw === null || !snapshotRaw.trim())
851
+ return [];
852
+ let entries = [];
853
+ try {
854
+ entries = JSON.parse(snapshotRaw);
855
+ }
856
+ catch {
857
+ return [];
858
+ }
859
+ const updated = [];
860
+ for (const entry of entries) {
861
+ const settings = await readJsonObjectFile(entry.settingsPath);
862
+ if (!entry.envHadKey) {
863
+ delete settings[CLAUDE_CODE_EDITOR_ENV_SETTING];
864
+ }
865
+ else {
866
+ settings[CLAUDE_CODE_EDITOR_ENV_SETTING] = entry.envPreviousValue;
867
+ }
868
+ if (!entry.disableLoginPromptHadKey) {
869
+ delete settings[CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING];
870
+ }
871
+ else {
872
+ settings[CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING] = entry.disableLoginPromptPreviousValue;
873
+ }
874
+ if (entry.existed || Object.keys(settings).length > 0) {
875
+ const next = `${JSON.stringify(settings, null, 2)}\n`;
876
+ const existing = await readFileIfExists(entry.settingsPath);
877
+ if (existing !== next) {
878
+ await promises_1.default.mkdir(node_path_1.default.dirname(entry.settingsPath), { recursive: true });
879
+ await promises_1.default.writeFile(entry.settingsPath, next, "utf8");
880
+ updated.push(entry.settingsPath);
881
+ }
882
+ continue;
883
+ }
884
+ if (await removeFileIfExists(entry.settingsPath)) {
885
+ updated.push(entry.settingsPath);
886
+ }
887
+ }
888
+ await removeFileIfExists(CLAUDE_EDITOR_SETTINGS_STATE_PATH);
889
+ return updated;
890
+ }
891
+ async function cleanupCodexFeatureFlags() {
892
+ const snapshotRaw = await readFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
893
+ if (snapshotRaw === null || !snapshotRaw.trim())
894
+ return false;
895
+ let snapshot = null;
896
+ try {
897
+ snapshot = JSON.parse(snapshotRaw);
898
+ }
899
+ catch {
900
+ snapshot = null;
901
+ }
902
+ if (!snapshot)
903
+ return false;
904
+ const configPath = node_path_1.default.join(paths_1.codexDir, "config.toml");
905
+ const existing = await readFileIfExists(configPath);
906
+ if (existing === null) {
907
+ await removeFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
908
+ return false;
909
+ }
910
+ let next = existing;
911
+ if (snapshot.appsHadKey && snapshot.appsPreviousValue !== null) {
912
+ next = setTopLevelTableKey(next, "features", "apps", snapshot.appsPreviousValue);
913
+ }
914
+ else {
915
+ next = removeTopLevelTableKey(next, "features", "apps");
916
+ }
917
+ if (snapshot.appsMcpGatewayHadKey && snapshot.appsMcpGatewayPreviousValue !== null) {
918
+ next = setTopLevelTableKey(next, "features", "apps_mcp_gateway", snapshot.appsMcpGatewayPreviousValue);
919
+ }
920
+ else {
921
+ next = removeTopLevelTableKey(next, "features", "apps_mcp_gateway");
922
+ }
923
+ await removeFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
924
+ return writeIfChanged(configPath, next, existing);
925
+ }
678
926
  async function cleanupOpenClawConfig() {
679
927
  const configPath = node_path_1.default.join(node_os_1.default.homedir(), ".openclaw", "openclaw.json");
680
928
  const existingRaw = await readFileIfExists(configPath);
@@ -937,7 +1185,10 @@ class LogoutCommand extends base_command_1.BaseCommand {
937
1185
  let updatedShellFiles = [];
938
1186
  let updatedPowerShellProfiles = [];
939
1187
  let updatedVsCodeHooks = [];
1188
+ let updatedEditorTerminalSettings = [];
1189
+ let updatedClaudeEditorSettings = [];
940
1190
  let updatedCodexConfig = false;
1191
+ let updatedCodexFeatures = false;
941
1192
  let updatedContinueConfig = false;
942
1193
  let updatedClineConfig = false;
943
1194
  let updatedGsdConfig = false;
@@ -986,8 +1237,11 @@ class LogoutCommand extends base_command_1.BaseCommand {
986
1237
  updatedShellFiles = await cleanupShellFiles();
987
1238
  updatedPowerShellProfiles = await cleanupPowerShellProfiles();
988
1239
  updatedVsCodeHooks = await cleanupVsCodeHooks();
1240
+ updatedEditorTerminalSettings = await cleanupEditorTerminalEnvSettings();
1241
+ updatedClaudeEditorSettings = await cleanupClaudeEditorSettings();
989
1242
  progress.update("Reverting Codex");
990
1243
  updatedCodexConfig = await cleanupCodexConfig();
1244
+ updatedCodexFeatures = await cleanupCodexFeatureFlags();
991
1245
  sessionMigration = await (0, codex_history_migration_1.migrateSessionProviders)({
992
1246
  codexHome: paths_1.codexDir,
993
1247
  migrationStateFile: MIGRATION_STATE_FILE,
@@ -1028,8 +1282,11 @@ class LogoutCommand extends base_command_1.BaseCommand {
1028
1282
  throw error;
1029
1283
  }
1030
1284
  delete process.env[ENV_KEY_NAME];
1031
- delete process.env.ANTHROPIC_API_KEY;
1032
- delete process.env.ANTHROPIC_BASE_URL;
1285
+ delete process.env[CLAUDE_ENV_API_KEY_NAME];
1286
+ delete process.env[CLAUDE_ENV_BASE_URL_NAME];
1287
+ delete process.env[CLAUDE_ENV_SIMPLE_MODE_NAME];
1288
+ delete process.env[CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME];
1289
+ delete process.env[CLAUDE_ENV_ENABLE_TELEMETRY_NAME];
1033
1290
  if (!debugOutput && process.stdout.isTTY) {
1034
1291
  progress.succeed("Logout complete");
1035
1292
  }
@@ -1038,7 +1295,10 @@ class LogoutCommand extends base_command_1.BaseCommand {
1038
1295
  }
1039
1296
  const revertedTargets = [];
1040
1297
  const codexChanged = updatedCodexConfig ||
1298
+ updatedCodexFeatures ||
1041
1299
  updatedVsCodeHooks.length > 0 ||
1300
+ updatedEditorTerminalSettings.length > 0 ||
1301
+ updatedClaudeEditorSettings.length > 0 ||
1042
1302
  sessionMigration.rewritten > 0 ||
1043
1303
  sessionMigration.retimed > 0 ||
1044
1304
  stateDbMigration.updated > 0 ||
@@ -1086,7 +1346,9 @@ class LogoutCommand extends base_command_1.BaseCommand {
1086
1346
  removedEnvFile ||
1087
1347
  updatedShellFiles.length > 0 ||
1088
1348
  updatedPowerShellProfiles.length > 0 ||
1089
- updatedVsCodeHooks.length > 0,
1349
+ updatedVsCodeHooks.length > 0 ||
1350
+ updatedEditorTerminalSettings.length > 0 ||
1351
+ updatedClaudeEditorSettings.length > 0,
1090
1352
  notes: Array.from(summaryNotes),
1091
1353
  });
1092
1354
  return;
@@ -1102,7 +1364,10 @@ class LogoutCommand extends base_command_1.BaseCommand {
1102
1364
  this.log(`- Shell profiles updated: ${updatedShellFiles.length ? updatedShellFiles.join(", ") : "none"}`);
1103
1365
  this.log(`- PowerShell profiles updated: ${updatedPowerShellProfiles.length ? updatedPowerShellProfiles.join(", ") : "none"}`);
1104
1366
  this.log(`- VS Code env hooks updated: ${updatedVsCodeHooks.length ? updatedVsCodeHooks.join(", ") : "none"}`);
1367
+ this.log(`- Editor terminal env updated: ${updatedEditorTerminalSettings.length ? updatedEditorTerminalSettings.join(", ") : "none"}`);
1368
+ this.log(`- Claude editor settings updated: ${updatedClaudeEditorSettings.length ? updatedClaudeEditorSettings.join(", ") : "none"}`);
1105
1369
  this.log(`- Codex config cleaned: ${updatedCodexConfig ? "yes" : "no"}`);
1370
+ this.log(`- Codex Apps feature flags restored: ${updatedCodexFeatures ? "yes" : "no"}`);
1106
1371
  if (sessionMigration.rewritten > 0) {
1107
1372
  this.log(`- Conversations: updated ${sessionMigration.rewritten}/${sessionMigration.scanned} local sessions for cross-provider visibility.`);
1108
1373
  }
@@ -42,6 +42,18 @@ const ENV_KEY_NAME = "THECLAWBAY_API_KEY";
42
42
  const CLAUDE_ENV_API_KEY_NAME = "ANTHROPIC_API_KEY";
43
43
  const CLAUDE_ENV_BASE_URL_NAME = "ANTHROPIC_BASE_URL";
44
44
  const CLAUDE_ENV_SIMPLE_MODE_NAME = "CLAUDE_CODE_SIMPLE";
45
+ const CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME = "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC";
46
+ const CLAUDE_ENV_ENABLE_TELEMETRY_NAME = "CLAUDE_CODE_ENABLE_TELEMETRY";
47
+ const CLAUDE_CODE_EDITOR_ENV_SETTING = "claudeCode.environmentVariables";
48
+ const CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING = "claudeCode.disableLoginPrompt";
49
+ const MANAGED_EDITOR_TERMINAL_ENV_NAMES = [
50
+ ENV_KEY_NAME,
51
+ CLAUDE_ENV_API_KEY_NAME,
52
+ CLAUDE_ENV_BASE_URL_NAME,
53
+ CLAUDE_ENV_SIMPLE_MODE_NAME,
54
+ CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME,
55
+ CLAUDE_ENV_ENABLE_TELEMETRY_NAME,
56
+ ];
45
57
  const ENV_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "env");
46
58
  const CONTINUE_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".continue", "config.yaml");
47
59
  const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "globalState.json");
@@ -56,6 +68,9 @@ const GSD_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateD
56
68
  const OPENCODE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "opencode.restore.json");
57
69
  const KILO_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "kilo.restore.json");
58
70
  const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
71
+ const EDITOR_TERMINAL_ENV_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "editor-terminal-env.restore.json");
72
+ const CLAUDE_EDITOR_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "claude-editor-settings.restore.json");
73
+ const CODEX_FEATURE_FLAGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "codex-features.restore.json");
59
74
  const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
60
75
  const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
61
76
  const MANAGED_START = "# theclawbay-managed:start";
@@ -455,6 +470,99 @@ function upsertFirstKeyLine(source, key, tomlValue) {
455
470
  }
456
471
  return `${`${key} = ${tomlValue}\n${source}`.trimEnd()}\n`;
457
472
  }
473
+ function parseTomlScalarValue(line) {
474
+ const match = line.match(/^\s*[A-Za-z0-9_.-]+\s*=\s*(.+?)\s*$/);
475
+ return match?.[1]?.trim() ?? null;
476
+ }
477
+ function upsertTopLevelTableKey(source, tableName, key, tomlValue) {
478
+ const header = `[${tableName}]`;
479
+ const lines = source.split(/\r?\n/);
480
+ let tableStart = -1;
481
+ for (let i = 0; i < lines.length; i++) {
482
+ if ((lines[i] ?? "").trim() === header) {
483
+ tableStart = i;
484
+ break;
485
+ }
486
+ }
487
+ if (tableStart < 0) {
488
+ const block = `${header}\n${key} = ${tomlValue}\n`;
489
+ if (!source.trim())
490
+ return block;
491
+ return `${source.trimEnd()}\n\n${block}`;
492
+ }
493
+ let tableEnd = lines.length;
494
+ for (let i = tableStart + 1; i < lines.length; i++) {
495
+ if (/^\s*\[[^\]]+\]\s*$/.test(lines[i] ?? "")) {
496
+ tableEnd = i;
497
+ break;
498
+ }
499
+ }
500
+ for (let i = tableStart + 1; i < tableEnd; i++) {
501
+ const line = lines[i] ?? "";
502
+ if (/^\s*#/.test(line))
503
+ continue;
504
+ if (new RegExp(`^\\s*${key}\\s*=`).test(line)) {
505
+ lines[i] = `${key} = ${tomlValue}`;
506
+ return `${lines.join("\n").trimEnd()}\n`;
507
+ }
508
+ }
509
+ lines.splice(tableEnd, 0, `${key} = ${tomlValue}`);
510
+ return `${lines.join("\n").trimEnd()}\n`;
511
+ }
512
+ function readTopLevelTableKeyValue(source, tableName, key) {
513
+ const header = `[${tableName}]`;
514
+ const lines = source.split(/\r?\n/);
515
+ let tableStart = -1;
516
+ for (let i = 0; i < lines.length; i++) {
517
+ if ((lines[i] ?? "").trim() === header) {
518
+ tableStart = i;
519
+ break;
520
+ }
521
+ }
522
+ if (tableStart < 0) {
523
+ return { hadTable: false, hadKey: false, value: null };
524
+ }
525
+ for (let i = tableStart + 1; i < lines.length; i++) {
526
+ const line = lines[i] ?? "";
527
+ if (/^\s*\[[^\]]+\]\s*$/.test(line))
528
+ break;
529
+ if (/^\s*#/.test(line) || !line.trim())
530
+ continue;
531
+ if (new RegExp(`^\\s*${key}\\s*=`).test(line)) {
532
+ return { hadTable: true, hadKey: true, value: parseTomlScalarValue(line) };
533
+ }
534
+ }
535
+ return { hadTable: true, hadKey: false, value: null };
536
+ }
537
+ function removeTopLevelKeyLineIf(source, key, shouldRemove) {
538
+ const lines = source.split(/\r?\n/);
539
+ const filtered = [];
540
+ let removed = false;
541
+ for (let i = 0; i < lines.length; i++) {
542
+ const line = lines[i] ?? "";
543
+ if (/^\s*\[/.test(line)) {
544
+ filtered.push(...lines.slice(i));
545
+ break;
546
+ }
547
+ if (/^\s*#/.test(line) || !line.trim()) {
548
+ filtered.push(line);
549
+ continue;
550
+ }
551
+ const match = line.match(new RegExp(`^\\s*${key}\\s*=\\s*\"([^\"]*)\"\\s*$`));
552
+ if (!match) {
553
+ filtered.push(line);
554
+ continue;
555
+ }
556
+ if (shouldRemove(match[1] ?? "")) {
557
+ removed = true;
558
+ continue;
559
+ }
560
+ filtered.push(line);
561
+ }
562
+ if (!removed)
563
+ return source;
564
+ return `${filtered.join("\n").trimEnd()}\n`;
565
+ }
458
566
  function shellQuote(value) {
459
567
  return `'${value.replace(/'/g, `'\\''`)}'`;
460
568
  }
@@ -480,6 +588,19 @@ function publicApiOriginForBackendUrl(backendUrl) {
480
588
  return trimmed;
481
589
  }
482
590
  }
591
+ function isTheClawBayChatgptBaseUrl(value) {
592
+ const trimmed = trimTrailingSlash(value.trim());
593
+ if (!trimmed)
594
+ return false;
595
+ try {
596
+ const parsed = new URL(trimmed);
597
+ const hostname = parsed.hostname.toLowerCase();
598
+ return hostname === THECLAWBAY_CANONICAL_API_HOST || THECLAWBAY_WEBSITE_HOSTS.has(hostname);
599
+ }
600
+ catch {
601
+ return false;
602
+ }
603
+ }
483
604
  function openAiCompatibleProxyUrl(backendUrl) {
484
605
  return `${publicApiOriginForBackendUrl(backendUrl)}${CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX}`;
485
606
  }
@@ -1305,7 +1426,22 @@ async function writeCodexConfig(params) {
1305
1426
  next = removeProviderTable(next, DEFAULT_PROVIDER_ID);
1306
1427
  next = upsertFirstKeyLine(next, "model_provider", `"${DEFAULT_PROVIDER_ID}"`);
1307
1428
  next = upsertFirstKeyLine(next, "model", `"${params.model}"`);
1308
- next = upsertFirstKeyLine(next, "chatgpt_base_url", `"${proxyRoot}"`);
1429
+ next = removeTopLevelKeyLineIf(next, "chatgpt_base_url", isTheClawBayChatgptBaseUrl);
1430
+ const existingFeatureSnapshot = await readFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
1431
+ if (!existingFeatureSnapshot?.trim()) {
1432
+ const appsState = readTopLevelTableKeyValue(next, "features", "apps");
1433
+ const appsMcpGatewayState = readTopLevelTableKeyValue(next, "features", "apps_mcp_gateway");
1434
+ const snapshot = {
1435
+ hadFeaturesTable: appsState.hadTable || appsMcpGatewayState.hadTable,
1436
+ appsHadKey: appsState.hadKey,
1437
+ appsPreviousValue: appsState.value,
1438
+ appsMcpGatewayHadKey: appsMcpGatewayState.hadKey,
1439
+ appsMcpGatewayPreviousValue: appsMcpGatewayState.value,
1440
+ };
1441
+ await writeJsonObjectFile(CODEX_FEATURE_FLAGS_STATE_PATH, snapshot, 0o600);
1442
+ }
1443
+ next = upsertTopLevelTableKey(next, "features", "apps", "false");
1444
+ next = upsertTopLevelTableKey(next, "features", "apps_mcp_gateway", "false");
1309
1445
  const managedBlock = appendManagedBlock("", [
1310
1446
  MANAGED_START,
1311
1447
  `[model_providers.${DEFAULT_PROVIDER_ID}]`,
@@ -1563,7 +1699,7 @@ async function persistApiKeyEnv(params) {
1563
1699
  `export ${ENV_KEY_NAME}=${shellQuote(params.apiKey)}`,
1564
1700
  ];
1565
1701
  if (params.claudeEnabled) {
1566
- envLines.push("", "# Official Claude Code CLI", `export ${CLAUDE_ENV_API_KEY_NAME}=${shellQuote(params.apiKey)}`, `export ${CLAUDE_ENV_BASE_URL_NAME}=${shellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`, `export ${CLAUDE_ENV_SIMPLE_MODE_NAME}=1`);
1702
+ envLines.push("", "# Official Claude Code CLI", `export ${CLAUDE_ENV_API_KEY_NAME}=${shellQuote(params.apiKey)}`, `export ${CLAUDE_ENV_BASE_URL_NAME}=${shellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`, `export ${CLAUDE_ENV_SIMPLE_MODE_NAME}=1`, `export ${CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME}=1`, `export ${CLAUDE_ENV_ENABLE_TELEMETRY_NAME}=0`);
1567
1703
  }
1568
1704
  const envContents = `${envLines.join("\n")}\n`;
1569
1705
  await promises_1.default.writeFile(ENV_FILE, envContents, "utf8");
@@ -1599,11 +1735,15 @@ async function persistApiKeyEnv(params) {
1599
1735
  process.env[CLAUDE_ENV_API_KEY_NAME] = params.apiKey;
1600
1736
  process.env[CLAUDE_ENV_BASE_URL_NAME] = anthropicCompatibleProxyUrl(params.backendUrl);
1601
1737
  process.env[CLAUDE_ENV_SIMPLE_MODE_NAME] = "1";
1738
+ process.env[CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME] = "1";
1739
+ process.env[CLAUDE_ENV_ENABLE_TELEMETRY_NAME] = "0";
1602
1740
  }
1603
1741
  else {
1604
1742
  delete process.env[CLAUDE_ENV_API_KEY_NAME];
1605
1743
  delete process.env[CLAUDE_ENV_BASE_URL_NAME];
1606
1744
  delete process.env[CLAUDE_ENV_SIMPLE_MODE_NAME];
1745
+ delete process.env[CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME];
1746
+ delete process.env[CLAUDE_ENV_ENABLE_TELEMETRY_NAME];
1607
1747
  }
1608
1748
  return updated;
1609
1749
  }
@@ -1615,7 +1755,7 @@ async function persistFishEnv(params) {
1615
1755
  `set -gx ${ENV_KEY_NAME} ${shellQuote(params.apiKey)}`,
1616
1756
  ];
1617
1757
  if (params.claudeEnabled) {
1618
- lines.push("", "# Official Claude Code CLI", `set -gx ${CLAUDE_ENV_API_KEY_NAME} ${shellQuote(params.apiKey)}`, `set -gx ${CLAUDE_ENV_BASE_URL_NAME} ${shellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`, `set -gx ${CLAUDE_ENV_SIMPLE_MODE_NAME} 1`);
1758
+ lines.push("", "# Official Claude Code CLI", `set -gx ${CLAUDE_ENV_API_KEY_NAME} ${shellQuote(params.apiKey)}`, `set -gx ${CLAUDE_ENV_BASE_URL_NAME} ${shellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`, `set -gx ${CLAUDE_ENV_SIMPLE_MODE_NAME} 1`, `set -gx ${CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME} 1`, `set -gx ${CLAUDE_ENV_ENABLE_TELEMETRY_NAME} 0`);
1619
1759
  }
1620
1760
  await promises_1.default.writeFile(fishConfPath, `${lines.join("\n")}\n`, "utf8");
1621
1761
  return [fishConfPath];
@@ -1640,7 +1780,7 @@ async function persistPowerShellEnv(params) {
1640
1780
  `$env:${ENV_KEY_NAME} = ${powerShellQuote(params.apiKey)}`,
1641
1781
  ];
1642
1782
  if (params.claudeEnabled) {
1643
- lines.push(`$env:${CLAUDE_ENV_API_KEY_NAME} = ${powerShellQuote(params.apiKey)}`, `$env:${CLAUDE_ENV_BASE_URL_NAME} = ${powerShellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`, `$env:${CLAUDE_ENV_SIMPLE_MODE_NAME} = "1"`);
1783
+ lines.push(`$env:${CLAUDE_ENV_API_KEY_NAME} = ${powerShellQuote(params.apiKey)}`, `$env:${CLAUDE_ENV_BASE_URL_NAME} = ${powerShellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`, `$env:${CLAUDE_ENV_SIMPLE_MODE_NAME} = "1"`, `$env:${CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME} = "1"`, `$env:${CLAUDE_ENV_ENABLE_TELEMETRY_NAME} = "0"`);
1644
1784
  }
1645
1785
  lines.push(SHELL_END);
1646
1786
  const next = appendManagedBlock(cleaned, lines);
@@ -1677,6 +1817,165 @@ async function persistVsCodeServerEnvSource() {
1677
1817
  }
1678
1818
  return updated;
1679
1819
  }
1820
+ function terminalIntegratedEnvSettingsKey() {
1821
+ if (node_os_1.default.platform() === "darwin")
1822
+ return "terminal.integrated.env.osx";
1823
+ if (node_os_1.default.platform() === "win32")
1824
+ return "terminal.integrated.env.windows";
1825
+ return "terminal.integrated.env.linux";
1826
+ }
1827
+ function buildManagedEditorTerminalEnv(params) {
1828
+ const env = {
1829
+ [ENV_KEY_NAME]: params.apiKey,
1830
+ };
1831
+ if (params.claudeEnabled) {
1832
+ env[CLAUDE_ENV_API_KEY_NAME] = params.apiKey;
1833
+ env[CLAUDE_ENV_BASE_URL_NAME] = anthropicCompatibleProxyUrl(params.backendUrl);
1834
+ env[CLAUDE_ENV_SIMPLE_MODE_NAME] = "1";
1835
+ env[CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME] = "1";
1836
+ env[CLAUDE_ENV_ENABLE_TELEMETRY_NAME] = "0";
1837
+ }
1838
+ return env;
1839
+ }
1840
+ function buildManagedClaudeEditorEnv(params) {
1841
+ return {
1842
+ [CLAUDE_ENV_API_KEY_NAME]: params.apiKey,
1843
+ [CLAUDE_ENV_BASE_URL_NAME]: anthropicCompatibleProxyUrl(params.backendUrl),
1844
+ [CLAUDE_ENV_SIMPLE_MODE_NAME]: "1",
1845
+ [CLAUDE_ENV_DISABLE_NONESSENTIAL_TRAFFIC_NAME]: "1",
1846
+ [CLAUDE_ENV_ENABLE_TELEMETRY_NAME]: "0",
1847
+ };
1848
+ }
1849
+ async function persistEditorTerminalEnvSettings(params) {
1850
+ const settingsKey = terminalIntegratedEnvSettingsKey();
1851
+ const desiredEnv = buildManagedEditorTerminalEnv(params);
1852
+ const existingSnapshotRaw = await readFileIfExists(EDITOR_TERMINAL_ENV_STATE_PATH);
1853
+ let existingSnapshot = [];
1854
+ if (existingSnapshotRaw?.trim()) {
1855
+ try {
1856
+ existingSnapshot = JSON.parse(existingSnapshotRaw);
1857
+ }
1858
+ catch {
1859
+ existingSnapshot = [];
1860
+ }
1861
+ }
1862
+ const snapshotByPath = new Map(existingSnapshot.map((entry) => [entry.settingsPath, entry]));
1863
+ const managedPaths = [];
1864
+ for (const host of editorHosts()) {
1865
+ const settingsPath = host.userSettingsPath;
1866
+ const hostPresent = (await pathExists(host.extensionDir)) ||
1867
+ (await pathExists(settingsPath)) ||
1868
+ (await pathExists(node_path_1.default.dirname(settingsPath)));
1869
+ if (!hostPresent)
1870
+ continue;
1871
+ const existed = await pathExists(settingsPath);
1872
+ const settings = await readJsonObjectFile(settingsPath);
1873
+ const currentValue = settings[settingsKey];
1874
+ const currentEnv = typeof currentValue === "object" && currentValue !== null && !Array.isArray(currentValue)
1875
+ ? { ...currentValue }
1876
+ : {};
1877
+ let changed = false;
1878
+ for (const [name, value] of Object.entries(desiredEnv)) {
1879
+ if (currentEnv[name] === value)
1880
+ continue;
1881
+ currentEnv[name] = value;
1882
+ changed = true;
1883
+ }
1884
+ for (const name of MANAGED_EDITOR_TERMINAL_ENV_NAMES) {
1885
+ if (name in desiredEnv || !(name in currentEnv))
1886
+ continue;
1887
+ delete currentEnv[name];
1888
+ changed = true;
1889
+ }
1890
+ if (!changed)
1891
+ continue;
1892
+ if (!snapshotByPath.has(settingsPath)) {
1893
+ snapshotByPath.set(settingsPath, {
1894
+ settingsPath,
1895
+ existed,
1896
+ hadKey: Object.prototype.hasOwnProperty.call(settings, settingsKey),
1897
+ previousValue: currentValue ?? null,
1898
+ });
1899
+ }
1900
+ settings[settingsKey] = currentEnv;
1901
+ await writeJsonObjectFile(settingsPath, settings);
1902
+ managedPaths.push(settingsPath);
1903
+ }
1904
+ await writeJsonObjectFile(EDITOR_TERMINAL_ENV_STATE_PATH, Array.from(snapshotByPath.values()), 0o600);
1905
+ return managedPaths;
1906
+ }
1907
+ async function persistClaudeEditorSettings(params) {
1908
+ const existingSnapshotRaw = await readFileIfExists(CLAUDE_EDITOR_SETTINGS_STATE_PATH);
1909
+ let existingSnapshot = [];
1910
+ if (existingSnapshotRaw?.trim()) {
1911
+ try {
1912
+ existingSnapshot = JSON.parse(existingSnapshotRaw);
1913
+ }
1914
+ catch {
1915
+ existingSnapshot = [];
1916
+ }
1917
+ }
1918
+ const snapshotByPath = new Map(existingSnapshot.map((entry) => [entry.settingsPath, entry]));
1919
+ const managedPaths = [];
1920
+ const desiredEnv = params.claudeEnabled
1921
+ ? buildManagedClaudeEditorEnv({ apiKey: params.apiKey, backendUrl: params.backendUrl })
1922
+ : null;
1923
+ for (const host of editorHosts()) {
1924
+ const settingsPath = host.userSettingsPath;
1925
+ const hostPresent = (await pathExists(host.extensionDir)) ||
1926
+ (await pathExists(settingsPath)) ||
1927
+ (await pathExists(node_path_1.default.dirname(settingsPath)));
1928
+ if (!hostPresent)
1929
+ continue;
1930
+ const existed = await pathExists(settingsPath);
1931
+ const settings = await readJsonObjectFile(settingsPath);
1932
+ const currentEnvValue = settings[CLAUDE_CODE_EDITOR_ENV_SETTING];
1933
+ const currentEnv = typeof currentEnvValue === "object" && currentEnvValue !== null && !Array.isArray(currentEnvValue)
1934
+ ? { ...currentEnvValue }
1935
+ : {};
1936
+ let changed = false;
1937
+ if (!snapshotByPath.has(settingsPath)) {
1938
+ snapshotByPath.set(settingsPath, {
1939
+ settingsPath,
1940
+ existed,
1941
+ envHadKey: Object.prototype.hasOwnProperty.call(settings, CLAUDE_CODE_EDITOR_ENV_SETTING),
1942
+ envPreviousValue: currentEnvValue ?? null,
1943
+ disableLoginPromptHadKey: Object.prototype.hasOwnProperty.call(settings, CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING),
1944
+ disableLoginPromptPreviousValue: settings[CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING] ?? null,
1945
+ });
1946
+ }
1947
+ if (desiredEnv) {
1948
+ const nextEnv = { ...currentEnv };
1949
+ for (const [name, value] of Object.entries(desiredEnv)) {
1950
+ if (nextEnv[name] === value)
1951
+ continue;
1952
+ nextEnv[name] = value;
1953
+ changed = true;
1954
+ }
1955
+ settings[CLAUDE_CODE_EDITOR_ENV_SETTING] = nextEnv;
1956
+ if (settings[CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING] !== true) {
1957
+ settings[CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING] = true;
1958
+ changed = true;
1959
+ }
1960
+ }
1961
+ else {
1962
+ if (Object.prototype.hasOwnProperty.call(settings, CLAUDE_CODE_EDITOR_ENV_SETTING)) {
1963
+ delete settings[CLAUDE_CODE_EDITOR_ENV_SETTING];
1964
+ changed = true;
1965
+ }
1966
+ if (Object.prototype.hasOwnProperty.call(settings, CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING)) {
1967
+ delete settings[CLAUDE_CODE_EDITOR_DISABLE_LOGIN_PROMPT_SETTING];
1968
+ changed = true;
1969
+ }
1970
+ }
1971
+ if (!changed)
1972
+ continue;
1973
+ await writeJsonObjectFile(settingsPath, settings);
1974
+ managedPaths.push(settingsPath);
1975
+ }
1976
+ await writeJsonObjectFile(CLAUDE_EDITOR_SETTINGS_STATE_PATH, Array.from(snapshotByPath.values()), 0o600);
1977
+ return managedPaths;
1978
+ }
1680
1979
  function runOpenClawConfigCommand(args) {
1681
1980
  const run = (0, node_child_process_1.spawnSync)("openclaw", args, {
1682
1981
  encoding: "utf8",
@@ -2017,6 +2316,7 @@ async function writeOpenCodeFamilyConfig(params) {
2017
2316
  const optionsRoot = objectRecordOr(managedOpenAiProvider.options, {});
2018
2317
  optionsRoot.baseURL = openAiCompatibleProxyUrl(params.backendUrl);
2019
2318
  optionsRoot.apiKey = params.apiKey;
2319
+ optionsRoot.setCacheKey = true;
2020
2320
  managedOpenAiProvider.options = optionsRoot;
2021
2321
  managedOpenAiProvider.models = buildOpenCodeModelsObject(params.models);
2022
2322
  managedOpenAiProvider.whitelist = params.models.map((entry) => entry.id).filter(Boolean);
@@ -2144,7 +2444,7 @@ class SetupCommand extends base_command_1.BaseCommand {
2144
2444
  const setupClients = [
2145
2445
  {
2146
2446
  id: "codex",
2147
- label: "Codex CLI, VS Code extension, and Codex app",
2447
+ label: "Codex CLI and VS Code extension",
2148
2448
  summaryLabel: "Codex",
2149
2449
  detected: codexDetected,
2150
2450
  recommended: true,
@@ -2299,6 +2599,8 @@ class SetupCommand extends base_command_1.BaseCommand {
2299
2599
  let updatedPowerShellProfiles = [];
2300
2600
  let codexConfigPath = null;
2301
2601
  let updatedVsCodeEnvFiles = [];
2602
+ let updatedEditorTerminalSettings = [];
2603
+ let updatedClaudeEditorSettings = [];
2302
2604
  let sessionMigration = null;
2303
2605
  let authSeed = null;
2304
2606
  let authSeedCleanup = null;
@@ -2355,6 +2657,18 @@ class SetupCommand extends base_command_1.BaseCommand {
2355
2657
  });
2356
2658
  if (selectedSetupClients.has("codex") || selectedSetupClients.has("claude")) {
2357
2659
  updatedVsCodeEnvFiles = await persistVsCodeServerEnvSource();
2660
+ updatedEditorTerminalSettings = await persistEditorTerminalEnvSettings({
2661
+ apiKey: authCredential,
2662
+ backendUrl,
2663
+ claudeEnabled: claudeEnvEnabled,
2664
+ });
2665
+ if (selectedSetupClients.has("claude")) {
2666
+ updatedClaudeEditorSettings = await persistClaudeEditorSettings({
2667
+ apiKey: authCredential,
2668
+ backendUrl,
2669
+ claudeEnabled: claudeEnvEnabled,
2670
+ });
2671
+ }
2358
2672
  }
2359
2673
  if (selectedSetupClients.has("codex")) {
2360
2674
  progress.update("Configuring Codex");
@@ -2490,7 +2804,7 @@ class SetupCommand extends base_command_1.BaseCommand {
2490
2804
  if (resolved?.note)
2491
2805
  summaryNotes.add(resolved.note);
2492
2806
  if (selectedSetupClients.has("claude") && claudeAccess?.enabled) {
2493
- summaryNotes.add("Claude Code: exported ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY, and CLAUDE_CODE_SIMPLE=1 for the official client.");
2807
+ summaryNotes.add("Claude Code: exported ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY, CLAUDE_CODE_SIMPLE=1, disabled nonessential traffic, and disabled telemetry.");
2494
2808
  summaryNotes.add("If Claude Code is already open, restart it so the custom-key env takes effect cleanly. `claude auth status` should show `authMethod: api_key` once the new env is loaded.");
2495
2809
  }
2496
2810
  else if (selectedSetupClients.has("claude") && claudeAccess?.note) {
@@ -2559,6 +2873,12 @@ class SetupCommand extends base_command_1.BaseCommand {
2559
2873
  if (updatedPowerShellProfiles.length > 0) {
2560
2874
  this.log(`- PowerShell profiles updated: ${updatedPowerShellProfiles.join(", ")}`);
2561
2875
  }
2876
+ if (updatedEditorTerminalSettings.length > 0) {
2877
+ this.log(`- Editor terminal env updated: ${updatedEditorTerminalSettings.join(", ")}`);
2878
+ }
2879
+ if (updatedClaudeEditorSettings.length > 0) {
2880
+ this.log(`- Claude editor settings updated: ${updatedClaudeEditorSettings.join(", ")}`);
2881
+ }
2562
2882
  if (selectedSetupClients.has("codex")) {
2563
2883
  this.log(`- Codex: configured (${codexConfigPath})`);
2564
2884
  if (resolved)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theclawbay",
3
- "version": "0.3.55",
3
+ "version": "0.3.56",
4
4
  "description": "CLI for connecting Codex, Continue, Cline, GSD, OpenClaw, OpenCode, Kilo, Roo Code, Aider, experimental Trae, and experimental Zo to The Claw Bay.",
5
5
  "license": "MIT",
6
6
  "bin": {