Skip to content

carwash 0.4: polyglot rewrite - #5

Merged
nicholasjpaterno merged 22 commits into
mainfrom
rewrite
Sep 25, 2026
Merged

nicholasjpaterno merged 22 commits into
mainfrom
rewrite

Conversation

@nicholasjpaterno

Copy link
Copy Markdown
Contributor

Replace the Rust-only 0.3 app with a workspace: carwash-core (engine, no UI) and carwash (CLI and TUI).

Find build outputs, dependency installs, environments and caches across 40 ecosystems
Size by allocated blocks, counting hard links once
Protect git-tracked content and hold back generic or recently used directories
Add scan, clean, tasks, run, outdated, caches, ecosystems, history and completions
Add Reclaim, Tasks, Updates and Caches tabs to the TUI
Ignore 0.3 config files with a warning

This is the first CI run on Linux, macOS and Windows. Windows hasn't been built locally.

Details in CHANGELOG.md.

…che, path-keyed projects, Gestalt default theme
The rewrite replaces the single-crate app with a workspace: a UI-agnostic
engine (carwash-core) and the carwash binary. Everything removed here is
recoverable from the previous commit.
- Declarative ecosystem rules for 43 ecosystems (builtin.toml), user
  overridable, compiled into lookup indexes
- Parallel discovery that classifies directories by entry names, never
  descends into artifacts, understands workspaces (Cargo, npm/pnpm, uv,
  go.work, Dart, Gradle, .NET) and the projects enclosing the scan root
- Content detection: CACHEDIR.TAG, pyvenv.cfg, conda-meta, CMakeCache.txt,
  Meson build dirs, Cargo fingerprints, interrupted-clean leftovers
- Allocated, hard-link-aware sizes with a separate reclaimable figure
- Batched git inspection: tracked content is protected, generic names need
  git or content confirmation
- Validated deletion (rename-then-remove, or trash), size cache, history
scan prints a table (or --json) sorted by reclaimable bytes, with safety
status and notes; clean shows the plan, holds back recently used and
review-needing directories by default, confirms, deletes and records the
reclaimed space. XDG config at ~/.config/carwash/config.toml.
Elm-style app (pure update, effects executed by a small runtime) over a
single normalized store. Tree, projects and artifacts groupings with
aggregated sizes and compressed directory chains; fuzzy + facet filter
(eco:, kind:, size>, age>, is:); marking that follows the safety policy;
review, live progress and summary for cleaning; details panel; help
generated from the keymap; themes (Catppuccin-based default, ansi
fallback without truecolor); mouse support; instant start from the size
cache; redraws only on change.
Tasks come from package.json scripts (run with the project's package
manager), deno tasks, justfiles, Makefiles, Taskfiles, mise, poe/pdm,
composer scripts and cargo aliases, plus standard commands declared per
ecosystem in the rules (tasks = [...], with when/unless conditions).
`carwash run <task>` runs it in every project that has it, sequentially
with the terminal inherited or in parallel with prefixed output.
Projects on the left (mark several to fan out), their tasks below, and
job output on the right, rendered from a pseudo-terminal through vt100
so colors and progress bars look like a normal shell. Jobs can be
switched, stopped and cleared; quitting with running jobs asks twice.
Keymap split into global, reclaim and tasks tables.
carwash-core::deps reads declared dependencies from manifests and current
versions from lockfiles/installs, then asks each registry directly
(crates.io sparse index, npm abbreviated metadata, PyPI JSON, Go module
proxy) for wanted/latest versions, with OSV vulnerability lookups.
Lookups are deduplicated across projects, parallel, and cached.
Updates are applied through each ecosystem's tool; major Cargo upgrades
raise requirements with toml_edit, preserving formatting.
New command: carwash outdated [--json] [--exit-code].
Applied from carwash's own Updates tab.
Projects with status badges (outdated count by worst bump, vulnerable
count), dependencies sorted vulnerable-first with current/wanted/latest,
marking, `u` to update within requirements and `U` (twice) to raise
them to latest. Updates run as jobs in the Tasks tab and the project is
checked again when they finish. Shared pane/spinner helpers move to
widgets.rs.
Built-in specs for 32 per-user caches (package stores, toolchains, IDE
and SDK caches) with per-platform paths, user overrides in caches.toml,
and per-child expansion that keeps the default rustup toolchain.

`carwash caches` lists and measures them; `carwash caches clean` runs
the tool's own prune command when installed, or deletes when safe.
The TUI gains a Caches tab (4) with the same actions; prune commands
run as jobs in the Tasks tab and re-measure when they finish.
…-0204)

The rewrite no longer uses tokio, futures, reqwest, process-wrap, shlex,
humantime, jiff, cargo-lock, insta or a direct crossterm dependency;
carwash-core never used crossbeam-channel or tracing.
Scrolling on Tasks, Updates or Caches moved the hidden Reclaim cursor.
Other tabs now receive Up/Down actions; clicks stay Reclaim-only.
0.3 stored its config at the same path on Linux, so upgrading made
every command fail on unknown fields. Such files now produce a warning
and defaults. Also: the home directory always comes from paths::home(),
the caches override file from Dirs::caches_file(), and config comments
list the real theme and icon choices.
justfile recipes now target the workspace (the old ones ran
`cargo test --lib` at the virtual root, which fails).
Caches: discovery runs at startup (it only checks known paths), and
sizes come from the size cache, so the tab and its total appear
instantly. Only sizes older than a day are measured when the tab is
shown; r measures everything. `carwash caches` stores its measurements
there too. The cursor stays on the largest cache until the user moves.

Footer: hints are derived from the keymap instead of a parallel list.
This tab's actions are on the left, the keys that work in any tab on the
right under an "any tab" label. Hovering a hint or tab shows what it
does (for d, exactly what will be deleted or run); clicking runs it.
Help shows the tab's purpose, separates "Any tab" keys, sizes itself to
its content and switches to balanced columns on short terminals.
Folder: p opens a path prompt in the footer with directory completion
(Tab, case-insensitive, ~ and relative paths). Enter validates the path,
rescans there and resets what belonged to the old scan; jobs keep
running. Scans are numbered so events of a superseded scan are dropped
instead of landing in the new store.

Cache sizes: remembered sizes are saved as soon as measuring finishes
(and after each scan), not only on a clean exit, so closing the
terminal no longer loses them. Each size carries a fingerprint of the
cache's top two levels (newest mtime, entry count), taken just before
measuring: a changed fingerprint means measure now, an unchanged one
trusts the size for a week, no fingerprint falls back to a day. The size
cache is now the only record of when a size was measured.

Fix: a message that changed nothing cleared the redraw flag set by an
earlier message of the same batch, delaying the redraw until the next
idle tick (up to a second).
Date the changelog and cover the last additions, ship LICENSE in both
packages, and give carwash-core a README for its crates.io page.
carwash prints native paths (app\target on Windows); the tests
hardcoded forward slashes.
@nicholasjpaterno
nicholasjpaterno merged commit bf3394a into main Sep 25, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant