Problem
internal/hooks/hooks.go:176 writes the merged settings.json directly with os.WriteFile:
if err := os.WriteFile(settingsPath, finalJSON, 0600); err != nil {
return nil, fmt.Errorf("writing settings.json: %w", err)
}
If the process is killed or the disk fills up mid-write, settings.json is left truncated or corrupt — which breaks the user's entire Claude Code configuration, not just Uncompact. This is a particularly high-impact failure because Claude Code reads settings.json at startup and a parse error could disable all hooks globally.
Fix
Use the same atomic temp-file + rename pattern already used elsewhere in the codebase:
internal/snapshot/snapshot.go:40-45 — writes .tmp then os.Rename
internal/activitylog/activitylog.go:95-99 — same pattern in rotate
In hooks.Install, replace the direct os.WriteFile with:
- Write
finalJSON to settingsPath + ".tmp"
os.Rename(settingsPath+".tmp", settingsPath)
os.Rename is atomic on POSIX systems (and reasonably safe on Windows with NTFS), so a crash mid-write leaves the original settings.json intact.
Affected file
internal/hooks/hooks.go lines 172–178
@claude please implement this