opencode-with-claude 1.1.1 → 1.1.6
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/dist/index.d.ts +5 -2
- package/dist/index.js +1 -52
- package/package.json +20 -19
- package/dist/logger.d.ts +0 -7
- package/dist/logger.js +0 -8
- package/dist/proxy.d.ts +0 -29
- package/dist/proxy.js +0 -91
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Plugin } from '@opencode-ai/plugin';
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* OpenCode plugin that manages the Claude Max proxy lifecycle.
|
|
4
5
|
*
|
|
@@ -9,4 +10,6 @@ import type { Plugin } from "@opencode-ai/plugin";
|
|
|
9
10
|
* 4. Returns a `config` hook that injects the proxy's baseURL into
|
|
10
11
|
* the Anthropic provider so each opencode instance gets its own proxy.
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
declare const ClaudeMaxPlugin: Plugin;
|
|
14
|
+
|
|
15
|
+
export { ClaudeMaxPlugin };
|
package/dist/index.js
CHANGED
|
@@ -1,52 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { registerCleanup, startProxy } from "./proxy.js";
|
|
3
|
-
/**
|
|
4
|
-
* OpenCode plugin that manages the Claude Max proxy lifecycle.
|
|
5
|
-
*
|
|
6
|
-
* On init:
|
|
7
|
-
* 1. Verifies the Claude CLI is installed and authenticated
|
|
8
|
-
* 2. Starts the proxy (port 3456, or falls back to a random port if in use)
|
|
9
|
-
* 3. Registers cleanup handlers to stop the proxy on exit
|
|
10
|
-
* 4. Returns a `config` hook that injects the proxy's baseURL into
|
|
11
|
-
* the Anthropic provider so each opencode instance gets its own proxy.
|
|
12
|
-
*/
|
|
13
|
-
export const ClaudeMaxPlugin = async ({ client, $, directory }) => {
|
|
14
|
-
const log = createLogger(client);
|
|
15
|
-
// 1. Verify Claude CLI is installed
|
|
16
|
-
try {
|
|
17
|
-
await $ `claude --version`;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
throw new Error("Claude Code CLI not found. Install it with: npm install -g @anthropic-ai/claude-code");
|
|
21
|
-
}
|
|
22
|
-
// 2. Verify authentication
|
|
23
|
-
let authOutput;
|
|
24
|
-
try {
|
|
25
|
-
authOutput = await $ `claude auth status`.text();
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
throw new Error("Failed to check Claude auth status. Run: claude login");
|
|
29
|
-
}
|
|
30
|
-
if (!authOutput.includes('"loggedIn": true')) {
|
|
31
|
-
throw new Error("Claude not authenticated. Run: claude login");
|
|
32
|
-
}
|
|
33
|
-
await log("info", "Claude authentication verified");
|
|
34
|
-
// 3. Start the proxy
|
|
35
|
-
const port = parseInt(process.env.CLAUDE_PROXY_PORT || "", 10) || undefined;
|
|
36
|
-
await log("info", "Starting Claude Max proxy...");
|
|
37
|
-
const proxy = await startProxy({ port, log });
|
|
38
|
-
const baseURL = `http://127.0.0.1:${proxy.port}`;
|
|
39
|
-
await log("info", `Claude Max proxy ready at ${baseURL}`);
|
|
40
|
-
// 4. Register cleanup handlers
|
|
41
|
-
registerCleanup(proxy);
|
|
42
|
-
// 5. Configure the Anthropic provider to route through the proxy
|
|
43
|
-
return {
|
|
44
|
-
async config(input) {
|
|
45
|
-
input.provider ??= {};
|
|
46
|
-
input.provider.anthropic ??= {};
|
|
47
|
-
input.provider.anthropic.options ??= {};
|
|
48
|
-
input.provider.anthropic.options.baseURL = baseURL;
|
|
49
|
-
input.provider.anthropic.options.apiKey = "claude-max-proxy";
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
};
|
|
1
|
+
function l(n){return(t,o)=>n.app.log({body:{service:"opencode-with-claude",level:t,message:o}})}import{startProxyServer as d}from"opencode-claude-max-proxy";var y=process.platform==="win32",f=3456;async function u(n){let{port:t=f,log:o}=n,e=console.error;console.error=(...r)=>{let a=r.map(String).join(" ");if(a.startsWith("[PROXY]")){o("debug",a);return}e.apply(console,r)};let c=async r=>{try{return await d({port:r,host:"127.0.0.1",silent:!0})}catch(a){if(r!==0&&a instanceof Error&&"code"in a&&a.code==="EADDRINUSE")return await o("info",`Port ${r} in use, starting on a random port instead...`),d({port:0,host:"127.0.0.1",silent:!0});throw a}},i;try{i=await c(t)}catch(r){throw console.error=e,r}let s=i.server.address().port;return await o("info",`Claude Max proxy running on port ${s}`),{port:s,close:async()=>{console.error=e,await i.close()}}}function g(n){let t=!1,o=()=>{t||(t=!0,n.close())};process.on("exit",o),process.on("SIGINT",o),y||process.on("SIGTERM",o)}var v=async({client:n,$:t,directory:o})=>{let e=l(n);try{await t`claude --version`}catch{throw new Error("Claude Code CLI not found. Install it with: npm install -g @anthropic-ai/claude-code")}let c;try{c=await t`claude auth status`.text()}catch{throw new Error("Failed to check Claude auth status. Run: claude login")}if(!c.includes('"loggedIn": true'))throw new Error("Claude not authenticated. Run: claude login");await e("info","Claude authentication verified");let i=parseInt(process.env.CLAUDE_PROXY_PORT||"",10)||void 0;await e("info","Starting Claude Max proxy...");let p=await u({port:i,log:e}),s=`http://127.0.0.1:${p.port}`;return await e("info",`Claude Max proxy ready at ${s}`),g(p),{async config(r){r.provider??={},r.provider.anthropic??={},r.provider.anthropic.options??={},r.provider.anthropic.options.baseURL=s,r.provider.anthropic.options.apiKey="claude-max-proxy"}}};export{v as ClaudeMaxPlugin};
|
package/package.json
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-with-claude",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
"url": "https://github.com/ianjwhite99/opencode-with-claude.git"
|
|
7
|
-
},
|
|
3
|
+
"description": "OpenCode plugin to use your Claude Max subscription via local proxy",
|
|
4
|
+
"version": "1.1.6",
|
|
5
|
+
"type": "module",
|
|
8
6
|
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"opencode-claude-max-proxy": "^1.17.0"
|
|
10
|
+
},
|
|
9
11
|
"devDependencies": {
|
|
10
12
|
"@opencode-ai/plugin": "^1.3.0",
|
|
11
13
|
"@types/node": "^25.5.0",
|
|
12
|
-
"
|
|
14
|
+
"tsup": "^8.4.0",
|
|
15
|
+
"typescript": "^6.0.2"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup src/index.ts --format esm --dts --clean --minify",
|
|
19
|
+
"test": "./test/run.sh",
|
|
20
|
+
"test:clean": "./test/run.sh --clean",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
13
22
|
},
|
|
14
|
-
"description": "OpenCode plugin to use your Claude Max subscription via local proxy",
|
|
15
23
|
"files": [
|
|
16
24
|
"dist"
|
|
17
25
|
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/ianjwhite99/opencode-with-claude.git"
|
|
29
|
+
},
|
|
18
30
|
"keywords": [
|
|
19
31
|
"opencode",
|
|
20
32
|
"opencode-plugin",
|
|
@@ -22,16 +34,5 @@
|
|
|
22
34
|
"claude-max",
|
|
23
35
|
"proxy"
|
|
24
36
|
],
|
|
25
|
-
"license": "MIT"
|
|
26
|
-
"scripts": {
|
|
27
|
-
"build": "tsc",
|
|
28
|
-
"test": "./test/run.sh",
|
|
29
|
-
"test:clean": "./test/run.sh --clean",
|
|
30
|
-
"prepublishOnly": "npm run build"
|
|
31
|
-
},
|
|
32
|
-
"type": "module",
|
|
33
|
-
"types": "dist/index.d.ts",
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"opencode-claude-max-proxy": "^1.15.0"
|
|
36
|
-
}
|
|
37
|
+
"license": "MIT"
|
|
37
38
|
}
|
package/dist/logger.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
|
-
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
3
|
-
export type LogFn = (level: LogLevel, message: string) => Promise<unknown>;
|
|
4
|
-
/**
|
|
5
|
-
* Create a logger bound to the plugin's client.
|
|
6
|
-
*/
|
|
7
|
-
export declare function createLogger(client: Parameters<Plugin>[0]["client"]): LogFn;
|
package/dist/logger.js
DELETED
package/dist/proxy.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { LogFn } from "./logger.js";
|
|
2
|
-
export interface StartProxyOptions {
|
|
3
|
-
port?: number;
|
|
4
|
-
log: LogFn;
|
|
5
|
-
}
|
|
6
|
-
export interface ProxyHandle {
|
|
7
|
-
port: number;
|
|
8
|
-
close(): Promise<void>;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Start the Claude Max proxy using the programmatic API.
|
|
12
|
-
*
|
|
13
|
-
* Tries the preferred port first (default 3456). If that port is already
|
|
14
|
-
* in use, falls back to port 0 so the OS assigns a free port. This keeps
|
|
15
|
-
* the port predictable for single-instance users while allowing multiple
|
|
16
|
-
* opencode instances to coexist without conflicts.
|
|
17
|
-
*
|
|
18
|
-
* The upstream proxy unconditionally writes `[PROXY]` lines to
|
|
19
|
-
* console.error, so we patch it for the duration of the call and
|
|
20
|
-
* redirect those messages through the plugin logger instead.
|
|
21
|
-
*/
|
|
22
|
-
export declare function startProxy(opts: StartProxyOptions): Promise<ProxyHandle>;
|
|
23
|
-
/**
|
|
24
|
-
* Register cross-platform cleanup handlers that stop the proxy on exit.
|
|
25
|
-
*
|
|
26
|
-
* - `exit` and `SIGINT` work on all platforms.
|
|
27
|
-
* - `SIGTERM` is only available on POSIX systems.
|
|
28
|
-
*/
|
|
29
|
-
export declare function registerCleanup(proxy: ProxyHandle): void;
|
package/dist/proxy.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { startProxyServer } from "opencode-claude-max-proxy";
|
|
2
|
-
const IS_WINDOWS = process.platform === "win32";
|
|
3
|
-
const DEFAULT_PORT = 3456;
|
|
4
|
-
/**
|
|
5
|
-
* Start the Claude Max proxy using the programmatic API.
|
|
6
|
-
*
|
|
7
|
-
* Tries the preferred port first (default 3456). If that port is already
|
|
8
|
-
* in use, falls back to port 0 so the OS assigns a free port. This keeps
|
|
9
|
-
* the port predictable for single-instance users while allowing multiple
|
|
10
|
-
* opencode instances to coexist without conflicts.
|
|
11
|
-
*
|
|
12
|
-
* The upstream proxy unconditionally writes `[PROXY]` lines to
|
|
13
|
-
* console.error, so we patch it for the duration of the call and
|
|
14
|
-
* redirect those messages through the plugin logger instead.
|
|
15
|
-
*/
|
|
16
|
-
export async function startProxy(opts) {
|
|
17
|
-
const { port = DEFAULT_PORT, log } = opts;
|
|
18
|
-
const origError = console.error;
|
|
19
|
-
console.error = (...args) => {
|
|
20
|
-
const msg = args.map(String).join(" ");
|
|
21
|
-
if (msg.startsWith("[PROXY]")) {
|
|
22
|
-
void log("debug", msg);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
origError.apply(console, args);
|
|
26
|
-
};
|
|
27
|
-
const attempt = async (p) => {
|
|
28
|
-
try {
|
|
29
|
-
return await startProxyServer({
|
|
30
|
-
port: p,
|
|
31
|
-
host: "127.0.0.1",
|
|
32
|
-
silent: true,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
if (p !== 0 &&
|
|
37
|
-
err instanceof Error &&
|
|
38
|
-
"code" in err &&
|
|
39
|
-
err.code === "EADDRINUSE") {
|
|
40
|
-
await log("info", `Port ${p} in use, starting on a random port instead...`);
|
|
41
|
-
return startProxyServer({
|
|
42
|
-
port: 0,
|
|
43
|
-
host: "127.0.0.1",
|
|
44
|
-
silent: true,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
throw err;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
let proxy;
|
|
51
|
-
try {
|
|
52
|
-
proxy = await attempt(port);
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
console.error = origError;
|
|
56
|
-
throw err;
|
|
57
|
-
}
|
|
58
|
-
const addr = proxy.server.address();
|
|
59
|
-
const actualPort = addr.port;
|
|
60
|
-
await log("info", `Claude Max proxy running on port ${actualPort}`);
|
|
61
|
-
return {
|
|
62
|
-
port: actualPort,
|
|
63
|
-
close: async () => {
|
|
64
|
-
console.error = origError;
|
|
65
|
-
await proxy.close();
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
// ---------------------------------------------------------------------------
|
|
70
|
-
// Process cleanup
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
|
-
/**
|
|
73
|
-
* Register cross-platform cleanup handlers that stop the proxy on exit.
|
|
74
|
-
*
|
|
75
|
-
* - `exit` and `SIGINT` work on all platforms.
|
|
76
|
-
* - `SIGTERM` is only available on POSIX systems.
|
|
77
|
-
*/
|
|
78
|
-
export function registerCleanup(proxy) {
|
|
79
|
-
let cleaned = false;
|
|
80
|
-
const cleanup = () => {
|
|
81
|
-
if (cleaned)
|
|
82
|
-
return;
|
|
83
|
-
cleaned = true;
|
|
84
|
-
void proxy.close();
|
|
85
|
-
};
|
|
86
|
-
process.on("exit", cleanup);
|
|
87
|
-
process.on("SIGINT", cleanup);
|
|
88
|
-
if (!IS_WINDOWS) {
|
|
89
|
-
process.on("SIGTERM", cleanup);
|
|
90
|
-
}
|
|
91
|
-
}
|