-
Notifications
You must be signed in to change notification settings - Fork 852
command batch
Execute multiple commands in a single pass.
officecli batch <file> [--input <file>] [--commands '<json>'] [--stop-on-error] [--force] [--json]
Executes a sequence of commands from a JSON array, opening the document once and saving once at the end. This is more efficient than running individual commands.
By default, execution continues on error — per-item errors surface in BatchResult.Error and any failure still returns exit 1, but the rest of the batch runs and succeeded changes are saved to disk. This is the safer default for dump → batch round-trips, where aborting on the first failing item could lose 80% of the document.
Use --stop-on-error to opt back into the strict abort-on-first-error mode. --force is decoupled from continue-on-error and remains the docx-protection bypass.
Commands are read from a JSON file (--input), inline JSON (--commands), or from stdin.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
file |
FileInfo | Yes | - | Office document path |
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
--input |
FileInfo | No | stdin | JSON file containing batch commands |
--commands |
string | No | - | Inline JSON array of batch commands (alternative to --input or stdin) |
--stop-on-error |
bool | No | false |
Abort the batch on the first failing command. Default: continue, then return exit 1 if any item failed. |
--force |
bool | No | false |
docx-protection bypass (decoupled from error handling) |
--json |
bool | No | false |
Output results as structured JSON envelope {success, data} (parity with resident mode) |
The input is a JSON array of command objects. Each object has the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
command |
string | Yes | Command name: get, query, set, add, remove, move, swap, view, raw, raw-set, validate. Alias: op
|
path |
string | No | DOM path (for get, set, remove, move) |
parent |
string | No | Parent path (for add) |
type |
string | No | Element type (for add) |
from |
string | No | Source path for copy (for add) |
index |
int | No | Insert position (for add, move) |
after |
string | No | Insert/move after anchor path or find:text (for add, move) |
before |
string | No | Insert/move before anchor path or find:text (for add, move) |
to |
string | No | Target parent (for move). Auto-inferred from after/before if omitted. |
path2 |
string | No | Second element path (for swap) |
props |
object OR string[] | No | Properties for set / add. Accepts an object ({"font":"Arial","size":"12pt"}) or an array of "k=v" strings (["font=Arial","size=12pt"]) — the latter is friendlier to hand-authored JSONL and mirrors the CLI --prop k=v form. |
selector |
string | No | CSS-like selector (for query) |
mode |
string | No | View mode (for view) |
depth |
int | No | Child depth (for get) |
part |
string | No | Part path (for raw, raw-set) |
xpath |
string | No | XPath expression (for raw-set) |
action |
string | No | XML action (for raw-set) |
xml |
string | No | XML fragment (for raw-set) |
Each result is prefixed with its 1-based index:
[1] OK
[2] output text here
[3] ERROR: error message
---
3 commands: 2 succeeded, 1 failed
{
"results": [
{ "index": 0, "success": true, "output": "..." },
{ "index": 1, "success": true, "output": "..." },
{ "index": 2, "success": false, "error": "error message", "item": { "command": "set", "path": "/slide[999]", "props": { "title": "bad" } } }
],
"summary": {
"total": 3,
"executed": 3,
"succeeded": 2,
"failed": 1,
"skipped": 0
}
}When get or query commands return structured data, the output field contains the parsed JSON object directly (not a double-encoded string).
Failed results include the original batch item in the item field, so the caller can inspect the failing command and its parameters without having to correlate by index.
When the JSON output exceeds 8 KB, the full results are written to a temp file and a slim envelope is returned inline:
{
"outputFile": "/tmp/officecli_batch_abc123.json",
"outputSize": 156234,
"results": [
{ "index": 0, "success": true },
{ "index": 1, "success": true },
{ "index": 2, "success": false, "error": "Slide 999 not found", "item": { "command": "set", "path": "/slide[999]", "props": { "title": "bad" } } }
],
"summary": { "total": 3, "executed": 3, "succeeded": 2, "failed": 1, "skipped": 0 }
}The temp file contains the full original JSON with all output fields. Error messages and the original item are always inline so the caller can act without reading the file.
echo '[
{"command": "set", "path": "/body/p[1]", "props": {"style": "Heading1", "text": "Title"}},
{"command": "add", "parent": "/body", "type": "paragraph", "props": {"text": "New paragraph"}},
{"command": "set", "path": "/body/p[2]", "props": {"bold": "true"}}
]' | officecli batch report.docxofficecli batch report.docx --input commands.jsonofficecli batch report.docx --input commands.json --jsonofficecli batch report.docx --input commands.json --forcecommands.json:
[
{
"command": "set",
"path": "/",
"props": { "title": "Quarterly Report", "author": "Finance Team" }
},
{
"command": "add",
"parent": "/body",
"type": "paragraph",
"props": { "text": "Executive Summary", "style": "Heading1" }
},
{
"command": "add",
"parent": "/body",
"type": "paragraph",
"props": { "text": "This report covers Q4 2024 performance." }
},
{
"command": "add",
"parent": "/body",
"type": "table",
"props": { "rows": "4", "cols": "3" }
},
{
"command": "set",
"path": "/body/tbl[1]/tr[1]/tc[1]",
"props": { "text": "Category", "bold": "true", "shd": "4472C4", "color": "FFFFFF" }
},
{
"command": "set",
"path": "/body/tbl[1]/tr[1]/tc[2]",
"props": { "text": "Q3", "bold": "true", "shd": "4472C4", "color": "FFFFFF" }
},
{
"command": "set",
"path": "/body/tbl[1]/tr[1]/tc[3]",
"props": { "text": "Q4", "bold": "true", "shd": "4472C4", "color": "FFFFFF" }
},
{
"command": "get",
"path": "/body",
"depth": 1
},
{
"command": "validate"
}
][
{ "command": "add", "parent": "/", "type": "sheet", "props": { "name": "Summary" } },
{ "command": "set", "path": "/Summary/A1", "props": { "value": "Total Revenue", "bold": "true" } },
{ "command": "set", "path": "/Summary/B1", "props": { "formula": "=SUM(Sheet1!B:B)", "numFmt": "#,##0.00" } },
{ "command": "add", "parent": "/Summary", "type": "chart", "props": {
"chartType": "bar",
"title": "Revenue by Quarter",
"categories": "Q1,Q2,Q3,Q4",
"series1": "Revenue:1000,2000,1500,3000"
}}
][
{ "command": "add", "parent": "/", "type": "slide", "props": { "title": "Introduction", "layout": "title" } },
{ "command": "set", "path": "/slide[1]", "props": { "background": "1A1A2E" } },
{ "command": "add", "parent": "/slide[1]", "type": "shape", "props": {
"text": "Welcome",
"x": "2cm", "y": "3cm", "width": "20cm", "height": "5cm",
"font": "Arial", "size": "36", "bold": "true", "color": "FFFFFF",
"fill": "none"
}},
{ "command": "add", "parent": "/", "type": "slide", "props": { "layout": "blank" } },
{ "command": "add", "parent": "/slide[2]", "type": "chart", "props": {
"chartType": "pie",
"title": "Market Share",
"categories": "Product A,Product B,Product C",
"data": "Share:40,35,25",
"x": "2cm", "y": "2cm", "width": "20cm", "height": "15cm"
}}
]A standalone batch saves to disk on its own, so this example needs nothing extra:
officecli batch report.docx --input commands.json # applied AND saved to disk
python my_reader.py report.docx # reads the new contentBut if a resident is already running for the file — because you called open, or ran any earlier command that auto-started one — the batch is applied in memory and the save is deferred. It will be flushed automatically by the idle auto-save (adaptive 2–10s after the last command), but if a non-OfficeCLI tool must read the file right away, flush explicitly:
officecli open report.docx # resident now holds the file
officecli batch report.docx --input commands.json # applied in memory, NOT yet on disk
officecli save report.docx # flush to disk, keep the resident (stays fast)
python my_reader.py report.docx # now reads the new content
officecli close report.docx # flush + release when finishedUse save for an immediate mid-session flush and close when you are done. The full set of flush triggers (explicit save/close + automatic idle auto-save / idle shutdown) is in open / close → When the file on disk is refreshed.
- All commands in a batch run in a single pass (one open/save cycle standalone; a deferred flush under a resident), making batch mode significantly faster than individual commands.
- By default, execution continues on error and returns a non-zero exit if any item failed; use
--stop-on-errorto abort on the first failure (--forceis a deprecated alias of the continue default). - Succeeded commands' changes are kept even when a later command fails (partial application by design —
addcommands are not idempotent, so rollback would cause duplicates on retry). - Returns non-zero exit code when any command fails.
- Read-only commands (get, query, view, validate) can be mixed with write commands.
- Add commands accept
pathas fallback whenparentis not set. - A standalone batch (no resident running) opens the file, applies every item, and saves to disk before exiting — no separate
save/closeis needed, and an external tool can read the file immediately afterward. - When a resident is active (you ran
open, or any prior command auto-started one), the batch is forwarded into the resident and applied in memory with the save deferred — the file on disk is not updated until a flush: the idle auto-save (adaptive 2–10s),officecli save,officecli close, or idle shutdown. (UnderOFFICECLI_RESIDENT_FLUSH=eachthe batch flushes once, before it returns.) This is the same deferred-flush behavior as individual commands; see Persisting changes for external readers below. (A read routed through OfficeCLI still sees the change immediately.)
- Command Reference - Overview of all commands
- open / close - Alternative for multi-step workflows
Based on OfficeCLI v1.0.73