TunnelTime

TunnelTime Docs

Use one token across multiple running clients, expose HTTP or TCP services, and decide whether a tunnel is public, allowlisted, or dynamically locked to the first client that reaches it.

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.

Good mental model: the token is your tenant identity, while each running 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.

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, or dynamic

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 http

Direct Downloads

Checksums

Use the published SHA-256 checksums to verify downloaded binaries before running them.

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
  • 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.

Common use cases: Vite or Next.js preview URLs, webhook development, temporary admin panels, or sharing an internal dashboard with one other person.

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.

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.

When to use dynamic: one trusted person needs temporary access and you do not know their IP in advance. When not to use it: unstable mobile networks, rotating proxy chains, or anything fronted by another proxy unless you trust the forwarded client IP.

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, or dynamic
  • 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.

Best practice: use 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, and rm still 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 allowlist or dynamic for sensitive services such as SSH and databases.
  • Use dedicated subdomains for long-lived tunnels so they are easy to recognize in list.
  • Use list regularly when one token is shared across multiple machines.
  • Use logout when a machine should no longer hold the saved token.
  • Remember that dynamic locks to the first successful client IP. If that caller’s source IP changes, reconnect may fail until the tunnel is recreated.