🧹 Vacuum up cruft from your AI coding-agent sessions. A small, standalone Python CLI that cleans, prunes, analyzes, archives, and repairs local session logs for Kiro CLI and Claude Code.
Long agent sessions rot over time — embedded screenshots, giant tool outputs, and ever-growing history. Because these agents replay the whole conversation every turn, that bloat causes real failures:
- Oversized images (>2000px) wedge a session:
image dimensions exceed max allowed size for many-image requests: 2000 pixels - Huge embedded payloads crash the load:
Agent connection closed/the selected model cannot continue this conversation - Runaway context triggers premature, quality-killing auto-compaction
- Hundreds of stale sessions quietly eat disk
vac fixes wedged sessions and keeps them lean:
clean— strip embedded images (both Kiro forms + Claude), fixing the 2000px / payload-size crashesprune— free a chosen % of context tokens from the oldest turns (the "compact the first N%" Kiro's/compactand/rewindcan't do)analyze/doctor— see what's eating a session and triage the ones about to breaklist/archive— inventory by age and archive old sessions (reversible)
Everything backs up before writing, refuses to touch live sessions, and JSON-validates the result (and offers --dry-run to preview) — so it never corrupts a session.
Pick whichever you have — the installed command is always vac.
pip (universal — works anywhere Python + pip exist):
pip install vac-clipipx / uv (isolated global tool):
pipx install vac-cli
uv tool install vac-cliHomebrew (macOS/Linux):
brew tap homeo26/vac
brew install vac # short form after tapping
# or one-shot without tapping first:
brew install homeo26/vac/vacFrom source, no pipx/uv needed (one-liner):
curl -fsSL https://raw.githubusercontent.com/homeo26/vac/main/install.sh | bashThis creates an isolated venv under ~/.vac and links vac into ~/.local/bin
(uses uv automatically if present). Make sure ~/.local/bin is on your PATH.
From a git checkout (for development):
git clone https://github.com/homeo26/vac.git && cd vac
pip install -e ".[test]" # or: uv tool install .Requires Python 3.9+.
| Command | Options | What it does |
|---|---|---|
vac list |
--older-than <dur> · --tool kiro|claude · --sort size|images|updated|age · --json |
Inventory sessions: size, images, age, live?, at-risk? |
vac analyze <id> |
— | Break down one session: size, image count, largest entry, active? |
vac clean <id> |
--keep N · --dry-run · --force · --no-backup |
Strip embedded images (fixes the 2000px / 100-image / payload crashes). Keeps the newest N (default 3); cleared file-read images keep a re-readable path |
vac prune <id> |
--oldest N · --mode outputs|hard · --max-field <n> · --dry-run · --force · --no-backup |
Free ~N% of context tokens from the oldest turns (hard guarantees the target; outputs keeps text) |
vac doctor |
--json |
Flag sessions likely wedged: many images, context-bomb entry, or oversized session |
vac name [<id>] |
--include-generic · --llm-cmd "claude -p" · --tool · --limit N · --dry-run |
AI-name untitled sessions from their content (ChatGPT/Claude-style). Uses a local LLM CLI — no API key. Kiro only (writable title store) |
vac archive |
--older-than <dur> · --tool · --include-active · --dry-run |
Archive (tar.gz) + remove sessions older than a threshold — reversible |
<id> = a session id or a path to a .jsonl. <dur> = 60d 2w 12h 30m. Commands that write (clean, prune, name, archive) apply by default — add --dry-run (-n) to preview. They create a .bak, refuse to edit active/locked sessions (--force overrides), and JSON-validate before writing. Works on both Kiro CLI and Claude Code.
vac doctor # triage everything
vac clean <id> --keep 1 # drop old images (add --dry-run to preview)
vac prune <id> --oldest 20 --mode hard # free ~20% of context tokens
vac archive --older-than 60d # reclaim disk (reversible)Tokens vs. bytes — which command to use. Kiro's context % counts tokens, not file size. An embedded image is megabytes on disk but only ~1–2K tokens.
- Fixing a file-size problem (2000px image error, "connection closed", disk)?
→
vac clean(removes image bytes). - Lowering the context % / delaying auto-compaction? →
vac prune(removes text tokens).--mode hardguarantees the target;--mode outputsis non-lossy for the dialogue but frees less.
Age is real last-used time. --older-than and the age column use each session's
updated_at metadata, not the file mtime — so sessions that vac itself rewrote
aren't misflagged as recently used. Durations: 60d, 2w, 12h, 30m.
Archiving is reversible. vac archive tar.gz's each session (log + metadata +
history) to ~/.kiro/sessions/vac-archive-<timestamp>.tar.gz; restore with
tar -xzf <archive> -C <dir>.
Images are "lazy", not lost. After the first read, an image's content is
already captured in the model's text reply, so keeping it re-sent every turn
mostly just burns tokens and hits the image caps. vac clean strips them
aggressively (keeps the newest 3 by default) and, for images read from a file,
leaves a placeholder with the source path (re-read /tmp/shot.png …) so the
model can pull the image back on demand if it ever needs the pixels again.
- Preview with
--dry-run— commands apply by default;-n/--dry-runshows what would change without writing. - Automatic backup — writes a
.bakbeside the log (disable with--no-backup). - Won't touch live sessions — refuses to edit a locked/recently-active session unless
--force. - Keeps source paths — cleared images become a text placeholder, and file-based images can simply be re-read.
- Local only — never makes network calls.
| Tool | Store | Image forms handled |
|---|---|---|
| Kiro CLI | ~/.kiro/sessions/cli/*.jsonl |
inline {"kind":"image",...} and tool-result {"Image":{"source":{...}}} (base64 or raw-bytes array) |
| Claude Code | ~/.claude/projects/**/*.jsonl |
{"type":"image","source":{"type":"base64",...}} |
Adapters are pluggable — more tools can be added.
vac doctor flags sessions likely to be wedged:
- Many-image risk — more than ~20 images (Anthropic's stricter 2000px cap).
- Context-bomb entry — any single log entry over ~1 MB (a runaway tool output or embedded image re-sent every turn).
- Oversized session — total size likely to exceed the model's context window.
Each finding prints the exact vac clean … command to fix it.
git clone https://github.com/homeo26/vac.git && cd vac
pip install -e ".[test]"
pytest -q # run the test suiteCI runs the tests on every push/PR (Python 3.9 and 3.12). Releases publish to
PyPI automatically via OIDC Trusted Publishing when a v* tag is pushed — no
tokens stored (see .github/workflows/publish.yml).
MIT