@hypeitnow/opencode-claude-auth 1.6.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +238 -0
  3. package/dist/anthropic-prompt.txt +166 -0
  4. package/dist/betas.d.ts +9 -0
  5. package/dist/betas.d.ts.map +1 -0
  6. package/dist/betas.js +102 -0
  7. package/dist/betas.js.map +1 -0
  8. package/dist/credentials.d.ts +29 -0
  9. package/dist/credentials.d.ts.map +1 -0
  10. package/dist/credentials.js +313 -0
  11. package/dist/credentials.js.map +1 -0
  12. package/dist/index.d.ts +14 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +495 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/keychain.d.ts +23 -0
  17. package/dist/keychain.d.ts.map +1 -0
  18. package/dist/keychain.js +365 -0
  19. package/dist/keychain.js.map +1 -0
  20. package/dist/logger.d.ts +8 -0
  21. package/dist/logger.d.ts.map +1 -0
  22. package/dist/logger.js +74 -0
  23. package/dist/logger.js.map +1 -0
  24. package/dist/model-config.d.ts +22 -0
  25. package/dist/model-config.d.ts.map +1 -0
  26. package/dist/model-config.js +44 -0
  27. package/dist/model-config.js.map +1 -0
  28. package/dist/oauth.d.ts +31 -0
  29. package/dist/oauth.d.ts.map +1 -0
  30. package/dist/oauth.js +158 -0
  31. package/dist/oauth.js.map +1 -0
  32. package/dist/pkce.d.ts +6 -0
  33. package/dist/pkce.d.ts.map +1 -0
  34. package/dist/pkce.js +23 -0
  35. package/dist/pkce.js.map +1 -0
  36. package/dist/plugin-config.d.ts +45 -0
  37. package/dist/plugin-config.d.ts.map +1 -0
  38. package/dist/plugin-config.js +66 -0
  39. package/dist/plugin-config.js.map +1 -0
  40. package/dist/signing.d.ts +31 -0
  41. package/dist/signing.d.ts.map +1 -0
  42. package/dist/signing.js +55 -0
  43. package/dist/signing.js.map +1 -0
  44. package/dist/transforms.d.ts +14 -0
  45. package/dist/transforms.d.ts.map +1 -0
  46. package/dist/transforms.js +271 -0
  47. package/dist/transforms.js.map +1 -0
  48. package/installation.md +98 -0
  49. package/opencode-claude-auth.js +2 -0
  50. package/package.json +79 -0
@@ -0,0 +1,271 @@
1
+ import { buildBillingHeaderValue } from "./signing.js";
2
+ import { config, getModelOverride } from "./model-config.js";
3
+ const TOOL_PREFIX = "mcp_";
4
+ /**
5
+ * Prefix a tool name with TOOL_PREFIX and uppercase the first character.
6
+ * Claude Code uses PascalCase tool names (e.g. mcp_Bash, mcp_Read);
7
+ * lowercase names (mcp_bash, mcp_read) are flagged as non-Claude-Code clients.
8
+ */
9
+ function prefixName(name) {
10
+ return `${TOOL_PREFIX}${name.charAt(0).toUpperCase()}${name.slice(1)}`;
11
+ }
12
+ /**
13
+ * Reverse prefixName: strip TOOL_PREFIX and restore the original leading case.
14
+ */
15
+ function unprefixName(name) {
16
+ return `${name.charAt(0).toLowerCase()}${name.slice(1)}`;
17
+ }
18
+ const SYSTEM_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude.";
19
+ export function repairToolPairs(messages) {
20
+ // Collect all tool_use ids and tool_result tool_use_ids
21
+ const toolUseIds = new Set();
22
+ const toolResultIds = new Set();
23
+ for (const message of messages) {
24
+ if (!Array.isArray(message.content))
25
+ continue;
26
+ for (const block of message.content) {
27
+ const id = block["id"];
28
+ if (block.type === "tool_use" && typeof id === "string") {
29
+ toolUseIds.add(id);
30
+ }
31
+ const toolUseId = block["tool_use_id"];
32
+ if (block.type === "tool_result" && typeof toolUseId === "string") {
33
+ toolResultIds.add(toolUseId);
34
+ }
35
+ }
36
+ }
37
+ // Find orphaned IDs
38
+ const orphanedUses = new Set();
39
+ for (const id of toolUseIds) {
40
+ if (!toolResultIds.has(id))
41
+ orphanedUses.add(id);
42
+ }
43
+ const orphanedResults = new Set();
44
+ for (const id of toolResultIds) {
45
+ if (!toolUseIds.has(id))
46
+ orphanedResults.add(id);
47
+ }
48
+ // Early return if nothing to fix
49
+ if (orphanedUses.size === 0 && orphanedResults.size === 0) {
50
+ return messages;
51
+ }
52
+ // Filter orphaned blocks and remove messages with empty content arrays
53
+ return messages
54
+ .map((message) => {
55
+ if (!Array.isArray(message.content))
56
+ return message;
57
+ const filtered = message.content.filter((block) => {
58
+ const id = block["id"];
59
+ if (block.type === "tool_use" && typeof id === "string") {
60
+ return !orphanedUses.has(id);
61
+ }
62
+ const toolUseId = block["tool_use_id"];
63
+ if (block.type === "tool_result" && typeof toolUseId === "string") {
64
+ return !orphanedResults.has(toolUseId);
65
+ }
66
+ return true;
67
+ });
68
+ return { ...message, content: filtered };
69
+ })
70
+ .filter((message) => !(Array.isArray(message.content) && message.content.length === 0));
71
+ }
72
+ export function transformBody(body) {
73
+ if (typeof body !== "string") {
74
+ return body;
75
+ }
76
+ try {
77
+ const parsed = JSON.parse(body);
78
+ // --- Billing header: inject as system[0] (no cache_control) ---
79
+ const version = process.env.ANTHROPIC_CLI_VERSION ?? config.ccVersion;
80
+ const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? "sdk-cli";
81
+ const billingHeader = buildBillingHeaderValue((parsed.messages ?? []), version, entrypoint);
82
+ if (!Array.isArray(parsed.system)) {
83
+ parsed.system = [];
84
+ }
85
+ // Remove any existing billing header entries
86
+ parsed.system = parsed.system.filter((e) => !(e.type === "text" &&
87
+ typeof e.text === "string" &&
88
+ e.text.startsWith("x-anthropic-billing-header")));
89
+ // Insert billing header as system[0], without cache_control
90
+ parsed.system.unshift({ type: "text", text: billingHeader });
91
+ // --- Split identity prefix into its own system entry ---
92
+ // OpenCode's system.transform hook prepends the identity string, but
93
+ // OpenCode then concatenates all system entries into a single text block.
94
+ // Anthropic's API requires the identity string as a separate entry for
95
+ // OAuth validation (see issue #98).
96
+ const splitSystem = [];
97
+ for (const entry of parsed.system) {
98
+ if (entry.type === "text" &&
99
+ typeof entry.text === "string" &&
100
+ entry.text.startsWith(SYSTEM_IDENTITY) &&
101
+ entry.text.length > SYSTEM_IDENTITY.length) {
102
+ const rest = entry.text
103
+ .slice(SYSTEM_IDENTITY.length)
104
+ .replace(/^\n+/, "");
105
+ // Preserve all properties except text (e.g. cache_control)
106
+ const { text: _text, ...entryProps } = entry;
107
+ // Only keep cache_control on the remainder block to avoid exceeding
108
+ // the API limit of 4 cache_control blocks per request.
109
+ const { cache_control: _cc, ...identityProps } = entryProps;
110
+ splitSystem.push({ ...identityProps, text: SYSTEM_IDENTITY });
111
+ if (rest.length > 0) {
112
+ splitSystem.push({ ...entryProps, text: rest });
113
+ }
114
+ }
115
+ else {
116
+ splitSystem.push(entry);
117
+ }
118
+ }
119
+ parsed.system = splitSystem;
120
+ // --- Relocate non-core system entries to user messages ---
121
+ // Anthropic's API now validates the system prompt for OAuth-authenticated
122
+ // requests that use Claude Code billing. Third-party system prompts
123
+ // (like OpenCode's) trigger a 400 "out of extra usage" rejection when
124
+ // they appear inside the system[] array alongside the identity prefix.
125
+ //
126
+ // Work-around: keep only the billing header and identity prefix in
127
+ // system[], and prepend all other system content to the first user
128
+ // message where it is functionally equivalent but avoids the check.
129
+ const BILLING_PREFIX = "x-anthropic-billing-header";
130
+ const keptSystem = [];
131
+ const movedTexts = [];
132
+ for (const entry of parsed.system) {
133
+ const txt = typeof entry === "string" ? entry : (entry.text ?? "");
134
+ if (txt.startsWith(BILLING_PREFIX) || txt.startsWith(SYSTEM_IDENTITY)) {
135
+ keptSystem.push(entry);
136
+ }
137
+ else if (txt.length > 0) {
138
+ movedTexts.push(txt);
139
+ }
140
+ }
141
+ if (movedTexts.length > 0 && Array.isArray(parsed.messages)) {
142
+ const firstUser = parsed.messages.find((m) => m.role === "user");
143
+ if (firstUser) {
144
+ parsed.system = keptSystem;
145
+ const prefix = movedTexts.join("\n\n");
146
+ if (typeof firstUser.content === "string") {
147
+ firstUser.content = prefix + "\n\n" + firstUser.content;
148
+ }
149
+ else if (Array.isArray(firstUser.content)) {
150
+ firstUser.content.unshift({ type: "text", text: prefix });
151
+ }
152
+ }
153
+ }
154
+ // Strip effort for models that don't support it (e.g. haiku).
155
+ // OpenCode sends { output_config: { effort: "high" } } but haiku
156
+ // rejects the effort parameter with a 400 error.
157
+ const modelId = parsed.model ?? "";
158
+ const override = getModelOverride(modelId);
159
+ if (override?.disableEffort) {
160
+ if (parsed.output_config) {
161
+ delete parsed.output_config.effort;
162
+ if (Object.keys(parsed.output_config).length === 0) {
163
+ delete parsed.output_config;
164
+ }
165
+ }
166
+ if (parsed.thinking && "effort" in parsed.thinking) {
167
+ delete parsed.thinking.effort;
168
+ if (Object.keys(parsed.thinking).length === 0) {
169
+ delete parsed.thinking;
170
+ }
171
+ }
172
+ }
173
+ // Anthropic's OAuth billing validation rejects lowercase tool names
174
+ // when multiple tools are present. Claude Code uses PascalCase after
175
+ // the mcp_ prefix (e.g. mcp_Bash, mcp_Read). Apply the same convention.
176
+ if (Array.isArray(parsed.tools)) {
177
+ parsed.tools = parsed.tools.map((tool) => ({
178
+ ...tool,
179
+ name: tool.name ? prefixName(tool.name) : tool.name,
180
+ }));
181
+ }
182
+ if (Array.isArray(parsed.messages)) {
183
+ parsed.messages = parsed.messages.map((message) => {
184
+ if (!Array.isArray(message.content)) {
185
+ return message;
186
+ }
187
+ return {
188
+ ...message,
189
+ content: message.content.map((block) => {
190
+ if (block.type !== "tool_use" || typeof block.name !== "string") {
191
+ return block;
192
+ }
193
+ return { ...block, name: prefixName(block.name) };
194
+ }),
195
+ };
196
+ });
197
+ }
198
+ if (Array.isArray(parsed.messages)) {
199
+ parsed.messages = repairToolPairs(parsed.messages);
200
+ }
201
+ return JSON.stringify(parsed);
202
+ }
203
+ catch {
204
+ return body;
205
+ }
206
+ }
207
+ export function stripToolPrefix(text) {
208
+ return text.replace(/"name"\s*:\s*"mcp_([^"]+)"/g, (_match, name) => `"name": "${unprefixName(name)}"`);
209
+ }
210
+ export function transformResponseStream(response) {
211
+ if (!response.body) {
212
+ return response;
213
+ }
214
+ // Don't wrap error responses through the SSE parser — pass them through
215
+ // with only tool-prefix stripping on the raw body. This preserves error
216
+ // messages for OpenCode / AI SDK to handle properly.
217
+ if (!response.ok) {
218
+ const reader = response.body.getReader();
219
+ const decoder = new TextDecoder();
220
+ const encoder = new TextEncoder();
221
+ const passthrough = new ReadableStream({
222
+ async pull(controller) {
223
+ const { done, value } = await reader.read();
224
+ if (done) {
225
+ controller.close();
226
+ return;
227
+ }
228
+ const text = decoder.decode(value, { stream: true });
229
+ controller.enqueue(encoder.encode(stripToolPrefix(text)));
230
+ },
231
+ });
232
+ return new Response(passthrough, {
233
+ status: response.status,
234
+ statusText: response.statusText,
235
+ headers: response.headers,
236
+ });
237
+ }
238
+ const reader = response.body.getReader();
239
+ const decoder = new TextDecoder();
240
+ const encoder = new TextEncoder();
241
+ let buffer = "";
242
+ const stream = new ReadableStream({
243
+ async pull(controller) {
244
+ for (;;) {
245
+ const boundary = buffer.indexOf("\n\n");
246
+ if (boundary !== -1) {
247
+ const completeEvent = buffer.slice(0, boundary + 2);
248
+ buffer = buffer.slice(boundary + 2);
249
+ controller.enqueue(encoder.encode(stripToolPrefix(completeEvent)));
250
+ return;
251
+ }
252
+ const { done, value } = await reader.read();
253
+ if (done) {
254
+ if (buffer) {
255
+ controller.enqueue(encoder.encode(stripToolPrefix(buffer)));
256
+ buffer = "";
257
+ }
258
+ controller.close();
259
+ return;
260
+ }
261
+ buffer += decoder.decode(value, { stream: true });
262
+ }
263
+ },
264
+ });
265
+ return new Response(stream, {
266
+ status: response.status,
267
+ statusText: response.statusText,
268
+ headers: response.headers,
269
+ });
270
+ }
271
+ //# sourceMappingURL=transforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.js","sourceRoot":"","sources":["../src/transforms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ # Install opencode-claude-auth
2
+
3
+ These instructions are designed for AI coding agents.
4
+
5
+ ## Prerequisites
6
+
7
+ Before installing, verify you have OpenCode and Claude Code installed and authenticated.
8
+
9
+ ### Check OpenCode version
10
+
11
+ ```bash
12
+ opencode --version
13
+ ```
14
+
15
+ You should see a version number (e.g., `1.2.28`).
16
+
17
+ ### Check Claude Code credentials (macOS)
18
+
19
+ ```bash
20
+ security find-generic-password -s "Claude Code-credentials" -w
21
+ ```
22
+
23
+ If this returns credentials, you're authenticated. If it fails or returns nothing, try the fallback:
24
+
25
+ ### Check Claude Code credentials (fallback for all platforms)
26
+
27
+ ```bash
28
+ cat ~/.claude/.credentials.json
29
+ ```
30
+
31
+ If this file exists and contains valid JSON, you're authenticated.
32
+
33
+ ### If credentials don't exist
34
+
35
+ Run Claude Code to authenticate:
36
+
37
+ ```bash
38
+ claude
39
+ ```
40
+
41
+ This will prompt you to log in and store credentials in Keychain (macOS) or `~/.claude/.credentials.json` (other platforms).
42
+
43
+ ## Installation
44
+
45
+ ### Step 1: Add to OpenCode configuration
46
+
47
+ Edit the OpenCode configuration file at `~/.config/opencode/opencode.json`.
48
+
49
+ Add `opencode-claude-auth@latest` to the `plugin` array:
50
+
51
+ ```json
52
+ {
53
+ "plugin": ["opencode-claude-auth@latest"]
54
+ }
55
+ ```
56
+
57
+ Or run this command to do it automatically:
58
+
59
+ ```bash
60
+ node -e "
61
+ const fs = require('fs'), p = require('path').join(require('os').homedir(), '.config/opencode/opencode.json');
62
+ const c = fs.existsSync(p) ? JSON.parse(fs.readFileSync(p,'utf8')) : {};
63
+ c.plugin = [...new Set([...(Array.isArray(c.plugin) ? c.plugin : []), 'opencode-claude-auth@latest'])];
64
+ fs.mkdirSync(require('path').dirname(p), {recursive:true});
65
+ fs.writeFileSync(p, JSON.stringify(c, null, 2));
66
+ console.log('Added opencode-claude-auth@latest to', p);
67
+ "
68
+ ```
69
+
70
+ The `@latest` tag ensures OpenCode always pulls the newest version on startup. No manual `npm install` is needed — OpenCode [automatically installs npm plugins using Bun at startup](https://opencode.ai/docs/plugins/#how-plugins-are-installed).
71
+
72
+ ### Step 2: Verification
73
+
74
+ Verify the plugin was added:
75
+
76
+ ```bash
77
+ cat ~/.config/opencode/opencode.json
78
+ ```
79
+
80
+ You should see `opencode-claude-auth@latest` in the `plugin` array.
81
+
82
+ ## Upgrading
83
+
84
+ If you previously installed `opencode-claude-auth` without the `@latest` tag, update your config to use `opencode-claude-auth@latest` as shown above.
85
+
86
+ If the plugin isn't picking up a new version, clear the cached package and restart OpenCode:
87
+
88
+ ```bash
89
+ rm -rf ~/.cache/opencode/packages/opencode-claude-auth@latest/
90
+ ```
91
+
92
+ ## Done
93
+
94
+ The plugin is now installed and configured. When you run OpenCode, it will automatically use your Claude Code credentials — no separate login needed.
95
+
96
+ ## Troubleshooting
97
+
98
+ If you encounter issues, see the [main README troubleshooting section](README.md#troubleshooting).
@@ -0,0 +1,2 @@
1
+ // Entry point: re-exports the compiled plugin from dist/
2
+ export { ClaudeAuthPlugin, default } from "./dist/index.js"
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@hypeitnow/opencode-claude-auth",
3
+ "version": "1.6.0",
4
+ "description": "OpenCode plugin that uses your Claude Code credentials — no separate login needed. Fork with OAuth fallback for org-locked accounts.",
5
+ "keywords": [
6
+ "anthropic",
7
+ "auth",
8
+ "claude",
9
+ "opencode",
10
+ "plugin"
11
+ ],
12
+ "license": "MIT",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/hypeitnow/opencode-claude-auth.git"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "files": [
21
+ "opencode-claude-auth.js",
22
+ "dist",
23
+ "installation.md"
24
+ ],
25
+ "type": "module",
26
+ "main": "opencode-claude-auth.js",
27
+ "module": "opencode-claude-auth.js",
28
+ "types": "dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./opencode-claude-auth.js"
33
+ },
34
+ "./server": {
35
+ "types": "./dist/index.d.ts",
36
+ "import": "./opencode-claude-auth.js"
37
+ },
38
+ "./claude-auth-plugin": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.js"
41
+ },
42
+ "./claude-auth-plugin.js": {
43
+ "types": "./dist/index.d.ts",
44
+ "import": "./dist/index.js"
45
+ },
46
+ "./opencode-claude-auth": {
47
+ "types": "./dist/index.d.ts",
48
+ "import": "./dist/index.js"
49
+ },
50
+ "./opencode-claude-auth.js": {
51
+ "types": "./dist/index.d.ts",
52
+ "import": "./dist/index.js"
53
+ }
54
+ },
55
+ "scripts": {
56
+ "build": "tsc && cp src/anthropic-prompt.txt dist/",
57
+ "test": "node --test --experimental-strip-types src/**/*.test.ts",
58
+ "test:models": "pnpm run build && node scripts/test-models.ts",
59
+ "intercept": "pnpm run build && node --experimental-strip-types scripts/intercept-claude.ts",
60
+ "intercept:all": "pnpm run build && node --experimental-strip-types scripts/intercept-claude.ts --all",
61
+ "intercept:update": "pnpm run build && node --experimental-strip-types scripts/intercept-claude.ts --all --update",
62
+ "validate:oauth": "pnpm run build && node --experimental-strip-types scripts/validate-oauth-refresh.ts",
63
+ "lint": "oxlint && oxfmt --check .",
64
+ "lint:fix": "oxlint --fix . && oxfmt --write .",
65
+ "format": "oxfmt --write .",
66
+ "prepublishOnly": "pnpm run build && pnpm test"
67
+ },
68
+ "devDependencies": {
69
+ "@opencode-ai/plugin": "latest",
70
+ "@types/node": "^25.5.0",
71
+ "oxfmt": "0.41.0",
72
+ "oxlint": "1.56.0",
73
+ "typescript": "^5.0.0"
74
+ },
75
+ "peerDependencies": {
76
+ "@opencode-ai/plugin": "*"
77
+ },
78
+ "packageManager": "pnpm@10.32.1"
79
+ }