Skip to main content

Rules and confidence

Cleanr does not decide that a path is removable from its name alone. It matches scanned entries against versioned rule packs that explain what the item is, why it can be removed, and what rebuilding it may cost.

What you see for each candidate​

Each rule match includes:

FieldMeaning
LabelHuman-readable name, such as “Rust target directory”
CategoryGroup such as build-cache, package-cache, or downloads
ConfidenceHigh, Medium, or Low
ReasonWhy the path is considered a cleanup candidate
Risk noteWhat may break, slow down, or require a download afterward
Default selectionWhether the rule asks to preselect the item
Match roleprimary for a specific rule, or fallback for broad evidence
PlatformsOptional macos, windows, and/or linux restriction
SourcesRevision-pinned projects used as adapted or audit-only evidence
Runtime guardOptional owning process names and the observed idle, active, or unknown state

When multiple rules match one entry, Cleanr retains every match as evidence. Rules with equivalent safety semantics resolve deterministically. A trusted specific primary rule may shadow a broad fallback rule for the selection decision, while the fallback remains visible in the report and plan. An untrusted rule cannot shadow a built-in fallback. Other semantic disagreements remain an unresolved conflict and require review instead of being ranked away. The final plan removes overlapping parent and child candidates so space is not counted twice.

Confidence is not a guarantee​

LevelHow to treat it
HighUsually generated or downloadable data; still review unfamiliar paths
MediumOften rebuildable, but may be expensive or contain local-only state
LowMay be user data and always needs careful manual review

Only a High confidence rule with default_selected = true from a built-in or trusted source can preselect an item.

Bulk selection changes only Preselected and Available items. Review items, including unresolved rule conflicts, must be selected individually. Candidates protected by a runtime guard are Excluded while an owning process is active or its state cannot be verified. Cleanr captures one process snapshot for analysis, records that evidence in the plan, then checks again before the run and immediately before each guarded item is moved to trash. It never stops an application on the user's behalf.

Built-in rule packs​

builtin-dev​

The built-in plugin manifest cleanr.builtin.dev provides the builtin-dev rule pack. In addition to known package-manager and tool caches, the pack uses project-aware rules for generated project artifacts. These rules first identify a project root from marker files, optionally constrained by its direct child directories, then match only declared, exact paths relative to that root. A directory name alone is not enough to identify one of these project artifacts.

Project-aware coverage includes:

  • Cargo, Node.js, Nuxt, SvelteKit, Astro, Parcel, React Native, Unity, Haskell, SBT, Maven, Gradle, Android native builds, CMake, and Unreal Engine;
  • Jupyter, Python, Pixi, Composer, Pub, Flutter, Elixir, Swift, Zig, Godot, and .NET;
  • Turborepo, Terraform, and CocoaPods.

The pack also retains rules for caches such as Cargo registries and Git dependencies, npm, pnpm, Yarn, pip, Go modules, Corepack, language-version manager downloads, rustup downloads, Xcode DerivedData, and Next.js and Python tool caches. Generated coverage, deployment output, managed hook environments, and other potentially retained artifacts stay review-only. On macOS it also discovers Homebrew, CocoaPods, SwiftPM, Go build, Deno, Cypress, Composer, Bun, Pub, CoreSimulator, and other named Xcode caches. DeviceSupport and XCTest devices require review; Xcode archives are low-confidence because retained builds and dSYMs may be irreplaceable.

Since v0.17.0, uv is inspection-only and cannot enter cleanup plans; see cache coverage and retention.

Python .venv directories are intentionally not covered: they may contain local environments that are costly or impossible to reproduce exactly. Other higher-risk or potentially locally stateful directories are review-only and are never preselected; read their reason and risk note before including them in a cleanup plan.

builtin-general​

Finds broader candidates that should be reviewed manually:

  • files of at least 100 MiB under a Downloads directory;
  • .log files of at least 50 MiB;
  • .tmp files of at least 1 MiB.

These rules are intentionally medium or low confidence and start unselected.

builtin-system​

Finds known user-level system cleanup candidates:

  • bounded profile cache directories for Chrome, Chromium, Edge, Firefox, Safari, Brave, Vivaldi, and Arc;
  • the standard macOS application-cache root plus narrowly named cache directories for popular desktop apps when they live under Application Support or an app container;
  • Quick Look thumbnails, Zoom update installers, user logs, and diagnostic reports;
  • stale regular files in the current Windows user's Temp and DirectX D3DSCache directories;
  • large temporary files and Downloads files, including .dmg, .pkg, .mpkg, and .iso installers.

Only known rebuildable cache targets may be preselected, and they still pass the shared age, evidence, and declared process-state gates. A valid standard cache-directory tag is accepted only as medium-confidence fallback evidence; it never preselects a directory by itself. Broad application caches, Spotify's persistent cache, logs, diagnostics, generic temporary-file matches, and Downloads remain review-only.

The macOS allowlist was audited against Dusty and PureMac, then narrowed to preserve Cleanr's trash-and-restore model. Cleanr deliberately excludes Trash contents, Mail data, iOS backups, Time Machine snapshots, browser service workers, Docker prune actions, and system-owned roots.

Beyond the exact named browser and desktop-app cache leaves above, the conservative Windows-specific allowlist contains only ordinary files and requires at least 30 days without modification before matching:

  • user temporary file means a regular file below the current user's AppData\Local\Temp; the Temp directory and child directories are not candidates;
  • DirectX shader cache file means a regular generated graphics-cache file below AppData\Local\D3DSCache; Windows recreates it as needed, although the next graphics launch may spend time recompiling shaders.

Cleanr does not stop applications. Rules for named browsers and desktop apps block selection when their owner is running or process state is unavailable, and execution repeats that check. If Windows still keeps another candidate locked, moving it to the Recycle Bin fails and the original stays in place. Explorer thumbnail databases are excluded because cleaning them would require restarting Explorer. Crash dumps, Windows Update and Delivery Optimization data, Prefetch, the Recycle Bin, registry data, Downloads, and system-owned roots are also excluded from this conservative Windows routine.

The Windows paths were audited against BleachBit and Winapp2, then independently narrowed using Microsoft's descriptions of Storage Sense temporary-file cleanup and generated DirectX and thumbnail caches. No external cleaner database or executable is bundled. Platform-specific scan roots are registered only by the corresponding operating-system build; the shared builtin-system plugin supplies their declarative explanations.

Additional reviewed coverage includes Windows browser and named Electron-app caches, user-level crash dumps as low-confidence diagnostics, Linux desktop thumbnail and selected Flatpak application caches, and platform-specific downloaded installers. Windows Update, macOS software updates, and Linux system package caches are reported as os_managed; they never become cleanup candidates or plan items.

Upstream source policy​

Built-in rules carry structured source metadata with a repository, full commit, license, and relationship. Permissively licensed sources may be translated with attribution. GPL and ShareAlike cleaner databases are audited-against only: they may reveal a coverage gap, but Cleanr independently verifies and writes the resulting rule instead of copying or bundling those databases. Run node scripts/check-rule-sources.mjs to validate the pinned source ledger.

platforms prevents an otherwise valid path pattern from matching on a different operating system. Omitting it preserves the legacy cross-platform behavior.

Enable or disable packs​

Only IDs in cleanup.enabled_rule_packs enable cleanup rules. Built-in inspection protections remain active even when their cleanup pack is disabled:

[cleanup]
enabled_rule_packs = ["builtin-dev", "builtin-general", "builtin-system"]

Removing builtin-general and builtin-system is useful when you want Cleanr to focus only on developer caches.

Run /rules inside the TUI to inspect the active packs and rules.

Add custom rules​

The recommended format is a declarative plugin bundle. See Plugins for a complete minimal example, validation commands, and the trust model.

For generated paths that are meaningful only inside a particular project, use a project matcher instead of a broad directory-name or path glob. Positive marker and root-directory globs identify the project root, excluded globs veto ambiguous roots, and artifact_paths lists the exact relative directories that may match:

[rules.match]
kind = "directory"

[rules.match.project]
marker_globs = ["acme-project.toml"]
root_dir_globs = ["src"]
excluded_marker_globs = ["acme-keep-build"]
excluded_root_dir_globs = ["keep-output"]
artifact_paths = ["build/cache", "build/generated"]

This fragment belongs to a [[rules]] entry. Keep the usual confidence, default-selection, reason, and risk fields conservative, especially when an artifact may require network access or contain local-only state. Excluded globs only veto children observed in the same scan snapshot; an ignored path is not proof that a child does not exist, so never use an exclusion as the rule's only safety boundary. When publishing a bundle that uses this matcher, set its cleanr_version to the first Cleanr release whose rule schema supports project; do not reuse the generic >=0.1.0 minimum from the minimal example.

For cache data that must not be touched while its owner runs, declare exact process or executable names on the rule:

runtime_guard = { process_names = ["Example Tool", "example-tool"] }

Names are matched case-insensitively, without wildcard or substring matching. An unavailable process snapshot fails closed. This field protects the matched cache; it is not permission to terminate the owner. Set the plugin's cleanr_version to the first release supporting runtime guards.

Legacy loose TOML rule-pack files are still discovered in plugin directories, but bundles provide version and compatibility metadata and are preferred.

Path glob and fallback semantics​

Path globs are segment-aware on every platform: * matches within one path segment and never crosses /, while ** may match recursively across segments. For example, **/Library/Caches/* matches a direct child of Caches, but not its nested descendants. Use **/Library/Caches/** only when recursive matching is intentional.

Set match_role = "fallback" only on a deliberately broad rule that should apply when no trusted primary rule matches the same candidate. Fallback rules cannot use default_selected = true. Prefer a specific matcher or a project matcher whenever one can express the ownership boundary.

A directory carrying a valid standard CACHEDIR.TAG can be matched with match = { kind = "directory", cache_tagged = true }. Treat this as a hint, not proof of low recreation cost: use a medium-confidence, unselected fallback rule and never combine it with another path matcher.

Inspection and constrained cache discovery (v0.17.0)​

See developer and AI cache coverage for the built-in paths, sources, review requirements and retained-data boundaries.

Use action = "inspect" and default_selected = false to explain retained data. Its default inspection_scope = "subtree" protects the path and every descendant, including matches inside an explicitly scanned subtree; covering ancestors are also excluded. Subtree inspectors require a path-only matcher and cannot depend on size, age, project markers or cache tags. inspection_scope = "entry" protects a mixed container and its ancestors while allowing separately reviewed children. Inspection is independent of rule trust/priority and can never be shadowed away by a trash rule.

match.exclude_path_globs excludes direct path matches using the same segment-aware glob syntax. It is not a general protected-path facility: an inspection still retains descendants of any ancestor it matches. For a mixed container, use an entry inspector plus subtree inspectors for retained children. match.parent_marker requires a fixed, regular direct-child filename in the candidate's parent, seen in the same scan; symlinks and absent markers do not qualify. This supports Conda archives without reading or executing configuration.

Bounded location expansion can declare include_child = true instead of suffixes, and current_user_only = true to restrict discovered children to the effective user's native ownership. Runtime guards accept the same ownership requirement and recheck it before execution. Unsupported hosts and unavailable metadata fail closed. Process names remain case-insensitive exact names, with .exe removed; Python numeric version suffixes (for example python3.13t) normalize to python. Executable names supplement process names; these checks do not prove that every possible cache user is absent.

These fields are additive in analysis/plan evidence; old records default to no inspection or ownership requirement, and absent optional fields stay omitted. Inspection uses the existing excluded state so older analysis readers remain closed to selection. Rule/location schemas reject unknown fields. Do not publish a plugin using these fields with a legacy compatibility minimum: set cleanr_version = ">=0.17.0" or a later minimum that includes every field it uses.