Manage your ports — view, inspect, and kill processes on TCP ports
Project description
portctl
Manage your ports.
A cross-platform Python CLI tool for viewing, managing, and killing processes on TCP ports.
Inspired by port-whisperer by Larsen Cundric.
What it looks like
$ portctl
┌──────────────────────────────────────────┐
│ portctl │
│ scanning your ports... │
└──────────────────────────────────────────┘
PORT PROCESS PID PROJECT FRAMEWORK UPTIME MEM BIND STATUS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
:8000 python.exe 14320 payments-api FastAPI 3h 12m 48.7 MB public ● healthy
:5173 node 52981 dashboard Vite 22m 112.4 MB local ● healthy
:8080 go 8734 gateway Go 6d 1h 23.1 MB public ● healthy
:5432 docker 7712 — Docker (PG) 14d 8h 67.0 MB local ● healthy
4 ports active · Run portctl <port> for details · --all to show everything
$ portctl 5173
┌─────────────────────── Port :5173 ───────────────────────┐
│ │
│ Process node │
│ PID 52981 │
│ Status ● healthy │
│ Framework Vite │
│ Memory 112.4 MB │
│ Uptime 22m │
│ Started 2026-04-04 10:15:42 │
│ Bind local (127.0.0.1) │
│ Command node node_modules/.bin/vite --port 5173 │
│ │
│ Directory /home/mubarak/projects/dashboard │
│ Project dashboard │
│ Git Branch feat/charts │
│ │
│ Process Tree │
│ → node (52981) │
│ └─ bash (52900) │
│ └─ tmux: server (1120) │
│ │
└──────────────────────────────────────────────────────────┘
Run portctl kill 5173 to stop · portctl cmd 5173 to see startup command
$ portctl 8000-8100
:8000 python.exe (PID 14320) [FastAPI]
:8001 free
:8002 free
...
:8080 go (PID 8734) [Go]
:8081 free
...
:8100 free
$ portctl free 5173 -- npm run dev
✓ Killed node (PID 52981) on port 5173
Running: npm run dev
$ portctl kill 8000 8080
✓ Killed python.exe (PID 14320) on port 8000
✓ Killed go (PID 8734) on port 8080
Install
pip install portctl
# or
pipx install portctl
Alias:
pctlis available as a shorthand forportctl.
Quick Start
portctl # Show dev server ports
portctl 3000 # Inspect what's on port 3000
portctl kill 3000 # Kill it
portctl --version # Show installed version
portctl update # Update to latest version
Commands
List ports
portctl # Dev server ports only
portctl --all # All listening ports
portctl --sort mem # Sort by memory (also: uptime)
portctl -f django # Filter by process, framework, or project
portctl -n 5 # Limit to top N rows
Inspect a port
portctl 3000 # Detail view if occupied, "available" if free
Shows process info, framework, memory, uptime, bind address, working directory, git branch, and process tree.
Scan a range
portctl 8000-9000 # Show which ports are in use
Kill processes
portctl kill 3000 # Kill process on port 3000
portctl kill 3000 8080 # Kill multiple ports
portctl kill 3000 --force # Force kill (SIGKILL)
portctl kill 3000 --dry-run # Preview without killing
Free a port and run a command
portctl free 3000 -- npm start # Kill port 3000, then run npm start
portctl free 3000 5432 -- docker compose up # Free multiple, then run
Show startup command
portctl cmd 3000 # Print the command that started the process
portctl cmd 3000 --copy # Copy it to clipboard
Update & version
portctl update # Update portctl to the latest version
portctl --version # Show installed version
Utilities
portctl open 3000 # Open http://localhost:3000 in browser
portctl copy 3000 # Copy http://localhost:3000 to clipboard
portctl clean # Kill orphaned/zombie dev processes
portctl clean --dry-run # Preview without killing
Features
- Cross-platform - works on macOS, Linux, and Windows
- Framework detection - identifies Next.js, Vite, Django, FastAPI, Flask, Express, and 20+ others
- Project detection - finds project root and name from package.json, pyproject.toml, Cargo.toml, etc.
- Smart filtering -shows only dev processes by default, use
--allfor everything - Protected processes - refuses to kill system-critical processes (systemd, lsass, etc.)
- Git branch - shows which branch each process is running from
Framework, project, and protected processes detection can be expanded to cover more cases.
Platform Support
| Platform | Status |
|---|---|
| macOS | Supported (use sudo for full visibility) |
| Linux | Supported |
| Windows | Supported (run as admin recommended for full PID visibility) |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file portctl-0.2.1.tar.gz.
File metadata
- Download URL: portctl-0.2.1.tar.gz
- Upload date:
- Size: 16.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cb505d5703cc65cae099c76f4637c080273dcae04ba3684f70ad345e1aed8e9
|
|
| MD5 |
412c63cc3e6e9e3571d0842b57dbfab0
|
|
| BLAKE2b-256 |
7d47718aa5e03331de85982aecbd33bad4a6015e62f58fb5fdc5a7e2a825730e
|
Provenance
The following attestation bundles were made for portctl-0.2.1.tar.gz:
Publisher:
release.yml on mubbie/portctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portctl-0.2.1.tar.gz -
Subject digest:
5cb505d5703cc65cae099c76f4637c080273dcae04ba3684f70ad345e1aed8e9 - Sigstore transparency entry: 1252555508
- Sigstore integration time:
-
Permalink:
mubbie/portctl@3a416b2a23cd08ea6e0d1b01e21cc00d9c01b910 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mubbie
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a416b2a23cd08ea6e0d1b01e21cc00d9c01b910 -
Trigger Event:
push
-
Statement type:
File details
Details for the file portctl-0.2.1-py3-none-any.whl.
File metadata
- Download URL: portctl-0.2.1-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5a54aae2dcff09d5ab9b0da71b6c536961e626287658517098ccacda2242544
|
|
| MD5 |
6e04bfc8a2554f2b7f84838f3013956b
|
|
| BLAKE2b-256 |
863fac5c90d3b2fc1ed72e1f7ca3f3faac9d653350219d35327d23d4ed625c53
|
Provenance
The following attestation bundles were made for portctl-0.2.1-py3-none-any.whl:
Publisher:
release.yml on mubbie/portctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portctl-0.2.1-py3-none-any.whl -
Subject digest:
f5a54aae2dcff09d5ab9b0da71b6c536961e626287658517098ccacda2242544 - Sigstore transparency entry: 1252555515
- Sigstore integration time:
-
Permalink:
mubbie/portctl@3a416b2a23cd08ea6e0d1b01e21cc00d9c01b910 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mubbie
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a416b2a23cd08ea6e0d1b01e21cc00d9c01b910 -
Trigger Event:
push
-
Statement type: