# Local vs Server Environment Detection in Agent Reach: A Complete Guide

> Learn how Agent Reach's _detect_environment uses local vs server environment detection to install the right backends for your desktop or remote machines. Get the complete guide.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: how-to-guide
- Published: 2026-07-11

---

**Agent Reach uses a multi-indicator scoring system in `_detect_environment()` to automatically distinguish between local desktop environments and headless servers, enabling it to install appropriate backends like OpenCLI for desktops or pure CLI tools for remote machines.**

Agent Reach requires precise environment detection to determine whether it's running on a graphical workstation or a headless server. This distinction, implemented in the [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) module, drives critical decisions about which backend tools to install for platforms like Reddit and XiaoHongShu. Understanding how local and server environment detection works in Agent Reach helps developers predict behavior across different deployment scenarios.

## How Environment Detection Works in Agent Reach

### The _detect_environment() Implementation

The core detection logic resides in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) (lines 955-994) within the private helper `_detect_environment()`. This function aggregates multiple OS-level indicators using a weighted scoring system, returning `"server"` when the cumulative score reaches **2 or higher**, and `"local"` otherwise.

```python
def _detect_environment():
    """Auto‑detect if running on local computer or server."""
    import os
    indicators = 0

    # 1️⃣ SSH session – typical for remote logins

    if os.environ.get("SSH_CONNECTION") or os.environ.get("SSH_CLIENT"):
        indicators += 2

    # 2️⃣ Docker / container environment

    if os.path.exists("/.dockerenv") or os.path.exists("/run/.containerenv"):
        indicators += 2

    # 3️⃣ Headless display (no X11/Wayland)

    if not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY"):
        indicators += 1

    # 4️⃣ Cloud‑VM identifiers (Amazon, Google, Azure, DigitalOcean, …)

    for cloud_file in ["/sys/hypervisor/uuid",
                       "/sys/class/dmi/id/product_name"]:
        if os.path.exists(cloud_file):
            try:
                with open(cloud_file) as f:
                    content = f.read().lower()
                if any(x in content
                       for x in ["amazon", "google", "microsoft",
                                 "digitalocean", "linode", "vultr", "hetzner"]):
                    indicators += 2
            except Exception:
                pass

    # 5️⃣ systemd‑detect‑virt (detects virtualisation)

    try:
        import subprocess
        result = subprocess.run(
            ["systemd-detect-virt"], capture_output=True,
            encoding="utf-8", errors="replace", timeout=3)
        if result.returncode == 0 and result.stdout.strip() != "none":
            indicators += 1
    except Exception:
        pass

    return "server" if indicators >= 2 else "local"

```

### The Five Detection Signals

The function checks five specific environment indicators with weighted values:

- **SSH connections** (2 points): Checks for `SSH_CONNECTION` or `SSH_CLIENT` environment variables, indicating remote login sessions.
- **Container environments** (2 points): Detects `/.dockerenv` or `/run/.containerenv` files present in Docker and containerized runtimes.
- **Missing display servers** (1 point): Verifies absence of `DISPLAY` (X11) or `WAYLAND_DISPLAY` variables, suggesting headless operation.
- **Cloud VM signatures** (2 points): Reads `/sys/hypervisor/uuid` and `/sys/class/dmi/id/product_name` for strings like "amazon", "google", "microsoft", or "digitalocean".
- **Virtualization detection** (1 point): Executes `systemd-detect-virt` to identify virtualized environments, adding a point for any non-"none" result.

## Platform-Specific Backend Selection

Agent Reach uses the environment classification to determine which backend implementation to install for each platform.

| Platform | Local Environment | Server Environment |
|----------|------------------|-------------------|
| **XiaoHongShu** | Installs **OpenCLI** (reuses desktop Chrome session) | Recommends **xiaohongshu-mcp** binary with QR-login guide |
| **Reddit** | Prefers **OpenCLI**; falls back to existing `rdt-cli` | Installs **rdt-cli** (pure CLI without UI requirements) |
| **General** | Browser-based tools assuming graphical environment | Self-contained binaries or pure CLI tools |

### Reddit Installation Logic

The branching logic for Reddit dependencies (lines 778-892 in [`cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/cli.py)) demonstrates this pattern:

```python
def _install_reddit_deps():
    """Set up Reddit — desktop prefers OpenCLI, rdt-cli for servers/legacy."""
    if _detect_environment() != "server":
        _install_opencli_deps()
        print("  Reddit 走 OpenCLI（浏览器里登录过 reddit.com 即可用）")
        # ... optionally use rdt‑cli if already present ...

        return

    _install_rdt_cli()

```

This ensures that desktop users get the browser-integrated OpenCLI experience while server deployments receive the headless-compatible `rdt-cli` tool.

## Understanding the Threshold Logic

The function returns `"server"` only when `indicators >= 2`. This threshold-based design intentionally weights strong signals (SSH, containers, cloud VMs) at 2 points each, while weak signals (missing display, virtualization) contribute only 1 point.

This prevents false positives where a desktop workstation might lack a DISPLAY variable but isn't actually a server. Conversely, a Docker container automatically scores 2 points, immediately triggering server mode regardless of other factors.

## Testing Environment Detection

The test suite in [`tests/test_cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_cli.py) (lines 88-100) verifies this branching behavior by mocking the environment detection function:

```python

# Simulating a server environment in a test (see tests/test_cli.py)

def test_install_reddit_deps_routes_by_environment(monkeypatch):
    monkeypatch.setattr(cli, "_detect_environment", lambda: "local")
    # ...assert OpenCLI path...

    monkeypatch.setattr(cli, "_detect_environment", lambda: "server")
    # ...assert rdt‑cli path...

```

You can manually verify your current environment using:

```python
from agent_reach.cli import _detect_environment
print(_detect_environment())  # Outputs: 'local' or 'server'

```

## Summary

- **Multi-factor detection**: Agent Reach evaluates SSH sessions, container files, display variables, cloud VM signatures, and virtualization status to determine the environment type.
- **Weighted scoring**: Strong indicators (SSH, containers, cloud VMs) contribute 2 points; weak indicators (missing display, virtualization) contribute 1 point.
- **Threshold decision**: The environment is classified as `"server"` only when the cumulative score reaches 2 or higher.
- **Backend routing**: Local environments receive browser-based tools like OpenCLI, while server environments get pure CLI binaries like `rdt-cli` or `xiaohongshu-mcp`.
- **Implementation location**: All detection logic resides in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) (lines 955-994), with platform-specific installation branching throughout the same file.

## Frequently Asked Questions

### How does Agent Reach detect if it's running on a server?

Agent Reach checks five OS-level indicators in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py): SSH environment variables, Docker/container files, display server availability, cloud VM hardware signatures, and virtualization status via `systemd-detect-virt`. Each indicator carries a weighted score, and the function returns `"server"` when the total reaches 2 or more points.

### What happens if Agent Reach incorrectly detects my environment?

If detection fails, the tool defaults to `"local"` mode (since the threshold requires >= 2 points to trigger server mode). However, this may cause installation failures when attempting to launch browser-based tools like OpenCLI on headless systems. You can verify the detection by importing `_detect_environment()` from `agent_reach.cli` and checking the return value.

### Can I override the automatic environment detection in Agent Reach?

While the source code in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) shows that installation functions directly call `_detect_environment()`, the test suite demonstrates that you can monkeypatch this function for custom behavior. For production deployments, ensure your environment presents sufficient server indicators (such as running inside Docker) to trigger automatic server mode.

### Why does Agent Reach use different backends for Reddit on local vs server?

**OpenCLI** requires a graphical browser environment to reuse existing Chrome sessions, making it ideal for local desktops but incompatible with headless servers. **rdt-cli** operates as a pure CLI tool without UI dependencies, ensuring Reddit functionality remains available in SSH sessions or containerized deployments where no display server exists.