Skip to main content

Overview

Portless automatically detects git worktrees and uses the branch name as a subdomain prefix. This gives each worktree its own URL without any configuration changes or name collisions.

How Detection Works

Portless uses a multi-step heuristic to detect worktrees:

Branch Name Handling

Default Branches

The main worktree (on main or master) gets no prefix:

Slashes in Branch Names

Branches with slashes use only the last segment:

Sanitization

Branch names are sanitized to be valid DNS labels:
  • Lowercased
  • Non-alphanumeric characters replaced with hyphens
  • Consecutive hyphens collapsed
  • Leading/trailing hyphens trimmed
  • Truncated to 63 characters (RFC 1035 limit)
Examples:

Fallback Detection

If the git binary is unavailable, portless falls back to parsing the .git file:
This ensures portless works even in minimal environments (Docker, CI) where git may not be installed.

Examples

Basic Worktree Setup

Both instances run simultaneously without conflicts.

Monorepo with Multiple Services

Explicit Subdomain with Worktree Prefix

If you use an explicit subdomain, the worktree prefix is still prepended:

Disabling Worktree Detection

Use the --no-worktree flag with portless get to skip worktree detection:
This is useful when you need a consistent URL regardless of the current worktree.
There is currently no flag to disable worktree detection for portless run or portless <name>. If you need this, use --name to force a specific name:

Integration with package.json

Put portless run in your package.json scripts:
package.json
This works everywhere:
  • Main worktree: pnpm devhttp://myapp.localhost:1355
  • Linked worktree: pnpm devhttp://fix-ui.myapp.localhost:1355
No configuration changes needed.

Wildcard Subdomain Routing

Worktree URLs benefit from wildcard subdomain routing. If you register myapp.localhost, then:
  • myapp.localhost routes to your app
  • fix-ui.myapp.localhost routes to your app
  • auth.myapp.localhost routes to your app
  • anything.myapp.localhost routes to your app
This means you can run multiple worktrees without explicitly registering each one:
Wildcard routing matches the longest registered suffix. If you explicitly register fix-ui.myapp.localhost, that route takes precedence over the wildcard match for myapp.localhost.