See what's filling your Mac. In seconds.
A fast, exact disk-space explorer for macOS with a live sunburst chart.
Free and open source, written in Rust with a GPU-rendered native UI.

▶ Watch Petal in 50 seconds (with sound)
Petal shows your disk as a sunburst: the centre is the folder you're looking at, each ring is one level deeper, and the size of a slice is how much space it takes. It draws the picture while it reads, tells you which big folders are safe to clear, and tells you exactly how much deleting them will free.
- Live from the first second. The chart appears straight away and fills in as Petal reads. Folders turn from muted to full colour the moment their total is final, and you can click into them before the scan has finished. Segments glide into place instead of jumping.
- Fast. A whole Mac (about 6 million files) in roughly 25 seconds; a typical home folder in a few
seconds; a 90,000-item folder in under a second. Directory listings use
getattrlistbulkandopenatacross all cores. The performance notes have the measurements. - Exact. Sizes are allocated blocks, so they match Finder's "on disk". For the startup disk, every other APFS volume (macOS itself, Preboot, VM, Recovery…) gets an exact slice, so the chart adds up to the disk's used space to the byte.
- Findings. Petal checks the usual suspects first (Trash, Downloads, Xcode build files and
archives, iOS device support and simulators, iPhone backups, Docker, app caches, npm, Cargo, Gradle,
Movies, Mail,
node_modules, Chrome's update leftovers) and labels each Safe to delete or Review first, with a one-line explanation. The first ones show up within a fraction of a second. - Savings you can trust. On APFS, deleting a cloned or hard-linked file may free nothing. Petal works out what deleting your selection really frees, counting clones and hard links once, and this is tested against real deletions on a throwaway APFS volume.
- Collect, then clean up. Drag folders (or press +) into the Collector, check the total, and move them to the Trash in one go. Nothing is deleted outright; you can put things back from the Trash.
- Safe by design. Petal only reads file metadata. It never downloads iCloud files that are only in the cloud, never sends anything over the network, and has no analytics.

A real scan of a sample home folder, slowed down 8×.
All screenshots and the video use a made-up home folder generated by
scripts/make-demo-home.py, not anyone's real files.
Download Petal 0.1.0 (DMG, 5.5 MB) for Macs with Apple silicon (M1 or later) running macOS 13 or later.
- Open the DMG and drag Petal into Applications.
- Open Petal. This build isn't notarized by Apple yet, so macOS says it can't verify the app. Click Done, then open System Settings › Privacy & Security, scroll down and click Open Anyway next to the message about Petal. You only need to do this once.
All releases are on the Releases page.
It takes a couple of minutes. You need: macOS 13 or later, the Xcode Command Line Tools (xcode-select --install), and
Rust. The repository pins the toolchain in rust-toolchain.toml, so rustup
fetches the right version automatically.
git clone https://github.com/henrydennis/petal.gitcd petal && scripts/bundle.shThat builds dist/Petal.app (signed ad hoc, so it runs on the Mac that built it). Drag it into
Applications and open it.
scripts/bundle.sh --dmg also makes a disk image.
Or run it straight from the source tree:
cargo run --releasemacOS keeps some folders private (Mail, Messages, Safari, other apps' data) unless an app has Full Disk Access. Petal works without it, but shows exactly how much it couldn't read, and offers a button that opens System Settings › Privacy & Security › Full Disk Access. Turn Petal on there; the card in Petal notices within a couple of seconds and offers to rescan.
When you run Petal from a terminal (cargo run), macOS asks about the terminal app instead of Petal.
The first time you open Petal it starts scanning your startup disk straight away. After that it opens on the Disks screen, with your volumes, Scan Home Folder and Choose Folder….
- Hover a slice or a row to see its size; the two stay in sync.
- Click a folder (in the chart or the list) to zoom in. Click the centre, or use the breadcrumbs, to go back up.
- Click a finding to open its folder in the chart; press + on it to collect it.
- In the list, ⌕ reveals an item in Finder and + adds it to the Collector.
- Move to Trash… asks for confirmation, moves the collected items to the Trash, and updates every total in place without rescanning.
| Keys | Action |
|---|---|
| ⌘O | Choose a folder to scan |
| ⌘R | Rescan |
| ⌫, Esc or ⌘↑ | Go to the enclosing folder |
| ⇧⌘D | Back to the Disks screen |
| ⌘Q | Quit |
You can also pass a folder on the command line: petal ~/Library.
src/
├── main.rs app setup, menus, key bindings, command-line flags
├── app.rs the GPUI view: disks, scanning and results screens, sidebar, findings, collector
├── scan.rs parallel walk (outline → hotspots → depth-first), the flat Tree, volumes, frees_of
├── dirlist.rs getattrlistbulk/openat directory listing, with a portable fallback
├── live.rs live per-folder totals during a scan, snapshots, and the live-chart benchmark
├── disk.rs the startup disk's APFS container: exact slices for the other volumes
├── findings.rs the catalog of known space hogs and how to recognise them
├── sunburst.rs layout in angle space, painting with PathBuilder, polar hit-testing, colours
├── motion.rs easing segments between live snapshots
├── eta.rs progress (items vs. the volume's object count) and "about N s left"
├── onboarding.rs first run and Full Disk Access detection
├── clock.rs the UI clock (lets the recorder pause time)
└── snapshot.rs dev tool: scripted input, screenshots and video recording
- Outline. The first two levels are listed by name in ~10 ms, so the chart has a shape at once.
- Hotspots. Known space hogs from the findings catalog are read next, in parallel, so findings and the biggest slices are exact within a couple of seconds even on a full disk.
- Main walk. Everything else, depth-first across all cores, reusing the hotspot results. Every folder in the top four levels has an atomic running total, and the UI snapshots those ten times a second. A folder is marked final as soon as the walk leaves it.
- Results. The finished tree is a flat array of nodes. Findings resolve their exact savings in
the background (
scan::frees_of), and results never wait for them.
The UI is built with GPUI (the community edition of the
framework behind the Zed editor), which renders everything on the GPU with Metal. The chart is painted
with PathBuilder inside a canvas, and the folder list is a virtualised uniform_list.
cargo test # unit tests
cargo test -- --ignored # plus the APFS clone-accounting test (creates and deletes a small disk image)
cargo run --release -- --bench-scan ~/Library 6 # headless scan benchmark (median of 6)
cargo run --release -- --bench-live ~/Library 3 # how soon the live chart looks right
cargo run --release -- --check-access # does this process have Full Disk Access?bench/ab.sh runs two builds alternately and compares their medians, and refuses to report a result
if the two scans disagree. See docs/PERFORMANCE.md for the method and the
history of what was tried.
With --features snapshot, Petal can drive its own window from a script and save PNGs, or record a
video (needs ffmpeg). While recording, the app's clock and the scan pause during each frame's
capture, so the video plays at the app's real speed and a smooth 30 fps no matter how long each
capture takes. slow-motion N records the following steps N times slower, still at 30 fps.
scripts/make-demo-home.py /tmp/demoHOME=/tmp/demo/alex PETAL_HIDE_ACCESS=1 PETAL_VIDEO=/tmp/petal.mp4 \
PETAL_SCRIPT="hide-pointer; until-done 10; wait 1; show-pointer; move 1100 700; glide 904 363 1; click; wait 2; quit" \
cargo run --release --features snapshot -- /tmp/demo/alexScript steps: wait S, glide X Y S, move X Y, click, until-done MAX, slow-motion N,
hide-pointer, show-pointer, quit (coordinates are in points within the window). For PNGs, set
PETAL_SNAPSHOT=/tmp/petal instead and use shot NAME and burst NAME COUNT MS.
scripts/bundle.sh signs ad hoc by default, which is fine on the Mac that built it. To distribute,
sign with a Developer ID and notarize:
PETAL_SIGN_ID="Developer ID Application: Your Name (TEAMID)" PETAL_NOTARY_PROFILE=petal-notary scripts/bundle.sh --dmg(Save the notary profile once with xcrun notarytool store-credentials petal-notary.) macOS ties
Full Disk Access to the code signature, so a stable Developer ID signature also keeps access granted
across updates.



