When to Use Stable ID Paths (`@attr=value`) in OfficeCLI Instead of Positional Indices

Use stable ID paths (@attr=value) for any multi-step workflow or automation script where document edits might shift positional indices, and reserve positional indices ([n]) only for elements that lack persistent OOXML identifiers like @id, @paraId, or @name.

OfficeCLI is an open-source command-line tool for manipulating Office documents (Word, PowerPoint, Excel) via XML-style addressing. When targeting elements inside .docx, .pptx, or .xlsx files, the CLI generates two types of paths: fragile positional indices and stable ID paths that persist across document changes. Understanding when to use each ensures your automation scripts remain robust against edits.

Understanding XML Path Types in OfficeCLI

OfficeCLI addresses elements using XML-style paths that fall into two distinct categories based on the underlying OOXML schema.

Positional Indices

When an element lacks a persistent identifier, OfficeCLI falls back to positional syntax like /slide[3]/shape[2]. These indices reflect the current ordinal position within the parent collection and are inherently fragile—inserting or deleting a sibling element shifts the numeric index, breaking any saved reference.

Stable ID Paths

When an element exposes a persistent attribute—such as @id, @paraId, @commentId, or @name—OfficeCLI generates a stable path like /slide[1]/shape[@id=550950021]. According to the source code in SchemaHelpRenderer.cs (lines 85-92), the CLI merges both paths.stable and paths.positional lists for user output, but the stable form survives insertions, deletions, and re-ordering.

When to Use Stable ID Paths

Robustness Across Document Edits

Adding a paragraph before an existing one shifts positional indices—/body/p[4] becomes /body/p[5]—but the stable path /body/p[@paraId=1A2B3C4D] remains valid. As implemented in WordHandler.Add.Misc.cs (lines 1660-2341), Word paragraphs expose @paraId and @sdtId attributes, while PowerPoint shapes expose @id and @name via PowerPointHandler.Helpers.ShapeId.cs (lines 90-183).

Concurrency Safety

When multiple scripts or agents interact with the same document, stable IDs guarantee addressability even if parallel edits reorder elements. The underlying OOXML object retains its identifier regardless of sibling changes, ensuring that /body/p[@paraId=1A2B3C4D] always points to the same logical paragraph.

Cross-Command Composition

Stable paths enable you to capture a path from a get or query command and reuse it directly in a subsequent set or mark command without recomputing indices. This is critical for watch-mode workflows where the selected command returns stable @id= paths that can be fed directly into set operations.

When Positional Indices Are Unavoidable

Reserve positional syntax for elements that genuinely lack stable attributes. In Excel, many cell-level operations use positional references like /Sheet1/B2 because rows and cells lack native persistent identifiers. Similarly, newly inserted table rows or PowerPoint slides may only have numeric indices until the document is saved and stable IDs are generated.

According to the user guide in SKILL.md, you should store positional paths only for the duration of the immediate operation and never persist them for later automation.

Practical Code Examples

Querying Stable Paths in Word

List paragraphs with their stable IDs to identify persistent references:

officecli get report.docx '/body/p' --json | jq -r '.data.Results[] | "\(.path)  \(.text)"'

Sample output showing the @paraId attribute:

/body/p[@paraId=1A2B3C4D]  This is the first paragraph.

Using Stable Paths for Updates

Modify a specific paragraph identified by its stable ID. This command succeeds even after other paragraphs are inserted before the target:

officecli set report.docx '/body/p[@paraId=1A2B3C4D]' --prop font=Helvetica

PowerPoint Shape Targeting

Highlight a shape by its stable ID. If you later add a new shape before the target, the numeric index (shape[2]) would shift, but the @id path remains correct:

officecli set deck.pptx '/slide[1]/shape[@id=550950021]' --prop fill=FF0000

Fallback to Positional for Slides

The slide itself has no stable ID; use positional index and accept that reordering will invalidate the reference:

officecli set deck.pptx '/slide[3]' --prop transition=fade

Watch Mode with Stable Selection

In a live watch session, capture selected shapes using stable paths to ensure subsequent operations target the correct elements:

PATHS=$(officecli get deck.pptx selected --json | jq -r '.data.Results[].path')
for p in $PATHS; do
  officecli set deck.pptx "$p" --prop fill=00FF00
done

The selected command always returns stable @id= paths, guaranteeing that the subsequent set affects the same visual element even if the document is edited in the meantime.

Summary

  • Stable ID paths (@attr=value) use persistent OOXML attributes like @id, @paraId, and @name that survive document edits.
  • Positional indices ([n]) rely on ordinal position and break when siblings are inserted or removed.
  • Word paragraphs use @paraId and @sdtId (see WordHandler.Add.Misc.cs), while PowerPoint shapes use @id and @name (see PowerPointHandler.Helpers.ShapeId.cs).
  • Use stable paths for multi-step workflows, automation scripts, and any operation where the document might change between commands.
  • Reserve positional indices for elements that truly lack stable identifiers, such as Excel cells or unsaved table rows.

Frequently Asked Questions

What makes a stable ID path different from a positional index?

A stable ID path uses an attribute embedded in the OOXML specification—such as @paraId in Word or @id in PowerPoint—that remains constant even when the document structure changes. A positional index like /body/p[4] simply counts elements from the top, so inserting a new paragraph at position 2 shifts all subsequent indices, breaking saved references.

Can I rely on stable IDs across different OfficeCLI versions?

Yes. Stable IDs derive from the underlying Office Open XML standard attributes (e.g., @paraId, @id), not from OfficeCLI-specific logic. As long as the document format remains consistent, the stable paths generated by SchemaHelpRenderer.cs will remain valid across CLI versions.

Why do some Excel elements only show positional indices?

Many Excel elements, particularly individual cells and rows, lack native persistent identifiers in the OOXML schema. While charts and drawings expose @id, standard cell references like /Sheet1/B2 are inherently positional based on row and column coordinates. In these cases, OfficeCLI falls back to positional syntax because no stable attribute exists on the element.

How do I convert a positional path to a stable ID path?

Run a get or query command against the parent collection to retrieve the stable identifier. For example, officecli get doc.docx '/body/p' returns both the positional and stable forms. Extract the @paraId= or @id= path from the JSON output and use that in subsequent set or mark commands to ensure durability across edits.

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 →