A beautiful CLI tool to see what's running on your ports.
Stop guessing which process is hogging port 3000. port-whisperer gives you a color-coded table of every dev server, database, and background process listening on your machine -- with framework detection, Docker container identification, and interactive process management.
$ ports
┌────────────────┬─────────┬───────┬──────────────────────┬────────────┬────────┬───────────┐
│ PORT │ PROCESS │ PID │ PROJECT │ FRAMEWORK │ UPTIME │ STATUS │
├────────────────┼─────────┼───────┼──────────────────────┼────────────┼────────┼───────────┤
│ localhost:3000 │ node │ 42872 │ frontend │ Next.js │ 1d 9h │ ● healthy │
├────────────────┼─────────┼───────┼──────────────────────┼────────────┼────────┼───────────┤
│ localhost:3001 │ node │ 95380 │ preview-app │ Next.js │ 2h 40m │ ● healthy │
├────────────────┼─────────┼───────┼──────────────────────┼────────────┼────────┼───────────┤
│ localhost:4566 │ docker │ 58351 │ backend-localstack-1 │ LocalStack │ 10d 3h │ ● healthy │
├────────────────┼─────────┼───────┼──────────────────────┼────────────┼────────┼───────────┤
│ localhost:5432 │ docker │ 58351 │ backend-postgres-1 │ PostgreSQL │ 10d 3h │ ● healthy │
├────────────────┼─────────┼───────┼──────────────────────┼────────────┼────────┼───────────┤
│ localhost:6379 │ docker │ 58351 │ backend-redis-1 │ Redis │ 10d 3h │ ● healthy │
└────────────────┴─────────┴───────┴──────────────────────┴────────────┴────────┴───────────┘
5 ports active · Run ports <number> for details · --all to show everything
Colors: green = healthy, yellow = orphaned, red = zombie. The PORT column is a clickable link in terminals that support hyperlinks. It shows localhost: by default; when several processes share a port on different bind addresses (e.g. one on * and one on [::1]), each process gets its own row with the explicit address that reaches it, like 127.0.0.1:3006 and [::1]:3006.
npm install -g port-whispererOr run it directly without installing:
npx port-whispererIf you use Claude Code, you can ask it to npm install -g port-whisperer and start using ports right away -- no setup steps needed.
portsShows dev servers, Docker containers, and databases. System apps (Spotify, Raycast, etc.) are filtered out by default.
ports --allIncludes system services, desktop apps, and everything else listening on your machine.
ports 3000
# or
whoisonport 3000Detailed view: full process tree, repository path, current git branch, memory usage, and an interactive prompt to kill the process.
If several processes listen on the same port (e.g. one on *:3006 and one on [::1]:3006), you get a warning listing them and pick which one you mean. The same picker appears for ports kill and ports logs; in non-interactive shells pass the PID instead.
$ ports 3006
⚠ 2 processes are listening on :3006:
1 127.0.0.1:3006 node (PID 14425) bedtime-stories
2 [::1]:3006 node (PID 78513) astra
Pick a process (1-2):
ports kill 3000 # kill by port
ports kill 3000 5173 8080 # kill multiple
ports kill 3000-3010 # kill a port range
ports kill 42872 # kill by PID
ports kill -f 3000 # force kill (SIGKILL)Resolves port to process automatically. Falls back to PID if no listener matches. Use -f when a process won't die gracefully. If a port is shared by several processes, you pick one (or a for all); port ranges kill every listener without asking.
Port ranges expand into individual kills -- empty ports are silently skipped and shown as a summary:
$ ports kill 3000-3005
Killing :3000 — node (PID 42872)
✓ Sent SIGTERM to :3000 — node (PID 42872)
Killing :3001 — node (PID 95380)
✓ Sent SIGTERM to :3001 — node (PID 95380)
Range summary: 2 killed, 4 empty
ports logs 3000 # show last 50 lines and exit
ports logs 3000 -f # follow (stream new lines)
ports logs 3000 --lines 10 # show last 10 lines
ports logs 3000 --lines 10 -f # show last 10 then follow
ports logs 3000 --err # stderr onlyDiscovers log files automatically using lsof file descriptor detection. If stdout/stderr is redirected to a file, it finds and tails it. Falls back to system log (log show on macOS, journalctl on Linux) when no log files are found.
$ ports logs 3000 --lines 5
Port Whisperer — logs for :3000 (node, PID 42872)
▸ Tailing stdout: /tmp/next-dev.output
▲ Next.js 16.2.3 (Turbopack)
- Local: http://localhost:3000
✓ Ready in 195ms
GET / 200 in 990ms
GET /api/auth/session 200 in 6ms
ports psA beautiful ps aux for developers. Shows all running dev processes (not just port-bound ones) with CPU%, memory, framework detection, and a smart description column. Docker processes are collapsed into a single summary row.
$ ports ps
┌───────┬─────────┬──────┬──────────┬──────────┬───────────┬─────────┬────────────────────────────────┐
│ PID │ PROCESS │ CPU% │ MEM │ PROJECT │ FRAMEWORK │ UPTIME │ WHAT │
├───────┼─────────┼──────┼──────────┼──────────┼───────────┼─────────┼────────────────────────────────┤
│ 592 │ Docker │ 1.3 │ 735.5 MB │ — │ Docker │ 13d 12h │ 14 processes │
├───────┼─────────┼──────┼──────────┼──────────┼───────────┼─────────┼────────────────────────────────┤
│ 36664 │ python3 │ 0.2 │ 17.6 MB │ — │ Python │ 6d 10h │ browser_use.skill_cli.daemon │
├───────┼─────────┼──────┼──────────┼──────────┼───────────┼─────────┼────────────────────────────────┤
│ 26408 │ node │ 0.1 │ 9.2 MB │ — │ Node.js │ 10d 13h │ jest jest_runner_cloud.js │
├───────┼─────────┼──────┼──────────┼──────────┼───────────┼─────────┼────────────────────────────────┤
│ 25752 │ node │ 0.0 │ 17.3 MB │ — │ Node.js │ 10d 13h │ server.js │
├───────┼─────────┼──────┼──────────┼──────────┼───────────┼─────────┼────────────────────────────────┤
│ 66921 │ Python │ 0.0 │ 4.1 MB │ — │ Python │ 2h 25m │ src.server │
└───────┴─────────┴──────┴──────────┴──────────┴───────────┴─────────┴────────────────────────────────┘
5 processes · --all to show everything
ports ps --all # show all processes, not just devports cleanFinds and kills orphaned or zombie dev server processes. Only targets dev runtimes (node, python, etc.) -- won't touch your desktop apps.
ports watchReal-time monitoring that notifies you whenever a port starts or stops listening.
ports --watch # re-render the port list every 2s
ports --all --watch # same, but for all listening ports
ports ps --watch # auto-refresh the process list
ports 3000 --watch # auto-refresh the detail view for a port
ports --watch --interval 5 # custom refresh interval (seconds)Like top: clears the screen and redraws the table on every tick. Press Ctrl+C to stop.
Three shell calls, runs in ~0.2s:
lsof -iTCP -sTCP:LISTEN-- finds all processes listening on TCP portsps(single batched call) -- retrieves process details for all PIDs at once: command line, uptime, memory, parent PID, statuslsof -d cwd(single batched call) -- resolves the working directory of each process to detect the project and framework
For Docker ports, a single docker ps call maps host ports to container names and images.
Framework detection reads package.json dependencies and inspects process command lines. Recognizes Next.js, Vite, Express, Angular, Remix, Astro, Django, Rails, FastAPI, and many others. Docker images are identified as PostgreSQL, Redis, MongoDB, LocalStack, nginx, etc.
| Platform | Status |
|---|---|
| macOS | Supported |
| Linux | Supported |
| Windows | Supported |