The agent

One process per machine. Every endpoint in your browser.

Install it once. After that, adding a tunnel is a form — not an SSH session. The agent picks up changes from the dashboard within seconds and keeps serving everything else while it does.

Why an agent

A tunnel shouldn't be a process you babysit.

hle expose is one tunnel tied to one terminal. The agent is one connection serving as many endpoints as you declare.

hle exposehle agent
Tunnels per processOneMany
Configured inThe command lineThe dashboard
Changing a tunnelRestart the commandTakes effect in seconds
Survives rebootNoYes — installed as a service
CredentialAPI key hle_…Agent token hlea_…
FirepuncherYes
Service discoveryYes — Kubernetes & Docker
Setup

Enrolled and running in one command.

Install and enroll

The installer sets up the client, enrolls the machine, and installs a service that starts at boot. It prompts for an agent token — grab one from Connections → New → Agent. It's shown only once.

shell
$ curl -fsSL https://get.hle.world | sh -s -- --agent

For cloud-init, Ansible, or CI, pass the token instead: --token hlea_xxxxx

Declare endpoints in the dashboard

Each endpoint is a label, a local URL the agent can reach, a domain, and whether it sits behind SSO. The target is any URL the agent can reach — not just its own machine, anything on its network.

LabelLocal URLPublic URL
hahttp://homeassistant:8123ha-x7k.hle.world
jellyhttp://nas:8096jelly.example.com
githttp://git:3000git-x7k.hle.world

Custom domains like jelly.example.com need pay-as-you-go; *-x7k.hle.world subdomains are on every plan.

Change things without touching the box

Edit an endpoint and the agent converges within seconds. Nothing restarts, and the other endpoints keep serving traffic throughout.

Manage the service

shell
# is it running?
$ hle service status --agent

# watch it in the foreground
$ hle agent run

# logs (linux, system)
$ journalctl -u hle-agent -f

A systemd unit on Linux, a launchd job on macOS.

Where the token lives. hle agent enroll writes it to ~/.config/hle/agent.toml with mode 0600 — never into the service definition, so the unit file is safe to back up or commit as a template.
Service discovery

It already knows what's running.

An agent inside a Kubernetes cluster or on a Docker host inventories what it can see and reports the list. You pick one and it becomes an endpoint — no hostname to look up, no port to remember. Discovery is strictly read-only.

shell
$ hle agent services

              Discovered services (k8s, docker)
  Name     Where       Address                          Suggested label
  grafana  monitoring  http://grafana.monitoring.svc…   grafana
  gitea    git         http://gitea.git.svc.cluster…    gitea
  plex     media       http://172.18.0.4:32400          plex

Read-only, always

Discovery never creates, changes, or deletes anything in your cluster or on your Docker host.

Self-detecting

Each provider is asked whether it applies before it's used. An agent on a plain VM finds nothing and reports nothing rather than erroring.

In the dashboard

Traffic, split by transport.

Because everything passes through the relay, the dashboard breaks your usage down by transport and protocol without you instrumenting anything — tunnels and firepuncher streams side by side, filterable down to HTTP, WebSocket or raw TCP.

Install the agent on one box.

Enroll it, declare an endpoint, and see how it feels to change a tunnel from a browser tab.