Every listening port, with its framework, project, and uptime. Zero config, one static binary.
List what's running, find a service, free a port, stop a project — the four commands, back to back.
$ portsPORT PROCESS PROJECT UPTIME3000 Next.js ~/projects/shop 14m5432 PostgreSQL docker: shop-db 2d8000 FastAPI ~/projects/shop 14m5173 Vite ~/projects/admin 3h11434 Ollama windows ? $ ports find postgres5432 PostgreSQL docker: shop-db 2d $ ports free 3000✓ killed Next.js (pid 48391) — port 3000 is free $ ports kill shop✓ stopped FastAPI (:8000)✓ stopped PostgreSQL (container shop-db)$
Next.js, Vite, FastAPI, Postgres, Redis — named the way you know them, not as PIDs.
A frontend, API, and database that belong together read — and stop — as one application.
Real container and Compose service names instead of docker-proxy.
Windows-side listeners and WSL processes, distinguished in the same table.
Pass --json to any list or find command for scripting and automation.
SIGTERM first, SIGKILL only if it won't exit. Never a reused PID.
portsList every listening port with its framework, project, and uptime.ports find <name>Filter by framework, process, project, or container. Case-insensitive.ports free <port>Kill whatever holds a port.ports kill <name>Stop every process in a project or service — containers included.--jsonMachine-readable output for scripts and coding agents.--forceSkip SIGTERM and kill immediately.Instead of raw PIDs and process names: framework names, project directories, and uptime — grouped so a frontend, API, and database that belong together read as one application.
Read the docssockets · processes · working directories
one command, zero config
Homebrew, Scoop, or curl — then run ports.
$ brew install pyjeebz/tap/ports
$ curl -fsSL https://ports.tools/install | sh
$ scoop install ports
No PID was harmed in the making of this harbor. Every ship gets SIGTERM before SIGKILL.