We've all been here:
$ lsof -i :3000
COMMAND PID USER FD TYPE ...
node 3877 dev ...
Is that my Next.js dev server? A stale process? Something else entirely? You grep, you squint, you kill -9 and hope for the best.
I got tired of guessing. So I built portrm.
What it does
ptrm 3000
Output:
⚡ Port 3000 in use
→ Next.js (PID 3877)
→ running for 9s
→ memory 69.4 MB
→ next-server (v14.2.29) TERM_PROGRAM=vscode
→ user dev
→ cwd /home/dev/projects/my-app
→ detected Next.js (95% confidence)
→ 🛡️ safe to kill.
Before touching anything, it shows you:
- What process is on that port
- How long it's been running
- Memory usage
- Working directory — so you know which project it belongs to
- Framework detection — Next.js, Vite, Express, and more
- Safety verdict — whether it's safe to kill
Then it sends SIGTERM first (graceful shutdown), and only escalates to SIGKILL if the process doesn't exit in time. No blind force kills.
Works in CI and scripts too
ptrm 3000 && npm start
Clean exit codes, fully scriptable. Drop it in your Makefile or pre-start hooks.
Install
# Homebrew
brew install abhishekayu/tap/portrm
# Cargo
cargo install portrm
# npm
npm install -g portrm
Single static binary. No Node, no Python, no runtime deps required.
Why I built this
On shared dev machines and in CI environments, a blind kill -9 on a PID you're not sure about can take down the wrong service. The "show first, kill second" approach has saved me a few times already.
Built in Rust mostly for the single binary distribution and native signal handling.
Repo: github.com/abhishekayu/portrm
Site: portrm.dev
Would love feedback especially if there's a workflow this breaks or a feature you'd expect.
Top comments (0)