TraLand.com
PortScope In development · not yet released

PortScope

Something is on port 3000. PortScope tells you which project.

A macOS app that shows what is listening on your local ports, names the project behind each one, and stops it safely. Not the process name — the project.

macOS · direct download, not the Mac App Store — see below for why

“It’s node” is the answer to a different question

You have five node processes. The one holding port 3000 belongs to one of your checkouts, and nothing on your machine will tell you which.

What lsof and netstat give you

  • The port
  • The PID holding it
  • The process name
  • Instantly, with no software to install

What they cannot give you

  • Which project. On a machine running several checkouts, node, python and ruby are noise.
  • A decision. You are handed a PID and left to work out for yourself whether killing it is safe.
How it works

From a port number to a project name

Two discovery sources, a resolution step that is allowed to say it does not know, and a stop that is a decision rather than a button.

01

Two sources, unioned

libproc walks each process’s file-descriptor table, giving a real listening socket, a real PID and full process metadata. A separate bind() occupancy sweep catches ports libproc cannot see into.

02

The project is resolved

Working directory, command line and project markers — package.json, pyproject.toml, Cargo.toml, .git and others — resolve to a project name, with a confidence tier of High, Medium or Low.

03

Every row says how sure it is

An authoritative row names the process and PID. An occupancy-only row says in use — owner unknown and claims nothing more. Low confidence never carries a project name; it shows the process instead.

04

Stopping is a decision

Stop sends SIGTERM to that PID only, with a grace period. Force Stop is a separate, deliberate second action. Children are not killed.

Project recognition

Measured, including the number that hurts

Independently measured over 63 real listening-socket processes — the only population PortScope ever displays.

95.2%
Named at all
A dev-server listener gets a name rather than a shrug.
82.5%
Correct, useful name
The name shown is the project you would have said yourself.
7.9%
Confidently wrong
0% on ordinary, realistic project shapes; 17.9% on deliberately adversarial ones.

The number to manage is the confidently-wrong rate, not the unrecognised rate. A row that admits it does not know costs you a moment. A wrong name shown confidently is the only outcome that costs trust.

Why that 7.9% is believable

It was measured five times. On four of those five rounds the resolver’s own test bed reported 0% confidently wrong. Independent beds measured 3.7%, 8.8%, 7.2%, 10.9% and 7.9%. The failure was the same every time: testing the fixed case instead of its neighbourhood.

What improved across those rounds was not the headline — it was the composition, which matters more. By the last round the ordinary subset of 35 scenarios was 0 confidently wrong and 0 wrong at any tier: vite, Next.js standalone, nodemon, node_modules/.bin shims, --import, --require, .mjs/.cjs/.ts, and real venv uvicorn, gunicorn and flask. The remaining 17.9% lives entirely in the 28 deliberately adversarial scenarios. Earlier rounds missed on plain, common shapes. Those now pass.

The controls

Mechanisms, not adjectives

What the app actually does, one line each.

Live table

Port, project or service, process, PID and address, refreshing on a roughly two-second cycle.

Project recognition

A resolved project name with an explicit confidence tier on every row, so you can see how much weight it carries.

Service labels and URL inference

Conservative by design: it offers to open a URL only where the inference is sound.

Detail inspector

Full process, project and socket detail for the row you have selected.

Safe termination

PID-only SIGTERM with a grace period. Force Stop is separate. Protected processes are refused rather than silently failing.

Search and Reveal in Finder

Search across every visible field, and jump straight to the project directory.

Scope

What PortScope is not

These are the limits that decide whether you can rely on a row. They are the reason to trust the rest of the page.

An occupancy row is not a listener.
bind() answers “can I bind this port?”, not “is something listening?” On one real machine, 66 ports reported occupied and only 10 were listeners — the other 56 were local ports held by outbound connections from things like Chrome and Slack. Those rows say “in use — owner unknown”, never “listening”.
A wildcard bind is not a security verdict.
0.0.0.0 and :: describe binding scope. Whether anything is actually reachable depends on firewall state, network topology and NAT, none of which PortScope can observe. It will never tell you a port is “exposed”.
Not a security scanner, a firewall, or a network monitor.
It shows local listening sockets on your own machine. That is the whole job.
Root-owned listeners are visible but not attributable in v1.
sshd and system-account databases appear as occupied ports without an owner. Full attribution needs a privileged helper — planned, not in v1.
Distribution

Not on the Mac App Store, by measurement

PortScope’s core capability is impossible inside the macOS App Sandbox. That is not an assumption — the same signed binary was run bare and sandboxed, and the difference is the whole product:

ProbeUnsandboxedSandboxed
TCP listeners discovered70
PROC_PIDLISTFDS on other processesPermitted EPERM — every process except the app itself
kill(), including kill(pid, 0)Permitted Denied outright

The file-descriptor table is the only structure linking a socket to a process, so losing it loses the product. Every route around it was tested, and each one failed.

So PortScope will ship direct — Developer ID, hardened runtime, and notarized. Stated as a decision rather than a grievance: it is the distribution the capability requires. The honest upside is no commission, no review latency, and updates that ship when they are ready.

Tell me when it ships

PortScope is in development. There is no download and no purchase yet. Leave an email and we will tell you when that changes.

One email when it ships. Nothing else, and we don’t pass it on.