Guide
Bosun vs lsof: when is a menu bar app worth it over a one liner?
September 14, 20264 min read
Let us get the awkward part out of the way first. If you know the port number and you just want whatever is on it gone, lsof already solves that, it is already on your Mac, and it costs nothing:
lsof -ti :3000 | xargs kill
That is the honest baseline, and any comparison that pretends otherwise is wasting your time. So the real question is not “which one kills a process faster”, it is “when does the command line stop being the right tool”.
What the one liner actually does
It is worth understanding, because it is better than most people think.
The -t flag makes lsof print process IDs and nothing else. xargs takes every ID it printed and passes all of them to a single kill. So if four processes hold port 3000, which is what happens with multi worker servers like gunicorn, Odoo or a clustered Node app, all four get the signal at once.
You can verify it yourself. Start a server with a supervisor and three workers, then:
lsof -ti :9911
# 39238 39271 39272 39273
lsof -ti :9911 | xargs kill
# the port is free, all four are gone
A plain kill sends SIGTERM, which lets the process shut down cleanly. If something ignores it and the port stays busy, -9 forces the issue:
lsof -ti :3000 | xargs kill -9
Use the gentle version first. SIGKILL gives a process no chance to flush anything to disk.
Where the one liner runs out
The command works when you already know what you are looking for. It is weaker in three situations.
You do not know the port. lsof -i -P -n -sTCP:LISTEN will list everything that is listening, but the output is a wall of text with no sorting, no grouping, and IPv4 and IPv6 entries duplicated for the same process. Reading it is the slow part, not typing it.
The process name tells you nothing. Docker is the classic case. Every published container port belongs to a process called docker-proxy, so lsof shows you six identical rows and no way to tell which container is which. Same story with a bare node or python when you have several projects open.
The thing you forgot about is not a port at all. An ngrok tunnel or a cloudflared quick tunnel is a live route from the public internet into your laptop. It does not appear in a port listing in any way that identifies it. Neither does an active VPN connection. If you want to answer “what is my Mac exposing right now”, lsof is the wrong question to be asking.
What Bosun adds
Bosun runs the same lsof call underneath. It is not a different way of reading the kernel, it is a different way of reading the output, kept permanently visible.
It groups by port number, so a multi worker service collapses into one row with a worker count instead of eight identical lines. It maps docker-proxy back to the actual container image and Compose project. It detects ngrok and Cloudflare tunnels, including quick tunnels, and shows the public URL. It shows whether a native macOS VPN is connected. It keeps a history, so you can see what was listening earlier and not only what is listening now.
None of that is impossible from a terminal. It is just several commands, some of which you would have to look up, and you would have to remember to run them.
An honest recommendation
| Situation | Use |
|---|---|
| You know the port, you want it free, right now | lsof -ti :PORT | xargs kill |
| Scripting, CI, a remote machine over SSH | lsof, every time |
| You are not on macOS | lsof, Bosun is macOS only |
| “What is running on this machine right now?” | Bosun |
| Several Docker containers competing for ports | Bosun |
| Checking whether a tunnel is still open to the internet | Bosun |
If you spend your day in one project with one dev server, learn the one liner and skip the app. Genuinely. The people Bosun is for are the ones running several services at once, or tunnels, or a stack of containers, who want the answer visible without going to look for it.
Bosun is a macOS menu bar app with a 14 day free trial and no signup. It needs macOS 14 or later.
See this instead of typing it
Bosun lives in your menu bar and shows every open port on your Mac, live, mapped to the process behind it. One-click kill, SIGTERM first. Useful the first time this happens. Genuinely useful the fifth time it happens in one afternoon.