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

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 (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 (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 and 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: 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: 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:


# 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):

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

List all marks:

officecli watch MyReport.docx marks

Navigate to a specific element:

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

Terminate the session:

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. This named-pipe client provides non-blocking methods that fail silently if no watch process exists, preventing CLI crashes.

// 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 for DOM diffing and 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 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). 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →