---
name: homeroot-agent-cli
description: Install and operate the HomeRoot agent. Create/edit/pause/delete tunnels and website forwards on the calling device only. Use when configuring HomeRoot on a server via the homeroot CLI.
---

# HomeRoot — Agent CLI

The `homeroot` agent runs on your server, connects to the hub at `https://homeroot.dev`, and exposes local services through tunnels and website forwards. Everything is **device-scoped**: the agent token can only manage tunnels and websites on that one device.

## Install

Get a device token from the dashboard (Devices → New device). Shown once — treat it as a secret.

**Linux:**

```bash
curl -fsSL 'https://homeroot.dev/install/linux.sh?token=DEVICE_TOKEN&api=https%3A%2F%2Fhomeroot.dev' | sudo sh
```

**Windows** (elevated PowerShell):

```powershell
irm 'https://homeroot.dev/install/windows.ps1?token=DEVICE_TOKEN&api=https%3A%2F%2Fhomeroot.dev' | iex
```

Installs the binary and registers the `homeroot-agent` service.

## Environment

| Variable | Meaning |
| --- | --- |
| `HOMEROOT_TOKEN` | device auth token |
| `HOMEROOT_API` | hub base URL (default from installer: `https://homeroot.dev`) |
| `HOMEROOT_SERVICE` | auto-update mode: `systemd` \| `launchd` \| `windows-service` |
| `HOMEROOT_STATE` | path to agent state file |

Flags override env vars.

## Commands

### `homeroot run`

Daemon mode (normally started by the service).

```bash
homeroot run --token <DEVICE_TOKEN> --api https://homeroot.dev [--service systemd|launchd|windows-service]
```

| Flag | Meaning | Default |
| --- | --- | --- |
| `-token` | device auth token (required) | — |
| `-api` | hub API base URL | `http://localhost:8080` |
| `-service` | service mode for auto-updates | unset = manual |

Registers the device, keeps the WireGuard link up, relays tunnels, heartbeats, and self-updates when a service mode is set.

### `homeroot tunnel`

Manage TCP/UDP port forwards for **this device only**.

```bash
homeroot tunnel list   [--token <T>] [--api https://homeroot.dev] [--json]
homeroot tunnel show   <id|port> [--token <T>] [--api ...] [--json]
homeroot tunnel create --local-port <PORT> \
    [--local-host 127.0.0.1] [--protocol tcp|udp] \
    [--proxy-protocol v1|v2|none] [--inactive] [--token <T>] [--api ...] [--json]
homeroot tunnel edit   <id|port> \
    [--local-host ...] [--local-port ...] [--protocol ...] \
    [--proxy-protocol ...] [--active|--inactive] [--token <T>] [--api ...] [--json]
homeroot tunnel delete <id|port> --yes [--token <T>] [--api ...] [--json]
```

- `create`: `--local-port` required (1–65535); `--local-host` defaults to `127.0.0.1`; `--protocol` defaults to `tcp`.
- `edit`: `--active` resumes, `--inactive` pauses (mutually exclusive).
- `delete`: requires `--yes`.
- `show` / `edit` / `delete` accept tunnel id or public port.

### `homeroot website`

Manage HTTP(S) reverse-proxy forwards (public subdomain → local port) for **this device only**.

```bash
homeroot website domains [--token <T>] [--api ...] [--json]
homeroot website check   --subdomain <name> --domain-id <id> [--token <T>] [--api ...] [--json]
homeroot website list    [--token <T>] [--api ...] [--json]
homeroot website show    <id|subdomain|fqdn> [--token <T>] [--api ...] [--json]
homeroot website create  --subdomain <name> --domain-id <id> --local-port <PORT> \
    [--local-host 127.0.0.1] [--scheme http|https] [--token <T>] [--api ...] [--json]
homeroot website edit    <id|subdomain|fqdn> \
    [--local-host ...] [--local-port ...] [--scheme http|https] \
    [--active|--inactive] [--token <T>] [--api ...] [--json]
homeroot website delete  <id|subdomain|fqdn> --yes [--token <T>] [--api ...] [--json]
```

- `domains`: list available public zones (pick a `domain_id` for create/check).
- `check`: whether a subdomain is free under that zone.
- `create`: `--subdomain`, `--domain-id`, and `--local-port` required; `--scheme` defaults to `http`.
- `edit`: `--active` enables, `--inactive` pauses.
- `delete`: requires `--yes`.
- `show` / `edit` / `delete` accept website id, subdomain label, or full FQDN.

## Agent API (device token)

Auth: `Authorization: Bearer <DEVICE_TOKEN>` or `?token=<DEVICE_TOKEN>`.

### Tunnels

| Method | Path |
| --- | --- |
| `GET` | `/api/v1/agent/tunnels` |
| `POST` | `/api/v1/agent/tunnels` |
| `GET` | `/api/v1/agent/tunnels/{idOrPort}` |
| `PATCH` | `/api/v1/agent/tunnels/{idOrPort}` |
| `DELETE` | `/api/v1/agent/tunnels/{idOrPort}` |

### Websites

| Method | Path |
| --- | --- |
| `GET` | `/api/v1/agent/websites` |
| `POST` | `/api/v1/agent/websites` |
| `GET` | `/api/v1/agent/websites/domains` |
| `GET` | `/api/v1/agent/websites/check?subdomain=&domain_id=` |
| `GET` | `/api/v1/agent/websites/{idOrName}` |
| `PATCH` | `/api/v1/agent/websites/{idOrName}` |
| `DELETE` | `/api/v1/agent/websites/{idOrName}` |

### Other agent endpoints

| Method | Path | Notes |
| --- | --- | --- |
| `POST` | `/api/v1/agent/register` | used by `run` |
| `POST` | `/api/v1/agent/heartbeat` | used by `run` |
| `GET` | `/api/v1/agent/config` | used by `run` |
| `GET` | `/api/v1/agent/update` | self-update manifest |

## Workflows

**Expose a local TCP service**

```bash
homeroot tunnel create --local-port 8080 --local-host 127.0.0.1 --protocol tcp
homeroot tunnel list --json
homeroot tunnel edit <id> --inactive   # pause
homeroot tunnel edit <id> --active     # resume
homeroot tunnel delete <id> --yes
```

**Expose a local HTTP app as a website**

```bash
homeroot website domains --json                    # pick domain_id
homeroot website check --subdomain myapp --domain-id <DOMAIN_ID>
homeroot website create --subdomain myapp --domain-id <DOMAIN_ID> --local-port 3000
# → https://myapp.<zone> → http://127.0.0.1:3000 on this device
homeroot website edit myapp --inactive
homeroot website delete myapp --yes
```

## Scope limits

The device token may **only**:

- manage tunnels on this device
- manage websites on this device
- register / heartbeat / self-update

It must **not** be used for user accounts, other devices, admin APIs, package changes, or DynDNS zone management. Those return 401 with a device token and are out of scope for this skill.

## Troubleshooting

| Symptom | Fix |
| --- | --- |
| Installer `400 missing token` | pass `token=DEVICE_TOKEN` in the install URL |
| CLI / API `401` | wrong or missing device token |
| CLI / API `429` | rate limited — back off and retry |
| `manual agent mode; … to update` | set `--service` / `HOMEROOT_SERVICE`, or re-run the installer |
| Tunnel up but unreachable | local service must listen on the configured host:port (usually `127.0.0.1`) |
| Website `409 subdomain is already taken` | pick another label; use `website check` first |
| Website `409 control panel hostname` | reserved name — choose a different subdomain |

## Safety

- Never print or store device tokens.
- `tunnel delete` / `website delete` need `--yes` — confirm with the user first.
- Prefer `--json` + `list`/`show` before any change; verify afterwards.
- Use `https://homeroot.dev` as the API base unless the user specifies another hub.
