# OfficeCLI Watch Command Live HTML Preview Auto-Refresh: Architecture and Usage

> Explore the OfficeCLI watch command architecture for live HTML preview auto-refresh. Learn how SSE relay, named pipes, and embedded JS deliver seamless DOM updates to your browser.

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: architecture
- Published: 2026-07-12

---

**The `officecli watch` command launches a Server-Sent Events (SSE) relay server that pushes HTML updates to your browser automatically whenever the document changes, using named pipes for IPC and embedded JavaScript for DOM diffing.**

The **OfficeCLI watch command live HTML preview auto-refresh** feature transforms document editing into a real-time web experience. Found in the iOfficeAI/OfficeCLI repository, this subsystem renders Word, Excel, and PowerPoint files as HTML and updates the browser instantly on every modification. The architecture cleanly separates document handling from network transmission through a three-layer design involving CLI orchestration, an SSE relay server, and client-side JavaScript overlays.

## Architecture Overview

The implementation spans three tightly-coupled layers that ensure the browser preview stays synchronized with your document without requiring manual refreshes.

### CLI Orchestration Layer (CommandBuilder.Watch.cs)

The entry point lives in [`src/officecli/CommandBuilder.Watch.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/CommandBuilder.Watch.cs) (lines 12-34), where the `watch` command parses arguments and initializes the rendering pipeline.

**Argument handling** expects a file path and an optional `--port` flag (default **26315**). The system first attempts to obtain HTML via a resident process (`ResidentClient.TrySend`) using `mode=html` and `Json=true`. If no resident process exists, it falls back to `DocumentHandlerFactory.Open` followed by `RenderViaRegistry` to generate the initial HTML snapshot.

Once rendering completes, the code creates a `WatchServer` instance with the file path, chosen port, and initial HTML. The entire lifecycle wraps in `SafeRun` to guarantee clean shutdown on SIGINT or SIGTERM.

### SSE Relay Server (WatchServer.cs)

The `WatchServer` class in [`src/officecli/Core/Watch/WatchServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/Watch/WatchServer.cs) (lines 16-30) functions as a **pure SSE relay** that never touches the document file directly. It receives pre-rendered HTML through a **named pipe** (`WatchNotifier`) and forwards updates to connected browsers via Server-Sent Events.

Key server responsibilities include:

- **Embedded script injection**: The `SseScriptContent` property lazily loads [`watch-sse-core.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-sse-core.js) and [`watch-overlay.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-overlay.js) via `LoadWatchResource`, injecting them into the page header to ensure the client possesses the required logic.
- **State management**: The server maintains in-memory **selection** (`_currentSelection`) and **marks** (`_currentMarks`) protected by `_selectionLock` and `_marksLock`, enabling fast queries via `WatchNotifier.GetSelection` and modifications via `WatchNotifier.AddMark`.
- **Idle shutdown**: The `ResolveIdleTimeout` method (lines 106-119) reads the `OFFICECLI_WATCH_IDLE_SECONDS` environment variable (default 5 minutes) and terminates the server automatically when no activity occurs.
- **Robust termination**: All shutdown paths—idle timeout, `unwatch` command, or OS signals—converge on a single `_shutdownTask` guarded by `_shutdownLock`, ensuring the underlying `TcpListener` stops cleanly.

### Client-Side Overlay (Embedded JavaScript)

Two embedded JavaScript resources handle the browser-side update mechanism:

**Layer 1 – [`watch-sse-core.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-sse-core.js)**: This script creates the SSE connection, listens for `"html"` events, and applies DOM diffs using a minimal patch algorithm. It exposes `window._watchEs` (the `EventSource` instance) and invokes `window._watchReapplyHook` after each mutation.

**Layer 2 – [`watch-overlay.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-overlay.js)**: This script registers `window._watchReapplyHook` to implement selection handling, mark rendering, and UI decorations such as rubber-band drawing and CSS injection. It communicates back to the server via the named pipe for actions like **mark**, **goto**, and **unmark**.

## Starting Watch Sessions and Managing State

To initiate a live preview session, specify the target document and optional port:

```bash

# Default port 26315

officecli watch MyReport.docx

# Custom port

officecli watch MyPresentation.pptx --port 3000

```

While the watch server runs, you can interact with the session through sub-commands:

**Mark the current selection** (adds an advisory annotation):

```bash
officecli watch MyReport.docx mark --color yellow --path /body/p[3]

```

**List all marks**:

```bash
officecli watch MyReport.docx marks

```

**Navigate to a specific element**:

```bash
officecli watch MyReport.docx goto --path /body/p[5]

```

**Terminate the session**:

```bash
officecli unwatch MyReport.docx

```

## Programmatic Integration with WatchNotifier

External tools can push updates to the watch server using the `WatchNotifier` static API in [`src/officecli/Core/Watch/WatchNotifier.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/Watch/WatchNotifier.cs). This named-pipe client provides non-blocking methods that fail silently if no watch process exists, preventing CLI crashes.

```csharp
// C# example – push a new HTML snapshot programmatically

bool ok = WatchNotifier.SendRefresh(
    filePath: @"C:\Docs\MyReport.docx",
    html: "<html>…</html>",
    version: 42);

```

Other available methods include `GetSelection` for querying the current selection, `AddMark`/`RemoveMark` for annotation management, and `Close` for shutting down the server remotely.

## Summary

- The **OfficeCLI watch command** provides live HTML preview auto-refresh for Word, Excel, and PowerPoint documents through a three-layer architecture.
- **CommandBuilder.Watch.cs** handles CLI argument parsing, initial rendering via resident process or direct handler invocation, and `WatchServer` lifecycle management.
- **WatchServer.cs** acts as a pure SSE relay using named pipes for IPC, maintaining in-memory selection and mark state with thread-safe locks.
- The client-side overlay uses [`watch-sse-core.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-sse-core.js) for DOM diffing and [`watch-overlay.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-overlay.js) for UI interactions, enabling seamless auto-refresh without page reloads.
- Optional environment variable `OFFICECLI_WATCH_IDLE_SECONDS` controls automatic server shutdown (default 5 minutes).
- **WatchNotifier** provides a programmatic API for external tools to send updates, query state, and control the server.

## Frequently Asked Questions

### How does the auto-refresh mechanism work without reloading the page?

The browser maintains a persistent Server-Sent Events connection to the `WatchServer`. When the document changes, the CLI sends new HTML through a named pipe to the server, which pushes it to the browser via SSE. The embedded [`watch-sse-core.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/watch-sse-core.js) applies a minimal DOM diff patch to update only changed elements, preserving scroll position and selection state.

### What happens if the watch server becomes idle?

The server monitors activity through the `ResolveIdleTimeout` method (lines 106-119 in [`WatchServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WatchServer.cs)). If no updates, selections, or mark operations occur within the duration specified by `OFFICECLI_WATCH_IDLE_SECONDS` (default 300 seconds), the server triggers automatic shutdown to free resources. All cleanup operations flow through `_shutdownTask` to ensure the TCP listener closes properly.

### Can I use the watch feature with custom HTML generators?

Yes. While the CLI defaults to the internal `DocumentHandlerFactory` and registry-based rendering, you can bypass the resident process and inject custom HTML programmatically using `WatchNotifier.SendRefresh`. This method accepts an arbitrary HTML string and version number, pushing it directly to connected browsers regardless of the source document format.

### How do I clean up a running watch server?

Use the `unwatch` command followed by the file path: `officecli unwatch MyReport.docx`. This sends a termination signal through the named pipe that triggers the server's `_shutdownTask`. Alternatively, sending SIGINT (Ctrl+C) to the original `watch` process or allowing the idle timeout to expire will also terminate the server cleanly.