tidyup 0.1.0

Free up ports and disk space from your dev projects: kill port hogs, delete node_modules/target folders, start your dev stack
tidyup-0.1.0 is not a library.

tidyup

Your dev machine, minus the mess.

Kill whatever is squatting on port 3000. Delete the 40 GB of node_modules and target folders from projects you forgot about. Start your whole dev stack with one command.

CI License: MIT macOS | Linux

Why

Every developer has seen these:

Error: listen EADDRINUSE: address already in use :::3000
Your disk is almost full.

The first one sends you to Stack Overflow for the lsof -ti :3000 | xargs kill incantation, again. The second one is 30 old projects, each with a gigabyte of node_modules, a few Rust target folders at 5 GB each, and a .venv from that weekend you tried machine learning.

tidyup handles both: one small binary, no runtime, no config needed.

Install

cargo install --git https://github.com/ChristiantangCC/tidyup

Works on macOS and Linux. It uses lsof and ps, which both ship with.

Ports: what's running, and stop it

tidyup ports          # what's listening, which process, which project folder
tidyup 3000           # stop whatever is on 3000
tidyup 3000 5173 8080 # several at once
tidyup kill 3000 -f   # skip the polite part
  • Shows the project folder each process runs from, so you can tell your three node processes apart.
  • Hides system noise. AirPlay, Spotify and other processes running from / stay out of the list unless you pass --all.
  • Stops nicely first. SIGTERM, a 3 second wait, then SIGKILL only if the process is still around. That's what happened to the stubborn Python server above.

Clean: get your disk back

tidyup clean ~/code                  # pick from a list, then confirm
tidyup clean ~/code --older-than 30  # only projects untouched for a month
tidyup clean ~/code --dry-run        # just show me
tidyup clean ~/code --older-than 90 --yes   # no questions asked

It only deletes what your tools can rebuild, and only when the project file that creates it sits next to it. A node_modules without a package.json beside it is left alone. So is a build/ folder you made yourself.

Deletes When next to
node_modules .next .nuxt .svelte-kit .turbo .parcel-cache .angular package.json JavaScript
target Cargo.toml · pom.xml Rust · Maven
build .gradle build.gradle(.kts) · settings.gradle(.kts) Gradle
.venv venv pyproject.toml · requirements.txt · setup.py · Pipfile Python
Pods Podfile CocoaPods
.dart_tool build pubspec.yaml Dart · Flutter
vendor composer.json PHP
_build deps mix.exs Elixir
.zig-cache zig-out build.zig Zig

It never looks inside hidden folders (.git, .vscode, .cargo, …), .app bundles or ~/Library, so your editor extensions keep their node_modules.

Sizes are honest. tidyup reports what deleting actually frees. A pnpm project's node_modules is mostly hard links into pnpm's shared store, so it shows up small, because deleting it frees almost nothing.

Age is the last time you touched the project, not its build folder. --older-than 30 means "projects I haven't opened in a month".

Up: your dev stack in one command

Put a tidyup.toml in your project (or run tidyup up --init):

[[service]]
name = "web"
cmd = "pnpm dev"
port = 3000              # whatever holds this port is stopped first

[[service]]
name = "api"
cmd = "uvicorn main:app --port 8080"
port = 8080

[[service]]
name = "worker"
cmd = "pnpm worker"
cwd = "packages/worker"  # optional, relative to tidyup.toml
env = { LOG_LEVEL = "debug" }
tidyup up          # start everything
tidyup up web api  # just these
  • Frees the ports first, so a leftover dev server from yesterday doesn't stop you.
  • One terminal, colored prefixes, colors from your tools kept.
  • ctrl-c stops everything, including the processes your services started themselves (pnpm → node → esbuild). No orphans holding port 3000 tomorrow.

The dashboard

Run tidyup with no arguments (or tidyup ui ~/code) for both tools in one screen. Ports refresh every 2 seconds; the Clean tab fills in while it scans.

Ports tab Clean tab
x stop space mark
X force kill a mark all
a show/hide system processes d delete marked (or current)
r refresh s / t sort by size / age, again to flip
r rescan

tab or 1/2 switches tabs, ↑↓ or j/k moves, q quits.

Contributing

Issues and pull requests are welcome. Before opening a PR:

cargo fmt && cargo clippy --all-targets -- -D warnings && cargo test

The GIFs above are recorded with VHS against made-up data. TIDYUP_DEMO=1 makes tidyup show fake ports and projects and only pretend to stop and delete them. To re-record one:

cargo build --release && sh demo/setup.sh && vhs demo/dashboard.tape

License

MIT