# How Agent Reach Auto-Detects Between Local Computer and Server Environments

> Discover how Agent Reach automatically detects local computer vs server environments using a four-tier strategy. Understand environment variables, CI indicators, TTY status, and config writability.

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

---

**Agent Reach uses a four-tier detection strategy in [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py) that checks environment variables, CI indicators, TTY status, and config directory writability to determine whether it is running on a local workstation or a headless server.**

Agent Reach is an open-source automation framework hosted in the Panniantong/Agent-Reach repository that must adapt its behavior depending on execution context. Understanding how Agent Reach auto-detects between local computer and server environments is essential for debugging configuration issues and ensuring your automation scripts behave correctly across different contexts.

## The Detection Logic in [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py)

The core classification logic resides in the `is_server()` function within [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py). This utility evaluates four distinct signals in sequence to classify the execution environment as either local or server.

### Step 1: Check for Explicit Environment Variable Hint

The function first inspects the `AGENT_REACH_ENV` environment variable. If set to `"server"`, the function immediately returns `True`. If set to `"local"`, it returns `False`. This allows users to override automatic detection when necessary.

### Step 2: Detect CI Environment Variables

When no explicit hint is present, the code checks for common CI environment variables. The presence of any of the following variables causes the function to classify the environment as a server: `CI`, `GITHUB_ACTIONS`, `GITLAB_CI`, or `TRAVIS`.

### Step 3: Interactive TTY Fallback

If no CI variables are found, the function checks whether the process has an attached terminal using `sys.stdin.isatty()`. A return value of `True` indicates an interactive local session, while `False` suggests a headless server environment.

### Step 4: Config Directory Writability Test

As a final safety net, the function attempts to create or write to the user-specific config directory `~/.agent-reach`. If this operation fails due to read-only filesystem constraints common in CI containers, the environment is classified as a server.

```python

# agent_reach/utils/paths.py

def is_server() -> bool:
    """Return True when running on a non‑interactive server/CI."""
    # 1️⃣ explicit hint

    env = os.getenv("AGENT_REACH_ENV", "").lower()
    if env in ("server", "local"):
        return env == "server"

    # 2️⃣ CI detection

    ci_vars = ("CI", "GITHUB_ACTIONS", "GITLAB_CI", "TRAVIS")
    if any(os.getenv(v) for v in ci_vars):
        return True

    # 3️⃣ TTY check

    if sys.stdin.isatty():
        return False

    # 4️⃣ Config‑dir writability test

    try:
        Config()._ensure_dir()
        return False
    except OSError:
        return True

```

## How Detection Results Drive Behavior Across the Codebase

The `is_server()` function is imported throughout the Agent Reach codebase to conditionally adjust behavior. The result is cached in `Config.is_server` and consulted by the CLI, doctor, and configuration manager.

### CLI Output Adjustments in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)

The CLI entry point uses the detection result to toggle between interactive and quiet modes. When `is_server()` returns `True`, the application disables colorful output and progress bars suitable for headless environments.

```python

# agent_reach/cli.py (excerpt)

from .utils.paths import is_server

def main():
    if is_server():
        # no colourful output, no progress bars

        logger.info("Running in head‑less/server mode")
    else:
        # interactive prompts, colour, progress bars

        logger.info("Running on a local workstation")

```

### Diagnostic Reporting in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py)

The doctor command imports `is_server()` to report the detected environment in its diagnostics output, helping users verify their current execution context.

```python

# agent_reach/doctor.py (excerpt)

from .utils.paths import is_server

def run():
    env = "server" if is_server() else "local"
    print(f"Environment detected: {env}")

```

### Credential Safety in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)

The configuration manager uses the detection to prevent accidental credential storage on servers. When running in server mode, it refuses to write sensitive keys ending in `"token"` or `"key"`.

```python

# agent_reach/config.py (excerpt)

from .utils.paths import is_server

def set(self, key: str, value: Any):
    if is_server() and key.lower().endswith(("token", "key")):
        raise RuntimeError("Refusing to store credentials on a non‑interactive server")
    self.data[key] = value
    self.save()

```

## Summary

- The `is_server()` function in [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py) implements a four-tier detection strategy to auto-detect between local computer and server environments.
- Detection follows this priority order: explicit `AGENT_REACH_ENV` variable → CI environment variables → TTY check → config directory writability test.
- The result is cached and used by [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py), [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py), and [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) to adapt logging, diagnostics, and security behaviors.
- Local environments receive interactive output with colors and progress bars, while server environments run headless with safety guards against credential leakage.

## Frequently Asked Questions

### How can I force Agent Reach to run in server mode regardless of environment detection?

Set the environment variable `AGENT_REACH_ENV=server` before executing any commands. This bypasses all automatic detection logic in [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py) and forces the application to behave as if it were running on a headless server.

### Why does Agent Reach detect my local terminal as a server environment?

If `is_server()` returns `True` on your local machine, check that your terminal is a proper TTY and that you have write permissions to `~/.agent-reach`. Containerized environments or redirected stdin/stdout (e.g., piping commands) may cause `sys.stdin.isatty()` to return `False`, triggering server mode detection.

### Which CI platforms are automatically detected by Agent Reach?

The code explicitly checks for `CI`, `GITHUB_ACTIONS`, `GITLAB_CI`, and `TRAVIS` environment variables. If any of these are present, the environment is classified as a server regardless of other signals.

### Can I use the `is_server()` function in my own Agent Reach extensions?

Yes, you can import `is_server()` from `agent_reach.utils.paths` to ensure your custom plugins respect the same environment detection rules as the core application. This maintains consistency in logging, interactivity, and security checks across the entire codebase.