Coming soon
A tunnel you fully own
pks-agent-tunnel
A self-hosted devtunnel replacement that exposes your local services to the public internet over one connection you control — no big cloud in the path.

A tunnel is the one thing that has to just work. Most don't.
To reach your agents from anywhere, your traffic gets routed through someone else's cloud — a vendor tunnel sitting between your laptop and the internet. That convenience hides a cost: split-brain across regions, races over which port owns which name, opaque CLI errors with nothing to grep, and URLs that churn every time you restart. When the demo dies five minutes before it matters, the path you don't own is exactly where you can't look. We lived this with Microsoft's devtunnel.ms in Aspire long enough to build the replacement.
Your traffic crosses a cloud you don't run, can't inspect, and can't fully trust.
Vendor tunnels hand you fresh, churning URLs — and demand a scorched-earth cleanup between runs.
When it breaks, the failure is opaque: 404s with nothing behind them and a split-brain you can't reach.
How it works
Run one server.
Stand it up on any VPS with two docker run lines — public frontend and control plane. No database, no Compose, no cluster. State is one folder you can back up with a single tar.
Point DNS once.
A wildcard and an apex record at your box, and you're done. Every tunnel you ever make lives under that one domain.
Connect and expose.
Run agent-tunnel host, name a slot, point it at a local port. The CLI holds one connection open and prints your public URL.
Reach it from anywhere.
The same name maps to the same URL on every restart — share it, script it, demo it. No cleanup, no churn, no surprises.

One server you run
A single self-hosted server on a VPS handles every tunnel — no vendor cloud, no tenant, no region to go split-brain on you.

Stable, deterministic URLs
The same slot and tunnel name always map to the same subdomain — no -{hash} churn between restarts.

One connection, many streams
HTTP, WebSocket, and raw TCP all ride a single persistent control connection, multiplexed with yamux — one socket, many streams.

Database-free by design
All state lives in one folder as plain .md sidecars. tar czf is a complete backup. No migrations, no schema, nothing to corrupt.

Drop-in for Aspire DevTunnels
Swap one using line and your AddDevTunnel code keeps compiling. The Aspire surface matches Aspire.Hosting.DevTunnels exactly.

No cleanup between runs
Reconnects reuse the same names and URLs. No scorched-earth teardown, no per-port race — restart as often as you like.
We own the whole path. Frontend, control plane, and CLI are ours, end to end. Nothing of yours crosses a cloud we don't run — that's the entire reason it exists.
No database to depend on. State is plain files in a folder, not a service that can drift, lock, or need migrating. One less thing you don't control.
Runs everywhere. A two-line docker run on any VPS — Hetzner, your own box, an air-gapped network. No managed service, no lock-in, no region map.
Composes, not couples. Same folder-backed storage convention as pks-agent-inbox and pks-agent-ftp. It's a layer in the suite, not an island — back it up the same way, run only what you need.
Composes with
No big cloud in the path.
Expose any local app to the internet over a single connection to one server you run. Stable URLs that survive every restart. No tenant, no region split-brain, no cleanup ritual between runs.