xcode-copilot-server 2.0.1 → 2.1.0
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 +24 -9
- package/dist/index.js +40 -13
- package/dist/index.js.map +1 -1
- package/dist/settings-patcher.d.ts +29 -0
- package/dist/settings-patcher.js +79 -0
- package/dist/settings-patcher.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,12 +39,15 @@ npx xcode-copilot-server
|
|
|
39
39
|
xcode-copilot-server [options]
|
|
40
40
|
|
|
41
41
|
Options:
|
|
42
|
-
--port <number>
|
|
43
|
-
--proxy <provider>
|
|
44
|
-
--log-level <level>
|
|
45
|
-
--config <path>
|
|
46
|
-
--cwd <path>
|
|
47
|
-
--
|
|
42
|
+
--port <number> Port to listen on (default: 8080)
|
|
43
|
+
--proxy <provider> API format to expose: openai, anthropic (default: openai)
|
|
44
|
+
--log-level <level> Log verbosity: none, error, warning, info, debug, all (default: info)
|
|
45
|
+
--config <path> Path to config file (auto-detected from --cwd, then process cwd, else bundled)
|
|
46
|
+
--cwd <path> Working directory for Copilot sessions (default: process cwd)
|
|
47
|
+
--auto-patch Auto-patch settings.json on start, restore on exit (anthropic mode)
|
|
48
|
+
--patch-settings Patch settings.json to point to this server, then exit
|
|
49
|
+
--restore-settings Restore settings.json from backup, then exit
|
|
50
|
+
--help Show help
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
The `--proxy` flag determines which API the server exposes:
|
|
@@ -70,7 +73,15 @@ To enable tool calling, select the provider and enable "Allow tools" under "Adva
|
|
|
70
73
|
|
|
71
74
|
1. Open Xcode and go to Settings > Intelligence > Anthropic > Claude Agent
|
|
72
75
|
2. Enable Claude Agent and sign in with an API key (the key can be any random text, since the calls are proxied through the server)
|
|
73
|
-
3.
|
|
76
|
+
3. Start the server with `--auto-patch` to automatically configure `settings.json`:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
xcode-copilot-server --proxy anthropic --auto-patch
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This creates (or updates) `settings.json` at `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/` to point to the server, and restores the original file when the server shuts down. If `settings.json` already exists, a backup is saved as `settings.json.backup` and restored on exit.
|
|
83
|
+
|
|
84
|
+
Alternatively, you can manage `settings.json` yourself. Create it manually at the path above:
|
|
74
85
|
|
|
75
86
|
```json
|
|
76
87
|
{
|
|
@@ -81,9 +92,13 @@ To enable tool calling, select the provider and enable "Allow tools" under "Adva
|
|
|
81
92
|
}
|
|
82
93
|
```
|
|
83
94
|
|
|
84
|
-
Set the port to match your `--port` flag (default 8080). The auth token can be any non-empty string.
|
|
95
|
+
Set the port to match your `--port` flag (default 8080). The auth token can be any non-empty string. Then start the server without `--auto-patch`:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
xcode-copilot-server --proxy anthropic
|
|
99
|
+
```
|
|
85
100
|
|
|
86
|
-
|
|
101
|
+
You can also use `--patch-settings` and `--restore-settings` as one-shot commands to patch or restore `settings.json` without starting the server.
|
|
87
102
|
|
|
88
103
|
The tool bridge is enabled by default in Anthropic mode (`toolBridge: true` in the config). It intercepts tool calls from the Copilot session and forwards them to Xcode, so Claude Agent can read files, search code, and make edits through the IDE.
|
|
89
104
|
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { loadConfig, resolveConfigPath } from "./config.js";
|
|
|
6
6
|
import { createServer } from "./server.js";
|
|
7
7
|
import { Logger, LEVEL_PRIORITY } from "./logger.js";
|
|
8
8
|
import { providers } from "./providers/index.js";
|
|
9
|
+
import { patchSettings, restoreSettings } from "./settings-patcher.js";
|
|
9
10
|
const PACKAGE_ROOT = dirname(import.meta.dirname);
|
|
10
11
|
const DEFAULT_CONFIG_PATH = join(PACKAGE_ROOT, "config.json5");
|
|
11
12
|
const VALID_LOG_LEVELS = Object.keys(LEVEL_PRIORITY);
|
|
@@ -19,12 +20,15 @@ function isProxy(value) {
|
|
|
19
20
|
const USAGE = `Usage: xcode-copilot-server [options]
|
|
20
21
|
|
|
21
22
|
Options:
|
|
22
|
-
--port <number>
|
|
23
|
-
--proxy <provider>
|
|
24
|
-
--log-level <level>
|
|
25
|
-
--config <path>
|
|
26
|
-
--cwd <path>
|
|
27
|
-
--
|
|
23
|
+
--port <number> Port to listen on (default: 8080)
|
|
24
|
+
--proxy <provider> API format to expose: ${VALID_PROXIES.join(", ")} (default: openai)
|
|
25
|
+
--log-level <level> Log verbosity: ${VALID_LOG_LEVELS.join(", ")} (default: info)
|
|
26
|
+
--config <path> Path to config file (auto-detected from --cwd, then process cwd, else bundled)
|
|
27
|
+
--cwd <path> Working directory for Copilot sessions (default: process cwd)
|
|
28
|
+
--auto-patch Auto-patch settings.json on start, restore on exit (anthropic mode)
|
|
29
|
+
--patch-settings Patch settings.json to point to this server, then exit
|
|
30
|
+
--restore-settings Restore settings.json from backup, then exit
|
|
31
|
+
--help Show this help message`;
|
|
28
32
|
function parseCliArgs() {
|
|
29
33
|
try {
|
|
30
34
|
return parseArgs({
|
|
@@ -34,6 +38,9 @@ function parseCliArgs() {
|
|
|
34
38
|
"log-level": { type: "string", default: "info" },
|
|
35
39
|
config: { type: "string" },
|
|
36
40
|
cwd: { type: "string" },
|
|
41
|
+
"auto-patch": { type: "boolean", default: false },
|
|
42
|
+
"patch-settings": { type: "boolean", default: false },
|
|
43
|
+
"restore-settings": { type: "boolean", default: false },
|
|
37
44
|
help: { type: "boolean", default: false },
|
|
38
45
|
},
|
|
39
46
|
strict: true,
|
|
@@ -52,24 +59,32 @@ async function main() {
|
|
|
52
59
|
console.log(USAGE);
|
|
53
60
|
process.exit(0);
|
|
54
61
|
}
|
|
62
|
+
const rawLevel = values["log-level"];
|
|
63
|
+
if (!isLogLevel(rawLevel)) {
|
|
64
|
+
console.error(`Invalid log level "${rawLevel}". Valid: ${VALID_LOG_LEVELS.join(", ")}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const logLevel = rawLevel;
|
|
68
|
+
const logger = new Logger(logLevel);
|
|
55
69
|
const port = parseInt(values.port, 10);
|
|
56
70
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
57
71
|
console.error(`Invalid port "${values.port}". Must be 1-65535.`);
|
|
58
72
|
process.exit(1);
|
|
59
73
|
}
|
|
74
|
+
if (values["patch-settings"]) {
|
|
75
|
+
await patchSettings({ port, logger });
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
if (values["restore-settings"]) {
|
|
79
|
+
await restoreSettings({ logger });
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
60
82
|
const proxy = values.proxy;
|
|
61
83
|
if (!isProxy(proxy)) {
|
|
62
84
|
console.error(`Invalid proxy "${proxy}". Valid: ${VALID_PROXIES.join(", ")}`);
|
|
63
85
|
process.exit(1);
|
|
64
86
|
}
|
|
65
87
|
const provider = providers[proxy];
|
|
66
|
-
const rawLevel = values["log-level"];
|
|
67
|
-
if (!isLogLevel(rawLevel)) {
|
|
68
|
-
console.error(`Invalid log level "${rawLevel}". Valid: ${VALID_LOG_LEVELS.join(", ")}`);
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
const logLevel = rawLevel;
|
|
72
|
-
const logger = new Logger(logLevel);
|
|
73
88
|
const configPath = values.config ?? resolveConfigPath(values.cwd, process.cwd(), DEFAULT_CONFIG_PATH);
|
|
74
89
|
const config = await loadConfig(configPath, logger, proxy);
|
|
75
90
|
const cwd = values.cwd;
|
|
@@ -88,6 +103,10 @@ async function main() {
|
|
|
88
103
|
process.exit(1);
|
|
89
104
|
}
|
|
90
105
|
logger.info(`Authenticated as ${auth.login ?? "unknown"} (${auth.authType ?? "unknown"})`);
|
|
106
|
+
const autoPatch = values["auto-patch"];
|
|
107
|
+
if (autoPatch) {
|
|
108
|
+
await patchSettings({ port, logger });
|
|
109
|
+
}
|
|
91
110
|
const ctx = { service, logger, config, port };
|
|
92
111
|
const app = await createServer(ctx, provider);
|
|
93
112
|
await app.listen({ port, host: "127.0.0.1" });
|
|
@@ -97,6 +116,14 @@ async function main() {
|
|
|
97
116
|
logger.info(`Current working directory: ${service.cwd}`);
|
|
98
117
|
const shutdown = async (signal) => {
|
|
99
118
|
logger.info(`Got ${signal}, shutting down...`);
|
|
119
|
+
if (autoPatch) {
|
|
120
|
+
try {
|
|
121
|
+
await restoreSettings({ logger });
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
logger.error(`Failed to restore settings.json: ${String(err)}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
100
127
|
await app.close();
|
|
101
128
|
const stopPromise = service.stop().then(() => {
|
|
102
129
|
logger.info("Clean shutdown complete");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,SAAS,EAAkB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Logger } from "./logger.js";
|
|
2
|
+
export interface SettingsPaths {
|
|
3
|
+
dir: string;
|
|
4
|
+
file: string;
|
|
5
|
+
backup: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Settings {
|
|
8
|
+
env?: Record<string, string>;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface PatchResult {
|
|
12
|
+
patched: boolean;
|
|
13
|
+
port?: number;
|
|
14
|
+
}
|
|
15
|
+
interface BaseOptions {
|
|
16
|
+
logger: Logger;
|
|
17
|
+
paths?: SettingsPaths;
|
|
18
|
+
}
|
|
19
|
+
export interface PatchOptions extends BaseOptions {
|
|
20
|
+
port: number;
|
|
21
|
+
authToken?: string;
|
|
22
|
+
}
|
|
23
|
+
export type RestoreOptions = BaseOptions;
|
|
24
|
+
export type DetectOptions = BaseOptions;
|
|
25
|
+
export declare function defaultSettingsPaths(): SettingsPaths;
|
|
26
|
+
export declare function detectPatchState(options: DetectOptions): Promise<PatchResult>;
|
|
27
|
+
export declare function patchSettings(options: PatchOptions): Promise<void>;
|
|
28
|
+
export declare function restoreSettings(options: RestoreOptions): Promise<void>;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile, writeFile, rename, unlink, mkdir, copyFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
export function defaultSettingsPaths() {
|
|
6
|
+
const dir = join(homedir(), "Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig");
|
|
7
|
+
return {
|
|
8
|
+
dir,
|
|
9
|
+
file: join(dir, "settings.json"),
|
|
10
|
+
backup: join(dir, "settings.json.backup"),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function isSettings(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
async function readSettingsFile(path) {
|
|
17
|
+
if (!existsSync(path))
|
|
18
|
+
return null;
|
|
19
|
+
const content = await readFile(path, "utf-8");
|
|
20
|
+
const parsed = JSON.parse(content);
|
|
21
|
+
return isSettings(parsed) ? parsed : null;
|
|
22
|
+
}
|
|
23
|
+
export async function detectPatchState(options) {
|
|
24
|
+
const { logger } = options;
|
|
25
|
+
const p = options.paths ?? defaultSettingsPaths();
|
|
26
|
+
if (!existsSync(p.backup)) {
|
|
27
|
+
return { patched: false };
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const settings = await readSettingsFile(p.file);
|
|
31
|
+
const url = settings?.env?.ANTHROPIC_BASE_URL;
|
|
32
|
+
if (url) {
|
|
33
|
+
const match = /localhost:(\d+)/.exec(url);
|
|
34
|
+
if (match?.[1]) {
|
|
35
|
+
return { patched: true, port: parseInt(match[1], 10) };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
logger.warn(`Could not read settings.json to extract port: ${String(err)}`);
|
|
41
|
+
}
|
|
42
|
+
return { patched: true };
|
|
43
|
+
}
|
|
44
|
+
export async function patchSettings(options) {
|
|
45
|
+
const { logger } = options;
|
|
46
|
+
const p = options.paths ?? defaultSettingsPaths();
|
|
47
|
+
await mkdir(p.dir, { recursive: true });
|
|
48
|
+
// Only back up once so crash recovery doesn't overwrite the original.
|
|
49
|
+
if (existsSync(p.file) && !existsSync(p.backup)) {
|
|
50
|
+
await copyFile(p.file, p.backup);
|
|
51
|
+
logger.info("Backed up settings.json");
|
|
52
|
+
}
|
|
53
|
+
let settings = {};
|
|
54
|
+
try {
|
|
55
|
+
settings = await readSettingsFile(p.file) ?? {};
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
logger.warn(`Could not read settings.json, starting fresh: ${String(err)}`);
|
|
59
|
+
}
|
|
60
|
+
settings.env = {
|
|
61
|
+
...settings.env,
|
|
62
|
+
ANTHROPIC_BASE_URL: `http://localhost:${String(options.port)}`,
|
|
63
|
+
ANTHROPIC_AUTH_TOKEN: options.authToken ?? "12345",
|
|
64
|
+
};
|
|
65
|
+
await writeFile(p.file, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
66
|
+
logger.info(`Patched settings.json to point to http://localhost:${String(options.port)}`);
|
|
67
|
+
}
|
|
68
|
+
export async function restoreSettings(options) {
|
|
69
|
+
const { logger } = options;
|
|
70
|
+
const p = options.paths ?? defaultSettingsPaths();
|
|
71
|
+
if (existsSync(p.file)) {
|
|
72
|
+
await unlink(p.file);
|
|
73
|
+
}
|
|
74
|
+
if (existsSync(p.backup)) {
|
|
75
|
+
await rename(p.backup, p.file);
|
|
76
|
+
logger.info("Restored settings.json from backup");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=settings-patcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-patcher.js","sourceRoot":"","sources":["../src/settings-patcher.ts"],"names":[],"mappings":"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"}
|