Quickstart
portctl eliminates hardcoded port numbers, prevents EADDRINUSE collisions, and automates public HTTPS ingress for local microservices.
1. Verify Installation
Section titled “1. Verify Installation”Check that portctl is present in your PATH:
portctl --version# Output: portctl 2.1.02. Inspect Current Port Registry
Section titled “2. Inspect Current Port Registry”Run portctl list to inspect all assigned ports, their scopes, and real-time socket statuses:
portctl list3. Run Your Application
Section titled “3. Run Your Application”Instead of hardcoding PORT=3000 or wrestling with .env files, run your development server through portctl run:
# Node.js / Next.js / Viteportctl run -- npm run dev
# Python / FastAPIportctl run -- uvicorn main:app --port $PORT
# Go / Rustportctl run -- ./serverportctl automatically:
- Detects the project name from
package.json,Cargo.toml,pyproject.toml, or the directory name. - Allocates a unique, deterministic port from the managed registry.
- Injects the assigned port into the environment variable
$PORT. - Executes your command with child process inheritance.
4. Query Assigned Port
Section titled “4. Query Assigned Port”To view the assigned port for the current project:
# Current directoryportctl get
# Or specify by project nameportctl get my-frontend5. Expose Locally Running Server to the Internet
Section titled “5. Expose Locally Running Server to the Internet”When you need to test webhooks (Stripe, GitHub, Shopify) or test on a mobile device, expose your service with Cloudflare Tunnel:
portctl expose my-app -d preview.example.comThis single command:
- Validates the domain name according to RFC 1123.
- Checks socket security guardrails (blocking sensitive internal ports).
- Adds a DNS route in Cloudflare.
- Updates ingress rules in
~/.cloudflared/config.yml. - Reloads the background
cloudflareddaemon.
To revoke the tunnel route when finished:
portctl unexpose my-app