unbound-claude-code 0.1.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Unbound
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # Unbound Code
2
+
3
+ Unbound Code is a drop-in replacement for Claude Code that automatically routes your API calls through [Unbound](https://getunbound.ai).
4
+
5
+ ### Installation
6
+
7
+ ```bash
8
+ npm install -g unbound-claude-code
9
+ ```
10
+
11
+ ### Usage
12
+
13
+ Simply replace `claude` with `unbound-claude-code` in your commands:
14
+
15
+ ```bash
16
+ # Instead of: claude chat
17
+ unbound-claude-code chat
18
+
19
+ # Instead of: claude
20
+ unbound-claude-code
21
+
22
+ # All Claude Code options work the same
23
+ unbound-claude-code --help
24
+ ```
25
+
26
+ ### First Time Setup
27
+
28
+ 1. Get your Unbound API key from [gateway.getunbound.ai](https://gateway.getunbound.ai)
29
+ 2. Run `unbound-claude-code` - you'll be prompted to enter your API key
30
+ 3. Your API key will be securely stored for future use
31
+ 4. Use Claude Code normally - it will authenticate with your Claude/Anthropic key as usual
32
+
33
+ ## 🔧 Configuration
34
+
35
+ ### API Key Management
36
+
37
+ ```bash
38
+ # Set API key directly
39
+ unbound-claude-code --api-key YOUR_UNBOUND_KEY
40
+
41
+ # Use environment variable
42
+ export UNBOUND_API_KEY=your_key_here
43
+ unbound-claude-code
44
+
45
+ # View current configuration
46
+ unbound-claude-code --show-config
47
+
48
+ # Clear stored configuration
49
+ unbound-claude-code --clear-config
50
+ ```
51
+
52
+ ### Available Options
53
+
54
+ ```bash
55
+ # Show help
56
+ unbound-claude-code --help
57
+
58
+ # Enable debug logging
59
+ unbound-claude-code --debug
60
+
61
+ # Skip authentication (requires UNBOUND_API_KEY env var)
62
+ unbound-claude-code --skip-auth
63
+
64
+ # Show version
65
+ unbound-claude-code --version
66
+ ```
67
+
68
+ ## 🏗️ How It Works
69
+
70
+ Unbound Code works by intercepting Claude Code's API calls and routing them through Unbound:
71
+
72
+ 1. **You use Claude Code normally** - All commands, shortcuts, and features work identically
73
+ 2. **Claude Code authenticates normally** - Uses your Claude/Anthropic API key as usual
74
+ 3. **Unbound Code intercepts API calls** - Transparently redirects calls to Unbound AI
75
+ 4. **Dual authentication** - Sends both your Claude key and Unbound key to Unbound's API
76
+ 5. **Smart model routing** - Unbound AI routes to the best available model
77
+ 6. **Seamless responses** - You get responses exactly as if you were using Claude Code directly
78
+
79
+
80
+ ## 📋 Environment Variables
81
+
82
+ | Variable | Description | Default |
83
+ |----------|-------------|---------|
84
+ | `UNBOUND_API_KEY` | Your Unbound API key | None (prompted if not set) |
85
+ | `UNBOUND_LOG_LEVEL` | Logging level (debug, info, warn, error) | `info` |
86
+ | `ANTHROPIC_API_KEY` | Your Claude/Anthropic API key (handled by Claude Code) | None |
87
+
88
+
89
+ ## 🤝 Compatibility
90
+
91
+ - **Node.js**: >= 16.0.0
92
+ - **Claude Code**: Latest version (bundled)
93
+ - **Operating Systems**: macOS, Linux, Windows
94
+ - **Terminals**: All terminals supported by Claude Code
95
+
96
+
97
+ ## 📄 License
98
+
99
+ MIT License - see [LICENSE](LICENSE) file for details.
package/dist/auth.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Unbound API Authentication and Verification
3
+ */
4
+ import { UnboundModelsResponse } from "./types";
5
+ export declare class UnboundAuth {
6
+ private baseUrl;
7
+ private storage;
8
+ constructor(baseUrl?: string);
9
+ /**
10
+ * Verify API key by calling the /models endpoint
11
+ */
12
+ verifyApiKey(apiKey: string): Promise<boolean>;
13
+ /**
14
+ * Get available models from Unbound API
15
+ */
16
+ getModels(apiKey: string): Promise<UnboundModelsResponse | null>;
17
+ /**
18
+ * Prompt user for API key interactively
19
+ */
20
+ promptForApiKey(): Promise<string>;
21
+ /**
22
+ * Get Unbound API key from environment or prompt user
23
+ */
24
+ getApiKey(): Promise<string>;
25
+ /**
26
+ * Get API key without verification
27
+ */
28
+ getApiKeyOnly(): Promise<string>;
29
+ /**
30
+ * Complete authentication flow: get API key and verify it
31
+ */
32
+ authenticate(): Promise<string>;
33
+ }
34
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGhD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAiB;gBAEpB,OAAO,GAAE,MAAuC;IAK5D;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgCpD;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAgCtE;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IA4BxC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAalC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IA0BtC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;CActC"}
package/dist/auth.js ADDED
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ /**
3
+ * Unbound API Authentication and Verification
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.UnboundAuth = void 0;
7
+ const storage_1 = require("./storage");
8
+ class UnboundAuth {
9
+ constructor(baseUrl = "https://api.getunbound.ai/v1") {
10
+ this.baseUrl = baseUrl;
11
+ this.storage = new storage_1.UnboundStorage();
12
+ }
13
+ /**
14
+ * Verify API key by calling the /models endpoint
15
+ */
16
+ async verifyApiKey(apiKey) {
17
+ try {
18
+ const response = await fetch(`${this.baseUrl}/models`, {
19
+ method: "GET",
20
+ headers: {
21
+ "Authorization": `Bearer ${apiKey}`,
22
+ "Content-Type": "application/json",
23
+ }
24
+ });
25
+ if (response.ok) {
26
+ const data = await response.json();
27
+ // Handle different response formats
28
+ if (data && Array.isArray(data.data) && data.data.length > 0) {
29
+ return true;
30
+ }
31
+ else if (data && Array.isArray(data) && data.length > 0) {
32
+ return true;
33
+ }
34
+ else if (data && typeof data === 'object') {
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ return false;
40
+ }
41
+ catch (error) {
42
+ console.error("API key verification failed:", error);
43
+ return false;
44
+ }
45
+ }
46
+ /**
47
+ * Get available models from Unbound API
48
+ */
49
+ async getModels(apiKey) {
50
+ try {
51
+ const response = await fetch(`${this.baseUrl}/models`, {
52
+ method: "GET",
53
+ headers: {
54
+ "Authorization": `Bearer ${apiKey}`,
55
+ "Content-Type": "application/json",
56
+ }
57
+ });
58
+ if (response.ok) {
59
+ const data = await response.json();
60
+ if (data && Array.isArray(data.data)) {
61
+ return data;
62
+ }
63
+ else if (data && Array.isArray(data)) {
64
+ return { object: "list", data: data };
65
+ }
66
+ else {
67
+ console.warn("Unexpected models response format:", data);
68
+ return null;
69
+ }
70
+ }
71
+ else {
72
+ console.warn(`Failed to fetch models: ${response.status} ${response.statusText}`);
73
+ }
74
+ return null;
75
+ }
76
+ catch (error) {
77
+ console.error("Failed to get models:", error);
78
+ return null;
79
+ }
80
+ }
81
+ /**
82
+ * Prompt user for API key interactively
83
+ */
84
+ async promptForApiKey() {
85
+ const readline = require('readline');
86
+ const rl = readline.createInterface({
87
+ input: process.stdin,
88
+ output: process.stdout
89
+ });
90
+ return new Promise((resolve, reject) => {
91
+ const askForKey = () => {
92
+ rl.question('Enter your Unbound API key: ', (apiKey) => {
93
+ const trimmedKey = apiKey ? apiKey.trim() : '';
94
+ if (!trimmedKey || trimmedKey.length === 0) {
95
+ console.log('API key cannot be empty. Please try again.');
96
+ askForKey(); // Ask again
97
+ return;
98
+ }
99
+ rl.close();
100
+ resolve(trimmedKey);
101
+ });
102
+ };
103
+ askForKey();
104
+ });
105
+ }
106
+ /**
107
+ * Get Unbound API key from environment or prompt user
108
+ */
109
+ async getApiKey() {
110
+ // First try environment variable
111
+ const envApiKey = process.env.UNBOUND_API_KEY;
112
+ if (envApiKey && envApiKey.trim().length > 0) {
113
+ console.log('Using Unbound API key from UNBOUND_API_KEY environment variable');
114
+ return envApiKey.trim();
115
+ }
116
+ // If not found in environment, prompt user
117
+ console.log('UNBOUND_API_KEY environment variable not found.');
118
+ return await this.promptForApiKey();
119
+ }
120
+ /**
121
+ * Get API key without verification
122
+ */
123
+ async getApiKeyOnly() {
124
+ // First try environment variable
125
+ const envApiKey = process.env.UNBOUND_API_KEY;
126
+ if (envApiKey && envApiKey.trim().length > 0) {
127
+ console.log('✓ Using Unbound API key from UNBOUND_API_KEY environment variable');
128
+ return envApiKey.trim();
129
+ }
130
+ // Then try stored API key
131
+ const storedApiKey = this.storage.getApiKey();
132
+ if (storedApiKey) {
133
+ console.log('✓ Using stored Unbound API key from ~/.unbound-code/config.json');
134
+ return storedApiKey;
135
+ }
136
+ // If not found anywhere, prompt user
137
+ console.log('UNBOUND_API_KEY environment variable not found.');
138
+ const apiKey = await this.promptForApiKey();
139
+ // Store the API key for future use
140
+ this.storage.setApiKey(apiKey);
141
+ console.log('✓ Unbound API key stored in ~/.unbound-code/config.json for future use');
142
+ return apiKey;
143
+ }
144
+ /**
145
+ * Complete authentication flow: get API key and verify it
146
+ */
147
+ async authenticate() {
148
+ const apiKey = await this.getApiKey();
149
+ console.log('Verifying API key...');
150
+ const isValid = await this.verifyApiKey(apiKey);
151
+ if (!isValid) {
152
+ throw new Error('Invalid API key. Please check your Unbound API key and try again.');
153
+ }
154
+ console.log('✓ API key verified successfully');
155
+ return apiKey;
156
+ }
157
+ }
158
+ exports.UnboundAuth = UnboundAuth;
159
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unbound Code CLI
4
+ *
5
+ * A Claude Code interceptor that redirects API calls to Unbound AI
6
+ */
7
+ declare class UnboundCli {
8
+ private auth;
9
+ private storage;
10
+ constructor();
11
+ private parseArgs;
12
+ private showHelp;
13
+ private showVersion;
14
+ private showConfig;
15
+ private clearConfig;
16
+ private setModel;
17
+ private checkClaudeCode;
18
+ private getInterceptorPath;
19
+ private authenticateUser;
20
+ private launchClaudeCode;
21
+ run(args: string[]): Promise<void>;
22
+ }
23
+ export { UnboundCli };
24
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAmBH,cAAM,UAAU;IACd,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,OAAO,CAAiB;;IAOhC,OAAO,CAAC,SAAS;IAoDjB,OAAO,CAAC,QAAQ;IAmChB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,WAAW;YAKL,QAAQ;YAwBR,eAAe;IAK7B,OAAO,CAAC,kBAAkB;YAKZ,gBAAgB;YA2EhB,gBAAgB;IAqDjB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA2ChD;AAQD,OAAO,EAAE,UAAU,EAAE,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,303 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Unbound Code CLI
5
+ *
6
+ * A Claude Code interceptor that redirects API calls to Unbound AI
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.UnboundCli = void 0;
10
+ const child_process_1 = require("child_process");
11
+ const path_1 = require("path");
12
+ const fs_1 = require("fs");
13
+ const auth_1 = require("./auth");
14
+ const storage_1 = require("./storage");
15
+ class UnboundCli {
16
+ constructor() {
17
+ this.auth = new auth_1.UnboundAuth();
18
+ this.storage = new storage_1.UnboundStorage();
19
+ }
20
+ parseArgs(args) {
21
+ const options = {};
22
+ const claudeArgs = [];
23
+ let i = 0;
24
+ while (i < args.length) {
25
+ const arg = args[i];
26
+ switch (arg) {
27
+ case '--help':
28
+ case '-h':
29
+ options.help = true;
30
+ break;
31
+ case '--version':
32
+ case '-v':
33
+ options.version = true;
34
+ break;
35
+ case '--debug':
36
+ options.debug = true;
37
+ break;
38
+ case '--skip-auth':
39
+ options.skipAuth = true;
40
+ break;
41
+ case '--api-key':
42
+ if (i + 1 < args.length) {
43
+ options.apiKey = args[i + 1];
44
+ i++; // Skip next arg
45
+ }
46
+ break;
47
+ case '--clear-config':
48
+ options.clearConfig = true;
49
+ break;
50
+ case '--show-config':
51
+ options.showConfig = true;
52
+ break;
53
+ case '--set-model':
54
+ if (i + 1 < args.length) {
55
+ options.setModel = args[i + 1];
56
+ i++; // Skip next arg
57
+ }
58
+ break;
59
+ default:
60
+ // Pass through to Claude Code
61
+ claudeArgs.push(arg);
62
+ break;
63
+ }
64
+ i++;
65
+ }
66
+ return { options, claudeArgs };
67
+ }
68
+ showHelp() {
69
+ console.log(`
70
+ Unbound Code - Claude Code with Unbound AI
71
+
72
+ USAGE:
73
+ unbound-claude-code [OPTIONS] [CLAUDE_ARGS...]
74
+
75
+ OPTIONS:
76
+ -h, --help Show this help message
77
+ -v, --version Show version information
78
+ --debug Enable debug logging
79
+ --skip-auth Skip API key authentication (use UNBOUND_API_KEY env var)
80
+ --api-key KEY Provide API key directly (will be stored)
81
+ --clear-config Clear stored configuration
82
+ --show-config Show current configuration
83
+ --set-model MODEL Set default model
84
+
85
+ EXAMPLES:
86
+ unbound-claude-code # Start Claude Code with Unbound AI
87
+ unbound-claude-code chat # Start in chat mode
88
+ unbound-claude-code --debug # Start with debug logging
89
+ unbound-claude-code --api-key YOUR_KEY # Set and store API key
90
+ unbound-claude-code --show-config # Show stored configuration
91
+ unbound-claude-code --clear-config # Clear stored credentials
92
+ unbound-claude-code --set-model gpt-4o # Set default model
93
+
94
+ ENVIRONMENT VARIABLES:
95
+ UNBOUND_API_KEY # Your Unbound API key
96
+ UNBOUND_LOG_LEVEL # Log level (debug, info, warn, error)
97
+
98
+ Claude Code will be launched with all API calls redirected to Unbound AI.
99
+ Claude Code is bundled with Unbound Code, so no separate installation is needed.
100
+ `);
101
+ }
102
+ showVersion() {
103
+ const packageJson = require('../package.json');
104
+ console.log(`unbound-claude-code v${packageJson.version}`);
105
+ }
106
+ showConfig() {
107
+ const config = this.storage.getFullConfig();
108
+ console.log('Current Unbound Code Configuration:');
109
+ console.log('');
110
+ console.log(`API Key: ${config.apiKey ? '***' + config.apiKey.slice(-8) : 'Not set'}`);
111
+ console.log(`Model: ${config.model || 'Default (anthropic/claude-sonnet-4-20250514)'}`);
112
+ console.log(`Base URL: ${config.baseUrl || 'https://api.getunbound.ai/v1'}`);
113
+ console.log(`Log Level: ${config.logLevel || 'info'}`);
114
+ if (config.lastUsed) {
115
+ console.log(`Last Used: ${new Date(config.lastUsed).toLocaleString()}`);
116
+ }
117
+ console.log('');
118
+ console.log(`Config stored at: ~/.unbound-code/config.json`);
119
+ }
120
+ clearConfig() {
121
+ this.storage.clearConfig();
122
+ console.log('✓ Configuration cleared successfully');
123
+ }
124
+ async setModel(model) {
125
+ // Verify the API key exists first
126
+ const apiKey = this.storage.getApiKey();
127
+ if (!apiKey) {
128
+ console.log('No API key found. Please set your API key first with --api-key');
129
+ return;
130
+ }
131
+ // Verify the model exists
132
+ const models = await this.auth.getModels(apiKey);
133
+ if (models && models.data && Array.isArray(models.data)) {
134
+ const modelExists = models.data.some(m => m && m.id && (m.id === model || m.id.endsWith(model)));
135
+ if (!modelExists) {
136
+ models.data
137
+ .filter(m => m && m.id)
138
+ .forEach(m => console.log(` - ${m.id}`));
139
+ return;
140
+ }
141
+ }
142
+ this.storage.setModel(model);
143
+ console.log(`✓ Default model set to: ${model}`);
144
+ }
145
+ async checkClaudeCode() {
146
+ // Claude Code is installed as a dependency, so we'll use npx to run it
147
+ // No need to log anything here
148
+ }
149
+ getInterceptorPath() {
150
+ // Get path to interceptor-loader.js
151
+ return (0, path_1.resolve)(__dirname, 'interceptor-loader.js');
152
+ }
153
+ async authenticateUser(options) {
154
+ if (options.skipAuth) {
155
+ const apiKey = process.env.UNBOUND_API_KEY;
156
+ if (!apiKey) {
157
+ throw new Error('UNBOUND_API_KEY environment variable required when using --skip-auth');
158
+ }
159
+ return apiKey;
160
+ }
161
+ if (options.apiKey) {
162
+ // Verify and store the provided API key
163
+ console.log('Verifying provided API key...');
164
+ const isValid = await this.auth.verifyApiKey(options.apiKey);
165
+ if (!isValid) {
166
+ throw new Error('Provided API key is invalid');
167
+ }
168
+ console.log('✓ API key verified successfully');
169
+ // Store the API key for future use
170
+ this.storage.setApiKey(options.apiKey);
171
+ return options.apiKey;
172
+ }
173
+ // Check if we have a stored API key first
174
+ const storedApiKey = this.storage.getApiKey();
175
+ if (storedApiKey) {
176
+ console.log('Using stored API key...');
177
+ console.log('Verifying stored API key...');
178
+ const isValid = await this.auth.verifyApiKey(storedApiKey);
179
+ if (isValid) {
180
+ console.log('✓ Stored API key verified successfully');
181
+ // Show available models
182
+ const models = await this.auth.getModels(storedApiKey);
183
+ if (models && models.data && Array.isArray(models.data) && models.data.length > 0) {
184
+ const modelNames = models.data
185
+ .filter(m => m && m.id)
186
+ .slice(0, 5)
187
+ .map(m => m.id.includes('/') ? m.id.split('/').pop() : m.id)
188
+ .join(', ');
189
+ }
190
+ return storedApiKey;
191
+ }
192
+ else {
193
+ console.log('Stored API key is invalid, requesting new key...');
194
+ this.storage.clearConfig();
195
+ }
196
+ }
197
+ // Get API key (from env or prompt) and verify it
198
+ const apiKey = await this.auth.getApiKeyOnly();
199
+ console.log('Verifying API key...');
200
+ const isValid = await this.auth.verifyApiKey(apiKey);
201
+ if (!isValid) {
202
+ throw new Error('Invalid API key. Please check your Unbound API key and try again.');
203
+ }
204
+ console.log('✓ API key verified successfully');
205
+ // Store the API key for future use
206
+ this.storage.setApiKey(apiKey);
207
+ // Show available models
208
+ const models = await this.auth.getModels(apiKey);
209
+ if (models && models.data && Array.isArray(models.data) && models.data.length > 0) {
210
+ const modelNames = models.data
211
+ .filter(m => m && m.id)
212
+ .slice(0, 5)
213
+ .map(m => m.id.includes('/') ? m.id.split('/').pop() : m.id)
214
+ .join(', ');
215
+ }
216
+ return apiKey;
217
+ }
218
+ async launchClaudeCode(apiKey, claudeArgs, debug) {
219
+ const interceptorPath = this.getInterceptorPath();
220
+ if (!(0, fs_1.existsSync)(interceptorPath)) {
221
+ throw new Error(`Interceptor not found at: ${interceptorPath}`);
222
+ }
223
+ // Set environment variables
224
+ const env = {
225
+ ...process.env,
226
+ UNBOUND_API_KEY: apiKey,
227
+ UNBOUND_LOG_LEVEL: debug ? 'debug' : 'info',
228
+ // Don't set ANTHROPIC_API_KEY - let Claude Code handle its own auth flow
229
+ // Our interceptor will extract the API key from the request headers
230
+ };
231
+ console.log('Starting Claude Code with Unbound AI...');
232
+ console.log('');
233
+ // Use npx to run the bundled Claude Code
234
+ const spawnArgs = [
235
+ '@anthropic-ai/claude-code',
236
+ ...claudeArgs
237
+ ];
238
+ const claudeProcess = (0, child_process_1.spawn)('npx', spawnArgs, {
239
+ stdio: 'inherit',
240
+ env: {
241
+ ...env,
242
+ NODE_OPTIONS: `--require ${interceptorPath}`
243
+ }
244
+ });
245
+ // Handle process events
246
+ claudeProcess.on('close', (code) => {
247
+ process.exit(code || 0);
248
+ });
249
+ claudeProcess.on('error', (error) => {
250
+ console.error('Failed to start Claude Code:', error);
251
+ process.exit(1);
252
+ });
253
+ // Handle Ctrl+C gracefully
254
+ process.on('SIGINT', () => {
255
+ claudeProcess.kill('SIGINT');
256
+ });
257
+ process.on('SIGTERM', () => {
258
+ claudeProcess.kill('SIGTERM');
259
+ });
260
+ }
261
+ async run(args) {
262
+ try {
263
+ const { options, claudeArgs } = this.parseArgs(args);
264
+ if (options.help) {
265
+ this.showHelp();
266
+ return;
267
+ }
268
+ if (options.version) {
269
+ this.showVersion();
270
+ return;
271
+ }
272
+ if (options.showConfig) {
273
+ this.showConfig();
274
+ return;
275
+ }
276
+ if (options.clearConfig) {
277
+ this.clearConfig();
278
+ return;
279
+ }
280
+ if (options.setModel) {
281
+ await this.setModel(options.setModel);
282
+ return;
283
+ }
284
+ // Check if Claude Code is available
285
+ await this.checkClaudeCode();
286
+ // Authenticate user
287
+ const apiKey = await this.authenticateUser(options);
288
+ // Launch Claude Code with interceptor
289
+ await this.launchClaudeCode(apiKey, claudeArgs, options.debug || false);
290
+ }
291
+ catch (error) {
292
+ console.error('Error:', error.message);
293
+ process.exit(1);
294
+ }
295
+ }
296
+ }
297
+ exports.UnboundCli = UnboundCli;
298
+ // Run CLI if this file is executed directly
299
+ if (require.main === module) {
300
+ const cli = new UnboundCli();
301
+ cli.run(process.argv.slice(2));
302
+ }
303
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}