[BUG] Cowork on Windows: bash sandbox can create files on mounted host folder but unlink is denied — breaks all git write operations

Status Open
Reported on v2.1.121
Maintainer reply None cached
Activity 14 comments · opened May 1, 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?

In Cowork on Windows, the bash sandbox can mount a selected host folder and perform read and create-write operations against it, but the unlink syscall is denied at the FUSE/mount layer. POSIX permissions and chmod have no effect — unlink is rejected regardless. sudo is not available (no-new-privs is set on the sandbox).
This is distinct from the reported stale-index.lock issue (#28546), which attributes the symptom to Windows file-handle latency. The behavior here is structural: a brand-new file created microseconds before the unlink attempt, on a path the sandbox just wrote, still fails to unlink. There is no race window where it works.
The practical effect is that all git write operations from the bash sandbox on a mounted Windows folder fail. git add partially succeeds but emits "unable to unlink" warnings on temp objects and .git/index.lock. git commit then fails because the prior .git/index.lock cannot be removed. Subsequent rm -f .git/index.lock from the bash sandbox also fails. Recovery requires the user to open PowerShell and clean up .git/ manually.
This makes the documented "Cowork can manage version control" workflow non-functional on Windows when the repo lives on a mounted host folder.

What Should Happen?

The bash sandbox should be able to perform unlink on paths under the mounted host folder, given that it can already create and write files there. Without unlink, git operations and any other workflow that uses temp/lock files cannot complete inside the sandbox.
If the unlink restriction is a deliberate security measure (preventing the sandbox from deleting host files), it should be documented, and the project-level workflow guidance should be updated to clarify that Cowork on Windows cannot perform git write operations on a mounted host folder.

Error Messages/Logs

$ git commit -m "test"
fatal: Unable to create '/sessions/<session>/mnt/<folder>/.git/index.lock': File exists.

Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. ...

$ rm -f .git/index.lock
rm: cannot remove '.git/index.lock': Operation not permitted

Control test demonstrating the structural unlink denial:
$ cd /tmp && touch foo && rm foo && echo "tmp ok"
tmp ok

$ cd /sessions/<session>/mnt/<folder> && touch foo && rm foo
rm: cannot remove 'foo': Operation not permitted

Same file, freshly created microseconds before the unlink. POSIX permissions and chmod have no effect.

Steps to Reproduce

On Windows 11 (any recent build with WSL2 / Hyper-V Platform installed), open Cowork.
Select a folder that is a git repo (any folder under C:\Users\<you>\... works — does not need to be in OneDrive or Downloads, which have their own known mount issues).
Start a session and run the following control test in the bash tool:

uname -a
cd /tmp && touch foo && rm foo && echo "tmp ok"
cd /sessions/<session>/mnt/<folder> && touch foo && rm foo && echo "mnt ok"

The first rm succeeds. The second fails with rm: cannot remove 'foo': Operation not permitted.

Now reproduce the git failure:

cd /sessions/<session>/mnt/<folder>
echo "# test" >> .gitignore
git add .gitignore
git commit -m "test"

git add will emit unlink warnings; git commit will fail with Unable to create '.git/index.lock': File exists.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.121 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

This is a Cowork-on-Windows bug. The form fields lean toward the Claude Code CLI but the Cowork sandbox runs Claude Code under the hood, so the same repo is the right place — see prior Cowork-tagged issues like #28546, #25096, #25293, #41710, #42520, #45433, #50873.

Related-but-distinct issues searched and ruled out as duplicates:

  • #28546 (stale .git/index.lock on Windows) — closest match, but reporter attributes the cause to Windows file-handle latency. The control test in this report (touch foo && rm foo on a brand-new file in the mount) rules that out: there's no race window, the unlink is structurally denied.
  • #11005 (closed NOT_PLANNED) — Linux/macOS scope, different platform.
  • #41710, #42520, #45433, #50873 — FUSE cache coherency / stale content issues. Different symptom (read returns wrong data); this report is a write-side issue (unlink denied).
  • #25xxx series — virtiofs/Plan9 mount-fails-to-establish issues. The mount in this report establishes successfully; the issue is what's allowed once it's mounted.

The repo I tested against is on local disk under the user profile (NOT OneDrive, NOT Downloads), so the special-folder mount issues don't apply.

Repro environment: Windows 11, WSL2 newly installed (Cowork's bash sandbox booted successfully on first session after the install), Cowork session in a fresh chat, no other modifications.

View original on GitHub ↗

14 Comments

github-actions[bot] · 4 months ago

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/53396

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

trevor127001 · 4 months ago
Found 1 possible duplicate issue: 1. Cowork VM SDK install on Windows ARM64: hundreds of Operation not permitted errors during node_modules cleanup #53396 This issue will be automatically closed as a duplicate in 3 days. If your issue is a duplicate, please close it and 👍 the existing issue instead To prevent auto-closure, add a comment or 👎 this comment 🤖 Generated with Claude Code

Not a duplicate of #53396. Both involve "Operation not permitted" on rm, but they're separate bugs:

  • #53396 fails on Cowork's own internal install path (claude-code-vm/<version>/node_modules/) on Windows ARM64. The reporter attributes it to NTFS file-handle semantics — another process holding open handles without FILE_SHARE_DELETE.
  • This issue fails on the user-selected mounted host folder on Windows x86_64. The control test (touch foo && rm foo on a freshly-created file in /tmp succeeds; same test on the mount fails) rules out the file-handle theory: no other process has ever opened the file. The denial is structural at the FUSE/mount-policy layer, not racy.

The user-facing impact is also different: #53396 is log spam during SDK install, this is a complete block on git write workflows in mounted user folders. Different path, different cause, different mitigation.

rdnfn · 3 months ago

I appear to have the same problem via cowork on macos, with failing unlinking in the sandbox appearing to be the root cause of the issue. Thanks for fixing this!

Claude-Cowork-generated summary of the issue on my side (Desktop app version: (1.5354.0 (9a9e3d) 2026-04-29T01:14:34.000Z):

In Cowork (Claude Code 2.1.121, macOS, model claude-opus-4-7), every git invocation leaves orphan files in .git/ that the sandbox cannot unlink. After one commit I see HEAD.lock, next-index-N.lock, index.lock, maintenance.lock, and tmp_obj_ files, and the next git command then fails with "Another git process seems to be running" until I manually rm the locks from a real terminal. GIT_OPTIONAL_LOCKS=0 and --no-optional-locks only address the optional index-refresh path; they do not prevent HEAD.lock, next-index-.lock, or tmp_obj_* orphans, since those are created by normal commit operations, not opportunistic ones. Root cause looks like the sandbox mount allowing create but denying unlink inside .git/. Combining git add and git commit into one invocation reduces the count but does not eliminate it.
leoravagnani · 3 months ago

Seeing the very same issue described above. Git leaves orphan files when using Cowork on macOS.

Snow333 · 3 months ago

Independently hit this as well (Windows 11, local disk). Confirming the structural unlink denial. Cowork bash could not remove .git/index.lock no matter how much we huffed and puffed to blow this house down. Ended up using PowerShell locally to clean up index.lock between every Cowork to git mediated operation. Every. Operation. No keyboards were destroyed in the repeated attempts to explore workarounds.

When using Claude Code (Desktop and CLI) I did not hit this issue. Bummer, as I'm enjoying Cowork Desktop and am excited to see this resolved.

I have the diagnostic data Claude captured/created during this. Eg. file size deltas vs HEAD, SHA256 hashes, session timing, totally down to share all 10KB of this data if needed.

trevor127001 · 3 months ago

Another workaround pattern, complementary to @Snow333 's: rather than cleaning up index.lock after the fact, we route all git writes through a PowerShell wrapper on the host so the sandbox's unlink denial never trips. Works reliably across commit / branch / stash operations. Script available if helpful.

cosmosmaxis · 3 months ago

I have the exact same issue

tisalvadores · 3 months ago

TL;DR

The root cause of this issue is that Cowork's bindfs mount is configured with the --delete-deny option, which is bindfs's documented policy for making unlink() and rmdir() return EPERM on the mount, resulting in a denied unlink.

Removing that flag fixes this issue, but --delete-deny is probably a deliberate anti-data-loss safeguard (preventing the sandbox from deleting host files), so the safety implications of removing it would need to be reviewed. A narrower allowlist could meet the same intent without breaking git and standard atomic-write workflows. The permission-asymmetry test below isolates the configuration exactly. Detailed evidence and proposed fix follow.

---

_Claude Assisted Bug Report_

Reproducing this on a separate Windows install. We have direct evidence Cowork's mount is bindfs with --delete-deny enabled, which is the root cause of this issue. While testing, we also reproduced #42520's read-side cache pathology on the same bindfs mount in the same session — independent bug, independent fix, but co-located in the same Cowork mount-setup code.

Environment: Cowork in the Claude desktop app on Windows. The bash sandbox reports claude --version = 2.1.138 (Claude Code) (newer than #55206's 2.1.121 — bug persists through CC updates). Sandbox is Ubuntu 22.04.5 LTS, kernel 6.8.0-106-generic. bindfs 1.14.7 (current stable, no upstream bugs in this area — this is a Cowork configuration issue).

The smoking gun: permission asymmetry matches bindfs --delete-deny exactly

bindfs's documented --delete-deny option disallows file deletion while leaving all other operations untouched. We ran every destructive syscall on a probe directory in our mounted workspace folder:

| Operation | Result | bindfs flag implicated |
|---|---|---|
| mkdir, touch, write, chmod, truncate, utimes, link, symlink | ✅ all succeed | — |
| mv (rename) | ✅ succeeds | --rename-deny OFF |
| unlink | ❌ EPERM | --delete-deny ON |
| rmdir | ❌ EPERM | --delete-deny ON |

strace confirmed the failure is unlinkat(...) = -1 EPERM at the kernel syscall level, not a higher-level interpretation. Python reports errno=1 (EPERM). Read-only mounts return EROFS instead of EPERM, separating the RO-mount semantics from the --delete-deny policy.

Direct evidence bindfs is in use

  • bindfs 1.14.7 is installed at /usr/bin/bindfs in the sandbox. (Why would it be there if it weren't being used?)
  • Mount-source path from /proc/self/mountinfo shows /mnt/.virtiofs-root/shared/c/Users/<user>/<folder> as the source of the FUSE mount at /sessions/<id>/mnt/<folder> — exactly the NTFS → virtiofs (host↔VM) → bindfs (FUSE) → sandbox stack #42520 reverse-engineered.
  • One FUSE connection per mount in /sys/fs/fuse/connections/ (five connections for five mounts) — bindfs's signature, not virtiofsd's.
  • Mount options match bindfs defaults: user_id=0,group_id=0,default_permissions,allow_other.
  • chmod is force-filtered to 0700 regardless of the requested mode (chmod 7770700, chmod 6440700, etc.; same chmod on tmpfs from the same process works normally). bindfs has a --perms option that does exactly this. Confirms the bindfs layer is actively rewriting metadata, not passively forwarding.

Direct reproduction of #42520's read-side cache pathology in the same session

Same mount, same shell session. Coordinated test with PowerShell on the host:

  1. Sandbox wrote 100 'A' bytes to _cache_test.txt. Sandbox view: size=100, sha256=d82c6aa1.... Correct.
  2. From PowerShell on the host, replaced the file with 16-byte "host_wrote_short". Host-side Get-Item.Length=16, Get-FileHash=f434f899.... File is genuinely 16 bytes on NTFS.
  3. Sandbox reads of the same file: size=100 (the old sandbox-originated size), sha256=d3853c93... (= 16 host bytes + 84 null bytes). This is exactly the pathology #42520 documents: FUSE size cache stuck at the last sandbox-originated value, host content visible up to that size with null-padding beyond.
  4. Cache TTL probe: re-read at +5s, +15s, +89s, +111s after the host write — every read returned the same stale size=100, sha256=d3853c93.... No natural cache expiration observed within 111 seconds.
  5. Manual flush attempts that did NOT invalidate: ls -la <file>, fresh open()+read(), ls -la of parent dir, sandbox-side touch (utimensat). The cache is opaque to userspace invalidation hints from the sandbox side.
  6. Sandbox writes invalidate asymmetrically: open('wb') (truncate-and-write) correctly updates the cached size; open('r+b').write() (partial overwrite without truncate) does not update the cached size even after the bytes change.
  7. Write-through still works correctly: after a sandbox open('wb').write(b'sandbox_overwrite'), host-side Get-FileHash confirmed the file on NTFS matched the sandbox's last write exactly. So the bug is purely on the read-side invalidation path — writes propagate fine.

Connection to the read-side issue cluster

The write-side issues (this report and #55206 itself) and the read-side cache-coherency cluster (#38993, #41710, #42520, #45433, #50873) are independent bugs with independent root causes — but they are co-located: both surface from Cowork's bindfs mount on Windows, reproducible simultaneously on the same mount instance. They likely land on the same engineering team and could plausibly share a single triage thread, but two distinct fixes are needed:

  • --delete-deny is ON, causing the write-side EPERM symptoms in this issue and #55206. Fix is well-defined (see below).
  • Cache invalidation is broken on the same bindfs layer, causing the read-side symptoms in #38993 / #41710 / #42520 / #45433 / #50873 (stale content, null-padding, host writes invisible, divergent answers between Cowork and Claude Code tabs). Exact root cause not nailed down by this report — see "Suggested fix" below.

Persistence

EPERM behavior survives: Cowork app restart via Task Manager, "Workspace needs to be reinstalled" prompt, full Windows reboot, fresh Cowork session pointed at a brand-new empty folder created moments earlier in PowerShell, and two distinct sandbox user identities (intelligent-compassionate-wright, gallant-sweet-babbage) across separate sessions. Not transient state, not per-folder, not per-user.

Workaround

For git: plumbing-path commit pipeline avoiding .git/index.lock by working on an alternate index in tmpfs (which is exempt from EPERM):

cp .git/index /tmp/myindex
GIT_INDEX_FILE=/tmp/myindex git update-index --add <paths>
TREE=$(GIT_INDEX_FILE=/tmp/myindex git write-tree)
COMMIT=$(echo "<msg>" | git commit-tree $TREE -p HEAD)
echo "$COMMIT" > .git/refs/heads/main   # bypasses HEAD.lock
cp /tmp/myindex .git/index              # bypasses index.lock

Produces structurally correct commits. Stale .git/index.lock, .git/HEAD.lock, and orphan tmp_obj_* blobs accumulate (cleanup via PowerShell Remove-Item + git gc --prune=now). The fact that tmpfs is exempt from EPERM is itself evidence the issue is at the bindfs layer, not virtiofs or anything below.

Suggested fix

Remove --delete-deny from Cowork's bindfs invocation. That single change resolves this issue and #55206. If --delete-deny was added deliberately as an anti-data-loss safeguard ("don't let the sandbox delete user files"), the same intent could be met by a narrower allowlist that permits .git/ lock files and tempfile+rename+unlink atomic-write patterns. Either way, removing the blanket deny is necessary for git and most standard write workflows to function inside the sandbox.

The read-side cluster requires a separate fix that this report doesn't fully characterize. The exact root cause could be excessive FUSE attr_timeout / entry_timeout settings, missing invalidation propagation from virtiofs through bindfs to the kernel, bindfs itself ignoring or mis-handling invalidation events, or a deeper architectural issue with bindfs-over-virtiofs cache coherency when the underlying file is written from outside the bindfs instance. The observed asymmetric invalidation on sandbox writes (truncate+write does invalidate, partial overwrite does not) is a clue that may rule out "just tune the timeouts" as a complete fix. Reverse-engineering the exact mechanism requires access to Cowork-internal mount-setup code.

bjcoombs · 3 months ago

Confirming on macOS (Darwin 24.2.0, current Claude desktop) — the bindfs --delete-deny root cause @tisalvadores identified isn't Windows-specific; the same mount policy is active on the macOS sandbox.

Reproduction:

$ touch .probe && rm .probe && echo "WRITE OK"
rm: cannot remove '.probe': Operation not permitted

Folder is a plain local path under /Users/<u>/dev/..., not iCloud-synced, no file provider, no chflags, Full Disk Access granted to Claude. Cowork's bash sandbox can touch the file but not rm it.

Cascading git failures observed: git addfatal: Unable to write new index file; git pullwarning: unable to unlink '.git/objects/maintenance.lock'; git push rejected non-fast-forward because fetch couldn't update refs. Cowork's own Read/Write/Edit tools succeed (they don't go via the bash mount path).

Persistence ruled out on macOS across: Claude desktop quit + restart, full Mac reboot, removing + re-granting Full Disk Access for Claude, and a fresh Cowork session pointed at the same folder (different probe filename, identical EPERM). Structural to the mount, not session/state.

Regression marker: committing and pushing from Cowork on this folder used to work for me. So either --delete-deny was added in a recent Cowork update, or some other change made the same flag start tripping where it previously didn't. Worth a look at when in the release history this flag was introduced or changed on the macOS build.

Workaround: commit/push from a native shell (Claude Code CLI on the same path works fine — same files, different I/O route, no bindfs in the way). Work stays on disk; only GitHub backup trails the Cowork session until then.

yurukusa · 3 months ago

Adding this thread to the broader Cowork sandbox failure-surface cluster framing I've been tracking, plus a CLI-side partial defense.

This is structurally the same shape as #38993 (virtiofs FUSE serves stale files) and #62932 (P1 critical, FUSE inode metadata frozen for the session) — the FUSE bridge between the Windows host and the Linux sandbox honours some POSIX operations (read, create-write) but rejects others (unlink, content invalidation). The unlink-denial you describe sits next to the stale-content / NUL-padded shrink already documented in those threads. Five sub-patterns now articulated in the bridge layer:

  1. Stale content + stat after first read (#38993, #62932)
  2. Working-tree git walks return phantom data (#62932)
  3. Pre-existing files invisible through the mount outside home directory (#40973)
  4. NUL-padded shrink on .git/config after host-side merges (#62932)
  5. Unlink denied at the FUSE layer regardless of POSIX perms (this issue, #55206) — the case you've isolated to a structural rejection rather than a Windows-handle race

I shipped a CLI-side advisory hook today (2026-05-28) that partially covers the unlink-denial case: cowork-fuse-staleness-watcher.sh (PR #410, 25 tests passing). The matcher already fires on git rm / git clean / git mv inside /sessions/<id>/mnt/ (and on git add / commit whose internal unlinks against .git/index.lock are the actual failure path you describe), so a CLI session that runs git commit over the mounted Windows folder will see the warning before the partial git add lands and leaves a stuck .git/index.lock.

The hook does NOT fix the underlying FUSE rejection — that's server-side from the operator's perspective. What it does cover:

  • Surfaces the unlink-denial risk before the bash command runs, with the recovery path (PowerShell-side .git/ cleanup, which matches your repro)
  • Recommends Cowork's first-class file tools (Read / Edit / Write) which bypass FUSE entirely and are authoritative for the working tree
  • Recommends ref-only ops (git rev-parse / log / show) which don't touch the unlink path and remain functional

The five-sub-pattern framing of Cluster 11 is in cc-safe-setup/docs/cluster-tracker.html (free reference). Whether an Anthropic-side acknowledgment of unlink-denial as a structural-not-racy bug would surface in the changelog or the Cowork docs would be useful for operators triaging this case — happy to refine the framing if more sub-patterns come in.

rcc8814-star · 2 months ago

Confirmed: unlink from bash breaks all git operations on Windows mounts

We experienced this repeatedly on a Flutter project mounted on Windows via VirtioFS in Claude Cowork / Claude Desktop.

What happens: Git operations (commit, rebase, pull) leave .git/index.lock, .git/HEAD.lock, refs/heads/master.lock, and .git/objects/maintenance.lock behind. Any attempt to rm/unlink these from the Linux bash sandbox fails silently or with permission denied — even for files the sandbox just created. They're visible in ls, but rm -f returns exit 0 and the file remains.

Cascading effect: once a single lock file accumulates, all subsequent git commands fail with "unable to lock" errors, making git unusable from the sandbox for the rest of the session.

Reliable workaround: write a .bat file from the sandbox (writes work fine), then run it from Windows File Explorer — the native Windows process has the NTFS permissions the sandbox lacks, so del /f /q on the locks actually succeeds.

Alternative workaround: use git plumbing (GIT_INDEX_FILE + read-tree + write-tree + commit-tree + push by hash) which never creates the lock files in the first place.

Environment: Anthropic Cowork / Claude Desktop, Windows 11, VirtioFS mount, Git 2.34.1 (Linux sandbox).

bjcoombs · 2 months ago

Follow-up from the same macOS setup (Darwin 24.2.0), two things since my 23 May comment.

Why locks specifically get orphaned — a rename-vs-unlink asymmetry. Git's lockfile protocol finishes a successful save by renaming the lock into place (index.lockindex), which bindfs allows; it only calls unlink() on the lock when cleaning up an aborted/interrupted save, which --delete-deny blocks. So completed commits leave nothing, but any save killed mid-flight orphans a lock the sandbox can't remove — .git/index.lock / .git/HEAD.lock then accumulate and block the next session with "Another git process seems to be running." Confirmed today: both rm and mv on .git/index.lock return Operation not permitted inside .git/.

In-Cowork recovery (didn't have this on 23 May). You don't have to drop to a native shell. When a git write hits the orphaned lock, Cowork prompts to grant delete access to the working folder; allowing it lets rm .git/index.lock succeed from the bash sandbox and the save proceeds. Allowing it persistently means a future orphaned lock can be cleared in-session instead of blocking until you switch to the CLI.

Common real-world trigger. The single-rm repro above is the root cause; in practice the orphaned lock most often arises from concurrency. Running two Cowork chats on the same folder, both on an auto-"commit and push after every change" workflow, reliably collides on the git index/ref lock ("Another git process seems to be running"). On a normal filesystem that race is transient — the loser retries, the winner's lock clears. Here, because the sandbox can't unlink inside .git/, any collision that leaves a lock behind can't be cleared from within Cowork, so a normally self-healing race becomes a hard block. Two auto-saving chats on one folder reproduces it quickly. (The contention is deterministic; whether a given collision orphans a lock depends on a save being interrupted while holding it — which the concurrency makes likely.)

rcc8814-star · 2 months ago

Thanks for laying out the root cause so clearly — that rename/unlink
asymmetry explains exactly what I'd been seeing on my end (VirtioFS on
Windows).

One thing that might add to the picture: today, working in Cowork on
Windows, I ran into something related but a bit different. A native Windows
script wrote a file and confirmed on the spot, using a native command, that
the content landed
correctly on disk. But reading that same file from the Linux sandbox (cat,
wc -l) kept returning the old version — same byte size, same mtime as
before the change — for over a minute afterward. So the write itself was
fine; what failed was the sandbox never invalidating its cached view of the
file. It only cleared up once I opened the file in a native Windows app
(Notepad), which showed the updated content right away.

Might be the flip side of what you described: if the rename does propagate
but the sandbox doesn't refresh its read cache for files changed from
outside it, that
would explain cases where it looks like "the write never landed" when it
actually did — it's the read afterward that's lying.

Thanks again for digging into this,
Rober

El sáb, 20 jun 2026 03:44, Ben Coombs @.***> escribió:

bjcoombs left a comment (anthropics/claude-code#55206) <https://github.com/anthropics/claude-code/issues/55206#issuecomment-4756758438> Follow-up from the same macOS setup (Darwin 24.2.0), two things since my 23 May comment. Why locks specifically get orphaned — a rename-vs-unlink asymmetry. Git's lockfile protocol finishes a successful save by renaming the lock into place (index.lock → index), which bindfs allows; it only calls unlink() on the lock when cleaning up an aborted/interrupted save, which --delete-deny blocks. So completed commits leave nothing, but any save killed mid-flight orphans a lock the sandbox can't remove — .git/index.lock / .git/HEAD.lock then accumulate and block the next session with "Another git process seems to be running." Confirmed today: both rm and mv on .git/index.lock return Operation not permitted inside .git/. In-Cowork recovery (didn't have this on 23 May). You don't have to drop to a native shell. When a git write hits the orphaned lock, Cowork prompts to grant delete access to the working folder; allowing it lets rm .git/index.lock succeed from the bash sandbox and the save proceeds. Allowing it persistently means a future orphaned lock can be cleared in-session instead of blocking until you switch to the CLI. — Reply to this email directly, view it on GitHub <https://github.com/anthropics/claude-code/issues/55206?email_source=notifications&email_token=B4GSVDXPB7EXKMMXSMH2FIL5AYXDBA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINZVGY3TKOBUGM4KM4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4756758438>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/B4GSVDX65E2AI3PNMLMLXNT5AYXDBAVCNFSNUABFKJSXA33TNF2G64TZHM4TGNZSGUZTINZVHNEXG43VMU5TIMZWGI3DOMJXG4Z2C5QC> . You are receiving this because you commented.Message ID: @.***>
peedawg · 1 month ago

Also reproduces on macOS — not Windows-specific.

Same structural unlink() denial on a Cowork session on macOS (Apple silicon). The repo is a normal local folder, mounted into the sandbox over FUSE (fuseblk / type fuse). POSIX perms show the files owned by the sandbox uid, but unlink is rejected regardless; rename() and in-place overwrite are allowed.

Control test (mount vs. off-mount, brand-new file, no race window):

off the mount (sandbox ext4) — fine

$ cd /tmp && touch foo && rm foo && echo ok
ok

on the mounted repo — denied

$ cd /sessions/<session>/mnt/<repo> && touch foo && rm foo
rm: cannot remove 'foo': Operation not permitted

The knock-on for git is worse than "commit fails": because git clears .git/index.lock with unlink(), even a read-only git status leaves a fresh index.lock behind that the sandbox then cannot remove, so it blocks the next command:

$ git status
warning: unable to unlink '/sessions/<session>/mnt/<repo>/.git/index.lock': Operation not permitted
$ find .git -name '*.lock'
.git/index.lock # ← left behind by a plain status, blocks the next op

So the friction is continuous, not occasional — each git invocation poisons the following one.

Filesystem-only workaround that does work (since rename is permitted but unlink is not): keep the working tree on the mount but move git's metadata off-mount, so all lock files land on a filesystem where unlink works:

git --git-dir=/tmp/repo.git --work-tree=/sessions/<session>/mnt/<repo> <cmd>

cp -a <mount>/.git /tmp/repo.git first (copy is create+read, both allowed). Commits/pushes then run clean with zero orphaned locks on the mount; the commit is delivered to origin and the host repo syncs by pulling. This is a palliative, not a fix — the underlying request stands: the sandbox should permit unlink() on the mounted folder (or the "Cowork can manage version control" workflow should be documented as unavailable on a mounted host repo until it does).

Suggested label update: this is not platform:windows only — please broaden to include macOS.