claude-overnight 1.0.1 → 1.1.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 +19 -8
- package/dist/index.js +41 -15
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ claude-overnight
|
|
|
52
52
|
◆ Assessing... ✓ Vision met
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
You interact once (objective, budget, model, review themes), then everything runs autonomously — thinking, planning, executing, reflecting, steering. Rate-limited? It waits and retries. Crash? Resume where you left off.
|
|
55
|
+
You interact once (objective, budget, model, review themes), then everything runs autonomously — thinking, planning, executing, reflecting, steering. Rate-limited? It waits and retries. Crash? Resume where you left off. Capped at usage limit? Pick up next time with full context preserved.
|
|
56
56
|
|
|
57
57
|
## How it works
|
|
58
58
|
|
|
@@ -62,7 +62,7 @@ For budgets > 15, the tool launches **architect agents** that explore your codeb
|
|
|
62
62
|
|
|
63
63
|
### 2. Orchestration
|
|
64
64
|
|
|
65
|
-
An orchestrator agent reads all design documents and synthesizes concrete execution tasks — grounded in real files and patterns the architects found. No guesswork.
|
|
65
|
+
An orchestrator agent reads all design documents and synthesizes concrete execution tasks — grounded in real files and patterns the architects found. No guesswork. The task plan is also written to a file for resilience — if orchestration is interrupted, partial results survive.
|
|
66
66
|
|
|
67
67
|
### 3. Iterative execution
|
|
68
68
|
|
|
@@ -97,20 +97,30 @@ Every run gets its own folder in `.claude-overnight/runs/`. Nothing is ever over
|
|
|
97
97
|
run.json, sessions/
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
Any run that stops before the steering system declares the objective complete — capped at usage limit, Ctrl+C, crash, rate limit timeout, steering failure — is automatically resumable:
|
|
101
101
|
|
|
102
102
|
```
|
|
103
|
-
⚠
|
|
103
|
+
⚠ Unfinished run
|
|
104
104
|
╭──────────────────────────────────────────────────╮
|
|
105
105
|
│ refactor auth, add tests, update docs │
|
|
106
|
-
│ 50/200 sessions ·
|
|
106
|
+
│ 50/200 sessions · 150 remaining · $69.16 │
|
|
107
107
|
│ 34 merged · 16 unmerged · 0 failed branches │
|
|
108
108
|
╰──────────────────────────────────────────────────╯
|
|
109
109
|
|
|
110
110
|
Resume │ Fresh │ Quit
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
On resume: unmerged branches auto-merge, the wave loop continues, all context is preserved.
|
|
113
|
+
On resume: unmerged branches auto-merge, the wave loop continues, all context is preserved. Designs and reflections stay on disk until the objective is truly complete.
|
|
114
|
+
|
|
115
|
+
If the thinking phase succeeds but orchestration crashes, the next run detects the orphaned design docs and reuses them — no re-running $9 worth of architect agents:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
✓ Reusing 5 design docs (from prior attempt)
|
|
119
|
+
Focus 0: Project Wizard UI vs VISION.md Flow
|
|
120
|
+
Focus 1: Team Load and Rebalancer Surface
|
|
121
|
+
Focus 2: Code Health After Swarm Wave
|
|
122
|
+
...
|
|
123
|
+
```
|
|
114
124
|
|
|
115
125
|
**Knowledge carries forward** — new runs inherit knowledge from completed previous runs. Thinking agents and steering see what past runs built. Run 2 knows run 1 already built the auth system.
|
|
116
126
|
|
|
@@ -186,9 +196,10 @@ Built for unattended runs lasting hours or days.
|
|
|
186
196
|
|
|
187
197
|
- **Hard block**: pauses until the rate limit window resets, then resumes
|
|
188
198
|
- **Soft throttle**: slows dispatch at >75% utilization
|
|
199
|
+
- **Cooldown between phases**: waits for rate limit reset after thinking before starting orchestration
|
|
189
200
|
- **Retry with backoff**: transient errors (429, overloaded) retry automatically
|
|
190
|
-
- **Usage cap**: set a ceiling, active agents finish, no new ones start
|
|
191
|
-
- **Planner retries**: steering and orchestration
|
|
201
|
+
- **Usage cap**: set a ceiling, active agents finish, no new ones start — run is resumable
|
|
202
|
+
- **Planner retries**: steering and orchestration retry on rate limits (30s/60s/120s backoff) with full context
|
|
192
203
|
|
|
193
204
|
## Worktrees and merging
|
|
194
205
|
|
package/dist/index.js
CHANGED
|
@@ -606,9 +606,18 @@ async function main() {
|
|
|
606
606
|
console.log(chalk.dim(`\n ${completedRuns.length} previous run${completedRuns.length > 1 ? "s" : ""}`));
|
|
607
607
|
for (const r of completedRuns.slice(0, 3)) {
|
|
608
608
|
const date = r.state.startedAt?.slice(0, 10) || "unknown";
|
|
609
|
-
const obj = r.state.objective?.slice(0,
|
|
609
|
+
const obj = r.state.objective?.slice(0, 50) || "";
|
|
610
610
|
const cost = r.state.accCost > 0 ? ` · $${r.state.accCost.toFixed(0)}` : "";
|
|
611
|
-
|
|
611
|
+
const merged = r.state.branches.filter(b => b.status === "merged").length;
|
|
612
|
+
console.log(chalk.dim(` ${date} · ${r.state.accCompleted} done · ${merged} merged${cost}${obj ? ` · ${obj}` : ""}${obj.length >= 50 ? "…" : ""}`));
|
|
613
|
+
// Show status if available
|
|
614
|
+
let status = "";
|
|
615
|
+
try {
|
|
616
|
+
status = readFileSync(join(r.dir, "status.md"), "utf-8").trim().split("\n")[0].slice(0, 80);
|
|
617
|
+
}
|
|
618
|
+
catch { }
|
|
619
|
+
if (status)
|
|
620
|
+
console.log(chalk.dim(` ${status}`));
|
|
612
621
|
}
|
|
613
622
|
}
|
|
614
623
|
// ── Resume detection ──
|
|
@@ -628,10 +637,11 @@ async function main() {
|
|
|
628
637
|
lastStatus = readFileSync(join(incomplete.dir, "status.md"), "utf-8").trim().slice(0, 120);
|
|
629
638
|
}
|
|
630
639
|
catch { }
|
|
631
|
-
|
|
640
|
+
const label = "Unfinished run";
|
|
641
|
+
console.log(chalk.yellow(`\n ⚠ ${label}`));
|
|
632
642
|
const boxLines = [
|
|
633
643
|
`${obj}${obj.length >= 50 ? "…" : ""}`,
|
|
634
|
-
`${prev.accCompleted}/${prev.budget} sessions · ${prev.
|
|
644
|
+
`${prev.accCompleted}/${prev.budget} sessions · ${prev.remaining} remaining · $${prev.accCost.toFixed(2)}`,
|
|
635
645
|
];
|
|
636
646
|
if (lastStatus)
|
|
637
647
|
boxLines.push(lastStatus);
|
|
@@ -862,7 +872,17 @@ async function main() {
|
|
|
862
872
|
mkdirSync(designDir, { recursive: true });
|
|
863
873
|
const existingDesigns = readMdDir(designDir);
|
|
864
874
|
if (existingDesigns) {
|
|
865
|
-
|
|
875
|
+
const designFiles = readdirSync(designDir).filter(f => f.endsWith(".md")).sort();
|
|
876
|
+
console.log(chalk.green(`\n ✓ Reusing ${designFiles.length} design docs`) + chalk.dim(` (from prior attempt)`));
|
|
877
|
+
for (const f of designFiles) {
|
|
878
|
+
try {
|
|
879
|
+
const firstLine = readFileSync(join(designDir, f), "utf-8").split("\n")[0].replace(/^#+\s*/, "").trim();
|
|
880
|
+
if (firstLine)
|
|
881
|
+
console.log(chalk.dim(` ${firstLine.slice(0, 80)}`));
|
|
882
|
+
}
|
|
883
|
+
catch { }
|
|
884
|
+
}
|
|
885
|
+
console.log("");
|
|
866
886
|
}
|
|
867
887
|
else {
|
|
868
888
|
const thinkingTasks = buildThinkingTasks(objective, themes, designDir, plannerModel, previousKnowledge || undefined);
|
|
@@ -1030,7 +1050,7 @@ async function main() {
|
|
|
1030
1050
|
const waveHistory = [];
|
|
1031
1051
|
let accCost, accCompleted, accFailed, accTools;
|
|
1032
1052
|
let accIn = 0, accOut = 0;
|
|
1033
|
-
let lastCapped = false, lastAborted = false;
|
|
1053
|
+
let lastCapped = false, lastAborted = false, objectiveComplete = false;
|
|
1034
1054
|
let lastWaveKind;
|
|
1035
1055
|
let reflectionBudgetUsed;
|
|
1036
1056
|
const branches = [];
|
|
@@ -1193,6 +1213,7 @@ async function main() {
|
|
|
1193
1213
|
if (steer.done || steer.action === "done") {
|
|
1194
1214
|
console.log(chalk.green(` \u2713 ${steer.reasoning}\n`));
|
|
1195
1215
|
steerDone = true;
|
|
1216
|
+
objectiveComplete = true;
|
|
1196
1217
|
remaining = 0; // exit outer loop too
|
|
1197
1218
|
break;
|
|
1198
1219
|
}
|
|
@@ -1245,6 +1266,7 @@ async function main() {
|
|
|
1245
1266
|
// action === "execute"
|
|
1246
1267
|
if (steer.tasks.length === 0) {
|
|
1247
1268
|
console.log(chalk.green(` \u2713 ${steer.reasoning}\n`));
|
|
1269
|
+
objectiveComplete = true;
|
|
1248
1270
|
remaining = 0;
|
|
1249
1271
|
break;
|
|
1250
1272
|
}
|
|
@@ -1262,22 +1284,26 @@ async function main() {
|
|
|
1262
1284
|
}
|
|
1263
1285
|
waveNum++;
|
|
1264
1286
|
}
|
|
1265
|
-
//
|
|
1287
|
+
// Only truly "done" if steering explicitly completed the objective (or non-flex single wave with budget exhausted)
|
|
1288
|
+
const trulyDone = objectiveComplete || (!flex && remaining <= 0);
|
|
1289
|
+
const finalPhase = trulyDone ? "done" : "capped";
|
|
1266
1290
|
saveRunState(runDir, {
|
|
1267
1291
|
id: `run-${new Date().toISOString().slice(0, 19)}`, objective: objective ?? "", budget: budget ?? tasks.length,
|
|
1268
1292
|
remaining, workerModel, plannerModel, concurrency, permissionMode,
|
|
1269
1293
|
usageCap, flex, useWorktrees, mergeStrategy, waveNum, currentTasks: [],
|
|
1270
1294
|
lastWaveKind, reflectionBudgetUsed, accCost, accCompleted, accFailed,
|
|
1271
|
-
branches, phase:
|
|
1295
|
+
branches, phase: finalPhase, startedAt: new Date(runStartedAt).toISOString(), cwd,
|
|
1272
1296
|
});
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1297
|
+
if (trulyDone) {
|
|
1298
|
+
try {
|
|
1299
|
+
rmSync(join(runDir, "designs"), { recursive: true, force: true });
|
|
1300
|
+
}
|
|
1301
|
+
catch { }
|
|
1302
|
+
try {
|
|
1303
|
+
rmSync(join(runDir, "reflections"), { recursive: true, force: true });
|
|
1304
|
+
}
|
|
1305
|
+
catch { }
|
|
1279
1306
|
}
|
|
1280
|
-
catch { }
|
|
1281
1307
|
// Switch back if we created a run branch
|
|
1282
1308
|
if (runBranch && originalRef) {
|
|
1283
1309
|
try {
|
package/dist/types.d.ts
CHANGED
|
@@ -125,7 +125,7 @@ export interface RunState {
|
|
|
125
125
|
accCompleted: number;
|
|
126
126
|
accFailed: number;
|
|
127
127
|
branches: BranchRecord[];
|
|
128
|
-
phase: "executing" | "steering" | "reflecting" | "done";
|
|
128
|
+
phase: "executing" | "steering" | "reflecting" | "capped" | "done";
|
|
129
129
|
startedAt: string;
|
|
130
130
|
cwd: string;
|
|
131
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-overnight",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Run 10, 100, or 1000 Claude agents overnight. Parallel autonomous AI coding with thinking waves, iterative quality steering, crash recovery, and rate limit handling. Built on the Claude Agent SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|