GitHub - vercel-labs/portless: Replace port numbers with stable, named .localhost URLs. For humans and agents.
Service

GitHub - vercel-labs/portless: Replace port numbers with stable, named .localhost URLs. For humans and agents.

vercel-labs
2026.03.02
·GitHub·by 이호민
#agent#development#localhost#proxy#URL

Key Points

  • 1Portless replaces traditional, fragile port numbers in local development with stable, named `.localhost` URLs, enhancing the experience for both humans and AI agents.
  • 2It functions via a central proxy that automatically assigns free ports to applications and routes traffic from unique `.localhost` domains to their respective services.
  • 3This system resolves common development issues such as port conflicts, cookie clashes, and hardcoded ports, further offering HTTP/2 and HTTPS support with automatic certificate management.

Portless is a developer tool designed to replace ephemeral, numerical port assignments for local development servers with stable, human-readable, and agent-friendly .localhost URLs. Its primary goal is to resolve common pain points associated with traditional local development, particularly in environments with multiple services or monorepos.

The core problem addressed by Portless is the fragility of local development using hardcoded or dynamically assigned port numbers. This includes issues such as EADDRINUSE port conflicts, the cognitive load of memorizing which service runs on which port, browser tab confusion when different applications subsequently occupy the same port, and the compounding effect of these problems in monorepo setups. Furthermore, it tackles challenges with AI coding agents guessing incorrect ports, cookie and localStorage clashes across applications on localhost, broken hardcoded configurations (e.g., CORS allowlists, OAuth redirect URIs), difficulty sharing development URLs, and the lack of meaningful browser history for localhost entries.

Portless fixes these issues by introducing a central proxy and assigning stable, named .localhost URLs to each application. The methodology operates as follows:

  1. Central Proxy: A single portless proxy runs on a designated port (defaulting to 1355), serving as the entry point for all *.localhost traffic. This proxy can be started explicitly using portless proxy start or is automatically initiated when an application is registered. For ports below 1024 (e.g., port 80), sudo is required.
  2. Application Registration: When an application is launched via portless<name><command>portless <name> <command>, Portless internally assigns a free, random ephemeral port (typically within the 4000-4999 range) to that application. It then registers this <name><name> and its corresponding ephemeral port with the central portless proxy.
  3. Environment Variable Injection: For most modern frameworks (Next.js, Express, Nuxt), Portless passes the assigned port and host via standard PORT and HOST environment variables. For frameworks that do not inherently respect these (e.g., Vite, Astro, React Router, Angular), Portless intelligently auto-injects the necessary --port and --host command-line flags directly into the executed command.
  4. Proxy-Based Routing: When a browser or agent requests http://<name>.localhost:1355http://<name>.localhost:1355, the request is routed through the portless proxy. The proxy, based on its internal mapping, then forwards the request to the specific ephemeral port where the myapp application is actually running. This provides a stable, named entry point while allowing the underlying application to run on any available port.

Key features and functionalities include:

  • HTTPS/HTTP/2 Support: Portless can enable HTTPS and HTTP/2 for dev servers. This is activated with portless proxy start --https, which automatically generates and trusts a local CA (requiring a one-time sudo prompt to add to the system trust store). Custom certificates can also be used via --cert and --key flags. The PORTLESSHTTPS=1PORTLESS_HTTPS=1 environment variable makes HTTPS the default. HTTP/2 improves performance by multiplexing requests, mitigating HTTP/1.1's 6-connection limit, which is beneficial for unbundled dev servers.
  • Command-Line Interface (CLI):
    • portless<name><cmd>[args...]portless <name> <cmd> [args...]: Runs an application and maps it to http://<name>.localhost:1355http://<name>.localhost:1355.
    • portless list: Displays all currently active routes and their mapped ports.
    • portless trust: Manually adds the local CA to the system trust store.
    • portless proxy start: Explicitly starts the daemonized proxy.
    • portless proxy stop: Stops the proxy.
  • Disabling Portless: The PORTLESS=0PORTLESS=0 or PORTLESS=skipPORTLESS=skip environment variables can temporarily bypass Portless, allowing commands to run directly on their default ports.
  • State Management: Portless stores its state (routes, PID, port file) in a directory that varies based on the proxy port. For ports < 1024 (requiring sudo), state is shared in /tmp/portless. For ports >= 1024, it's user-scoped in ~/.portless. The state directory can be overridden with PORTLESS_STATE_DIR.
  • Inter-App Proxying: When one Portless-managed frontend (e.g., Vite, webpack) proxies API requests to another Portless-managed backend service (e.g., api.myapp.localhost:1355), it is critical to configure the frontend's proxy to rewrite the Host header. This is achieved by setting changeOrigin: true in the proxy configuration. Failure to do so results in the Host header of the original frontend being sent to the backend, causing the Portless proxy to route the request back to the frontend in an infinite loop, which Portless detects and responds with a 508 Loop Detected error.

Portless requires Node.js 20+ and runs on macOS or Linux operating systems.