claude-overnight 1.16.2 → 1.16.4

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,10 +1,10 @@
1
1
  # claude-overnight
2
2
 
3
- Run 10, 100, or 1000 Claude agents overnight. Come back to shipped work.
3
+ **Run 10, 100, or 1000 Claude agents overnight.** A local multi-session orchestrator for the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) parallel Claude agent sessions in isolated git worktrees, spend caps, rate-limit handling, and crash-safe resume across days. Press Run and go to sleep.
4
4
 
5
- Local-first, git-native, budget-first. Describe what to build, set a spend cap, press Run. The tool plans, explores your codebase, breaks the objective into tasks, launches parallel agents in isolated git worktrees, iterates toward quality, handles rate limits automatically, and resumes cleanly across crashes and laptop sleeps. You wake up to merged commits.
5
+ Local-first, git-native, budget-first. Describe what to build, set a spend cap, press Run. The tool plans with a thinking wave of architect sessions, breaks the objective into concrete tasks, launches parallel agent sessions in isolated git worktrees, iterates toward quality with a planner/executor/reflection loop, handles rate limits automatically, and resumes cleanly across crashes, rate-limit windows, and laptop sleeps. You wake up to merged commits.
6
6
 
7
- Different shape from hosted single-session runtimes like [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview): this runs on your machine, against your real repo, as a parallel swarm with spend caps, git worktree choreography, and multi-day crash-safe resume. Built on the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk). Works with Claude Opus, Sonnet, and Haiku — or route executors to Qwen / OpenRouter / any Anthropic-compatible endpoint via the `Other…` picker.
7
+ Different shape from hosted single-session agent harnesses like [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview): instead of one agent in one cloud container, you get many parallel agent sessions running on your own machine, in your real repo, coordinated by multi-wave steering. Works with Claude Opus, Sonnet, and Haiku — or pair an Anthropic planner with a cheaper executor on Qwen, OpenRouter, or any Anthropic-compatible endpoint via the `Other…` picker.
8
8
 
9
9
  ## Install
10
10
 
@@ -12,16 +12,7 @@ Different shape from hosted single-session runtimes like [Claude Managed Agents]
12
12
  npm install -g claude-overnight
13
13
  ```
14
14
 
15
- Requires Node.js >= 20 and Claude authentication (`claude auth login`, or set `ANTHROPIC_API_KEY`).
16
-
17
- ### Claude Code plugin
18
-
19
- This repo also ships a Claude Code plugin so any Claude instance (inside this repo or any other) knows how to use, inspect, and resume `claude-overnight` runs:
20
-
21
- ```
22
- /plugin marketplace add Fornace/claude-overnight
23
- /plugin install claude-overnight
24
- ```
15
+ Requires Node.js 20 and Claude authentication (`claude auth login` or `ANTHROPIC_API_KEY`).
25
16
 
26
17
  ## Quick start
27
18
 
@@ -73,31 +64,55 @@ claude-overnight
73
64
 
74
65
  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.
75
66
 
67
+ ## How is this different?
68
+
69
+ Claude already has several ways to run agents. `claude-overnight` fills a specific niche:
70
+
71
+ - **Claude Code** — interactive pair programming in your terminal. One agent, one conversation, you drive. `claude-overnight` is the inverse: many agents, no driver, you walk away and come back to merged commits.
72
+ - **[Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview)** — a hosted single-session agent harness. One agent, one cloud container, stateful conversation. `claude-overnight` is a local multi-session *orchestrator* built on the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk): many parallel sessions on your machine, in your real repo, with spend caps and multi-day crash-safe resume.
73
+ - **[Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk)** — primitives for building your own agent. `claude-overnight` is one specific thing built on top of it: an overnight swarm orchestrator you didn't have to write.
74
+ - **IDE copilots (Cursor, Copilot, Cline, etc.)** — synchronous assistants that complete while you're at the keyboard. `claude-overnight` is asynchronous: you hand off an objective and a budget, close the laptop lid, and review a branch in the morning.
75
+
76
+ If you want to hand an objective and a spend cap to Claude and wake up to shipped work on your real repo, this is the shape.
77
+
78
+ ## Use cases
79
+
80
+ - **Overnight refactors** — "Modernize the auth system" at budget 200.
81
+ - **Batch feature implementation** — dozens of features from a task file, parallelized.
82
+ - **Codebase-wide cleanups** — deduplicate, simplify, rename, normalize.
83
+ - **Test generation at scale** — integration tests for every route or module.
84
+ - **Documentation sprints** — API docs, READMEs, inline comments, changelogs.
85
+ - **Framework migrations** — version upgrades, type annotations, config format swaps.
86
+ - **Quality audits** — reflection waves surface architectural issues and code smells.
87
+ - **Long research runs** — architect sessions explore a large codebase before any code lands.
88
+
89
+ Typical shape: one objective + a $20–$200 spend cap + sleep.
90
+
76
91
  ## How it works
77
92
 
78
- ### 1. Thinking wave
93
+ ### 1. Thinking wave — parallel architect sessions
79
94
 
80
95
  For budgets > 15, the tool launches **architect agents** that explore your codebase before any code is written. Each one gets a different research angle (architecture, data models, APIs, testing, etc.) and writes a structured design document. The number scales with budget: 5 for budget=50, 10 for budget=2000.
81
96
 
82
- ### 2. Orchestration
97
+ ### 2. Task orchestration
83
98
 
84
- 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.
99
+ An orchestrator session 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.
85
100
 
86
- ### 3. Iterative execution
101
+ ### 3. Parallel execution waves
87
102
 
88
- Tasks run in parallel (each agent in its own git worktree). After completing its task, each agent automatically runs a **simplify pass** — reviewing its own `git diff` for code reuse opportunities, quality issues, and inefficiencies, then fixing them before the framework commits.
103
+ Tasks run in parallel agent sessions (each in its own git worktree). After completing its task, each session automatically runs a **simplify pass** — reviewing its own `git diff` for code reuse opportunities, quality issues, and inefficiencies, then fixing them before the framework commits.
89
104
 
90
105
  After each wave, steering assesses: "how good is this?" — not "what's missing?" It can:
91
106
 
92
107
  - **Execute** more tasks to build features, fix bugs, polish UX
93
- - **Reflect** by spinning up 1-2 review agents for deep quality/architecture audits
108
+ - **Reflect** by spinning up 1-2 review sessions for deep quality/architecture audits
94
109
  - **Declare done** when the vision is met at high quality
95
110
 
96
- ### 4. Goal refinement
111
+ ### 4. Goal refinement and steering
97
112
 
98
113
  The tool starts with your broad objective but evolves its definition of "amazing" as it learns your codebase. Steering refines the goal after each wave. Late waves are informed by early discoveries.
99
114
 
100
- ### 5. Three-layer context
115
+ ### 5. Three-layer context memory
101
116
 
102
117
  Long runs stay sharp because steering maintains three layers of memory:
103
118
 
@@ -105,7 +120,7 @@ Long runs stay sharp because steering maintains three layers of memory:
105
120
  - **Milestones** — strategic snapshots archived every ~5 waves. Long-term memory.
106
121
  - **Goal** — the evolving north star. What "amazing" means for this codebase.
107
122
 
108
- ## Run history and resume
123
+ ## Run history, resume, and knowledge carryforward
109
124
 
110
125
  Every run gets its own folder in `.claude-overnight/runs/`. Nothing is ever overwritten.
111
126
 
@@ -133,7 +148,7 @@ Any run that stops before the steering system declares the objective complete
133
148
 
134
149
  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.
135
150
 
136
- 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:
151
+ 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 sessions:
137
152
 
138
153
  ```
139
154
  ✓ Reusing 5 design docs (from prior attempt)
@@ -143,15 +158,13 @@ If the thinking phase succeeds but orchestration crashes, the next run detects t
143
158
  ...
144
159
  ```
145
160
 
146
- **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.
161
+ **Knowledge carries forward** — new runs inherit knowledge from completed previous runs. Thinking sessions and steering see what past runs built. Run 2 knows run 1 already built the auth system.
147
162
 
148
163
  Add `.claude-overnight/` to your `.gitignore` (with the trailing slash — see below).
149
164
 
150
165
  A separate, tiny `claude-overnight.log.md` is also written at the repo root on every run. It's human-readable, append-only, one block per run (objective, start/finish, cost, outcome, branch), and is designed to be **committed** — so even after `.claude-overnight/` is cleaned up you can still recover which prompt produced which commits. Use `.claude-overnight/` (with trailing slash) in your gitignore so this file isn't matched by accident.
151
166
 
152
- ## Other usage modes
153
-
154
- ### Task file
167
+ ## Task file and inline modes
155
168
 
156
169
  ```bash
157
170
  claude-overnight tasks.json
@@ -181,7 +194,7 @@ For multi-wave runs, add `objective` and `flexiblePlan`:
181
194
  }
182
195
  ```
183
196
 
184
- ### Inline
197
+ Inline:
185
198
 
186
199
  ```bash
187
200
  claude-overnight "fix auth bug in src/auth.ts" "add tests for user model"
@@ -215,7 +228,7 @@ claude-overnight "fix auth bug in src/auth.ts" "add tests for user model"
215
228
  | `mergeStrategy` | `"yolo" \| "branch"` | `"yolo"` | Merge into HEAD or new branch |
216
229
  | `usageCap` | `number (0-100)` | unlimited | Stop at N% utilization |
217
230
 
218
- ## Custom providers (Qwen, OpenRouter, anything Anthropic-compatible)
231
+ ## Custom providers (Qwen, OpenRouter, any Anthropic-compatible endpoint)
219
232
 
220
233
  Planner and executor are picked separately — pair Opus-on-Anthropic for the planner/thinker with a cheaper model on another provider for the bulk of execution.
221
234
 
@@ -245,7 +258,7 @@ Saved providers live user-level at `~/.claude/claude-overnight/providers.json` (
245
258
 
246
259
  **Non-interactive / CI.** `claude-overnight --model=qwen3-coder-plus` auto-resolves the model id to a saved provider — no separate `--provider` flag.
247
260
 
248
- ## Usage controls
261
+ ## Spend caps and usage controls
249
262
 
250
263
  ### Extra usage protection
251
264
 
@@ -272,7 +285,7 @@ The usage bar cycles through all rate limit windows (5h, 7d, etc.) every 3 secon
272
285
 
273
286
  When using extra usage with a budget, a dedicated progress bar shows spend vs limit with color-coded fill (magenta → yellow → red).
274
287
 
275
- ## Rate limits
288
+ ## Rate-limit handling and crash-safe recovery
276
289
 
277
290
  Built for unattended runs lasting hours or days.
278
291
 
@@ -286,15 +299,24 @@ Built for unattended runs lasting hours or days.
286
299
  - **Usage cap**: set a ceiling, active agents finish, no new ones start — run is resumable
287
300
  - **Planner retries**: steering and orchestration retry on rate limits (30s/60s/120s backoff) with full context
288
301
 
289
- ## Worktrees and merging
302
+ ## Git worktrees and branch merging
290
303
 
291
- Each agent gets an isolated git worktree (`swarm/task-N` branch). Changes auto-commit. After all agents complete, branches merge back.
304
+ Each agent session gets an isolated git worktree (`swarm/task-N` branch). Changes auto-commit. After all sessions complete, branches merge back.
292
305
 
293
306
  - `"yolo"` (default): merges into your current branch
294
307
  - `"branch"`: creates a new `swarm/run-{timestamp}` branch
295
308
 
296
309
  Conflicts retry with `-X theirs`. Unresolved branches are preserved for manual merge.
297
310
 
311
+ ## Claude Code plugin
312
+
313
+ This repo also ships a Claude Code plugin so any Claude instance (inside this repo or any other) knows how to use, inspect, and resume `claude-overnight` runs:
314
+
315
+ ```
316
+ /plugin marketplace add Fornace/claude-overnight
317
+ /plugin install claude-overnight
318
+ ```
319
+
298
320
  ## Exit codes
299
321
 
300
322
  | Code | Meaning |
package/dist/cli.js CHANGED
@@ -158,10 +158,12 @@ export function ask(question) {
158
158
  }
159
159
  return new Promise((resolve) => {
160
160
  const segs = [];
161
- const lastLine = question.split("\n").pop() ?? "";
161
+ // DEC save/restore cursor + clear-to-end-of-screen so redraws don't pile
162
+ // up when the input wraps past the terminal width onto additional rows.
162
163
  const redraw = () => {
163
- stdout.write("\r\x1B[K" + lastLine + renderSegments(segs));
164
+ stdout.write("\x1B8\x1B[J" + question + renderSegments(segs));
164
165
  };
166
+ stdout.write("\x1B7");
165
167
  stdout.write(question);
166
168
  stdout.write("\x1B[?2004h");
167
169
  try {
package/dist/merge.d.ts CHANGED
@@ -17,6 +17,15 @@ export declare function mergeAllBranches(agents: {
17
17
  branch: string;
18
18
  filesChanged: number;
19
19
  }[], cwd: string, strategy: MergeStrategy, log: (id: number, msg: string) => void): MergeAllResult;
20
+ /**
21
+ * Last-resort merge: overlay the branch's file state onto HEAD without a real
22
+ * 3-way merge. Walks `git diff --name-status base..branch` and for each entry
23
+ * either checks out the branch's version (add/modify/rename) or removes the
24
+ * file (delete). Always succeeds unless the branch itself is broken. Trades
25
+ * merge-graph fidelity for "your changes actually land" — the right call for
26
+ * an autonomous swarm.
27
+ */
28
+ export declare function forceMergeOverlay(branch: string, cwd: string): boolean;
20
29
  export declare function warnDirtyTree(cwd: string, log: (id: number, msg: string) => void): void;
21
30
  export declare function cleanStaleWorktrees(cwd: string, log: (id: number, msg: string) => void): void;
22
31
  export declare function writeSwarmLog(opts: {
package/dist/merge.js CHANGED
@@ -5,20 +5,45 @@ import { tmpdir } from "os";
5
5
  export function gitExec(cmd, cwd) {
6
6
  return execSync(cmd, { cwd, encoding: "utf-8", stdio: "pipe" });
7
7
  }
8
+ /** Total files the agent touched vs base — tracked changes + untracked. */
9
+ function measureWork(worktreeCwd, baseRef) {
10
+ const seen = new Set();
11
+ try {
12
+ // Tracked: committed + staged + unstaged, all vs the worktree's base.
13
+ const diff = gitExec(`git diff --name-only ${baseRef} --`, worktreeCwd);
14
+ for (const p of diff.split("\n"))
15
+ if (p)
16
+ seen.add(p);
17
+ }
18
+ catch { }
19
+ try {
20
+ // Untracked files don't show in `git diff`; count them separately.
21
+ const untracked = gitExec("git ls-files --others --exclude-standard", worktreeCwd);
22
+ for (const p of untracked.split("\n"))
23
+ if (p)
24
+ seen.add(p);
25
+ }
26
+ catch { }
27
+ return seen.size;
28
+ }
8
29
  export function autoCommit(agentId, taskPrompt, worktreeCwd, baseRef, log) {
9
30
  if (!existsSync(worktreeCwd)) {
10
31
  log(agentId, "Worktree directory gone, skipping commit");
11
32
  return 0;
12
33
  }
13
- // Step 1: commit any uncommitted changes. Agents *may* commit their own work;
14
- // we pick up whatever is still dirty.
34
+ if (!baseRef)
35
+ return 0;
36
+ // Measure actual work BEFORE committing. This captures reality even if a
37
+ // pre-commit hook rejects the commit: we used to silently return 0 in that
38
+ // case and the worktree cleanup would destroy the changes.
39
+ const preCount = measureWork(worktreeCwd, baseRef);
15
40
  let status;
16
41
  try {
17
42
  status = gitExec("git status --porcelain", worktreeCwd);
18
43
  }
19
44
  catch (err) {
20
45
  log(agentId, `git status failed: ${String(err.message || err).slice(0, 120)}`);
21
- return 0;
46
+ return preCount;
22
47
  }
23
48
  if (status.trim()) {
24
49
  try {
@@ -27,33 +52,49 @@ export function autoCommit(agentId, taskPrompt, worktreeCwd, baseRef, log) {
27
52
  catch (err) {
28
53
  log(agentId, `git add failed: ${String(err.message || err).slice(0, 120)}`);
29
54
  }
55
+ const msg = taskPrompt.slice(0, 72).replace(/'/g, "'\\''");
30
56
  try {
31
- const msg = taskPrompt.slice(0, 72).replace(/'/g, "'\\''");
32
57
  gitExec(`git commit -m 'swarm: ${msg}'`, worktreeCwd);
33
58
  }
34
59
  catch (err) {
35
60
  const m = String(err.message || err);
36
- if (!m.includes("nothing to commit"))
37
- log(agentId, `git commit failed: ${m.slice(0, 120)}`);
61
+ if (!m.includes("nothing to commit")) {
62
+ // Hook-gated project: the user's pre-commit hooks rejected a
63
+ // potentially work-in-progress commit (lint errors, type errors,
64
+ // whatever). Retry bypassing hooks — this is swarm scaffolding,
65
+ // not a user-facing commit. Without this the branch stays empty,
66
+ // the merge gate drops it, and the work is destroyed when the
67
+ // worktree is cleaned up.
68
+ try {
69
+ gitExec(`git commit --no-verify -m 'swarm: ${msg}'`, worktreeCwd);
70
+ log(agentId, `Commit hooks bypassed (rejected swarm WIP commit)`);
71
+ }
72
+ catch (err2) {
73
+ log(agentId, `git commit failed even with --no-verify: ${String(err2.message || err2).slice(0, 120)}`);
74
+ }
75
+ }
38
76
  }
39
77
  }
40
- // Step 2: measure against the worktree's origin commit — true regardless of
41
- // who made the commits (agent or autoCommit). Pre-1.11.10 this counted
42
- // `git status --porcelain` lines, which was zero whenever the agent committed
43
- // its own work → filesChanged=0 → branch skipped by the merge gate → orphaned.
44
- if (!baseRef)
45
- return 0;
78
+ // Authoritative post-commit count: this is what `mergeAllBranches` will
79
+ // actually see on the branch.
80
+ let landed = 0;
46
81
  try {
47
82
  const diff = gitExec(`git diff --name-only ${baseRef}..HEAD`, worktreeCwd);
48
- const count = diff.trim().split("\n").filter(Boolean).length;
49
- if (count > 0)
50
- log(agentId, `${count} file(s) changed`);
51
- return count;
83
+ landed = diff.trim().split("\n").filter(Boolean).length;
52
84
  }
53
85
  catch (err) {
54
86
  log(agentId, `diff vs base failed: ${String(err.message || err).slice(0, 120)}`);
55
- return 0;
56
87
  }
88
+ // Red-flag: work existed before the commit attempt but didn't land on the
89
+ // branch. Surfaces silent data loss (stuck hooks, writes outside the
90
+ // worktree, gitignored targets) that used to look like "agent did 0 work".
91
+ if (landed === 0 && preCount > 0) {
92
+ log(agentId, `${preCount} file(s) touched but did NOT land on branch — check hooks / gitignore / absolute paths`);
93
+ return preCount;
94
+ }
95
+ if (landed > 0)
96
+ log(agentId, `${landed} file(s) changed`);
97
+ return landed;
57
98
  }
58
99
  export function mergeAllBranches(agents, cwd, strategy, log) {
59
100
  const mergeResults = [];
@@ -121,8 +162,17 @@ export function mergeAllBranches(agents, cwd, strategy, log) {
121
162
  gitExec("git merge --abort", cwd);
122
163
  }
123
164
  catch { }
124
- result.error = e.message?.slice(0, 80);
125
- log(agent.id, `Merge conflict: ${agent.branch}`);
165
+ // 3rd tier: brute-force overlay. Handles rename/rename, rename/delete
166
+ // and other tree-level conflicts that `-X theirs` can't resolve.
167
+ if (forceMergeOverlay(agent.branch, cwd)) {
168
+ result.ok = true;
169
+ result.autoResolved = true;
170
+ log(agent.id, `Force-merged ${agent.branch} (overlay)`);
171
+ }
172
+ else {
173
+ result.error = e.message?.slice(0, 80);
174
+ log(agent.id, `Merge conflict: ${agent.branch}`);
175
+ }
126
176
  }
127
177
  }
128
178
  mergeResults.push(result);
@@ -165,6 +215,70 @@ export function mergeAllBranches(agents, cwd, strategy, log) {
165
215
  }
166
216
  return { mergeResults, mergeBranch };
167
217
  }
218
+ /**
219
+ * Last-resort merge: overlay the branch's file state onto HEAD without a real
220
+ * 3-way merge. Walks `git diff --name-status base..branch` and for each entry
221
+ * either checks out the branch's version (add/modify/rename) or removes the
222
+ * file (delete). Always succeeds unless the branch itself is broken. Trades
223
+ * merge-graph fidelity for "your changes actually land" — the right call for
224
+ * an autonomous swarm.
225
+ */
226
+ export function forceMergeOverlay(branch, cwd) {
227
+ try {
228
+ const base = gitExec(`git merge-base HEAD "${branch}"`, cwd).trim();
229
+ const diff = gitExec(`git diff --name-status ${base} "${branch}"`, cwd);
230
+ for (const line of diff.split("\n")) {
231
+ if (!line)
232
+ continue;
233
+ const fields = line.split("\t");
234
+ const status = fields[0];
235
+ if (status.startsWith("R") || status.startsWith("C")) {
236
+ const from = fields[1];
237
+ const to = fields[2];
238
+ if (status.startsWith("R")) {
239
+ try {
240
+ gitExec(`git rm -f -- "${from}"`, cwd);
241
+ }
242
+ catch { }
243
+ }
244
+ try {
245
+ gitExec(`git checkout "${branch}" -- "${to}"`, cwd);
246
+ gitExec(`git add -- "${to}"`, cwd);
247
+ }
248
+ catch { }
249
+ }
250
+ else if (status.startsWith("D")) {
251
+ try {
252
+ gitExec(`git rm -f -- "${fields[1]}"`, cwd);
253
+ }
254
+ catch { }
255
+ }
256
+ else {
257
+ try {
258
+ gitExec(`git checkout "${branch}" -- "${fields[1]}"`, cwd);
259
+ gitExec(`git add -- "${fields[1]}"`, cwd);
260
+ }
261
+ catch { }
262
+ }
263
+ }
264
+ const dirty = gitExec("git status --porcelain", cwd).trim();
265
+ if (!dirty)
266
+ return true;
267
+ gitExec(`git commit -m 'swarm: force-merge ${branch}'`, cwd);
268
+ return true;
269
+ }
270
+ catch {
271
+ try {
272
+ gitExec("git merge --abort", cwd);
273
+ }
274
+ catch { }
275
+ try {
276
+ gitExec("git reset --hard HEAD", cwd);
277
+ }
278
+ catch { }
279
+ return false;
280
+ }
281
+ }
168
282
  export function warnDirtyTree(cwd, log) {
169
283
  try {
170
284
  const status = gitExec("git status --porcelain", cwd);
@@ -219,6 +219,19 @@ export function postProcess(raw, budget, onLog) {
219
219
  tasks = tasks.filter((t) => t.prompt && t.prompt.trim().split(/\s+/).length >= 3);
220
220
  if (tasks.length < before)
221
221
  onLog(`Filtered ${before - tasks.length} task(s) with fewer than 3 words`);
222
+ // Read-only tasks (verify/audit/user-test) shouldn't get a worktree: they
223
+ // don't change files, so they'd just create empty swarm branches that show
224
+ // up as "0 files changed" noise. Run them in the real project directory so
225
+ // env files, dependencies, and local config are available.
226
+ let readOnly = 0;
227
+ for (const t of tasks) {
228
+ if (!t.noWorktree && /^\s*(verify|audit|user[- ]?test)\b/i.test(t.prompt)) {
229
+ t.noWorktree = true;
230
+ readOnly++;
231
+ }
232
+ }
233
+ if (readOnly > 0)
234
+ onLog(`${readOnly} read-only task(s) marked noWorktree`);
222
235
  const dominated = new Set();
223
236
  for (let i = 0; i < tasks.length; i++) {
224
237
  if (dominated.has(i))
package/dist/state.js CHANGED
@@ -2,6 +2,7 @@ import { readFileSync, existsSync, mkdirSync, readdirSync, writeFileSync, symlin
2
2
  import { execSync } from "child_process";
3
3
  import { join } from "path";
4
4
  import chalk from "chalk";
5
+ import { forceMergeOverlay } from "./merge.js";
5
6
  // ── File I/O helpers ──
6
7
  export function readMdDir(dir) {
7
8
  try {
@@ -472,8 +473,14 @@ export function autoMergeBranches(cwd, branches, onLog) {
472
473
  execSync("git merge --abort", { cwd, encoding: "utf-8", stdio: "pipe" });
473
474
  }
474
475
  catch { }
475
- br.status = "merge-failed";
476
- onLog(` ✗ ${br.branch} (conflict — preserved for manual merge)`);
476
+ if (forceMergeOverlay(br.branch, cwd)) {
477
+ br.status = "merged";
478
+ onLog(` ✓ ${br.branch} (force-merged)`);
479
+ }
480
+ else {
481
+ br.status = "merge-failed";
482
+ onLog(` ✗ ${br.branch} (conflict — preserved for manual merge)`);
483
+ }
477
484
  }
478
485
  }
479
486
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-overnight",
3
- "version": "1.16.2",
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.",
3
+ "version": "1.16.4",
4
+ "description": "Local multi-session orchestrator for the Claude Agent SDK. Runs parallel Claude agents in git worktrees overnight spend caps, rate-limit handling, crash-safe resume, multi-wave steering. Opus/Sonnet/Haiku + Qwen/OpenRouter. A local alternative to hosted agent harnesses.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "claude-overnight": "dist/bin.js"
@@ -29,19 +29,34 @@
29
29
  },
30
30
  "keywords": [
31
31
  "claude",
32
+ "claude-code",
32
33
  "claude-agent-sdk",
34
+ "agent-sdk",
35
+ "managed-agents",
36
+ "anthropic",
33
37
  "ai-agents",
34
38
  "ai-coding",
35
- "parallel-agents",
36
39
  "autonomous-coding",
40
+ "autonomous-agent",
41
+ "coding-agent",
42
+ "background-agent",
43
+ "async-coding",
44
+ "parallel-agents",
45
+ "multi-agent",
37
46
  "swarm",
38
47
  "overnight",
39
- "cli",
48
+ "overnight-coding",
40
49
  "orchestration",
41
- "multi-agent",
42
- "code-generation",
43
- "anthropic",
50
+ "orchestrator",
51
+ "cli",
44
52
  "worktrees",
53
+ "git-worktree",
54
+ "code-generation",
55
+ "code-automation",
56
+ "refactoring",
57
+ "migration",
58
+ "qwen",
59
+ "openrouter",
45
60
  "iterative"
46
61
  ],
47
62
  "engines": {