New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@tidyports/guard

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tidyports/guard

When a dev server can't bind, say who is holding the port instead of just EADDRINUSE.

latest
Source
npmnpm
Version
0.2.0
Version published
Maintainers
1
Created
Source

@tidyports/guard

EADDRINUSE tells you a port is taken. It never tells you by what.

Put this in front of your dev command and the error answers the actual question:

$ tidyports-guard npm run dev

Error: listen EADDRINUSE: address already in use :::3000

:3000 is held by Claude Code, in Ghostty [PID 12345] in acme-web (feature/auth)

  [1] use 3001 instead
  [2] stop it (asks again first)
  [enter] leave it

Pick 1 and the port lands on your clipboard. Enter leaves everything alone, so a stray keystroke never stops anyone's server.

Naming the owner matters most when an agent is reading it. An agent that hits a port conflict and can't tell it from a bug will often "fix" working code to get around the port — usually by editing your app's configuration. Naming the owner is what makes the conflict legible as a conflict.

When you get the choice, and when you don't

Not everything dies when it can't bind. Vite prints Port 5173 is in use and carries on at 5174, and a prompt underneath a live dev server would be competing with its output for the same terminal. So the choice appears only once the command has actually exited and the terminal is free.

If it's still running — or you're piped, in CI, or an agent is reading — you get the same answer as plain text instead, and nothing ever waits for input:

[tidyports] :3000 is held by Claude Code, in Ghostty [PID 12345] in acme-web (feature/auth)
To take a different port:  PORT=$(tidy-ports alloc web)
To stop it:                tidy-ports kill --match 3000

Use it

npx @tidyports/guard npm run dev

Or wire it into the script you already run:

{
  "scripts": {
    "dev": "tidyports-guard vite"
  }
}

It needs the TidyPorts CLI on your PATH to name the owner. Without it you get a one-line note instead, and nothing else changes.

What it does to your dev loop

Nothing, by design. It is a wrapper around a command you already run, so it is worth being precise about what it does not touch:

  • stdout stays a TTY. Only stderr is intercepted, and every chunk is written through before it's even inspected — so your dev server keeps its colour and its interactive keys.
  • Exit codes and signals are reproduced exactly, including the terminating signal, so a shell, a CI step or an agent reading the status sees what it would have seen anyway.
  • Ctrl-C still works. SIGINT, SIGTERM and SIGHUP are forwarded to the child.
  • Nothing is added on success. The message appears only when a bind actually failed, once, and never again for the same run.

What it understands

The message is different in every ecosystem, so it matches the wording rather than the language:

Nodelisten EADDRINUSE: address already in use :::3000
VitePort 5173 is in use
Flask / PythonAddress already in use + Port 5000 is in use
Rails / Pumabind(2) for "127.0.0.1" port 3000
Golisten tcp :8080: bind: address already in use
DockerBind for 0.0.0.0:5432 failed: port is already allocated

Lines that merely mention a port are deliberately ignored. A false positive would send you after the wrong process, which is worse than staying quiet.

Tests

npm test

Covers the patterns above — including the ones that must not match — and the wrapper's behaviour: exit codes, stderr passthrough, and a real bind failure.

Licence

MIT

Keywords

eaddrinuse

FAQs

Package last updated on 26 Jul 2026

Related posts