Void cleans up after your AI agents — and your agents can call Void themselves.
Void finds and cleans developer disk bloat across 15 ecosystems: agent worktrees, agent transcripts, local AI models and the build artifacts behind them. One scan, gigabytes back. Everything runs locally.
Download · Website · Contributing · Changelog
Every project you touch leaves something behind: a target/ here, a node_modules/ there,
a Docker build cache quietly eating 20 GB. AI coding agents multiply that. Each parallel
session gets its own git worktree with its own dependencies and build output, every
conversation is saved as a transcript, and every model you tried is still sitting in
~/.ollama or the Hugging Face cache. You know it's there. You just don't know where,
or which parts are safe to remove.
Void answers both questions. It walks your home directory in parallel, groups what it finds by ecosystem, tells you how stale each item is, and labels every cleanup action with a risk level before you click it. Nothing is deleted without your say-so. And because your agents are the ones filling the disk, they can ask Void for a plan themselves, from the command line or over MCP.
- 15 ecosystem scanners: agent worktrees, AI agent data, local AI models, stale projects, Rust, Node.js, Python, Go, Java, Docker, Apple/Xcode, Homebrew, JetBrains, .NET and system caches
- Built for the AI era: worktrees from Claude Code, Cursor, Codex and Conductor, agent transcripts and editor state, Ollama and Hugging Face models, duplicate model files
- Agents can call Void: a
voidCLI with JSON output and dry-run plans, an MCP server, and Claude Code hooks - Guard mode: watches free space in the background and warns before the disk fills up; optional auto-clean policies that only ever run Safe actions
- Safety first: blocked-path lists, sentinel-file detection, Safe / Caution / Danger on every action, Move to Trash for anything worth recovering
- Fast: multi-threaded filesystem walker with concurrent analysis, built on Tokio and the
ignorecrate - Nothing runs unseen: every item shows the exact command or deletion it will perform
- Keeps a record: each clean is stored locally with the paths, commands and bytes recovered
- Local only: no account, no telemetry. Void never uploads anything. Its one network request is a once-a-day check of GitHub Releases for a newer version, which you can turn off in Settings → About (details)
curl -fsSL https://raw.githubusercontent.com/eladbash/void/main/install.sh | shDownloads the latest .dmg for your architecture, installs to /Applications, and launches it.
Grab the installer for your platform from the Releases page:
a .deb or .AppImage for Linux, an .msi or setup .exe for Windows.
Every release also lists each file's SHA-256 in SHA256SUMS (check a download with
shasum -a 256 -c SHA256SUMS --ignore-missing), and in manifest.json, which is signed with
Void's release key. The app checks that signature before it installs an update.
The desktop app is native on all three: a GPU-rendered GPUI window (Metal on macOS, DirectX on Windows, Vulkan on Linux), not a webview. On Linux the tray icon uses the StatusNotifierItem protocol, which GNOME shows with the AppIndicator extension and KDE shows natively.
The CLI (and the MCP server inside it) comes with the desktop app: it ships inside Void.app,
next to Void.exe on Windows, and in /usr/bin with the .deb. Click Install void command on
the Agents screen to put it on your PATH. On macOS that links it into /usr/local/bin (macOS asks
for your password if the folder isn't writable) or ~/.local/bin; an AppImage copies it to
~/.local/bin; Windows adds the install folder to your PATH. The link follows the app through
updates, and install.sh sets it up for you. Install hooks and MCP work right away, using
the bundled copy.
Without the app, each release also attaches the CLI on its own for every platform
(void-<version>-<target>); put it on your PATH as void. Or build it from source with
Rust 1.95+ — the CLI needs no system libraries.
git clone https://github.com/eladbash/void.git
cd void
cargo install --path crates/void-cli # builds and installs `void` into ~/.cargo/bin
void --version~/.cargo/bin must be on your PATH (rustup adds it; if void is not found, add
export PATH="$HOME/.cargo/bin:$PATH" to your shell profile). The desktop app prefers its bundled
copy and falls back to the void on your PATH.
Then connect it to your agents:
void scan # see what's reclaimable (changes nothing)
claude mcp add void -- void mcp # let Claude Code call Void as an MCP server
void mcp-config # JSON snippet for other MCP clients (Cursor, Codex…)
void hook install # optional: low-disk warning + worktree trim hooksTo update, run void self-update. A release binary replaces itself after checking the release's
signature and checksum; a cargo-installed void prints the cargo install --force command to run
instead. To remove: void hook uninstall (if you installed hooks), then
cargo uninstall void-cli.
Requires Rust 1.95+. On Linux, install the windowing and font libraries
first with ./scripts/linux-deps.sh (Debian/Ubuntu).
cargo run -p deepclean-app # run in development
cargo build --release -p deepclean-app # release binary: target/release/void-app
cargo install cargo-packager --locked # once
(cd crates/deepclean-app && cargo packager --release) # .app/.dmg, .deb/.AppImage or .msi- Scan: Void walks your configured roots (your home directory by default) with a parallel walker, using half your cores and up to 8 concurrent analyses, and checks the well-known global locations (caches, agent data, model stores) directly.
- Review: results are grouped by ecosystem with size, last-modified date, a risk level and the facts you need to decide: a worktree's branch and unpushed commits, a model's tag, which agent produced it.
- Clean: each item carries its own actions (
cargo clean,git worktree remove,docker builder prune, Move to Trash, delete), lowest risk first. Void re-checks the safety gates, runs it, and reports what it freed.
| Ecosystem | Artifacts |
|---|---|
| Agent worktrees | Git worktrees from Claude Code (<repo>/.claude/worktrees), Cursor (~/.cursor/worktrees), Codex (~/.codex/worktrees), Conductor (~/conductor/workspaces) and custom roots; orphaned worktrees; stale worktree records; merged agent branches |
| AI agent data | Claude Code transcripts, file history, debug logs and caches; Codex sessions; Cursor / VS Code / Windsurf state databases and orphaned workspace storage |
| Local AI models | Ollama models and orphaned blobs, Hugging Face cache (per repo, detached revisions, incomplete downloads), LM Studio, torch hub, ComfyUI; duplicate model files across stores |
| Stale projects | Git projects with no commit and no edit in 90 days |
| Rust | target/ dirs, cargo registry, git checkouts |
| Node.js | node_modules/, npm / yarn / pnpm / Bun caches, Next.js / Turbo / Parcel / SvelteKit / Nuxt caches, Playwright and Puppeteer browsers |
| Python | __pycache__/, virtualenvs, pip, uv and conda (Miniconda / Anaconda / Miniforge) caches, pytest / ruff / mypy / tox caches |
| Go | Build cache, module cache, test cache |
| Java | Gradle caches and build dirs, Maven .m2/repository and target/ dirs |
| Docker | Dangling images, build cache (docker builder prune), stopped containers, unused volumes; Docker Desktop / OrbStack / Colima VM disk size (informational) |
| Apple/Xcode | DerivedData, archives, device support, simulator caches and runtimes |
| Homebrew | Package download cache |
| JetBrains | Per-IDE caches (rebuilt on next launch) |
| .NET | NuGet cache, bin/ and obj/ dirs |
| System | Trash (macOS and Linux), application logs, stale downloads |
Agents that work in parallel give every task its own git worktree, and each one carries a full
copy of node_modules/ or target/. Void finds them all and shows, for each: the agent that made
it, the branch, uncommitted changes, unpushed commits, whether the branch is merged, and whether
the worktree is locked.
- Trim build artifacts (keep worktree): the default action. Removes the rebuildable output inside an idle worktree and leaves your code and branch alone.
- Remove worktree:
git worktree remove, offered only for clean worktrees. Void checks again that it is clean at the moment it runs, and never passes--force. - Orphaned worktrees: directories whose repository no longer knows about them.
- Prune:
git worktree prunefor records that point at deleted directories. - Merged agent branches: deleted with
git branch -d, never-D, so git itself refuses anything that isn't merged.
Claude Code keeps every conversation in ~/.claude/projects, plus file-history snapshots,
debug logs and caches. Codex keeps sessions and archived sessions. Void lists what's older than
your retention window (30 days by default) and flags oversized session files.
AI editors (Cursor, VS Code, Windsurf) keep chat history in a state.vscdb SQLite database
that grows without bound. Void offers to VACUUM it, never to delete it, because deleting it
loses your chat history. Workspace storage for folders that no longer exist is offered as orphaned.
Void never touches agent settings, credentials, memory, CLAUDE.md, skills, agents, commands,
plugins or your prompt history.
- Ollama: per model, with the space each one would actually free (layers shared between models are counted once), plus orphaned blobs no model references.
- Hugging Face: per repository, with detached revisions and incomplete downloads listed separately.
- LM Studio, torch hub, ComfyUI: per store.
- Duplicate models: the same weights downloaded into two stores. Void replaces the copies with APFS copy-on-write clones (hardlinks elsewhere), so the space comes back and every path still works. Nothing is deleted, and file contents are re-hashed right before replacement.
The Agents screen adds it all up per tool, for example Claude Code: 38 GB — worktrees 30, transcripts 6, browsers 2, so you know which agent is costing you the most.
Git projects with no commit and no edit in 90 days, with their remote, unpushed commits and dirty state shown up front. Strip the build artifacts and keep the code, or move the whole project to the Trash.
Your agents already know when they're about to run out of disk. With the CLI, the MCP server and Claude Code hooks, they can find out how bad it is and ask for a cleanup plan themselves.
void scan # everything reclaimable, grouped by ecosystem
void scan --json # the same, as JSON for scripts and agents
void worktrees # agent worktrees and their state
void models # local AI models and duplicates
void agents # AI agent data
void usage # disk usage by agent
void plan # dry-run cleanup plan, expires after one hour
void apply <plan-id> # carry out a plan you have reviewed
void guard check # one free-space check
void version --check # is a newer void out?
void self-update # install it, after verifying its signature and checksumA plan is always a dry run first. void apply executes exactly the plan it's given, and a
plan older than an hour is refused, so nobody acts on a stale view of the disk.
claude mcp add void -- void mcpFor other MCP clients, void mcp-config prints a config snippet to paste. The server exposes
these tools:
| Tool | What it does |
|---|---|
disk_status |
Free and used space on the volume |
scan |
Everything reclaimable, grouped by ecosystem |
explain_item |
What an item is, why it's there, what each action would do |
plan_cleanup |
Build a dry-run plan |
apply_plan |
Run a plan. Requires explicit confirmation |
usage_by_agent |
Disk usage per AI tool |
Danger actions are never available over MCP. An agent can plan and, with confirmation, apply Safe and Caution cleanups; anything permanent stays with you.
void hook install # add Void's hooks to ~/.claude/settings.json
void hook uninstall # remove them againThis adds two hooks: a SessionStart warning when free space is low, and a
WorktreeRemove hook that trims build artifacts when Claude Code removes a worktree.
Void backs up settings.json before editing it, and running install twice changes nothing.
Void can watch free space in the background (every 15 minutes by default) and notify you at 15% free (warning) and 5% (critical). The menu bar shows the current state, and Void can launch at login.
Auto-clean is off by default. When you turn it on, only the policies you enable run, and they only ever run Safe actions:
- trim build artifacts in agent worktrees idle for 3+ days
- clear agent debug logs and caches older than 30 days
- remove build folders (
node_modules/,target/, …) untouched for 30+ days
Deleting files is easy to get wrong, so Void is deliberately conservative:
- Never-touch paths:
~/Documents,~/Desktop,~/Pictures,~/Library/Keychainsand~/Library/Preferences, plus anything named.ssh,.gnupg,.aws,.config, or.envanywhere in the path.~/Downloadsis protected as a folder, though individual files inside it can be cleaned — that is what the System scanner is for. - Home and root are off limits: your home directory,
/, and any folder that contains your home can never be deleted, whatever the configuration says. - Agent config is protected:
~/.claude.json,~/.claude/settings.json, memory, skills, agents, commands, plugins andhistory.jsonl, and Codex'sauth.json,config.tomland memories are never touched. - Commands are checked too: an action that shells out to
rm,osascriptor PowerShell has its arguments scanned against the same protected paths, and discovered filenames are escaped before they are ever embedded in a script. - Sentinel detection: a directory containing
.env,credentials,secrets.y(a)ml,id_rsa,id_ed25519,.claude.json,auth.json,CLAUDE.mdorAGENTS.mdis never deleted wholesale. - Git work is re-checked when it runs: a worktree is removed only if it is still clean at
execution time,
--forceis never used, and branches are deleted with-d, never-D. - Move to Trash: items worth recovering (projects, transcripts, worktrees) offer Move to Trash next to permanent deletion.
- Honest sizes: hardlinked files are counted once and sparse files by what they really use, so the space Void promises is the space you get.
- Risk escalation: paths directly under
$HOMEand symlinks are automatically promoted to a higher risk level. - Risk follows the action: an artifact can offer several cleanups at different risk levels;
Void shows the risk of the one that will actually run, and asks you to type
deletebefore anything permanent. - Your own blocklist: add any path in settings and Void will refuse to touch it.
- Nothing is automatic unless you ask: Void never deletes anything you haven't selected. Guard auto-clean is opt-in and limited to Safe actions; MCP apply needs explicit confirmation and never includes Danger actions.
Found a safety gap? Please report it privately — see SECURITY.md.
Once a day, the desktop app asks GitHub's public Releases API
(api.github.com/repos/eladbash/void/releases) whether a newer version exists. This is the only
network request Void makes. It sends nothing but an ordinary HTTPS request with a Void/<version>
user agent. Turn it off with Check for updates automatically in Settings → About; with it
off, Void makes no request unless you click Check for updates. A failed check at launch (you're
offline, or GitHub is rate-limiting) stays quiet and is tried again on the next launch.
Update now downloads the new version and installs it without leaving the app. Before
installing anything, Void checks the release manifest's Ed25519 signature against the key built
into it, then the download's size and SHA-256 against the manifest. A download that fails either
check is deleted. On macOS the new Void.app is unpacked next to the old one and swapped in by
rename, and the old one is put back if the swap fails. Windows runs the installer silently, and an
AppImage replaces itself. Void then restarts into the new version. For a .deb, Void downloads and
verifies the package, then shows the sudo apt install command rather than asking for root itself.
For development, VOID_UPDATE_FEED=<file> points the check at a local releases JSON. A sandboxed
run (VOID_HOME) never touches the network: it checks a local feed or nothing. In a sandbox,
VOID_UPDATE_KEY and VOID_UPDATE_TARGET swap in a test signing key and a stand-in app to
update, and void dev release <dir> writes a matching fake release.
Settings and clean history are plain JSON, written atomically next to the bundle identifier:
| Platform | Location |
|---|---|
| macOS | ~/Library/Application Support/com.void.app/ |
| Linux | ~/.config/com.void.app/ |
| Windows | %APPDATA%\com.void.app\ |
Beyond scan roots, ecosystems and thresholds, settings cover the AI features (worktree idle days, agent data retention, stale project age, extra worktree roots, duplicate model detection) and Guard mode (interval, warning levels, auto-clean policies).
The last scan is kept beside them in scan-cache.json, so Void opens to it and refreshes it in the
background. It only decides what's shown at launch: every clean re-checks its safety gates when
it runs, and a cache from another version or for other scan folders is ignored.
Both files are safe to edit or delete by hand — a missing or unparseable file falls back to defaults rather than blocking launch.
cargo test --workspace # everything, including the window's headless tests
cargo clippy --workspace --all-targets -- -D warningsTests never touch your real home directory or Trash: they build a fake home in a temp dir. The
desktop app's UI logic lives in crates/deepclean-app/src/model/ and is tested without a window;
src/ui/tests.rs drives the real window on GPUI's headless test platform — shortcuts, selection,
the clean confirmation and a full scan → clean → History round trip.
To try everything by hand, safely, build a realistic fake home and point the CLI at it:
cargo run -p void-cli -- dev seed /tmp/void-home # worktrees in every state, fake ~/.claude,
# Ollama and Hugging Face stores, stale projects
cargo run -p void-cli -- --home /tmp/void-home scan
VOID_HOME=/tmp/void-home cargo run -p deepclean-app # the real app, sandboxedVOID_HOME runs the desktop app against the fake home: scans, settings, history and the
Trash all stay inside it, the window title says SANDBOX, and any action that could reach the
real machine (Docker prunes, ollama rm, system caches) is dropped.
On macOS, scripts/drive.py launches the real app in a fresh sandbox, drives it like a user and
saves a screenshot of its window at each step; scripts/compare.py puts two such runs side by
side. It needs the app built with the drive feature, a debug-only driver that takes keys and
clicks over a socket and feeds them straight into GPUI, so nothing goes through the OS:
cargo build -p void-cli -p deepclean-app --features deepclean-app/drive
python3 scripts/drive.py target/debug/void-app /tmp/shots screens matrix persistence
python3 scripts/drive.py target/debug/void-app /tmp/shots updates update-skip update-tampered cli relaunch
scripts/compare.py /tmp/shots-before /tmp/shots /tmp/compareThe update scenarios run against a fake signed release (void dev release) and update a stand-in
app inside the sandbox; nothing touches the network or your installed Void.
The driven window opens behind your other windows and never takes focus. Your keyboard, mouse and
clipboard are left alone (clipboard writes, notifications and Finder reveals are captured for the
script to check instead), so you can keep working while it runs, and several runs can go at once.
Each step checks that Void never became the frontmost app; DRIVE_STRICT=1 also fails the run if
the frontmost app or the mouse moved at all, for runs nobody touches the machine during. The
driver only starts with both VOID_HOME and VOID_DRIVE set, and release builds don't contain it.
scripts/linux-smoke.Dockerfile builds and tests on Linux and screenshots the app under Xvfb.
crates/
deepclean-core/ scanning engine, safety checker, action executor, cleanup plans, guard, hooks
deepclean-app/ native desktop app (GPUI): window, tray, notifications, login item
void-cli/ the `void` command line tool and MCP server
docs/ project website (GitHub Pages)
design/ design system, screen specifications and plans
scripts/ macOS UI driver, screenshot comparison, Linux smoke test and deps
Contributions are genuinely welcome — a new ecosystem scanner is a great first PR. Start with CONTRIBUTING.md and our Code of Conduct.
MIT — see LICENSE.
Built by @eladbash
If Void bought you back some disk space, consider sponsoring the project ⭐