How the OfficeCLI Watch Command Provides Live Browser Preview with Auto-Refresh
The OfficeCLI watch command launches a lightweight Server-Sent Events (SSE) server that broadcasts HTML snapshots to connected browsers via named-pipe IPC, enabling real-time updates without file-lock contention.
The iOfficeAI/OfficeCLI repository provides a command-line interface for manipulating Microsoft Office documents. Its watch feature creates a self-contained preview environment that automatically refreshes browser views whenever the underlying document changes, without requiring manual reloads or suffering from file-lock conflicts.
Architecture of the Live Preview System
The live preview system operates as a multi-process architecture that separates document mutation from rendering. This design prevents the watch server from locking the Office file while still providing instantaneous visual feedback.
The SSE Relay Server
At the core of the system is WatchServer, implemented in src/officecli/Core/Watch/WatchServer.cs. This lightweight TCP listener serves HTTP on localhost:26315 by default and maintains an in-memory HTML cache of the document state.
The server embeds two JavaScript resources—watch-sse-core.js and watch-overlay.js—which it injects into every served page. These handle the client-side EventSource connection and overlay UI features like marks and selection indicators. As implemented in the source, the server never opens the Office document directly; it only operates on HTML snapshots passed via inter-process communication.
Initial HTML Rendering
When you execute officecli watch mydoc.docx, the command first attempts to obtain an HTML view through the resident daemon process. According to src/officecli/CommandBuilder.Watch.cs (lines 34-70), the code calls ResidentClient.TrySend to request a pre-rendered snapshot from the long-running officecli service.
If the resident process is unavailable, the watch command falls back to opening the document directly using the appropriate handler—PowerPointHandler, ExcelHandler, or WordHandler—and invokes RenderViaRegistry to generate the initial HTML. This snapshot is then cached in memory within the WatchServer instance.
Real-Time Update Mechanism via Named Pipes
All other OfficeCLI commands that modify documents—such as set, add, or remove—communicate with the watch server through a named pipe. The WatchNotifier class in src/officecli/Core/Watch/WatchNotifier.cs (lines 15-25) opens the pipe officecli-watch-<hash> and transmits JSON messages describing the change.
These messages support two update modes:
- Full HTML replacement – Contains a complete
FullHtmlsnapshot that replaces the entire document view - Incremental patching – Provides slide-specific or block-level mutations (fields:
replace,add,removeplus slide numbers)
When WatchServer.RunPipeListenerAsync detects an incoming connection, HandleSinglePipeClientAsync parses the JSON via HandleWatchMessage. If FullHtml is present, it updates _currentHtml directly. For patches, it applies methods like PatchSlideInHtml, AppendSlideToHtml, or RemoveSlideFromHtml to mutate the cached HTML. After updating the snapshot, the server increments an internal version counter and broadcasts the change via SendSseEvent.
Client-Side DOM Synchronization
The embedded watch-sse-core.js script establishes an EventSource connection back to the server. Upon receiving SSE messages, it parses the action field and applies updates to the DOM:
- Full refresh – Replaces the entire
<body>element with the new HTML - Slide-level updates – For PowerPoint documents, patches individual slide elements by ID
- Word block updates – Computes block-level diffs using
ComputeWordPatchesfor granular text updates - Auto-scroll – If the SSE message includes a
scrollselector, the script scrolls the viewport to the target element
The companion watch-overlay.js handles auxiliary UI features including visual marks, selection rectangles, and rubber-band highlighting, all synchronized through the same SSE channel.
Configuration and Usage
Start a watch session with automatic port assignment:
# Start watching a Word document (default port 26315)
officecli watch mydoc.docx
The command outputs a URL like Watch: http://localhost:26315. Opening this in any browser connects you to the live preview.
Modify the document in another terminal:
# Update text content - triggers automatic browser refresh
officecli set mydoc.docx --text "Hello, world!"
# Add a visual mark in the preview
officecli watch mark mydoc.docx "/body/p[1]" --color "#ff0000" --note "Important"
The watch server supports environment-based configuration:
OFFICECLI_WATCH_IDLE_SECONDS– Configures the idle timeout (default: 300 seconds). If no browser remains connected for this duration,WatchServertriggers graceful shutdown viaStopAsync, closing TCP sockets and cleaning up the on-disk marker file.- Signal handling – The server captures SIGTERM, SIGHUP, SIGQUIT, and Ctrl-C to ensure clean termination.
Summary
- Server-Sent Events provide the transport mechanism for live updates, with
WatchServeracting as the SSE relay. - Named-pipe IPC (
officecli-watch-<hash>) allows mutation commands to push changes without file-lock conflicts. - Incremental HTML patching minimizes bandwidth and DOM manipulation for large presentations.
- Embedded JavaScript resources handle DOM synchronization, scrolling, and UI overlays client-side.
- Resident process fallback ensures the initial render succeeds even when the daemon is unavailable.
Frequently Asked Questions
How does the watch server avoid locking the Office document?
The WatchServer process never opens the actual .docx, .pptx, or .xlsx file. Instead, it receives HTML snapshots through the named pipe from other officecli processes that perform the document manipulation. This architecture, visible in WatchServer.cs, ensures the preview server remains completely decoupled from file I/O operations.
What happens if I edit the document while the watch server is running?
Any officecli command that modifies the document—such as set, add, or remove—automatically notifies the watch server via WatchNotifier.Send. The command opens the named pipe, transmits a JSON message describing the change, and the server broadcasts an SSE event to all connected browsers, triggering an immediate DOM update without requiring a manual refresh.
Can I use the watch feature without the resident daemon process?
Yes. While CommandBuilder.Watch.cs first attempts to use ResidentClient.TrySend for the initial HTML snapshot to improve performance, the watch command gracefully falls back to direct document rendering via RenderViaRegistry if the daemon is unavailable. This ensures the preview works in standalone mode.
How do I configure the auto-shutdown timeout?
Set the OFFICECLI_WATCH_IDLE_SECONDS environment variable before starting the watch server. The default value is 300 seconds (5 minutes). When configured, WatchServer monitors active SSE connections in its idle watchdog loop (lines 55-73 in WatchServer.cs) and calls StopAsync to terminate cleanly if no clients remain connected past the threshold.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →