xc-copilot-api 1.2.0 → 1.2.2

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
@@ -35,7 +35,7 @@ A reverse-engineered proxy for the GitHub Copilot API that exposes it as an Open
35
35
  ## Features
36
36
 
37
37
  - **OpenAI & Anthropic Compatibility**: Exposes GitHub Copilot as an OpenAI-compatible (`/v1/chat/completions`, `/v1/models`, `/v1/embeddings`) and Anthropic-compatible (`/v1/messages`) API.
38
- - **Claude Code Integration**: Easily configure and launch [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) to use Copilot as its backend with a simple command-line flag (`--claude-code`).
38
+ - **Claude Code & Codex CLI Integration**: Configure [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) or Codex CLI to use Copilot as backend with `config --claude` or `config --codex`.
39
39
  - **Usage Dashboard**: A web-based dashboard to monitor your Copilot API usage, view quotas, and see detailed statistics.
40
40
  - **Rate Limit Control**: Manage API usage with rate-limiting options (`--rate-limit`) and a waiting mechanism (`--wait`) to prevent errors from rapid requests.
41
41
  - **Manual Request Approval**: Manually approve or deny each API request for fine-grained control over usage (`--manual`).
@@ -188,10 +188,28 @@ Copilot API now uses a subcommand structure with these main commands:
188
188
 
189
189
  - `start`: Start the Copilot API server. This command will also handle authentication if needed.
190
190
  - `auth`: Run GitHub authentication flow without starting the server. This is typically used if you need to generate a token for use with the `--github-token` option, especially in non-interactive environments.
191
+ - `config`: Configure external AI tools (Claude Code, Codex CLI) to use Copilot API.
191
192
  - `check-usage`: Show your current GitHub Copilot usage and quota information directly in the terminal (no server required).
192
193
  - `debug`: Display diagnostic information including version, runtime details, file paths, and authentication status. Useful for troubleshooting and support.
193
194
 
194
- A separate **[`xc-copilot-api-daemon`](docs/daemon.md)** CLI is available for managing the server as a background daemon (install, status, restart, stop, uninstall, logs) on macOS, Linux, and Windows.
195
+ ### Running as a Background Service
196
+
197
+ Use [easy-service](https://github.com/billxc/easy-service) to run as a background service on macOS, Linux, and Windows:
198
+
199
+ ```bash
200
+ # Install easy-service
201
+ uv tool install git+https://github.com/billxc/easy-service.git
202
+
203
+ # Install and start the service
204
+ easy-service install copilot-api -- npx -y xc-copilot-api@latest start
205
+
206
+ # Manage the service
207
+ easy-service status copilot-api
208
+ easy-service logs copilot-api -f
209
+ easy-service restart copilot-api
210
+ easy-service stop copilot-api
211
+ easy-service uninstall copilot-api
212
+ ```
195
213
 
196
214
  ## Command Line Options
197
215
 
@@ -208,10 +226,16 @@ The following command line options are available for the `start` command:
208
226
  | --rate-limit | Rate limit in seconds between requests | none | -r |
209
227
  | --wait | Wait instead of error when rate limit is hit | false | -w |
210
228
  | --github-token | Provide GitHub token directly (must be generated using the `auth` subcommand) | none | -g |
211
- | --claude-code | Generate a command to launch Claude Code with Copilot API config | false | -c |
212
229
  | --show-token | Show GitHub and Copilot tokens on fetch and refresh | false | none |
213
230
  | --proxy-env | Initialize proxy from environment variables | false | none |
214
231
 
232
+ ### Config Command Options
233
+
234
+ | Option | Description | Default | Alias |
235
+ | ------- | ------------------------------------------------- | ------- | ----- |
236
+ | --claude | Configure Claude Code (`~/.claude/settings.json`) | false | -c |
237
+ | --codex | Configure Codex CLI (`~/.codex/config.toml`) | false | -x |
238
+
215
239
  ### Auth Command Options
216
240
 
217
241
  | Option | Description | Default | Alias |
@@ -328,44 +352,29 @@ The dashboard provides a user-friendly interface to view your Copilot usage data
328
352
 
329
353
  ## Using with Claude Code
330
354
 
331
- This proxy can be used to power [Claude Code](https://docs.anthropic.com/en/claude-code), an experimental conversational AI assistant for developers from Anthropic.
332
-
333
- There are two ways to configure Claude Code to use this proxy:
334
-
335
- ### Interactive Setup with `--claude-code` flag
355
+ This proxy can be used to power [Claude Code](https://docs.anthropic.com/en/claude-code).
336
356
 
337
- To get started, run the `start` command with the `--claude-code` flag:
357
+ The quickest way to get started:
338
358
 
339
359
  ```sh
340
- npx xc-copilot-api@latest start --claude-code
341
- ```
342
-
343
- You will be prompted to select a primary model and a "small, fast" model for background tasks. After selecting the models, a command will be copied to your clipboard. This command sets the necessary environment variables for Claude Code to use the proxy.
360
+ # Start the server
361
+ npx xc-copilot-api@latest start
344
362
 
345
- Paste and run this command in a new terminal to launch Claude Code.
363
+ # Configure Claude Code (writes to ~/.claude/settings.json)
364
+ npx xc-copilot-api@latest config --claude
365
+ ```
346
366
 
347
- ### Manual Configuration with `settings.json`
367
+ This merges the required `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN` into your existing settings without overwriting other configuration. A backup of your original config is saved as `settings.json.bak`.
348
368
 
349
- Alternatively, you can configure Claude Code by creating a `.claude/settings.json` file in your project's root directory. This file should contain the environment variables needed by Claude Code. This way you don't need to run the interactive setup every time.
369
+ > **Note:** Copilot API natively understands Claude model names (e.g. `claude-sonnet-4.5`, `opus[1m]`), so you don't need to set `ANTHROPIC_MODEL` or other model environment variables they just work.
350
370
 
351
- Here is an example `.claude/settings.json` file:
371
+ If you prefer manual configuration, add the following to your `~/.claude/settings.json`:
352
372
 
353
373
  ```json
354
374
  {
355
375
  "env": {
356
376
  "ANTHROPIC_BASE_URL": "http://localhost:4141",
357
- "ANTHROPIC_AUTH_TOKEN": "dummy",
358
- "ANTHROPIC_MODEL": "gpt-4.1",
359
- "ANTHROPIC_DEFAULT_SONNET_MODEL": "gpt-4.1",
360
- "ANTHROPIC_SMALL_FAST_MODEL": "gpt-4.1",
361
- "ANTHROPIC_DEFAULT_HAIKU_MODEL": "gpt-4.1",
362
- "DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
363
- "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
364
- },
365
- "permissions": {
366
- "deny": [
367
- "WebSearch"
368
- ]
377
+ "ANTHROPIC_AUTH_TOKEN": "Powered by xc copilot"
369
378
  }
370
379
  }
371
380
  ```
@@ -374,6 +383,30 @@ You can find more options here: [Claude Code settings](https://docs.anthropic.co
374
383
 
375
384
  You can also read more about IDE integration here: [Add Claude Code to your IDE](https://docs.anthropic.com/en/docs/claude-code/ide-integrations)
376
385
 
386
+ ## Using with Codex CLI
387
+
388
+ ```sh
389
+ # Start the server
390
+ npx xc-copilot-api@latest start
391
+
392
+ # Configure Codex CLI (writes to ~/.codex/config.toml)
393
+ npx xc-copilot-api@latest config --codex
394
+ ```
395
+
396
+ A backup of your original config is saved as `config.toml.bak`.
397
+
398
+ If you prefer manual configuration, add the following to your `~/.codex/config.toml`:
399
+
400
+ ```toml
401
+ model = "gpt-5.4"
402
+ model_provider = "copilot-api"
403
+
404
+ [model_providers.copilot-api]
405
+ name = "copilot-api"
406
+ base_url = "http://localhost:4141/v1"
407
+ wire_api = "responses"
408
+ ```
409
+
377
410
  ## Running from Source
378
411
 
379
412
  The project can be run from source in several ways:
package/dist/main.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { defineCommand, runMain } from "citty";
3
+ import consola from "consola";
4
+ import fs, { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
3
5
  import os, { homedir } from "node:os";
4
6
  import path, { join } from "node:path";
5
- import consola from "consola";
6
- import fs, { mkdir, readFile, writeFile } from "node:fs/promises";
7
7
  import { randomUUID } from "node:crypto";
8
8
  import { serve } from "srvx";
9
9
  import { getProxyForUrl } from "proxy-from-env";
@@ -17,7 +17,7 @@ import "hono/logger";
17
17
 
18
18
  //#region package.json
19
19
  var name = "xc-copilot-api";
20
- var version = "1.2.0";
20
+ var version = "1.2.2";
21
21
  var description = "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code and Codex";
22
22
  var keywords = [
23
23
  "proxy",
@@ -32,10 +32,7 @@ var repository = {
32
32
  };
33
33
  var author = "Xiaochen <wxc9312@gmail.com>";
34
34
  var type = "module";
35
- var bin = {
36
- "xc-copilot-api": "./dist/main.js",
37
- "xc-copilot-api-daemon": "./dist/daemon-main.js"
38
- };
35
+ var bin = { "xc-copilot-api": "./dist/main.js" };
39
36
  var files = ["dist"];
40
37
  var scripts = {
41
38
  "build": "tsdown",
@@ -465,7 +462,14 @@ const checkUsage = defineCommand({
465
462
 
466
463
  //#endregion
467
464
  //#region src/config.ts
468
- async function configureClaude() {
465
+ async function backupFile(filePath) {
466
+ try {
467
+ const backupPath = `${filePath}.bak`;
468
+ await copyFile(filePath, backupPath);
469
+ consola.info(`Backup saved: ${backupPath}`);
470
+ } catch {}
471
+ }
472
+ async function configureClaude(port) {
469
473
  const configDir = join(homedir(), ".claude");
470
474
  const configPath = join(configDir, "settings.json");
471
475
  await mkdir(configDir, { recursive: true });
@@ -484,11 +488,12 @@ async function configureClaude() {
484
488
  ...existing,
485
489
  env: {
486
490
  ...existingEnv,
487
- ANTHROPIC_BASE_URL: "http://localhost:4141",
491
+ ANTHROPIC_BASE_URL: `http://localhost:${port}`,
488
492
  ANTHROPIC_AUTH_TOKEN: "Powered by xc copilot"
489
493
  },
490
494
  model: "opus[1m]"
491
495
  };
496
+ await backupFile(configPath);
492
497
  await writeFile(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
493
498
  consola.success(`Claude Code configured: ${configPath}`);
494
499
  }
@@ -516,7 +521,7 @@ function setTomlSection(content, header, body) {
516
521
  if (pattern.test(content)) return content.replace(pattern, block);
517
522
  return content.trimEnd() + "\n\n" + block;
518
523
  }
519
- async function configureCodex() {
524
+ async function configureCodex(port) {
520
525
  const configDir = join(homedir(), ".codex");
521
526
  const configPath = join(configDir, "config.toml");
522
527
  await mkdir(configDir, { recursive: true });
@@ -531,7 +536,8 @@ async function configureCodex() {
531
536
  }
532
537
  content = setTomlTopLevelKey(content, "model", "gpt-5.4");
533
538
  content = setTomlTopLevelKey(content, "model_provider", "copilot-api");
534
- content = setTomlSection(content, "model_providers.copilot-api", "name = \"copilot-api\"\nbase_url = \"http://localhost:4141/v1\"\nwire_api = \"responses\"");
539
+ content = setTomlSection(content, "model_providers.copilot-api", `name = "copilot-api"\nbase_url = "http://localhost:${port}/v1"\nwire_api = "responses"`);
540
+ await backupFile(configPath);
535
541
  await writeFile(configPath, content, "utf-8");
536
542
  consola.success(`Codex CLI configured: ${configPath}`);
537
543
  }
@@ -552,6 +558,12 @@ const config = defineCommand({
552
558
  type: "boolean",
553
559
  default: false,
554
560
  description: "Configure Codex CLI (~/.codex/config.toml)"
561
+ },
562
+ port: {
563
+ alias: "p",
564
+ type: "string",
565
+ default: "4141",
566
+ description: "Port the Copilot API server listens on"
555
567
  }
556
568
  },
557
569
  async run({ args }) {
@@ -559,8 +571,9 @@ const config = defineCommand({
559
571
  consola.error("Specify at least one: --claude or --codex");
560
572
  process.exit(1);
561
573
  }
562
- if (args.claude) await configureClaude();
563
- if (args.codex) await configureCodex();
574
+ const port = Number.parseInt(args.port, 10);
575
+ if (args.claude) await configureClaude(port);
576
+ if (args.codex) await configureCodex(port);
564
577
  }
565
578
  });
566
579
 
@@ -1882,15 +1895,25 @@ function tryParsePayload(bodyText) {
1882
1895
  }
1883
1896
  }
1884
1897
  const createResponses = async (bodyText, requestHeaders) => {
1898
+ const filtered = filterUnsupportedTools(bodyText);
1885
1899
  return postCopilotPassthrough({
1886
1900
  path: "/responses",
1887
- body: bodyText,
1901
+ body: filtered,
1888
1902
  requestHeaders,
1889
1903
  initiator: "user",
1890
1904
  errorMessage: "Failed to create responses",
1891
1905
  throwOnError: true
1892
1906
  });
1893
1907
  };
1908
+ function filterUnsupportedTools(bodyText) {
1909
+ const payload = tryParsePayload(bodyText);
1910
+ if (!payload?.tools || !Array.isArray(payload.tools)) return bodyText;
1911
+ const UNSUPPORTED_TOOL_TYPES = new Set(["image_generation"]);
1912
+ const filtered = payload.tools.filter((tool) => !UNSUPPORTED_TOOL_TYPES.has(tool.type ?? ""));
1913
+ if (filtered.length === payload.tools.length) return bodyText;
1914
+ payload.tools = filtered;
1915
+ return JSON.stringify(payload);
1916
+ }
1894
1917
  function getForwardHeaders(headers) {
1895
1918
  return filterResponseHeaders(headers, RESPONSE_HEADERS_TO_FORWARD);
1896
1919
  }
@@ -1996,7 +2019,8 @@ async function runServer(options) {
1996
2019
  consola.box(`🌐 Usage Viewer: https://billxc.github.io/copilot-api?endpoint=${serverUrl}/usage`);
1997
2020
  serve({
1998
2021
  fetch: server.fetch,
1999
- port: options.port
2022
+ port: options.port,
2023
+ idleTimeout: 255
2000
2024
  });
2001
2025
  }
2002
2026
  const start = defineCommand({