{"id":50962271,"url":"https://github.com/ariccio/compress-agent-sessions","last_synced_at":"2026-06-18T15:33:26.625Z","repository":{"id":356602477,"uuid":"1233245053","full_name":"ariccio/compress-agent-sessions","owner":"ariccio","description":"macOS APFS transparent compression for cold agentic-CLI session JSONLs (Claude Code, Codex, Gemini).","archived":false,"fork":false,"pushed_at":"2026-05-08T20:02:58.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-08T21:32:00.877Z","etag":null,"topics":["agentic","apfs","claude-code","codex-cli","compression","decmpfs","disk-space","gemini-cli","macos","zsh"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ariccio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-08T18:46:40.000Z","updated_at":"2026-05-08T20:03:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ariccio/compress-agent-sessions","commit_stats":null,"previous_names":["ariccio/compress-agent-sessions"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/ariccio/compress-agent-sessions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariccio%2Fcompress-agent-sessions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariccio%2Fcompress-agent-sessions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariccio%2Fcompress-agent-sessions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariccio%2Fcompress-agent-sessions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ariccio","download_url":"https://codeload.github.com/ariccio/compress-agent-sessions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariccio%2Fcompress-agent-sessions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34497366,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic","apfs","claude-code","codex-cli","compression","decmpfs","disk-space","gemini-cli","macos","zsh"],"created_at":"2026-06-18T15:33:24.503Z","updated_at":"2026-06-18T15:33:26.610Z","avatar_url":"https://github.com/ariccio.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# compress-agent-sessions\n\n![macOS only](https://img.shields.io/badge/macOS-only-lightgrey) ![best-effort](https://img.shields.io/badge/maintenance-best--effort-yellow)\n\nApply macOS transparent per-file compression (APFS `UF_COMPRESSED`) to stale\nagentic-CLI session-log JSONL archives. Reclaim disk without changing how\napps read the files — the kernel decompresses transparently on read.\n\nTypical ratio on JSONL: **5–50× with LZFSE**.\n\n\u003e This is a focused macOS-only utility, maintained on a best-effort basis.\n\u003e See [Scope](#scope) before filing feature requests.\n\n## Why\n\nClaude Code, Codex CLI, Gemini CLI, and similar agentic tools accumulate\nJSONL session transcripts indefinitely. On APFS, macOS's built-in\ntransparent compression mechanism — the same one Apple uses for OS\nbinaries — reclaims huge amounts of space with zero runtime cost:\nthe file looks and reads identically, the disk usage drops.\n\n## Install\n\n    brew install Dr-Emann/homebrew-tap/applesauce\n    # then drop the script anywhere in PATH, e.g.:\n    ln -s \"$(pwd)/bin/compress-agent-sessions\" /usr/local/bin/\n\nThe script auto-detects the best available tool at runtime:\n\n| Preference | Tool | Notes |\n|---|---|---|\n| 1 | `applesauce` | Recommended — fastest, safest, atomic rename |\n| 2 | `afsctool` | Classic choice; `brew install afsctool` |\n| 3 | `ditto --hfsCompression` | Pre-installed but **unreliable on APFS**; avoid if possible |\n\nForce a specific tool with `--tool applesauce|afsctool|ditto`.\n\n## Quick start\n\n    # what's eligible, without touching anything\n    compress-agent-sessions estimate\n\n    # show every file with its classification\n    compress-agent-sessions list\n\n    # dry run — describe without modifying\n    compress-agent-sessions compress --dry-run\n\n    # actually compress\n    compress-agent-sessions compress\n\n    # cumulative + recent-run totals\n    compress-agent-sessions stats\n\n    # undo (decompress)\n    compress-agent-sessions restore ~/.codex/sessions/2026/01\n\nDefault discovery scopes (auto-detected):\n\n- Claude Code: `$HOME/.claude/projects/*/*.jsonl`\n- Codex CLI:   `$HOME/.codex/sessions/**/*`\n- Gemini CLI:  `$HOME/.gemini/sessions/` (if present)\n\nOverride with explicit paths:\n\n    compress-agent-sessions compress ~/.codex/sessions/2026/01\n\n## Safety model\n\nThe tool will **skip** a file — never silently compressing it — if:\n\n- mtime within `--active-grace-minutes` (default 15) — likely being written\n- held open by any process (`lsof`) — someone's reading/writing right now\n- in the Codex \"current month\" directory — today's logs\n- already has the `UF_COMPRESSED` flag (idempotent)\n- younger than `--age-days` (default 14)\n- matches an `--exclude` glob\n\nEvery skip has a reason code, surfaced in `list`, `compress`, and the ledger.\n\nAll compression is reversible: `compress-agent-sessions restore PATHS`.\n\n## How it works\n\nmacOS has had transparent per-file compression since Mac OS X 10.6 Snow\nLeopard — the original HFS+ `com.apple.decmpfs` mechanism. APFS kept\nbackward compatibility and uses the same `UF_COMPRESSED` inode flag.\nModern compressors like `applesauce` use it to store compressed payload\ninline (small files) or in an xattr-overflow extent (larger files).\n\nKey property: **writes to a compressed file kill the compression**. The\nkernel decompresses the whole file back to uncompressed bytes before\napplying the write. That's why this tool only targets cold archives —\ncompression is stable as long as nobody writes to the file again.\n\nAlgorithms (via `--algorithm`):\n\n| Algo | Ratio (JSONL) | Decode speed | Recommended? |\n|---|---|---|---|\n| `LZFSE` (default) | ~50× | fastest | yes, for new work |\n| `ZLIB` | slightly higher at level 9 | ~3× slower than LZFSE | only if you need maximum ratio |\n| `LZVN` | in between | fast | no (LZFSE dominates) |\n\n## Ledger\n\nPer-run JSON at `$LEDGER_DIR/runs/\u003cISO8601\u003e.json`. Cumulative totals in\n`$LEDGER_DIR/cumulative.txt`.\n\n`$LEDGER_DIR` defaults to `${XDG_STATE_HOME:-$HOME/.local/state}/compress-agent-sessions`.\nOverride with `--ledger-dir PATH`.\n\n`compress-agent-sessions stats` prints the cumulative totals + the 10\nmost recent runs.\n\n## Automation\n\nSee `docs/launchd-weekly-example.plist` for a launchd template that runs\nthe tool weekly. Install with:\n\n    mkdir -p ~/Library/LaunchAgents\n    cp docs/launchd-weekly-example.plist ~/Library/LaunchAgents/com.user.compress-agent-sessions.plist\n    # edit paths to match your install\n    launchctl load ~/Library/LaunchAgents/com.user.compress-agent-sessions.plist\n\n## Scope\n\nSingle-script macOS utility. Scope is **frozen** to the current 5 subcommands\n(`estimate`, `compress`, `list`, `stats`, `restore`) and the existing 3 backends\n(`applesauce`, `afsctool`, `ditto`). PRs adding new subcommands, new compression\nbackends, or non-macOS platform support **will not be merged** — fork instead.\n\nBug-fix PRs are welcome when accompanied by a smoke-test assertion. See\n[CONTRIBUTING.md](CONTRIBUTING.md) for the contribution policy and the three\nhard-close labels (`wontfix:platform`, `wontfix:scope`, `wontfix:ai-generated`).\n\n## Troubleshooting\n\n### No candidates found\n\nAuto-discovery looks under `~/.claude/projects/`, `~/.codex/sessions/`, and\n`~/.gemini/sessions/`. If those directories don't exist or all files are\nyounger than `--age-days` (default 14), zero candidates is correct. Check:\n\n    compress-agent-sessions list                  # see classification\n    compress-agent-sessions list --age-days 0     # ignore age (debug)\n\n### `lsof not found on PATH`\n\nRequired for active-handle safety detection. `/usr/sbin/lsof` ships with\nmacOS as part of the base install — it is **not** an Xcode CLT component.\nIf the script cannot find it, the likely causes are:\n\n- **Asahi Linux / Docker-on-Mac**: the macOS base userspace is absent; lsof\n  is genuinely missing and must be installed.\n- **Stripped macOS environment**: a minimal container or CI image that\n  deliberately excludes base tools.\n\nWorkaround:\n\n    brew install lsof\n\nThe script aborts hard rather than silently shipping without open-handle\nprotection — this is intentional.\n\n### `ditto` compresses but `du -sh` shows no change\n\n`ditto --hfsCompression` is documented as best-effort and **frequently no-ops\non APFS** despite returning success. Force a real backend:\n\n    brew install Dr-Emann/homebrew-tap/applesauce  # preferred\n    # or\n    brew install afsctool                           # fallback\n\nThen re-run with `--tool applesauce` (or let auto-detection pick it).\n\n### chflags truncation — known macOS kernel behavior\n\n\u003e ⚠ **Read this before wrapping the script in other tooling.**\n\u003e\n\u003e Calling `chflags(1)` or `chflags(2)` on a decmpfs-compressed file will\n\u003e **silently truncate it to zero bytes**. This is documented Apple kernel\n\u003e behavior, **not** a vulnerability in this tool. The script never calls\n\u003e `chflags` on a compressed file, but if you pipe its output into tooling\n\u003e that does, decompress first via `applesauce decompress` or\n\u003e `compress-agent-sessions restore \u003cpath\u003e`.\n\u003e\n\u003e Reports of this as a CVE will be closed with `wontfix:platform`.\n\n### `restore` aborted — \u003e100 compressed files in scope\n\n`restore` requires `--confirm-destructive` when the target scope contains more\nthan 100 decmpfs-compressed files. This gate applies to both real restore **and**\n`--dry-run`. If you have verified the scope and intend to decompress, re-run with:\n\n    compress-agent-sessions restore --confirm-destructive [PATHS...]\n\nThis gate does NOT apply to `compress` (compression is reversible). The error\nmessage includes the exact command to re-run with the flag.\n\n### Before Filing a Bug\n\nThree things make any bug actionable. Include all three:\n\n1. `compress-agent-sessions estimate --verbose 2\u003e\u00261` (full output)\n2. `sw_vers -productVersion` (your macOS version)\n3. `which applesauce afsctool ditto` (which backends you have)\n\nThe issue template enforces these. Reports without all three will be\nclosed and reopened once they're added.\n\n## Limitations\n\n- **macOS only.** Uses APFS/HFS+ decmpfs, which doesn't exist on Linux or Windows.\n- **Requires applesauce or afsctool for reliable compression.** The `ditto`\n  fallback is best-effort and may silently no-op on APFS.\n- **Compression is lost on any write.** Do not run this on files you expect\n  to modify.\n- **Not for non-JSONL content.** Works fine on any file type, but the\n  compression ratio is tuned to text/JSONL in the estimator sampling.\n\n## Testing\n\n    zsh tests/smoke.zsh\n\nCreates a synthetic fixture in `$TMPDIR`, exercises estimate/compress/\nlist/stats/restore/exclude paths end-to-end, and asserts a 5×+ ratio\non the synthetic payload. No real user data is touched.\n\n## License\n\nMIT — see `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fariccio%2Fcompress-agent-sessions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fariccio%2Fcompress-agent-sessions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fariccio%2Fcompress-agent-sessions/lists"}