claude-overnight 1.17.2 → 1.17.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/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Your Max plan rate limits eat interactive coding time. One deep refactor and the 5-hour window is gone before lunch. `claude-overnight` runs background agent sessions up to the percentage cap you pick (90% is typical), leaving the rest free for your own Claude Code session. Hand it an objective and a session budget, walk away, review the diff when the run ends.
6
6
 
7
+ Cursor API Proxy supported -- route through Cursor's model gateway for Composer-powered execution on `auto`, `composer`, or `composer-2` models. See **Run via Cursor API Proxy** below.
8
+
7
9
  Isolated by default. Every agent runs in its own git worktree on its own branch, so a misbehaving agent can't trash your working tree. You choose what agents can do before the run starts -- no surprise escalation mid-flight. Unmerged branches are preserved for manual review, never discarded. Built on the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) -- not a Claude Code replacement, but a background lane that runs alongside it.
8
10
 
9
11
  Different shape from hosted agent harnesses like [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview): instead of one agent in one cloud container billed separately, you get many parallel sessions on your own machine, in your real repo, against your own Max plan (or API key). Works with Claude Opus, Sonnet, and Haiku -- or pair an Anthropic planner with a cheaper executor on Qwen, OpenRouter, or any Anthropic-compatible endpoint.
@@ -33,6 +35,39 @@ export ANTHROPIC_MODEL="qwen3.6-plus"
33
35
  claude-overnight
34
36
  ```
35
37
 
38
+ ## Run via Cursor API Proxy
39
+
40
+ Use Cursor's model gateway as an executor -- `auto` (delegates to best available), `composer`, or `composer-2` models. Runs locally through a proxy that speaks the Anthropic Messages API, so it's a drop-in replacement for any other provider.
41
+
42
+ 1. **Install the Cursor CLI and proxy:**
43
+
44
+ ```bash
45
+ curl https://cursor.com/install -fsS | bash
46
+ npm install -g cursor-api-proxy
47
+ ```
48
+
49
+ 2. **Get an API key.** Visit [cursor.com/dashboard/integrations](https://cursor.com/dashboard/integrations) and scroll to the "API Keys" section.
50
+
51
+ 3. **Set up.** Run `claude-overnight` and when prompted to pick a model, choose **Cursor…**. It walks you through a one-time setup: CLI check, API key entry (persisted to `providers.json`), and proxy health check.
52
+
53
+ 4. **Start the proxy** (in a separate terminal):
54
+
55
+ ```bash
56
+ npx cursor-api-proxy
57
+ ```
58
+
59
+ 5. Pick your model (`auto`, `composer`, `composer-2`, etc.). The provider is saved and reappears in every future run.
60
+
61
+ Or configure the key manually:
62
+
63
+ ```bash
64
+ export CURSOR_BRIDGE_API_KEY="sk-..."
65
+ npx cursor-api-proxy &
66
+ claude-overnight
67
+ ```
68
+
69
+ **Tip:** run `claude-overnight` with the `--model=cursor-auto` flag in non-interactive mode to skip the picker. If the proxy isn't running at startup, a warning is shown but Anthropic providers remain available.
70
+
36
71
  ## Install
37
72
 
38
73
  ```bash
@@ -17,6 +17,8 @@ export interface ProviderConfig {
17
17
  useJWT?: boolean;
18
18
  /** When true, this provider routes through cursor-api-proxy (special env/health-check handling). */
19
19
  cursorProxy?: boolean;
20
+ /** API key for cursor-api-proxy. Stored in providers.json (0600), used as fallback when CURSOR_BRIDGE_API_KEY env is not set. */
21
+ cursorApiKey?: string;
20
22
  }
21
23
  export declare function getStorePath(): string;
22
24
  export declare function loadProviders(): ProviderConfig[];
@@ -65,7 +67,7 @@ export declare function healthCheckCursorProxy(baseUrl?: string): Promise<boolea
65
67
  export declare function fetchCursorModels(baseUrl?: string): Promise<string[]>;
66
68
  /**
67
69
  * Interactive setup guide for cursor-api-proxy.
68
- * Walks through CLI install, login, and proxy start.
70
+ * Walks through CLI install, API key config, and proxy start.
69
71
  * Returns true when proxy is running and healthy.
70
72
  */
71
73
  export declare function setupCursorProxy(): Promise<boolean>;
package/dist/providers.js CHANGED
@@ -64,9 +64,9 @@ export function envFor(p) {
64
64
  if (v !== undefined)
65
65
  base[k] = v;
66
66
  if (p.cursorProxy) {
67
- // cursor-api-proxy: routes through local proxy, no real API key needed
68
67
  base.ANTHROPIC_BASE_URL = p.baseURL;
69
- base.ANTHROPIC_AUTH_TOKEN = process.env.CURSOR_BRIDGE_API_KEY || "unused";
68
+ const key = process.env.CURSOR_BRIDGE_API_KEY || p.cursorApiKey;
69
+ base.ANTHROPIC_AUTH_TOKEN = key || "unused";
70
70
  delete base.ANTHROPIC_API_KEY;
71
71
  return base;
72
72
  }
@@ -328,19 +328,14 @@ function setupSteps() {
328
328
  successMsg: "Cursor CLI found",
329
329
  },
330
330
  {
331
- label: "Cursor authentication",
331
+ label: "Cursor API key",
332
332
  check: () => {
333
- try {
334
- const out = execSync("agent --list-models", { stdio: "pipe", timeout: 10_000 });
335
- return out.toString().trim().length > 0;
336
- }
337
- catch {
338
- return false;
339
- }
333
+ const key = process.env.CURSOR_BRIDGE_API_KEY;
334
+ return !!key && key.trim().length > 0;
340
335
  },
341
- autoCmd: "agent login",
342
- manualCmd: "agent login",
343
- successMsg: "Cursor authenticated",
336
+ autoCmd: "",
337
+ manualCmd: "",
338
+ successMsg: "Cursor API key configured",
344
339
  },
345
340
  {
346
341
  label: "cursor-api-proxy server",
@@ -359,15 +354,51 @@ function setupSteps() {
359
354
  },
360
355
  ];
361
356
  }
357
+ const CURSOR_KEY_PROVIDER_ID = "cursor";
358
+ /** Persist the Cursor API key into providers.json. Updates any existing cursor proxy provider,
359
+ * or creates a sentinel entry so the key survives across sessions. */
360
+ function saveCursorApiKey(key) {
361
+ const existing = loadProviders().filter(p => p.cursorProxy);
362
+ if (existing.length > 0) {
363
+ const p = existing[0];
364
+ p.cursorApiKey = key;
365
+ saveProvider(p);
366
+ }
367
+ else {
368
+ const sentinel = {
369
+ id: CURSOR_KEY_PROVIDER_ID,
370
+ displayName: "Cursor (API key)",
371
+ baseURL: PROXY_DEFAULT_URL,
372
+ model: "auto",
373
+ cursorProxy: true,
374
+ cursorApiKey: key,
375
+ };
376
+ saveProvider(sentinel);
377
+ }
378
+ }
379
+ /** Prompt the user for a Cursor API key and persist it. Returns true if saved. */
380
+ async function promptAndSaveCursorKey() {
381
+ console.log(chalk.dim(` Get your API key from https://cursor.com/dashboard/integrations`));
382
+ console.log(chalk.dim(` (Scroll to the "API Keys" section at the bottom of the page)\n`));
383
+ const key = await ask(` ${chalk.cyan("API key")}: `);
384
+ if (key && key.trim()) {
385
+ const trimmed = key.trim();
386
+ process.env.CURSOR_BRIDGE_API_KEY = trimmed;
387
+ saveCursorApiKey(trimmed);
388
+ return true;
389
+ }
390
+ console.log(chalk.yellow(" No key provided — skipped"));
391
+ return false;
392
+ }
362
393
  /**
363
394
  * Interactive setup guide for cursor-api-proxy.
364
- * Walks through CLI install, login, and proxy start.
395
+ * Walks through CLI install, API key config, and proxy start.
365
396
  * Returns true when proxy is running and healthy.
366
397
  */
367
398
  export async function setupCursorProxy() {
368
399
  console.log(chalk.dim("\n Cursor API Proxy Setup"));
369
400
  console.log(chalk.dim(" " + "─".repeat(40)));
370
- console.log(chalk.dim(" We need three things: Cursor CLI, authentication, and the proxy server.\n"));
401
+ console.log(chalk.dim(" We need three things: Cursor CLI, an API key, and the proxy server.\n"));
371
402
  const steps = setupSteps();
372
403
  for (const step of steps) {
373
404
  if (step.check()) {
@@ -381,18 +412,10 @@ export async function setupCursorProxy() {
381
412
  { key: "s", desc: "kip (I'll handle it)" },
382
413
  ]);
383
414
  if (choice === "a") {
384
- if (step.label === "Cursor authentication") {
385
- // agent login needs interactive browser — run it directly
386
- console.log(chalk.dim(` Running: ${step.autoCmd}`));
387
- console.log(chalk.dim(" (A browser window will open for login)\n"));
388
- try {
389
- execSync(step.autoCmd, { stdio: "inherit", timeout: 120_000 });
415
+ if (step.label === "Cursor API key") {
416
+ if (await promptAndSaveCursorKey()) {
390
417
  console.log(chalk.green(` ✓ ${step.successMsg}`));
391
418
  }
392
- catch {
393
- console.log(chalk.yellow(" Login failed — try manual mode"));
394
- // Fall through to manual display
395
- }
396
419
  }
397
420
  else if (step.label === "cursor-api-proxy server") {
398
421
  // Don't auto-start the proxy server here — it blocks. Just verify it's installable.
@@ -428,10 +451,20 @@ export async function setupCursorProxy() {
428
451
  }
429
452
  }
430
453
  else if (choice === "m") {
431
- console.log(chalk.cyan(`\n Run this command:`));
432
- console.log(chalk.white(` ${step.manualCmd}`));
433
- if (step.label === "cursor-api-proxy server") {
434
- console.log(chalk.yellow(` Then start the proxy: ${chalk.bold("npx cursor-api-proxy")}`));
454
+ if (step.label === "Cursor API key") {
455
+ console.log(chalk.cyan(`\n 1. Open: https://cursor.com/dashboard/integrations`));
456
+ console.log(chalk.cyan(` 2. Scroll to "API Keys" at the bottom of the page`));
457
+ console.log(chalk.cyan(` 3. Copy your API key and paste it below\n`));
458
+ if (await promptAndSaveCursorKey()) {
459
+ console.log(chalk.green(` ✓ ${step.successMsg}`));
460
+ }
461
+ }
462
+ else {
463
+ console.log(chalk.cyan(`\n Run this command:`));
464
+ console.log(chalk.white(` ${step.manualCmd}`));
465
+ if (step.label === "cursor-api-proxy server") {
466
+ console.log(chalk.yellow(` Then start the proxy: ${chalk.bold("npx cursor-api-proxy")}`));
467
+ }
435
468
  }
436
469
  console.log();
437
470
  const done = await selectKey(` Done?`, [
@@ -500,13 +533,14 @@ async function pickCursorModel() {
500
533
  value: id,
501
534
  hint: cursorModelHint(id),
502
535
  })), 0);
503
- // Save as a cursor proxy provider
536
+ const existingKey = loadProviders().find(p => p.id === CURSOR_KEY_PROVIDER_ID)?.cursorApiKey;
504
537
  const provider = {
505
538
  id: `cursor-${picked}`,
506
539
  displayName: `Cursor: ${picked}`,
507
540
  baseURL: PROXY_DEFAULT_URL,
508
541
  model: picked,
509
542
  cursorProxy: true,
543
+ ...(existingKey ? { cursorApiKey: existingKey } : {}),
510
544
  };
511
545
  saveProvider(provider);
512
546
  console.log(chalk.green(` ✓ Saved as provider: ${provider.displayName}`));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-overnight",
3
- "version": "1.17.2",
4
- "description": "Background lane for your Claude Max plan. Parallel Claude Agent SDK sessions in git worktrees with a usage cap that reserves headroom for your interactive Claude Code. Crash-safe resume. Opus/Sonnet/Haiku + Qwen/OpenRouter.",
3
+ "version": "1.17.3",
4
+ "description": "Background lane for your Claude Max plan. Parallel Claude Agent SDK sessions in git worktrees with a usage cap that reserves headroom for your interactive Claude Code. Crash-safe resume. Opus/Sonnet/Haiku + Cursor API Proxy + Qwen/OpenRouter.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "claude-overnight": "dist/bin.js"
@@ -60,6 +60,7 @@
60
60
  "code-automation",
61
61
  "refactoring",
62
62
  "migration",
63
+ "cursor",
63
64
  "qwen",
64
65
  "openrouter",
65
66
  "iterative"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-overnight",
3
- "version": "1.17.2",
4
- "description": "Claude Code skill for understanding, installing, and inspecting claude-overnight runs -- parallel Claude agents in git worktrees with thinking waves, multi-wave steering, and crash-safe resume.",
3
+ "version": "1.17.3",
4
+ "description": "Claude Code skill for understanding, installing, and inspecting claude-overnight runs -- parallel Claude agents in git worktrees with thinking waves, multi-wave steering, and crash-safe resume. Supports Cursor API Proxy, Qwen, OpenRouter.",
5
5
  "author": {
6
6
  "name": "Francesco Fornace"
7
7
  },