
Portless
Give every local app a stable `https://name.localhost` URL so you, teammates, and coding agents stop guessing ports and fighting `EADDRINUSE`.
Install
npx skills add https://github.com/vercel-labs/portless --skill portlessWhat is this skill?
- Maps dev servers to stable `https://<name>.localhost` URLs via a global or per-project portless install (not one-off `np
- Targets monorepo pain: port conflicts, wrong-tab refreshes, cookies bleeding on shared `localhost`, and agents testing t
- Documents proxy setup, dev server naming, `.localhost` behavior, and port/proxy troubleshooting
- Improves shareable local URLs for teammates instead of “what port is that on?” Slack threads
Adoption & trust: 3.1k installs on skills.sh; 9.7k GitHub stars; 2/3 security scanners passed (skills.sh audits).
Recommended Skills
Journey fit
Portless is installed and wired into dev scripts during product construction—the canonical shelf is Build → integrations because it connects your stack to a local reverse proxy, not production deploy. Named `.localhost` hosts replace hardcoded `localhost:PORT` in CORS, OAuth, and env config—classic integration work between the repo and your machine’s dev network.
Common Questions / FAQ
Is Portless safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Portless
# Portless Replace port numbers with stable, named .localhost URLs. For humans and agents. ## Why portless - **Port conflicts**: `EADDRINUSE` when two projects default to the same port - **Memorizing ports**: which app is on 3001 vs 8080? - **Refreshing shows the wrong app**: stop one server, start another on the same port, stale tab shows wrong content - **Monorepo multiplier**: every problem scales with each service in the repo - **Agents test the wrong port**: AI agents guess or hardcode the wrong port - **Cookie/storage clashes**: cookies on `localhost` bleed across apps; localStorage lost when ports shift - **Hardcoded ports in config**: CORS allowlists, OAuth redirects, `.env` files break when ports change - **Sharing URLs with teammates**: "what port is that on?" becomes a Slack question - **Browser history is useless**: `localhost:3000` history is a mix of unrelated projects ## Installation Install globally (recommended) or as a project dev dependency. Do NOT use `npx` or `pnpm dlx` for one-off execution. ```bash # Global (available everywhere) npm install -g portless # Or per-project dev dependency npm install -D portless ``` When installed per-project, invoke via package.json scripts or `npx portless` (since the package is local, npx will not download anything). ## Quick Start ```bash # Install globally (or add -D to a project) npm install -g portless # Run your app (auto-starts the HTTPS proxy on port 443) portless run next dev # -> https://<project>.localhost # Or with an explicit name portless myapp next dev # -> https://myapp.localhost ``` The proxy auto-starts when you run an app. You can also start it explicitly with `portless proxy start`. Auto-start reuses the configuration (port, TLS, TLD) from the most recent proxy run, so a restart or reboot does not silently revert to defaults. Explicit env vars always take priority. In non-interactive environments (no TTY, or `CI=1`), portless exits with a descriptive error instead of prompting. Task runners like turborepo should pre-start the proxy. ## Integration Patterns ### Zero-config (recommended) Bare `portless` works out of the box. It runs the `"dev"` script from `package.json` through the proxy, inferring the app name from the package name, git root, or directory: ```bash portless # -> runs "dev" script, https://<project>.localhost pnpm dev # -> works without portless, plain "next dev" ``` Use an optional `portless.json` to override defaults (name, script, port): ```json { "name": "myapp" } ``` ```bash portless # -> runs "dev" script, https://myapp.localhost ``` ### Monorepo One `portless.json` at the repo root. Portless discovers packages from `pnpm-workspace.yaml`, or the `"workspaces"` field in `package.json` (npm, yarn, bun): ```json { "apps": { "apps/web": { "name": "myapp" }, "apps/api": { "name": "api.myapp" } } } ``` ```bash portless # from repo root: start all packages with a "dev" script cd apps/web && portless # start just one package portless --script start # run "start" instead of "dev" ``` The `apps` map is optional and only provides name overrides. Unlisted packages auto-discover with inferred names. Without an `apps` map, hostnames follow `<package>.<project>.localhost`. The project name comes from the most common npm scope (e.g. `@myorg/web` and `@myorg/api` produce `myorg`), falling back to the workspace root directory name. If a package's short name matches the project name, it uses the bare `<project>.localhost`. ### Turborepo For turborepo projects, use portless as the `dev` script with the real command in a separate script: ```jso