claude-overnight 1.17.1 → 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 +35 -0
- package/dist/providers.d.ts +3 -1
- package/dist/providers.js +64 -30
- package/package.json +3 -2
- package/plugins/claude-overnight/.claude-plugin/plugin.json +2 -2
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
|
package/dist/providers.d.ts
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
|
331
|
+
label: "Cursor API key",
|
|
332
332
|
check: () => {
|
|
333
|
-
|
|
334
|
-
|
|
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: "
|
|
342
|
-
manualCmd: "
|
|
343
|
-
successMsg: "Cursor
|
|
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,
|
|
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,
|
|
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
|
|
385
|
-
|
|
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
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
console.log(chalk.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
},
|