Your laptop isn't the only machine with mystery ports. Somewhere there's a staging box where port 8080 has been taken since March, nobody remembers by what, and the last person to look ran four different commands to find out. le is a single static binary, so the fix is the same one you use locally: run it, read the table.
The dance it replaces
On a server the usual investigation goes: ss -tlnp for the socket (or netstat, if the box is old enough), squint at a truncated process name, ps aux | grep to expand it, ls /proc/<pid>/cwd to find out where it lives, and docker ps to check whether the PID you're looking at is really a container — because if it is, kill is the wrong verb and the container runtime will just restart it. Four commands, most of them needing sudo, to answer one question.
le list answers it in one:
$ le list 8080
PORT PID WHAT DIR RISK OWNER STOP WITH
8080 2113 api-server /srv/deploy/api medium container docker stop api-server
Same table as on your Mac: the process's real name, its working directory, who owns it, and the stop that will actually stick. On Linux the owner detection cares most about one distinction — plain process versus container — because that's the difference between SIGTERM working and the runtime resurrecting the thing behind your back.
One binary, no dependency graph
Getting it onto a server is a copy, not an installation. The release tarballs are static Go binaries for amd64 and arm64:
# grab the linux tarball for your arch from the Releases page, then:
tar -xzf le_*_linux_*.tar.gz
sudo mv le /usr/local/bin/
No runtime, no package manager, no root beyond the mv. It needs ps and lsof on the box and nothing else. And because a binary you curl onto a server deserves more suspicion than one from a package manager, every tarball is checksummed and carries a signed build-provenance attestation — gh attestation verify le_*.tar.gz --repo alikatgh/le-cli proves it was built by CI from the public repo, not on someone's laptop.
The clipboard that reaches back through the tunnel
The detail that makes the TUI genuinely usable on a remote box: press c on a row and the stop command lands on your local clipboard, not the server's. There's no clipboard daemon involved — le emits OSC 52, the terminal escape sequence for "here's clipboard content," and your terminal carries it home through the SSH session like any other output. Works in iTerm2, kitty, WezTerm, Alacritty, and recent tmux.
The workflow that falls out: SSH in, le, arrow to the culprit, c, and the exact docker stop command is waiting on your Mac — ready to paste into the runbook, the incident channel, or the next shell. The TUI never runs anything you didn't confirm; x asks first, every time.
CI runners are Linux boxes too
The same binary earns its place in pipelines. The classic flaky-test culprit — the suite starts before the service is listening — is a one-liner:
le ready 5432 -t 30s || exit 1 # wait for Postgres, bounded
le list --json # snapshot what's listening, for the job log
ready blocks until something listens (exit non-zero on timeout), wait blocks until a port frees, and --json makes the table scriptable — the same three primitives whether the machine is your laptop or a runner that lives for ninety seconds.
The engine underneath is unchanged from the one the engineering post dissects: every stop re-verifies the PID's start time first, so a recycled PID — more common on servers, where PIDs churn fast — never gets a signal meant for something else.
Put it on the box.
MIT-licensed. macOS and Linux, amd64 and arm64. brew install alikatgh/tap/le at home, one tarball everywhere else.