# Lupable Disk Doctor

Disk Doctor is a local developer disk tool with coding-agent integrations, powered by [Void](https://github.com/eladbash/void)'s Rust engine. Version **0.6.6** vendors Void **1.3.0**, commit `daebcaa13988235d62f18b90fe80565caebd9687`, under its MIT licence. Upstream copyright and licence are included in `vendor/void/LICENSE` and `vendor/void/NOTICE`.


## What it does

| Need | Plugin command / MCP tool |
| --- | --- |
| Explain growth, capacity and deleted files still held open | `diagnose` / `diagnostics` |
| Find developer disk bloat across all 15 ecosystems | `scan` / `scan`, `explain_item` |
| Inspect agent worktrees, changes, branches and rebuildable outputs | `worktrees`; filtered cleanup plans |
| Find old agent transcripts, logs, editor state and usage by tool | `agents`, `usage` / `usage_by_agent` |
| Inspect local models, orphan blobs and duplicates | `models`; filtered cleanup plans |
| Clean caches, builds, Docker data, stale projects or models | `plan` → approved `apply` / `plan_cleanup` → `apply_plan` |
| Retain recoverability where available | Scanner-provided Move to Trash action; OS Trash recovery |
| Configure roots, exclusions, ecosystems and retention | `settings` / `settings`, `configure` |
| Monitor disk pressure and opt into background cleanup policies | `guard check`, `guard tick` / `disk_status`, `guard_tick` |
| Inspect results, failures, estimates and triggers | `history` / `history` |
| Keep existing scratch expiry and qualified uv housekeeping | `temp`, `run`, `keep`, `release`, `status`, `pause`, `schedule` |

Scanners cover Rust, Node, Apple, Docker, Go, System, Python, Java, Homebrew, JetBrains, .NET, worktrees, agent data, local models and stale projects. They share Void's executor, safety checks, Git revalidation and saved plans. This is a port of the functionality into the agent interface; the GPUI desktop application, tray and desktop-specific gestures are not shipped. [The feature map](docs/VOID_INTEGRATION.md) records each mapping and deliberate changes.

## Install once on the machine

```sh
curl -fsSL https://lupable.com/plugins/disk-doctor/install.sh | sh
```

The installer selects a checksum-pinned native package. Python and the engine are bundled; neither Python nor Rust is required on the user's PATH. It installs one runtime per OS user, starts read-only monitoring and registers detected Codex, Claude Code, Cursor, Gemini CLI, Windsurf and Pi installations. Other agents can use the same CLI or the output of `mcp-config`. Native client trust/approval controls still apply.

Released native packages cover Apple Silicon and Intel Macs, plus Linux x86_64/ARM64. Each passed installation, real scheduled monitoring, MCP calls, approved cleanup, replay rejection, history preservation, pause/reinstall and uninstall. Linux x86_64 requires glibc 2.35 or newer; Linux ARM64 requires 2.35 or newer. See the [current package manifest](https://lupable.com/plugins/disk-doctor/machine-releases.json) for available architectures. Windows native checks are failing, so Windows packages remain unreleased. Unsupported platforms and older libc versions are rejected before installation.

Setup installs MCP registrations and CLI skills for supported detected agents. Detection checks agent directories, configuration files, terminal commands and known Mac application locations. Codex is registered through its shared TOML configuration independently of CLI availability. Cursor configurations may contain comments and trailing commas; values are preserved, a private original-file backup is retained, and the updated file is normalized to JSON.

Known older Disk Doctor helpers are identified by checksum and migrated with a private registration backup. Unknown/custom registrations, disabled integrations and modified skills are preserved. Agent command failures show a useful reason without printing potentially sensitive stderr. Cursor failures include a native installation link that opens its approval flow.

```sh
lupable-disk-doctor connect                  # MCP + CLI skills where supported
lupable-disk-doctor connect codex,cursor --mode cli
lupable-disk-doctor check-connections        # Fresh read-only MCP settings call
```

CLI skills are installed for Codex, Claude Code, Cursor and Pi. Gemini and Windsurf use MCP; other agents can run the ordinary CLI or use `mcp-config`. Skills contain the absolute runtime command, so a GUI agent does not depend on terminal PATH updates. CLI-only setup leaves existing MCP settings alone. `check-connections` distinguishes registration, direct server/tool verification and an agent handshake that has not been observed. It does not bypass an agent's approval controls.

Reopen your terminal for the CLI and restart connected agents if needed. To register an agent installed later, run `lupable-disk-doctor connect`; to print generic stdio configuration, run `lupable-disk-doctor mcp-config`. Agent registration and a verified tool handshake are reported separately. Existing disabled integrations, changed registrations and unrelated settings are preserved.

Installation is per machine: install on a remote VM to inspect that VM's files. Each OS user keeps separate state and permissions. No hosted Lupable server or public port is needed.

## Existing plugin and source installations

Use the download at https://lupable.com/plugins/. Ask your coding agent to unpack and inspect the release, install it as a persistent user plugin, preserve existing configuration, and guide its one-time hook trust review. The package contains Claude Code, Codex and Cursor manifests, a skill, lifecycle hooks and a stdio MCP server. Codex uses an explicit package-relative working directory for its MCP launcher so tools and trusted lifecycle hooks load together. Cursor is contract-tested only.

The Linux x86_64 release bundles its pinned native engine; first tool use copies that verified engine into private local state. The installed-helper alternative is:

```sh
python3 disk-doctor/disk_doctor.py install --upgrade
python3 disk-doctor/disk_doctor.py engine setup
```

A Git checkout contains the engine source, not compiled binaries. Build it once with Rust 1.95+ and Cargo:

```sh
python3 disk-doctor/disk_doctor.py engine setup --build
```

These older plugin/source paths still require Python 3.9+. They do not install the bundled machine runtime. Source supports upstream macOS/Windows paths; qualified automatic scratch/uv housekeeping remains POSIX-only. A separately installed legacy plugin should be removed through its agent's plugin manager if you switch to the machine registration; user-modified plugin caches are not erased by the installer.

For another MCP-capable agent, launch `python3 /absolute/path/disk-doctor/disk_doctor.py mcp` as a local stdio server. Do not expose it as a public network service. The agent runs with your OS permissions; this is not an OS security sandbox.

## Daily use

```sh
lupable-disk-doctor scan --json
lupable-disk-doctor diagnose
lupable-disk-doctor worktrees --json
lupable-disk-doctor plan --ecosystem rust --path "$PWD" --json
# Inspect every entry. Only after approval:
lupable-disk-doctor apply PLAN_ID --yes --json
lupable-disk-doctor history --json
lupable-disk-doctor settings --json
```

Filter plans by ecosystem, kind, path, age, item or byte limit. `--action 'EXACT SCANNER LABEL'` selects an offered action instead of the safest default. Danger requires `--max-risk danger` to plan and `--confirm-path EXACT_PATH` for every Danger entry to apply. The MCP equivalents are `action_label` and `confirm_paths`. The agent must obtain real user approval, including typed paths. Plans expire after an hour, execute precisely the saved entries, and are consumed before execution so a crash cannot replay them. Failed items require a new plan.

Worktree removal retains ignored files, including ignored developer notes. Review them or approve a separate trim of qualified build output, then scan again. Git cleanliness alone does not prove that ignored data is disposable. Removal rechecks this condition when applying a saved plan.

To try it safely, use `dev seed /a/new/disposable/home`, then pass `--home /that/home` to every engine command. Sandbox scans exclude global commands and outside paths; the sandbox has its own settings, plans, history and Trash. Some native-cache commands are deliberately absent there. Never use your actual home as a test fixture.

MCP scans provide a `scan_id` and `next_offset` for reviewing more than 20
candidates without changing their ids. Continue with that same `scan_id` and
`offset`; snapshots expire after 15 minutes. Your existing agent model reviews
the local evidence. Pass `scan_id`, selected `item_ids` and a `review_reason` to
`plan_cleanup`; CLI plans accept `--reason`. The reason is saved in the plan and
history as caller-provided reasoning, alongside the linked plan/run ids. It does
not bypass local checks. Arbitrary task files without scanner evidence stay
unchanged. See the [workflow and limits](docs/RELEASE_0.6.3.md).

## Daily review by your coding agent

Use Disk Doctor normally in your coding agent. On its first interactive use,
the installed skill tells the agent to create or reuse one local daily read-only
review automatically; no separate scheduling request is needed. The default is
09:00 local time, unless you have chosen another time. Existing pauses, opt-outs
and task times are preserved. The agent reports the confirmed schedule.

Each review leaves a saved cleanup proposal for you to approve. It never applies
cleanup by itself. An expired or changed proposal needs a fresh review and
approval. The installer alone cannot create the agent's task: the agent must load
the skill and have a supported local scheduler. If it lacks that capability, it
reports the limitation and supplies the task prompt for manual setup. The OS
monitor remains separate and unchanged. Codex local tasks need the computer awake
and the app running. See the [first-use workflow and limits](docs/RELEASE_0.6.5.md).

## Automatic work and controls

A fresh machine setup starts read-only monitoring without any agent. Scheduled checks use a user systemd timer or cron on Linux, launchd on Mac, and a per-user Windows scheduled task. Windows user tasks require the user to be logged in. Status distinguishes registration, scheduler configuration and an observed scheduled run. Existing pause and cleanup-off choices survive reinstall.

Older trusted plugin hooks can activate the existing qualified native uv 0.12.2 prune and owned-scratch expiry. Histories and other developer artifacts are not automatically removed by that activation. Once-per-minute ticks sample bounded provider growth; the deeper factor inventory and native Guard remain on their 15-minute cadence, and uv pruning is limited to daily. Broader cleanup still requires explicit permission. Hooks cannot take over an existing machine installation.

`diagnose` takes a fresh bounded metadata measurement and checks current-user Linux descriptors for deleted files still held open. It reports file identity, allocated size and holding PIDs without reading file contents, process arguments or environment variables. Measurements are grouped by volume. Host process inspection is skipped for `diagnose --home DIR` fixtures; other operating systems report it as unsupported. This is not a complete system inventory.

Growth needs two complete samples of the same directory and measurement basis, with consistent clocks. Rates require at least five seconds and at most one day between samples. Repeated questions preserve a sampling window instead of resetting it. Missing, partial or replaced roots have an explicit status. The default rapid-growth warning requires both 256 MiB of growth and 64 MiB/minute. Read or adjust those thresholds with `monitor-settings --growth-mib 256 --rate-mib-per-minute 64`; this does not enable deletion. Warnings appear through agent lifecycle hooks with a 15-minute cooldown and in fresh diagnostics. There is no desktop push notification, writer quota or automatic process termination.

Void's broader Guard auto-clean flag and individual policies are **off by default**. Read `settings`, show a proposed change, and explicitly approve it before sending JSON to `settings --set --confirm` or MCP `configure`. Guard cleans only Safe policy selections when disk space is low, checks CPU pressure, and limits retries to hourly. It never runs uv cleanup beside the existing qualified uv owner. `pause`, `disable-cleanup` and earlier uv revocations carry forward. An already-running action may finish.

```sh
lupable-disk-doctor pause
lupable-disk-doctor schedule
lupable-disk-doctor disable-cleanup
lupable-disk-doctor deny-cache-prune uv
lupable-disk-doctor uninstall
```

Pause before disabling a plugin: the OS cron job outlives an agent session. Uninstall preserves local settings, scratch and receipts. Modified installations and unrelated crontab entries are preserved.

Linux state lives in `~/.local/state/lupable-disk-doctor/`, new Mac state in `~/Library/Application Support/Lupable/DiskDoctor/`, and new Windows state under `%LOCALAPPDATA%/Lupable/DiskDoctor/`. Existing state locations are retained during upgrades. Engine settings/history are under `engine/`, separate from Void. Plans use the separate `lupable-disk-doctor` cache namespace. No telemetry is added. Inventory primarily reads metadata, filenames, Git state and supported editor metadata; the scanner may inspect manifests/state to identify artifacts. Your coding agent can receive tool results under its own permissions.

Trash moves are recoverable where the OS supports them, but free zero bytes until emptied. File deletion counters are logical bytes, not guaranteed physical free-space gains; command savings may be estimates. Native pruning can require later downloads. Disk Doctor releases own engine updates; upstream self-update is blocked so it cannot overwrite the fork.

## Development

```sh
python3 -m unittest discover -s tests -v
cargo test --locked --manifest-path vendor/void/Cargo.toml --workspace
cargo build --locked --release --manifest-path vendor/void/Cargo.toml --bin void
python3 build_release.py --engine /path/to/verified/release/void --output /path/to/staging
python3 tests/verify_native_mcp.py /path/to/unpacked/lupable-plugins
# Build dependencies are needed only on release builders:
python3 -m pip install pyinstaller==6.22.3
python3 build_machine.py --engine /path/to/native/void --output /path/to/staging
python3 tests/verify_machine.py /path/to/staging/disk-doctor/0.6.2/machine/PLATFORM.tar.gz --native-scheduler
python3 build_machine.py --output /path/to/staging
```

The legacy release builder produces an allowlisted source/plugin ZIP. The machine builder bundles the native engine and Python; installer generation refuses packages without native lifecycle and scheduler verification. Run native acceptance on a disposable OS account/runner because it installs and removes a real user job. Current evidence and exact upstream/local differences are in `docs/VOID_INTEGRATION.md`.
