waytunnel
v0.1.1
Published
Dev tunnel for mobile testing, PWA development, and coding on the go
Maintainers
Readme
waytunnel
Dev tunnel for mobile testing, PWA development, and coding on the go.
Expose any local dev server with an HTTPS tunnel and QR code. Test on your phone, develop PWAs with real HTTPS, or code from anywhere. One command.
npx waytunnel waytunnel - dev on the go
Detected vite project (bun)
Local: http://localhost:5173
Tunnel: https://random-name.trycloudflare.com
Provider: cloudflare
█▀▀▀▀▀▀▀█ ▀▀▀█▀█ █▀▀▀▀▀▀▀█
█ █▀▀▀█ █ █▀██▀▀ █ █▀▀▀█ █
█ █ █ █ ▀█▀▀█▀ █ █ █ █
█ ▀▀▀▀▀ █ █ █ █ █ ▀▀▀▀▀ █
█▀▀▀█▀█▀▀ ▀ ▀█▀▀ ▀▀█▀▀▀▀▀
▀██▀▀ █▀█▀▀█ ▀▀ █▀▀▀█▀▀█▀
█▀▀▀▀▀▀▀█ █▀▀█▀ █ █ ▀ █▀█
█ █▀▀▀█ █ ▀█▀█▀ ▀▀▀█▀ ▀▀
█ █ █ █ ▀▀▀ ▀█ ██▀▀█▀▀█
█ ▀▀▀▀▀ █ █▀ █▀ ▀▀█▀█▀▀▀
▀▀▀▀▀▀▀▀▀ ▀▀▀ ▀▀ ▀▀▀▀▀▀▀▀
Shortcuts:
q quit r restart c copy URL o open browserInstall
# Use directly
npx waytunnel
# Or install globally
npm i -g waytunnelUsage
Auto-detect (reads your package.json)
waytunnelDetects Vite, Next.js, Astro, Remix, Hono, or any project with a dev script.
Passthrough — run any command
waytunnel -- bun dev --port 3000
waytunnel -- python -m http.server 8080
waytunnel -- cargo leptos serve
waytunnel -- php artisan serveEverything after -- is your command. waytunnel parses the port and tunnels it.
Tunnel-only — expose an existing server
waytunnel --port 4000Choose a tunnel provider
waytunnel --provider cloudflare # default, free, no account
waytunnel --provider lt # localtunnel, free, no account
waytunnel --provider ngrok # requires account + authtokenNamed Tunnel — fixed custom domain
Quick Tunnels generate a random *.trycloudflare.com subdomain each time. For a permanent URL on your own domain, use a Cloudflare Named Tunnel.
One-time setup (free Cloudflare account required):
# 1. Login to Cloudflare
cloudflared tunnel login
# 2. Create a Named Tunnel
cloudflared tunnel create mydev
# 3. Route your domain to the tunnel
cloudflared tunnel route dns mydev dev.example.comThen use it with waytunnel:
waytunnel --tunnel mydev --hostname dev.example.com -- npm run devThe tunnel URL will always be https://dev.example.com.
LocalTunnel subdomain
Request a specific subdomain with localtunnel (not guaranteed if taken):
waytunnel --provider lt --subdomain myapp -- npm run dev
# → https://myapp.loca.ltSession Manager
waytunnel tracks active sessions so you can manage multiple tunnels.
# List active sessions
waytunnel ls
ID Port Provider Tunnel URL Command
-------------------------------------------------------------------------------------------------
a1b2c3d4 5173 cloudflare https://abc-xyz.trycloudflare.com bun dev
e5f6g7h8 3000 lt https://wild-fish-22.loca.lt npm run dev
# Stop by port or session ID
waytunnel stop 5173
waytunnel stop a1b2c3d4
# Stop all
waytunnel stop --allSessions auto-clean when processes die — no stale entries.
Keyboard Shortcuts
While running:
| Key | Action |
|-----|--------|
| q | Quit (clean shutdown) |
| r | Restart dev server |
| c | Copy tunnel URL to clipboard |
| o | Open tunnel URL in browser |
| Enter | Show status |
Config File (optional)
Create waytunnel.config.ts in your project root:
export default {
provider: "cloudflare",
port: 3000,
command: "bun dev",
};Pre-install cloudflared
waytunnel installDownloads the cloudflared binary to ~/.waytunnel/bin/.
Framework Configuration
Cloudflare Quick Tunnels serve your app from *.trycloudflare.com. Most dev servers block requests from unknown hosts by default. You need to allow the tunnel domain in your framework config.
Vite
// vite.config.ts
export default defineConfig({
server: {
allowedHosts: [".trycloudflare.com"],
},
});Next.js
// next.config.js
module.exports = {
allowedDevHosts: ["*.trycloudflare.com"],
};Or set the environment variable:
HOSTNAME=0.0.0.0 waytunnelHono (with @hono/vite-dev-server)
If using Vite as the dev server, same as Vite above. If running standalone:
// No config needed — Hono doesn't enforce host checks by default.Astro
// astro.config.mjs
export default defineConfig({
server: { host: true },
vite: {
server: {
allowedHosts: [".trycloudflare.com"],
},
},
});Remix (with Vite)
// vite.config.ts
export default defineConfig({
server: {
allowedHosts: [".trycloudflare.com"],
},
plugins: [remix()],
});Nuxt
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
server: {
allowedHosts: [".trycloudflare.com"],
},
},
});SvelteKit
// vite.config.ts
export default defineConfig({
server: {
allowedHosts: [".trycloudflare.com"],
},
plugins: [sveltekit()],
});Angular
// angular.json → serve → options
{
"allowedHosts": [".trycloudflare.com"]
}Django
# settings.py
ALLOWED_HOSTS = ["localhost", ".trycloudflare.com"]Laravel
# .env
APP_URL=https://your-subdomain.trycloudflare.com
SESSION_DOMAIN=.trycloudflare.comTip: If using localtunnel (
--provider lt), replace.trycloudflare.comwith.loca.lt.
How It Works
- Detects your project type and package manager
- Spawns your dev server (or uses an existing one)
- Waits for the port to be ready
- Starts a Cloudflare Quick Tunnel (free, no account needed)
- Displays the HTTPS URL + QR code
- Manages the session for multi-tunnel workflows
License
MIT
