skalpel 2.0.11 → 2.0.12

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/README.md CHANGED
@@ -26,9 +26,9 @@ npx skalpel --api-key sk-skalpel-YOUR_KEY --auto
26
26
  ```
27
27
 
28
28
  This will:
29
- - Start the local proxy on ports 18100 (Anthropic) and 18101 (OpenAI)
29
+ - Start the local proxy on port 18100 (Anthropic)
30
30
  - Detect coding agents on your machine
31
- - Configure Claude Code and Codex agents automatically
31
+ - Configure Claude Code automatically
32
32
  - Set shell environment variables in your `.bashrc`/`.zshrc`
33
33
  - Begin optimizing API traffic immediately
34
34
 
@@ -68,7 +68,6 @@ Environment variables are added for tools that read them directly:
68
68
  ```bash
69
69
  # BEGIN SKALPEL PROXY - do not edit manually
70
70
  export ANTHROPIC_BASE_URL="http://localhost:18100"
71
- export OPENAI_BASE_URL="http://localhost:18101"
72
71
  # END SKALPEL PROXY
73
72
  ```
74
73
 
@@ -127,10 +126,6 @@ The proxy adds these headers to every request forwarded to the Skalpel backend:
127
126
 
128
127
  The original `x-api-key` header (your Anthropic key) is forwarded as-is.
129
128
 
130
- ## Codex Support
131
-
132
- Skalpel also supports OpenAI Codex on port 18101. The same `--auto` flow detects and configures both agents if present.
133
-
134
129
  ## SDK Integration
135
130
 
136
131
  For programmatic use in your own applications:
package/dist/cli/index.js CHANGED
@@ -250,35 +250,8 @@ function detectClaudeCode() {
250
250
  }
251
251
  return agent;
252
252
  }
253
- function detectCodex() {
254
- const agent = {
255
- name: "codex",
256
- installed: false,
257
- version: null,
258
- configPath: null
259
- };
260
- const binaryPath = tryExec(`${whichCommand()} codex`);
261
- const hasBinary = binaryPath !== null && binaryPath.length > 0;
262
- const codexConfigDir = process.platform === "win32" ? path3.join(os.homedir(), "AppData", "Roaming", "codex") : path3.join(os.homedir(), ".codex");
263
- const hasConfigDir = fs3.existsSync(codexConfigDir);
264
- agent.installed = hasBinary || hasConfigDir;
265
- if (hasBinary) {
266
- const versionOutput = tryExec("codex --version");
267
- if (versionOutput) {
268
- const match = versionOutput.match(/(\d+\.\d+[\w.-]*)/);
269
- agent.version = match ? match[1] : versionOutput;
270
- }
271
- }
272
- const configFile = path3.join(codexConfigDir, "config.toml");
273
- if (fs3.existsSync(configFile)) {
274
- agent.configPath = configFile;
275
- } else if (hasConfigDir) {
276
- agent.configPath = configFile;
277
- }
278
- return agent;
279
- }
280
253
  function detectAgents() {
281
- return [detectClaudeCode(), detectCodex()];
254
+ return [detectClaudeCode()];
282
255
  }
283
256
 
284
257
  // src/cli/doctor.ts
@@ -596,7 +569,6 @@ var DEFAULTS = {
596
569
  remoteBaseUrl: "https://api.skalpel.ai",
597
570
  anthropicDirectUrl: "https://api.anthropic.com",
598
571
  anthropicPort: 18100,
599
- openaiPort: 18101,
600
572
  logLevel: "info",
601
573
  logFile: "~/.skalpel/logs/proxy.log",
602
574
  pidFile: "~/.skalpel/proxy.pid",
@@ -615,7 +587,6 @@ function loadConfig(configPath) {
615
587
  remoteBaseUrl: fileConfig.remoteBaseUrl ?? DEFAULTS.remoteBaseUrl,
616
588
  anthropicDirectUrl: fileConfig.anthropicDirectUrl ?? DEFAULTS.anthropicDirectUrl,
617
589
  anthropicPort: fileConfig.anthropicPort ?? DEFAULTS.anthropicPort,
618
- openaiPort: fileConfig.openaiPort ?? DEFAULTS.openaiPort,
619
590
  logLevel: fileConfig.logLevel ?? DEFAULTS.logLevel,
620
591
  logFile: expandHome(fileConfig.logFile ?? DEFAULTS.logFile),
621
592
  pidFile: expandHome(fileConfig.pidFile ?? DEFAULTS.pidFile),
@@ -749,8 +720,6 @@ function generateLaunchdPlist(config, proxyRunnerPath) {
749
720
  <dict>
750
721
  <key>SKALPEL_ANTHROPIC_PORT</key>
751
722
  <string>${config.anthropicPort}</string>
752
- <key>SKALPEL_OPENAI_PORT</key>
753
- <string>${config.openaiPort}</string>
754
723
  </dict>
755
724
  </dict>
756
725
  </plist>`;
@@ -766,7 +735,6 @@ ExecStart=${process.execPath} ${proxyRunnerPath}
766
735
  Restart=always
767
736
  RestartSec=5
768
737
  Environment=SKALPEL_ANTHROPIC_PORT=${config.anthropicPort}
769
- Environment=SKALPEL_OPENAI_PORT=${config.openaiPort}
770
738
 
771
739
  [Install]
772
740
  WantedBy=default.target`;
@@ -1026,47 +994,11 @@ function configureClaudeCode(agent, proxyConfig) {
1026
994
  config.env.ANTHROPIC_BASE_URL = `http://localhost:${proxyConfig.anthropicPort}`;
1027
995
  fs9.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
1028
996
  }
1029
- function readTomlFile(filePath) {
1030
- try {
1031
- return fs9.readFileSync(filePath, "utf-8");
1032
- } catch {
1033
- return "";
1034
- }
1035
- }
1036
- function setTomlKey(content, key, value) {
1037
- const pattern = new RegExp(`^${key.replace(".", "\\.")}\\s*=.*$`, "m");
1038
- const line = `${key} = "${value}"`;
1039
- if (pattern.test(content)) {
1040
- return content.replace(pattern, line);
1041
- }
1042
- const sectionMatch = content.match(/^\[/m);
1043
- if (sectionMatch && sectionMatch.index !== void 0) {
1044
- return content.slice(0, sectionMatch.index) + line + "\n" + content.slice(sectionMatch.index);
1045
- }
1046
- const separator = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
1047
- return content + separator + line + "\n";
1048
- }
1049
- function removeTomlKey(content, key) {
1050
- const pattern = new RegExp(`^${key.replace(".", "\\.")}\\s*=.*\\n?`, "gm");
1051
- return content.replace(pattern, "");
1052
- }
1053
- function configureCodex(agent, proxyConfig) {
1054
- const configDir = process.platform === "win32" ? path10.join(os7.homedir(), "AppData", "Roaming", "codex") : path10.join(os7.homedir(), ".codex");
1055
- const configPath = agent.configPath ?? path10.join(configDir, "config.toml");
1056
- ensureDir(path10.dirname(configPath));
1057
- createBackup(configPath);
1058
- let content = readTomlFile(configPath);
1059
- content = setTomlKey(content, "openai_base_url", `http://localhost:${proxyConfig.openaiPort}`);
1060
- fs9.writeFileSync(configPath, content);
1061
- }
1062
997
  function configureAgent(agent, proxyConfig) {
1063
998
  switch (agent.name) {
1064
999
  case "claude-code":
1065
1000
  configureClaudeCode(agent, proxyConfig);
1066
1001
  break;
1067
- case "codex":
1068
- configureCodex(agent, proxyConfig);
1069
- break;
1070
1002
  }
1071
1003
  }
1072
1004
  function unconfigureClaudeCode(agent) {
@@ -1089,27 +1021,11 @@ function unconfigureClaudeCode(agent) {
1089
1021
  fs9.unlinkSync(backupPath);
1090
1022
  }
1091
1023
  }
1092
- function unconfigureCodex(agent) {
1093
- const configDir = process.platform === "win32" ? path10.join(os7.homedir(), "AppData", "Roaming", "codex") : path10.join(os7.homedir(), ".codex");
1094
- const configPath = agent.configPath ?? path10.join(configDir, "config.toml");
1095
- if (fs9.existsSync(configPath)) {
1096
- let content = readTomlFile(configPath);
1097
- content = removeTomlKey(content, "openai_base_url");
1098
- fs9.writeFileSync(configPath, content);
1099
- }
1100
- const backupPath = `${configPath}.skalpel-backup`;
1101
- if (fs9.existsSync(backupPath)) {
1102
- fs9.unlinkSync(backupPath);
1103
- }
1104
- }
1105
1024
  function unconfigureAgent(agent) {
1106
1025
  switch (agent.name) {
1107
1026
  case "claude-code":
1108
1027
  unconfigureClaudeCode(agent);
1109
1028
  break;
1110
- case "codex":
1111
- unconfigureCodex(agent);
1112
- break;
1113
1029
  }
1114
1030
  }
1115
1031
 
@@ -1145,7 +1061,6 @@ function generateUnixBlock(proxyConfig) {
1145
1061
  return [
1146
1062
  BEGIN_MARKER,
1147
1063
  `export ANTHROPIC_BASE_URL="http://localhost:${proxyConfig.anthropicPort}"`,
1148
- `export OPENAI_BASE_URL="http://localhost:${proxyConfig.openaiPort}"`,
1149
1064
  END_MARKER
1150
1065
  ].join("\n");
1151
1066
  }
@@ -1153,7 +1068,6 @@ function generatePowerShellBlock(proxyConfig) {
1153
1068
  return [
1154
1069
  PS_BEGIN_MARKER,
1155
1070
  `$env:ANTHROPIC_BASE_URL = "http://localhost:${proxyConfig.anthropicPort}"`,
1156
- `$env:OPENAI_BASE_URL = "http://localhost:${proxyConfig.openaiPort}"`,
1157
1071
  PS_END_MARKER
1158
1072
  ].join("\n");
1159
1073
  }
@@ -1268,7 +1182,7 @@ async function runStart() {
1268
1182
  }
1269
1183
  if (isServiceInstalled()) {
1270
1184
  startService();
1271
- print5(` Skalpel proxy started via system service on ports ${config.anthropicPort} and ${config.openaiPort}`);
1185
+ print5(` Skalpel proxy started via system service on port ${config.anthropicPort}`);
1272
1186
  configureAgentsForProxy(config);
1273
1187
  return;
1274
1188
  }
@@ -1279,7 +1193,7 @@ async function runStart() {
1279
1193
  stdio: "ignore"
1280
1194
  });
1281
1195
  child.unref();
1282
- print5(` Skalpel proxy started on ports ${config.anthropicPort} and ${config.openaiPort}`);
1196
+ print5(` Skalpel proxy started on port ${config.anthropicPort}`);
1283
1197
  configureAgentsForProxy(config);
1284
1198
  }
1285
1199
  function configureAgentsForProxy(config) {
@@ -1341,8 +1255,7 @@ function getProxyStatus(config) {
1341
1255
  running: pid !== null,
1342
1256
  pid,
1343
1257
  uptime: proxyStartTime > 0 ? Date.now() - proxyStartTime : 0,
1344
- anthropicPort: config.anthropicPort,
1345
- openaiPort: config.openaiPort
1258
+ anthropicPort: config.anthropicPort
1346
1259
  };
1347
1260
  }
1348
1261
 
@@ -1438,7 +1351,6 @@ async function runStatus() {
1438
1351
  }
1439
1352
  }
1440
1353
  print7(` Anthropic: port ${status.anthropicPort}`);
1441
- print7(` OpenAI: port ${status.openaiPort}`);
1442
1354
  print7(` Config: ${config.configFile}`);
1443
1355
  print7("");
1444
1356
  }
@@ -1502,7 +1414,6 @@ async function runConfig(subcommand, args) {
1502
1414
  "apiKey",
1503
1415
  "remoteBaseUrl",
1504
1416
  "anthropicPort",
1505
- "openaiPort",
1506
1417
  "logLevel",
1507
1418
  "logFile",
1508
1419
  "pidFile"
@@ -1513,7 +1424,7 @@ async function runConfig(subcommand, args) {
1513
1424
  process.exit(1);
1514
1425
  }
1515
1426
  const updated = { ...config };
1516
- if (key === "anthropicPort" || key === "openaiPort") {
1427
+ if (key === "anthropicPort") {
1517
1428
  const parsed = parseInt(value, 10);
1518
1429
  if (isNaN(parsed) || parsed < 1 || parsed > 65535) {
1519
1430
  print9(` Invalid port number: ${value}`);
@@ -1679,7 +1590,6 @@ async function runWizard(options) {
1679
1590
  print11("");
1680
1591
  let agentsToConfigure = installedAgents.filter((a) => {
1681
1592
  if (options?.skipClaude && a.name === "claude-code") return false;
1682
- if (options?.skipCodex && a.name === "codex") return false;
1683
1593
  return true;
1684
1594
  });
1685
1595
  if (agentsToConfigure.length > 0 && !isAuto) {
@@ -1726,19 +1636,6 @@ async function runWizard(options) {
1726
1636
  print11(` [!] Proxy not responding yet. It may take a moment to start.`);
1727
1637
  print11(' Run "npx skalpel status" to check later, or "npx skalpel start" to start manually.');
1728
1638
  }
1729
- try {
1730
- const controller = new AbortController();
1731
- const timeout = setTimeout(() => controller.abort(), 3e3);
1732
- const healthUrl = `http://localhost:${proxyConfig.openaiPort}/health`;
1733
- const res = await fetch(healthUrl, { signal: controller.signal });
1734
- clearTimeout(timeout);
1735
- if (res.ok) {
1736
- print11(` [+] OpenAI proxy (port ${proxyConfig.openaiPort}): healthy`);
1737
- } else {
1738
- print11(` [!] OpenAI proxy (port ${proxyConfig.openaiPort}): HTTP ${res.status}`);
1739
- }
1740
- } catch {
1741
- }
1742
1639
  print11("");
1743
1640
  print11(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1744
1641
  print11("");
@@ -1747,7 +1644,7 @@ async function runWizard(options) {
1747
1644
  if (agentsToConfigure.length > 0) {
1748
1645
  print11(" Configured agents: " + agentsToConfigure.map((a) => a.name).join(", "));
1749
1646
  }
1750
- print11(" Proxy ports: Anthropic=" + proxyConfig.anthropicPort + ", OpenAI=" + proxyConfig.openaiPort);
1647
+ print11(" Proxy port: Anthropic=" + proxyConfig.anthropicPort);
1751
1648
  print11("");
1752
1649
  print11(' Run "npx skalpel status" to check proxy status');
1753
1650
  print11(' Run "npx skalpel doctor" for a full health check');
@@ -1903,7 +1800,7 @@ function clearNpxCache() {
1903
1800
  var require3 = createRequire2(import.meta.url);
1904
1801
  var pkg2 = require3("../../package.json");
1905
1802
  var program = new Command();
1906
- program.name("skalpel").description("Skalpel AI CLI \u2014 optimize your OpenAI and Anthropic API calls").version(pkg2.version).option("--api-key <key>", "Skalpel API key for non-interactive setup").option("--auto", "Run setup in non-interactive mode").option("--skip-claude", "Skip Claude Code configuration").option("--skip-codex", "Skip Codex configuration").action((options) => runWizard(options));
1803
+ program.name("skalpel").description("Skalpel AI CLI \u2014 optimize your OpenAI and Anthropic API calls").version(pkg2.version).option("--api-key <key>", "Skalpel API key for non-interactive setup").option("--auto", "Run setup in non-interactive mode").option("--skip-claude", "Skip Claude Code configuration").action((options) => runWizard(options));
1907
1804
  program.command("init").description("Initialize Skalpel in your project").action(runInit);
1908
1805
  program.command("doctor").description("Check Skalpel configuration health").action(runDoctor);
1909
1806
  program.command("benchmark").description("Run performance benchmarks").action(runBenchmark);