Skip to content

AppsGanin/Trashly

Repository files navigation

Trashly

Trashly

Reclaim gigabytes on your Mac — clean, uninstall, optimize and monitor, in one fast native app.

A free & open-source macOS toolkit that finds the junk other cleaners miss, removes apps with every leftover, and shows you exactly what's happening on your machine — all behind a slick custom UI.

License: AGPL v3 Platform Arch Built with Tauri Rust React Stars

Download · Features · Screenshots · Build · Safety

Trashly — clean, uninstall, optimize and monitor your Mac

Why Trashly?

Most cleaners either nag you for money, ship a giant Electron bundle, or quietly miss the gigabytes that actually matter (Xcode device support, Android emulators, Electron code caches, the iCloud trash…). Trashly is different:

  • ⚡️ Tiny & fast — a Rust core + native WebView. No Electron, no bloat, instant scans.
  • 🔎 Finds what others miss — generic cache roots plus curated heavy-data paths for Xcode, Android Studio, JetBrains, Docker, browsers and more.
  • 🧯 Safe by design — every deletion is re-validated against an allow-list in Rust; defaults to the Trash (recoverable).
  • 🆓 Free & open source — AGPLv3, no upsells, no telemetry.

Features

🟦 Dashboard — one-tap Smart Scan

A landing screen with a single Smart Scan button that fans out across the cleaners at once — caches & junk, the Trash, and duplicate files — then shows the total reclaimable space as result cards. Click a card to jump straight into that module and review.

🧹 Clean — reclaim disk space

Progressive scanning renders instantly, then streams sizes in so a 3 GB cache never freezes the UI.

  • User & app caches — everything under ~/Library/Caches, per-item so you choose what stays.
  • Developer caches — Xcode DerivedData / iOS DeviceSupport / device logs, npm, yarn, bun, gradle, cargo, Go, CocoaPods…
  • App & container caches — Electron Code Cache/GPUCache/service workers, sandboxed-app caches.
  • Browser caches — Chrome, Edge, Brave, Arc, Vivaldi, Opera, Yandex.
  • Project build artifacts — finds node_modules, target, dist, .next… sitting next to a real project manifest in your dev folders.
  • Logs & Trash — including the separate iCloud Drive trash that Finder hides.
  • Per-category checkboxes, live totals, and a clear Move to Trash / Delete permanently choice.

🗑 Uninstall — apps + every leftover

Drag an app to the Bin and you leave gigabytes behind. Trashly hunts them all down.

  • Lists installed apps sorted by size, with their real icons.
  • Finds leftovers by bundle id and name: caches, app support, containers, group containers, preferences, launch agents, login items, HTTP storage, WebKit, cookies, crash reports, application scripts…
  • Knows the heavy hitters: Xcode DerivedData/DeviceSupport, Android SDK & emulators, JetBrains caches, Docker/OrbStack data, browser profiles.
  • Keep the app, clean its data — untick the bundle to wipe only the leftovers.
  • Handles system apps (Safari): can't delete the bundle, but clears its data.
  • Warns if the app is running so you can quit it before uninstalling.

📑 Duplicate Finder — by content, not by name

Two modes over your Downloads, Documents, Desktop, Pictures, Movies & Music:

  • Exact duplicates — files are grouped by size, then confirmed with a full BLAKE3 content hash, so identical files are caught even when renamed. Keeps the oldest copy by default.
  • Similar photos & screenshots — a perceptual (dHash) hash clusters look-alike images (resized, re-compressed, edited screenshots, incl. HEIC iPhone photos), shown as a thumbnail grid. Keeps the largest (best-quality) copy.
  • Inspect before deleting — Reveal in Finder or Quick Look any item straight from the list.
  • Runs in parallel with live progress and a Cancel button; user data is fenced to your home folders (never Library or secrets) and removed to the Trash by default.

⚡️ Optimize — one-shot maintenance

Native admin prompt for privileged tasks; tools that aren't installed are hidden automatically.

Rebuild Launch Services · Reset QuickLook / font caches · Homebrew cleanup · Flush DNS · Purge inactive memory · Clear system caches & logs · Rebuild Spotlight.

📊 Status — a real system monitor

Live dashboard with a health score and diagnosis — accurate numbers read from top/ps/netstat and the kernel's own memory-pressure signal, not the libraries that report zero on recent macOS.

CPU + per-core + load · memory / swap / pressure · disks · real-time network rates · battery (health, cycles, temp, adapter) · Wi-Fi / Ethernet / Bluetooth · top processes by CPU & memory.

📈 Menu-bar widget

A tray icon with live CPU / RAM / Disk / Battery in the menu bar, a dropdown with the same stats, and quick Show / Quit. Closing the window keeps Trashly running in the menu bar.

⚙️ Settings

  • Menu-bar metrics — choose exactly which appear in the title and the tray dropdown (pick none → just the icon).
  • Protected folders — pick folders Trashly must never touch; enforced across every cleaner, on top of the built-in guards.
  • Cleanup history — a running log of what was removed (path · size · Trash/permanent), so you can review and restore.

Screenshots

Clean Uninstall
Clean Uninstall
Optimize Status
Optimize Status

🧯 Safety first

A cleaner you can't trust is worse than no cleaner. Trashly is built defensively:

  • Allow-list guard — every path is re-validated in Rust before deletion (safety.rs). A forged path from the UI can never escape the allow-listed roots, and .. escapes are rejected.
  • Trash by default — items move to the real macOS Trash via NSFileManager (restorable with “Put Back”). Permanent deletion is a separate, two-step confirmation.
  • Never inside packages — the user-file tools skip .photoslibrary, .app, .fcpbundle, .musiclibrary… so your Photos library and apps can't be damaged.
  • Protected folders — user-defined folders that no engine will ever touch (Settings).
  • Smart dedup — duplicates always keep ≥1 copy; hardlinks are collapsed; iCloud-offloaded files are skipped (no surprise downloads or cloud deletions).
  • Privileged tasks confirm first — Optimize actions show what they'll do and route admin tasks through the native macOS password prompt.
  • No silent failures — anything that can't be removed is reported (with the reason, e.g. needs Full Disk Access), never hidden.
  • Shared/risky data is opt-in — SDKs, emulators and browser profiles are flagged verify and left unchecked.
  • Audit log + no telemetry. Every removal is logged locally for you; nothing ever leaves your Mac.

Install

macOS 10.15 (Catalina) or later — Apple Silicon & Intel. Runs on every Mac: MacBook / MacBook Air / Pro, iMac, Mac mini, Mac Studio, Mac Pro.

Download the latest .dmg from the Releases page, drag Trashly to Applications, and launch.

The app isn't notarized yet, so on first launch right-click → Open (or System Settings → Privacy & Security → Open Anyway).

🔄 Auto-update — Trashly checks GitHub releases on launch and (from the About dialog) installs signature-verified updates in a click.

💡 For full results, grant Trashly Full Disk Access (System Settings → Privacy & Security) so it can see protected caches and the Trash.

Build from source

Requires Rust and Node.js.

git clone https://github.com/AppsGanin/Trashly.git
cd trashly
npm install
npm run tauri dev      # run in development
npm run tauri build    # build for your current Mac's architecture

To ship a universal binary that runs on both Apple Silicon and Intel:

rustup target add aarch64-apple-darwin x86_64-apple-darwin
npm run tauri build -- --target universal-apple-darwin

Architecture

A Rust core does the heavy lifting (scanning, sizing, safe file ops) off the UI thread; a React + TypeScript frontend renders a custom interface.

src-tauri/src/
  safety.rs     path allow-list guard (is_deletable / is_uninstall_target / is_user_path)
  fsutil.rs     shared dir_size / trash / delete helpers
  clean.rs      scan() + size_paths() + clean()   — data-driven category table
  uninstall.rs  list_apps() + app_leftovers() + app_icon() + uninstall()
  dupes.rs      scan_duplicates()                 — size buckets → BLAKE3 content hash
  photos.rs     scan_similar_photos()             — perceptual dHash + clustering
  userfiles.rs  remove_files()                    — safe removal of user-picked files
  optimize.rs   list_optimizations() + run_optimization()
  status.rs     status() + system_info()          — ps / top / netstat / ioreg
src/
  lib/          typed API wrappers, toast system, helpers
  views/        Dashboard · Clean · Uninstall · Duplicates · Optimize · Status · modals

Stack: Tauri 2 · Rust · React 19 · TypeScript · Vite · lucide icons.

Heavy commands run via spawn_blocking so the UI never janks. Per-process CPU, memory footprint and network rates come from top/ps/netstat because sysinfo's counters are unreliable on recent macOS.

How it compares

Trashly CleanMyMac AppCleaner
Free & open source
Native (no Electron)
Clean caches/logs
App uninstall + leftovers
Dev-tool heavy data (Xcode/Android/JetBrains) 🟡
Project build-artifact cleanup (node_modules/target/dist)
One-tap Smart Scan
Duplicate finder (content hash) 🟡
Similar-photo / screenshot detection 🟡
Live system monitor
Menu-bar widget with configurable live stats 🟡

✅ full · 🟡 partial · ❌ none

Roadmap

Have an idea? Open an issue.

Contributing

PRs and issues welcome! Found a junk path Trashly misses, or a path it shouldn't touch? That's the most valuable contribution — open an issue with the location and the app it belongs to.

Commits follow Conventional Commits (feat:, fix:, docs:…) — this drives automated versioning and the changelog.

Releasing

Fully automated via release-please + tauri-action:

  1. Merge conventional-commit PRs into main.
  2. release-please keeps a Release PR open with the next version bump (package.json, Cargo.toml, tauri.conf.json) and the updated CHANGELOG.md.
  3. Merge the Release PR → it tags the commit and creates the GitHub Release.
  4. The CI then builds the universal .dmg, signs the auto-update artifacts, and attaches them (plus latest.json) to that release automatically.

No manual version edits — the commit types decide the bump (fix: → patch, feat: → minor, feat!:/BREAKING CHANGE → major).

Updater signing — the in-app updater verifies a minisign signature, so CI needs two repository secrets:

  • TAURI_SIGNING_PRIVATE_KEY — the private key generated with npm run tauri signer generate.
  • TAURI_SIGNING_PRIVATE_KEY_PASSWORD — its password (empty if you generated the key without one).

The matching public key lives in tauri.conf.json (plugins.updater.pubkey) and the update feed is releases/latest/download/latest.json.

License

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later) — see LICENSE.

If Trashly saved you some disk space, consider leaving a ⭐ — it really helps.