# tunli

> Developer-first HTTP tunneling CLI with daemon-based tunnel management, profiles, and self-hosted server support.

Latest version **0.8.0** (published 2026-09-24) · GPL-3.0 license · 0 weekly downloads

## Install

```sh
npm install tunli
pnpm add tunli
yarn add tunli
bun add tunli
```

Provides the command `tunli`.

## Health

**Score 60/100 (C)** — status: active.

Positive: esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads; no types; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.8.0 |
| Published | 2026-09-24 |
| First published | 2024-06-06 |
| Weekly downloads | 0 |
| License | GPL-3.0 |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Node | >=22 |
| Dependencies | 8 |
| Unpacked size | 604.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 2 |
| Author | Pascal Pfeifer |
| Maintainers | something_with_code |
| Keywords | tunnel, http tunnel, reverse proxy, local development, websocket, daemon, self-hosted |

## Links

- npm: https://www.npmjs.com/package/tunli
- Repository: https://github.com/tunlijs/tunli-client
- Homepage: https://tunli.app
- Issues: https://github.com/tunlijs/tunli-client/issues
- npm.io page: https://npm.io/package/tunli

## Dependencies (8)

- [ink](https://npm.io/package/ink.md) ^6.8.0
- [chalk](https://npm.io/package/chalk.md) ^5.5.0
- [react](https://npm.io/package/react.md) ^19.2.4
- [qrcode](https://npm.io/package/qrcode.md) ^1.5.4
- [@tunli/daemon](https://npm.io/package/@tunli/daemon.md) ^1.0.0
- [@pfeiferio/ipv4](https://npm.io/package/@pfeiferio/ipv4.md) ^1.1.0
- [socket.io-client](https://npm.io/package/socket.io-client.md) ^4.8.1
- [@pfeiferio/string-interpolate](https://npm.io/package/@pfeiferio/string-interpolate.md) ^1.0.0

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 0.8.0 (latest) — 2026-09-24
- 0.7.1 — 2026-09-24
- 0.7.0 — 2026-03-27
- 0.6.0 — 2026-03-27
- 0.5.1 — 2026-03-27
- 0.5.0 — 2026-03-26
- 0.4.2 — 2026-03-26
- 0.4.1 — 2026-03-26
- 0.4.0 — 2026-03-26
- 0.3.0 — 2026-03-24
- 0.2.0 — 2026-03-24
- 0.1.0 — 2026-03-23
- 0.0.27 — 2025-08-11
- 0.0.26 — 2025-08-11
- 0.0.25 — 2024-06-17
- … 6 more at https://npm.io/package/tunli/versions

## README

# Tunli

Tunli is a developer-first tunneling tool that gives you full control — use the official server at [tunli.app](https://tunli.app) or run your own with [tunli-server](https://github.com/tunlijs/tunli-server).

## Installation

**Binary (no Node.js required):**

```bash
# Linux
curl -L https://github.com/tunlijs/tunli-client/releases/latest/download/tunli-linux.tar.gz | tar -xz -C /usr/local/bin

# macOS
curl -L https://github.com/tunlijs/tunli-client/releases/latest/download/tunli-macos.tar.gz | tar -xz -C /usr/local/bin
```

Or download manually from the [releases page](https://github.com/tunlijs/tunli-client/releases).

**via npm:**

```bash
npm install -g tunli
```

Requires Node.js >= 22.

## Features

- Stable public URLs per profile
- HTTP & WebSocket tunneling via a background daemon
- Multiple simultaneous tunnels
- Profiles & environments
- Self-hosted relay servers
- CIDR allow/deny access control
- Private peer-to-peer tunnels (`tunli share` / `tunli connect`) — no public URL, access by key only

## Quick Start

By default the client connects to the official server — no server setup required.

```bash
# 1. Register (once)
tunli register

# 2. Start a tunnel to your local port
tunli http 3000

# 3. Watch live output
tunli logs
```

`tunli http` hands the tunnel off to the background daemon and exits immediately. Use `tunli logs` or `tunli dashboard` to observe traffic.

## Commands

### `tunli http <port> [host]`

Start a tunnel to a local HTTP service. The daemon is started automatically if it isn't running yet.

```bash
tunli http 3000
tunli http 3000 127.0.0.1
tunli http 3000 --save myapp      # save as a named profile for later reuse
```

`tunli 3000` also works — `http` is the default command.

Use `--save <name>` to persist the configuration as a profile. Start it again with `tunli start <profile>`.

**Foreground mode** — run the tunnel directly in the CLI process without a background daemon:

```bash
tunli http 3000 --foreground      # alias: --fg
tunli http 3000 --dashboard       # with live TUI dashboard (alias: --db)
tunli http 3000 --logs            # with live log output to stdout
```

### `tunli start <profile>`

Start a tunnel using a saved profile.

```bash
tunli start myapp
```

### `tunli up` / `tunli down`

Start or stop all profiles defined in the local `.tunli/config.json`. Useful for projects with multiple services.

```bash
tunli up      # start all local profiles (skips already running)
tunli down    # stop all tunnels belonging to local profiles
```

### `tunli list`

Show all active tunnels managed by the daemon.

```bash
tunli list
```

### `tunli dashboard [profile]`

Attach to a running tunnel and show the live TUI dashboard. If multiple tunnels are active and no profile is given, a picker is shown. Press Ctrl+T inside the dashboard to switch between tunnels.

```bash
tunli dashboard
tunli dashboard myapp
```

### `tunli logs [profile]`

Attach to a running tunnel and stream live log output to stdout.

```bash
tunli logs
tunli logs myapp
```

### `tunli stop [profile...]`

Stop one or more running tunnels without stopping the daemon.

```bash
tunli stop myapp
tunli stop api frontend worker
```

### `tunli daemon`

Manage the background daemon process.

```bash
tunli daemon start
tunli daemon stop              # requires --force if tunnels are active
tunli daemon stop --force      # stop immediately, tunnels are closed
tunli daemon restart           # dump tunnels, restart, restore them
tunli daemon status
```

`restart` preserves active tunnels — it dumps state, restarts the daemon, and restores all tunnels. Use `stop` + `start` for a clean restart.

### `tunli register`

Register a new account and store the auth token.

```bash
tunli register
tunli register --force                                        # renew existing token
tunli register --relay https://api.myserver.com --name self   # self-hosted server
```

### `tunli auth <token>`

Manually store an auth token (e.g. received via invitation).

```bash
tunli auth <token>
```

### `tunli init`

Initialize a local config file in the current directory. Local configs override the global config and are useful for per-project settings.

```bash
tunli init
tunli init --force   # overwrite existing local config
```

### `tunli config`

Show or modify the active configuration.

```bash
tunli config                               # show active config
tunli config get host                      # read a single value
tunli config set host 127.0.0.2            # set a value
tunli config set port 3001 -p staging      # set in a named profile
tunli config delete                        # remove the active config file
tunli config dump                          # dump global + local config
tunli config relays                        # list registered relay servers
```

Scope flags (available on most config commands):

```
--global / -g     use the global config (~/.tunli/config.json)
--local  / -l     use the local config  (./.tunli/config.json)
--profile / -p    target a specific profile
```

### `tunli profile`

Manage tunnel profiles.

```bash
tunli profile list
tunli profile use staging       # set staging as the default profile
tunli profile delete staging    # remove a profile
```

### `tunli identity`

Show your tunli identity (public key and fingerprint). The keypair is generated automatically on first `tunli register`.

```bash
tunli identity
```

### `tunli share <port> [host]`

Share a local port privately via a peer-to-peer tunnel. No public URL is created — only someone with your public key can connect.

```bash
tunli share 8080
# → Your public key: tunli1abc...
# → Share this: tunli connect tunli1abc...
```

### `tunli connect <pubkey>`

Connect to a remote share by the host's public key. Opens a local TCP port that proxies to the remote service.

```bash
tunli connect tunli1abc...
# → Connected. Service available at localhost:52416
# → For SSH: ssh -p 52416 user@localhost

tunli connect tunli1abc... --port 2222   # fixed local port
```

### `tunli update`

Download and apply the latest binary release. If the daemon was running, you are prompted to restart it afterwards.

```bash
tunli update
tunli update --restart     # restart daemon automatically without prompting
tunli update --no-restart  # skip daemon restart
```

### `tunli relay`

Manage relay servers.

```bash
tunli relay list
tunli relay use myserver        # switch the active relay server
```

## Architecture & internals

For a deeper look at the two-binary model, daemon protocol, update flow and build system see [docs/architecture.md](docs/architecture.md).

## Configuration

Tunli stores its config in JSON files:

| Scope  | Location                                               |
|--------|--------------------------------------------------------|
| Global | `~/.tunli/config.json`                                 |
| Local  | `./.tunli/config.json` (per-project, takes precedence) |

A profile holds the target `host`, `port`, `protocol`, saved `proxyURL`, and optional CIDR allow/deny lists.

## License

GPL-3.0

---
_Source: https://npm.io/package/tunli · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
