From af873fa529ab5e9d85a6fdbf14d5a50e0dfa25d8 Mon Sep 17 00:00:00 2001 From: Aurelio <19254254+Aureliolo@users.noreply.github.com> Date: Mon, 16 Mar 2026 21:45:06 +0100 Subject: [PATCH 1/2] docs: add uv cache lock contention handling to worktree skill Pre-sync venvs sequentially during worktree setup to prevent concurrent uv instances from serializing on the global cache lock. Adds troubleshooting guidance for the lock file location. --- .claude/skills/worktree/SKILL.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.claude/skills/worktree/SKILL.md b/.claude/skills/worktree/SKILL.md index a97fcfbf5f..991892cc7a 100644 --- a/.claude/skills/worktree/SKILL.md +++ b/.claude/skills/worktree/SKILL.md @@ -137,6 +137,14 @@ Directory suffix is auto-derived from the branch name: for f in .claude/*.local.*; do test -f "$f" && cp "$f" "/.claude/$(basename "$f")"; done ``` + d. **Pre-sync the venv** to prevent uv cache lock contention when multiple Claude Code instances run concurrently. `uv` uses a global cache lock (`~/.local/uv/cache/.lock` or `$LOCALAPPDATA/uv/cache/.lock`) — if multiple worktrees run `uv run`/`uv sync` simultaneously, they serialize on this lock and all appear to hang. Pre-syncing sequentially here avoids this: + + ```bash + cd && uv sync 2>&1 | tail -3; cd - + ``` + + Run these **sequentially** (one per worktree, not in parallel) to avoid cache lock contention during setup itself. + 4. **Verify all worktrees created:** ```bash @@ -450,6 +458,7 @@ Update all worktrees to latest main. Pulls main first, then rebases clean worktr - Owner/repo (from `git remote`): must match `^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$` - Directory paths: must not contain shell metacharacters (`;`, `|`, `&`, `$`, `` ` ``, `(`, `)`) - Reject and warn if any value fails validation — do not execute the command. +- **uv cache lock contention:** `uv` uses a global cache lock file (`$LOCALAPPDATA/uv/cache/.lock` on Windows, `~/.cache/uv/.lock` on Linux/macOS). When multiple worktrees run `uv run` or `uv sync` concurrently, they serialize on this lock, causing all instances to appear stuck. The `setup` command pre-syncs each worktree's venv sequentially to avoid this. If users report all instances hanging on python/uv commands, the fix is: `rm -f "$LOCALAPPDATA/uv/cache/.lock"` (Windows) or `rm -f ~/.cache/uv/.lock` (Linux/macOS). - If `$ARGUMENTS` is empty or doesn't match a command, show a brief usage guide: ```text From be953335ab7a450cade3da1cf20e130c58bddc16 Mon Sep 17 00:00:00 2001 From: Aurelio <19254254+Aureliolo@users.noreply.github.com> Date: Mon, 16 Mar 2026 21:56:35 +0100 Subject: [PATCH 2/2] fix: address PR review feedback on worktree skill - Correct macOS cache lock path to ~/Library/Caches/uv/.lock (was grouped with Linux as ~/.cache/uv/.lock) - Use $HOME/.cache/uv/.lock for Linux (explicit) - Remove uv sync pipe to tail -3 that masked exit codes - Add safety note: verify no active uv processes before removing stale lock file --- .claude/skills/worktree/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/skills/worktree/SKILL.md b/.claude/skills/worktree/SKILL.md index 991892cc7a..5d205478e3 100644 --- a/.claude/skills/worktree/SKILL.md +++ b/.claude/skills/worktree/SKILL.md @@ -137,10 +137,10 @@ Directory suffix is auto-derived from the branch name: for f in .claude/*.local.*; do test -f "$f" && cp "$f" "/.claude/$(basename "$f")"; done ``` - d. **Pre-sync the venv** to prevent uv cache lock contention when multiple Claude Code instances run concurrently. `uv` uses a global cache lock (`~/.local/uv/cache/.lock` or `$LOCALAPPDATA/uv/cache/.lock`) — if multiple worktrees run `uv run`/`uv sync` simultaneously, they serialize on this lock and all appear to hang. Pre-syncing sequentially here avoids this: + d. **Pre-sync the venv** to prevent uv cache lock contention when multiple Claude Code instances run concurrently. `uv` uses a global cache lock (`$LOCALAPPDATA/uv/cache/.lock` on Windows, `$HOME/.cache/uv/.lock` on Linux, `~/Library/Caches/uv/.lock` on macOS) — if multiple worktrees run `uv run`/`uv sync` simultaneously, they serialize on this lock and all appear to hang. Pre-syncing sequentially here avoids this: ```bash - cd && uv sync 2>&1 | tail -3; cd - + cd && uv sync; cd - ``` Run these **sequentially** (one per worktree, not in parallel) to avoid cache lock contention during setup itself. @@ -458,7 +458,7 @@ Update all worktrees to latest main. Pulls main first, then rebases clean worktr - Owner/repo (from `git remote`): must match `^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$` - Directory paths: must not contain shell metacharacters (`;`, `|`, `&`, `$`, `` ` ``, `(`, `)`) - Reject and warn if any value fails validation — do not execute the command. -- **uv cache lock contention:** `uv` uses a global cache lock file (`$LOCALAPPDATA/uv/cache/.lock` on Windows, `~/.cache/uv/.lock` on Linux/macOS). When multiple worktrees run `uv run` or `uv sync` concurrently, they serialize on this lock, causing all instances to appear stuck. The `setup` command pre-syncs each worktree's venv sequentially to avoid this. If users report all instances hanging on python/uv commands, the fix is: `rm -f "$LOCALAPPDATA/uv/cache/.lock"` (Windows) or `rm -f ~/.cache/uv/.lock` (Linux/macOS). +- **uv cache lock contention:** `uv` uses a global cache lock file (`$LOCALAPPDATA/uv/cache/.lock` on Windows, `$HOME/.cache/uv/.lock` on Linux, `~/Library/Caches/uv/.lock` on macOS). When multiple worktrees run `uv run` or `uv sync` concurrently, they serialize on this lock, causing all instances to appear stuck. The `setup` command pre-syncs each worktree's venv sequentially to avoid this. If users report all instances hanging on python/uv commands, first verify no `uv` processes are still running (`ps aux | grep uv` or Task Manager), then remove the stale lock: `rm -f "$LOCALAPPDATA/uv/cache/.lock"` (Windows), `rm -f ~/.cache/uv/.lock` (Linux), or `rm -f ~/Library/Caches/uv/.lock` (macOS). - If `$ARGUMENTS` is empty or doesn't match a command, show a brief usage guide: ```text