Skip to content
Development
Skill

/portless

Set up and use portless for named local dev server URLs (e.g. https://myapp.localhost instead of http://localhost:3000). Use when integrating portless into a project, configuring dev server names, setting up the local proxy, working with .localhost domains, or troubleshooting

From plugin
portless
13k2 skills

Claude Code

$ npx -y skills add vercel-labs/portless --skill portless --agent claude-code

SKILL.md

portless.SKILL.md
name: portless
description: Set up and use portless for named local dev server URLs (e.g. https://myapp.localhost instead of http://localhost:3000). Use when integrating portless into a project, configuring dev server names, setting up the local proxy, working with .localhost domains, or troubleshooting port/proxy issues.

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.

# 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

# 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 saved port, TLS, TLD, and LAN settings only after the proxy exits unexpectedly. A normal `portless proxy stop` clears them, so the next start uses the flags and environment variables it is given. Explicit env vars 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:

portless        # -> runs "dev" script, https://<project>.localhost
portless -- --inspect  # -> runs "dev --inspect"
pnpm dev        # -> works without portless, plain "next dev"

Arguments after `--` go to the script. At a monorepo root, portless passes them to each app it starts. Forwarding through a script with shell operators or a comment exits 2; run the command directly or make the script a single command. In Turbo mode only the root script is checked, and Turbo passes the arguments to each package script unchanged.

Use an optional `portless.json` to override defaults (name, script, port):

{ "name": "myapp" }
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):

{
  "apps": {
    "apps/web": { "name": "myapp" },
    "apps/api": { "name": "api.myapp" }
  }
}
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:

{
  "scripts": { "dev": "portless", "dev:app": "next dev" },
  "portless": { "name": "myapp", "script": "dev:app" }
}

`pnpm dev` runs turbo, which runs `portless` in each package. Portless detects the package manager and runs `pnpm run dev:app` through the proxy.

When `portless` runs from a workspace root, it uses the existing Turbo integration to preserve task ordering when either `turbo.json` or `turbo.jsonc` is readable. Set `"turbo": false` in the root portless configuration to use direct spawning instead.

package.json scripts

You can still use portless directly in scripts:

{
  "scripts": {
    "dev": "portless run next dev"
  }
}

The proxy auto-starts when you run an app. Or start it explicitly: `portless proxy start`.

Multi-app setups with subdomains

portless myapp next dev          # https://myapp.localhost
portless api.myapp pnpm start    # https://api.myapp.localhost
portless docs.myapp next dev     # https://docs.myapp.localhost

By default, only explicitly registered subdomains are routed (strict mode). Start the proxy with `--wildcard` to allow any subdomain of a registered route to fall back to that app (e.g. `tenant1.myapp.localhost` routes to the `myapp` app). Exact matches always take priority over wildcards. When several registered routes are parents of the host, the most specific one wins (`admin.api.myapp.localhost` routes to `api.myapp`, not `myapp`).

Git worktrees

`portless run` automatically detects git worktrees. In a linked worktree, the

Read more
@vercel-labs-2
Ships withportless

Replace port numbers with stable, named .localhost URLs for local development. For humans and agents. portless runs a local reverse proxy and gives each dev server a name.

Stars on GitHub

Momentum

stars in total
12.9k
Star history of vercel-labs/portless on GitHub, a chart by star-history.com

Other skills on portless.

oauth

oauth

Configure OAuth providers (Google, Apple, Microsoft, Facebook, GitHub, etc.) to work with portless local dev URLs. Use when…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about portless.

Which coding agents can use portless?
portless installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.