Devclean
Safely kill orphaned dev processes (MCP servers, Flutter daemons, Gradle, iOS Simulators) to reclaim GBs of leaked memory. macOS & Linux.
Install / Use
/learn @ImL1s/DevcleanQuality Score
Category
Development & EngineeringSupported Platforms
README
🧹 DevClean
A smart, safe, and lightning-fast cleanup script for development environments.
It identifies and kills orphaned background processes (processes where PPID=1) to reclaim memory without affecting your active development sessions (like your IDE, terminal, or Claude Code/AI agents).
Specially optimized for macOS mobile developers (Flutter/iOS/Android) and developers using modern AI tools (MCP servers).

Why You Need This
AI-powered coding tools and mobile development toolchains spawn background processes that frequently fail to clean up after themselves. These orphaned processes silently accumulate, consuming 10-20+ GB of RAM before you even notice your machine slowing down.
Instead of manually hunting them down in Activity Monitor or rebooting, devclean safely sweeps them away in milliseconds.
Root Causes
1. MCP Servers: No Cleanup on Exit
Tools like Claude Code, Cursor, OpenCode, and Antigravity spawn MCP (Model Context Protocol) servers as child processes. When the parent IDE or terminal exits — especially via crash, force-quit, or closing a tab — these child processes are not terminated. They become orphaned (PPID=1) and keep running indefinitely.
Why it happens:
- macOS lacks
prctl(PR_SET_PDEATHSIG)— there's no native way to auto-kill children when the parent dies. - Node.js
child.kill()sends SIGTERM but doesn't wait for cleanup, and nestednpm execwrappers add additional layers that signals don't propagate through. - The MCP protocol specifies a graceful shutdown phase, but most host implementations don't invoke it on exit.
Real-world impact:
| Tool | Issue | Impact |
|------|-------|--------|
| Claude Code | MCP servers not terminated on exit | Processes accumulate across sessions |
| Claude Code | Chrome MCP spawns ~4/min without cleanup | 27 GB over ~10 hours |
| Claude Code | Subagents leak when parent terminal killed | ~45 MB per orphaned process |
| Claude Code | VS Code extension leaks worker processes | OOM killer triggered on Linux |
| Cursor | MCP child processes not cleaned up | ~3-5 GB over days |
| Cursor | MCP processes accumulate over time | Dozens of orphaned node/npm processes |
| OpenCode | MCP processes not terminated on session end | Zombie process accumulation |
| Antigravity | Language server high memory consumption | Zombie processes after quit; backend ports don't clear |
| Antigravity | MCP servers spawn per-workspace, never cleaned up | Process explosion; ~10 GB idle RAM |
2. Frontend Dev Servers: Ctrl+C Doesn't Always Work
Webpack-dev-server is notorious for leaving orphaned node processes after Ctrl+C. The child process cannot be killed when spawned via child_process, and if the parent exits, the dev server continues running. Similar issues affect Vite, Next.js dev server, and other frontend tooling.
| Tool | Issue | Impact | |------|-------|--------| | webpack-dev-server | Orphaned node.exe processes | Port occupied, node process lingers | | webpack-dev-server | Child process cannot be killed | Parent exit doesn't terminate server | | Vue/webpack | Dev server continues after Ctrl+C | Needs manual kill |
3. Flutter / Dart: SIGTERM Doesn't Reach the VM (Mobile)
The flutter command is a shell script wrapper. When IDE sends SIGTERM on shutdown, the signal hits the shell process but doesn't propagate to the underlying Dart VM. The VM process becomes orphaned while the shell exits cleanly.
The Flutter daemon also spawns sub-processes like xcdevice observe that are never cleaned up.
| Tool | Issue | Impact |
|------|-------|--------|
| Flutter / Dart | Daemon orphaned when IDE closes | SIGTERM doesn't propagate through shell wrapper |
| Flutter | xcdevice observe leaked by daemon | Orphaned sub-processes pile up |
| FVM | FVM-managed dart/flutter processes can get stuck (e.g. fvm use waiting for interactive input) | Stuck processes accumulate at 100% CPU each |
4. Gradle: Daemon Multiplication
Gradle daemons are designed to stay alive for performance. But a new daemon is spawned whenever JVM args, Java version, or Gradle version differ between builds. Multi-project setups with Kotlin can spawn 3+ Kotlin daemons, each consuming 1 GB+ of heap. The built-in 3-hour idle timeout is far too long for developer machines.
| Tool | Issue | Impact | |------|-------|--------| | Gradle Daemon | Multiple instances exhaust memory | Config mismatches spawn duplicates | | Kotlin Daemon | Excessive memory usage | 3+ daemons × 1 GB+ each |
5. iOS Simulators: Silent Memory Hogs
CoreSimulator processes from previous Xcode sessions linger in the background because Xcode has no idea what you still need and won't clean them up for you. They collectively consume 10-20+ GB.
6. Logi Options+: Known Memory Leak
logioptionsplus_agent has a well-documented memory leak that has been reported for 3+ years. The agent starts at ~100 MB but grows to multi-GB over time — in extreme cases up to 36 GB. Since launchd auto-restarts it, the only practical solution is to periodically kill the process and let it restart fresh. Logitech has not fully fixed this issue.
How We Solve It
| Strategy | How | Safe for active work? |
|----------|-----|----------------------|
| Orphan detection (PPID=1) | Only kills processes whose parent has died — the defining trait of a leaked process | Yes — active IDE/terminal children always have a living parent |
| Pattern matching | Targets known offenders via ORPHAN_PATTERNS regex array, not blanket process killing | Yes — only matches specific tool signatures |
| pgrep over ps\|grep | Uses pgrep -f to avoid self-matching and reduce false positives | Yes |
| Frontend dev servers | Catches orphaned webpack-dev-server, vite, next.js, esbuild, turbopack processes | Yes — only PPID=1 orphans |
| Graceful termination | SIGTERM → 2s wait → SIGKILL only for unresponsive processes | Yes — gives processes time to save state |
| Deep mode separation | Heavy daemons (Gradle, Kotlin LSP, FVM, Antigravity Language Server, Logi Options+) require explicit --deep flag; xcodebuild further restricted to orphans only | Yes — opt-in, never surprises |
| Dry-run | --dry-run previews everything without killing | N/A — read-only |
Installation
git clone https://github.com/ImL1s/devclean.git
cd devclean
./install.sh
Note: Ensure
~/.local/binis in yourPATH. Add this line to your~/.zshrcor~/.bashrc:export PATH="$HOME/.local/bin:$PATH"
Usage
Safe Mode (Default)
Safe mode ONLY targets detached, orphaned tools (PPID=1). It is designed to avoid active sessions — processes attached to a living parent (your IDE, terminal, shell) are never matched.
devclean
Deep Clean Mode (--deep)
Shuts down heavy background daemons that aren't technically orphaned but can consume GBs of RAM when idle. (Tools like Gradle will automatically restart on your next build.)
Warning: Deep mode kills non-orphaned Gradle, Kotlin LSP, Flutter daemons, FVM processes, Antigravity Language Server, Logi Options+ agent, and Ruby/Fastlane processes. If a build or compilation is actively running, it may be interrupted. Use
--dry-runfirst to preview what would be affected.
devclean --deep
Dry Run Mode (--dry-run)
Preview what the script would kill without
