The cache-cleaner project consists of three cross-platform Go CLI tools designed to help developers reclaim disk space by identifying and cleaning various types of cache directories and developer cruft. Each tool serves a specific purpose and can be used independently or together.
- Safety first (no direct deletions where possible, use official tool commands)
- Transparent dry-run by default
- Cross-platform support (macOS, Linux, Windows WSL)
- Extensible via YAML configuration
- Transparent size reporting
- Selective filtering for targeted operations
- JSON output for automation/CI integration
A safe, config-driven Go CLI for macOS that frees disk space using official tool commands (Docker, npm/yarn/pnpm, Go, Maven, Brew, and many more) instead of deleting files directly.
- Safety first (no direct deletions)
- Transparent dry-run by default
- Extensible via YAML
- Transparent size reporting
- Target filtering for selective operations
- Intelligent tool requirement checking
- Installation guidance for missing tools
--initwrites starter config to~/.config/mac-cache-cleaner/config.yaml--forceforces overwrite of existing config when used with--init--configspecifies path to YAML config (defaults to~/.config/mac-cache-cleaner/config.yaml)--cleanexecutes cleanup commands (default: dry-run mode)--targetsfilters targets to scan/clean (comma-separated or "all")--detailsshows detailed per-directory information--jsonoutputs structured JSON for automation/CI--list-targetslists all available targets in the config--docker-pruneinjects Docker prune commands at runtime--check-toolschecks if required tools are installed and exits (can be combined with--targets)
version: 1
options:
dockerPruneByDefault: false
targets:
- name: docker
enabled: true
notes: "Report Docker.raw size; optionally run prunes."
paths: ["~/Library/Caches/docker/*", ...] # measured for size
cmds: [["docker", "builder", "prune", "-af"], ...] # executed when --clean
tools: # required tools for this target
- name: docker
version: "24.0" # optional: minimum version
installCmd: "brew install --cask docker" # installation command
installNotes: "Optional installation notes"
checkPath: "~/.docker/config" # optional: check specific file path instead of PATH- docker - Docker caches and images
- brew - Homebrew packages and caches
- npm - npm cache
- yarn - Global Yarn cache
- pnpm - pnpm store and cache
- node-versions - Node version managers (nvm, volta)
- expo - Expo and React Native caches
- go - Go build & module caches
- rust - Rust registry and build caches
- python - pip, pipenv, and poetry caches
- conda - Conda package and cache cleanup
- maven - Maven local repository
- gradle - Gradle build caches and wrappers
- xcode - Xcode build artifacts and caches
- ruby - Ruby and Bundler caches
- php - Composer PHP cache
- dotnet - .NET SDK and NuGet caches
- vscode - VS Code caches and logs
- jetbrains - JetBrains IDE caches (IntelliJ, PyCharm, WebStorm, etc.)
- build-tools - Compiler and build caches (ccache, bazel, Xcode)
- chrome - Chrome caches (informational only, no CLI)
- macos - macOS system caches (advanced users only, disabled by default)
- flutter - Flutter and Dart caches
- android - Android SDK and emulator caches
- android-studio - Android Studio IDE caches
- terraform - Terraform plugin cache
- packer - Packer plugins directory
- ollama - Ollama models and cache (uses official prune)
- home-cache - Top-level ~/.cache subdirectories (informational only)
- pyenv - Pyenv installed versions and downloads (informational)
- rustup - Rustup toolchains and targets (informational)
- vscode-extensions - VS Code extensions and data under ~/.vscode (informational)
- rvm - RVM installed rubies and archives (informational/has cleanup)
- dropbox - Dropbox metadata and state (informational only)
- cursor - Cursor editor state and cache (informational)
- Supports
~for home directory - Expands environment variables (
$VAR) - Supports
$(brew --cache)expansion - Glob patterns for flexible matching
- Command substitutions are whitelist-only for safety; currently only
brew --cacheis supported. Other substitutions (e.g.,$(docker ...)) are rejected.
- Size measurement in bytes with human-readable output
- Item count tracking
- Latest modification time per path
- Command availability detection
- JSON output for programmatic processing
- Warnings for glob errors
- Before/after comparison when
--cleanis used - Total space freed calculation
- Docker usage is measured via
docker system df(JSON/template parsing), not by readingDocker.rawdirectly
- Dry-run by default - Reports sizes without making changes
- Tool requirement checking - Checks if required tools are installed before running commands
- Size scanning - Measures all configured paths before any cleanup
- Command execution - Runs official tool CLI commands when
--cleanis set - Target filtering - Process specific targets with
--targetsflag - Docker prune injection - Adds prune commands when configured/flagged
- Auto-confirm prompts - Automatically sends 'y' to interactive prompts when running commands
- Re-scan after cleanup - Shows before/after sizes and freed space when
--cleanis used
- Before executing commands, the app checks if required tools (specified in
toolsarray) are installed - If a tool is missing, a warning is shown with installation guidance
- Installation commands default to
brew installif Homebrew is available - Version checking: When a version is specified, the app performs a basic
--versioncontains check to verify presence; it does not perform full semantic version comparison - Commands are marked as "not found" when their prerequisite tools are missing
- Custom path checking: If
checkPathis specified, the app checks for the existence of that file instead of using PATH lookup - Tool status is displayed with ✓ for installed tools and ✗ for missing tools
The --check-tools flag provides a quick way to verify tool requirements:
- Shows ✓ for installed tools with version info (if available)
- Shows ✗ for missing tools with installation commands
- Lists which targets require each tool
- Respects
--targetsflag to check tools for specific targets only - Exits with status 0 (all OK) or 1 (some missing) - useful for CI/CD scripts
The --list-targets flag shows all available targets:
- Lists all targets from the config file
- Shows [ENABLED] or [DISABLED] status for each target
- Displays notes for each target
- Useful for discovering available cleanup options
- When
--jsonis provided, the app outputs the initial scan results (including totals and warnings) and exits. Cleanup is not performed even if--cleanis also set.
- Windows/Linux paths (future)
- Direct file deletion (unsafe)
- Chrome deletion automation (no stable CLI)
- Interactive prompts (auto-confirmed with 'y')
- TUI interface
- Homebrew formula
- Scheduled runs
- CI/CD integration examples
- Windows/Linux support
A cross-platform Go CLI tool that scans source code directories to find and optionally delete local project cache directories (like node_modules, build, dist, .venv, etc.) across multiple programming languages.
- Cross-platform support (macOS, Linux, Windows WSL)
- Multi-language cache detection
- Configurable scanning depth and patterns
- Safe deletion with confirmation prompts
- Detailed reporting by language and project
--initcreates starter config file and exits--forceforces overwrite of existing config (use with --init)--config PATHspecifies path to YAML config (default:~/.config/dev-cache/config.yaml)--scan PATHdirectory to scan (overrides config default)--depth Nmax scan depth (overrides config default, 0 = use config)--languages LISTcomma-separated list of languages to scan (e.g.,node,python,go)--cleandeletes found cache directories--yesskips confirmation prompt for cleanup--jsonoutputs results as JSON--detailsshows detailed per-project breakdown
version: 1
options:
defaultScanPath: ~/src
maxDepth: 1 # How many levels deep to scan
languages:
- name: node
enabled: true
patterns:
- node_modules
- .npm
- .yarn
- .pnpm-store
- name: python
enabled: true
patterns:
- .venv
- venv
- __pycache__
- .pytest_cache
- .mypy_cache- Node.js:
node_modules,.npm,.yarn,.pnpm-store - Python:
.venv,venv,__pycache__,.pytest_cache,.mypy_cache,.tox - Go:
vendor - Rust:
target - Java/Kotlin:
target,.gradle,build - Next.js:
.next,dist,build,out,.cache - Vue/Nuxt:
.nuxt,dist,build,out,.cache,.parcel-cache - PHP:
vendor - Ruby:
vendor/bundle - C#/.NET:
bin,obj - C/C++:
build,cmake-build-*(wildcard supported) - Flutter/Dart:
.dart_tool
- Exact match:
node_modulesmatches onlynode_modules - Wildcard prefix:
cmake-build-*matchescmake-build-debug,cmake-build-release, etc.
- Summary mode (default): Groups findings by language with totals
- Detailed mode (
--details): Shows each cache directory found with project path, cache type, language, size, and item count - JSON output for programmatic processing
- Size measurement in bytes with human-readable output
- Item count tracking per directory
- Dry-run by default - Reports cache directories without deleting files
- Recursive scanning - Walks through directory tree looking for cache patterns
- Language filtering - Can target specific languages via
--languagesflag - Depth control - Configurable maximum scan depth to limit traversal
- Safe deletion - Requires explicit
--cleanflag with confirmation prompt (unless--yesis used) - Error handling - Deletion errors are logged and reported, but don't stop the process
- macOS: Native support (amd64 and arm64)
- Linux: Full support (amd64 and arm64)
- Windows WSL: Full support through Linux compatibility
All paths use filepath.Join() for cross-platform compatibility. Home directory expansion (~) works on all platforms via os.UserHomeDir().
- Dry-run by default: The tool never deletes files unless
--cleanis explicitly provided - Confirmation prompt: When using
--clean, you must confirm the deletion (unless--yesis used) - Shows what will be deleted: The tool displays all findings before asking for confirmation
- Error handling: Deletion errors are logged and reported, but don't stop the process
- Integration with version control (skip if in .gitignore)
- Whitelist/blacklist per project
- Age-based filtering (delete only old caches)
- Backup before deletion
- TUI interface
A cross-platform Go CLI tool that scans directories for .git directories, reports their sizes, and optionally optimizes repositories using git gc.
- Cross-platform support (macOS, Linux, Windows WSL)
- Efficient repository discovery
- Safe optimization using official Git commands
- Clear reporting of disk savings
--scan PATHdirectory to scan for .git directories (required)--cleanrunsgit gcin each repository and shows disk savings
- Table output showing repository paths and
.gitdirectory sizes - Item count tracking per repository
- Before/after comparison when
--cleanis used - Total disk savings calculation with percentage
- Recursive scanning - Walks through directory tree looking for
.gitdirectories - Size calculation - Calculates total size by walking through all files in each
.gitdirectory - Optimization (with
--clean) - Runsgit gcin each repository's parent directory - Rescan after optimization - After optimization, rescans to calculate disk space saved
- macOS: Native support (amd64 and arm64)
- Linux: Full support (amd64 and arm64)
- Windows WSL: Full support through Linux compatibility
All paths use filepath.Join() for cross-platform compatibility. Home directory expansion (~) works on all platforms via os.UserHomeDir().
- Go 1.21 or later
- Git must be installed and available in PATH (for
--cleanfunctionality)
- Uses official
git gccommand for optimization (safe) - Only optimizes Git repositories, never deletes them
- Shows clear before/after comparison
- Configuration file support for default scan paths
- Filtering by repository size (only optimize large repos)
- Filtering by last activity date
- Integration with git worktree detection
- Support for Git LFS optimization
- JSON output mode
All three apps support:
- macOS (amd64 and arm64)
- Linux (amd64 and arm64)
- Windows WSL (via Linux compatibility)
- Go 1.21+ required
- Consistent Makefile structure
- Pre-commit hooks support
- Test coverage tracking
- Linting with golangci-lint
- Formatting with gofmt
- Human-readable table output (default)
- JSON output for automation (
--jsonflag) - Detailed mode for granular information (
--detailsflag where applicable)
- Dry-run by default
- Explicit confirmation required for destructive operations
- Clear reporting of what will be affected
- Error handling that doesn't silently fail
| Target | Description |
|---|---|
help |
Show all available make targets |
all |
Build all applications (default) |
dev-cache |
Build dev-cache application only |
git-cleaner |
Build git-cleaner application only |
mac-cache-cleaner |
Build mac-cache-cleaner application only |
build |
Build all applications |
test |
Run tests in all applications |
fmt |
Format code in all applications |
lint |
Lint all applications |
vet |
Run go vet on all applications |
goreleaser-check |
Validate GoReleaser configuration |
release-dry-run |
Test GoReleaser without building/publishing |
release-snapshot |
Build snapshot release locally (no git tag required) |
clean |
Clean all applications and build artifacts |
Before creating an actual release, you can test the entire build process:
# Verify GoReleaser configuration
make goreleaser-check
# Build a local snapshot (no git tag required)
make release-snapshot
# Artifacts will be in ./dist/
# - Individual binaries: dev-cache-darwin-amd64, etc.
# - Homebrew tarball: cache-cleaner-VERSION-darwin-{amd64,arm64}.tar.gz
# - Homebrew formula: dist/homebrew/Formula/cache-cleaner.rb-
Ensure all changes are committed and pushed
git status git add . git commit -m "Prepare release v1.0.0" git push origin main
-
Create and push a version tag
git tag v1.0.0 git push origin v1.0.0
-
GitHub Actions automatically:
- Validates GoReleaser configuration
- Builds all 6 binaries (3 apps × 2 architectures)
- Creates GitHub release with:
- Individual binaries for direct download
- Combined tarballs for Homebrew
- Checksums for verification
- Auto-generated changelog
- Updates Homebrew formula in
markcallen/homebrew-cache-cleaner - Commits formula changes with proper checksums
-
Verify the release:
- Check GitHub Releases: https://github.com/markcallen/cache-cleaner/releases
- Check Homebrew formula: https://github.com/markcallen/homebrew-cache-cleaner/tree/main/Formula
- Test installation:
brew upgrade cache-cleaner
Formula not found after release:
If brew install cache-cleaner fails with "No available formula":
-
Check that the formula was pushed to the tap:
- Visit: https://github.com/markcallen/homebrew-cache-cleaner/tree/main/Formula
- You should see
cache-cleaner.rb
-
Update Homebrew and retry:
brew update brew tap markcallen/cache-cleaner brew install cache-cleaner
Token errors in GitHub Actions:
If you see authentication errors in the release workflow:
-
Verify the secret exists:
- Go to: https://github.com/markcallen/cache-cleaner/settings/secrets/actions
- Look for
HOMEBREW_TAP_GITHUB_TOKEN
-
Verify the token has the correct permissions:
- It needs
public_reposcope - It must not be expired
- It needs
-
Regenerate the token if needed and update the secret
Checksum mismatches:
If users report checksum errors:
- The formula might be out of sync with the release
- Re-run the release workflow or manually update checksums
- Check that GoReleaser successfully updated the tap
- Verify the formula at: https://github.com/markcallen/homebrew-cache-cleaner/tree/main/Formula
The project uses GoReleaser for automated releases with the following configuration:
Builds:
- 3 separate builds (one per application)
- Each build specifies
dirto point to the app directory - Main file is
./main.gorelative to the app directory - CGO is disabled for static binaries
- Targets darwin/amd64 and darwin/arm64
Archives:
- Individual binaries for direct download (format:
{app}-darwin-{arch}) - Combined tarball for Homebrew (format:
cache-cleaner-{version}-darwin-{arch}.tar.gz) - The tarball includes all three binaries
Homebrew Integration:
- Automatically generates formula in
markcallen/homebrew-cache-cleaner - Formula installs all three binaries
- Includes caveats with quick start instructions
- Includes version tests for all binaries
Changelog:
- Auto-generated from Git commits
- Grouped by type (Features, Bug Fixes, Performance, etc.)
- Excludes internal changes (docs, tests, ci)
Primary: Homebrew (Recommended)
brew tap markcallen/cache-cleaner
brew install cache-cleanerBenefits:
- Automatic PATH configuration
- Easy updates via
brew upgrade - No sudo required
- Standard for macOS users
- Handles dependencies automatically
Secondary: Direct Download
# Via install script (requires -b flag)
curl -sSfL https://raw.githubusercontent.com/markcallen/cache-cleaner/HEAD/install.sh | sh -s -- -b $HOME/.local/bin
# Or download binaries directly from GitHub Releases
# https://github.com/markcallen/cache-cleaner/releasesinstall.sh Behavior:
- Requires
-bflag to specify installation directory - Errors if Homebrew is detected (recommends using
brew install) - Downloads pre-built binaries from GitHub Releases
- Supports version selection
- Supports individual app installation with
-aflag
To enable automated Homebrew releases:
-
Create tap repository:
- Go to: https://github.com/new
- Repository name:
homebrew-cache-cleaner(must start withhomebrew-) - Description: "Homebrew tap for cache-cleaner tools"
- Visibility: Public
- Initialize with README
- After creation, clone and create
Formula/directory:git clone git@github.com:markcallen/homebrew-cache-cleaner.git cd homebrew-cache-cleaner mkdir Formula git add Formula git commit -m "Add Formula directory" git push origin main
-
Configure GitHub token:
- Go to: https://github.com/settings/tokens/new
- Note: "GoReleaser Homebrew Tap"
- Expiration: Choose appropriate expiration
- Scopes: Select
public_repo(allows read/write to public repositories) - Click "Generate token"
- IMPORTANT: Copy the token immediately (you won't see it again)
- Add as repository secret in the cache-cleaner repository:
- Go to: https://github.com/markcallen/cache-cleaner/settings/secrets/actions
- Click "New repository secret"
- Name:
HOMEBREW_TAP_GITHUB_TOKEN - Value: Paste the token you copied
- Click "Add secret"
-
Verify workflow:
- GitHub Actions workflow is in
.github/workflows/release.yml - Uses
goreleaser/goreleaser-action@v6 - Requires Go 1.22.x
- GitHub Actions workflow is in
-
Test after first release:
# Add the tap and install brew tap markcallen/cache-cleaner brew install cache-cleaner --verbose # Verify all binaries are installed which dev-cache which git-cleaner which mac-cache-cleaner # Test functionality dev-cache --version git-cleaner --version mac-cache-cleaner --version # Audit the formula brew audit --strict --online cache-cleaner # Test uninstall (optional) brew uninstall cache-cleaner brew untap markcallen/cache-cleaner
Once the formula is stable and has users, the project can be submitted to homebrew-core for wider distribution:
- Review the Homebrew contribution guidelines
- Ensure the formula passes
brew audit --strict --online - Submit a PR to Homebrew/homebrew-core
- After acceptance, users can install with just:
(no tap required)
brew install cache-cleaner