Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Prithvi-Web/TreeMap-Disk-Visualizer

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

130 Commits
130 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


🟩  Find it
Squarified treemap of every byte
🟨  Understand it
Trends, diffs & duplicate hunting
🟥  Reclaim it
One-click cleanup → system Trash

Tip

No Node. No setup. No telemetry. The desktop app is fully self-contained and scans the disk of the machine it runs on. Deletes always go to your system Trash — nothing is ever hard-deleted, so every action is recoverable.


✨ The ten views

TreeMap isn't just a treemap — it's a full disk-hygiene workbench. Ten views, one zero-dependency frontend.

The ten views: Dashboard, Treemap, Grid, Apps, Duplicates, Trends, Compare, Clean Up, Offloaded, Scheduled + Ignore

📊 Dashboard

Disk-usage ring, live scan progress, file-type donut chart, and the top-10 largest files and folders. Click a folder to leap straight into the treemap. A disk-full forecast projects from your scan history — "At current growth (+5.4 GB/day), this disk is full in ~58 days — top culprits: …" — and is honest when it can't know: too little history, erratic growth, or shrinking usage all say so instead of inventing a number. An All Storage strip unifies your local disk with any connected Google Drive / Dropbox / OneDrive — scan a cloud account into the very same treemap (metadata only, no file contents are ever downloaded; deletes go to the provider's own trash; duplicates/live/offload are disabled with clear notices). Opt-in and local-first: with no account connected, zero cloud code runs and nothing touches the network.

🗺️ Treemap

A squarified treemap of every file, sized by bytes and colored teal → amber → red. Drill in, climb back with breadcrumbs + zoom-out, search with highlights (report, *.zip), pin folder budgets (over-budget folders get a red dashed border), and export the chart (PNG / SVG) or the whole scan (CSV, or a multi-page PDF report). A time slider appears once a folder has scan history: scrub to any past scan and watch the map morph — in the treemap and the sunburst — with a diff overlay tinting what grew green and what shrank red. And a Live toggle watches the scanned folder in real time: changed files pulse, regions re-flow as bytes move, and a "writing now" feed ranks the busiest paths by MB/min (auto-pauses when the disk goes quiet). Containers are drillable: .zip/.jar/.tar/.tar.gz/.iso (and Docker's data file, with the CLI) get a badge — click to look inside without extracting a byte, using the archive's own directory listing. Nothing inside an archive can be trashed or opened — only the archive itself.

🔲 Grid

A size-proportional icon grid with multi-select, sorting, and virtual scrolling — buttery even on huge folders.

📦 Apps

How much disk does each application own? Every app's total, split into app / caches / data / logs, with a "Clear caches safely" button (Trash-only, never touches your data) and click-through into the treemap. Files no app owns land in an honest "Everything else" bucket, so the totals always match the scan.

🧬 Duplicates

Finds true duplicates (size + streamed SHA-256), grouped with reclaimable space per group. Auto-select keeps the newest copy of each. A Near-Duplicate Images tab catches resized, re-encoded and screenshot copies with a perceptual dHash.

📈 Trends

Every scan saves a lightweight snapshot, charted over time per folder — with a clear "what grew / what shrank since last scan" breakdown.

🔀 Compare

Pick any two scans of the same folder for a file-level diff: added, removed, grew, shrank. Subtrees collapse to one row instead of thousands.

🧹 Clean Up

Custom rules (old / huge / by extension / duplicated), Smart Suggestions — sorted into regenerable (node_modules, Rust/Maven target, virtualenvs, build output — each shown with the command that restores it), cache, and junk, plus a per-profile browser cache breakdown (Chrome / Edge / Brave / Firefox / Safari) — and Empty Folders. Everything → Trash.

📤 Offloaded

The third option next to keep and trash: Offload… copies files to another drive, verifies every byte (SHA-256, read back from the destination), and only then moves the originals to the Trash — never a bare move; any failure rolls back cleanly. This tab is the searchable index of everything offloaded, with per-destination totals, reveal-on-destination, and verified Restore. Unplugged drives show grayed out with a last-seen date.

⏰ Scheduled scans + 🚫 Ignore list

Re-scan folders on a schedule with growth-threshold alerts and disk-full forecast warnings (native desktop notifications; the forecast horizon is configurable in Settings, default 30 days). Tell it what to skip with paths, names, or globs like *.iso and ~/projects/**/dist.

How it's built — Node.js + Express 5 + TypeScript on the backend. A single, zero-dependency index.html on the frontend: hand-coded Canvas 2D, no React, no D3, no Chart.js. Ships as a web app and a downloadable Electron desktop app for macOS and Windows.

⬇️ Download the app (for users)

Grab the latest installer from the Releases page:

PlatformFileHow
🍎 macOS TreeMap-x.y.z-arm64.dmg Open it, drag TreeMap to Applications, launch.
🪟 Windows TreeMap Setup x.y.z.exe Run it and follow the installer.

Important

First-launch security prompt. Because the app isn't signed with a paid Apple/Microsoft developer certificate, your OS shows a one-time warning.

  • macOS: right-click the app → OpenOpen
  • Windows: click More infoRun anyway

After the first launch it opens normally.

🛠️ macOS says "TreeMap is damaged and can't be opened"?

That happens when the download's quarantine flag is still set. Clear it once, then launch normally — open Terminal and paste:

xattr -dr com.apple.quarantine /Applications/TreeMap.app

No Node.js or setup required — the desktop app is self-contained and scans the disk of the computer it runs on.

🖥️ Desktop extras

  • 📌 Menu bar / tray icon with live free-disk stats and quick actions (open app, scan home folder, quit). Close the window and TreeMap stays in the tray so scheduled scans keep running — quit from the tray menu.
  • 🖱️ Drag & drop a folder onto the window or dock icon to scan it instantly.
  • 🔄 Auto-updates from GitHub Releases (Windows; asks before restarting). On macOS, auto-update needs a code-signed build, so unsigned builds skip it — grab new versions from Releases.
  • 🔔 Growth alerts from scheduled scans arrive as native notifications.

🚀 Run from source / web mode (3 commands)

npm install
npm run build
npm start

Then open http://127.0.0.1:4280 in your browser.

💡 For development with auto-reload: npm run dev

Requires Node.js 20+. Trash support uses gio on Linux (preinstalled on GNOME/KDE), Finder via osascript on macOS, and the Recycle Bin via PowerShell on Windows.

📦 Build the desktop app

npm install
npm run app          # build + launch the desktop app locally
npm run dist:mac     # produce a macOS .dmg in release/
npm run dist:win     # produce a Windows installer in release/

⚠️ You can only build the macOS app on a Mac and the Windows app on Windows. To get both without owning both machines, use the automated release below — GitHub builds them for you.

🤖 Publish a new version (automated GitHub Actions)

A workflow (.github/workflows/release.yml) builds the macOS and Windows installers on GitHub's servers and attaches them to a Release — including the latest*.yml metadata the in-app auto-updater checks.

To cut a release:

  1. Bump the version in package.json (e.g. 1.2.1).
  2. Create a matching tag prefixed with v (e.g. v1.2.1) and push it. In GitHub Desktop: Repository → Push, then on github.com: Releases → Draft a new release → Choose a tag → type v1.2.1Publish.
  3. The workflow runs automatically, builds both installers, and uploads them. After a few minutes the download links appear on the Releases page.

You can also trigger a test build anytime from Actions → Build & Release → Run workflow (installers are saved as downloadable artifacts instead of a Release).

🔌 API overview

Click to expand the full endpoint table
Endpoint Description
POST /api/scan Start scanning a folder → { scanId }
GET /api/scan/:id/progress Live scan progress (Server-Sent Events)
GET /api/scan/:id/result Full file tree (202 while running)
GET /api/scan/:id/treemap Pre-computed squarified treemap layout
GET /api/scan/:id/stats Scan counters incl. engine, duration & fast-rescan cache usage
GET /api/scan/:id/budgets Saved folder budgets cross-referenced against this scan
GET /api/scan/:id/export?format=csv|pdf Download the scan as CSV (files / folders) or a PDF report
GET /api/scans Completed scans currently in memory
GET /api/large-files?scanId= Top N largest files
GET /api/large-folders?scanId= Top N largest folders (recursive sizes)
GET /api/file-types?scanId= Size breakdown by extension
GET /api/apps?scanId= Per-app storage attribution: totals, app / cache / data / logs breakdown, safe-to-clear bytes
GET /api/duplicates?scanId= Duplicate groups (starts hashing; poll until complete)
GET /api/near-duplicates?scanId=&threshold= Perceptual (dHash) near-duplicate image clusters
GET /api/empty-folders?scanId= Recursively empty folders (ignoreJunk configurable)
GET /api/compare?scanIdA=&scanIdB= File-level diff of two scans of the same root
GET /api/snapshots Scan history: roots, per-root snapshots (?path=), or all (?all=true)
GET /api/snapshots/compare?a=&b= Top-level deltas between two snapshots
GET /api/snapshots/tree?path=&at= Historical treemap closest to a timestamp (time slider), with grew/shrank data
GET /api/forecast?path= Disk-full projection: days until full, confidence, top growers — honest when history is thin
GET /api/watch/:scanId Live disk activity (Server-Sent Events): per-second batches of { path, delta, kind }
POST /api/container/expand List a container's contents (zip/jar/tar/tgz/iso/docker) as virtual treemap children — never extracts
POST /api/offload · GET /api/offload/:id/progress Copy → SHA-256 verify → trash originals, to another drive (SSE progress, cancellable with rollback)
GET /api/offload/index · POST /api/offload/restore Searchable offload catalog (mount-aware) and verified restore
GET /api/cloud/status · POST /api/cloud/connect · …/disconnect Cloud accounts: local-only status, PKCE OAuth (loopback + paste fallback), token wipe
POST /api/cloud/scan · POST /api/cloud/trash Metadata-only cloud scan (registers like a disk scan) and provider-trash deletes — the documented pathGuard exemption
GET /api/cleanup/suggestions?scanId= Smart cleanup suggestions (regenerable / cache / junk)
GET /api/cleanup/browser-profiles?scanId= Per-browser-profile cache breakdown
GET /api/git/repos?scanId= · POST /api/git/gc Git pack/loose/LFS breakdown, and git gc a scanned repo
GET /api/system/snapshots · POST …/purge OS snapshot accounting (APFS / Btrfs / VSS)
GET /api/settings · PUT /api/settings Ignore list, scheduled scans + folder budgets
GET /api/notifications Growth alerts from scheduled scans
GET /api/system · GET /api/trash/size Disk totals & platform; system Trash size
GET /api/fs/list?path= Folder browser (powers the path picker)
GET /api/files/preview?path= Quick-look preview (image / text / thumbnail)
DELETE /api/files Move files to the system trash
POST /api/files/open Open / reveal a path in Finder & co.

🤖 Use it with AI (MCP)

TreeMap speaks the Model Context Protocol (MCP) — the open standard that lets AI assistants like Claude use apps as tools. Connect it once and you can simply talk to your disk:

"What's eating my disk?"  ·  "Find duplicates in my Downloads and clean them up"  ·  "How long until this disk is full?"  ·  "Move my old videos to the external drive"

The AI does the scanning and number-crunching with TreeMap's real engine, and every safety rule still applies: deletes only ever go to the system Trash, destructive actions can be previewed with a dry run first, and everything is written to an audit log.

Step 1 — One-time setup (~2 minutes)

You need Node.js 20+ installed. Then copy-paste this into a terminal:

git clone https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer.git
cd TreeMap-Disk-Visualizer
npm install
npm run build

Done. Now print the folder's full location — you'll paste it in step 2 wherever you see /PATH/TO/TreeMap-Disk-Visualizer:

pwd

Step 2 — Connect your AI app

🟠 Claude Desktop
  1. Open Claude Desktop → Settings → Developer → Edit Config. That opens claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\).
  2. Add TreeMap to it (if the file already has an mcpServers block, just add the "treemap" entry inside it):
{
  "mcpServers": {
    "treemap": {
      "command": "node",
      "args": ["/PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js"]
    }
  }
}
  1. Fully quit and reopen Claude Desktop. A tools icon appears in the chat box — TreeMap's tools are listed under treemap.

🪟 Windows: write the path with double backslashes, e.g. "C:\\Users\\you\\TreeMap-Disk-Visualizer\\dist\\mcp\\index.js".

⌨️ Claude Code

One command (swap in your real path):

claude mcp add treemap -- node /PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js

That's it — next session, ask Claude Code to scan a folder and it will pick up the TreeMap tools automatically. (claude mcp list shows it; claude mcp remove treemap undoes it.)

🖱️ Cursor

Create (or edit) .cursor/mcp.json in your home folder for all projects — or in a project's root for just that project — with:

{
  "mcpServers": {
    "treemap": {
      "command": "node",
      "args": ["/PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js"]
    }
  }
}

Then enable it under Settings → MCP.

🧩 Any other MCP client

TreeMap is a standard stdio MCP server. Point your client at:

  • Command: node
  • Arguments: /PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js

No environment variables, ports, or API keys needed — it runs locally and talks over stdin/stdout. (Quick smoke test from the repo folder: npm run mcp should print server ready on stdio.)

What the AI can do

Eight tools, all calling the exact same internals as the app — same validation, same safety rails:

Tool What it does
scan_path Scan a folder → returns a scanId the other tools use
get_largest The biggest files or folders in a scan
find_duplicates True duplicates (size + SHA-256 content hashing)
cleanup_suggestions Known-reclaimable space: caches, regenerable build folders, junk
forecast Disk-full projection — "full in ~58 days at current growth"
compare_scans What grew and what shrank between two scans
offload Move files to another drive the safe way: copy → verify → then trash originals
trash_paths Move files to the system Trash — never a hard delete

Kept safe by design

  • 🎯 The AI can only touch paths inside folders it has scanned — scanning is what grants permission.
  • 🧪 trash_paths and offload accept dryRun: true, returning the exact list of affected files and bytes while doing nothing — so the AI can show you the plan before acting.
  • 📜 You can pin down what agents may ever touch with an agent-policy.json (allowed roots, protected paths, a per-operation byte cap) — see AGENTS.md.
  • 🧾 Every destructive request — executed, dry-run, or refused — lands in an append-only audit.jsonl you can review any time.

🤓 Prefer plain HTTP? The same power is available as a REST API with a machine-readable spec — start the server and fetch /api/openapi.json or /api/capabilities, or read AGENTS.md, the full guide for automated agents.

🛡️ Safety

Disk tools should never lose your data. TreeMap is built defensively:

  • 🔒 Paths are sanitized and traversal-proofed; system dirs (/proc, /sys, /dev, /run, C:\Windows\System32, …) are blocked outright.
  • 🎯 Trash/open endpoints only accept paths inside a folder you scanned — and never paths inside an archive (only the archive itself can be trashed).
  • ♻️ Deletes always go through the OS Trash — undo from Finder/Explorer any time.
  • 📤 Offload never bare-moves: copy first, verify every byte against a SHA-256 read back from the destination, and only then trash the originals — any failure rolls back with local data untouched.
  • ☁️ Cloud scanning is strictly opt-in and metadata-only: no file contents are ever downloaded, OAuth tokens live only in the local app-data folder (Disconnect wipes them), cloud deletes go to the provider's own trash, and with no account connected no cloud code path executes at all.
  • 🧬 The Duplicates view refuses to trash every copy in a group — at least one always stays.
  • 🚦 Token-bucket rate limiting (10 req/s per IP), plus graceful SIGTERM shutdown that drains live SSE streams and stops background hashing, scheduled scans & live-activity watchers.
  • ⏳ Scan results live in memory only and auto-expire after 30 minutes; history snapshots and settings are small JSON files in the platform app-data folder (~/Library/Application Support/TreeMap, %APPDATA%\TreeMap, or ~/.config/treemap).

🗂️ Project layout

src/
  api/          Express routes (scan, files, system, insights, settings)
  services/     ScanStore (packed Structure-of-Arrays scan memory),
                DiskScanner (adaptive concurrent walker), Cleaner (trash/open),
                DuplicateFinder (staged hashing), Snapshots (Trends history),
                CleanupRules (smart suggestions), AppAttribution (per-app storage),
                Forecast (disk-full projection), Watcher (live activity),
                ContainerScanner (archive drill-down), Offload (copy-verify-trash),
                cloud/ (Google Drive, Dropbox, OneDrive — OAuth + metadata scans),
                Scheduler (recurring scans), Settings, Storage (app-data JSON), DiskUsage
  models/       Shared TypeScript interfaces
  utils/        formatBytes, squarified treemap, path sanitizer, glob matcher
  middleware/   errorHandler, rateLimiter, pathGuard
  index.ts      App entrypoint + graceful shutdown
electron/
  main.js       Desktop shell: window, tray, drag-drop, notifications, auto-update
  preload.js    Context-isolated bridge for drag-drop paths & scan pushes
public/
  index.html    The entire frontend (inline CSS + JS, zero dependencies)
scripts/
  gen-tray-icon.js  One-time generator for the tray template icons

🧠 Design decisions worth knowing

  • A scan lives in a packed Structure-of-Arrays store, not a tree of objects. Every scan used to be millions of JavaScript objects (~330 bytes each, measured) — which put a hard ceiling of a few million files on what fit in RAM. The tree now lives in a handful of typed arrays (src/services/scanStore.ts): names in one UTF-8 pool, children as contiguous id ranges laid out breadth-first, paths reconstructed on demand instead of stored. Measured cost: ~52 bytes per file at 1M, 5M, 20M and 40M synthetic nodes — a 40M-item scan is ~2 GB of arrays, and a 100M-item scan projects to ~5 GB, on hardware where the object tree could not have held 20M. Summing every directory size is one reverse linear pass (28 ms for 5M nodes vs 2.2 s recursive), nothing recurses on pathological depth, and the browser notices nothing: the pruned JSON the API emits is byte-identical to the old tree — a golden test replays a fixture scan against responses recorded from the pre-rewrite server and compares the raw bytes. The store is pure JS + TypedArrays — no native modules, nothing new to package. (An on-disk SQLite tier behind the same interface remains a possible future for scans that must survive restarts; the packed store is the shipping default.) The one deliberate trade: handing 250k pruned nodes to the UI rebuilds path strings the old tree kept around, ~150 ms per handover on an operation that already spends ~170 ms serializing.
  • Scan speed is a threadpool problem, not a walker problem. Every async lstat/readdir runs on libuv's threadpool, which defaults to 4 threads — that, not the walker's concurrency, was the bottleneck. TreeMap sizes the pool to 2× cores (≤ 16) before it spins up; measured on APFS this scans ~1.6× faster, while 32 threads is slower than 4 (kernel metadata-lock contention). The dashboard shows which engine ran and how long the scan took.
  • Snapshots are automatic — one is saved after every successful scan, so Trends needs zero setup. Totals + top-level entries live in snapshots.json (a few KB each, capped at 200 per folder); the time slider's shallow trees (≤ 3 levels, ~100 KB budget each) sit in separate per-root files so the main history file stays tiny.
  • The scheduler is a 60-second setInterval, not node-cron — hour-level granularity doesn't justify a dependency. Schedules fire while the app runs (the desktop app keeps running in the tray).
  • Duplicate detection is staged (size → first 64 KB hash → full SHA-256) so scans with hundreds of thousands of files finish hashing in seconds, and only true content matches are reported.
  • Compare collapses subtrees — a deleted or added folder shows as one row, not thousands of file rows.

Found this useful?

Star  Fork  Issues



TreeMap  ·  built with 🟩🟨🟥 by Prithvi-Web

If TreeMap freed up a few gigs for you, a ⭐ goes a long way.

About

TreeMap is a fully downloadable app that can run on mac, windows, and linux. That visualizeses all of your disk-space into charts and square board. It also lets you delete unwanted files and opens files for you aswell.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.