🐾 paw-proxy

Stop fighting
localhost.

Named HTTPS domains for every local dev server. Zero config.

❯ up npm run dev
β†’ https://myapp.test βœ“
$ brew install alexcatdad/tap/paw-proxy
The problem

Three projects.
One port.

You have three Next.js projects. All of them want port 3000. The second one detects it's taken and silently moves to 3001.

Your OAuth callback is hardcoded to localhost:3000. Your test fixtures expect it. Your env files point to it.

You've been debugging the wrong app for 20 minutes.

❯ npm run dev # project-a
β†’ localhost:3000
❯ npm run dev # project-b
⚠ port 3000 in use, using 3001
β†’ localhost:3001
❯ open http://localhost:3001/auth/callback
βœ— OAuth error: redirect_uri_mismatch
  expected: http://localhost:3000/auth/callback
It gets worse

Same project. Two branches.
No idea which is which.

You're using git worktrees to run two branches of the same project side by side. Both register as "MyApp" on localhost. Both look identical in the browser tab.

You just spent 10 minutes testing code that hasn't changed β€” because you're hitting the wrong instance.

# ~/myapp (main branch)
❯ npm run dev β†’ localhost:3000
# ~/myapp-feat-auth (feature branch)
❯ npm run dev β†’ localhost:3001
# two browser tabs, both say "MyApp"
# ...which branch is this again?
# you refresh, nothing changed
# because you're hitting the wrong one
The insight

The problem isn't ports.
It's identity.

localhost:3000 doesn't tell you what you're running. A named domain does.

And once you have names, HTTPS comes free β€” real trusted certificates, no browser warnings, OAuth callbacks that just work.

# ports tell you nothing
localhost:3000  β†’ ???
localhost:3001  β†’ ???
localhost:3002  β†’ ???
# names tell you everything
myapp.test            β†’ myapp (main)
myapp-feat-auth.test β†’ feature branch
api.shop.test         β†’ shop's API
The fix

Just prefix with "up".

paw-proxy gives every dev server a named HTTPS domain. It handles DNS, certificates, port allocation, and worktree conflicts automatically. Zero config files. Zero nginx. Zero mkcert.

Auto SSL
Trusted certificates generated on-the-fly.
WebSocket & HMR
Hot module reload just works over HTTPS.
Docker Compose
Auto-discovers services β†’ service.project.test
Live Dashboard
Real-time request feed at _paw.test
Worktree Aware
Automatic fallback when domains collide.
# any dev server
❯ up npm run dev
β†’ https://myapp.test βœ“
# docker compose β€” every service gets a domain
❯ up docker compose up
β†’ https://frontend.shop.test βœ“
β†’ https://api.shop.test βœ“
# worktrees β€” automatic conflict resolution
❯ up npm run dev # ~/myapp-feat-auth
⚠ myapp.test in use
β†’ https://myapp-feat-auth.test βœ“
How it works

Three moving parts

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Browser │────▢│ paw-proxy │────▢│ Dev Server β”‚ β”‚ β”‚ β”‚ port 443 β”‚ β”‚ dynamic β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ DNS Server β”‚ *.test β†’ 127.0.0.1 β”‚ β”‚ port 9353 β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ └──── https://myapp.test βœ“ Trusted SSL
Get started

Up and running in 30 seconds

1 β€” install
brew install alexcatdad/tap/paw-proxy
2 β€” setup (once)
sudo paw-proxy setup
3 β€” use it
up npm run dev
Prior art

Standing on giants' shoulders

We modernized the wheel, didn't reinvent it.