Rust CLI toolkit for Flutter/Android/iOS developers, with a tech-agnostic purge that also cleans Node, Rust, Go, Ruby/Rails, and Python build caches. Auto-detects your project and runs common dev tasks from within your project directory.
adb is powerful but the daily-driver workflow is full of papercuts:
adb installfails with "more than one device/emulator" — as soon as you have a phone plugged in and an emulator running, every command needs an explicit-s <serial>.mdevfans out to all connected devices with--all, or targets one with-d.- Clearing app storage means tapping through the emulator UI — Settings → Apps → pick app → Storage → Clear data. Minutes per cycle, repeated dozens of times a day.
mdev clearreads the app id from your project and does it in one command. adb logcatdrowns you in noise from every app and system service — the default stream is thousands of lines per second and filtering it down to just your app requires juggling--pid, tag filters, andgrep(ref).- Every action needs the package name first —
adb shell pm clear,adb uninstall,pm grantall take a package id, so you end up runningpm list packages | grep myappbefore the real command (ref). - "unauthorized" / "offline" dance — device drops off the bridge and you're back to
adb kill-server, revoking USB debugging keys, replugging, and re-accepting the fingerprint prompt (ref). - Corrupted build caches send you hunting across Stack Overflow — a weird build failure and suddenly you need to remember the right incantation:
~/.gradle/caches,flutter clean && flutter pub cache repair,pod deintegrate,rm -rf ~/Library/Developer/Xcode/DerivedData,pod cache clean --all,rm -rf node_modules,cargo clean,go clean -modcache,find . -name __pycache__ -exec rm -rf {} +… different path, different flag, same wasted afternoon.mdev purgeknows all of them across Flutter, Android, iOS, Node, Rust, Go, Ruby/Rails, and Python, and supports--dry-runso you can see what's about to go.
Every command has a one-letter alias (e.g. mdev u == mdev uninstall).
| Command | Alias | Description |
|---|---|---|
mdev uninstall |
u |
Uninstall the app from connected devices/emulators |
mdev clear |
c |
Clear app data and restart on connected devices |
mdev purge |
p |
Purge build artifacts and caches across Flutter, Android, iOS, Node, Rust, Go, Ruby/Rails, and Python projects |
mdev keystore |
k |
Interactively generate an Android signing keystore |
mdev emulator config |
e c |
Apply config tweaks (e.g. showAVDManager=no) to every local Android AVD |
mdev emulator list |
e l |
List known AVD config.ini tweaks |
mdev doctor |
d |
Check development environment (flutter, adb, java, xcode, etc.) |
mdev completions |
s |
Generate shell completion script |
mdev purge auto-detects projects in the current directory (and one level of subdirs) and applies per-ecosystem cleaners. Global caches are gated behind explicit --<eco>-global flags and prompt for confirmation before deletion.
| Ecosystem | Anchor file(s) | Per-project paths | Global (gated) |
|---|---|---|---|
| Flutter | pubspec.yaml |
build/, .dart_tool/, android/build, ios/Pods, ios/Podfile.lock, ios/.symlinks, … |
~/.pub-cache, <flutter>/bin/cache for the active SDK and every FVM/asdf version (~/fvm/versions/*/bin/cache, $FVM_CACHE_PATH/versions/*/bin/cache, ~/.asdf/installs/flutter/*/bin/cache) |
| Android | app/build.gradle{,.kts} |
app/build/, build/, .gradle/ |
~/.gradle/caches |
| iOS | *.xcodeproj |
Pods/, Podfile.lock, *.xcworkspace, DerivedData |
CocoaPods cache, ~/Library/Developer/Xcode/DerivedData |
| Node | package.json (+ lockfile) |
node_modules/, .next/, .nuxt/, .turbo/, .vite/, .parcel-cache/, dist/, build/, .svelte-kit/, .astro/, coverage/ |
~/.npm, ~/.pnpm-store, ~/.cache/yarn or ~/Library/Caches/Yarn, ~/.bun/install/cache |
| Rust | Cargo.toml |
target/ |
~/.cargo/registry/cache, ~/.cargo/registry/src, ~/.cargo/git/db |
| Go | go.mod |
bin/, pkg/ |
go clean -modcache, ~/Library/Caches/go-build or ~/.cache/go-build |
| Ruby / Rails | Gemfile (+ config/application.rb) |
vendor/bundle/, .bundle/, Rails: tmp/cache/, log/*.log |
~/.bundle/cache, ~/.gem/cache |
| Python (Django / FastAPI / generic) | pyproject.toml, requirements.txt, Pipfile, uv.lock, poetry.lock, manage.py |
__pycache__/, .pytest_cache/, .mypy_cache/, .ruff_cache/, .tox/, .coverage, htmlcov/, Django: staticfiles/; opt-in: .venv/, venv/, env/ |
~/Library/Caches/pip/pypoetry (macOS), ~/.cache/pip/pypoetry (Linux), ~/.cache/uv, ~/.local/share/virtualenvs |
Per-project paths are always cleaned for any detected project. Global caches are destructive and only fire when you pass the matching --<eco>-global flag, with an interactive confirmation prompt before any deletion (skipped in --dry-run).
For every detected project (and the current directory when nothing is detected), mdev purge also scans for size-hungry files that aren't tied to any specific ecosystem and that tend to pile up unnoticed:
- JVM heap dumps:
java_pid<NNN>.hprof - JVM crash logs:
hs_err_pid<NNN>.log - Core dumps:
core,core.<pid>,*.dmp - Package-manager debug logs:
npm-debug.log*,yarn-debug.log*,yarn-error.log*,lerna-debug.log* - Editor backups:
*~,.*.swp,.*.swo,.*.swn - OS metadata:
.DS_Store,Thumbs.db - Linter caches:
.eslintcache,.stylelintcache - Coverage / misc:
.nyc_output/,nohup.out
The scanner lists each match with its size and a total, then prompts once before deleting. Subtrees owned by other cleaners (node_modules/, target/, .venv/, .git/, build/, …) are skipped to avoid double-walking. Pass --no-extras to disable this scan.
brew tap <user>/tap
brew install mdevRequires Rust. Run make setup if you don't have it.
git clone https://github.com/<user>/mdev
cd mdev
make installRun any command from within your project directory. uninstall, clear, keystore, emulator, and doctor target Flutter/Android/iOS; purge works across every supported ecosystem (see the table above).
# Uninstall from a specific device
mdev uninstall -d <device-id>
# Uninstall from all connected devices
mdev uninstall --all
# Clear app data and relaunch on all devices
mdev clear --all
# Purge all build caches (dry run first)
mdev purge --dry-run
mdev purge
# Purge only specific targets
mdev purge --flutter --gradle
mdev purge --rust --dry-run # only Rust projects
mdev purge --node --node-global # Node projects + global stores
mdev purge --python --python-venv # Python + remove .venv/venv/env
# Generate a release keystore
mdev keystore
# Configure all local Android AVDs (default: showAVDManager=no)
mdev emulator config # apply defaults
mdev emulator config -n # dry run
mdev emulator config --set hw.keyboard=yes --backup
mdev emulator config --avd Pixel_9
# Check your dev environment
mdev doctormdev completions <shell> prints a completion script to stdout. Supported shells: bash, zsh, fish, powershell, elvish.
zsh (ensure ~/.zfunc is on fpath and autoload -U compinit && compinit runs in ~/.zshrc):
mkdir -p ~/.zfunc
mdev completions zsh > ~/.zfunc/_mdevbash:
mdev completions bash > ~/.local/share/bash-completion/completions/mdevfish:
mdev completions fish > ~/.config/fish/completions/mdev.fishRestart the shell after installing.
Most commands support:
-d / --device <id>— target a specific device-a / --all— apply to all connected devices-v / --verbose— show detailed output-n / --dry-run(purge only) — preview what would be deleted
- Android:
adbin PATH - iOS: macOS + Xcode with
xcrun simctl - Flutter:
flutterin PATH - Keystore: JDK with
keytool
MIT