Terminal program  /  MIT  /  29 stdlib modules, nothing else

Your machine,observed.

Twelve things are listening on localhost and you cannot name half of them. AI coding tools make this worse: Claude, Cursor and Codex start servers you never typed, and days later nothing tells you what is still up or what is safe to kill. lsof gives you a PID. This gives you the agent session that started it, the project it belongs to, and whether anyone has touched it since Tuesday.

Listening
12services on this host
Off-box
02reachable from the network
AI agents
06coding tools read, never written to
Telemetry
00nothing leaves the machine
$ curl -fsSL https://mr-hunt-007.github.io/portlist/install.sh | sh other ways
Plate 02  —  the program itself press 0-9, V, or use the keys below
 PORTLIST  devbox               16 listening  2 off-box  2 need attention                                                       O 02:35:00
 0 Dashboard   1 Services   2 Exposed   3 Attention   4 Leftovers   5 Agents   6 Containers   7 Sessions   8 System   9 Graph
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  machine   load 4.87 5.38 5.40 ──────────────────  exposure ──────────────  agents ────────────────  containers ──────────────
     ·             ·                          LISTENING    16           Claude Code  14           ENGINE       docker       
   ·              ·                              EXPOSED      2            terminal     1            STATE        no answer    
  ·    49%           86%           98%          NEEDS WORK   2            launchd      1            COUNT        unknown      
   ·   CPU           RAM          DISK          UNATTRIBUTED 12                                                  not zero     
     ·  ·                                                                                                                   
  ▄▃▂▁  ▁▁▂▃▄▄▃   ▃▅▆▇▆▅▃▁  ▁▂▄   ▁▃▅▇██▆▄▂▁ ▁▂         ▁▁▁▁▁▁      ▁▁▁▁▁▁     ▆▇▇▆▄▂  ▁▃▅▇██▆▄▂▁ ▁▂    ······················    
 ────────────────────────────────────────────────── ───────────────────────── ───────────────────────── ───────────────────────────
  ▂▂▁    ▁▂▂▂▂▂▁▁   ▁▁▂▂▂▂▂▁   ▁▁▂▂▂▂▂▁    ▁▂▂▂▂▂▁▁   ▁▁▂▂▂▂▂▁    ▁▂▂▂▂▂▁▁   ▁▁▂▂▂▂▂▁    ▁▂▂▂▂▂▁▁   ▁▁▂▂▂▂▁▁   ▁▁▂▂▂▂▂▁    ▁▂▂▂▂▂▁▁   ▁▁▂▂
  LISTENING  16 services  O LIVE                                                                                    h/l pane   tab view
    PORT    SERVICE               PROJECT           STARTED BY          REACH           RISK             UPTIME   minutes ━━━━▸ weeks   (lo
   :7337   shopfront             shopfront         terminal            Localhost only  6 Info           ━━━━━━━━━━━━━                10h
   :8000   Python http.server    analytics         Claude Code         Localhost only  12 Info          ━━━━━━━━━━━━━━━━━━━━━━━━━━━  21d
   :8078   sink.py               payments          Claude Code         Localhost only  6 Info           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 29d
   :8422   store-helper.mjs      data-export       Claude Code         Localhost only  6 Info           ━━━━━━━━━━━━━━━━━━━━         2d
▸  :8787   Python http.server    data-export       Claude Code         All interfaces  71 High          ━━━━━━━━━━━━━━━━━━━━━━       6d
  SELECTED SERVICE                                                                ACTIVITY
                                                                                 
  Python http.server :8787                                                       
  ~/Downloads/data-export                                                         CPU
                                                                                  ▄▄▄▄▄▄▄▄▄▄▄▄▄
  RISK  71 / 100   High                                                           MEMORY
    +42   Listening on all interfaces (0.0.0.0)                                   ▇▇▇▇▇▇▇▇▇▇▇▇▇
    +10   No authentication seen and reachable off-box                           
    +10   Static file server exposing its working directory off-box              
   2 exposed     2 need attention    ⚠ 12 unknown origin     3 agents    firewall on      ▁  ▁▁▂▃▄▄▃▂▁   ▁▂▃▄▄▃▃▂▁
 j/k move   h/l pane   tab view   enter detail   O open   / search   f free port   V vibe   q quit                          updated 1s ago
real screens, captured from a running machine

Does anyone else end up with a pile of things running on localhost and forget what half of them are?

A dev server, two APIs, a database, a container, a tunnel. You started some. Claude, Cursor and Codex started the rest, days ago, in a window you have since closed. Nothing on the machine can tell you which is which, so none of it gets turned off and it all comes back tomorrow.

lsof can tell you a PID owns port 8000. It cannot tell you that an agent opened it on Tuesday while working on the billing retries, in a project you have not touched since, and that nothing has connected to it in six days. That second answer is the one that lets you close it.

01

What is listening?

Every TCP and UDP service, one row each, named from the command and the project rather than from a port number. A row is a service on a port, not a port: two processes can hold the same number with different reach, and collapsing them loses the one that matters.

you asklsof saysportlist says
what is on :8787?Python, pid 96798 a static file server, started by a Claude Code session, in ~/code/data-export
who started it?nothingthat session, and whether it has since exited
can anyone reach it?0.0.0.0, a bind string what answered when it connected to this machine's real address
is it still needed?how long it has been up how long it has been unused, measured over time
is it safe to kill?nothing what depends on it, and the command to stop it
02

Who started it? Usually an AI.

Process ancestry first, environment second, and a launch record last. On a machine where Claude Code, Cursor, Codex or Copilot is doing the typing, most of what is listening was started by something other than you, and the useful question stops being which process and becomes which session, in which project, and does it still matter. Six AI coding tools are read from the store each already writes, and nothing is installed into any of them.

Claude Code Codex Cursor GitHub Copilot Gemini CLI VS Code pl six AI coding tools  /  read, never written to
 PORTLIST  devbox               16 listening  2 off-box  2 need attention                                                       O 02:35:15
  0 Dashboard   1 Services   2 Exposed   3 Attention   4 Leftovers  5 Agents   6 Containers   7 Sessions   8 System   9 Graph
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 PORT    SERVICE                 PROJECT           REACHABLE      RISK     STARTED BY
 a Claude Code session  -  session has exited  -  14 services
 :8000   Python http.server      analytics         Localhost only 12 Info  Claude Code 21d
 :8078   sink.py                 payments          Localhost only 6 Info   Claude Code 29d
 :8422   store-helper.mjs        data-export       Localhost only 6 Info   Claude Code 2d
 :8787   Python http.server      data-export       All interfaces 71 High  Claude Code 6d
 :8787   FastAPI / Uvicorn       scanner           Localhost only 12 Info  Claude Code 23d
 :8807   Python http.server      data-export       All interfaces 71 High  Claude Code 3d
 :42065  Bun                     portlist          Localhost only 0 Info   Claude Code 4h
 :48744  Bun                     shopfront         Localhost only 0 Info   Claude Code 25h
 :55302  Bun                     portlist          Localhost only 6 Info   Claude Code 4h
 :56050  Bun                     ~/Downloads       Localhost only 6 Info   Claude Code 3h
 :56609  Bun                     scanner           Localhost only 6 Info   Claude Code 25d
 :57244  Bun                     data-export       Localhost only 6 Info   Claude Code 6d
 :59195  Bun                     ~/Downloads       Localhost only 0 Info   Claude Code 3h
 :61535  Bun                     shopfront         Localhost only 6 Info   Claude Code 25h
 a terminal  -  still running  -  1 service
 :7337   shopfront               shopfront         Localhost only 6 Info   terminal 10h
 launchd  -  still running  -  1 service
 :9050   Tor                     /opt/homebrew     Localhost only 12 Info  launchd 24d





───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 j/k move   h/l pane   tab view   enter detail   O open   / search   f free port   V vibe   q quit                          updated 1s ago
Plate 03  —  系統grouped by who started it
The same services, grouped by the thing that started them. Eleven under one agent session is a fact about your machine that a flat list hides, and the group says whether that session is still running or has since exited.
03

Which of those windows can you close?

Twelve AI coding sessions open, none of them closed, and no way to tell them apart from the outside. You have wondered which of them is still doing something, which left a server behind, and which you can safely close. Every one is a transcript on disk that Claude, Codex, Copilot, Cursor or Gemini already wrote. Reading those is the difference between a list of processes and a list of decisions.

  • Open now, then left on disk. A session with a process behind it is one you can act on. One without is a transcript nobody is holding. Mixing them in a single list ordered by recency buried the only rows that matter.
  • What it was actually about. The title its own tool generated, and the first prompt you typed to start it, which is usually the thing you recognise when the title is not enough.
  • How much it is carrying. The tokens on the last turn, taken from the usage the transcript records, next to a bar comparing it with the biggest session on this machine. Not a percentage of a context window: nothing on disk says what that model's limit is, so no number here pretends to.
  • How long since anyone touched it. Five hours, six days, a fortnight. Stale is the axis you actually close along.
  • Which account is paying. One line per tool for the plan it is signed in under, because that is the answer to which one is burning quota.
  • It prints the command; you run it. And when four agents share a directory it says so rather than picking one, because a kill that might close the wrong window is worse than no command at all.
 PORTLIST  devbox               16 listening  2 off-box  2 need attention                                   04:18:52
  0   1   2   3   4   5   6  7 Sessions   8   9
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 TOOL     WHAT IT WAS ABOUT                       PROJECT           CONTEXT  VS BIGGEST  LAST USED
 4 agent processes running  -  30 transcripts on disk
     Claude Code      claude max - default claude max 20x
     Codex            not signed in
     GitHub Copilot   signed in
     Gemini           signed in

 6 open right now  -  2.9M tokens between them  -  oldest untouched 5h
 * claude Refactor the billing webhook retries    payments              225k ██░░░░░░    13s ago     4 here
 * claude Port the admin table to components      admin-ui              904k ████████    19m ago     4 here
 * claude Trace the flaky integration test        api                   479k ████░░░░    28m ago     4 here
 * claude Add a rate limit to the upload route    storefront            307k ███░░░░░    28m ago     4 here
 * claude Write the migration for the new index   scanner               628k █████░░░    5h ago      4 here
 * claude Fix the timezone bug in the report      analytics             334k ███░░░░░    5h ago      4 here

 24 left on disk, no process behind them
   claude Split the worker into two queues        worker                935k ████████    7h ago
   claude Make the search endpoint paginate       docs                  193k ██░░░░░░    9h ago
   claude Update the deploy script for staging    infra                 196k ██░░░░░░    27h ago     4 here
   claude Cache the pricing lookup                checkout              182k ██░░░░░░    2d ago
   claude Retry the webhook on 5xx                payments              518k ████░░░░    2d ago      4 here
   claude Move the cron into the scheduler        admin-ui              371k ███░░░░░    2d ago
   claude Document the auth flow                  api                   287k ██░░░░░░    2d ago      4 here
   claude Drop the unused columns                 storefront            240k ██░░░░░░    3d ago      4 here
   claude Tidy the error messages                 scanner                53k ░░░░░░░░    6d ago      4 here
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 j/k move   h/l pane   tab view   enter detail   O open   / search   f free port   V vibe   q quit    updated 0s ago
Plate 04  —  エージェントagent sessions
Open now at the top, with a process behind each one. Everything under it is a transcript nobody is holding. Press enter on any row for the first prompt it started from, where it got to, and the command that closes it.

Six tools, each read from the store it already writes: Claude Code, Codex, GitHub Copilot CLI, VS Code chat, Cursor and Gemini CLI. Nothing is installed into any of them, nothing is written back, and no prompt leaves the machine — the reading happens here and stops here.

04

Does it matter?

Reachability checked by connecting to this machine's real address, not by reading a bind string. Risk as a score with every reason attached, so it can be argued with rather than believed. Use measured over time, because a process can be up for a month and touched this morning.

  • It never stops anything. The detail pane prints the command and you run it. A tool that both guesses which process is abandoned and can end it will eventually end the wrong one.
  • It opens no listening socket. It connects outward to see what answers, and binds a candidate port for a moment to check it is free. Neither calls listen().
  • It sends nothing anywhere. No server, no telemetry, no update check. Agent transcripts are read locally and stay there.
  • It says unknown out loud rather than letting a stale process inherit a repository label from whatever owns the port now.
05

One scan, one model, ten views.

A view is a question asked of the model, never a second trip to the machine. That is why switching views is instant, why the counts always agree with the rows underneath, and why a new view costs a filter rather than a collector.

the machine one model ten views socketsprocesses containersgit roots transcripts a row per serviceon a port signature, not pid ~/.portlist launch ledger, use history 0 dashboard5 agents 1 services6 containers 2 exposed7 sessions 3 attention8 system 4 leftovers9 graph a filter or a grouping, never a second scan read once filter, group written once, never rewritten
The ledger is the only thing that persists, and it is matched by signature rather than by pid, which is what lets provenance survive a restart.
06

Install.

One program, no dependencies, nothing system-wide unless your package manager puts it there. Uninstalling leaves one directory you can delete.

# into ~/.local, no root, nothing system-wide
$ curl -fsSL https://mr-hunt-007.github.io/portlist/install.sh | sh

Piping into a shell deserves suspicion, so read it first: one tarball, two directories.

$ brew tap Mr-hunt-007/portlist https://github.com/Mr-hunt-007/homebrew-portlist
$ brew trust mr-hunt-007/portlist   # asked of every third-party tap
$ brew install portlist

The trust step is not optional: Homebrew refuses a tap it has not been told to trust, and says so rather than installing anything.

$ pipx install git+https://github.com/Mr-hunt-007/portlist
$ pip  install git+https://github.com/Mr-hunt-007/portlist

Straight from the repository: the name portlist on PyPI belongs to an unrelated package, so the distribution will be portlist-tui while the command stays portlist.

$ git clone https://github.com/Mr-hunt-007/portlist
$ cd portlist && python3 portlist.py

No build step. The standard library is the whole dependency list.

07

Questions.

The ones worth answering before you install anything that reads your machine.