Skip to content

fix(cli): disable background tasks for Claude Code batch spawns#862

Merged
pedramamini merged 1 commit intoRunMaestro:rcfrom
scriptease:861-cli-disable-background-tasks
Apr 22, 2026
Merged

fix(cli): disable background tasks for Claude Code batch spawns#862
pedramamini merged 1 commit intoRunMaestro:rcfrom
scriptease:861-cli-disable-background-tasks

Conversation

@scriptease
Copy link
Copy Markdown

@scriptease scriptease commented Apr 18, 2026

Adds a new batchModeEnvVars field to agent definitions that is read only by the CLI spawners (spawnClaudeAgent, spawnJsonLineAgent), not by the desktop UI path or --live mode. Populates Claude Code with CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 so run_in_background tool calls do not silently fail when the short-lived maestro-cli send batch session exits before the async task completes.

Shell-env-wins precedence matches the existing defaultEnvVars pattern, so users can still opt out by setting the var in their shell.

The original issues it that maestro-cli requests can cause background tasks to spawn that then never report back and the result is lost.

IMG_5030 png

The setting is documented here https://claudelog.com/faqs/what-is-disable-background-tasks-in-claude-code/

But Claude Opus 4.7 couldn't figure it out and had to be carried to the finish line.

Bildschirmfoto 2026-04-18 um 17 10 56

Fixes #861

Summary by CodeRabbit

  • Chores
    • Enhanced batch mode behavior by disabling background tasks for agent operations during CLI spawning, preventing interference with batch processes. Environment variable configuration respects pre-existing shell settings and ensures consistent batch operation execution.

Adds a new `batchModeEnvVars` field to agent definitions that is read
only by the CLI spawners (spawnClaudeAgent, spawnJsonLineAgent), not by
the desktop UI path or --live mode. Populates Claude Code with
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 so run_in_background tool calls
do not silently fail when the short-lived `maestro-cli send` batch
session exits before the async task completes.

Shell-env-wins precedence matches the existing defaultEnvVars pattern,
so users can still opt out by setting the var in their shell.

Fixes RunMaestro#861

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 18, 2026

📝 Walkthrough

Walkthrough

This change introduces automatic injection of environment variables for batch-mode agent spawns by adding an optional batchModeEnvVars field to agent configurations. The claude-code agent now automatically sets CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 during CLI spawns to prevent background task failures in headless sessions. Existing environment values take precedence.

Changes

Cohort / File(s) Summary
Agent Configuration
src/main/agents/definitions.ts
Added optional batchModeEnvVars?: Record<string, string> field to AgentConfig interface; configured claude-code agent with CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: '1'.
Agent Spawning Logic
src/cli/services/agent-spawner.ts
Modified spawnClaudeAgent and spawnJsonLineAgent to apply batchModeEnvVars from agent definitions to spawned process environment, respecting pre-existing shell environment values.
Test Coverage
src/__tests__/cli/services/agent-spawner.test.ts, src/__tests__/main/agents/definitions.test.ts
Added test cases validating that CLAUDE_CODE_DISABLE_BACKGROUND_TASKS environment variable is set to '1' in spawned agents and defined in agent configurations; verified that pre-existing environment values are preserved.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Batch mode hops along with care,
Background tasks float in the air—
Now we pin them down with '1',
Batch sessions won't lose their run! 🌱

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: disabling background tasks for Claude Code batch spawns via an environment variable injection mechanism.
Linked Issues check ✅ Passed The code changes fully address all coding requirements from issue #861: adding batchModeEnvVars field to AgentConfig, populating CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 for claude-code in CLI batch paths, and preserving shell environment precedence.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the issue objective: agent definition interface extension, batch mode environment variable injection in spawners, and corresponding test coverage—no unrelated modifications present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 18, 2026

Greptile Summary

This PR fixes a silent data-loss issue (#861) where run_in_background tool calls initiated during a short-lived maestro-cli send batch session would exit before the async task completed. It introduces a new batchModeEnvVars field on agent definitions, scoped exclusively to the CLI spawners (spawnClaudeAgent / spawnJsonLineAgent), and sets CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 for Claude Code batch invocations using a "shell env wins" falsy-check that is consistent with the existing defaultEnvVars pattern.

Confidence Score: 5/5

Safe to merge — targeted fix with no P0/P1 issues found.

The change is well-scoped: a single new optional field on the agent definition type, applied only in the two CLI spawner functions, with three targeted tests covering normal/read-only/shell-override cases. The "shell env wins" falsy-check is consistent with the existing defaultEnvVars pattern, and the desktop UI path is unaffected. No correctness, data-integrity, or security concerns identified.

No files require special attention.

Important Files Changed

Filename Overview
src/main/agents/definitions.ts Adds optional batchModeEnvVars field to AgentConfig interface and populates it for claude-code with CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1; no issues found.
src/cli/services/agent-spawner.ts Applies batchModeEnvVars in both spawnClaudeAgent and spawnJsonLineAgent using the existing falsy-check "shell env wins" pattern; consistent with defaultEnvVars precedence.
src/tests/cli/services/agent-spawner.test.ts Adds three targeted tests for CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: normal spawn, read-only mode, and shell-env-wins override; coverage is correct.
src/tests/main/agents/definitions.test.ts Adds one definition-level test verifying claude-code.batchModeEnvVars.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS === '1'; well-scoped.

Reviews (1): Last reviewed commit: "fix(cli): disable background tasks for C..." | Re-trigger Greptile

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/cli/services/agent-spawner.ts (1)

179-186: Optional: tighten the "shell env wins" check and deduplicate.

if (!env[k]) treats any falsy string (e.g., an intentionally empty CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=) as unset and overwrites it. While '0' is truthy in JS (so the existing test passes), a stricter presence check better matches the stated "shell env wins" contract and is consistent across future env vars. The same block is duplicated in spawnClaudeAgent and spawnJsonLineAgent — worth a tiny helper.

♻️ Proposed helper
+function applyEnvDefaults(env: NodeJS.ProcessEnv, vars?: Record<string, string>) {
+	if (!vars) return;
+	for (const k of Object.keys(vars)) {
+		if (!(k in env)) env[k] = vars[k];
+	}
+}

Then replace both blocks:

-		if (def?.batchModeEnvVars) {
-			for (const k of Object.keys(def.batchModeEnvVars)) {
-				if (!env[k]) env[k] = def.batchModeEnvVars[k];
-			}
-		}
+		applyEnvDefaults(env, def?.batchModeEnvVars);

Note: the existing defaultEnvVars loop at lines 407-411 uses the same !env[k] pattern; applying the helper there too keeps behavior consistent.

Also applies to: 413-418

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/services/agent-spawner.ts` around lines 179 - 186, The batch-mode env
merge currently uses "if (!env[k])" which treats empty strings or other falsy
values as unset; change this to a strict presence check (e.g., test env[k] ===
undefined or use Object.prototype.hasOwnProperty.call(env, k)) so the
shell-provided empty or falsy values are preserved, and extract the logic into a
small helper (e.g., applyAgentEnvDefaults(def, env) or mergeBatchModeEnvVars)
and call it from where getAgentDefinition('claude-code') is applied as well as
from spawnClaudeAgent and spawnJsonLineAgent; also consider reusing the same
helper for the defaultEnvVars loop to keep behavior consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/cli/services/agent-spawner.ts`:
- Around line 179-186: The batch-mode env merge currently uses "if (!env[k])"
which treats empty strings or other falsy values as unset; change this to a
strict presence check (e.g., test env[k] === undefined or use
Object.prototype.hasOwnProperty.call(env, k)) so the shell-provided empty or
falsy values are preserved, and extract the logic into a small helper (e.g.,
applyAgentEnvDefaults(def, env) or mergeBatchModeEnvVars) and call it from where
getAgentDefinition('claude-code') is applied as well as from spawnClaudeAgent
and spawnJsonLineAgent; also consider reusing the same helper for the
defaultEnvVars loop to keep behavior consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 02e85a1c-a6a8-4878-b1d8-2acf0183da32

📥 Commits

Reviewing files that changed from the base of the PR and between a777eaa and 2b02e58.

📒 Files selected for processing (4)
  • src/__tests__/cli/services/agent-spawner.test.ts
  • src/__tests__/main/agents/definitions.test.ts
  • src/cli/services/agent-spawner.ts
  • src/main/agents/definitions.ts

@pedramamini
Copy link
Copy Markdown
Collaborator

Thanks for the clean fix, @scriptease! 🙏

Reviewed the diff and I'm happy with this:

  • Scope is tight: new batchModeEnvVars field is applied exclusively in the CLI spawners (spawnClaudeAgent / spawnJsonLineAgent), so the desktop UI and --live paths are untouched. Exactly right for a fix that targets short-lived maestro-cli send sessions.
  • Precedence is consistent: the !env[k] shell-env-wins check matches the existing defaultEnvVars pattern a few lines down, so users can still opt out via their shell.
  • Good test coverage: normal spawn, read-only mode, and the shell-override case are all exercised — plus a definition-level assertion. Nice.
  • Docs: the inline comment on batchModeEnvVars explicitly calls out that it's CLI-only and points at maestro-cli send (batch mode): background tasks silently fail — should auto-set CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 #861, which is exactly the kind of breadcrumb future us will appreciate.

The CodeRabbit nitpick about extracting a helper / using a strict presence check is reasonable but not worth blocking on — staying consistent with the existing defaultEnvVars loop is the right call for now, and we can refactor both together if/when a third case lands.

Approving. 🟢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants