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 +62 -29
- package/dist/main.js +39 -15
- package/dist/main.js.map +1 -1
- package/package.json +2 -3
- package/dist/daemon-main.js +0 -868
- package/dist/daemon-main.js.map +0 -1
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
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
357
|
+
The quickest way to get started:
|
|
338
358
|
|
|
339
359
|
```sh
|
|
340
|
-
|
|
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
|
-
|
|
363
|
+
# Configure Claude Code (writes to ~/.claude/settings.json)
|
|
364
|
+
npx xc-copilot-api@latest config --claude
|
|
365
|
+
```
|
|
346
366
|
|
|
347
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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": "
|
|
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.
|
|
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
|
|
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:
|
|
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",
|
|
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
|
-
|
|
563
|
-
if (args.
|
|
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:
|
|
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({
|