{"id":51490144,"url":"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer","last_synced_at":"2026-07-26T07:00:45.512Z","repository":{"id":364163219,"uuid":"1266676309","full_name":"Prithvi-Web/TreeMap-Disk-Visualizer","owner":"Prithvi-Web","description":"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. ","archived":false,"fork":false,"pushed_at":"2026-07-24T19:50:09.000Z","size":1574,"stargazers_count":332,"open_issues_count":0,"forks_count":26,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-07-24T21:14:41.804Z","etag":null,"topics":["cleanup","cross-platform","dashboard","data-visualization","disk-cleanup","disk-management","disk-space-analyzer","disk-usage","electron","electron-app","file-manager","macos","nodejs","storage-analyzer","treemap","typescript","windows"],"latest_commit_sha":null,"homepage":"https://tree-map-landing-page.vercel.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Prithvi-Web.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-11T21:10:27.000Z","updated_at":"2026-07-24T19:48:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer","commit_stats":null,"previous_names":["prithvi-web/treemap","prithvi-web/treemap-disk-visualizer"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/Prithvi-Web/TreeMap-Disk-Visualizer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prithvi-Web%2FTreeMap-Disk-Visualizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prithvi-Web%2FTreeMap-Disk-Visualizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prithvi-Web%2FTreeMap-Disk-Visualizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prithvi-Web%2FTreeMap-Disk-Visualizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Prithvi-Web","download_url":"https://codeload.github.com/Prithvi-Web/TreeMap-Disk-Visualizer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prithvi-Web%2FTreeMap-Disk-Visualizer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35904303,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-26T02:00:06.503Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cleanup","cross-platform","dashboard","data-visualization","disk-cleanup","disk-management","disk-space-analyzer","disk-usage","electron","electron-app","file-manager","macos","nodejs","storage-analyzer","treemap","typescript","windows"],"created_at":"2026-07-07T11:00:27.948Z","updated_at":"2026-07-26T07:00:45.505Z","avatar_url":"https://github.com/Prithvi-Web.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003c!-- ░░░░░░░░░░░░░░░░░░░░░░░░░░░  TREEMAP  ░░░░░░░░░░░░░░░░░░░░░░░░░░░ --\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/releases\"\u003e\n  \u003cimg src=\"treemap-hero.svg\" alt=\"TreeMap — a disk-space visualizer that shows exactly what's eating your disk\" width=\"100%\"\u003e\n\u003c/a\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003c!-- primary CTAs --\u003e\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/releases\"\u003e\u003cimg src=\"https://img.shields.io/badge/⬇_Download-Latest_Release-2dd4bf?style=for-the-badge\u0026labelColor=0b1220\" alt=\"Download\"\u003e\u003c/a\u003e\u0026nbsp;\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/Prithvi-Web/TreeMap-Disk-Visualizer?style=for-the-badge\u0026label=Star\u0026labelColor=0b1220\u0026color=fbbf24\" alt=\"Stars\"\u003e\u003c/a\u003e\u0026nbsp;\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/fork\"\u003e\u003cimg src=\"https://img.shields.io/github/forks/Prithvi-Web/TreeMap-Disk-Visualizer?style=for-the-badge\u0026label=Fork\u0026labelColor=0b1220\u0026color=f43f5e\" alt=\"Forks\"\u003e\u003c/a\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003c!-- platform --\u003e\n\u003cimg src=\"https://img.shields.io/badge/macOS-arm64-0b1220?style=flat-square\u0026logo=apple\u0026logoColor=white\" alt=\"macOS\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Windows-installer-0b1220?style=flat-square\u0026logo=windows\u0026logoColor=white\" alt=\"Windows\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Linux-web_mode-0b1220?style=flat-square\u0026logo=linux\u0026logoColor=white\" alt=\"Linux\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/TypeScript-0b1220?style=flat-square\u0026logo=typescript\u0026logoColor=3178C6\" alt=\"TypeScript\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Express_5-0b1220?style=flat-square\u0026logo=express\u0026logoColor=white\" alt=\"Express 5\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Electron-0b1220?style=flat-square\u0026logo=electron\u0026logoColor=47848F\" alt=\"Electron\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/frontend-zero_dependencies-0b1220?style=flat-square\u0026color=2dd4bf\" alt=\"Zero deps\"\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003ckbd\u003e\u003ca href=\"#-download-the-app-for-users\"\u003e⬇ Download\u003c/a\u003e\u003c/kbd\u003e \u0026nbsp;\n\u003ckbd\u003e\u003ca href=\"#-the-ten-views\"\u003e✨ Features\u003c/a\u003e\u003c/kbd\u003e \u0026nbsp;\n\u003ckbd\u003e\u003ca href=\"#-run-from-source--web-mode-3-commands\"\u003e🚀 Run it\u003c/a\u003e\u003c/kbd\u003e \u0026nbsp;\n\u003ckbd\u003e\u003ca href=\"#-use-it-with-ai-mcp\"\u003e🤖 AI / MCP\u003c/a\u003e\u003c/kbd\u003e \u0026nbsp;\n\u003ckbd\u003e\u003ca href=\"#-api-overview\"\u003e🔌 API\u003c/a\u003e\u003c/kbd\u003e \u0026nbsp;\n\u003ckbd\u003e\u003ca href=\"#-safety\"\u003e🛡️ Safety\u003c/a\u003e\u003c/kbd\u003e\n\n\u003c/div\u003e\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd align=\"center\" width=\"33%\"\u003e🟩\u0026nbsp;\u0026nbsp;\u003cb\u003eFind it\u003c/b\u003e\u003cbr\u003e\u003csub\u003eSquarified treemap of every byte\u003c/sub\u003e\u003c/td\u003e\n\u003ctd align=\"center\" width=\"33%\"\u003e🟨\u0026nbsp;\u0026nbsp;\u003cb\u003eUnderstand it\u003c/b\u003e\u003cbr\u003e\u003csub\u003eTrends, diffs \u0026 duplicate hunting\u003c/sub\u003e\u003c/td\u003e\n\u003ctd align=\"center\" width=\"33%\"\u003e🟥\u0026nbsp;\u0026nbsp;\u003cb\u003eReclaim it\u003c/b\u003e\u003cbr\u003e\u003csub\u003eOne-click cleanup → system Trash\u003c/sub\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\n\u003e [!TIP]\n\u003e **No Node. No setup. No telemetry.** The desktop app is fully self-contained and scans the disk\n\u003e of the machine it runs on. Deletes always go to your **system Trash** — nothing is ever\n\u003e hard-deleted, so every action is recoverable.\n\n\u003cbr\u003e\n\n## ✨ The ten views\n\nTreeMap isn't just a treemap — it's a full disk-hygiene workbench. Ten views, one zero-dependency frontend.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"views.svg\" width=\"100%\" alt=\"The ten views: Dashboard, Treemap, Grid, Apps, Duplicates, Trends, Compare, Clean Up, Offloaded, Scheduled + Ignore\"\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 📊 Dashboard\nDisk-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.\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 🗺️ Treemap\nA 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.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 🔲 Grid\nA size-proportional icon grid with multi-select, sorting, and virtual scrolling — buttery even on huge folders.\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 📦 Apps\n**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.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 🧬 Duplicates\nFinds **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**.\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 📈 Trends\nEvery scan saves a lightweight snapshot, charted over time per folder — with a clear **\"what grew / what shrank since last scan\"** breakdown.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 🔀 Compare\nPick any two scans of the same folder for a file-level diff: **added, removed, grew, shrank.** Subtrees collapse to one row instead of thousands.\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 🧹 Clean Up\n**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.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### 📤 Offloaded\nThe 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.\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### ⏰ Scheduled scans + 🚫 Ignore list\nRe-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`.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003e **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.\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n## ⬇️ Download the app (for users)\n\nGrab the latest installer from the [**Releases page**](https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/releases):\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003ePlatform\u003c/th\u003e\u003cth\u003eFile\u003c/th\u003e\u003cth\u003eHow\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e🍎 \u003cb\u003emacOS\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eTreeMap-x.y.z-arm64.dmg\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eOpen it, drag TreeMap to Applications, launch.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e🪟 \u003cb\u003eWindows\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eTreeMap Setup x.y.z.exe\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRun it and follow the installer.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003e [!IMPORTANT]\n\u003e **First-launch security prompt.** Because the app isn't signed with a paid Apple/Microsoft\n\u003e developer certificate, your OS shows a one-time warning.\n\u003e - **macOS:** right-click the app → **Open** → **Open**\n\u003e - **Windows:** click **More info** → **Run anyway**\n\u003e\n\u003e After the first launch it opens normally.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🛠️ macOS says \"TreeMap is damaged and can't be opened\"?\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\nThat happens when the download's quarantine flag is still set. Clear it once, then launch normally — open **Terminal** and paste:\n\n```bash\nxattr -dr com.apple.quarantine /Applications/TreeMap.app\n```\n\n\u003c/details\u003e\n\n\u003e No Node.js or setup required — the desktop app is self-contained and scans the disk of the computer it runs on.\n\n### 🖥️ Desktop extras\n\n- 📌 **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.\n- 🖱️ **Drag \u0026 drop** a folder onto the window or dock icon to scan it instantly.\n- 🔄 **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.\n- 🔔 **Growth alerts** from scheduled scans arrive as native notifications.\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n## 🚀 Run from source / web mode (3 commands)\n\n```bash\nnpm install\nnpm run build\nnpm start\n```\n\nThen open **http://127.0.0.1:4280** in your browser.\n\n\u003e 💡 For development with auto-reload: `npm run dev`\n\nRequires **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.\n\n### 📦 Build the desktop app\n\n```bash\nnpm install\nnpm run app          # build + launch the desktop app locally\nnpm run dist:mac     # produce a macOS .dmg in release/\nnpm run dist:win     # produce a Windows installer in release/\n```\n\n\u003e ⚠️ You can only build the macOS app on a Mac and the Windows app on Windows.\n\u003e To get **both** without owning both machines, use the automated release below — GitHub builds them for you.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🤖 Publish a new version (automated GitHub Actions)\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\nA 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.\n\n**To cut a release:**\n\n1. Bump the `version` in `package.json` (e.g. `1.2.1`).\n2. Create a matching **tag** prefixed with `v` (e.g. `v1.2.1`) and push it.\n   In GitHub Desktop: **Repository → Push**, then on github.com: **Releases → Draft a new release → Choose a tag →** type `v1.2.1` → **Publish**.\n3. The workflow runs automatically, builds both installers, and uploads them. After a few minutes the download links appear on the Releases page.\n\nYou can also trigger a test build anytime from **Actions → Build \u0026 Release → Run workflow** (installers are saved as downloadable artifacts instead of a Release).\n\n\u003c/details\u003e\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n## 🔌 API overview\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eClick to expand the full endpoint table\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\n| Endpoint | Description |\n|---|---|\n| `POST /api/scan` | Start scanning a folder → `{ scanId }` |\n| `GET /api/scan/:id/progress` | Live scan progress (Server-Sent Events) |\n| `GET /api/scan/:id/result` | Full file tree (202 while running) |\n| `GET /api/scan/:id/treemap` | Pre-computed squarified treemap layout |\n| `GET /api/scan/:id/stats` | Scan counters incl. engine, duration \u0026 fast-rescan cache usage |\n| `GET /api/scan/:id/budgets` | Saved folder budgets cross-referenced against this scan |\n| `GET /api/scan/:id/export?format=csv\\|pdf` | Download the scan as CSV (files / folders) or a PDF report |\n| `GET /api/scans` | Completed scans currently in memory |\n| `GET /api/large-files?scanId=` | Top N largest files |\n| `GET /api/large-folders?scanId=` | Top N largest folders (recursive sizes) |\n| `GET /api/file-types?scanId=` | Size breakdown by extension |\n| `GET /api/apps?scanId=` | Per-app storage attribution: totals, app / cache / data / logs breakdown, safe-to-clear bytes |\n| `GET /api/duplicates?scanId=` | Duplicate groups (starts hashing; poll until complete) |\n| `GET /api/near-duplicates?scanId=\u0026threshold=` | Perceptual (dHash) near-duplicate image clusters |\n| `GET /api/empty-folders?scanId=` | Recursively empty folders (`ignoreJunk` configurable) |\n| `GET /api/compare?scanIdA=\u0026scanIdB=` | File-level diff of two scans of the same root |\n| `GET /api/snapshots` | Scan history: roots, per-root snapshots (`?path=`), or all (`?all=true`) |\n| `GET /api/snapshots/compare?a=\u0026b=` | Top-level deltas between two snapshots |\n| `GET /api/snapshots/tree?path=\u0026at=` | Historical treemap closest to a timestamp (time slider), with grew/shrank data |\n| `GET /api/forecast?path=` | Disk-full projection: days until full, confidence, top growers — honest when history is thin |\n| `GET /api/watch/:scanId` | Live disk activity (Server-Sent Events): per-second batches of `{ path, delta, kind }` |\n| `POST /api/container/expand` | List a container's contents (zip/jar/tar/tgz/iso/docker) as virtual treemap children — never extracts |\n| `POST /api/offload` · `GET /api/offload/:id/progress` | Copy → SHA-256 verify → trash originals, to another drive (SSE progress, cancellable with rollback) |\n| `GET /api/offload/index` · `POST /api/offload/restore` | Searchable offload catalog (mount-aware) and verified restore |\n| `GET /api/cloud/status` · `POST /api/cloud/connect` · `…/disconnect` | Cloud accounts: local-only status, PKCE OAuth (loopback + paste fallback), token wipe |\n| `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 |\n| `GET /api/cleanup/suggestions?scanId=` | Smart cleanup suggestions (regenerable / cache / junk) |\n| `GET /api/cleanup/browser-profiles?scanId=` | Per-browser-profile cache breakdown |\n| `GET /api/git/repos?scanId=` · `POST /api/git/gc` | Git pack/loose/LFS breakdown, and `git gc` a scanned repo |\n| `GET /api/system/snapshots` · `POST …/purge` | OS snapshot accounting (APFS / Btrfs / VSS) |\n| `GET /api/settings` · `PUT /api/settings` | Ignore list, scheduled scans + folder budgets |\n| `GET /api/notifications` | Growth alerts from scheduled scans |\n| `GET /api/system` · `GET /api/trash/size` | Disk totals \u0026 platform; system Trash size |\n| `GET /api/fs/list?path=` | Folder browser (powers the path picker) |\n| `GET /api/files/preview?path=` | Quick-look preview (image / text / thumbnail) |\n| `DELETE /api/files` | Move files to the system trash |\n| `POST /api/files/open` | Open / reveal a path in Finder \u0026 co. |\n\n\u003c/details\u003e\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n## 🤖 Use it with AI (MCP)\n\nTreeMap 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*:\n\n\u003e *\"What's eating my disk?\"* \u0026nbsp;·\u0026nbsp; *\"Find duplicates in my Downloads and clean them up\"* \u0026nbsp;·\u0026nbsp; *\"How long until this disk is full?\"* \u0026nbsp;·\u0026nbsp; *\"Move my old videos to the external drive\"*\n\nThe 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.\n\n### Step 1 — One-time setup (~2 minutes)\n\nYou need [Node.js 20+](https://nodejs.org) installed. Then copy-paste this into a terminal:\n\n```bash\ngit clone https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer.git\ncd TreeMap-Disk-Visualizer\nnpm install\nnpm run build\n```\n\nDone. Now print the folder's full location — you'll paste it in step 2 wherever you see `/PATH/TO/TreeMap-Disk-Visualizer`:\n\n```bash\npwd\n```\n\n### Step 2 — Connect your AI app\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🟠 Claude Desktop\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. Open Claude Desktop → **Settings → Developer → Edit Config**. That opens `claude_desktop_config.json`\n   (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\\Claude\\`).\n2. Add TreeMap to it (if the file already has an `mcpServers` block, just add the `\"treemap\"` entry inside it):\n\n```json\n{\n  \"mcpServers\": {\n    \"treemap\": {\n      \"command\": \"node\",\n      \"args\": [\"/PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js\"]\n    }\n  }\n}\n```\n\n3. **Fully quit and reopen Claude Desktop.** A tools icon appears in the chat box — TreeMap's tools are listed under `treemap`.\n\n\u003e 🪟 **Windows:** write the path with double backslashes, e.g. `\"C:\\\\Users\\\\you\\\\TreeMap-Disk-Visualizer\\\\dist\\\\mcp\\\\index.js\"`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e⌨️ Claude Code\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\nOne command (swap in your real path):\n\n```bash\nclaude mcp add treemap -- node /PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js\n```\n\nThat'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.)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🖱️ Cursor\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\nCreate (or edit) `.cursor/mcp.json` in your home folder for all projects — or in a project's root for just that project — with:\n\n```json\n{\n  \"mcpServers\": {\n    \"treemap\": {\n      \"command\": \"node\",\n      \"args\": [\"/PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js\"]\n    }\n  }\n}\n```\n\nThen enable it under **Settings → MCP**.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🧩 Any other MCP client\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\nTreeMap is a standard **stdio** MCP server. Point your client at:\n\n- **Command:** `node`\n- **Arguments:** `/PATH/TO/TreeMap-Disk-Visualizer/dist/mcp/index.js`\n\nNo 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`.)\n\n\u003c/details\u003e\n\n### What the AI can do\n\nEight tools, all calling the exact same internals as the app — same validation, same safety rails:\n\n| Tool | What it does |\n|---|---|\n| `scan_path` | Scan a folder → returns a `scanId` the other tools use |\n| `get_largest` | The biggest files or folders in a scan |\n| `find_duplicates` | True duplicates (size + SHA-256 content hashing) |\n| `cleanup_suggestions` | Known-reclaimable space: caches, regenerable build folders, junk |\n| `forecast` | Disk-full projection — *\"full in ~58 days at current growth\"* |\n| `compare_scans` | What grew and what shrank between two scans |\n| `offload` | Move files to another drive the safe way: copy → verify → then trash originals |\n| `trash_paths` | Move files to the system Trash — never a hard delete |\n\n### Kept safe by design\n\n- 🎯 The AI can only touch paths **inside folders it has scanned** — scanning is what grants permission.\n- 🧪 `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.\n- 📜 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](AGENTS.md).\n- 🧾 Every destructive request — executed, dry-run, or refused — lands in an append-only `audit.jsonl` you can review any time.\n\n\u003e 🤓 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](AGENTS.md), the full guide for automated agents.\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n## 🛡️ Safety\n\nDisk tools should never lose your data. TreeMap is built defensively:\n\n- 🔒 Paths are sanitized and traversal-proofed; system dirs (`/proc`, `/sys`, `/dev`, `/run`, `C:\\Windows\\System32`, …) are blocked outright.\n- 🎯 Trash/open endpoints only accept paths **inside a folder you scanned** — and never paths *inside an archive* (only the archive itself can be trashed).\n- ♻️ Deletes always go through the OS Trash — undo from Finder/Explorer any time.\n- 📤 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.\n- ☁️ 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.\n- 🧬 The Duplicates view refuses to trash *every* copy in a group — at least one always stays.\n- 🚦 Token-bucket rate limiting (10 req/s per IP), plus graceful SIGTERM shutdown that drains live SSE streams and stops background hashing, scheduled scans \u0026 live-activity watchers.\n- ⏳ 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`).\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n## 🗂️ Project layout\n\n```text\nsrc/\n  api/          Express routes (scan, files, system, insights, settings)\n  services/     ScanStore (packed Structure-of-Arrays scan memory),\n                DiskScanner (adaptive concurrent walker), Cleaner (trash/open),\n                DuplicateFinder (staged hashing), Snapshots (Trends history),\n                CleanupRules (smart suggestions), AppAttribution (per-app storage),\n                Forecast (disk-full projection), Watcher (live activity),\n                ContainerScanner (archive drill-down), Offload (copy-verify-trash),\n                cloud/ (Google Drive, Dropbox, OneDrive — OAuth + metadata scans),\n                Scheduler (recurring scans), Settings, Storage (app-data JSON), DiskUsage\n  models/       Shared TypeScript interfaces\n  utils/        formatBytes, squarified treemap, path sanitizer, glob matcher\n  middleware/   errorHandler, rateLimiter, pathGuard\n  index.ts      App entrypoint + graceful shutdown\nelectron/\n  main.js       Desktop shell: window, tray, drag-drop, notifications, auto-update\n  preload.js    Context-isolated bridge for drag-drop paths \u0026 scan pushes\npublic/\n  index.html    The entire frontend (inline CSS + JS, zero dependencies)\nscripts/\n  gen-tray-icon.js  One-time generator for the tray template icons\n```\n\n## 🧠 Design decisions worth knowing\n\n- **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.\n- **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.\n- **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.\n- **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).\n- **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.\n- **Compare collapses subtrees** — a deleted or added folder shows as one row, not thousands of file rows.\n\n\u003cbr\u003e\n\n\u003cimg src=\"divider.svg\" width=\"100%\" alt=\"\"\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n### Found this useful?\n\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/badge/⭐_Star_the_repo-fbbf24?style=for-the-badge\u0026labelColor=0b1220\" alt=\"Star\"\u003e\u003c/a\u003e\u0026nbsp;\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/fork\"\u003e\u003cimg src=\"https://img.shields.io/badge/🍴_Fork_it-f43f5e?style=for-the-badge\u0026labelColor=0b1220\" alt=\"Fork\"\u003e\u003c/a\u003e\u0026nbsp;\n\u003ca href=\"https://github.com/Prithvi-Web/TreeMap-Disk-Visualizer/issues\"\u003e\u003cimg src=\"https://img.shields.io/badge/🐛_Open_an_issue-2dd4bf?style=for-the-badge\u0026labelColor=0b1220\" alt=\"Issues\"\u003e\u003c/a\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n**TreeMap** \u0026nbsp;·\u0026nbsp; built with 🟩🟨🟥 by [**Prithvi-Web**](https://github.com/Prithvi-Web)\n\n\u003csub\u003eIf TreeMap freed up a few gigs for you, a ⭐ goes a long way.\u003c/sub\u003e\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPrithvi-Web%2FTreeMap-Disk-Visualizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPrithvi-Web%2FTreeMap-Disk-Visualizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPrithvi-Web%2FTreeMap-Disk-Visualizer/lists"}