Zlog Multi-Instance Storage Optimizer
Compress background tool logs across AI agents (~77%-99.9% space saved / fast zstd -15 fallback). Purge 0-byte empty logs. Keep transcript.jsonl intact. Safe for concurrent running agents. Skip tiny logs (<10KiB) and text docs. Handle symlinks cleanly. Reports per-run savings + total summary.
Execution Intents
- Standard Cleanup: Triggered on "zlog", "compress logs", "clean up chat logs", "pack logs", or session wrap-up.
- Dry-Run Preview: Triggered on "preview zlog", "dry run", "test log cleanup".
- Deep Scan: Triggered on "find new AI agents", "scan disk for hidden AI logs".
Safety & Invariant Protection
- Process Locks: Query
fuser -s "$f" (Linux/WSL), lsof "$f" (macOS), or [System.IO.File]::Open(..., 'None') (Windows 11 PowerShell). Skip file if active process lock exists.
- In-Flight Window: Skip files modified <60 seconds ago (
-mmin +1).
- Protected Files: Exclude
*.jsonl, SKILL.md, README*, LICENSE*, and files <= 10KiB.
- Junk-Dir Pruning: Scans never descend into
node_modules, Caches, Cache, Code Cache, blob_storage, GPUCache, DawnGraphiteCache, DawnWebGPUCache, or .git. Pruned-dir count is reported.
- Depth Bound: Deep scan capped at
-maxdepth 12 (Antigravity nests ~8 levels deep) — bounded runtime, belt-and-suspenders with pruning.
- Hardlink Aliases: Mirror dirs sharing the same inode (e.g. Antigravity
antigravity-* copies) may list one file several times; each name compresses independently — harmless and self-healing.
Commands
Standard Compression & Empty Log Purge (Linux, macOS, WSL, Git Bash)
raw=0; saved=0; count=0
for d in ~/.gemini ~/.config/Cursor ~/.cursor ~/.ollama ~/.claude ~/.config/claude-code ~/.windsurf ~/.codex ~/.cache/lm-studio; do
[ -d "$d" ] || continue
find -L "$d" \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -empty -type f -delete 2>/dev/null || true
while IFS= read -r f; do
[ -z "$f" ] && continue
size=$(stat -c%s "$f" 2>/dev/null || stat -f%z "$f" 2>/dev/null) || size=0
(command -v fuser >/dev/null 2>&1 && fuser -s "$f" 2>/dev/null) || (command -v lsof >/dev/null 2>&1 && lsof "$f" >/dev/null 2>&1) || (command -v zstd >/dev/null 2>&1 && zstd -15 -q --rm "$f") || (command -v xz >/dev/null 2>&1 && xz -9 "$f") || gzip -f "$f"
for c in zst xz gz; do
[ -f "$f.$c" ] || continue
newsize=$(stat -c%s "$f.$c" 2>/dev/null || stat -f%z "$f.$c" 2>/dev/null) || newsize=0
raw=$((raw + size)); saved=$((saved + size - newsize)); count=$((count + 1))
break
done
done < <(find -L "$d" \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache \) -prune \) -o \( -type f \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -not -name "*.gz" -not -name "*.zst" -not -name "*.xz" -not -name "*.jsonl" -not -name "SKILL.md" -not -iname "README*" -not -iname "LICENSE*" -size +10k -mmin +1 \) 2>/dev/null)
done
if [ "$count" -gt 0 ]; then
comp=$((raw - saved))
raw_h=$(numfmt --to=iec "$raw" 2>/dev/null || echo "${raw}B")
comp_h=$(numfmt --to=iec "$comp" 2>/dev/null || echo "${comp}B")
saved_h=$(numfmt --to=iec "$saved" 2>/dev/null || echo "${saved}B")
echo "[zlog] Compressed $count files: $raw_h -> $comp_h (saved $saved_h, $(( saved * 100 / raw ))% smaller)"
fi
dirs=(); for d in ~/.gemini ~/.config/Cursor ~/.cursor ~/.ollama ~/.claude ~/.config/claude-code ~/.windsurf ~/.codex ~/.cache/lm-studio; do [ -d "$d" ] && [ ! -L "$d" ] && dirs+=("$d"); done; [ ${#dirs[@]} -gt 0 ] && du -ch "${dirs[@]}" 2>/dev/null | tail -n 1 || true
Dry-Run Mode (Preview Without Modifying Files)
total=0; count=0
for d in ~/.gemini ~/.config/Cursor ~/.cursor ~/.ollama ~/.claude ~/.config/claude-code ~/.windsurf ~/.codex ~/.cache/lm-studio; do
[ -d "$d" ] || continue
while IFS= read -r f; do
[ -z "$f" ] && continue
size=$(stat -c%s "$f" 2>/dev/null || stat -f%z "$f" 2>/dev/null) || size=0
total=$((total + size)); count=$((count + 1))
hum=$(numfmt --to=iec "$size" 2>/dev/null || echo "${size}B")
echo "[DRY-RUN] Would compress: $f ($hum)"
done < <(find -L "$d" \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache \) -prune \) -o \( -type f \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -not -name "*.gz" -not -name "*.zst" -not -name "*.xz" -not -name "*.jsonl" -not -name "SKILL.md" -not -iname "README*" -not -iname "LICENSE*" -size +10k -mmin +1 \) 2>/dev/null)
done
saved=$((total * 77 / 100)); comp=$((total - saved))
total_hum=$(numfmt --to=iec "$total" 2>/dev/null || echo "${total}B")
comp_hum=$(numfmt --to=iec "$comp" 2>/dev/null || echo "${comp}B")
echo ""
echo "[DRY-RUN] Total: $count files, $total_hum raw -> ~$comp_hum compressed (est. 77% savings)"
Windows 11 Native Compression (PowerShell - Process Lock Safe)
Get-ChildItem -Path "$env:USERPROFILE\.gemini","$env:USERPROFILE\.cursor","$env:USERPROFILE\.ollama","$env:USERPROFILE\.claude","$env:USERPROFILE\.windsurf","$env:USERPROFILE\.codex" -Recurse -Include *.log,*.out,*.txt,*.trace -Exclude *.gz,*.zst,*.xz,*.jsonl,SKILL.md,README*,LICENSE* -ErrorAction SilentlyContinue | Where-Object { $_.Length -gt 10KB -and $_.LastWriteTime -lt (Get-Date).AddMinutes(-1) -and (try { $s = [System.IO.File]::Open($_.FullName, 'Open', 'ReadWrite', 'None'); $s.Close(); $true } catch { $false }) } | ForEach-Object { tar.exe -czf "$($_.FullName).tar.gz" -C $_.DirectoryName $_.Name; Remove-Item $_.FullName }
Deep Scan (On user request: "find new AI agents" / "scan disk")
pruned=$(find -L ~ -maxdepth 12 \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache -o -name .git \) -prune \) -print 2>/dev/null | wc -l)
find -L ~ -maxdepth 12 \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache -o -name .git \) -prune \) -o \( -path "*/.gemini/*" -o -path "*/.config/Cursor/*" -o -path "*/.cursor/*" -o -path "*/.claude/*" -o -path "*/.config/claude-code/*" -o -path "*/.ollama/*" -o -path "*/.windsurf/*" -o -path "*/.codex/*" -o -path "*/.cache/lm-studio/*" -o -path "*/.lm-studio/*" \) -type f \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -not -name "*.gz" -not -name "*.zst" -not -name "*.xz" -not -name "*.jsonl" -not -name "SKILL.md" -not -iname "README*" -not -iname "LICENSE*" -size +10k -mmin +1 -exec sh -c 'for f; do (command -v fuser >/dev/null 2>&1 && fuser -s "$f" 2>/dev/null) || (command -v lsof >/dev/null 2>&1 && lsof "$f" >/dev/null 2>&1) || (command -v zstd >/dev/null 2>&1 && zstd -15 -q --rm "$f") || (command -v xz >/dev/null 2>&1 && xz -9 "$f") || gzip -f "$f"; done' sh {} + 2>/dev/null || true
echo "[zlog] Deep scan pruned $pruned junk/cache dirs (maxdepth 12)"
Helpers
- Read
.zst / .gz: zstdcat file.log.zst or zcat file.log.gz
- Read Windows
.tar.gz: tar -xzf file.log.tar.gz (extracts original log back)
- Decompress:
zstd -d file.log.zst or gzip -d file.log.gz
- Search:
zstdgrep "pattern" file.log.zst or zgrep "pattern" file.log.gz
1---2name: zlog3description: Multi-agent session log compressor and storage optimizer. Compresses `.log`, `.out`, `.txt`, `.trace` (>10KiB) to `.zst`, `.xz`, `.gz`, or `.tar.gz` (Windows) (saving 77%-99.9% disk space) across `~/.gemini`, `~/.config/Cursor`, `~/.ollama`, `~/.claude`, `~/.windsurf`, `~/.codex`, etc. Auto-discovers AI log dirs, purges empty 0-byte logs. Safe for concurrent multi-instance running agents. Includes Dry-Run preview mode. Use when wrapping up, ending sessions, or asked to clean logs, zlog, pack logs, or find new AI agents.4license: MIT5---67# Zlog Multi-Instance Storage Optimizer89Compress background tool logs across AI agents (~77%-99.9% space saved / fast zstd -15 fallback). Purge 0-byte empty logs. Keep `transcript.jsonl` intact. Safe for concurrent running agents. Skip tiny logs (<10KiB) and text docs. Handle symlinks cleanly. Reports per-run savings + total summary.1011## Execution Intents1213- **Standard Cleanup**: Triggered on "zlog", "compress logs", "clean up chat logs", "pack logs", or session wrap-up.14- **Dry-Run Preview**: Triggered on "preview zlog", "dry run", "test log cleanup".15- **Deep Scan**: Triggered on "find new AI agents", "scan disk for hidden AI logs".1617## Safety & Invariant Protection1819- **Process Locks**: Query `fuser -s "$f"` (Linux/WSL), `lsof "$f"` (macOS), or `[System.IO.File]::Open(..., 'None')` (Windows 11 PowerShell). Skip file if active process lock exists.20- **In-Flight Window**: Skip files modified <60 seconds ago (`-mmin +1`).21- **Protected Files**: Exclude `*.jsonl`, `SKILL.md`, `README*`, `LICENSE*`, and files <= 10KiB.22- **Junk-Dir Pruning**: Scans never descend into `node_modules`, `Caches`, `Cache`, `Code Cache`, `blob_storage`, `GPUCache`, `DawnGraphiteCache`, `DawnWebGPUCache`, or `.git`. Pruned-dir count is reported.23- **Depth Bound**: Deep scan capped at `-maxdepth 12` (Antigravity nests ~8 levels deep) — bounded runtime, belt-and-suspenders with pruning.24- **Hardlink Aliases**: Mirror dirs sharing the same inode (e.g. Antigravity `antigravity-*` copies) may list one file several times; each name compresses independently — harmless and self-healing.2526## Commands2728### Standard Compression & Empty Log Purge (Linux, macOS, WSL, Git Bash)2930```bash31raw=0; saved=0; count=032for d in ~/.gemini ~/.config/Cursor ~/.cursor ~/.ollama ~/.claude ~/.config/claude-code ~/.windsurf ~/.codex ~/.cache/lm-studio; do33 [ -d "$d" ] || continue34 find -L "$d" \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -empty -type f -delete 2>/dev/null || true35 while IFS= read -r f; do36 [ -z "$f" ] && continue37 size=$(stat -c%s "$f" 2>/dev/null || stat -f%z "$f" 2>/dev/null) || size=038 (command -v fuser >/dev/null 2>&1 && fuser -s "$f" 2>/dev/null) || (command -v lsof >/dev/null 2>&1 && lsof "$f" >/dev/null 2>&1) || (command -v zstd >/dev/null 2>&1 && zstd -15 -q --rm "$f") || (command -v xz >/dev/null 2>&1 && xz -9 "$f") || gzip -f "$f"39 for c in zst xz gz; do40 [ -f "$f.$c" ] || continue41 newsize=$(stat -c%s "$f.$c" 2>/dev/null || stat -f%z "$f.$c" 2>/dev/null) || newsize=042 raw=$((raw + size)); saved=$((saved + size - newsize)); count=$((count + 1))43 break44 done45 done < <(find -L "$d" \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache \) -prune \) -o \( -type f \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -not -name "*.gz" -not -name "*.zst" -not -name "*.xz" -not -name "*.jsonl" -not -name "SKILL.md" -not -iname "README*" -not -iname "LICENSE*" -size +10k -mmin +1 \) 2>/dev/null)46done47if [ "$count" -gt 0 ]; then48 comp=$((raw - saved))49 raw_h=$(numfmt --to=iec "$raw" 2>/dev/null || echo "${raw}B")50 comp_h=$(numfmt --to=iec "$comp" 2>/dev/null || echo "${comp}B")51 saved_h=$(numfmt --to=iec "$saved" 2>/dev/null || echo "${saved}B")52 echo "[zlog] Compressed $count files: $raw_h -> $comp_h (saved $saved_h, $(( saved * 100 / raw ))% smaller)"53fi54dirs=(); for d in ~/.gemini ~/.config/Cursor ~/.cursor ~/.ollama ~/.claude ~/.config/claude-code ~/.windsurf ~/.codex ~/.cache/lm-studio; do [ -d "$d" ] && [ ! -L "$d" ] && dirs+=("$d"); done; [ ${#dirs[@]} -gt 0 ] && du -ch "${dirs[@]}" 2>/dev/null | tail -n 1 || true55```5657### Dry-Run Mode (Preview Without Modifying Files)5859```bash60total=0; count=061for d in ~/.gemini ~/.config/Cursor ~/.cursor ~/.ollama ~/.claude ~/.config/claude-code ~/.windsurf ~/.codex ~/.cache/lm-studio; do62 [ -d "$d" ] || continue63 while IFS= read -r f; do64 [ -z "$f" ] && continue65 size=$(stat -c%s "$f" 2>/dev/null || stat -f%z "$f" 2>/dev/null) || size=066 total=$((total + size)); count=$((count + 1))67 hum=$(numfmt --to=iec "$size" 2>/dev/null || echo "${size}B")68 echo "[DRY-RUN] Would compress: $f ($hum)"69 done < <(find -L "$d" \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache \) -prune \) -o \( -type f \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -not -name "*.gz" -not -name "*.zst" -not -name "*.xz" -not -name "*.jsonl" -not -name "SKILL.md" -not -iname "README*" -not -iname "LICENSE*" -size +10k -mmin +1 \) 2>/dev/null)70done71saved=$((total * 77 / 100)); comp=$((total - saved))72total_hum=$(numfmt --to=iec "$total" 2>/dev/null || echo "${total}B")73comp_hum=$(numfmt --to=iec "$comp" 2>/dev/null || echo "${comp}B")74echo ""75echo "[DRY-RUN] Total: $count files, $total_hum raw -> ~$comp_hum compressed (est. 77% savings)"76```7778### Windows 11 Native Compression (PowerShell - Process Lock Safe)7980```powershell81Get-ChildItem -Path "$env:USERPROFILE\.gemini","$env:USERPROFILE\.cursor","$env:USERPROFILE\.ollama","$env:USERPROFILE\.claude","$env:USERPROFILE\.windsurf","$env:USERPROFILE\.codex" -Recurse -Include *.log,*.out,*.txt,*.trace -Exclude *.gz,*.zst,*.xz,*.jsonl,SKILL.md,README*,LICENSE* -ErrorAction SilentlyContinue | Where-Object { $_.Length -gt 10KB -and $_.LastWriteTime -lt (Get-Date).AddMinutes(-1) -and (try { $s = [System.IO.File]::Open($_.FullName, 'Open', 'ReadWrite', 'None'); $s.Close(); $true } catch { $false }) } | ForEach-Object { tar.exe -czf "$($_.FullName).tar.gz" -C $_.DirectoryName $_.Name; Remove-Item $_.FullName }82```8384### Deep Scan (On user request: "find new AI agents" / "scan disk")8586```bash87pruned=$(find -L ~ -maxdepth 12 \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache -o -name .git \) -prune \) -print 2>/dev/null | wc -l)88find -L ~ -maxdepth 12 \( -type d \( -name node_modules -o -name Caches -o -name Cache -o -name "Code Cache" -o -name blob_storage -o -name GPUCache -o -name DawnGraphiteCache -o -name DawnWebGPUCache -o -name .git \) -prune \) -o \( -path "*/.gemini/*" -o -path "*/.config/Cursor/*" -o -path "*/.cursor/*" -o -path "*/.claude/*" -o -path "*/.config/claude-code/*" -o -path "*/.ollama/*" -o -path "*/.windsurf/*" -o -path "*/.codex/*" -o -path "*/.cache/lm-studio/*" -o -path "*/.lm-studio/*" \) -type f \( -name "*.log" -o -name "*.out" -o -name "*.trace" -o -name "*.txt" \) -not -name "*.gz" -not -name "*.zst" -not -name "*.xz" -not -name "*.jsonl" -not -name "SKILL.md" -not -iname "README*" -not -iname "LICENSE*" -size +10k -mmin +1 -exec sh -c 'for f; do (command -v fuser >/dev/null 2>&1 && fuser -s "$f" 2>/dev/null) || (command -v lsof >/dev/null 2>&1 && lsof "$f" >/dev/null 2>&1) || (command -v zstd >/dev/null 2>&1 && zstd -15 -q --rm "$f") || (command -v xz >/dev/null 2>&1 && xz -9 "$f") || gzip -f "$f"; done' sh {} + 2>/dev/null || true89echo "[zlog] Deep scan pruned $pruned junk/cache dirs (maxdepth 12)"90```9192## Helpers9394- **Read `.zst` / `.gz`**: `zstdcat file.log.zst` or `zcat file.log.gz`95- **Read Windows `.tar.gz`**: `tar -xzf file.log.tar.gz` (extracts original log back)96- **Decompress**: `zstd -d file.log.zst` or `gzip -d file.log.gz`97- **Search**: `zstdgrep "pattern" file.log.zst` or `zgrep "pattern" file.log.gz`