Find and kill processes on any port

Port Hero tells you what is using a port, why it is running, and kills it safely — grouped by your git projects, on macOS, Linux and Windows.

Single static binary (~3.5 MB) MIT license Free forever No telemetry v0.3.0
port — terminal

$ port 3000

✓ Found node (PID 48211) on port 3000

  Project: web-app · branch: feature/payments

  Why: launched by npm run dev (PID 48210)

  Command: node --watch src/index.ts

$ port 3000 --kill

✓ SIGTERM → 1.5s grace → SIGKILL · 4 processes

✓ Port 3000 is free

How it works

01

Ask for the port

One command shows the process, PID, project, branch and full command behind any port — TCP or UDP.

$port 3000 ✓ node (PID 48211) on port 3000
02

See why it runs

The causality chain walks back to the parent that launched it, so you know exactly what you are about to stop.

$port 3000 --why ✓ launchd → pm2 → node
03

Act safely

Graceful SIGTERM to the process and its whole tree, with the Safety Shield and a confirmation prompt first.

$port 3000 --kill ✓ SIGTERM · 4 processes stopped

Built for the terminal

Find what's on a port

One command shows the process, PID and command behind any port — TCP and UDP.

port 3000

Know your project

Detects the git repo and branch, so you know exactly what you are about to touch.

port 3000

Kill the whole tree

Terminates the process and its children gracefully, child-first — no orphans left behind.

port 3000 --kill

Safety built in

Never PID 1, kernel threads, foreign users or yourself. Confirmation before killing.

port 3000 --kill

Browse from the terminal

A keyboard-first TUI for every port and process on your machine.

port

One binary everywhere

macOS, Linux and Windows, in a single static binary (~3.5 MB).

port 3000 --json

Enterprise-grade capabilities

Everything you need for development, CI/CD and team workflows — in a single 3.5 MB binary.

UDP support

Inspect DNS, NTP, mDNS and any bound UDP socket. One flag, every platform.

port 53 --udp

CI/CD scripting

Drop-in for shell pipelines. Check if a port is busy, wait until it's free, or find the next available one — all with clean exit codes.

port --check 3000

File lock detection

Who's holding that lock file? One command reveals the process, PID and type — no more guessing.

port --file /path/to/lock

Container-aware

Knows when a process runs inside Docker. Labels containers automatically so you never confuse host and container processes.

port 3000 --why

Team config files

Drop a .port-hero.yaml in your repo for a display name and start command. Global config for grace period, whitelist and logging.

port 3000 --restart

Built-in jq filtering

Filter any JSON output with a jq expression — no external jq binary needed. Works on every platform, built right into the binary.

port --json --jq '.[].name'

Dry-run preview

See exactly what would be terminated before sending a single signal. Zero risk, full visibility.

port 3000 --kill --dry-run

PID targeting

Target any process by PID — kill, force, restart or trace causality. No port number needed.

port --pid 4821 --kill

Structured logging

Debug, info, warn, error — with text or JSON output. Built on stdlib slog for CI audit trails and log aggregation.

port --log-level debug

Defence-in-depth security

Port Hero's Safety Shield is a multi-layer protection system that prevents accidental damage.

Critical protections

PID 1, kernel threads, 60+ system daemons (launchd, systemd, sshd, dockerd…), foreign users' processes, and self-kill are always blocked — even with --force.

Protected ports

Well-known system ports (22 SSH, 53 DNS, 80 HTTP, 443 HTTPS, 3306 MySQL, 5432 PostgreSQL, 6379 Redis…) raise an explicit confirmation dialog before any action.

PID-reuse protection

Before every signal, the target's identity is re-verified. On Linux, signals go through pidfd (atomic — a recycled PID returns ESRCH). On macOS, start-time is verified via PROC_PIDTBSDINFO.

Graceful termination

SIGTERM to the whole tree (child-first) → 1.5 s configurable grace period → SIGKILL only if needed. Clean connection shutdown, no data corruption, no orphaned workers.

Terminal UI at your fingertips

A keyboard-first interface for browsing, inspecting and managing every port on your machine.

List view

↑↓ or jk Navigate
enter Inspect port detail
r Refresh list
q Quit

Detail view

space or K Graceful kill (SIGTERM)
F Force kill (SIGKILL)
R Kill & restart
b Back to list

Confirm dialog

y or enter Confirm action
f Toggle force mode
esc Cancel

Every command

One binary, 27 commands. Copy any of them, paste, read the answer.

$port Interactive list of every listening port
$port 3000 Interactive detail view for port 3000
$port node Interactive list filtered by process name
$port 3000 --why Trace causality: why is this running?
$port node --why Causality for every matching process
$port --pid 4821 --why Causality for a specific PID
$port 3000 --kill Graceful kill (SIGTERM, whole process tree)
$port 3000 --force Force kill (SIGKILL after 1.5 s grace)
$port 3000 --restart Kill and restart the command, detached
$port 3000 --kill --all Kill every process on the port
$port 3000 --kill --dry-run Preview without sending a signal
$port --pid 4821 --kill Kill a specific PID by number
$port --file /path/to/file Show which process holds a lock on a file
$port --json Machine-readable list of all listeners
$port 3000 --json Machine-readable detail for one port
$port 3000 --kill --json Machine-readable kill result (CI)
$port --json --jq '.[].name' Filter JSON output with jq (no external jq needed)
$port --check 3000 Exit 0 if busy, 2 if free (CI scripts)
$port --wait 3000 Wait until port is free (default 30s)
$port --wait 3000 --timeout 90s Wait with custom timeout
$port --next 3000 Print the first free port at or above 3000
$port 53 --udp Query UDP instead of TCP (DNS, NTP, mDNS)
$port --protocol udp 3000 Explicit protocol selection (tcp|udp)
$port --completion bash Print shell completions (bash, zsh, fish)
$port --log-level debug Structured logging level
$port --log-format json Structured log format (text|json)
$port --version Print the installed version
0 Success, no warnings
1 Success with warnings
2 Not found, port free
3 Blocked by Safety Shield
4 Invalid input
5 Internal error

Real responses

Paste any command and read the answer, exactly as the terminal prints it.

$port 3000 --why
Target    : node (pid 14233)
User      : deploy
Command   : node dist/server.js
Git Branch: main [CLEAN]
Started By: pm2 (pid 5034)

Why It Runs:
launchd (pid 1)
└─ pm2 (pid 5034)  [pm2]
   └─ node (pid 14233)
$port 3000 --kill
✓ SIGTERM sent to node (PID 48211)
✓ Grace 1.5s · process tree terminated (4 processes)
✓ Port 3000 is free
$port 3000 --json
[
  {
    "PID": 48211,
    "PPID": 48210,
    "Name": "node",
    "Command": "node --watch src/index.ts",
    "User": "alex",
    "Port": 3000,
    "Protocol": "tcp",
    "LocalAddr": "127.0.0.1",
    "MemoryMB": 142.5,
    "CPUPercent": 1.2,
    "CWD": "/Users/alex/projects/golively-app",
    "Project": "golively-app",
    "GitBranch": "feature/auth-flow",
    "GitDirty": true,
    "Container": "",
    "Children": []
  }
]
$port --check 3000 && port --next 3000
$ port --check 3000
port 3000 is busy
$ port --next 3001
3001

Port Hero vs the manual way

lsof, netstat and fuser work. Port Hero tells you why it is running and kills it safely.

FeaturePort Herolsofnetstatfuser
Find PID on a port Yes Yes Yes Yes
Git project + branch Yes No No No
Why is it running Yespartial No No
Kill process tree Yes No Nopartial
Safety guardrails Yes No No No
TUI interface Yes No No No
Cross-platform Yes Yes Yespartial
UDP support Yes Yes Yes No
CI scripting (--check/--wait/--next) Yes No No No
File lock detection Yes Yes No Yes
Container detection Yes No No No
Team config files Yes No No No
Dry-run preview Yes No No No
Built-in jq filtering Yes No No No
PID-reuse protection Yes No No No

Install in 10 seconds

$ brew install systemendgame/tap/port-hero
macOS No daemon · No telemetry · MIT · ~3.5 MB binary

How to check what is running on port 3000

Run port 3000 in your terminal and Port Hero shows the process name, PID, memory usage, working directory and even the git branch of the project holding the port. It also traces the causality chain, so you see that the process was launched by npm run dev and not by some hidden daemon.

You can filter by process name with port node, target a specific PID with port --pid 4821 --why, or list every listener with the interactive TUI. Every answer arrives without remembering lsof flags.

  • Process name, PID and full command line
  • Git project and branch, detected without calling git
  • Causality chain showing what launched the process
  • Memory and CPU usage at a glance
  • Container detection on Linux (Docker)

How to kill a process on a port safely

Instead of kill -9, which can corrupt data and leave orphaned children, Port Hero sends SIGTERM first, waits 1.5 seconds for a graceful shutdown, and only escalates to SIGKILL if the process ignores it. The whole process tree is handled child-first, so children do not keep the port open.

The Safety Shield refuses to touch PID 1, kernel threads, processes owned by other users or the terminal itself, and asks for confirmation before anything is terminated. Use port 3000 --kill for a graceful stop, port 3000 --force to skip the grace period, and port 3000 --restart to launch the command again detached. Keep your environment files in sync with Envy.

CI/CD integration for port management

Port Hero is designed for shell pipelines and CI workflows. port --check 3000 exits 0 if the port is busy and 2 if it is free — perfect for conditional logic in build scripts. port --wait 3000 blocks until the port is free (with a configurable timeout), and port --next 3000 prints the first available port starting from a given number.

Every action supports --json output for machine parsing, and the built-in --jq filter lets you extract exactly the fields you need without installing an external jq binary. Structured logging with --log-level debug --log-format json provides full audit trails for CI pipelines.

  • port --check 3000 — test if a port is busy (exit 0) or free (exit 2)
  • port --wait 3000 — block until a port is free (default 30s timeout)
  • port --next 3000 — find the first available port
  • port 3000 --kill --json — machine-readable kill results for CI
  • port --json --jq '.[].name' — filter JSON with built-in jq engine

Frequently Asked Questions

Real questions about finding and killing processes on ports

Run port 3000. It returns the PID, the full command and the git project and branch behind the process, without touching lsof flags.

Stop guessing what's on a port

One command shows what is running, why, and how to free the port safely. TCP, UDP, CI scripting, container detection — all in a 3.5 MB binary.