Skip to main content

Local dev port registry + scanner. Claim ports per project, detect clashes before your app fails to bind.

Project description

portchk

Local dev port registry + scanner. Claim ports per project, detect clashes before your app fails to bind.

If you run multiple local projects, you know the pain: everything defaults to 3000 or 8000, and two of them collide. portchk keeps a lightweight registry of which project claims which port, and reconciles it against what's actually listening so you see a clash before your app refuses to start.

  • Cross-platform: macOS/Linux via lsof, Windows via netstat + tasklist
  • Zero dependencies: Python 3.8+ standard library only
  • Safe by default: confirmation prompt before killing processes; read-only until you explicitly act
  • Single JSON registry: ~/.config/portchk/registry.json (per-machine)

Install

pip install portchk

Or from source:

git clone https://github.com/shivswami/portchk.git
cd portchk
pip install .

Quick start

portchk                          # show live listeners + registry status
portchk add 3000 myapp           # claim port 3000 for "myapp" (uses cwd)
portchk add 8000 backend -p ~/projects/api
portchk                          # now shows CLAIMED / CLASH / unregistered
portchk next 3000                # find the next free port >= 3000

Commands

Command Description
portchk Default: live listening ports with registry status
portchk list Show all registered projects and their ports
portchk conflicts Show only ports claimed by more than one project
portchk next [port] Print the next free TCP port at or after port (default 3000)
portchk add <port> <name> Claim a port for a project (path = current dir)
portchk add <port> <name> -p /path Claim with explicit project path
portchk rm <port> Release a claim
portchk kill <port> [--force] Kill the process listening on a port
portchk isfree <port> Exit 0 if free, exit 1 if in use (for scripting)
portchk wait <port> [--timeout N] Block until port is free (default 30s)
portchk export [env|dotenv|json] Dump registry as env vars, dotenv, or JSON
portchk --version Print version
portchk --help Show usage

Status output explained

Running portchk shows every listening TCP port and how it relates to your registry:

  • claimed:myapp (green) — the port is live and its process cwd matches a registered project path
  • claimed:myapp (cyan) — the port is registered, but cwd could not be confirmed (Windows, or system process)
  • CLASH (claimed by ...) (yellow) — the port is live but the running process doesn't match the registered project
  • unregistered (grey) — the port is in use but not in your registry

Killing processes

When you find a clash, kill the offender directly:

portchk kill 3000              # prompts for confirmation
portchk kill 3000 --force      # skip prompt, SIGKILL on Unix / taskkill /F on Windows

Without --force, you'll be asked to confirm. The command kills whatever process is listening on that port, whether or not it's in your registry.

Scripting with isfree and wait

isfree and wait are designed for CI, Makefiles, and shell scripts. They use exit codes, not text, to signal state:

# Only start dev server if port is free
portchk isfree 3000 && npm run dev

# Conditional logic
if portchk isfree 5432; then
    echo "starting database..."
fi

# In CI: wait for a port to free up after teardown
docker-compose down
portchk wait 5432 --timeout 60
pytest

isfree exits 0 if the port is free, 1 if in use. wait polls every 0.5s and exits 0 when the port frees up, or 1 on timeout.

Exporting the registry

Export your registered ports for use in docker-compose, Makefiles, or .env files:

portchk export env       # MYAPP_PORT=3000 / BACKEND_PORT_1=8000 / BACKEND_PORT_2=8001
portchk export dotenv    # same format, alias
portchk export json      # raw registry JSON

Wire into docker-compose:

portchk export dotenv > .env
docker-compose up

Variable naming: NAME_PORT for single-port projects, NAME_PORT_1, NAME_PORT_2 for multi-port. Hyphens and spaces in project names become underscores.

Why not just a markdown file?

A markdown list rots the day you forget to update it, can't be queried, and won't flag a clash until your app fails to bind. portchk gives you a queryable registry (portchk next) and a live scan that shows the actual state of your machine.

Why not a background service?

A port manager shouldn't need its own port. portchk runs on demand and exits. No daemon, no background process, no extra listening socket.

Registry format

~/.config/portchk/registry.json:

{
  "projects": {
    "myapp": {
      "ports": [3000],
      "path": "/Users/you/projects/myapp"
    },
    "backend": {
      "ports": [8000, 8001],
      "path": "/Users/you/projects/api"
    }
  }
}

The registry is per-machine (ports differ across machines) so do not sync it.

Windows note

On macOS/Linux, portchk can read each process's working directory, so it can confirm that the process on a registered port is actually your project (green claimed:). Windows does not expose a process's cwd without elevation, so on Windows the status falls back to port-number matching only. Clashes are still detected; the cwd confirmation degrades gracefully.

Requirements

  • Python 3.8+
  • macOS / Linux: lsof (pre-installed on macOS, available on all major Linux distros)
  • Windows: netstat and tasklist (both built into Windows)

No other dependencies. portchk uses the Python standard library only.

License

MIT — see LICENSE.

Copyright (c) 2026 Shivprakash Swami.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

portchk-0.1.0.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

portchk-0.1.0-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file portchk-0.1.0.tar.gz.

File metadata

  • Download URL: portchk-0.1.0.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for portchk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 357f9527602338d9a8a34543c1a193e0f4126d2a3924276c5245aa8fcbb5a69c
MD5 aef2d4bc9ac0a0b091898f76d4743546
BLAKE2b-256 d3067f4a9ac09bd81adcddb3adfc15977282ff93cb30965173c5ddd6f5374110

See more details on using hashes here.

File details

Details for the file portchk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: portchk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for portchk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2ed786d6ebf7bdfc3708308aa6a5db53da241f2e8bc2be4bf7a8af41a5187d73
MD5 4b6d464256d446c001c4d21aa1240f47
BLAKE2b-256 4b080dfd841c4b72c1fedb2fb856e67f5d86ce263de55f853f6d03b0c7c3ce1d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page