PortKiller puts a kill control on every listening TCP port
A powerful cross-platform port management tool for developers. Monitor ports, manage Kubernetes port forwards, integrate Cloudflare Tunnels, and kill processes with one click.
At a glance
- What is it?
- PortKiller is a Swift desktop app that turns the machine's listening TCP port table into a clickable list, then wraps kubectl port forwards and Cloudflare Tunnel status around it. The window is the whole interface, and the documentation stops short of the settings and dependencies you would need to run any of it unattended.
- Who is it for?
- PortKiller fits a developer on a Mac or Windows laptop who keeps a pile of local servers and kubectl forwards open and wants one list to act on. It is the wrong tool for a Linux box, a headless server, or any workflow that needs scripted, non-interactive kills.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- productdevbook/port-killer5,174 ★ · +113
| Repository | 2026-09-11 | 2026-11-14 |
|---|---|---|
| productdevbook/port-killer | 5.1k | 5.2k |
113 Stars in the last 64 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Auto-discovery stops at listening TCP sockets
PortKiller builds its list from listening TCP sockets, and that one choice decides what you can see. UDP listeners never appear, so a resolver, a metrics agent or a QUIC service holding a UDP port stays invisible even though it will stop your own bind. Outbound connections are out of scope for the same reason: the view is a socket table snapshot, not a traffic view. Search and filtering work on port number or process name, and entries fall into four buckets, Web Server, Database, Development and System, which is convenient right up to the moment two processes matter equally and you have to guess who claimed the Development bucket. The README does not say how ownership is resolved when a port belongs to another user's process.
Graceful and force kill sit one click apart
Termination is described as a single click with a graceful path and a force path, and nothing in between. There is no dry run, no preview of what the target process currently holds, and no listing of child processes that would go down with it. A database listener and a dev server look the same in a list filtered by port number, so a misclick on a busy afternoon costs you whatever that process had buffered. The README does not document a confirmation step, an allowlist, or any way to undo a kill, which leaves your own habit of noting the pid first as the only safety net.
The refresh interval is a value you find in the app
A configurable refresh interval drives the whole view, and its default, its limits and the place you change it are written down nowhere except inside the running application. That matters more than it sounds. Auto-discovery plus auto-refresh means the row you aimed at can be a different row a moment later, and a fast interval on a busy machine turns what should be a stable inventory into a list that shifts while you read it. Favorites and watched ports are the two ways to pin what you care about: favorites give quick access to important ports, and watched ports add notifications. Neither one has a documented notification permission step per platform, so treat delivery as unverified until you watch it fire on your own machine.
Kubernetes forwarding wraps kubectl and documents none of it
Port forwards are handled as kubectl port-forward sessions, with auto-reconnect on connection loss, connection logs, status monitoring, and notifications on connect and disconnect. That is the entire documented contract for the Kubernetes side. Installing kubectl, picking a context, selecting a namespace and passing credentials are all outside it, so on an unusual kubeconfig the failure surface belongs to kubectl and PortKiller adds a place to watch it happen. Two consequences follow from the documented behaviour. The forward's local socket appears in the same port list as your own servers, so a kill aimed at a stale entry can take down the forward along with whatever you meant to stop. And auto-reconnect means a dropped forward can return on its own, so a port you believe you closed may be bound again when you next start your server.
Tunnel status is a panel, not a documented control surface
The Cloudflare side gets two lines: view and manage active Cloudflare Tunnel connections, and quick access to tunnel status. Read literally, that is a status panel with a manage verb attached to it. The README does not name the binary that owns those connections, does not explain how they are discovered on the machine, and does not define what manage covers. You cannot tell from the documentation whether the app starts a tunnel, stops one, or only reads a list somebody else maintains. The practical effect is that a tunnel you expect to see may not appear, and there is no documented screen inside the app for finding out why. If tunnel visibility is the reason you are considering this tool, verify it first, because the rest of the feature list stands up without it.
A cask on a personal tap, a zip on Windows, nothing for Linux
macOS has two documented paths and Windows has one. The Homebrew path is a cask on the maintainer's own tap, and the tap is part of the command rather than a detail you can drop:
brew install --cask productdevbook/tap/portkillerLeave out the tap segment and Homebrew looks for a cask published somewhere it is not. The manual route is a .dmg from the Releases page, and on Windows the archive is a .zip you extract. No Linux package, snap, AppImage or flatpak is documented, even though the project describes itself as cross-platform: the two host integrations given are a macOS menu bar and a Windows system tray, and nothing addresses a Linux desktop or a headless machine. That gap decides who can use this. If your day is spent in an SSH session on a remote server, the port list you are after is not here.
The JavaScript package.json only bumps the version
The repository splits into platforms/ and portkiller-core/, which fits the claim of a native UI per platform with shared logic behind it, but the README never says what portkiller-core exposes or what the interface to each platform app looks like. The JavaScript side is thinner than the layout suggests. package.json is marked private and carries exactly one script, a release bump:
{
"name": "portkiller",
"version": "3.4.0",
"private": true,
"scripts": {
"release": "bumpp"
},
"dependencies": {
"bumpp": "^10.3.2"
},
"changelogithub": {
"emoji": true,
"contributors": true,
"capitalize": true,
"group": true
}
}There is no build, test or lint entry here, and a bun.lock file sits beside a Swift codebase, so these manifests will not produce a working development environment. CONTRIBUTING.md is named as the place for development setup, and this README does not repeat it. On cadence, the last push was 2026-10-15, the same day as the newest tag, v3.4.0, which followed v3.3.3 on 2026-06-21 and v3.3.2 on 2026-06-13. An appcast.xml sits at the top level and nothing here explains what feeds it or whether updates can be turned off.
Editorial conclusion
PortKiller fits a developer on a Mac or Windows laptop who keeps a pile of local servers and kubectl forwards open and wants one list to act on. It is the wrong tool for a Linux box, a headless server, or any workflow that needs scripted, non-interactive kills. Before you commit, check three things yourself: that the processes you care about show up with the right owner, that the refresh interval and notifications behave as you need, and that kubectl and the tunnel view connect in your environment. The install path is one cask command, `brew install --cask productdevbook/tap/portkiller`, plus a .dmg or a .zip if you would rather not use a package manager. The last push was 2026-10-15 and the newest tag is v3.4.0 from the same day; pin a release rather than tracking the default branch.
Frequently asked questions
How do I kill a process on a port with PortKiller?
The app auto-discovers listening TCP ports, and you can search or filter by port number or process name. The matching row gets a one-click termination control that offers a graceful stop and a force kill, with favorites and watched ports available for the ports you check often.
How do I kill port 5000?
Type 5000 into the port search or filter to narrow the discovered list, then use the termination control on the row that holds it. Only listening TCP ports are discovered, and the kill offers both a graceful path and a force path with no documented undo.
Does PortKiller have a Linux build?
No Linux package is documented. The install paths given are a Homebrew cask or a .dmg on macOS and an extracted .zip on Windows, and the platform integration described is a menu bar app on macOS and a system tray app on Windows.
What does PortKiller need for the Kubernetes and Cloudflare features?
The Kubernetes side is described as kubectl port-forward sessions with auto-reconnect, connection logs and status monitoring. The Cloudflare side is described as viewing and managing active tunnel connections. Nothing spells out which binaries must be installed, how connections are discovered, or how credentials reach kubectl.
How recently has PortKiller been worked on?
The last push to the repository was 2026-10-15. The most recent tagged release is v3.4.0, published the same day, following v3.3.3 on 2026-06-21 and v3.3.2 on 2026-06-13.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/productdevbook-port-killer)Star history chart for your README
[](https://hysenlabs.com/projects/productdevbook-port-killer)Was this useful?