[BUG] Edit tool breaks hard links — creates new inode instead of writing in-place

Resolved 💬 4 comments Opened Mar 6, 2026 by Mationetap Closed Apr 4, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When using the Edit tool on a file that is a hard link, the edit breaks the link — the source file gets a new inode. After editing, the source and linked copy are no longer connected. The linked copy retains the old content.

This affects any workflow using hard links for file deployment (e.g., agent definitions in a config repo hard-linked to ~/.claude/agents/).

What Should Happen?

The Edit tool should write to the existing file in-place (open → truncate → write → close), preserving hard links and inode identity. This is what most in-place editors do (vim with set nobackup, Python's open('w')).

Error Messages/Logs

No error. The edit succeeds silently, but the hard link is broken.

Steps to Reproduce

  1. Create a test file and hard link:

``bash
echo "line 1" > /tmp/source.md
echo "line 2" >> /tmp/source.md
cp -l /tmp/source.md /tmp/deployed.md
# Verify same inode:
stat /tmp/source.md /tmp/deployed.md
``

  1. Open Claude Code in the directory containing source.md
  1. Ask Claude: "Edit /tmp/source.md — replace 'line 1' with 'modified line 1'"
  1. Claude uses the Edit tool. The edit succeeds.
  1. Check the hard link:

```bash
stat /tmp/source.md /tmp/deployed.md
# source.md has a NEW inode number
# deployed.md has the OLD inode number
# They are no longer linked

cat /tmp/deployed.md
# Still shows "line 1" — old content
```

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.69 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

Root cause (likely): The Edit tool uses a write-to-temp-file + rename pattern:

fs.writeFileSync(tempPath, newContent);
fs.renameSync(tempPath, originalPath);

This creates a new inode at originalPath, breaking any hard links.

Fix suggestion: Use in-place write:

// Option A: direct write (preserves inode)
fs.writeFileSync(originalPath, newContent);

// Option B: detect hard links and choose strategy
const stat = fs.statSync(originalPath);
if (stat.nlink > 1) {
  // In-place write to preserve hard link
  fs.writeFileSync(originalPath, newContent);
} else {
  // Safe temp+rename for non-linked files
  fs.writeFileSync(tempPath, newContent);
  fs.renameSync(tempPath, originalPath);
}

My use case: I maintain 10 agent definitions in a config repo (claude-agents-config/agents/global/*.md) and deploy them via hard links to ~/.claude/agents/. Every time I use the Edit tool on an agent file, I have to manually cp -f source.md ~/.claude/agents/source.md to re-deploy. Symlinks require admin privileges on Windows, so hard links are the only practical option.

Note: This likely affects all platforms (Linux, macOS), not just Windows. The temp+rename pattern breaks hard links on any filesystem.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗