Skip to content

Releases: eslamfaisal/mac-cleaner

v1.6.0 — Audit remediation: safer deletes, verified duplicates, hardened server

Choose a tag to compare

@eslamfaisal eslamfaisal released this 17 Aug 13:23

A security and correctness release. Six areas of the app were audited — the delete path, the local HTTP surface, how every location is classified, performance, the interface, and the build pipeline. 38 findings were raised and each was re-checked against the real code by an independent reviewer trying to disprove it; 31 survived and are fixed here.

Nothing about how you use the app has changed, except one thing noted at the bottom if you run it from source.

Files that could have been lost

The inside of app bundles, Logic projects, VMs and document packages is no longer offered. macOS shows a .app, .logicx, .sparsebundle, .key or .pvm as a single file, but underneath each is a folder. The scanner used to walk into them and list their contents as separate items — so a 300 MB audio take inside a Logic project appeared as "a big media file", and deleting it left the project opening with a silently missing track. Worse, two apps built on the same Electron version contain byte-identical framework binaries, so they were clustering as duplicates behind a one-click "delete every copy but one". Each package is now a single row: all of it or none of it.

Duplicates are now proven identical before one is deleted. Sets were decided from 384 KB sampled out of each file — the first 256 KB, 64 KB from the middle, 64 KB from the end — and the row then stated "identical content" as fact. On a 4 GB file that is 0.009% of it. Two files can match at all three points and differ everywhere in between: VM disk images cloned from a template, preallocated database files, partly-downloaded files. This was reproduced with two 8 MB files differing at a single byte 3 MB in — the app called them identical and offered one for permanent deletion. Now the entire contents of both files are read and compared before anything is removed, and a copy that only looked identical is refused with the reason shown.

The suggested copy to keep was the wrong one. The keeper was whichever copy was newest, but a re-downloaded file is always the newest — so Downloads/2024-lease.pdf was kept and Documents/Contracts/2024-lease.pdf was the one offered for deletion. The filed copy now wins over one sitting in Downloads, Desktop or the Trash, and a name ending in "copy" or "(2)" loses.

Lightroom. The app offered every folder in your Lightroom directory while describing all of them as "generated JPEG previews that Lightroom regenerates" — including the catalog's edit data (masking, healing, AI denoise), your catalog backups, and cloud-synced originals. None of those come back. Only actual previews are offered now; smart previews and catalog backups get their own rows with honest descriptions.

A Downloads folder synced to Dropbox or iCloud. If ~/Downloads or ~/Desktop is a link into a cloud folder — a common "keep my Downloads in Dropbox" setup — deleting from it removed the file from the cloud, and from every other device. The app has always refused to touch cloud folders; one type of row skipped the check. Fixed.

Emptying the Trash could stop halfway. A file with two dots in its name (Talk with....mp4) was rejected as an invalid path, which aborted the rest of the operation — some files gone, others untouched, one confusing error. Related: one locked or in-use file no longer abandons everything after it, and a partly-completed cleanup is now reported as failed rather than counted as a success.

Things the app claimed without checking

  • Old JetBrains / Android Studio folders were declared dead purely by comparing version numbers in folder names — so running IntelliJ 2024.3 alongside 2025.2 (normal when a project needs an older version) got you "nothing reads it any more" about the IDE you had open, and deleting reset it to factory defaults. It now checks whether the version has actually been used in the last 90 days. Local file history is never deleted.
  • App data was labelled "left behind after an uninstall" for apps that were still installed, if the app lived in a subfolder of Applications (Bitdefender, and similar), or if it writes to a subfolder rather than its top-level folder. On this machine that was 13 of 185 folders.
  • "Downloads you have not opened in 3 months" was measured by when files were last changed. Opening a file does not change it. The wording now says what it measures.
  • A scan that could not read everything looked complete. A long scan of a large folder was killed after 45 seconds and the progress bar still reached 100%. The timer now watches whether work is actually progressing, and anything skipped or refused by macOS is reported next to the item count.

Security

  • The dashboard is no longer embeddable in another web page. It could be loaded invisibly inside a hostile page, where your own clicks would drive it — as far as a chain that empties your Trash permanently.
  • Every request now needs the session token. Loading the page and reading the full inventory of your files previously needed nothing at all.
  • Force-quitting the app really stops it. Quitting mid-cleanup used to leave the background process deleting to completion, with Full Disk Access, after the window was gone — and its port stayed open until you rebooted.
  • A permission prompt can no longer freeze the app. Checking for Full Disk Access could occupy every available file-system thread, after which nothing that touches disk would start again — deletes included.
  • The bundled Node runtime is verified before it is signed. It was downloaded with no integrity check at all, then signed with the developer certificate and notarized. It is now confirmed to be Apple-signed by the Node.js Foundation, or the build refuses to continue.
  • Thumbnail previews are cached in a private folder instead of a world-readable temporary one, and are cleaned up.

Interface

  • The risky label failed accessibility contrast (3.3:1) — the most consequential tier was the hardest to read. Every colour pair now passes WCAG AA.
  • Checkboxes rendered as light-grey squares on the dark background, and disabled ones looked identical to enabled ones.
  • The confirm dialog now takes keyboard focus properly, starting on Cancel — never on the delete button — and you can no longer tab into the page behind it and change the selection while it is open.
  • Scan progress is announced to screen readers; every row's controls are named after that row rather than all reading "Select item".
  • The window no longer overflows between roughly 760 and 1065 pixels wide.
  • Disk figures now use the same units as Finder, so the gauge agrees with System Settings instead of reading about 7% low.

Speed

  • A large cleanup no longer breaks the live connection at the moment it starts — which used to leave the app saying "Cleaning…" forever with no summary.
  • The list stopped rewriting itself four times a second when nothing had changed: identical redraws now touch the page zero times.
  • Files with no preview are no longer re-rendered on every redraw.

If you run from source

npm start now prints a URL containing a one-time token — open that, not http://127.0.0.1:4545, which is refused on purpose. Your browser exchanges the token for a cookie immediately and the address bar returns to normal. The .app handles this by itself; nothing changes for you if you use the DMG.

v1.5.0 — Normal mode: a Mac cleaner for everyone, not just developers

Choose a tag to compare

@eslamfaisal eslamfaisal released this 13 Aug 07:46

Mac Cleaner now has two modes. Normal mode is a brand-new interface for anyone who is not a developer: twelve plain-language categories, Move-to-Trash by default, and every row explained in a sentence. Developer mode is the tool you already know, unchanged. You pick once on first launch and can switch any time from the toolbar.

Universal build: one download runs natively on Apple Silicon and Intel.

Normal mode

  • Twelve categories instead of twenty-six technical ones: System Junk, Trash, Large & Old Files, Duplicate Files, Downloads & Installers, Unused Apps & Leftovers, App Caches, Mail & Message Attachments, Photos/Music & Media, Backups & Updates, Cloud Files on This Mac, and one collapsed card for everything developer-related.
  • Move to Trash by default, so a mistake is one "Put Back" away. The counter says what is in the Trash versus what is actually freed — emptying the Trash is what returns the space, and the app now says so.
  • A receipt after every clean: what went, what failed, and one click to the failures.
  • Keep list: pin any row you never want offered again. It stays kept across scans, and one chip brings them all back.

Where your space actually went

  • Cloud Files on This Mac — iCloud Drive, Dropbox, OneDrive and Google Drive files kept on the disk. Often the largest folder on a normal Mac, and previously invisible. Read-only: freeing them is done from Finder, and the app explains how.
  • Mail's downloaded messages are listed (read-only) instead of a category promising "Mail" and showing a few hundred megabytes.
  • Screensaver and wallpaper videos macOS downloads in the background (20–65 GB on many Macs).
  • Old app updates left behind by Sparkle, Google's updater, Microsoft AutoUpdate and Zoom.
  • The Trash on every disk, not just the boot drive.
  • iPhone and iPad backups now say which device and when, instead of a 40-character identifier.

Duplicate files, rebuilt

  • Finds duplicates from 1 MB (was 5 MB), so photos and documents saved twice show up.
  • A thumbnail for every set — click for a bigger preview. A duplicate photo is judged with your eyes, not its filename.
  • Each set says what deleting the extras frees, not what the set occupies.
  • One copy is always kept. The set checkbox skips the newest file, the confirm dialog marks it, and the server refuses any request that would delete every copy of a set.

See exactly what you are deleting

Every row shows its real path on its own line, and clicking it opens the folder in Finder with the file selected. The confirmation dialog lists paths too.

Permissions

Full Disk Access now explains what is locked ("56 places on your disk cannot be measured yet"), and offers a Quit & Reopen button — macOS only applies the permission to an app that starts after you grant it, which is the step people got stuck on. A fresh Mac with no Safari, Mail or backup data is no longer misread as "already granted".

Fixes

Two independent audit rounds found — and this release fixes — a set of defects worth naming:

  • The headline number was wrong. Space that can never be freed (your Photos library, Time Machine snapshots) was counted in "you can free up". It is now reported separately, and every total in the app follows one rule.
  • Ticking a whole duplicates category could delete every copy of every set.
  • The main scan could walk inside a Photos or Final Cut library and offer its internals as ordinary files.
  • Rescanning doubled every total because the previous scan's rows were never cleared.
  • "Select all safe" did nothing while a safety filter was active, and froze the interface on large selections (measured 96 ms per frame, now 0.7 ms).
  • A single unreadable folder could freeze the app. Three causes, all fixed: iCloud enumeration on the main thread, hashing a cloud placeholder (which makes macOS download it first), and any remaining stall — a watchdog now skips a folder that takes longer than 45 seconds and keeps going.
  • iPhone backup labels, Zoom's data row, uninstalled-app leftovers and JetBrains caches all reported wrong sizes or vanished entirely; each is fixed.

v1.4.2 — Signed and notarized: no more Gatekeeper warning

Choose a tag to compare

@eslamfaisal eslamfaisal released this 29 Jul 13:34

No more Gatekeeper warning, and no Node.js to install. Downloads are now signed with an Apple Developer ID certificate and notarized by Apple: double-click and it opens.

What changed

Previous releases were ad-hoc signed, so macOS blocked the first launch. The workaround the docs gave — right-click → Open — stopped working in macOS 15; there was no path left except System Settings → Privacy & Security → Open Anyway. That's fixed.

Three things it took:

  • Sign inside-out instead of codesign --deep, which is deprecated and can't apply per-binary entitlements.
  • New app/entitlements-node.plist. The hardened runtime that notarization requires blocks V8 from allocating executable memory, so without allow-jit and allow-unsigned-executable-memory the bundled Node aborts on launch.
  • Sign the DMG itself. Stapling a notarization ticket onto an unsigned disk image isn't enough — Gatekeeper still reads it as no usable signature.

The .app is notarized and stapled before it goes into the DMG, so it stays valid when dragged out of the DMG or launched with no network.

Upgrading from 1.4.1

Grant Full Disk Access to Mac Cleaner again after replacing the app. macOS ties that permission to the code signature, and the signature changed from ad-hoc to Developer ID. This is a one-time step — future updates keep the same identity, so the grant sticks from now on.

Verify it yourself

spctl -a -vvv "/Applications/Mac Cleaner.app"
# accepted
# source=Notarized Developer ID
# origin=Developer ID Application: Eslam Faisal (CDRX96YDNZ)

Downloads

File For
Mac.Cleaner.dmg Universal — Apple Silicon and Intel
Mac.Cleaner-AppleSilicon.dmg Apple Silicon only (smaller)
Mac.Cleaner-Intel.dmg Intel only (smaller)

No behaviour changes to scanning or deletion in this release.

v1.4.1 — Filters you can see, safe totals that add up

Choose a tag to compare

@eslamfaisal eslamfaisal released this 25 Jul 22:50
8269a39

Follow-up to v1.4.0 — two fixes for numbers that didn't reconcile on screen.

Filters are now visible and clearable

The safety tiles are a toggle filter and scroll out of view in a category, so a group could read 0 items (3 filtered out) while its card showed a size, with nothing naming the filter that hid them.

  • A chip appears in the controls row whenever items are hidden: 1,286 hidden by: safe · ≥ 10 MB — clear ✕ — one click resets the safety, size and text filters together.
  • The per-group label is now (3 filtered out — show), clickable, and its tooltip names the active filters.

The safe total now explains itself

safe 77.3 GB next to Select all safe (35.3 GB) looked like a bug. It isn't — bulk-select deliberately skips build artifacts inside recently-touched projects, the Trash (irreversible) and read-only items. Now it says so:

77.3 GB · safe
35.3 GB in one click — 41.9 GB in active projects, 117 MB in Trash (permanent) must be picked by hand

Selection behaviour is unchanged — only the explanation is new.

Everything from v1.4.0 (old & unused apps, superseded IDE versions, uninstall leftovers, creative categories) is included.

Downloads

File For
Mac.Cleaner.dmg Universal — Apple Silicon and Intel (recommended)
Mac.Cleaner-AppleSilicon.dmg Apple Silicon only (smaller)
Mac.Cleaner-Intel.dmg Intel only (smaller)

macOS 12+. Ad-hoc signed — right-click → Open on first launch.

v1.4.0 — Old & unused apps, uninstall leftovers, creative cleanup

Choose a tag to compare

@eslamfaisal eslamfaisal released this 25 Jul 21:55
2462b8a

Mac Cleaner now cleans up after apps, not just caches — the apps you stopped opening, the old versions of the ones you kept, and the data left behind by everything you uninstalled.

⏳ Applications — Old & Unused

  • Apps you stopped using. Three signals are combined per bundle: Spotlight (kMDItemLastUsedDate, version, bundle id), the mtime of ~/Library/Preferences/<bundle-id>.plist, and the running-process list. An app is listed only when every signal is 6+ months old — and a running app is never listed.
  • Duplicate installs. Same bundle id installed twice — the older copy is listed, the newer one is named in the reason.
  • Superseded IDE versions. Android Studio and JetBrains IDEs keep one settings/cache folder per version (AndroidStudio2025.2.3, IntelliJIdea2024.3, DataGrip2025.3 …) and never remove them after an upgrade. Only folders that are not the newest of their product are listed, badged with the version that replaced them.
  • Old JetBrains Toolbox builds — the previous builds Toolbox keeps after updating.
  • Forgotten macOS installers — Install macOS *.app is 12–16 GB and usually sits there long after the upgrade ran.

👻 Leftovers from Uninstalled Apps

Dragging an app to the Trash leaves its ~/Library/Application Support and ~/Library/Containers data behind forever. Those folders are now matched against the names and bundle ids of every installed app, and listed when nothing claims them. Matching is deliberately loose so ambiguous names stay out; macOS daemons and folders touched in the last 60 days are skipped.

🎬 Cleanup for the rest of the Mac world

  • Creative — Video · Photo · Audio · Design: Adobe media cache (Premiere / After Effects / Audition), DaVinci Resolve render cache and proxies, Final Cut backups, Camera Raw cache, Lightroom previews, Capture One, Photoshop autorecover, Sketch, Figma, Blender, Logic and GarageBand sound libraries.
  • Games: Steam libraries, shader cache and partial downloads.
  • Personal: Podcast downloads, Apple Books downloads, Messages attachments.
  • App caches: Teams, Word, Outlook, Slack, OneDrive, Google Drive, plus an iCloud Drive explainer.

26 categories total.

Safety

/Applications became deletable, so the server-side validator was tightened for it: only whole .app bundles at the top level of /Applications pass — nothing else under that path can be deleted, and the existing symlink / realpath TOCTOU checks still run on every target. Apple's own apps and the running Mac Cleaner bundle are never listed. As always: scanning is read-only, deletion is Trash-first, and nothing goes without your click.

Downloads

File For
Mac.Cleaner.dmg Universal — Apple Silicon and Intel (recommended)
Mac.Cleaner-AppleSilicon.dmg Apple Silicon only (smaller)
Mac.Cleaner-Intel.dmg Intel only (smaller)

macOS 12+. The build is ad-hoc signed — right-click → Open on first launch.

Mac Cleaner v1.3.0

Choose a tag to compare

@eslamfaisal eslamfaisal released this 23 Jul 16:41

Universal binary — one app for every Mac 🎉

The main DMG is now a Universal 2 binary: native code for Apple Silicon (M1/M2/M3/M4) and Intel in one app. macOS picks the right one automatically — no Rosetta needed.

Which download?

Asset Runs on Size
Mac.Cleaner.dmg (recommended) Every Mac (macOS 12+) ~80 MB
Mac.Cleaner-AppleSilicon.dmg Apple Silicon only ~41 MB
Mac.Cleaner-Intel.dmg Intel only ~41 MB

Not sure? → About This Mac ("Chip: Apple M…" = Apple Silicon, "Processor: Intel…" = Intel) — or just take the universal DMG.

Also in this release

  • build-app.sh --arch universal|arm64|x64|all — build any variant yourself
  • Fixed: pre-1.3.0 DMGs were Apple Silicon-only ("Bad CPU type in executable" on Intel)
  • README: new Apple Silicon vs Intel guide + troubleshooting
  • Landing page: SEO overhaul (Open Graph, Twitter cards, JSON-LD, sitemap, robots.txt)

First launch: releases are ad-hoc signed — right-click the app → Open → Open (once).

Mac Cleaner v1.2.0

Choose a tag to compare

@eslamfaisal eslamfaisal released this 22 Jul 21:18
e0c2cf1

Now for every Mac user — not just developers.

⬇ Download & install

Download Mac.Cleaner.dmg below (41 MB, Apple Silicon, macOS 12+), drag to Applications.
First launch: right-click → Open → Open (ad-hoc signed), or
xattr -d com.apple.quarantine "/Applications/Mac Cleaner.app".

✨ New in 1.2.0

  • 👯 Duplicate Files — identical files (same size and checksum) clustered into sets. One click selects every copy except the newest, so you always keep one.
  • 🐋 Biggest Files — every file ≥ 50 MB across your whole home folder, now including Movies, Music and Pictures, sorted largest-first. Photos/Music libraries are shown but protected (read-only).
  • 🏠 Personal & Media — screenshots piling up on the Desktop, Downloads untouched for 90+ days, Mail attachment copies.
  • Smarter big-file safety: Downloads leftovers are caution (re-downloadable), personal files risky, media libraries never deletable.

Still: 100% local · zero dependencies · always manual deletion · per-boot token · open source (MIT).

🔐 Verify

shasum -a 256 Mac.Cleaner.dmg
# 4d7de6c1b81f551d5dc58d23fd441ac346ec54b1505e4f0a081de114f81a40dc

Full docs: README · Site: https://eslamfaisal.github.io/mac-cleaner/

Mac Cleaner v1.1.0

Choose a tag to compare

@eslamfaisal eslamfaisal released this 22 Jul 18:11

Mac Cleaner — find what is eating your disk, delete only what you choose.
A zero-dependency, 100% local disk cleaner for developer Macs. Native app and web dashboard, same code.

⬇ Download & install

  1. Download Mac.Cleaner.dmg below (41M, Apple Silicon, macOS 12+).
  2. Open it and drag Mac Cleaner into Applications.
  3. First launch: right-click the app → Open → Open. (Ad-hoc signed — no paid Apple certificate — so Gatekeeper asks once.)
    Terminal alternative: xattr -d com.apple.quarantine "/Applications/Mac Cleaner.app"
  4. Optional: grant Full Disk Access to Mac Cleaner when prompted — unlocks Safari/Mail/backup scanning. The app walks you through it and detects the grant live.

Intel Mac? Run from source (npm start) or build with an x64 Node: NODE_BIN=/path/to/node ./build-app.sh.

🧭 How to use

  1. Start Scan — category cards and the disk gauge fill in live.
  2. Browse the overview; each card shows size, item count and a safety split (🟢 safe / 🟡 caution / 🔴 risky).
  3. Click a card to drill into its files. Hover a row for why it's cleanable and how it comes back.
  4. Select items (or Select all safe), pick Move to Trash or Delete permanently, then Clean. Risky items need an explicit confirmation.

Root-owned System Data is shown read-only with the exact terminal command instead of a delete button. Nothing is ever deleted automatically.

✨ What's in this release

  • System Data insights — old iOS device updates, Homebrew cache, diagnostic reports, update payloads, Time Machine local snapshots, system caches, sized and explained.
  • Full Disk Access onboarding — three-step guided grant with live detection.
  • CleanMyMac-style UI — category card grid with safety-split bars, drill-down detail views, subtle animations (respects reduced motion).
  • Native app — Swift WKWebView shell with a bundled Node runtime; FDA is attributed to Mac Cleaner itself. The same code still runs as a local web dashboard from source.
  • Hardened deletes: root-owned items rejected both when queued and at delete validation.

100% local · zero dependencies · per-boot token · path validation · open source (MIT).

🔐 Verify your download

shasum -a 256 Mac.Cleaner.dmg
# 4180a7db1e67df4b83af168a5364e6e230f5886b5da3bf36b9df2ce3deb3e8d3

Full docs: README