Skip to content

danielgomezrico/mdev-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mdev

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.

Why this?

adb is powerful but the daily-driver workflow is full of papercuts:

  • adb install fails 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>. mdev fans 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 clear reads the app id from your project and does it in one command.
  • adb logcat drowns 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, and grep (ref).
  • Every action needs the package name firstadb shell pm clear, adb uninstall, pm grant all take a package id, so you end up running pm list packages | grep myapp before 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 purge knows all of them across Flutter, Android, iOS, Node, Rust, Go, Ruby/Rails, and Python, and supports --dry-run so you can see what's about to go.

Commands

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

Supported ecosystems

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).

Extras (cross-platform junk)

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.

Installation

Homebrew

brew tap <user>/tap
brew install mdev

From source

Requires Rust. Run make setup if you don't have it.

git clone https://github.com/<user>/mdev
cd mdev
make install

Usage

Run 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 doctor

Shell completions

mdev 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/_mdev

bash:

mdev completions bash > ~/.local/share/bash-completion/completions/mdev

fish:

mdev completions fish > ~/.config/fish/completions/mdev.fish

Restart the shell after installing.

Flags

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

Requirements

  • Android: adb in PATH
  • iOS: macOS + Xcode with xcrun simctl
  • Flutter: flutter in PATH
  • Keystore: JDK with keytool

License

MIT

About

A Rust CLI toolkit for Flutter/Android/iOS developers: uninstall apps, clear data, purge build caches, generate keystores, and check the dev environment, all from within the project directory

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors