fp (freeport) is a small, no-daemon CLI for answering "what is on this port?"
and freeing a port quickly. Designed for local dev workflows and automation.
./install.sh
# or
go install .fp list # list all listening ports
fp list node # filter by process name
fp who 3000 # detailed info on port 3000
fp kill 3000 # kill process on port 3000
fp doctor # check system dependenciesfp list # all ports
fp list node # filter by command name
fp list --port 3000 # filter by port
fp list --unique # dedupe by port+PID
fp list -v # show full executable path
fp list --json # JSON outputfp who 3000
fp who 3000 --jsonfp kill 3000 # SIGTERM with 2s timeout
fp kill 3000 --signal INT --timeout 1s
fp kill 3000 --force # override user check
fp kill 3000 --dry-run # preview targetsfp pick # default: prefer 3000
fp pick --prefer 8080 --range 8000-8999
fp pick --prefer 0 # OS-assigned ephemeralfp check 3000 # exit 0=free, 1=in-use, 2=error
fp check 3000 --wait 5s # wait up to 5s for port to freefp run -- node server.js
fp run --prefer 8080 -- python app.py
fp run --env API_PORT -- ./myserver# Bash
eval "$(fp completion bash)"
# Zsh
eval "$(fp completion zsh)"
# Fish
fp completion fish | sourcefp doctor- Uses
lsofon macOS andsson Linux runis best-effort; cannot prevent races with non-fp processes- On Linux,
ssmay omit PID/command without root
Why no daemon? All data comes from the OS at query time. No background services needed.
Why not clean up TIME_WAIT? TIME_WAIT is a closed connection, not a listener. If a port is blocked, there's almost always a live listener.
Does run guarantee exclusivity?
No. It uses lockfiles to avoid collisions between fp invocations, but
external processes can still race.