PortShelf is a menu-bar utility that shows every local listening port, the process behind it, and the project that owns it - with safe local actions, named .localhost URLs, and opt-in sharing through Cloudflare or Tailscale.
Free download from GitHub. Local-first by default. Public routes are created only when you explicitly opt in.Expose a selected local listener on your Cloudflare-managed hostname, with PortShelf managing the tunnel, DNS route, Access policy, and cleanup.
Share privately to your tailnet with Tailscale Services, or publish an allowed Funnel port when your tailnet policy permits it.
Attach a friendly name to a project+port pair and open it as personal.localhost instead of hunting for localhost:3000.
PortShelf walks up from the process working directory past marker files - .git, package.json, go.mod, Cargo.toml - to name the project, not just the PID.
Next.js, Vite, Rails, Django, Go, Rust, Postgres, Redis and more, inferred from the command that started the listener.
Open the URL, copy it, reveal the project in Finder, or open it in your editor. One click each, right from the menu bar.
Copy Diagnostics strips token=, secret=, bearer and other secret-looking values before anything reaches your clipboard.
Menu-bar first with no Dock icon. Optional local notifications when common dev ports change. Launch at login if you want it.
When a listener belongs to a detected project, PortShelf can publish a bare .localhost route for it. Name your Gatsby site personal once, then open it through personal.localhost in the browser.
Named ports are scoped to a known project folder plus the port, so the route follows the project without claiming unknown system listeners.
Choose a lowercase single-label name like personal. PortShelf maps it to personal.localhost and keeps direct localhost:port URLs available.
An opt-in local router helper leases loopback port 80/443 only while PortShelf is open, then forwards traffic to the live listener.
localhost:3000HTTP or HTTPSHTTPS routes use a locally generated PortShelf CA. After one Keychain trust approval, PortShelf issues exact host certificates such as personal.localhost for Safari, Chrome, and Edge.
PortShelf inspects the local machine using the same macOS tools you would: lsof for listening sockets, ps for command and parent data. Named routing is an explicit opt-in helper that binds only to loopback while PortShelf is open. Sharing is also opt-in: Cloudflare uses OAuth, Tailscale uses user-provided OAuth client credentials, and secrets stay in Keychain.
PortShelf does not send process, project, port, diagnostic, route, or certificate data to a PortShelf backend. Cloudflare and Tailscale sharing touch third-party APIs only for listeners you explicitly share, and provider secrets stay in Keychain.
Read the full Privacy PolicyPortShelf is distributed as a direct download from GitHub Releases. It requires macOS 13.0 or newer.
This build is not notarized with an Apple Developer ID yet, so macOS will warn you on first open. The source is public, and you can build it yourself.
Or clear the quarantine flag in Terminal: