claude-overnight 1.7.1 → 1.8.1
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/dist/index.js +48 -21
- package/dist/planner.js +6 -3
- package/dist/swarm.js +5 -4
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1573,35 +1573,62 @@ async function main() {
|
|
|
1573
1573
|
const elapsedStr = elapsed < 60 ? `${elapsed}s` : elapsed < 3600 ? `${Math.floor(elapsed / 60)}m ${elapsed % 60}s` : `${Math.floor(elapsed / 3600)}h ${Math.floor((elapsed % 3600) / 60)}m`;
|
|
1574
1574
|
const totalMerged = branches.filter(b => b.status === "merged").length;
|
|
1575
1575
|
const totalConflicts = branches.filter(b => b.status === "merge-failed").length;
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1576
|
+
const termW = Math.max((process.stdout.columns ?? 80) || 80, 50);
|
|
1577
|
+
// Banner
|
|
1578
|
+
console.log("");
|
|
1579
|
+
const bannerChar = accFailed === 0 ? "=" : "-";
|
|
1580
|
+
console.log(chalk.green(` ${bannerChar.repeat(Math.min(termW - 4, 60))}`));
|
|
1581
|
+
if (trulyDone) {
|
|
1582
|
+
console.log(chalk.bold.green(` CLAUDE OVERNIGHT — COMPLETE`));
|
|
1583
|
+
}
|
|
1584
|
+
else {
|
|
1585
|
+
console.log(chalk.bold.yellow(` CLAUDE OVERNIGHT — BUDGET EXHAUSTED`));
|
|
1586
|
+
}
|
|
1587
|
+
console.log(chalk.green(` ${bannerChar.repeat(Math.min(termW - 4, 60))}`));
|
|
1588
|
+
console.log("");
|
|
1589
|
+
// Stats grid
|
|
1590
|
+
const statRows = [
|
|
1591
|
+
[chalk.bold("Waves"), String(waves), chalk.bold("Sessions"), `${accCompleted} done${accFailed > 0 ? ` / ${accFailed} failed` : ""}`],
|
|
1592
|
+
[chalk.bold("Cost"), chalk.green(`$${accCost.toFixed(2)}`), chalk.bold("Elapsed"), elapsedStr],
|
|
1593
|
+
[chalk.bold("Merged"), `${totalMerged} branches`, chalk.bold("Conflicts"), totalConflicts > 0 ? chalk.red(String(totalConflicts)) : chalk.green("0")],
|
|
1594
|
+
[chalk.bold("Tokens"), `${fmtTokens(accIn)} in / ${fmtTokens(accOut)} out`, chalk.bold("Tool calls"), String(accTools)],
|
|
1595
|
+
];
|
|
1596
|
+
for (const [k1, v1, k2, v2] of statRows) {
|
|
1597
|
+
console.log(` ${k1} ${v1.padEnd(20)} ${k2} ${v2}`);
|
|
1598
|
+
}
|
|
1584
1599
|
if (overheadBudgetUsed > 0)
|
|
1585
|
-
|
|
1600
|
+
console.log(` ${chalk.bold("Overhead")} ${overheadBudgetUsed} agents (review/verify/explore)`);
|
|
1586
1601
|
if (lastCapped)
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1602
|
+
console.log(` ${chalk.yellow(`Capped at ${usageCap != null ? Math.round(usageCap * 100) : 100}%`)}`);
|
|
1603
|
+
console.log("");
|
|
1604
|
+
// Status summary (the product-level assessment from the planner)
|
|
1605
|
+
const statusFile = join(runDir, "status.md");
|
|
1606
|
+
if (existsSync(statusFile)) {
|
|
1607
|
+
const statusContent = readFileSync(statusFile, "utf-8").trim();
|
|
1608
|
+
if (statusContent) {
|
|
1609
|
+
console.log(chalk.dim(` ${"─".repeat(Math.min(termW - 4, 60))}`));
|
|
1610
|
+
console.log(chalk.bold(" Status"));
|
|
1611
|
+
console.log("");
|
|
1612
|
+
for (const line of statusContent.split("\n")) {
|
|
1613
|
+
console.log(` ${line}`);
|
|
1614
|
+
}
|
|
1615
|
+
console.log("");
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
// Conflicts detail
|
|
1595
1619
|
if (totalConflicts > 0) {
|
|
1620
|
+
console.log(chalk.dim(` ${"─".repeat(Math.min(termW - 4, 60))}`));
|
|
1596
1621
|
const conflictBranches = branches.filter(b => b.status === "merge-failed");
|
|
1597
|
-
console.log(chalk.red(
|
|
1622
|
+
console.log(chalk.red(` Unresolved conflicts:`));
|
|
1598
1623
|
for (const c of conflictBranches)
|
|
1599
1624
|
console.log(chalk.red(` ${c.branch}`));
|
|
1600
1625
|
console.log(chalk.dim(" git merge <branch> to resolve"));
|
|
1626
|
+
console.log("");
|
|
1601
1627
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1628
|
+
// Footer
|
|
1629
|
+
console.log(chalk.dim(` ${"─".repeat(Math.min(termW - 4, 60))}`));
|
|
1630
|
+
if (runBranch)
|
|
1631
|
+
console.log(chalk.dim(` Branch: ${runBranch} — git merge ${runBranch}`));
|
|
1605
1632
|
console.log(chalk.dim(` Run: ${runDir}`));
|
|
1606
1633
|
if (currentSwarm?.logFile)
|
|
1607
1634
|
console.log(chalk.dim(` Log: ${currentSwarm.logFile}`));
|
package/dist/planner.js
CHANGED
|
@@ -691,10 +691,10 @@ You have full creative freedom. Design the wave that will have the highest impac
|
|
|
691
691
|
**Synthesize** — An agent reads multiple alternatives or review findings and makes a decision. Writes the chosen approach or prioritized fix list.
|
|
692
692
|
Example: 1 agent reads 3 design docs and writes the implementation plan
|
|
693
693
|
|
|
694
|
-
**Verify** — Agents actually RUN the application: build it, start it, navigate it, click things, try edge cases. They report what works and what's broken. Not code reading — real testing.
|
|
694
|
+
**Verify** — Agents actually RUN the application: build it, start it, navigate it, click things, try edge cases. They report what works and what's broken. Not code reading — real testing. Always set "noWorktree": true so they run in the real project environment (env files, dependencies, config). Tell verify agents: you MUST get the app running and tested — do not give up. If auth is required, search the codebase for dev login routes, test tokens, seed users, env vars with keys/secrets, CLI auth commands, or any bypass. If a port is taken, use another. If a dependency is missing, install it. If a build fails, fix it or work around it. Exhaust every option before declaring something impossible.
|
|
695
695
|
Example: 1 agent does end-to-end QA, writing a report with reproduction steps
|
|
696
696
|
|
|
697
|
-
**User-test** — Agents emulate specific user personas interacting with the product. "First-time user who just downloaded this." "Power user trying to do X fast." They test from that perspective and report friction.
|
|
697
|
+
**User-test** — Agents emulate specific user personas interacting with the product. Always set "noWorktree": true. "First-time user who just downloaded this." "Power user trying to do X fast." They test from that perspective and report friction.
|
|
698
698
|
Example: 2 agents, one new user, one power user, each writing a report
|
|
699
699
|
|
|
700
700
|
**Polish** — Agents focus purely on feel: loading states, error messages, micro-interactions, empty states, responsiveness. Not features — the texture that makes users trust the product.
|
|
@@ -715,11 +715,13 @@ Respond with ONLY a JSON object (no markdown fences):
|
|
|
715
715
|
"statusUpdate": "REQUIRED — concise project status: what's built, what works, what's rough, quality level, key gaps. This replaces the previous status.",
|
|
716
716
|
"tasks": [
|
|
717
717
|
{"prompt": "task instruction...", "model": "worker"},
|
|
718
|
-
{"prompt": "review task...", "model": "planner"}
|
|
718
|
+
{"prompt": "review task...", "model": "planner"},
|
|
719
|
+
{"prompt": "verify the app end-to-end...", "model": "planner", "noWorktree": true}
|
|
719
720
|
]
|
|
720
721
|
}
|
|
721
722
|
|
|
722
723
|
The "model" field on each task: use "worker" (${workerModel}) for implementation tasks, "planner" (${plannerModel}) for review/analysis/verification tasks. Default is "worker".
|
|
724
|
+
Set "noWorktree": true for verify/user-test tasks — they run in the real project directory instead of an isolated worktree, with access to env files, installed dependencies, and local config.
|
|
723
725
|
|
|
724
726
|
If done: {"done": true, "waveKind": "done", "reasoning": "...", "statusUpdate": "...", "tasks": []}`;
|
|
725
727
|
onLog("Assessing...");
|
|
@@ -747,6 +749,7 @@ If done: {"done": true, "waveKind": "done", "reasoning": "...", "statusUpdate":
|
|
|
747
749
|
id: String(i),
|
|
748
750
|
prompt: typeof t === "string" ? t : t.prompt,
|
|
749
751
|
...(t.model && { model: t.model }),
|
|
752
|
+
...(t.noWorktree && { noWorktree: true }),
|
|
750
753
|
}));
|
|
751
754
|
tasks = postProcess(tasks, remainingBudget, onLog);
|
|
752
755
|
return { done: tasks.length === 0, tasks, reasoning: parsed.reasoning || "", waveKind: tasks.length === 0 ? "done" : waveKind, goalUpdate: parsed.goalUpdate, statusUpdate };
|
package/dist/swarm.js
CHANGED
|
@@ -202,7 +202,7 @@ export class Swarm {
|
|
|
202
202
|
this.agents.push(agent);
|
|
203
203
|
// Create worktree if enabled
|
|
204
204
|
let agentCwd = task.cwd || this.config.cwd;
|
|
205
|
-
if (this.config.useWorktrees && this.worktreeBase) {
|
|
205
|
+
if (this.config.useWorktrees && this.worktreeBase && !task.noWorktree) {
|
|
206
206
|
try {
|
|
207
207
|
const branch = `swarm/task-${id}`;
|
|
208
208
|
const dir = join(this.worktreeBase, `agent-${id}`);
|
|
@@ -238,11 +238,12 @@ export class Swarm {
|
|
|
238
238
|
let resumeSessionId;
|
|
239
239
|
let resumePrompt = "Continue. Complete the task.";
|
|
240
240
|
const runOnce = async (isResume) => {
|
|
241
|
+
const preamble = "Keep files under ~500 lines. If a file would exceed that, split it.\n\n";
|
|
241
242
|
const agentPrompt = isResume
|
|
242
243
|
? resumePrompt
|
|
243
|
-
: this.config.useWorktrees
|
|
244
|
-
? `You are working in an isolated git worktree. Focus only on this task. Do NOT commit your changes — the framework handles that.\n\n${task.prompt}`
|
|
245
|
-
: task.prompt
|
|
244
|
+
: this.config.useWorktrees && !task.noWorktree
|
|
245
|
+
? `You are working in an isolated git worktree. Focus only on this task. Do NOT commit your changes — the framework handles that.\n\n${preamble}${task.prompt}`
|
|
246
|
+
: `${preamble}${task.prompt}`;
|
|
246
247
|
const agentQuery = query({
|
|
247
248
|
prompt: agentPrompt,
|
|
248
249
|
options: {
|
package/dist/types.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface Task {
|
|
|
8
8
|
cwd?: string;
|
|
9
9
|
/** Claude model override for this specific task (e.g. "sonnet", "opus"). */
|
|
10
10
|
model?: string;
|
|
11
|
+
/** When true, skip worktree isolation — run in the real project directory with env files, dependencies, and local config. */
|
|
12
|
+
noWorktree?: boolean;
|
|
11
13
|
}
|
|
12
14
|
/** Schema for a JSON task file that defines a batch of work for the swarm. */
|
|
13
15
|
export interface TaskFile {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-overnight",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
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": {
|