claude-code - 💡(How to fix) Fix Windows: background agent .output files always 0 bytes (symlink fallback) [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#46975Fetched 2026-04-13 05:44:49
View on GitHub
Comments
2
Participants
2
Timeline
7
Reactions
0
Timeline (top)
labeled ×4commented ×2closed ×1

Root Cause

Root Cause (traced through source)

Code Example

// Current (fails on Windows without admin):
fs.symlinkSync(targetPath, outputPath);

// Fix:
try {
  fs.linkSync(targetPath, outputPath);  // hard link works without admin on Windows
} catch {
  fs.symlinkSync(targetPath, outputPath);  // fall back to symlink on Unix
}
RAW_BUFFERClick to expand / collapse

Bug Description

On Windows, background agent output files (.output JSONL transcripts) remain 0 bytes for the entire agent lifecycle and after completion. The completion notification returns results correctly, but the output file is never populated.

This is NOT the Git 2.53.0 bash stdout issue (though that's related). This is specific to background agent transcript files.

Environment

  • Windows 11 Pro 10.0.26200
  • Claude Code CLI (latest, also reproduced on prior versions)
  • PowerShell AND Git Bash (MINGW64) — both affected
  • CLAUDE_CODE_TMPDIR remapped to ~/.claude/tmp — no change (rules out temp dir permissions)

Root Cause (traced through source)

The bug is in utils/task/diskOutput.ts:

  1. initTaskOutputAsSymlink() (line ~438) tries to create a symlink from the .output file to the agent's .jsonl transcript
  2. Windows symlinks require admin/developer privileges — the fs.symlink() call fails
  3. The fallback (line ~447) calls initTaskOutput() which creates an empty 0-byte file
  4. The agent's conversation is written to the .jsonl transcript via the project backend (recordSidechainTranscript() in tools/AgentTool/runAgent.ts)
  5. The .output file has no connection to the .jsonl file after the symlink fails — it stays 0 bytes permanently

Why Bash Works But Agents Don't

ComponentMechanismWorks on Windows?
Bash tool (utils/Shell.ts)Opens file with fs.openSync(), passes fd via stdio[1] — child writes directly to file handleYes — OS-level fd redirect
Background agents (bridge/sessionRunner.ts)stdio: ['pipe', 'pipe', 'pipe'] — parent reads via readline, writes to project backend separatelyNo — relies on symlink .output.jsonl

The Bash tool bypasses the pipe entirely by giving the child process a file descriptor. Background agents use pipes + a symlink, and the symlink is the part that breaks on Windows.

Proposed Fix

In diskOutput.ts, replace the symlink fallback with one of:

  1. Hard link (fs.linkSync) — works on Windows without admin privileges, same semantics as symlink for read purposes
  2. Junction (fs.symlinkSync with 'junction' type) — Windows junctions work without elevation for directories
  3. Periodic copy/tail — write .output from the same source that feeds the .jsonl
  4. Direct fd redirect — match the Bash tool pattern: open the .output file, pass fd to the child process stdio

Option 1 (hard link) is the simplest one-line fix:

// Current (fails on Windows without admin):
fs.symlinkSync(targetPath, outputPath);

// Fix:
try {
  fs.linkSync(targetPath, outputPath);  // hard link works without admin on Windows
} catch {
  fs.symlinkSync(targetPath, outputPath);  // fall back to symlink on Unix
}

Note: hard links require both paths on the same volume, which they are (both under the temp/project directory).

Related Issues

  • #17147 — Background agents output files remain empty
  • #14521 — Background agents cannot write files with run_in_background=true
  • #21352 — Agents complete but output files are empty
  • #32252 — Background tasks report "completed" but output files missing or empty
  • #21915 — Bash tool produces no output on Windows (separate Git 2.53.0 issue)

Reproduction

  1. Run Claude Code on Windows (any shell)
  2. Spawn a background agent: Agent({ prompt: "echo hello", run_in_background: true })
  3. Check the output file path returned in the launch message
  4. File is 0 bytes during execution AND after completion
  5. The completion notification correctly returns the agent's result (proving the agent ran fine)

extent analysis

TL;DR

Replace the symlink fallback in diskOutput.ts with a hard link using fs.linkSync to fix the issue of 0-byte output files on Windows.

Guidance

  • Verify that the issue is indeed caused by the symlink creation failure on Windows by checking the error logs or debugging the initTaskOutputAsSymlink function.
  • Consider implementing a try-catch block to handle the case where fs.linkSync fails, and fall back to a different approach such as periodic copying or direct fd redirect.
  • Test the proposed fix on different Windows environments to ensure it works consistently.
  • Review the related issues (#17147, #14521, #21352, #32252, #21915) to ensure the fix does not introduce any regressions.

Example

try {
  fs.linkSync(targetPath, outputPath);  // hard link works without admin on Windows
} catch {
  // fall back to a different approach, such as periodic copying or direct fd redirect
  // or log an error and continue with an empty output file
}

Notes

The proposed fix assumes that both the target and output paths are on the same volume, which is the case in the given scenario. However, if this assumption does not hold in other scenarios, a different approach may be needed.

Recommendation

Apply the workaround using fs.linkSync to replace the symlink fallback, as it is a simple and effective solution that works on Windows without requiring admin privileges.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING