How Mole's Caching System Speeds Up Disk Analysis

Mole's caching system stores filesystem scan results in ~/.cache/mole using xxHash-64 keyed binary files, validating them for up to 7 days while detecting directory modifications to avoid unnecessary rescans.

Mole is an open-source disk analysis tool by tw93/Mole that builds detailed views of filesystem trees, large files, and storage totals. Because full directory walks can be expensive on large drives, Mole's caching system persists per-directory results and reuses them when possible. The implementation lives primarily in cmd/analyze/cache.go, with integration logic spread across cmd/analyze/scanner.go and cmd/analyze/main.go.

Cache Storage Location and Structure

Where Mole Stores Cache Files

Mole creates a dedicated cache directory at ~/.cache/mole on first run. The getCacheDir() function in cmd/analyze/cache.go (lines 65-71) ensures this directory exists before any write operations.

Each scanned path receives its own cache file named <hash>.cache, where the hash is a xxHash-64 of the absolute path string. The getCachePath() function (lines 78-84) generates these filenames consistently.

Additionally, Mole maintains an overview.json file in the same directory for quick size lookups of top-level folders. This is managed separately from the per-path caches.

The Cache Entry Data Structure

Each .cache file stores a serialized cacheEntry struct defined in cmd/analyze/cache.go:

type cacheEntry struct {
    Entries    []dirEntry   // all scanned directories
    LargeFiles []fileEntry  // files > threshold
    TotalSize  int64        // bytes of everything under the path
    TotalFiles int64        // file count
    ModTime    time.Time    // modification time of the directory at scan time
    ScanTime   time.Time    // when the scan finished
}

The saveCacheToDisk() function (lines 57-85) writes this structure using Go's gob encoding for fast binary serialization.

Cache Validation and Expiration Logic

Mole's caching system implements a multi-layered validation strategy in loadCacheFromDisk() (lines 8-36) to balance performance with accuracy.

The 7-Day Age Limit

By default, any cache older than 7 days is automatically rejected, regardless of directory state. This hard limit prevents displaying stale data from long-obsolete scans. The check compares ScanTime against the current time, rejecting entries where scanAge > 7*24h.

Directory Modification Detection

If the cache is younger than 7 days, Mole checks whether the directory has changed since the scan. It compares the current directory ModTime against the ModTime stored in the cache entry.

If the current modification time is newer than the cached value, the cache is usually invalid.

Grace Windows and Reuse Policies

To prevent excessive invalidations from minor, rapid changes, Mole applies two configurable windows defined in cmd/analyze/constants.go (lines 20-21):

  • cacheModTimeGrace: A tolerance period for directory modifications. If the directory changed within this grace period, the cache remains valid.
  • cacheReuseWindow: If this is set and the scan age is within this window, Mole reuses the cache even if the directory modified time suggests change.

The validation logic in loadCacheFromDisk() implements this cascade:

if info.ModTime().After(entry.ModTime) {
    if cacheModTimeGrace <= 0 || info.ModTime().Sub(entry.ModTime) > cacheModTimeGrace {
        if cacheReuseWindow <= 0 || scanAge > cacheReuseWindow {
            return nil, fmt.Errorf("cache expired: directory modified")
        }
    }
}

Performance Optimizations

Stale Cache for Instant UI Rendering

When starting the TUI mode via runTUIMode() in cmd/analyze/main.go (line 66), Mole spawns prefetchOverviewCache() to load data immediately. The loadStaleCacheFromDisk() function (lines 38-55) implements a "stale-while-revalidate" pattern:

  • It ignores the strict 7-day age limit and modification checks
  • It only verifies the cache is younger than staleCacheTTL (approximately 5 seconds)
  • If valid, the UI renders instantly while a background scan refreshes the data

This ensures users see a directory tree immediately, even if it's slightly outdated, rather than waiting for a full filesystem walk.

Overview Snapshots for Quick Size Lookups

For the overview mode that lists top-level directories, Mole maintains a separate overview.json snapshot. The loadStoredOverviewSize() function (lines 6-11) checks this JSON map, which stores size and updated timestamps.

If the snapshot is younger than overviewCacheTTL (approximately 30 minutes), Mole returns the stored size without touching the per-path cache or scanning the directory. After a fresh scan completes, storeOverviewSize() (lines 15-30) automatically updates this snapshot.

How the Analyze Command Integrates Caching

The caching system is tightly integrated into the analysis workflow across three main components:

  1. Prefetched Loading: When runTUIMode() starts in cmd/analyze/main.go (lines 65-70), it immediately calls prefetchOverviewCache() to load any available cached data before the UI renders.

  2. Scan-Time Resolution: In cmd/analyze/scanner.go, the scanner first attempts loadCacheFromDisk(path) (lines 351-356).

    • Cache Hit: The UI populates instantly with the cached cacheEntry data.
    • Cache Miss: The scanner performs a full filesystem walk, then calls saveCacheToDisk() (lines 57-85) to persist the new results.
  3. Overview Updates: After a successful scan, the system calls storeOverviewSize() (lines 61-62) to update the overview.json snapshot, ensuring subsequent top-level listings remain fast.

Clearing and Invalidating the Cache

Users can clear Mole's caching system through several methods:

Manual deletion of the entire cache directory:

rm -rf "${HOME}/.cache/mole"

Using Mole's built-in purge command:

mo purge

This executes the bin/purge.sh script (lines 102-114), which specifically removes cache files while preserving the directory structure.

Update-triggered clearing: When running mo update or reinstalling Mole, the installation process ensures a clean cache directory to prevent version incompatibilities.

Summary

  • Mole's caching system stores disk analysis results in ~/.cache/mole using xxHash-64 keyed binary files encoded with Go's gob format.
  • Each cache entry contains the full directory tree, large file lists, totals, and modification timestamps, defined in the cacheEntry struct in cmd/analyze/cache.go.
  • Validation logic rejects caches older than 7 days or those where the directory has been modified outside the grace window, with configurable tolerance via cacheModTimeGrace and cacheReuseWindow.
  • Performance features include stale-cache loading for instant UI rendering (5-second tolerance) and an overview.json snapshot for 30-minute fast size lookups of top-level directories.
  • The analyze command integrates caching via loadCacheFromDisk() in cmd/analyze/scanner.go, falling back to full scans that automatically persist via saveCacheToDisk().
  • Users can invalidate caches manually, via mo purge, or through updates that clean the ~/.cache/mole directory.

Frequently Asked Questions

Where does Mole store its cache files?

Mole stores all cache files in the ~/.cache/mole directory. The getCacheDir() function in cmd/analyze/cache.go creates this directory automatically if it doesn't exist. Individual scan results are stored as <hash>.cache files where the hash is a xxHash-64 of the absolute path, while overview snapshots live in overview.json.

How long does Mole's cache remain valid?

By default, Mole's cache remains valid for up to 7 days. However, the cache also becomes invalid immediately if the directory's modification time changes outside the configured grace window (cacheModTimeGrace). Additionally, the overview snapshot used for quick size lookups expires after approximately 30 minutes (overviewCacheTTL), while stale caches used for instant UI rendering last only about 5 seconds (staleCacheTTL).

Can I force Mole to ignore the cache?

While there is no public command-line flag exposed in the current version, you can force Mole to ignore the cache by removing the specific cache file before running the analysis. Locate the cache file by computing the xxHash-64 of your target path, then delete ${HOME}/.cache/mole/<hash>.cache. Alternatively, running mo purge clears all caches, ensuring the next analysis performs a fresh scan.

What happens if I modify files while Mole is running?

If files are modified while Mole is running, the stale cache mechanism ensures the UI remains responsive. When the TUI launches, it first loads any available cache (even if slightly outdated) to render the initial view instantly. A background scan then refreshes the data asynchronously. For subsequent runs, the loadCacheFromDisk() function detects the directory modification via ModTime comparison and invalidates the cache unless the change falls within the grace window, ensuring you don't see stale data for long.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →