# CLI

`thq` is the TunnelHQ command-line tool. Use it to test any VPN config, share link, or subscription URL from your terminal, manage monitors, Uptime checks, and API keys, and connect the MCP server to your AI editor. It runs on macOS, Linux, WSL, and Windows.

This page describes `thq` 0.4.0, the current release. Run `thq --version` to see yours.

## Install

`thq` needs Node.js 20 or newer. Both installers check for Node.js and npm before installing.

<Tabs syncKey="os">
  <TabItem label="macOS / Linux / WSL">
    ```bash title="Install on macOS, Linux, or WSL"
    curl -fsSL https://tunnelhq.com/install.sh | bash
    ```
  </TabItem>
  <TabItem label="Windows">
    In PowerShell 5.1 or newer:

    ```powershell title="Install on Windows"
    irm https://tunnelhq.com/install.ps1 | iex
    ```

    Or install the package with npm directly:

    ```powershell title="Install on Windows with npm"
    npm install -g https://tunnelhq.com/releases/latest/tunnelhq-cli.tgz
    ```
  </TabItem>
</Tabs>

## Sign in

`thq login` uses the device flow: run the command, approve the request in your browser, and you're signed in. There's no token to copy. Your credentials are saved to `~/.thq/credentials.json`.

```bash title="Sign in"
thq login
```

| Option | Description |
| --- | --- |
| `--no-browser` | Don't open the browser; print the approval URL instead. |
| `--qr` | Print a QR code for the approval URL. On by default when there's no display, for example over SSH. |
| `--no-qr` | Don't print the QR code. |
| `--host <url>` | Sign in to a different API host. |

The approval is refused if your workspace's plan doesn't include API access, with the message "API access isn't included on this workspace's plan. Upgrade to use the CLI."

The key `thq login` creates is an [account-wide key](/docs/api-keys/#kinds-of-key), named "CLI · &lt;computer name&gt; · &lt;date&gt;", which never expires.

`thq logout` removes the saved credentials and switches the key off on the server. The key stays on the **API Keys** page as **Disabled**; to delete it, choose **Revoke** there, or run `thq keys revoke <id> --hard` before you log out.

For CI and scripts, set an API key in the environment instead. When `THQ_API_KEY` is set, it's used instead of the saved sign-in.

```bash title="Use an API key in CI"
export THQ_API_KEY="thk_..."
```

:::caution[Requires a paid plan]
The CLI uses the API, so it needs a plan with API access: Starter and above. See [Getting an API key](/docs/api-keys/).
:::

## Test a config

`thq test` checks a VPN config on the spot and saves nothing. The target can be a config file path, a share link, a raw config string, or an `https://` subscription URL.

```bash title="Test a config, a share link, or a subscription"
thq test ./wg0.conf
thq test 'vless://<uuid>@vpn.example.com:443?security=reality&...'
thq test https://provider.example.com/sub --first 5 --json
```

| Option | Description |
| --- | --- |
| `--json` | Machine-readable output, for CI. |
| `--protocol <name>` | Force the protocol: `wireguard`, `openvpn`, `ikev2`, `openconnect`, `vmess`, `vless`, `trojan`, `shadowsocks`, `amneziawg`, `hysteria2`, or `tuic`. |
| `--timeout <seconds>` | How long to wait. Default 30, minimum 5, maximum 120. |
| `--host <hostname>`, `--port <number>` | Server host and port for IKEv2, OpenConnect, and OpenVPN (required for IKEv2 and OpenConnect). WireGuard, AmneziaWG, and share links use their own. |
| `-u`, `--username`; `-p`, `--password` | Override the credentials. |
| `--remote-id <id>` | Set the IKEv2 remote ID. |
| `--engine <name>` | Force an engine: `singbox`, `xray`, `auto`, `both`, or `race`. By default, the checker picks one per protocol. |
| `--first <n>` | Subscription URLs only: test the first *n* entries. Alias: `--limit`. |
| `--index <n>` | Subscription URLs only: test one entry, counting from 1. |

A subscription URL tests every entry unless you pass `--first` or `--index`.

IKEv2 and OpenConnect don't need a config: pass the server and the credentials.

```bash title="Test IKEv2 without a config"
thq test --protocol ikev2 --host vpn.example.com -u alice -p secret
```

`thq test` works out the protocol from, in order:

1. `--protocol`.
2. The URI scheme, such as `vless://` or `ss://`.
3. The content: an `[Interface]` section is WireGuard, or AmneziaWG when it has `Jc`, `Jmin`, `Jmax`, or `H1`–`H4` keys; `client` and `remote` lines are OpenVPN. So a `.conf` file that holds an OpenVPN config is tested as OpenVPN.
4. The file extension: `.conf` is WireGuard, `.ovpn` is OpenVPN.
5. An `http://` or `https://` address is a subscription URL.

`thq test` exits with `0` when the test passes and `1` when it fails, so you can use it in CI.

Tests run on the same checkers as scheduled monitors, through [`POST /check`](/docs/api/#endpoints). They count toward your API rate limit, not your on-demand test quota.

## Manage monitors

`thq servers` manages the project's saved monitors. Every `thq servers` and `thq checks` command works in the project in `THQ_PROJECT_ID`, or the one you pass with `--project <id>`, and takes `--json`.

| Command | Description |
| --- | --- |
| `thq servers list` | List monitors. `--family` chooses `tunnel` (the default), `uptime`, or `all`. Filter with `--status`, `--protocol`, `--search`, and `--active-only`; `--limit` defaults to 100. |
| `thq servers create <input> --name <name>` | Create a VPN monitor from a config file, share link, or raw config. It takes `thq test`'s connection options (`--protocol`, `--host`, `--port`, `-u`, `-p`, `--remote-id`), plus `--proto udp` or `tcp` for OpenVPN, `--ip` for a WireGuard or AmneziaWG config without an `Endpoint` line, `--interval`, `--tag` (repeat it for more), and `--paused`. For OpenConnect and IKEv2, leave out the input and pass `--host`, `--username`, and `--password`. |
| `thq servers delete <id> --yes` | Delete a monitor or an Uptime check by its ID, `srv_123` or `123`. `--yes` is always required, with `--json` too. |

```bash title="Create monitors"
thq servers create wg.conf --name "WG Frankfurt"
thq servers create 'vless://<uuid>@host:443' --name "VLESS EU"
thq servers create '' --protocol openconnect --name "OC Corp" \
  --host vpn.example.com --username alice --password secret
```

## Manage Uptime checks

`thq checks list` lists the project's [Uptime checks](/docs/uptime/). Filter with `--type`, `--status`, `--search`, and `--active-only`; `--limit` defaults to 100.

`thq checks create <target> --name <name>` creates a check. Without `--type`, the target sets the type, the same way the dashboard does:

| Target | Creates |
| --- | --- |
| `https://example.com` or `example.com/health` | A website check, with `https://` added if it's missing. With `--keyword`, a keyword check. |
| `db.example.com:5432` or `[2001:db8::1]:443` | A TCP port check. `--port` overrides the port. |
| `8.8.8.8` (an IP address) | A ping check. |
| `example.com` (a bare hostname) | A website check, with `https://` added. Add `--type ping` to ping it instead. |
| `1.1.1.1 --domain example.com` | A DNS check. The target is the DNS server; `--keyword` is text the answer must contain. |
| No target, with `--period` | A heartbeat. The command prints the address your job calls. |

Targets must be public addresses: private and reserved ones are refused.

| Option | Description |
| --- | --- |
| `--type <type>` | `http`, `keyword`, `ping`, `port`, `dns`, or `push` (a heartbeat). |
| `--keyword <text>` | Keyword check: text the page must contain. DNS check: text the answer must contain. |
| `--invert-keyword` | Keyword check: alert when the text *is* found. |
| `--accept <codes>` | Website and keyword checks: accepted status codes, such as `200-299,301`. Default `200-299`. |
| `--port <n>` | TCP port check: the port. |
| `--domain <name>` | DNS check: the domain to ask about. |
| `--period <seconds>` | Heartbeat: the longest time between two calls from your job. Default 86400. |
| `--grace <seconds>` | Heartbeat: how late a call can be before it's down. Default 3600. |
| `--interval <seconds>` | Seconds between checks. Left out, the recommended default. |
| `--tag <name>` | Add a tag. Repeat it for more. |
| `--paused` | Create the check paused. |

```bash title="Create Uptime checks"
thq checks create https://example.com --name "Homepage"
thq checks create https://example.com/login --name "Login" --keyword "Sign in"
thq checks create db.example.com:5432 --name "Postgres"
thq checks create 1.1.1.1 --name "Resolver" --domain example.com
thq checks create --name "Nightly backup" --period 86400 --grace 3600
```

To change or pause a check, use the dashboard, the [REST API](/docs/uptime/checks/#uptime-checks-in-the-api), or the [MCP server](/docs/mcp/). To delete one, use `thq servers delete`.

## Manage API keys

| Command | Description |
| --- | --- |
| `thq keys list` | List your API keys. |
| `thq keys create <name> [--expires <ISO date>]` | Create a workspace key. Keys created this way start with `uk`. Needs a workspace key in `THQ_API_KEY`: the account-wide key from `thq login` is refused. An `--expires` value that isn't a date, such as `31/12/2026`, is refused. |
| `thq keys revoke <id> [--hard]` | Disable a key. With `--hard`, delete it permanently. The ID is the number, or the `uk…` form. |

## Set up the MCP server

`thq mcp` prints the configuration for the [MCP server](/docs/mcp/), or applies it for you.

| Option | Description |
| --- | --- |
| `--client <name>` | `claude`, `cursor`, `windsurf`, or `cline`. |
| `--apply` | Apply the configuration: runs `claude mcp add` for Claude Code, or writes the JSON config for the other clients. |
| `--update` | With `--client`, clear TunnelHQ's cached MCP server and add it to that client again, so your editor gets the current release on its next start. Without `--client`, it changes nothing. |
| `--json` | Print the configuration snippet and exit. |
| `--api-key <value>` | Use this key in the configuration. |

## Other commands

| Command | Description |
| --- | --- |
| `thq whoami` | Show the account you're signed in as. |
| `thq doctor` | Diagnose connection and authentication problems. |
| `thq upgrade` | Update the CLI. It detects whether you installed it with npm, Homebrew, or the install script. Alias: `thq update`. |
| `thq install` | Reinstall the CLI to a stable location and add it to your `PATH`. |

Run `thq --help` for every command and option.

## Interactive REPL

Run `thq` with no arguments in an interactive terminal to open the slash-command interface. It doesn't open when input or output is redirected, or when `NO_COLOR` is set.

| Command | Description |
| --- | --- |
| `/test` | Test a VPN config, share link, or subscription URL. |
| `/whoami` | Show your account, plan, and quota. |
| `/keys` | `list`, `create <name>`, or `revoke <id>`. |
| `/mcp` | Set up the MCP server. |
| `/doctor` | Diagnose connection and authentication problems. |
| `/upgrade` | Update the CLI. |
| `/login`, `/logout` | Sign in or out. |
| `/help` | List every command. |
| `/exit` | Quit. |

## Environment variables

| Variable | Description |
| --- | --- |
| `THQ_API_KEY` | API key to use instead of the saved sign-in. |
| `THQ_HOST` | API host. Version 0.3.1 defaults to `https://beta.tunnelhq.com`. |
| `THQ_PROJECT_ID` | Default project. |
| `THQ_ORG_ID` | Default workspace. |
| `THQ_HEADLESS` | `1` or `0` to force headless mode on or off. |
| `THQ_SKIP_UPDATE_CHECK` | `1` to skip the background check for a newer version. |
| `THQ_INSTALL_DIR` | Where `thq install` puts the CLI. Defaults to `~/.local/bin`, or `%LOCALAPPDATA%\TunnelHQ\bin` on Windows. |
