antigravity-claude-proxy 2.7.8 → 2.8.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 CHANGED
@@ -1,5 +1,3 @@
1
- # ⚠️ DO NOT USE THIS ANYMORE – GOOGLE IS ISSUING TOS VIOLATION BANS FOR THE ACCOUNTS CONNECTED
2
-
3
1
  # Antigravity Claude Proxy
4
2
 
5
3
  [![npm version](https://img.shields.io/npm/v/antigravity-claude-proxy.svg)](https://www.npmjs.com/package/antigravity-claude-proxy)
@@ -10,6 +8,8 @@ A proxy server that exposes an **Anthropic-compatible API** backed by **Antigrav
10
8
 
11
9
  ![Antigravity Claude Proxy Banner](images/banner.png)
12
10
 
11
+ > **⚠️ WARNING:** Google has been issuing ToS violation bans on accounts connected to this proxy. Use at your own risk.
12
+
13
13
  <details>
14
14
  <summary><strong>⚠️ Terms of Service Warning — Read Before Installing</strong></summary>
15
15
 
@@ -83,8 +83,9 @@ npm start
83
83
  ### 1. Start the Proxy Server
84
84
 
85
85
  ```bash
86
- # If installed via npm
87
- antigravity-claude-proxy start
86
+ # If installed globally
87
+ acc start
88
+ # or: antigravity-claude-proxy start
88
89
 
89
90
  # If using npx
90
91
  npx antigravity-claude-proxy@latest start
@@ -93,7 +94,16 @@ npx antigravity-claude-proxy@latest start
93
94
  npm start
94
95
  ```
95
96
 
96
- The server runs on `http://localhost:8080` by default.
97
+ The server launches as a **background process** on `http://localhost:8080` by default and survives terminal closure.
98
+
99
+ | Command | Description |
100
+ | :--- | :--- |
101
+ | `acc start` | Launch proxy in the background |
102
+ | `acc stop` | Shut down the proxy |
103
+ | `acc restart` | Restart the proxy |
104
+ | `acc status` | Check proxy health and PID |
105
+ | `acc ui` | Open the web dashboard |
106
+ | `acc start --log` | Run in foreground with visible logs |
97
107
 
98
108
  ### 2. Link Account(s)
99
109
 
package/bin/cli.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  import { fileURLToPath } from 'url';
4
4
  import { dirname, join } from 'path';
5
- import { readFileSync } from 'fs';
5
+ import { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from 'fs';
6
+ import { spawn, exec } from 'child_process';
6
7
 
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = dirname(__filename);
@@ -12,47 +13,408 @@ const packageJson = JSON.parse(
12
13
  readFileSync(join(__dirname, '..', 'package.json'), 'utf-8')
13
14
  );
14
15
 
16
+ // PID file location for background process management
17
+ const CONFIG_DIR = join(process.env.HOME || process.env.USERPROFILE || '', '.config', 'antigravity-proxy');
18
+ const PID_FILE = join(CONFIG_DIR, 'server.pid');
19
+
15
20
  const args = process.argv.slice(2);
16
21
  const command = args[0];
17
22
 
23
+ // Ensure config directory exists
24
+ function ensureConfigDir() {
25
+ if (!existsSync(CONFIG_DIR)) {
26
+ mkdirSync(CONFIG_DIR, { recursive: true });
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Check if the service is running by reading PID file and verifying process
32
+ */
33
+ function isServiceRunning() {
34
+ if (!existsSync(PID_FILE)) {
35
+ return false;
36
+ }
37
+
38
+ try {
39
+ const pidStr = readFileSync(PID_FILE, 'utf-8');
40
+ const pid = parseInt(pidStr, 10);
41
+ if (isNaN(pid)) {
42
+ cleanupPidFile();
43
+ return false;
44
+ }
45
+
46
+ // Check if process is running (signal 0 doesn't kill, just checks)
47
+ process.kill(pid, 0);
48
+ return true;
49
+ } catch (e) {
50
+ // Process doesn't exist
51
+ cleanupPidFile();
52
+ return false;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Get the PID of the running service
58
+ */
59
+ function getServicePid() {
60
+ if (!existsSync(PID_FILE)) {
61
+ return null;
62
+ }
63
+ try {
64
+ const pid = parseInt(readFileSync(PID_FILE, 'utf-8'), 10);
65
+ return isNaN(pid) ? null : pid;
66
+ } catch (e) {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Save PID to file
73
+ */
74
+ function savePid(pid) {
75
+ if (!existsSync(CONFIG_DIR)) {
76
+ mkdirSync(CONFIG_DIR, { recursive: true });
77
+ }
78
+ writeFileSync(PID_FILE, pid.toString());
79
+ }
80
+
81
+ /**
82
+ * Clean up PID file
83
+ */
84
+ function cleanupPidFile() {
85
+ if (existsSync(PID_FILE)) {
86
+ try {
87
+ unlinkSync(PID_FILE);
88
+ } catch (e) {
89
+ // Ignore cleanup errors
90
+ }
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Get current port from environment or default
96
+ */
97
+ function getPort() {
98
+ return process.env.PORT || 8080;
99
+ }
100
+
101
+ /**
102
+ * Wait for service to be ready
103
+ */
104
+ async function waitForService(timeout = 10000, initialDelay = 1000) {
105
+ await new Promise(resolve => setTimeout(resolve, initialDelay));
106
+
107
+ const startTime = Date.now();
108
+ while (Date.now() - startTime < timeout) {
109
+ if (isServiceRunning()) {
110
+ // Additional wait to ensure service is fully ready
111
+ await new Promise(resolve => setTimeout(resolve, 500));
112
+ return true;
113
+ }
114
+ await new Promise(resolve => setTimeout(resolve, 100));
115
+ }
116
+ return false;
117
+ }
118
+
119
+ /**
120
+ * Start the server as a background process (or foreground with --log)
121
+ */
122
+ async function startServer() {
123
+ // Check for --log flag
124
+ const logMode = args.includes('--log');
125
+
126
+ if (isServiceRunning() && !logMode) {
127
+ console.log('');
128
+ console.log('╭' + '─'.repeat(48) + '╮');
129
+ console.log('│ 🛸 Antigravity Proxy is already in orbit │');
130
+ console.log('╰' + '─'.repeat(48) + '╯');
131
+ console.log('');
132
+
133
+ const pid = getServicePid();
134
+ const port = getPort();
135
+ console.log(` ┌─ PID: ${pid}`);
136
+ console.log(` ├─ Local: http://localhost:${port}`);
137
+ console.log(` └─ Dashboard: http://localhost:${port}`);
138
+ console.log('');
139
+ return;
140
+ }
141
+
142
+ console.log('');
143
+ if (logMode) {
144
+ console.log('🌌 Launching Antigravity Proxy (foreground mode)...');
145
+ console.log(' Press Ctrl+C to stop');
146
+ console.log('');
147
+ } else {
148
+ console.log('🌌 Launching Antigravity Proxy...');
149
+ }
150
+
151
+ const serverScript = join(__dirname, '..', 'src', 'index.js');
152
+ const port = getPort();
153
+
154
+ // Filter out --log from args passed to server
155
+ const serverArgs = args.slice(1).filter(arg => arg !== '--log');
156
+
157
+ if (logMode) {
158
+ // Foreground mode - show logs directly
159
+ const serverProcess = spawn('node', [serverScript, ...serverArgs], {
160
+ stdio: 'inherit', // Show output in current terminal
161
+ env: { ...process.env, PORT: port.toString() }
162
+ });
163
+
164
+ serverProcess.on('error', (error) => {
165
+ console.error('');
166
+ console.error('⚠️ Launch failed:', error.message);
167
+ console.error('');
168
+ process.exit(1);
169
+ });
170
+
171
+ serverProcess.on('exit', (code) => {
172
+ console.log('');
173
+ console.log('🌙 Proxy has exited');
174
+ console.log('');
175
+ process.exit(code || 0);
176
+ });
177
+
178
+ // Keep process running
179
+ return;
180
+ }
181
+
182
+ // Background mode - detached process
183
+ const serverProcess = spawn('node', [serverScript, ...serverArgs], {
184
+ detached: true,
185
+ stdio: 'ignore',
186
+ env: { ...process.env, PORT: port.toString() }
187
+ });
188
+
189
+ serverProcess.on('error', (error) => {
190
+ console.error('');
191
+ console.error('⚠️ Launch failed:', error.message);
192
+ console.error('');
193
+ process.exit(1);
194
+ });
195
+
196
+ // Save PID and detach
197
+ savePid(serverProcess.pid);
198
+ serverProcess.unref();
199
+
200
+ // Wait for service to be ready
201
+ if (await waitForService()) {
202
+ console.log('╭' + '─'.repeat(48) + '╮');
203
+ console.log('│ ⚡ Proxy is now in orbit! │');
204
+ console.log('╰' + '─'.repeat(48) + '╯');
205
+
206
+ console.log('');
207
+ console.log(' ┌─ Process ID:', serverProcess.pid);
208
+ console.log(' ├─ Local:', `http://localhost:${port}`);
209
+ console.log(' └─ Dashboard:', `http://localhost:${port}/`);
210
+ console.log('');
211
+ console.log(' Next steps:');
212
+ console.log(' • acc ui → Open dashboard');
213
+ console.log(' • acc status → View proxy health');
214
+ console.log(' • acc stop → Shut down proxy');
215
+ console.log('');
216
+ } else {
217
+ console.error('');
218
+ console.error('⚠️ Proxy launched but health check timed out');
219
+ console.log(` Try: curl http://localhost:${port}/health`);
220
+ console.error('');
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Stop the running server
226
+ */
227
+ function stopServer() {
228
+ if (!isServiceRunning()) {
229
+ console.log('');
230
+ console.log('🌑 Proxy is not running');
231
+ console.log('');
232
+ cleanupPidFile();
233
+ return;
234
+ }
235
+
236
+ const pid = getServicePid();
237
+ try {
238
+ process.kill(pid, 'SIGTERM');
239
+ cleanupPidFile();
240
+ console.log('');
241
+ console.log('🌙 Proxy has been taken offline');
242
+ console.log('');
243
+ } catch (e) {
244
+ console.error('');
245
+ console.error('⚠️ Shutdown failed:', e.message);
246
+ console.error('');
247
+ cleanupPidFile();
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Restart the server
253
+ */
254
+ async function restartServer() {
255
+ console.log('');
256
+ console.log('♻️ Restarting proxy...');
257
+ console.log('');
258
+
259
+ // Stop if running
260
+ if (isServiceRunning()) {
261
+ const pid = getServicePid();
262
+ try {
263
+ process.kill(pid, 'SIGTERM');
264
+ cleanupPidFile();
265
+ console.log(' └─ Existing instance stopped');
266
+ console.log('');
267
+ // Wait for process to fully terminate
268
+ await new Promise(resolve => setTimeout(resolve, 1000));
269
+ } catch (e) {
270
+ console.log(' └─ No previous instance found');
271
+ console.log('');
272
+ cleanupPidFile();
273
+ }
274
+ }
275
+
276
+ // Start fresh
277
+ await startServer();
278
+ }
279
+
280
+ /**
281
+ * Show server status
282
+ */
283
+ function showStatus() {
284
+ console.log('');
285
+ console.log('╭' + '─'.repeat(48) + '╮');
286
+ console.log('│ 🛸 Antigravity Claude Proxy │');
287
+ console.log('╰' + '─'.repeat(48) + '╯');
288
+ console.log('');
289
+
290
+ if (isServiceRunning()) {
291
+ const pid = getServicePid();
292
+ const port = getPort();
293
+ console.log(' STATUS');
294
+ console.log(' ⚡ Proxy is active');
295
+ console.log('');
296
+ console.log(' DETAILS');
297
+ console.log(` ├─ PID: ${pid}`);
298
+ console.log(` ├─ Port: ${port}`);
299
+ console.log(` ├─ API: http://localhost:${port}`);
300
+ console.log(` └─ Dashboard: http://localhost:${port}/`);
301
+ console.log('');
302
+ console.log(' AVAILABLE COMMANDS');
303
+ console.log(' • acc ui Open dashboard');
304
+ console.log(' • acc restart Relaunch proxy');
305
+ console.log(' • acc stop Take offline');
306
+ } else {
307
+ console.log(' STATUS');
308
+ console.log(' 🌑 Proxy is offline');
309
+ console.log('');
310
+ console.log(' TO LAUNCH');
311
+ console.log(' • acc start Bring proxy online');
312
+ }
313
+ console.log('');
314
+ }
315
+
316
+ /**
317
+ * Open WebUI in browser
318
+ */
319
+ async function openUI() {
320
+ // Start server if not running
321
+ if (!isServiceRunning()) {
322
+ console.log('');
323
+ console.log('🌌 Proxy offline - launching now...');
324
+ await startServer();
325
+ // Wait for it to be fully ready
326
+ await new Promise(resolve => setTimeout(resolve, 1000));
327
+ }
328
+
329
+ const port = getPort();
330
+ const uiUrl = `http://localhost:${port}/`;
331
+
332
+ console.log('');
333
+ console.log(`🖥️ Opening dashboard → ${uiUrl}`);
334
+ console.log('');
335
+
336
+ // Open URL in browser based on platform
337
+ const platform = process.platform;
338
+ let openCommand = '';
339
+
340
+ if (platform === 'win32') {
341
+ openCommand = `start ${uiUrl}`;
342
+ } else if (platform === 'darwin') {
343
+ openCommand = `open ${uiUrl}`;
344
+ } else if (platform === 'linux') {
345
+ openCommand = `xdg-open ${uiUrl}`;
346
+ } else {
347
+ console.error('⚠️ Cannot auto-open browser on this platform');
348
+ console.log(` Manual URL: ${uiUrl}`);
349
+ console.log('');
350
+ return;
351
+ }
352
+
353
+ exec(openCommand, (error) => {
354
+ if (error) {
355
+ console.error('⚠️ Browser launch failed:', error.message);
356
+ console.log(` Manual URL: ${uiUrl}`);
357
+ console.log('');
358
+ }
359
+ });
360
+ }
361
+
18
362
  function showHelp() {
19
363
  console.log(`
20
- antigravity-claude-proxy v${packageJson.version}
364
+ ╭${'─'.repeat(58)}
365
+ │ 🛸 Antigravity Claude Proxy v${packageJson.version.padEnd(27)}│
366
+ ╰${'─'.repeat(58)}╯
21
367
 
22
- Proxy server for using Antigravity's Claude models with Claude Code CLI.
368
+ Route Claude Code CLI through Antigravity's multi-model API
369
+ with intelligent load balancing across Google accounts.
23
370
 
24
- USAGE:
371
+ USAGE
25
372
  antigravity-claude-proxy <command> [options]
373
+ acc <command> [options] ← shorthand
374
+
375
+ ━━━ PROXY CONTROL ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
376
+ start Launch proxy as background service
377
+ stop Shut down the proxy
378
+ restart Relaunch the proxy
379
+ status View proxy health and details
380
+ ui Open dashboard in browser
381
+
382
+ ━━━ ACCOUNT MANAGEMENT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
383
+ accounts Interactive account menu
384
+ accounts add Add Google account via OAuth
385
+ accounts list Show all linked accounts
386
+ accounts remove Unlink accounts
387
+ accounts verify Check account health
388
+ accounts clear Remove all accounts
389
+
390
+ ━━━ OPTIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
391
+ --help, -h Show this help
392
+ --version, -v Show version
393
+ --log Run in foreground with visible logs
394
+ --strategy=NAME Load balancing: hybrid (default),
395
+ sticky (cache-optimized), round-robin
396
+ --fallback Enable model fallback on errors
26
397
 
27
- COMMANDS:
28
- start Start the proxy server (default port: 8080)
29
- accounts Manage Google accounts (interactive)
30
- accounts add Add a new Google account via OAuth
31
- accounts list List all configured accounts
32
- accounts remove Remove accounts interactively
33
- accounts verify Verify account tokens are valid
34
- accounts clear Remove all accounts
35
-
36
- OPTIONS:
37
- --help, -h Show this help message
38
- --version, -v Show version number
39
-
40
- ENVIRONMENT:
41
- PORT Server port (default: 8080)
42
-
43
- EXAMPLES:
44
- antigravity-claude-proxy start
45
- PORT=3000 antigravity-claude-proxy start
46
- antigravity-claude-proxy accounts add
47
- antigravity-claude-proxy accounts list
48
-
49
- CONFIGURATION:
50
- Claude Code CLI (~/.claude/settings.json):
51
- {
52
- "env": {
53
- "ANTHROPIC_BASE_URL": "http://localhost:8080"
54
- }
398
+ ━━━ ENVIRONMENT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
399
+ PORT Custom port (default: 8080)
400
+
401
+ ━━━ EXAMPLES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
402
+ acc start Launch proxy
403
+ acc start --log Launch with visible logs
404
+ acc ui Open dashboard
405
+ PORT=3000 acc start Use custom port
406
+ acc start --strategy=sticky Optimize for prompt caching
407
+ acc accounts add Link new Google account
408
+
409
+ ━━━ CLAUDE CODE SETUP ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
410
+ Edit ~/.claude/settings.json:
411
+ {
412
+ "env": {
413
+ "ANTHROPIC_BASE_URL": "http://localhost:8080"
55
414
  }
415
+ }
416
+
417
+ Docs: https://github.com/badrisnarayanan/antigravity-claude-proxy
56
418
  `);
57
419
  }
58
420
 
@@ -75,9 +437,23 @@ async function main() {
75
437
  // Handle commands
76
438
  switch (command) {
77
439
  case 'start':
78
- case undefined:
79
- // Default to starting the server
80
- await import('../src/index.js');
440
+ await startServer();
441
+ break;
442
+
443
+ case 'stop':
444
+ stopServer();
445
+ break;
446
+
447
+ case 'restart':
448
+ await restartServer();
449
+ break;
450
+
451
+ case 'status':
452
+ showStatus();
453
+ break;
454
+
455
+ case 'ui':
456
+ await openUI();
81
457
  break;
82
458
 
83
459
  case 'accounts': {
@@ -96,9 +472,14 @@ async function main() {
96
472
  showVersion();
97
473
  break;
98
474
 
475
+ case undefined:
476
+ // No command - show help
477
+ showHelp();
478
+ break;
479
+
99
480
  default:
100
481
  console.error(`Unknown command: ${command}`);
101
- console.error('Run "antigravity-proxy --help" for usage information.');
482
+ console.error('Run "acc --help" for usage information.');
102
483
  process.exit(1);
103
484
  }
104
485
  }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "antigravity-claude-proxy",
3
- "version": "2.7.8",
3
+ "version": "2.8.0",
4
4
  "description": "Proxy server to use Antigravity's Claude models with Claude Code CLI",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "antigravity-claude-proxy": "bin/cli.js"
8
+ "antigravity-claude-proxy": "bin/cli.js",
9
+ "acc": "bin/cli.js"
9
10
  },
10
11
  "files": [
11
12
  "src",