Skip to content

Latest commit

Β 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

flsweep 🧹⚑

The ultimate concurrent Flutter workspace cleaner and package syncer.

flsweep is a high-performance, cross-platform CLI tool written in pure Dart. It scans any workspace for Flutter projects, batch-runs flutter clean, deep-cleans stubborn native build artifacts, and immediately restores dependencies with flutter pub get β€” so your IDE symbols and indices come back instantly. Every byte recovered is measured and reported.

$ flsweep ~/dev --all --deep -c 8

  Flutter projects discovered: 12

  Sweeping 12 projects
  βœ“ shop_app               freed 1.21 GB
  βœ“ tracker                freed 312.4 MB
  βœ— legacy_client          flutter clean failed (exit 1): ...
  βœ“ portfolio              freed 890.7 MB
  ...

  Sweep summary
  βœ“ Freed 2.45 GB β€” 11 ok, 1 failed.

✨ Features

  • Parallel execution β€” a bounded async worker pool cleans up to --concurrent projects at once (default: 4).
  • Zero-break sync β€” flutter clean βž” flutter pub get run back-to-back per project, so every project stays buildable and IDE-friendly.
  • Deep clean (--deep) β€” wipes what flutter clean leaves behind: android/.gradle, ios/Pods, ios/Podfile.lock, and .dart_tool.
  • Exact disk metrics β€” recursive size calculation (B/KB/MB/GB) before and after cleaning; the summary reports precisely what was recovered.
  • Dual interface β€” an interactive multi-select checklist with live braille spinners, and a fully non-interactive headless mode for CI/CD and AI agents (--all --quiet).
  • Error isolation β€” one broken project never aborts the run. Failures are logged, the remaining projects keep processing, and the exit code signals the outcome to CI.
  • Instant startup β€” the recommended install is a standalone native executable: --help and --version respond in milliseconds, and no Dart SDK messages ever appear at runtime.

πŸ“¦ Installation

One-liner installer (recommended)

Install the latest prebuilt native binary for your OS and architecture β€” no Dart SDK required, no cloning needed:

curl -fsSL https://raw.githubusercontent.com/MotiurRahmanSany/flsweep/main/install.sh | bash

The script auto-detects Linux/macOS and x64/ARM, downloads the matching release artifact, and drops the binary on your PATH. Set FLSWEEP_INSTALL_DIR to install somewhere other than ~/.local/bin.

Download a release binary directly

Grab the latest flsweep from the Releases page, pick the archive for your platform, and put the binary on your PATH:

tar -xzf flsweep-<version>-linux-x64.tar.gz
sudo install -m 0755 flsweep /usr/local/bin/

Build from source (native executable)

Build once with any Dart SDK β‰₯ 3.0, then run without Dart entirely:

git clone <your-fork-url> flsweep
cd flsweep
tool/install.sh          # compiles build/flsweep, installs to ~/.local/bin

The result is a standalone binary that starts instantly and never prints SDK messages like *"Resolving dependencies…", "Downloading packages…", or "Building package executables…" β€” not even on a fresh machine. Set FLSWEEP_INSTALL_DIR to install somewhere other than ~/.local/bin.

Prefer dart run? It works, but on a fresh clone (or after dependency changes) the Dart toolchain may print those messages first. They come from the Dart SDK before flsweep starts, so no tool or flag can suppress them β€” the native build is the fix.

Global activate (pure Dart, auto-rebuilt by the SDK on change)

git clone <your-fork-url> flsweep
cd flsweep
dart pub get
dart pub global activate --source path .

After global activation, flsweep is available on your PATH.

One-off runs without installing

dart run bin/flsweep.dart [path] [flags]

🚦 Usage

flsweep [path] [flags]

The first positional argument, if given, overrides --path.

Flags

Flag Short Type Default Description
--path -p String ./ Root path to start scanning for Flutter projects.
--all -a Bool false Non-interactive mode; process all found projects immediately.
--deep -d Bool false Deep clean mode; removes android/.gradle, ios/Pods, .dart_tool.
--exclude -e String "" Comma-separated paths or names to ignore during scan.
--dry-run -n Bool false Scan and display cleanable storage size without deleting anything.
--concurrent -c Int 4 Maximum number of projects to clean in parallel.
--quiet -q Bool false Suppress spinners/TUI animations; output minimal plain text.
--verbose -v Bool false Show additional command output.
--help -h Bool false Print usage information.
--version Bool false Print the tool version.

Examples

Preview how much space a workspace could reclaim β€” touches nothing:

flsweep ~/dev --dry-run

Clean everything in a workspace, quietly, for a CI cron job:

flsweep ~/workspaces --all --quiet

Deep clean with 8 parallel workers, skipping a legacy monorepo and vendor dirs:

flsweep ~/dev --all --deep -c 8 --exclude legacy_monorepo,vendored

Point at a single project and interactively confirm:

flsweep ~/dev/my_app

Restore dependencies only, without cleaning:

# flsweep always runs pub get after clean; use --dry-run first to audit.
flsweep ~/dev --all

Exit codes

Code Meaning
0 Success (including a clean dry run).
1 At least one project failed during the sweep (the rest still completed).
64 Invalid command-line usage.
66 The given path does not exist.
70 An unexpected internal error.

πŸ— Architecture

flsweep/
β”œβ”€β”€ bin/
β”‚   └── flsweep.dart          # CLI entry point, flag parsing, and route dispatching
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ flsweep.dart          # Public library entry
β”‚   └── src/
β”‚       β”œβ”€β”€ models/
β”‚       β”‚   └── project_info.dart  # Data model for discovered projects
β”‚       β”œβ”€β”€ services/
β”‚       β”‚   β”œβ”€β”€ scanner.dart       # Workspace file crawler & filtering engine
β”‚       β”‚   β”œβ”€β”€ executor.dart      # Process runner (clean, pub get, deep clean)
β”‚       β”‚   └── metrics.dart       # Disk space calculator (KB/MB/GB)
β”‚       └── ui/
β”‚           β”œβ”€β”€ tui.dart        # Interactive multi-select & terminal prompts
β”‚           β”œβ”€β”€ spinner.dart    # Animated terminal braille spinners
β”‚           └── logger.dart     # Colorized log formatters
└── test/                     # Unit tests for scanner, executor, and metrics

Data flow

  1. Scan (scanner.dart) β€” a breadth-first crawler walks the workspace from --path, skipping .pub-cache, .git, node_modules, build, .dart_tool, other dotted directories, and anything passed to --exclude. A directory is a Flutter project iff its pubspec.yaml has a top-level name: and a top-level flutter: block. Nested traversal stops at each discovered project.
  2. Measure (metrics.dart) β€” for every project, the sizes of build, .dart_tool, android/.gradle, ios/Pods, and ios/Podfile.lock are summed recursively (symlinks are never followed).
  3. Select (tui.dart + checklist.dart) β€” interactive arrow-key checklist with a toggle-all (a first-party component built on dart_console), or zero prompts with --all / --quiet.
  4. Execute (executor.dart) β€” a fixed-size async worker pool runs, per project: flutter clean β†’ (optional deep clean) β†’ flutter pub get, then re-measures. Results preserve input order; every failure is captured per project.
  5. Report (logger.dart, tui.dart) β€” live spinner progress, per-project outcomes, and a final summary with total storage freed.

Safety guarantees

  • Never touches .pub-cache or any system/SDK directory β€” the scanner hard-ignores it, and the deep-clean deleter re-validates every path against a whitelist (build, .dart_tool, .gradle, Pods, Podfile.lock) and a canonical containment check against the project root.
  • Deep-clean whitelist β€” a path is only deletable if it is (a) inside the canonical project root, (b) exactly one of the whitelisted artifact names, (c) not the project root, home directory, or filesystem root, and (d) not under any .pub-cache segment.
  • No symlink following β€” neither size measurement nor deletion follows links, so linked artifacts elsewhere on disk are never affected.
  • Crash-proof β€” main has a final safety net; per-project failures are converted into status/exit codes, never stack traces.

πŸ§ͺ Development

dart pub get        # fetch dependencies
dart analyze        # static analysis β€” zero issues expected
dart test           # run the full test suite
tool/build.sh       # compile a standalone native executable to build/flsweep

The executor's process runner and delete routine are injectable seams, so the test suite exercises the full pipeline (ordering, concurrency caps, failure isolation, deep-clean safety) without a Flutter SDK on the machine.

Tech stack

Package Purpose
args CLI flag parsing
dart_console Raw terminal/key input for the interactive checklist
mason_logger Logger baseline utilities
path Cross-platform path handling everywhere

🀝 Contributing

Issues and pull requests are welcome. Please run dart analyze and dart test before submitting; both must be clean.

πŸ“„ License

Released under the MIT License β€” Β© 2026 Motiur Rahman Sany.

About

🧹⚑ High-performance concurrent Flutter workspace cleaner β€” batch flutter clean, deep-clean native artifacts, auto pub get, and track exactly how much disk you freed.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages