How to Handle File-on-Disk Refresh Timing in OfficeCLI: Save, Close, and Flush Modes Explained

OfficeCLI controls when in-memory document changes become visible on disk through four flush modes—each, auto, fixed intervals, and off—configured via the OFFICECLI_RESIDENT_FLUSH environment variable, with explicit save, close, and refresh commands providing manual control over write timing.

OfficeCLI operates as a resident process that keeps documents in memory while you execute commands, using a dirty flag (_dirty) to track modifications. Understanding how to manage file-on-disk refresh timing is crucial when integrating OfficeCLI with external tools that need immediate read access after modification. The flush policy determines exactly when mutated content transitions from memory to disk, balancing performance against data visibility.

Understanding the Flush Policy Architecture

OfficeCLI maintains a resident server that holds documents in memory between commands. When the in-memory DOM is mutated, changes are marked as dirty in ResidentServer.cs (lines 23-28) where the _dirty flag tracks unsaved modifications.

The flush policy governs when these dirty changes become visible on disk:

  • each: Flushes immediately before every mutation command returns, ensuring deterministic writes
  • auto: Flushes after an adaptive idle period (default), using an interval that adjusts based on measured save cost (2-10 seconds) according to ResidentFlushPolicy.cs (lines 11-13)
  • fixed : Flushes after a fixed idle interval of N seconds configured via environment variable, as implemented in ResidentFlushPolicy.cs (lines 73-78)
  • off / 0: Disables automatic flushing, writing only on explicit save, close, or process shutdown

Configuring Flush Modes

The flush policy reads from the environment variable OFFICECLI_RESIDENT_FLUSH (or the legacy OFFICECLI_RESIDENT_IDLE_SAVE_SECONDS) during ResidentServer static construction, specifically in lines 31-42. The server caches the selected mode in ResidentServer.FlushMode (lines 28-30) at startup.

To configure the mode for your session:


# Deterministic flush – every mutation writes to disk immediately

export OFFICECLI_RESIDENT_FLUSH=each

# Adaptive background flush (default behavior)

export OFFICECLI_RESIDENT_FLUSH=auto

# Fixed 5-second idle flush interval

export OFFICECLI_RESIDENT_FLUSH=5

# No automatic flushing – manual save/close only

export OFFICECLI_RESIDENT_FLUSH=off

Changing the variable requires restarting the resident process, as the mode is cached during initialization.

How Commands Interact with the Dirty Flag

The interaction between CLI commands and disk writes varies by operation:

Set and Add Commands

Mutation commands like officecli set or officecli add set the dirty flag to true via PromoteToEditable in ResidentServer.cs (lines 19-27).

If the flush mode is each, ResidentServer performs an immediate _handler.Save() before returning, as shown in lines 92-99. For other modes, the dirty flag remains set until the autosave watchdog flushes or you issue an explicit save.

Save Command

The officecli save <file> command calls _handler.Save() and clears the dirty flag (lines 94-101). This guarantees the file is up-to-date on disk and resets the autosave interval via RecordSaveDuration.

Close Command

Running officecli close <file> triggers a graceful shutdown via ShutdownAsync (lines 35-45), which disposes the handler and flushes any remaining dirty state. After close, the resident process exits and the file is guaranteed saved.

Refresh Command

The officecli refresh <file> command does not modify the dirty flag. Instead, it recomputes derived content inside the document:

  • Word PDF fields: Invokes WordPdfBackend.RefreshFields (lines 555-560)
  • Word HTML preview: Invokes WordHtmlRefresh.RefreshViaHtml (lines 14-18)

Both are called from ResidentServer.ExecuteRefresh (lines 2404-2421). Although refresh does not mark the document dirty, it writes refreshed content to disk, making it visible to external readers even when flush mode is off.

Practical Usage Examples

Shell Workflow with Controlled Flushing


# 1. Start a resident with default (auto) flush mode

officecli open mydoc.docx

# 2. Mutate the document – dirty flag becomes true

officecli set paragraph 1 "Hello world"

# 3. Enable immediate flush mode for critical writes

export OFFICECLI_RESIDENT_FLUSH=each
officecli set paragraph 2 "Another line"

# Command returns only after writing to disk

# 4. Manual save – works regardless of flush mode

officecli save mydoc.docx

# 5. Refresh derived field values

officecli refresh mydoc.docx

# 6. Close and force final flush

officecli close mydoc.docx

Programmatic Control (C#)

For applications embedding OfficeCLI directly:

var server = new ResidentServer("mydoc.docx", editable: true);

// Mutate in-memory DOM (sets _dirty = true)
server.Handler.SetParagraphText(1, "New text");

// Force immediate disk write
server.Handler.Save();

// Refresh PDF fields without dirtying
WordPdfBackend.RefreshFields("mydoc.docx");

// Graceful shutdown with final flush
await server.ShutdownAsync();

Summary

  • OfficeCLI uses four flush modes (each, auto, fixed, off) controlled by the OFFICECLI_RESIDENT_FLUSH environment variable
  • The _dirty flag in ResidentServer.cs tracks unsaved modifications until explicit saves or automatic flushes occur
  • each mode provides immediate disk visibility but impacts performance; auto balances performance with adaptive timing
  • save commands guarantee disk consistency and reset autosave timers, while close triggers final cleanup via ShutdownAsync
  • refresh commands write derived content (fields, previews) to disk without setting the dirty flag, ensuring external tools see updates even when automatic flushing is disabled

Frequently Asked Questions

What is the default flush mode in OfficeCLI?

auto is the default mode, which flushes changes after an adaptive idle period typically between 2-10 seconds. This behavior is defined in ResidentFlushPolicy.cs (lines 11-13) where an exponential moving average adjusts the debounce interval based on measured save costs.

How do I force immediate disk writes after every edit?

Set export OFFICECLI_RESIDENT_FLUSH=each before starting the resident process. In this mode, ResidentServer executes _handler.Save() immediately before returning from mutation commands (lines 92-99), ensuring the file is always current on disk when the CLI prompt returns.

Does the refresh command trigger a disk flush?

While refresh does not modify the _dirty flag, it writes derived content (such as PDF fields or HTML previews) directly to the package using the same save path as manual saves. This means external readers see refreshed content immediately, even when the flush mode is set to off or when no other changes have been made to the document.

What happens to unsaved changes if the resident process crashes?

If the process terminates unexpectedly while _dirty is true and flush mode is off or auto with pending debounce, unsaved changes are lost. Only changes written via each mode, explicit save commands, or close operations are guaranteed on disk, as these invoke the save handler and file disposal routines in ResidentServer.cs.

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 →