# OpenClaw Windows Node Architecture: A Modular Four-Layer Desktop System

> Explore the modular four-layer desktop architecture of OpenClaw Windows Node. Discover how WinUI, WebSocket, credentials, and onboarding logic are separated for enhanced testability and maintainability.

- Repository: [openclaw/openclaw-windows-node](https://github.com/openclaw/openclaw-windows-node)
- Tags: architecture
- Published: 2026-06-06

---

**OpenClaw Windows Node implements a modular, layered desktop architecture that separates the WinUI tray interface from WebSocket connection management, credential persistence, and on-boarding logic to ensure testability and maintainability.**

OpenClaw Windows Node is a Windows desktop application that provides a system-tray experience for connecting a user's local machine to an OpenClaw gateway. According to the source code in `openclaw/openclaw-windows-node`, the architecture cleanly divides responsibilities across four distinct layers, preventing direct UI-to-network coupling and enabling both headed and headless operation modes.

## The Four Architectural Layers

The codebase organizes functionality into isolated tiers, each with explicit boundaries and public interfaces.

### UI (Tray) Layer

The topmost layer presents the user-facing interface through WinUI 3 XAML pages and Windows system-tray integration. Key components include:

- `src/OpenClaw.Tray.WinUI/Pages/ConnectionPage.xaml` – Displays connection status and gateway pairing UI.
- [`src/OpenClaw.Tray.WinUI/Services/NodeService.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Tray.WinUI/Services/NodeService.cs) – A background service that keeps the node process alive independently of visible UI pages.
- [`src/OpenClaw.Tray.WinUI/App.xaml.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Tray.WinUI/App.xaml.cs) – Application bootstrap that instantiates a singleton `GatewayConnectionManager` and wires it to the NodeService.

UI pages never invoke the gateway client directly; they interact exclusively through the connection manager's immutable snapshot (`GatewaySnapshot`).

### Connection Layer

This layer manages the lifecycle of the WebSocket connection to the gateway, handles pairing handshakes, and implements reconnection logic.

- [`src/OpenClaw.Connection/GatewayConnectionManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Connection/GatewayConnectionManager.cs) – The single owning object per process that opens the WebSocket, performs the device handshake, and stores tokens. It exposes `EnsureNodeConnectedAsync()` and `DisconnectAsync()` APIs.
- [`src/OpenClaw.Connection/IGatewayConnectionManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Connection/IGatewayConnectionManager.cs) – The public interface consumed by UI and service layers.
- [`src/OpenClaw.Connection/ChatNavigationReadiness.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Connection/ChatNavigationReadiness.cs) – Helper class that queries the manager to determine when the operator handshake is complete and chat UI can be shown.

The `GatewayConnectionManager` in [`src/OpenClaw.Connection/GatewayConnectionManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Connection/GatewayConnectionManager.cs) follows a **Single Owner Model**, ensuring only one connection instance exists per process to prevent duplicate sockets and state fragmentation.

### Credential & Registry Layer

Responsible for persisting gateway credentials and abstracting migration logic from legacy formats.

- [`src/OpenClaw.Shared/GatewayRegistry.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Shared/GatewayRegistry.cs) – The newer API that all writes traverse; reads from `%APPDATA%\OpenClawTray\gateways.json` and per-gateway identity files.
- [`src/OpenClaw.Shared/Settings/SettingsManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Shared/Settings/SettingsManager.cs) – Legacy settings reader/writer used only for one-time migration scenarios.

Credential storage follows a strict **Token Precedence** hierarchy: device token takes priority over shared gateway token, which takes priority over bootstrap token. The system never downgrades a paired device back to bootstrap credentials.

### Setup / On-boarding Layer

Guides new installations through pairing, QR code scanning, and initial configuration generation.

- [`src/OpenClaw.SetupEngine/SetupWizardRunner.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.SetupEngine/SetupWizardRunner.cs) – Orchestrates the wizard steps defined in [`SetupPipeline.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/SetupPipeline.cs) and [`SetupContext.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/SetupContext.cs).
- `src/OpenClaw.SetupEngine.UI` – XAML views for the on-boarding flow (welcome, permissions, progress).
- [`src/OpenClaw.SetupEngine/TrayArtifactCleanup.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.SetupEngine/TrayArtifactCleanup.cs) – Removes stale tray artifacts after successful setup.

The SetupEngine is a pure-C# pipeline executable in both interactive UI mode and headless CLI mode.

### CLI Layer (Optional)

Provides a command-line entry point for scripting or automation scenarios.

- [`src/OpenClaw.WinNode.Cli/Program.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.WinNode.Cli/Program.cs) – Parses arguments and runs the node without WinUI, utilizing the same `GatewayConnectionManager` and `GatewayRegistry` services as the tray application.

## Layer Interaction Lifecycle

Understanding how these layers interact reveals the system's startup and operational flow.

1. **Startup** – [`App.xaml.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/App.xaml.cs) creates the singleton `GatewayConnectionManager` and registers it with `NodeService`.
2. **Credential Load** – `GatewayRegistry` attempts to read `%APPDATA%\OpenClawTray\gateways.json`. If no gateway exists, the SetupEngine launches the on-boarding wizard.
3. **Pairing** – `GatewayConnectionManager` opens a WebSocket to the gateway URL, negotiates the handshake, and persists the resulting device token via the registry.
4. **Operation** – UI pages like `ChatPage.xaml` and `ChannelsPage.xaml` subscribe to connection events exposed by the manager, sending and receiving messages through its API.
5. **Reconnection** – Upon WebSocket failure, the manager automatically reattempts connection using the stored token hierarchy without UI intervention.

## Key Architectural Concepts

The design enforces several invariants that simplify testing and extension.

**Single Owner Model** – Only one `GatewayConnectionManager` instance exists per process. This prevents race conditions in connection state and provides a unified source of truth for the UI.

**Decoupled UI** – View logic depends solely on the `IGatewayConnectionManager` interface and immutable snapshots. The UI layer has no reference to WebSocket implementations or network protocols.

**Isolation for Tests** – The test suite replaces `SettingsManager` with a temporary directory specified by the `OPENCLAW_TRAY_DATA_DIR` environment variable, ensuring unit tests never touch real user data in `%APPDATA%`.

**Modular On-boarding** – The SetupEngine pipeline in `src/OpenClaw.SetupEngine` can execute headlessly or with full WinUI visuals, making it reusable across the tray app and CLI tool.

## Practical Code Examples

Below are typical interactions with the core architecture.

Creating and connecting via the manager:

```csharp
// Bootstrap (normally in App.xaml.cs)
var manager = new GatewayConnectionManager(
    resolver: new GatewayUrlResolver(),
    factory: new WebSocketFactory(),
    registry: new GatewayRegistry(),
    logger: NullLogger.Instance);

// Connect from UI or service
await manager.EnsureNodeConnectedAsync(CancellationToken.None);

// Query state for data binding
var snapshot = manager.CurrentSnapshot;
bool isConnected = snapshot.IsConnected;
bool chatReady = ChatNavigationReadiness.IsOperatorHandshakeReady(manager);

```

Running the on-boarding wizard programmatically:

```csharp
var wizard = new SetupWizardRunner(
    pipeline: new SetupPipeline(),
    logger: NullLogger.Instance);

await wizard.RunAsync(CancellationToken.None);

```

Reading persisted credentials:

```csharp
var registry = new GatewayRegistry(); // reads %APPDATA%\OpenClawTray\gateways.json
var gateway = registry.GetGatewayById("my-gateway-id");
string deviceToken = gateway?.DeviceToken;

```

## Summary

- OpenClaw Windows Node uses a **four-layer architecture** (UI, Connection, Credential, Setup) to isolate concerns.
- `GatewayConnectionManager` in [`src/OpenClaw.Connection/GatewayConnectionManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Connection/GatewayConnectionManager.cs) is the sole owner of WebSocket lifecycle and enforces single-instance semantics.
- Credentials follow a strict precedence (device → shared → bootstrap) and persist to `%APPDATA%\OpenClawTray\` via `GatewayRegistry`.
- The SetupEngine supports both GUI and CLI execution modes, defined in [`src/OpenClaw.SetupEngine/SetupWizardRunner.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.SetupEngine/SetupWizardRunner.cs).
- UI decoupling is achieved through immutable snapshots and the `IGatewayConnectionManager` interface, enabling comprehensive test isolation.

## Frequently Asked Questions

### How does OpenClaw Windows Node handle connection reconnection?

The `GatewayConnectionManager` continuously monitors the underlying WebSocket. Upon detecting a failure, it automatically triggers `EnsureNodeConnectedAsync`, which attempts reconnection using the stored token hierarchy without requiring user interaction. As implemented in [`src/OpenClaw.Connection/GatewayConnectionManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Connection/GatewayConnectionManager.cs), this process respects the token precedence—device tokens are preferred over shared or bootstrap tokens—and persists new credentials through `GatewayRegistry` upon successful re-handshake.

### Where are gateway credentials stored on disk?

Gateway credentials are persisted as JSON files under `%APPDATA%\OpenClawTray\`. The `GatewayRegistry` class in [`src/OpenClaw.Shared/GatewayRegistry.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Shared/GatewayRegistry.cs) manages reading and writing to [`gateways.json`](https://github.com/openclaw/openclaw-windows-node/blob/main/gateways.json) and individual gateway identity files. Legacy migration logic from older versions is handled by `SettingsManager` in [`src/OpenClaw.Shared/Settings/SettingsManager.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.Shared/Settings/SettingsManager.cs), but all new writes flow exclusively through the `GatewayRegistry` API.

### Can the application run without the WinUI interface?

Yes. The [`src/OpenClaw.WinNode.Cli/Program.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/src/OpenClaw.WinNode.Cli/Program.cs) entry point provides a headless mode that parses command-line arguments and executes the `GatewayConnectionManager` and `SetupEngine` without loading any XAML pages. This CLI layer uses identical services to the tray application, ensuring consistent behavior across interactive and automated deployment scenarios.

### What prevents multiple simultaneous connections to the same gateway?

The **Single Owner Model** enforced by `GatewayConnectionManager` ensures only one instance exists per process. The application bootstrap in [`App.xaml.cs`](https://github.com/openclaw/openclaw-windows-node/blob/main/App.xaml.cs) creates this as a singleton and injects it into `NodeService` and UI pages. This architectural constraint prevents duplicate WebSocket connections and eliminates state fragmentation between competing connection managers.