portview
See what's on your ports, then act on it.
A diagnostic-first port viewer for Linux, macOS, and Windows. One command shows you what's listening, who owns it, how long it's been running, and lets you act on it. With --docker, Docker containers appear as first-class rows - inspect, stop, restart, or tail logs right from the TUI.
~1 MB single binary. Zero runtime dependencies.
Install
# One-liner (Linux/macOS)
|
# PowerShell (Windows)
|
# Homebrew
# Cargo
Or grab the binary from Releases.
Quick start
Usage
Scan
$ portview
╭──────┬───────┬───────┬──────┬──────────┬─────────┬────────┬─────────────────────────────────────╮
│ PORT │ PROTO │ PID │ USER │ PROCESS │ UPTIME │ MEM │ COMMAND │
├──────┼───────┼───────┼──────┼──────────┼─────────┼────────┼─────────────────────────────────────┤
│ 3000 │ TCP │ 48291 │ mark │ node │ 3h 12m │ 248 MB │ next dev │
│ 5432 │ TCP │ 1203 │ pg │ postgres │ 14d 2h │ 38 MB │ /usr/lib/postgresql/16/bin/postgres │
│ 6379 │ TCP │ 1198 │ redis│ redis │ 14d 2h │ 12 MB │ redis-server *:6379 │
│ 8080 │ TCP │ 51002 │ mark │ python3 │ 22m │ 45 MB │ uvicorn main:app --port 8080 │
╰──────┴───────┴───────┴──────┴──────────┴─────────┴────────┴─────────────────────────────────────╯
Use --all to include non-listening connections. Use --wide to show full commands without truncation.
Inspect a port
$ portview 3000
Port 3000 (TCP) - node (PID 48291)
Bind: *:3000
Command: next dev
User: mark
Started: 3h 12m ago
Memory: 248 MB
CPU time: 14.3s
Children: 3
State: LISTEN
Kill process 48291? [y/N]
Search by process name
Docker integration
Add --docker to any command. Docker-published ports that have no visible host process appear as their own rows:
$ portview --docker
╭──────┬───────┬───────┬────────┬──────────┬────────┬────────┬───────────────────────────────────╮
│ PORT │ PROTO │ PID │ USER │ PROCESS │ UPTIME │ MEM │ COMMAND │
├──────┼───────┼───────┼────────┼──────────┼────────┼────────┼───────────────────────────────────┤
│ 3000 │ TCP │ 48291 │ mark │ node │ 3h 12m │ 248 MB │ next dev [docker:web] │
│ 5432 │ TCP │ 1203 │ pg │ postgres │ 14d 2h │ 38 MB │ /usr/lib/postgresql/16/bin/post… │
│ 8080 │ TCP │ - │ docker │ pv-nginx │ - │ - │ nginx:alpine :8080->80/tcp │
╰──────┴───────┴───────┴────────┴──────────┴────────┴────────┴───────────────────────────────────╯
- Host processes with a Docker mapping get a
[docker:<name>]tag - Docker-only ports (no host PID) show as synthetic rows with
PID - portview 8080 --dockershows container detail with image infoportview nginx --dockerfinds containers by name- Works in all modes: scan, inspect, search, watch, and JSON
Kill
On Windows, kill always force-terminates via
TerminateProcess.
Watch mode (interactive TUI)
Keybindings
| Key | Action |
|---|---|
j/k, ↑/↓ |
Navigate rows |
g/G, Home/End |
Jump to first/last |
Enter |
Inspect selected port |
d/D |
Kill process or manage Docker container |
/ |
Filter across all columns |
</>, r |
Cycle sort column, reverse direction |
1-8 |
Sort by column N |
a |
Toggle all/listening-only |
q, Esc, Ctrl+C |
Quit |
On a Docker row, d opens a container management popup with Stop, Restart, and Logs actions. On a host process row, d/D opens the kill confirmation popup (SIGTERM / SIGKILL).
JSON
|
Custom colors
PORTVIEW_COLORS="port=red,pid=magenta,command=bright_cyan"
Columns: port, proto, pid, user, process, uptime, mem, command
Colors: red, green, blue, cyan, yellow, magenta, white, bold, dimmed, bright_*, none
Watch mode uses an RGB palette by default. Set PORTVIEW_COLORS to override, or --no-color to disable.
How it works
All process and port data is read directly from the OS - no shelling out to lsof, ss, or netstat.
| Field | Linux | macOS | Windows |
|---|---|---|---|
| Port & protocol | /proc/net/tcp{,6}, udp{,6} |
proc_pidfdinfo |
GetExtendedTcp/UdpTable |
| PID | inode→pid via /proc/*/fd/ |
proc_listpids |
Included in socket table |
| Process name | /proc/<pid>/comm |
proc_pidpath |
QueryFullProcessImageNameW |
| Command | /proc/<pid>/cmdline |
proc_pidpath |
QueryFullProcessImageNameW |
| User | /proc/<pid>/status → getpwuid |
proc_pidinfo → getpwuid |
OpenProcessToken → LookupAccountSidW |
| Uptime | /proc/<pid>/stat starttime |
proc_pidinfo start time |
GetProcessTimes |
| Memory (RSS) | /proc/<pid>/status VmRSS |
proc_pidinfo resident size |
K32GetProcessMemoryInfo |
| CPU time | /proc/<pid>/stat utime+stime |
proc_pidinfo user+system |
GetProcessTimes |
| Children | /proc/<pid>/task/*/children |
proc_listchildpids |
CreateToolhelp32Snapshot |
Docker integration queries docker ps when --docker is passed.
Why portview
| Tool | Limitation |
|---|---|
lsof -i :3000 |
Different flags per OS, cryptic output, slow |
ss -tlnp |
Powerful but unreadable, no uptime/memory |
fkill-cli |
Requires Node.js, kill-first not diagnostic-first |
killport |
Kill-only, no inspection |
procs |
General process viewer, not port-centric |
portview is diagnostic-first: understand what's on your ports, then act.
Building from source
Limitations
- Linux: Needs read access to
/proc/<pid>/fd/. Other users' processes requiresudo. - macOS: Other users' processes may require
sudo. - Windows: Some system processes may not be accessible. Kill always force-terminates. Run as Administrator for full visibility.
- Docker: Requires the
dockerCLI and access to the Docker daemon.
License
MIT