tunnelkit
v0.0.13
Published
Run Cloudflare Tunnels (Quick, Remote, Local) from Node or Bun — a typed API and CLI, with zero dependencies.
Downloads
2,077
Maintainers
Readme
TunnelKit wraps the cloudflared binary into a typed library and a CLI command.
// API
const tk = new TunnelKit();
const { publicUrl } = await tk.quick.start({ service: 3000 });# CLI
tunnelkit quick 3000Why TunnelKit
- All three modes — Quick, Remote (token), and Local (named), each behind its own namespace.
- Fully typed events —
TunnelKitandCloudflaredTunnelare typedEventEmitters. - Manages the binary — downloads
cloudflaredon demand, or reuses one onPATH. - Persistence by default — tunnels you start are saved; restore them by name, or disable with
store: false. - Zero dependencies — pure Node built-ins. Runs on Node 18+ and Bun.
Quick start
| Mode | API | CLI |
| --- | --- | --- |
| Quick | tk.quick.start({ service }) | tunnelkit quick <port> |
| Remote | tk.remote.start({ id, token }) | tunnelkit remote run --token <token> |
| Local | tk.local.start({ id, name, tunnelId, credentialsFile, ingress }) | tunnelkit local run <name> --route <host>=<service> |
bun add tunnelkit # library
bun add -g tunnelkit # CLIcloudflared is downloaded on first use, or use one already on PATH.
The three modes
Quick — a random *.trycloudflare.com URL, no account needed.
const { publicUrl } = await tk.quick.start({
service: 8080, autoStopMinutes: 30
});tunnelkit quick 8080 --auto-stop 30Remote — dashboard-managed tunnel, run from a token.
const { ingress } = await tk.remote.start({
id: 'my-app', token: process.env.CF_TUNNEL_TOKEN!
});tunnelkit remote run --token "$CF_TUNNEL_TOKEN"
# tunnelkit remote run prod # reuse savedLocal — named tunnel: authenticate once, create, route DNS, run.
await tk.local.login({ onUrl, onComplete, onError });
await tk.local.create('acme-prod');
await tk.local.routeDns('acme-prod', 'app.example.com');
await tk.local.start({ id, name, tunnelId, credentialsFile, ingress });tunnelkit local login
tunnelkit local run my-app \
--route app.example.com=http://localhost:3000
# tunnelkit local run my-app # reuse savedInteractive panel
tunnelkit with no arguments opens a live TUI — view all tunnels, stop/start, copy URLs, manage
saved configs.
tunnelkit > tunnels
❯ ● quick-5173 → https://abc.trycloudflare.com
○ quick-3000 → https://xyz.trycloudflare.com
● remotely-prod → 2 routes
- http://localhost:4001 → app.example.com
- http://localhost:4002 → api.example.com
● locally-prod → 2 routes
- http://localhost:5001 → shop.example.com
- http://localhost:5002 → blog.example.com
[↑/↓] select [n] new tunnel [x] stop [c] copy URL
[m] manage saved [q] quitSee the CLI reference for all keybindings.
Events
tk.on('status-changed', (tunnels) => { });
tk.on('ingress-update', ({ id, ingress }) => { });
tk.on('connection', ({ id, info, status }) => { });The interactive panel shows live status per tunnel; --verbose prints diagnostics.
Persistence
Remote and local tunnels auto-save to <dataDir>/config.json. Quick tunnels are ephemeral.
new TunnelKit(); // auto-save
new TunnelKit({ store: false }); // disable
await tk.restoreAll(); // rehydrate alltunnelkit saved # list saved
tunnelkit forget <name> # remove entry
# auto-save on remote run / local runBinary management
tk.bin.status();
await tk.bin.ensure();
await tk.bin.install('2024.12.2');tunnelkit status
tunnelkit install [version]Options
| Option | API | CLI |
| --- | --- | --- |
| Data directory | { dataDir } | --data-dir |
| Install directory | { installDir } | --install-dir |
| Store / persistence | { store: false } | --no-save |
| Logger | { logger: console } | --verbose |
| Quick timeout | { quickTimeoutMs: 15000 } | — |
| Connection timeout | { connectTimeoutMs: 30000 } | — |
| Skip confirm | — | --yes / -y |
Low-level API
import { CloudflaredTunnel } from 'tunnelkit';
const tunnel = CloudflaredTunnel.quick('http://localhost:3000');
tunnel.on('url', (url) => console.log(url));Graceful shutdown
const shutdown = async () => { await tk.stopAll(); process.exit(0); };
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);From the CLI, Ctrl+C / q stops everything.
Documentation
- API reference — every export, option, method, and event.
- CLI reference — every command, option, and example.
- Examples — runnable scenarios.
License
MIT License — see LICENSE for details.
