portview
See what's on your ports, then act on it.
A diagnostic-first port viewer for Linux, macOS, and Windows. No more lsof -i :3000 | grep LISTEN incantations. One command shows you what's listening, who owns it, how long it's been running, and offers to kill it if you want.
~960 KB single binary. Zero runtime dependencies.
Install
One-liner (downloads pre-built binary):
|
PowerShell (Windows):
irm https://raw.githubusercontent.com/mapika/portview/main/install.ps1 | iex
Homebrew:
Cargo (build from source):
Manual: grab the binary from Releases, chmod +x, drop in PATH.
Usage
Show all listening ports
$ 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 │
╰──────┴───────┴───────┴──────┴──────────┴─────────┴────────┴─────────────────────────────────────╯
Inspect a specific 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
$ portview python
╭──────┬───────┬───────┬──────┬─────────┬────────┬───────┬──────────────────────────────────╮
│ PORT │ PROTO │ PID │ USER │ PROCESS │ UPTIME │ MEM │ COMMAND │
├──────┼───────┼───────┼──────┼─────────┼────────┼───────┼──────────────────────────────────┤
│ 8000 │ TCP │ 51002 │ mark │ python3 │ 22m │ 45 MB │ uvicorn main:app --port 8000 │
│ 8080 │ TCP │ 51340 │ mark │ python3 │ 5m │ 32 MB │ python3 -m http.server 8080 │
╰──────┴───────┴───────┴──────┴─────────┴────────┴───────┴──────────────────────────────────╯
Kill directly
Note: On Windows,
--killalways force-terminates the process viaTerminateProcess. There is no graceful shutdown equivalent to Unix SIGTERM.
Watch mode (interactive TUI)
Watch mode opens an interactive TUI with a scrollable table, row selection, filtering, and kill confirmation.
Keybindings
Table view:
| Key | Action |
|---|---|
j / ↓ |
Select next row |
k / ↑ |
Select previous row |
g / Home |
Jump to first row |
G / End |
Jump to last row |
Enter |
Inspect selected port (detail view) |
d |
Kill process (SIGTERM, with confirmation) |
D |
Force kill (SIGKILL, with confirmation) |
/ |
Enter filter mode |
< / > |
Cycle sort column left / right |
r |
Reverse sort direction |
1-8 |
Jump to column N (same column toggles direction) |
a |
Toggle all/listening-only ports |
q / Esc |
Quit |
Ctrl+C |
Quit |
Detail view: Esc to go back, d/D to kill, q to quit.
Filter mode: Type to filter across all columns, Enter to apply, Esc to cancel and clear.
Kill popup: y/Enter to confirm, n/Esc to cancel.
Use --watch --json for non-interactive streaming JSON output (no TUI).
JSON output
|
Show all connections (not just listening)
Custom colors
Table columns are colored by default. Customize with the PORTVIEW_COLORS environment variable:
PORTVIEW_COLORS="port=red,pid=magenta,command=bright_cyan"
Available columns: port, proto, pid, user, process, uptime, mem, command
Available colors: red, green, blue, cyan, yellow, magenta, white, bold, dimmed, bright_red, bright_green, bright_blue, bright_cyan, bright_yellow, bright_magenta, bright_white, none
One-shot defaults: port=cyan, proto=dimmed, pid=yellow, user=green, process=bold, uptime=dimmed, mem=dimmed, command=white
Watch mode uses a soft RGB color palette by default. Set PORTVIEW_COLORS to override, or --no-color to disable all colors.
What it shows
For each listening port:
| Field | Linux source | macOS source | Windows source |
|---|---|---|---|
| Port & protocol | /proc/net/tcp, /proc/net/udp |
proc_pidfdinfo |
GetExtendedTcpTable / GetExtendedUdpTable |
| PID | inode→pid mapping via /proc/*/fd/ |
proc_listpids |
Included in socket table |
| Process name | /proc/<pid>/comm |
proc_pidpath |
QueryFullProcessImageNameW |
| Full command | /proc/<pid>/cmdline |
proc_pidpath |
QueryFullProcessImageNameW |
| User | /proc/<pid>/status → getpwuid |
proc_pidinfo → getpwuid |
OpenProcessToken → LookupAccountSidW |
| Uptime | /proc/<pid>/stat starttime + btime |
proc_pidinfo start time |
GetProcessTimes |
| RSS memory | /proc/<pid>/status VmRSS |
proc_pidinfo resident size |
K32GetProcessMemoryInfo WorkingSetSize |
| CPU time | /proc/<pid>/stat utime + stime |
proc_pidinfo total user + system |
GetProcessTimes kernel + user |
| Child count | /proc/<pid>/task/<pid>/children |
proc_listchildpids |
CreateToolhelp32Snapshot |
Everything is read directly from the OS. No shelling out to lsof, ss, netstat, or netsh.
Why not...
| Tool | Issue |
|---|---|
lsof -i :3000 |
Different flags per OS, cryptic output, slow |
ss -tlnp |
Powerful but unreadable, no uptime/memory info |
fkill-cli |
Node.js dependency, kill-first not diagnostic-first |
killport |
Rust but kill-only, no inspection |
procs |
General process viewer, not port-centric |
portview is diagnostic-first: understand what's on your ports, then optionally act.
Building from source
Limitations
- Linux: Needs read access to
/proc/<pid>/fd/for inode→pid mapping. Processes owned by other users are hidden withoutsudo. - macOS: Processes owned by other users may not be visible without
sudo. - Windows: Some system/protected processes may not be accessible.
--killalways force-terminates (no graceful SIGTERM equivalent). Run as Administrator to see all processes.
License
MIT