Thanks for the tool — the incremental sync design is genuinely nice. Two environment reports incoming; this one is Windows.
Environment: claude-backup 0.1.12 (commit 6c009ec), Python 3.13, Windows 11, installed via uv tool install.
Symptom: every run crashes on the first write:
File "...\claude_backup\__init__.py", line 238, in save
Path(f.name).rename(cache_file)
...
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '...\\account.json-ifkiygrk'
Cause: in Store.save, the Path(f.name).rename(cache_file) happens inside the with NamedTemporaryFile(...) block, while the handle is still open. POSIX allows renaming an open file; Windows does not. The except BaseException cleanup path then also fails for the same reason (unlink of an open file).
Suggested fix: keep delete=False, write + flush inside the block, and move the rename to after the with closes the handle — os.replace(f.name, cache_file) after the block preserves the atomic-replace semantics on both platforms (Path.rename refuses to overwrite an existing target on Windows too, so os.replace covers that case as well).
Happy to test a fix — I have a Windows + WSL setup where this reproduces 100% of the time.
Thanks for the tool — the incremental sync design is genuinely nice. Two environment reports incoming; this one is Windows.
Environment: claude-backup 0.1.12 (commit 6c009ec), Python 3.13, Windows 11, installed via
uv tool install.Symptom: every run crashes on the first write:
Cause: in
Store.save, thePath(f.name).rename(cache_file)happens inside thewith NamedTemporaryFile(...)block, while the handle is still open. POSIX allows renaming an open file; Windows does not. Theexcept BaseExceptioncleanup path then also fails for the same reason (unlinkof an open file).Suggested fix: keep
delete=False, write + flush inside the block, and move the rename to after thewithcloses the handle —os.replace(f.name, cache_file)after the block preserves the atomic-replace semantics on both platforms (Path.renamerefuses to overwrite an existing target on Windows too, soos.replacecovers that case as well).Happy to test a fix — I have a Windows + WSL setup where this reproduces 100% of the time.