# How to Use OfficeCLI Batch Mode for Atomic Multi-Command Execution with Rollback

> Master OfficeCLI batch mode for atomic multi-command execution. Ensure data integrity with automatic rollback on failure. Execute complex tasks reliably.

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: how-to-guide
- Published: 2026-08-02

---

**OfficeCLI batch mode executes multiple commands as a single atomic transaction—if any command fails, the resident process automatically rolls back all changes, leaving the document unchanged.**

OfficeCLI's batch mode lets you send a list of *batch-item* objects to the resident in one round-trip, guaranteeing **atomicity by default**. This guide explains how to structure batch payloads, control rollback behavior, and handle errors using both the Node.js SDK and the raw CLI. All examples reference the actual implementation in `iOfficeAI/OfficeCLI`.

## Understanding Atomic Batch Execution

According to the OfficeCLI source code, the batch command is described as "atomic by default—any failed item rolls back the whole batch" in the README at line 17【https://github.com/iOfficeAI/OfficeCLI/blob/main/README.md#batch-mode---multi-command-execution-atomic-by-default-any-failed-item-rolls-back-the-whole-batch‑line‑17-L17-L31】. This means you can safely chain dependent operations without worrying about partial state corruption.

The atomic guarantee is **enforced by the resident process**, not the SDK. The Node SDK's `Document.batch()` method at lines 519-522 simply forwards the JSON-encoded list to the resident via the pipe protocol【https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js#L519-L522】.

### Batch-Item Structure

Each item in your batch array must contain these keys (see lines 500-505)【https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js#L500-L505】:

| Key | Required | Description |
|-----|----------|-------------|
| `command` (or `op`) | Yes | The operation to perform: `set`, `get`, `delete`, etc. |
| `path` | Yes | Document path targeting a cell, shape, or property |
| `props` | Yes | Object containing operation-specific parameters |

Additional keys are forwarded verbatim as arguments to the underlying command.

## Using the Node.js SDK for Atomic Batches

The SDK provides the cleanest interface for **OfficeCLI batch mode with rollback guarantees**. Here's the complete pattern:

```javascript
const oc = require('@officecli/sdk');

// Open or create a document in resident mode
const doc = await oc.open('financial-report.xlsx');

// Build your batch as an array of operation objects
const batch = [
  {
    command: 'set',
    path: '/Sheet1/A1',
    props: { text: 'Q1 Revenue' }
  },
  {
    command: 'set',
    path: '/Sheet1/B1',
    props: { formula: '=SUM(C2:C10)' }
  },
  {
    command: 'format',
    path: '/Sheet1/A1:B1',
    props: { bold: true, bgColor: '#4472C4' }
  }
];

// Execute atomically—any failure triggers automatic rollback
try {
  const result = await doc.batch(batch);
  console.log('All commands applied:', result);
} catch (err) {
  // Document remains unchanged if any item failed
  console.error('Batch failed, rollback complete:', err);
}

```

On delivery failure, the SDK throws `OfficeCliError` (defined at the top of [`sdk/node/index.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js)). Successful batches return a parsed JSON envelope with operation results.

## Control Flags for Batch Behavior

The SDK accepts options that map directly to CLI flags (lines 519-522)【https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js#L519-L522】:

| Flag | SDK Option | Default | Behavior |
|------|-----------|---------|----------|
| `--force` | `force: true` | `true` | Execute even if resident reports busy status |
| `--stop-on-error` | `stopOnError: true` | `false` | Halt processing on first failure (still rolls back entire batch) |
| `--best-effort` | `bestEffort: true` | `false` | **Disable atomic rollback**—keep successful items, skip failures |

### Force Mode

When `force: true` (default), the resident queues your batch even during active operations. Set `force: false` to fail fast if the resident is busy:

```javascript
// Fail immediately if resident cannot accept the batch
await doc.batch(criticalUpdates, { force: false });

```

### Stop-on-Error Behavior

By default, the resident processes all items to identify every failure. Enable `stopOnError` to abort early—note this does **not** disable rollback:

```javascript
// Stop at first failure (still atomic—everything rolls back)
await doc.batch(largeBatch, { stopOnError: true });

```

## Disabling Rollback: Best-Effort Mode

For non-critical operations where partial success is acceptable, use **best-effort mode**. This opt-in behavior disables the atomic guarantee.

Via CLI:

```bash
officecli batch report.pptx --input updates.json --best-effort --json

```

Via SDK:

```javascript
// Apply what succeeds, skip what fails—no rollback
const partial = await doc.batch(
  [setTitle, setSubtitle, riskyOperation],
  { bestEffort: true }
);

// partial.results contains per-item success/failure status

```

## Raw CLI Usage for Atomic Batches

You can invoke batch mode directly without the SDK, receiving identical atomic guarantees:

```bash

# Pipe JSON array to the batch command

echo '[
  {"command":"set","path":"/Slide1/Title","props":{"text":"Q3 Report"}},
  {"command":"set","path":"/Slide1/Subtitle","props":{"text":"Draft"}},
  {"command":"add","path":"/Slide1","props":{"type":"chart","left":100,"top":200}}
]' | officecli batch presentation.pptx --json

```

The resident parses the stdin JSON, validates each item, and executes as a transaction. Output is a JSON envelope:

```json
{
  "success": true,
  "transactionId": "txn_7f3a9b",
  "results": [
    {"status": "ok", "path": "/Slide1/Title"},
    {"status": "ok", "path": "/Slide1/Subtitle"},
    {"status": "ok", "path": "/Slide1/Shape3", "id": "Shape3"}
  ]
}

```

## Error Handling Patterns

The SDK distinguishes between **transport failures** (throws `OfficeCliError`) and **command failures** (returned in the result envelope). Structure your error handling accordingly:

```javascript
const { OfficeCliError } = require('@officecli/sdk');

try {
  const result = await doc.batch(operations);
  
  // Check for command-level failures even on "success"
  const failures = result.results.filter(r => r.status !== 'ok');
  if (failures.length > 0) {
    console.warn('Some commands failed (batch was rolled back):', failures);
  }
} catch (transportError) {
  if (transportError instanceof OfficeCliError) {
    // Pipe broken, resident crashed, or timeout
    console.error('Cannot reach resident:', transportError.code);
  }
}

```

## Key Implementation Files

| File | Relevance |
|------|-----------|
| [`sdk/node/index.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js) | `Document.batch()` implementation, lines 500-522【https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js】 |
| [`README.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/README.md) | Batch command specification and flag documentation【https://github.com/iOfficeAI/OfficeCLI/blob/main/README.md#batch-mode】 |
| [`ResidentServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ResidentServer.cs) / [`ResidentClient.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ResidentClient.cs) | C# resident process handling actual transaction semantics and rollback |

| Wiki: `command-batch` | Extended syntax reference: https://github.com/iOfficeAI/OfficeCLI/wiki/command-batch |

## Summary

- **Atomic by default**: OfficeCLI batch mode treats your command list as a transaction—any failure triggers automatic rollback inside the resident process.
- **SDK is a thin wrapper**: The Node SDK's `Document.batch()` forwards JSON to the resident without adding logic; guarantees come from the resident itself.
- **Structure items correctly**: Each batch item needs `command`/`op`, `path`, and `props` keys.
- **Control with flags**: Use `force`, `stopOnError`, and `bestEffort` to adjust behavior—only `bestEffort` disables rollback.
- **Handle two error types**: Catch `OfficeCliError` for transport problems; inspect result envelopes for command failures.

## Frequently Asked Questions

### What happens if one command in a batch fails?

The resident automatically rolls back **all changes** from that batch, leaving the document in its pre-batch state. This atomic guarantee is the default behavior in OfficeCLI batch mode and requires no additional code from you.

### Can I disable rollback and keep partial results?

Yes. Pass `--best-effort` to the CLI or `{ bestEffort: true }` to the SDK. This opt-in mode applies successful commands and skips failures without rolling back. Use it only when partial state is acceptable.

### How do I know if a batch succeeded or failed?

The SDK returns a parsed JSON envelope on success—inspect `result.success` and `result.results[]`. On transport failure (broken pipe, crashed resident), the SDK throws `OfficeCliError`. The CLI exits with non-zero status and prints error details to stderr.

### Does the SDK add any transaction logic?

No. The Node SDK at [`sdk/node/index.js`](https://github.com/iOfficeAI/OfficeCLI/blob/main/sdk/node/index.js) lines 519-522 merely encodes your batch array and writes it to the resident's pipe. All transaction semantics, validation, and rollback logic live in the resident process—making the SDK lightweight and the guarantees consistent across all clients.