Portless Integration
Named .localhost URLs for local development. Replaces localhost:3000 with https://myapp.localhost.
Full CLI reference: Load Read("${CLAUDE_SKILL_DIR}/references/upstream.md") for complete command docs.
New in 2026-04 (portless 0.10.x)
- HTTPS on 443 by default (breaking from 0.9.x http:1355). Valid cert, no setup.
--no-tls reverts. NODE_EXTRA_CA_CERTS auto-injected (0.10.2) into child processes — node HTTPS calls trust portless CA with zero setup.--wildcard subdomains — https://*.myapp.localhost for multi-tenant / preview routing.portless alias <name> <port> — map a docker-compose / emulate port to a named URL without a long-running run process.portless clean — full teardown: stops proxy, removes CA, wipes state, cleans /etc/hosts.--lan mode — mDNS .local hostnames reachable across wifi (phone, tablet, other machines) without router config.- Fixed app ports —
--app-port 3000 / PORTLESS_APP_PORT for tools that need a known port (debuggers, docker). - hosts-sync on by default for Safari compat (disable with
PORTLESS_SYNC_HOSTS=0). - HTTP/2 HMR fixes for Vite/VitePlus/Next.js dev — websocket upgrades no longer break under h2.
- Expo / React Native support —
portless run expo start gives Metro a stable URL for device QR codes.
When to Use
- Starting a dev server that agents or browser tests will target
- Running multiple services locally (API + frontend + docs)
- Working in git worktrees (branch-named subdomains)
- Local OAuth flows (stable callback URLs)
- Connecting emulate API mocks to named URLs
Quick Start
# Instead of: npm run dev (random port)
portless run npm run dev
# → https://myapp.localhost (stable, named, HTTPS on 443 — default in 0.10+)
# Multi-service
portless run --name api npm run dev:api
portless run --name web npm run dev:web
# → https://api.localhost, https://web.localhost
# LAN mode (0.10.0) — reachable from phone/tablet via mDNS
portless proxy start --lan
portless run npm run dev
# → https://myapp.local (resolves across the local network, no router config)
# Full teardown (0.10.1) — stops proxy, removes CA, wipes state, cleans /etc/hosts
portless clean
0.10.x breaking change: default switched from http://app.localhost:1355 to https://app.localhost on port 443. Use --no-tls to revert. NODE_EXTRA_CA_CERTS is injected into child processes automatically (0.10.2) — no manual cert setup. /etc/hosts is synced automatically for Safari; disable with PORTLESS_SYNC_HOSTS=0.
Framework-Specific Setup
Load Read("${CLAUDE_SKILL_DIR}/references/framework-integration.md") for full framework recipes.
Most frameworks (Next.js, Vite, Express) work with portless run <cmd>. Some need explicit flags:
| Framework | Auto-detected? | Extra flags needed |
|---|
| Next.js | Yes | None |
| Vite / Astro | Yes | None |
| Express / Fastify / Hono | Yes | None (reads PORT env var) |
| Ruby on Rails | Yes | None |
| FastAPI / uvicorn | No | --port $PORT --host $HOST |
| Django | No | $HOST:$PORT positional arg |
Why .localhost?
| Feature | .localhost (RFC 6761) | 127.0.0.1:PORT | /etc/hosts hack |
|---|
No /etc/hosts editing | Yes | Yes | No |
| HTTPS with valid cert | Yes | No | Manual |
| Wildcard subdomains | Yes | No | No |
| Works in all browsers | Yes | Yes | Varies |
| Cookie isolation per service | Yes | No | Yes |
| No port conflicts | Yes | No | Yes |
Key Environment Variables
When portless runs your command, it injects:
| Variable | Value | Use in agents |
|---|
PORT | Assigned ephemeral port (4000-4999) | Internal only |
HOST | 127.0.0.1 | Internal only |
PORTLESS_URL | https://myapp.localhost | Use this in agent prompts |
NODE_EXTRA_CA_CERTS | Path to portless CA *(auto-injected 0.10.2)* | Child node processes trust portless certs without setup |
Toggle env vars
| Variable | Effect |
|---|
PORTLESS=0 | Bypass portless entirely (CI) |
PORTLESS_SYNC_HOSTS=0 | Disable auto /etc/hosts sync (default: on in 0.10.1+) |
PORTLESS_STATE_DIR | Override state dir (default: ~/.portless or /tmp/portless for privileged ports) |
OrchestKit Integration Patterns
1. Agent-Accessible Dev Server
# Start with portless, then agents can target PORTLESS_URL
portless run npm run dev
# In ork:expect or agent-browser:
agent-browser open $PORTLESS_URL
2. Emulate + Portless (Named API Mocks)
# Register emulate ports as named aliases
portless alias github-api 4001
portless alias vercel-api 4000
portless alias google-api 4002
# Now agents can target:
# https://github-api.localhost — GitHub emulator
# https://vercel-api.localhost — Vercel emulator
3. Git Worktree Dev
# In worktree for feature/auth-flow:
portless run npm run dev
# → https://auth-flow.myapp.localhost (auto branch prefix)
4. Bypass in CI
# Disable portless in CI — direct port access
PORTLESS=0 npm run dev
Anti-Patterns
| Don't | Do Instead |
|---|
Hardcode localhost:3000 in tests | Use PORTLESS_URL or process.env.PORTLESS_URL |
| Run portless in CI | Set PORTLESS=0 in CI environments |
| Use numeric ports in AGENTS.md | Document the portless URL |
References
| File | Content |
|---|
references/upstream.md | Full portless CLI reference (synced from Vercel) |
references/upstream-oauth.md | OAuth callback patterns with stable URLs |
references/framework-integration.md | Framework recipes (FastAPI, Django, Docker, gotchas) |
checklists/new-project-setup.md | Step-by-step: add portless to a new project |