> ## Documentation Index
> Fetch the complete documentation index at: https://momentic.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The canonical docs host is https://momentic.ai/docs. Append .md to any page URL for clean Markdown. Fetch https://momentic.ai/docs/llms.txt for the page index and https://momentic.ai/docs/llms-full.txt for every page in one file.
> For an unattended setup, run `npx --yes @momentic/wizard@latest -y --platform web --editor-tools skills` (use `--platform ios` or `--platform android` for mobile). Never run an interactive command in a non-TTY shell.
> Mo is the AI QA engineer, a separate product from the YAML test framework: its npm package and CLI are `qa` (not `mo` — `npx mo` is a different project). Install with `npm install -g qa`, authenticate the same MOMENTIC_API_KEY way, install repo skills with `qa skills -y`, and start a session with `qa start "<brief>"` or `qa <url>`. Docs: https://momentic.ai/docs/mo.md.
> You cannot complete the browser sign-in yourself. Read the API key from the exact MOMENTIC_API_KEY environment variable (similarly named vars like BILT_MOMENTIC_API_KEY are ignored), or ask the user to create one at https://app.momentic.ai/settings/api-keys and paste it back.
> Momentic's capability summary for agents is at https://momentic.ai/docs/skill.md. Install the skills with `npx momentic skills --yes` (or `npx momentic-mobile skills --yes` for mobile).
> Tests are YAML files in the user's repository. Use only the step names listed at https://momentic.ai/docs/reference/commands.md and the file structure at https://momentic.ai/docs/core-concepts/file-format.md. Do not invent step names, config keys, or CLI flags.
> Web tests run on Chromium, iOS tests on simulators, and Android tests on emulators. Physical devices are not supported.

# Keep a tunnel running

> Run a named qa tunnel under your OS's service manager so it survives crashes and reboots.

A [`qa tunnel`](https://momentic.ai/docs/mo/tunneling) runs as long as its process does. To keep one
online across crashes and reboots, give it a name and let your operating
system's service manager restart it. A named tunnel keeps its ID, so Mo sessions
that use it keep working.

> [!TIP]
>
> On a host that can run Docker, the [Connector Docker
> image](https://momentic.ai/docs/mo/tunneling.md#run-the-connector-with-docker) with `--restart
>     unless-stopped` does the same job with less setup.

## Create the tunnel

> [!NOTE]
>
> Named tunnels need a recent `qa`. Run `qa upgrade`, then check that `qa tunnel
>     start --help` lists `--name`.

Sign in with [`qa login`](https://momentic.ai/docs/mo/cli#authenticate), then create the tunnel once in
a terminal. Replace `localhost:3000` with your app's address and `checkout-dev`
with a name for the tunnel:

```bash theme={null}
qa tunnel start localhost:3000 --name checkout-dev --foreground
```

When the ready summary appears, press `Ctrl+C`. The tunnel goes offline but
isn't revoked, and `qa tunnel list` shows it as `offline`. The service below
resumes it with the same command. Resuming a named tunnel doesn't call the
Momentic API, so the service doesn't need an API key.

## Linux

Run the tunnel as a systemd user service. Save this as
`~/.config/systemd/user/qa-tunnel.service`, with the absolute path that
`command -v qa` prints:

```ini theme={null}
[Unit]
Description=Momentic tunnel
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
ExecStart=/home/jane/.local/bin/qa tunnel start localhost:3000 --name checkout-dev --foreground
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
```

If you installed `qa` with npm, it runs on Node.js, which the service can't find
through your shell's `PATH`. Add a line under `[Service]` with the directory
that `command -v node` prints:

```ini theme={null}
Environment=PATH=/home/jane/.nvm/versions/node/v22.12.0/bin:/usr/bin:/bin
```

Start it, and let it start at boot without a login:

```bash theme={null}
systemctl --user daemon-reload
systemctl --user enable --now qa-tunnel.service
loginctl enable-linger "$USER"
```

Read the logs with `journalctl --user -u qa-tunnel.service`.

## macOS

Run the tunnel as a launchd agent. Save this as
`~/Library/LaunchAgents/ai.momentic.qa-tunnel.plist`, with the absolute path
that `command -v qa` prints:

```xml theme={null}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>ai.momentic.qa-tunnel</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/qa</string>
    <string>tunnel</string>
    <string>start</string>
    <string>localhost:3000</string>
    <string>--name</string>
    <string>checkout-dev</string>
    <string>--foreground</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <!-- Lets an npm-installed qa find Node.js. -->
    <key>PATH</key>
    <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
  </dict>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
  <key>ThrottleInterval</key>
  <integer>10</integer>
  <key>StandardOutPath</key>
  <string>/tmp/qa-tunnel.log</string>
  <key>StandardErrorPath</key>
  <string>/tmp/qa-tunnel.log</string>
</dict>
</plist>
```

Load it:

```bash theme={null}
launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/ai.momentic.qa-tunnel.plist
```

A launchd agent runs while you're logged in to the Mac and starts again when you
log in.

## Windows

Task Scheduler starts a PowerShell script that restarts the tunnel whenever it
exits. Save this as `%USERPROFILE%\qa-tunnel.ps1`:

```powershell theme={null}
$log = "$env:USERPROFILE\qa-tunnel.log"
while ($true) {
  & qa.cmd tunnel start localhost:3000 --name checkout-dev --foreground *>> $log
  "$(Get-Date -Format s) qa exited with code $LASTEXITCODE, restarting in 10s" >> $log
  Start-Sleep -Seconds 10
}
```

On Windows Server 2016, replace `qa.cmd` and `qa` with
`npx.cmd --yes @momentic/qa-node` throughout this page, including the check and
stop commands. See [Windows Server 2016](https://momentic.ai/docs/mo/windows-server-2016).

Then register the script with Task Scheduler. Pick the block for how the machine
is used.

On a machine that runs without anyone logged in, such as a server, run this in
an elevated PowerShell. The task starts at boot:

```powershell theme={null}
$action = New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$env:USERPROFILE\qa-tunnel.ps1`""
$trigger = New-ScheduledTaskTrigger -AtStartup
$trigger.Delay = "PT1M" # the logon fails if the task starts in the first seconds of boot
$principal = New-ScheduledTaskPrincipal -UserId (whoami) -LogonType S4U
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask QaTunnel -Action $action -Trigger $trigger -Principal $principal -Settings $settings
Start-ScheduledTask QaTunnel
```

The account needs the **Log on as a batch job** right, which administrators
have.

On a machine that you're logged in to, run this in PowerShell. The task starts
when you log in:

```powershell theme={null}
$action = New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$env:USERPROFILE\qa-tunnel.ps1`""
$trigger = New-ScheduledTaskTrigger -AtLogOn -User (whoami)
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask QaTunnel -Action $action -Trigger $trigger -Settings $settings
Start-ScheduledTask QaTunnel
```

The script writes to `%USERPROFILE%\qa-tunnel.log`.

## Check and stop the tunnel

Check the tunnel from any terminal on the machine:

```bash theme={null}
qa tunnel list
```

To stop it for good, remove the service first so it doesn't restart the tunnel,
then revoke it:

```bash Linux theme={null}
systemctl --user disable --now qa-tunnel.service
qa tunnel stop checkout-dev
```

```bash macOS theme={null}
launchctl bootout "gui/$(id -u)/ai.momentic.qa-tunnel"
rm ~/Library/LaunchAgents/ai.momentic.qa-tunnel.plist
qa tunnel stop checkout-dev
```

```powershell Windows theme={null}
Stop-ScheduledTask QaTunnel
Unregister-ScheduledTask QaTunnel -Confirm:$false
qa.cmd tunnel stop checkout-dev
```

## Notes

* Each user account runs one tunnel at a time. To expose several apps, pass
  every address to the one tunnel.
* To change a tunnel's addresses, stop it and create a new one. A name can't be
  reused after `qa tunnel stop`, so pick a new one.
* The service doesn't inherit proxy variables such as `HTTPS_PROXY` from your
  shell. If the machine needs a proxy to reach Momentic, set it in the service
  definition.
* The machine needs the [tunnel network access](https://momentic.ai/docs/mo/tunneling.md#prerequisites)
  whenever the service runs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.