Overview
TunnelTime lets you expose a local HTTP service or TCP port through tunneltime.dev with a lightweight client binary and one agent token.
The CLI is designed for the common case: log in once, run a single command to expose one service, and keep that process running. Each running tunnel process owns its own live session, but management commands operate across every tunnel attached to the same token.
tunneltime http ... or tunneltime tcp ... process is a separate live session under that token.Install
Use the installer scripts if you want the fastest path from download to saved token and optional first tunnel. The guided flow downloads the binary, asks for your token, asks whether to start a tunnel now, then walks through tunnel type, local port, optional subdomain, and access mode.
macOS Installer
sh <(curl -fsSL https://tunneltime.dev/install.sh)This downloads the correct Mac binary for Apple Silicon or Intel and launches the guided setup prompts.
Linux Installer
sh <(curl -fsSL https://tunneltime.dev/install.sh)This downloads the correct Linux binary for your architecture and launches the guided setup prompts.
Windows Installer
powershell -ExecutionPolicy Bypass -Command "& { iwr https://tunneltime.dev/install.ps1 -OutFile install.ps1; .\install.ps1 }"This downloads tunneltime.exe and launches the same guided setup flow on Windows.
What The Installer Asks
- your agent token
- whether to start a tunnel now
- HTTP or TCP
- the local port to expose
- an optional custom subdomain, with blank meaning auto-generate
- the access mode:
public,allowlist, ordynamic
Before the installer starts the tunnel, it prints the exact tunneltime command it is about to run so you can reuse it later without the installer.
Compatibility Mode
The old argument-driven installer forms still work for scripting and existing docs:
sh <(curl -fsSL https://tunneltime.dev/install.sh) <agent-token> 3000 http
.\install.ps1 -Token '<agent-token>' -Port 3000 -Mode httpDirect Downloads
Checksums
Use the published SHA-256 checksums to verify downloaded binaries before running them.
macOS
curl -fsSLO https://tunneltime.dev/downloads/tunneltime-darwin-arm64.sha256
curl -fsSLO https://tunneltime.dev/downloads/tunneltime-darwin-arm64
shasum -a 256 -c tunneltime-darwin-arm64.sha256
Linux
curl -fsSLO https://tunneltime.dev/downloads/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing
Windows PowerShell
iwr https://tunneltime.dev/downloads/tunneltime.exe.sha256 -OutFile tunneltime.exe.sha256
(Get-FileHash .\tunneltime.exe -Algorithm SHA256).Hash
The PowerShell hash should match the first value in tunneltime.exe.sha256.
tunneltime login
Stores your agent token locally so later commands can reuse it automatically.
tunneltime login <agent-token>
tunneltime login <agent-token> --server https://api.tunneltime.dev
Use this once per machine or user account. After that, commands like http, tcp, status, and list will reuse the saved token unless you override it with --token.
The CLI stores config in:
- Windows:
%AppData%\TunnelTime\config.json - macOS:
~/Library/Application Support/TunnelTime/config.json - Linux:
~/.config/TunnelTime/config.json
tunneltime http
Creates a public HTTPS endpoint for a local web service. This is the command you use for dev servers, dashboards, webhook receivers, preview environments, and internal web tools.
tunneltime http 5173
tunneltime http 3000 --subdomain readiversebot
tunneltime http http://127.0.0.1:8080 --subdomain myapp
If you pass a bare port, TunnelTime assumes http://127.0.0.1:<port>. If you want a predictable public URL, pass --subdomain. Otherwise use a random subdomain when appropriate.
tunneltime tcp
Creates a public TCP relay to a local port. Use this for SSH, databases, custom TCP services, or anything that is not HTTP.
tunneltime tcp 22
tunneltime tcp 22 --subdomain northstar
tunneltime tcp 5432 --local-host 127.0.0.1
The server allocates a public relay port automatically from its configured TCP range. If you provide --subdomain, the returned address will use that hostname plus the assigned port, for example northstar.tunneltime.dev:22003.
Use tcp when the client on the other end expects a raw TCP socket and does not speak HTTP.
Private Forwarding
Private forwarding publishes named TCP services to other clients using the same agent token without creating a public URL or public TCP port. A destination host runs tunneltime serve, and a source client runs tunneltime services and tunneltime connect to bind one service to a local loopback address.
Destination config
machine:
id: lab-r32
name: r32
services:
- name: rdp
protocol: tcp
local_host: 127.0.0.1
local_port: 3389
- name: ssh
protocol: tcp
local_host: 127.0.0.1
local_port: 22
connect:
connection_mode: auto
defaults:
meter: auto
Run the destination
tunneltime serve --config tunneltime.yaml
You can also publish a single TCP service without a YAML file:
tunneltime serve --machine-name r32 --service rdp --local-host 127.0.0.1 --local-port 3389
Connect from a source client
tunneltime services
tunneltime connect r32/rdp --listen 127.0.0.1:1000 --connection-mode auto
The connect target can be machine/service, service_id, a unique service name, or a unique machine ID. If no target is supplied, the CLI lists available services and prompts for a selection.
auto tries direct QUIC over UDP first using TunnelTime STUN metadata and falls back to the HTTPS/WebSocket relay when direct connectivity fails. Use --connection-mode relay to force the relay path, or --connection-mode direct to fail instead of falling back.
Private forwarding commands read tunneltime.yaml from an explicit --config path, from the executable directory, or from the TunnelTime user config directory. Runtime status is written to tunneltime.status.json beside the loaded config when available.
Use the configuration builder to create a private forwarding config file without sending form data anywhere.
Access Control
Both http and tcp support the same access modes through --access. This lets you decide whether a tunnel is public, restricted to known IP ranges, or locked to whoever connects first.
--access public
tunneltime http 5173 --access public
tunneltime tcp 22 --access public
This is the default. Any client that can reach the public endpoint can connect.
--access allowlist
tunneltime http 5173 --access allowlist --allow 203.0.113.10 --allow 198.51.100.0/24
tunneltime tcp 22 --access allowlist --allow 203.0.113.0/24
Only the listed IPs or CIDR blocks can connect. Use this when you know where the caller will come from, such as a home IP, office IP block, VPN egress, or a known service.
--access dynamic
tunneltime http 5173 --access dynamic
tunneltime tcp 22 --access dynamic
The first successful client IP claims the tunnel. After that, only that IP can keep using it until the tunnel is closed or expires.
tunneltime status
Shows a tenant-wide summary for the saved token: whether it is configured, whether any sessions are connected, and aggregate tunnel counts and limits.
tunneltime status
Use this when you want a quick high-level view without listing every tunnel individually.
tunneltime list
Lists every HTTP and TCP tunnel associated with the current token. This is the command to use when you need the exact public URL, TCP address, session ownership, access mode, or dynamic lock state.
tunneltime list
Common reasons to run it:
- find the public port assigned to a TCP tunnel
- see which session owns a tunnel when multiple machines share one token
- confirm whether a tunnel is
public,allowlist, ordynamic - see which client IP has claimed a dynamic tunnel
tunneltime rm
Closes one tunnel or every tunnel for the current token.
tunneltime rm <tunnel-id>
tunneltime rm --all
Use rm <tunnel-id> when one public endpoint is no longer needed. Use rm --all when you want to shut down everything tied to that token, including tunnels created from other running sessions.
list first, copy the exact tunnel ID, then remove only what you intend to close.tunneltime logout
Deletes the saved local config so future commands no longer reuse the token automatically.
tunneltime logout
This does not revoke the token server-side. It only removes the local saved credentials from this machine.
Token And Session Model
One token can back multiple running clients at the same time. Each http or tcp process creates or reclaims its own server-side session, and each tunnel is owned by the session that created it.
- You can run one app on your laptop and another on a server with the same token.
list,status, andrmstill operate across the whole token.- Reconnects reclaim the same session so temporary disconnects do not create duplicate ownership.
Common Recipes
Share a local Vite or React app
tunneltime http 5173 --subdomain my-preview
Expose SSH but lock it to the first client that connects
tunneltime tcp 22 --subdomain northstar --access dynamic
Expose Postgres only to one office CIDR
tunneltime tcp 5432 --access allowlist --allow 203.0.113.0/24
Share an internal web tool only with one known IP
tunneltime http 8080 --subdomain admin-preview --access allowlist --allow 198.51.100.17
Best Practices
- Prefer
allowlistordynamicfor sensitive services such as SSH and databases. - Use dedicated subdomains for long-lived tunnels so they are easy to recognize in
list. - Use
listregularly when one token is shared across multiple machines. - Use
logoutwhen a machine should no longer hold the saved token. - Remember that
dynamiclocks to the first successful client IP. If that caller’s source IP changes, reconnect may fail until the tunnel is recreated.