Specfork

@specfork/disk-usage

Desktop disk usage analyzer for Windows, macOS and Linux. Scan a folder or drive, explore a size tree and treemap, see file types and largest files, and clean up safely.

desktopfiles Version 0.1.1 101 requirements Licence CC-BY-4.0 Specfork/disk-usage

Disk usage

A desktop program that shows where disk space goes. It scans a folder or drive, sums sizes up a tree, draws a treemap where area equals size, groups files by type, finds the largest, newest, oldest and oddest files, and runs cleanup actions (trash, delete, custom commands) with confirmation and an automatic rescan. Scans can be saved and reopened elsewhere. Behaviour derived from QDirStat's open-source code (GPL-2.0-only), written fresh and stack-free. Not affiliated with or endorsed by Stefan Hundhammer. The name is used only to credit the source.

Area Prefix Covers
scan.md SCAN Starting, progress, stopping, item types, read states, mount boundaries, volumes overview, performance
sizes.md SIZE Size model: apparent and allocated size, hard links, sparse and offline files, roll-ups, units
tree.md TREE Size tree: columns, loose-files group, sorting, percent bars, selection, navigation
treemap.md MAP Treemap layout, colours, shading, zoom, selection sync, performance
filetypes.md TYPE File categories, type statistics, locating files of a type, age statistics
discover.md DISC Largest, newest, oldest, hard-linked, broken-link and sparse files; find by name
cleanup.md CLN Cleanup actions, placeholders, confirmation, protected paths, refresh policies, output
exclude.md EXCL Exclude rules for folders
export.md EXP Saving and reopening scans, list export
settings.md SET Preferences, defaults, keyboard shortcuts, offline guarantee

Single user, local only: no account, no network, no telemetry. Every rule runs on one device. Sizes use binary units (1 KiB = 1024 B); times are local in the interface and UTC ISO 8601 in files; enum values are snake_case. Keyboard shortcuts are defaults; a build may follow its platform's conventions instead.

Cleanup

Status: Draft · Prefix: CLN

Purpose

Acting on what the scan found (trash, delete, or any command) safely, then updating the numbers.

Requirements

ID Requirement Verified by
CLN-1 A cleanup action is {id, title, kind: builtin|command, command?, enabled, works_for: [file, folder, loose_files], destructive, confirm, refresh, recurse, output, shell, shortcut?}; it appears in menus only for selections where every item's kind is in works_for. action for folders only → hidden when a file is selected
CLN-2 Built-in actions, which can be disabled but not removed: open_in_file_manager, open_terminal_here, move_to_trash (Delete), delete_permanently (Shift+Delete), and compress_folder (archives the folder beside itself, then removes it after success; marked destructive). fresh install → 5 built-in actions
CLN-3 move_to_trash and delete_permanently always confirm, whatever confirm says: the dialog lists the first 20 paths, the item count, and the summed total_size without double-counting nested items; the default button is Cancel. delete_permanently adds that it cannot be undone. Shift+Delete on 3 items → dialog "3 items, 1.2 GiB", Cancel focused
CLN-4 Protected paths are never trashed, deleted or passed to a command action marked destructive: the OS root, the user's home folder itself, any mount point, and the scan root itself. The action is refused with a message naming the path. delete on a mount point → refused
CLN-5 If the trash is unavailable for an item's volume, move_to_trash stops and offers delete_permanently with its own confirmation (CLN-3) for those items only. volume without trash → second confirmation
CLN-6 Command actions expand placeholders before running: {path} (full path), {name} (last component), {dir} (the folder itself, or a file's parent), {terminal} and {file_manager} (the platform's default apps); every substituted value is quoted for the chosen shell. name a b'c.txt → passed as one argument
CLN-7 Commands run with the working folder set to {dir}; shell is user_default (default), a named shell, or none (run directly). With several items the command runs once per item, in tree order, one at a time. 3 files selected → 3 runs
CLN-8 confirm (default off for commands, on for those marked destructive) shows the expanded command line(s) and item count before running. destructive action → expanded command shown first
CLN-9 recurse runs the command in the folder and in each of its subfolders, deepest first. recurse on a/ with a/b/ → runs in a/b, then a
CLN-10 refresh after the action: none, this (rescan the item), parent (rescan its parent), assume_deleted (remove it from the tree without rescanning). Built-in trash and delete use assume_deleted only for items that are really gone, and rescan the parent otherwise. trash file → gone from tree, parent totals drop
CLN-11 output: always, on_error (default; opens when the command writes to stderr or exits non-zero), after_delay (opens if still running after 5 s), never. The output view shows each command line, stdout, stderr (visually distinct) and exit code, and can stop the running command. failing command → output opens with exit code
CLN-12 Cleanups are disabled while a scan of the affected subtree runs, and for scans opened from a file (EXP-3) until rescanned from disk. during scan → cleanup menu disabled
CLN-13 User actions are added, edited, reordered, enabled or disabled, and removed in settings; removing one asks for confirmation. remove action → confirm → gone from menus

Out of scope

  • Undo of permanent deletion; secure erase.
  • Scheduled or automatic cleanups.

Decisions

  • Trash and delete confirm always (CLN-3); only user commands may skip confirmation, and only when not marked destructive.
  • Protected paths (CLN-4) are refused outright rather than double-confirmed: deleting a mount point or a home folder from a disk-usage view is never what the user meant.
  • Placeholder names are generic ({path}); the source uses its own macro syntax.

Discover

Status: Draft · Prefix: DISC

Purpose

Ready-made searches that surface the files most worth a look, plus a name search.

Requirements

ID Requirement Verified by
DISC-1 Every search runs over the current item's subtree (the root if none) and opens a results list with columns size, modified, path, sortable, with a count; opening a row selects it in the tree and treemap; cleanup actions work on selected rows. open row → item selected in tree
DISC-2 Largest files: the 200 files with the largest size, descending. subtree of 1,000 files → 200 rows, first = biggest
DISC-3 Newest files: the 200 most recently modified files; oldest files: the 200 least recently modified. newest → first row is latest modified
DISC-4 Hard-linked files: every file with links > 1, with its link count as an extra column. file with 3 links → listed, links 3
DISC-5 Broken links: every symbolic link whose target does not exist, with the target as an extra column. link to deleted file → listed
DISC-6 Sparse files and offline files (SIZE-4, SIZE-5): one search each, with bytes and allocated as extra columns. sparse file → listed with both sizes
DISC-7 Files from a year or month (from age statistics, TYPE-7): every file whose modified time falls in it. 2021 row → only 2021 files
DISC-8 Find (Ctrl+F): a text with mode contains (default), starts_with, ends_with, exact, wildcard or regex; case_sensitive (default off); type filter files, folders, links, all (default files). An invalid regex is refused with a message. ends_with .log → only names ending .log
DISC-9 Find returns at most 1,000 results and then says the list was cut at 1,000. 5,000 matches → 1,000 + notice
DISC-10 Result lists drop rows for items removed by a cleanup or rescan without being reopened. trash a listed file → row disappears

Out of scope

  • Duplicate-file finding by content.
  • Saved searches.

Decisions

  • Fixed caps (200, 1,000) keep result lists usable; a narrower subtree gives more precise results.

Exclude rules

Status: Draft · Prefix: EXCL

Purpose

Skipping folders the user does not want scanned or counted.

Requirements

ID Requirement Verified by
EXCL-1 A rule is {pattern, syntax: fixed|wildcard|regex, match: name|full_path, case_sensitive, if_contains_file}; defaults wildcard, name, case-sensitive on POSIX and off on Windows and macOS. rule node_modules → every such folder excluded
EXCL-2 Rules apply to folders only. A folder matching any rule is not read; it shows in the tree with state excluded (SCAN-3), size 0, and the rule on hover. .git rule → .git folders size 0, excluded
EXCL-3 if_contains_file: the rule matches a folder when one of its direct files matches the pattern instead of the folder's own name (a marker such as .nobackup). rule .nobackup with flag → folders holding that file excluded
EXCL-4 Default rules: one, .snapshot (fixed, name); users may edit or remove it. fresh install → 1 rule
EXCL-5 "Exclude folder" in the item menu adds a fixed, full_path rule for it and marks it excluded at once, subtracting its size from all ancestors without a rescan. exclude a 5 GiB folder → root total −5 GiB
EXCL-6 Rule changes in settings apply to the next scan or rescan; an invalid regex cannot be saved. save regex ( → refused
EXCL-7 A one-time --exclude <pattern> on the command line adds a wildcard, name rule for that run only. run with --exclude cache → cache folders excluded, not saved

Out of scope

  • Excluding individual files by pattern.

Decisions

  • Exclusions show as zero-size entries, not hidden ones, so the user sees why numbers are lower.

Rescan and export

Status: Draft · Prefix: EXP

Purpose

Refreshing parts of a scan, and saving scans to look at later or on another machine.

Requirements

ID Requirement Verified by
EXP-1 Scan file: gzip-compressed JSON Lines. Line 1: {format: "disk-usage-scan", version: 1, root, scanned_at, os, options: {cross_filesystems, split_hard_links, excludes[]}}; then one line per item in depth-first order: {path, type, bytes, allocated, links, mtime, state?, flags?, owner?, group?, mode?} with path relative to root and mtime UTC ISO 8601. save, gunzip → line 1 has format and version
EXP-2 "Save scan" (Ctrl+S) writes the current tree, or a selected subtree, to a file the user picks (default name <root name>-<YYYY-MM-DD>.scan.gz); folders still being read are saved with state aborted. save during scan → aborted folders in file
EXP-3 "Open scan" loads a scan file into the tree, treemap and statistics as if scanned; the title shows the file name and scanned_at. Cleanups stay disabled (CLN-12) until a rescan from disk. open file → tree shows, delete disabled
EXP-4 A file with another format, a newer major version, or a corrupt line is refused with the line number; nothing partial is shown. truncated file → refused, "line 1234"
EXP-5 Rescan the selected folder (Ctrl+R) or everything (F5): reads that subtree afresh, replaces it in place, updates ancestors' roll-ups, and keeps expansion and selection for paths that still exist. rescan after adding 1 GiB → folder +1 GiB, still expanded
EXP-6 A rescan of a folder that no longer exists removes it from the tree and updates ancestors. delete folder outside the app, rescan it → removed
EXP-7 Any results or statistics list exports as CSV (UTF-8, comma, header row, sizes in bytes, times UTC ISO 8601). export largest files → CSV with 200 rows + header
EXP-8 Saving and reopening a scan of 1,000,000 items each take ≤ 10 s and the file is ≤ 60 MiB. manual: 1 M-item scan

Out of scope

  • Reading other tools' scan formats; a separate headless scanner program.
  • Automatic use of scan files found inside scanned folders.

Decisions

  • JSON Lines in gzip: stream-friendly, readable by any stack, and greppable after decompressing; the source uses its own line-based text format.
  • Opened scans are read-only for cleanups: their paths may not exist on this machine or may have changed.

File types

Status: Draft · Prefix: TYPE

Purpose

Grouping files into categories by name, and showing how much space each type and each year takes.

Requirements

ID Requirement Verified by
TYPE-1 A category is {name, colour, patterns[]}; a pattern is a suffix pattern (*.jpg), an exact file name (core) or a wildcard (*.so.*), each with its own case_sensitive (default off). category "images" with *.jpg → A.JPG matches
TYPE-2 Matching order: exact names first, then the longest matching suffix, then wildcards in category order; the first hit wins; no hit → other. a.tar.gz: *.tar.gz (archives) beats *.gz (compressed)
TYPE-3 Default categories (editable, removable, re-addable from defaults): junk, archives, compressed, images, raw_images, videos, music, documents, source_code, build_output, libraries, executables, disk_images, other, each with a distinct colour and common suffixes. fresh install → 14 categories listed
TYPE-4 Type statistics for the current subtree: one row per category with file count, total_size and % of the subtree; each expands to its suffixes (or names) with the same columns; files with no suffix group as no_extension. Sorted by size, descending. subtree with 3 .png (6 MiB) → images row 6 MiB, expands to .png
TYPE-5 Suffixes not in any category are listed under other as their own rows (top 50 by size; the rest summed as one row). 80 unknown suffixes → 50 rows + 1 rest row
TYPE-6 Locate type: opening a suffix row lists every folder holding such files with their count and total size; opening a folder there selects those files in the tree (TREE-8), ready for a cleanup. open .iso row → folders listed; open one → its .iso files selected
TYPE-7 Age statistics for the current subtree: one row per modified year with file count, total size and % of each; for the current and previous year, rows also per month. Opening a row lists those files (DISC-1). files from 2021 and 2024 → 2 year rows
TYPE-8 Statistics recompute when their subtree changes (rescan, cleanup) and are not available while that subtree's scan is running. delete a .png → images row drops
TYPE-9 Categories are edited in settings: add, rename, recolour, reorder, edit patterns, delete (with confirmation when it has patterns); changes recolour the treemap at once. recolour videos → map tiles change on save

Out of scope

  • Detecting type by file content (magic bytes); OS content-type databases.
  • Size distribution histograms and percentiles.

Decisions

  • Type by name only: reading content of millions of files would make the scan far slower, and most space hogs have telling suffixes.
  • Category ids are generic; their display names are translated.

Scan

Status: Draft · Prefix: SCAN

Purpose

Reading a folder or drive into an in-memory tree, fast, visibly and safely.

Requirements

ID Requirement Verified by
SCAN-1 A scan starts from a folder chosen in a picker, typed as a path, passed on the command line, picked from recent folders (last 10), or from the volumes overview (SCAN-11). A path that does not exist or is not a folder is refused with a message. /nope → refused, no scan
SCAN-2 The scan walks every entry below the root without following symbolic links or junctions; each entry gets a type: file, dir, symlink, block_device, char_device, fifo, socket, other. link to /usr inside root → listed as symlink, not entered
SCAN-3 Each folder has a read state: queued, reading, finished, aborted (scan stopped), error (could not be listed), excluded (EXCL), not_crossed (mount point not entered, SCAN-7), duplicate (SCAN-9). A folder's subtree counts as complete only when all its folders are finished, excluded, not_crossed or duplicate. stop mid-scan → some folders aborted, root incomplete
SCAN-4 Results appear while the scan runs: the tree and totals update at least every update_interval_ms (default 500); the treemap is drawn when the scan finishes (MAP-1). manual: large scan shows growing totals
SCAN-5 Status shows elapsed time, folders read, items found and the folder being read; Stop (Esc) ends the scan within 1 s and keeps everything read so far. Esc → scan ends, partial tree kept
SCAN-6 A folder that cannot be listed (permission, I/O error) gets state error, keeps size 0, shows a warning mark, and is counted in a "N folders unreadable" notice that opens a list of their paths and reasons. chmod 000 folder → error, notice "1 folder unreadable"
SCAN-7 cross_filesystems (default off): a mount point below the root on another volume is shown with state not_crossed, size 0, and a mount mark; "continue scanning here" scans just that one. external drive mounted under root → not_crossed
SCAN-8 Even with cross_filesystems on, virtual or system filesystems (process, device, kernel tables) and network filesystems are not entered unless scanned explicitly; sub-volumes of the root's own volume (same device) are entered as part of it. cross on, /proc below root → not_crossed
SCAN-9 A folder reached twice through bind mounts, firmlinks or similar (same device and file id as a folder already read) is scanned once; later paths get state duplicate and size 0. bind-mount a at b inside root → b duplicate
SCAN-10 Reading uses at most scan_threads (default 4) concurrent folder reads and keeps the interface responsive throughout. manual: scroll tree during a scan, no freeze
SCAN-11 Volumes overview: every mounted volume with mount path, device or label, filesystem type, total, used, reserved, free and free %; virtual and system mounts hidden by default with a toggle; opening a row scans it. open overview → system disk listed with free %
SCAN-12 Scanning 1,000,000 files on a local SSD finishes within 2 × the time the OS's own disk-usage command needs on a warm cache, using ≤ 300 MiB of memory for the tree. manual: 1 M-file tree, compare times, read memory

Out of scope

  • Network-transparent scanning of remote hosts (scan files made elsewhere open via EXP).
  • Package-manager views (which files belong to installed packages).
  • Live watching for changes after the scan.

Decisions

  • Mount points are not crossed by default so a drive's numbers are not inflated by other volumes mounted inside it.
  • Duplicate folders (SCAN-9) count once; the source handles bind mounts by mount table only, this rule covers firmlinks and junction-like cases on every OS.

Settings

Status: Draft · Prefix: SET

Purpose

Preferences, their defaults, keyboard shortcuts and the command line.

Requirements

ID Requirement Verified by
SET-1 Settings live in one local file per user and apply at once; defaults: cross_filesystems off, split_hard_links on, update_interval_ms 500, scan_threads 4, show_folder_borders off, min_tile_px 3, shading cushion, treemap_visible on, recent_folders (last 10), tree columns and sort (TREE-2, TREE-4), categories (TYPE-3), exclude rules (EXCL-4), cleanup actions (CLN-2). delete settings file → app starts with these defaults
SET-2 "Reset to defaults" per settings page restores that page's defaults after a confirmation. reset cleanups → user actions removed after confirm
SET-3 Window size, position, split position and open statistics windows are restored on next start. resize, restart → same size
SET-4 Default shortcuts: open folder Ctrl+O, rescan all F5, rescan selected Ctrl+R, stop Esc, find Ctrl+F, copy path Ctrl+C, trash Delete, delete permanently Shift+Delete, treemap toggle F9, zoom Ctrl+Plus / Ctrl+Minus / Ctrl+0, go up Alt+Up, save scan Ctrl+S; on macOS Cmd replaces Ctrl. User cleanup actions may get their own shortcut; a clash with an existing one is refused. assign F5 to an action → refused
SET-5 Command line: <app> [folder] scans it; --open <scan-file> opens a saved scan; --exclude <pattern> (EXCL-7); --cross-filesystems; --version; an unknown option prints usage and exits with code 2. --bogus → usage, exit 2
SET-6 "Clear recent folders" empties the list at once. clear → list empty
SET-7 The app needs no account, works fully offline and sends nothing over the network: no update checks, analytics or crash uploads. manual: full session with network blocked, watch traffic
SET-8 Interface text is translatable; numbers, dates and sizes follow the OS locale, keeping binary units (SIZE-9). German locale → 34,4 MiB

Out of scope

  • Themes beyond following the OS light/dark setting.
  • Sync of settings between machines.

Decisions

  • No @specfork/privacy requirement: the app stores no personal records, only settings, recent folders (SET-6 clears them) and scan files the user saves deliberately.

Sizes

Status: Draft · Prefix: SIZE

Purpose

What "size" means for each item and folder, so numbers match real disk use.

Requirements

ID Requirement Verified by
SIZE-1 Each item has bytes (apparent length from the filesystem) and allocated (space the filesystem reports as used for it). Folders and links count their own entry's size too. 1-byte file on 4 KiB-block disk → bytes 1, allocated 4 KiB
SIZE-2 An item's size (the default measure everywhere) is bytes, except for sparse files (SIZE-4), whose size is allocated. normal 10 MiB file → size 10 MiB
SIZE-3 A file with links > 1 hard links counts size / links and allocated / links at each path, so the paths together count it once, whether or not they are all inside the scan. With split_hard_links (default on) turned off, every path counts the full size. 1 GiB file, 2 links, both scanned → total 1 GiB
SIZE-4 A file is sparse when allocated + 64 KiB < bytes; it is flagged sparse. 1 GiB file with 1 MiB written → sparse, size ≈ 1 MiB
SIZE-5 Files whose content is not stored locally (cloud placeholders, offline files) are flagged offline and have allocated 0 and size 0; their bytes still shows. 2 GiB cloud-only file → size 0, offline
SIZE-6 Folder roll-ups: total_size, total_allocated, total_items, total_files, total_folders sum the subtree (including the folder's own entry); latest_mtime is the newest modified time in the subtree, oldest_mtime the oldest file time. folder with files from 2019 and 2024 → oldest 2019, latest 2024
SIZE-7 percent of an item = its total_size ÷ its parent's total_size × 100, one decimal; a parent of total 0 gives children blank percent. 3 MiB in 4 MiB parent → 75.0
SIZE-8 Roll-ups update incrementally during the scan, after rescans and after cleanups; a folder whose subtree is incomplete (SCAN-3) shows its totals with a ≥ mark. stop scan → partial folders show ≥
SIZE-9 Sizes display with binary units B, KiB, MiB, GiB, TiB, PiB, three significant digits (34.4 MiB); the exact byte count shows on hover and in item details. 36,116,381 B → 34.4 MiB, hover shows exact
SIZE-10 Item details for the current item: path, type, size, bytes, allocated, links, sparse/offline flags, modified time, owner and group and permissions where the OS has them (blank otherwise), and for folders the roll-ups of SIZE-6. select a file → details show all fields

Out of scope

  • Filesystem-level compression or deduplication savings, snapshots and copy-on-write sharing; these explain why scan totals and a volume's "used" can differ, which the volumes overview (SCAN-11) helps compare.

Decisions

  • Hard links are split per link (SIZE-3) so each path's share is stable whatever the scan root; the source does the same.
  • The sparse threshold of 64 KiB avoids flagging ordinary files whose last block is partly used.
  • offline is added for cloud-synced folders on Windows and macOS, which the source does not handle.

Size tree

Status: Draft · Prefix: TREE

Purpose

The main list: the scanned hierarchy with sizes, sorted so the biggest things come first.

Requirements

ID Requirement Verified by
TREE-1 The tree shows the scan root and its descendants, expandable per folder; the root starts expanded one level. scan → root's children visible
TREE-2 Columns: name (always first), percent_bar, percent, size, allocated, items, files, folders, latest_mtime, oldest_mtime, owner, group, permissions. The user can hide, show and reorder all but name; the layout persists. hide owner, restart → still hidden
TREE-3 When a folder has both files and subfolders, its direct non-folder items are grouped under a pseudo-child loose_files (shown as "files" in the user's language) with its own roll-ups, so they compare against subfolders; a folder with only files lists them directly. folder with 2 subfolders + 30 files → 3 children
TREE-4 Default sort: size descending at every level; clicking any column sorts by it, again reverses; ties break by name. Sorting applies to all levels and is kept across rescans. sort by latest_mtime → newest-changed first
TREE-5 percent_bar draws percent as a bar whose colour depends on tree depth, so nested levels are told apart. expand 3 levels → 3 bar colours
TREE-6 Items with state error, aborted, excluded, not_crossed, duplicate, or flags sparse, offline, show a distinct mark and the reason on hover. unreadable folder → warning mark, hover "permission denied"
TREE-7 Selection: click selects one, Ctrl+click toggles, Shift+click selects a range; the status line shows the count and summed total_size of selected items, without double-counting items inside selected folders. select folder + a file inside it → sum = folder size
TREE-8 Selection and current item sync with the treemap both ways (MAP-7); selecting from the treemap expands the tree down to the item and scrolls to it. click tile → tree expands to that file
TREE-9 Navigation: go up one level (Alt+Up), go to the root (Alt+Home), a breadcrumb path for the current item with clickable parts, and "expand to level" 0–9 that opens every folder down to that depth and closes the rest. expand to level 2 → depth ≤ 2 open
TREE-10 Copy path (Ctrl+C) puts the full paths of the selected items on the clipboard, one per line; "open containing folder" shows the item in the OS file manager. select 2 → 2 lines
TREE-11 The context menu on items offers: rescan (EXP-5), cleanup actions that apply (CLN-1), exclude folder (EXCL-5), copy path, continue scanning here (for not_crossed), details. right-click mount point → "continue scanning here"
TREE-12 Expanding a folder of 100,000 direct children shows it within 1 s and sorting it within 1 s. manual: generated folder of 100,000 files

Out of scope

  • Bookmarks of favourite folders.
  • Editing names or moving items by drag and drop.

Decisions

  • Grouping loose files (TREE-3) is shown in both tree and treemap so a folder's own files are one comparable block.

Treemap

Status: Draft · Prefix: MAP

Purpose

A picture of the scanned tree where every file is a rectangle whose area is its size.

Requirements

ID Requirement Verified by
MAP-1 The treemap shows the subtree of the current zoom root (default the scan root); it is built when a scan or rescan finishes and rebuilt after cleanups, zoom and window resizes (debounced 200 ms). During a scan it shows a progress placeholder. resize window → map redraws once after resize ends
MAP-2 Layout is squarified: each folder's area is split among its children in size order so tiles stay close to square; tile area is proportional to total_size (SIZE-6). folder of 1 GiB + 3 GiB children → tiles 1 : 3 by area
MAP-3 Only files (and loose_files groups, TREE-3) are painted as tiles; folders show as nesting, with optional 1-px borders when show_folder_borders (default off). Items of size 0 get no tile. empty file → no tile
MAP-4 A tile whose longer side is under min_tile_px (default 3) is not drawn; its area is painted in its parent's colour. 100,000 tiny files → no sub-3 px tiles
MAP-5 Tile colour = the file's category colour (TYPE-1); uncategorised files use the other colour. .mp4 tile in the videos colour
MAP-6 Shading: cushion (default; each tile lit like a soft bump so tile edges are visible) or flat (solid colours with 1-px gaps). switch to flat → no gradients
MAP-7 Click selects a tile and makes it current; Ctrl+click toggles it in the selection; the current item has a strong outline, other selected items a lighter one; changes sync to the tree (TREE-8). Ctrl+click 2 tiles → both outlined, both selected in tree
MAP-8 Hovering a tile shows its path and size in the status line within 100 ms. manual: hover
MAP-9 Highlight ancestors: Shift+click (or middle click) outlines every ancestor folder of the clicked tile and dims the rest of the map; the same action again clears it. Shift+click file → its folders outlined
MAP-10 Zoom in (Ctrl+Plus, double-click, wheel up) makes the folder one level below the zoom root on the path to the current item the new zoom root; zoom out (Ctrl+Minus, wheel down) goes up one level; reset (Ctrl+0) returns to the scan root. double-click a deep tile 3 times → 3 levels in
MAP-11 Show or hide the treemap (F9); the split between tree and treemap is draggable and persists. F9 → map hidden; restart → still hidden
MAP-12 Building the map for 1,000,000 files on a 1920 × 1080 area takes ≤ 1 s on a mid-range laptop. manual: time redraw after resize

Out of scope

  • 3-D or radial (sunburst) charts; exporting the map as an image.

Decisions

  • The map draws after the scan, not during, so constantly moving tiles never distract or cost time.

From Specfork/disk-usage at 4db4090, licence CC-BY-4.0.