A3S Office CLI reference
Office is moving to an A3S-owned Rust engine for Word, Spreadsheet, and
Presentation documents. The native engine now includes bounded package
admission, byte-preserving XML, content types, a safe relationship graph,
stable selectors, semantic get, query, text, outline, and stats
reads, bounded issues reports, safe blank-document creation, and
loss-preserving text assignment plus scoped literal/regex replacement for Word,
Spreadsheet, and Presentation. Matches may span rich-text runs without
flattening their formatting. Typed rich-text mutation covers bold, italic,
none/single/double underline, baseline/superscript/subscript, font family,
exact centipoint font size, RGB text color, and horizontal alignment. Word and
Spreadsheet also support an explicit single-strikethrough boolean;
Presentation rejects that property with a typed error instead of silently
dropping it. Word and Presentation additionally share a portable 17-color
highlight palette, display-only text case, and conservative BCP-47 primary
language tags. Word alone supports explicit double strikethrough; Spreadsheet
and Presentation reject it through format-specific typed errors.
Word and Presentation table-cell reads expose one-based row and column,
positive rowSpan and columnSpan, and mergeAnchor. A covered physical cell
has mergeAnchor=false plus the stable semantic mergeAnchorPath of its
logical anchor. Invalid, overlapping, orphaned, or out-of-bounds merge topology
fails closed instead of being projected as a rectangular table. These fields
describe document structure only; they are not page-layout geometry.
Word and Presentation apply character properties to run paths and alignment to
paragraph paths; Spreadsheet applies the same contract to cells or bounded A1
ranges,
creating and deduplicating OOXML font and cell-style records when necessary. It
also exposes a separate typed Spreadsheet cell-presentation contract for
number formats, solid RGB fill or explicit fill removal, cardinal and diagonal
borders, vertical alignment, wrap text, rotation, indentation, shrink-to-fit,
and reading order. These properties apply to a cell or bounded rectangular
range, compose atomically with content and text formatting, preserve unknown
style data, and deduplicate number-format, fill, border, and cell-style
records. Spreadsheet merged cells use a separate typed contract: rectangular
A1 ranges are normalized, exact repeated merges are idempotent, and unmerge
requires one exact existing range. Geometric overlaps and ListObject table
intersections fail closed. Semantic reads expose stable mergeCell nodes and
anchor metadata without materializing every blank covered cell. A third typed
Spreadsheet contract owns data-validation rules for list, whole-number,
decimal, date, time, text-length, and custom-formula constraints. One rule may
target multiple disjoint normalized A1 ranges and carries typed comparison
operators, prompt/error messages, alert style, blank handling, and
list-dropdown state. Inline lists are quoted safely, ISO dates and clock times
are normalized to Spreadsheet serial values, and overlapping rule ranges fail
atomically. Semantic reads expose stable /Sheet/dataValidation[N] nodes,
annotate observed and virtual blank cells, and project inert metadata into
HTML/SVG. Native add/set/remove, batch, exact replay, CLI, Rust, and standard
MCP use the same closed contract while retaining strict/transitional
SpreadsheetML and unknown attributes. It stores validation formulas but does
not evaluate them.
A separate typed Spreadsheet conditional-format contract owns comparison and
formula rules; text, rank, average, duplicate/unique, blank/error, and time
predicates; data bars; two- or three-color scales; and standard three-, four-,
or five-icon sets. Classic rules apply a differential solid fill, font color,
and bold state. Visual rules use typed thresholds, colors, and display flags.
One rule can cover multiple disjoint A1 areas and can stop later rule
evaluation. Semantic reads expose stable /Sheet/cf[N] nodes and selectors
such as conditionalFormatting[type=dataBar]. Rust, versioned batch, CLI,
standard MCP, exact replay, and the Office Skill share the closed value. The
writer deduplicates differential formats, preserves strict or transitional
SpreadsheetML plus unknown attributes, and fails closed when unsupported child
or collection content would be lost. This milestone does not evaluate rule
formulas, reproduce Excel rendering, or cover x14-only data-bar axes/colors,
table/chart/pivot conditional formatting, or complete Spreadsheet parity.
Native Spreadsheet defined names use a separate typed contract for
workbook-global and worksheet-local scopes. Stable selectors include both name
and scope, while compatibility selectors remain available when the name is
unambiguous. worksheet:workbook disambiguates a local scope when the
worksheet itself is literally named workbook. The writer validates Excel identifier and reference limits,
qualifies a bare A1 range only for a local scope, enforces case-insensitive
uniqueness by (name, scope), rejects ListObject table-name collisions, and
protects _xlnm.* and Slicer_* names owned by other Office features.
Semantic get/query, ordinary typed remove, batch, exact replay, CLI, Rust, and
standard MCP share the same value. Strict/transitional SpreadsheetML and
unknown defined-name attributes are retained; unknown collection or child
content fails closed when it cannot be preserved. This contract owns
defined-name lifecycle, not external-link authoring or complete Spreadsheet
parity; supported names participate when an explicit native cell-formula
recalculation references them.
Native Spreadsheet AutoFilters use a closed typed contract shared by worksheet
filters and ListObject tables. One value owns a normalized rectangular A1
range plus at most one criterion for each zero-based range column. Supported
criteria are exact value sets with optional blanks; equality, text, and ordered
comparisons; between/not-between; blanks/non-blanks; top/bottom count or
percentage; and closed dynamic average, relative-date, month, and quarter
families. Worksheet lifecycle uses stable /Sheet/autofilter and
/Sheet/autofilter/filterColumn[N] paths; table filters appear below
/Sheet/table[N]/autofilter. Rust, versioned batch, CLI, standard MCP, exact
replay, and the Office Skill use the same value. The strict/transitional writer
sorts columns deterministically, escapes wildcard literals, rejects duplicate
or out-of-range columns, protects table/merge geometry, and fails closed for
imported date-group items, color/icon filters, embedded sort state,
extensions, comments, or unknown attributes. Physical row sorting is owned by
the separate typed sort contract below; an imported AutoFilter with unsupported
embedded sort state remains readable but non-mutable.
Native Spreadsheet sorting physically reorders a worksheet range through one
stable, ordered multi-key contract. A worksheet path auto-detects its used
range; callers may instead supply /Sheet/A1:D100. Keys are absolute A:XFD
columns inside that range, the first selected row stays fixed only when
header=true, text comparison is case-insensitive by default, numbers sort
before text, blanks always remain last, and records equal on every key retain
their source order. Partial-column sorts move only selected cells; cells outside
the range and destination row properties stay fixed. The editor persists a
worksheet SpreadsheetML sortState, exposed as /Sheet/sort and ordered
/Sheet/sort/key[N] nodes. Removing /Sheet/sort deletes metadata only and
never reverses the physical row order.
Rust, versioned batch/replay, CLI, standard MCP, and the Office Skill share the same sort value. Sorts accept 1–64 unique keys and at most 100,000 selected cells. Exact mutable ListObject or worksheet-AutoFilter ranges, or their exact data ranges, are supported. Table totals rows, formulas anywhere in the workbook, intersecting merges, pivots, unknown existing sort state, and drawing anchors that cannot follow one record losslessly fail closed. Hyperlinks, comments/VML notes, data validation, conditional formatting, protected ranges, ignored errors, and supported drawing anchors move with their records; chart caches are cleared and the worksheet used dimension is recomputed after the physical change.
Native Spreadsheet delimited import accepts bounded UTF-8 CSV or TSV from a regular file or stdin and writes it into an existing worksheet from an explicit A1 start cell. The parser supports a leading BOM, CRLF, quoted delimiters, embedded newlines, and doubled quotes; malformed quote state fails atomically. One request is limited to 8 MiB and a 100,000-cell rectangular extent. Explicit empty fields clear existing target cells, while missing trailing fields in a ragged row leave those cells unchanged.
Typed inference stores formulas, finite numbers, booleans, ISO dates/times, and
text without a Python, Node.js, OfficeCLI, or spreadsheet-application runtime.
Dates honor the workbook's 1900/1904 system and receive a native date number
format. Inferred formulas pass the same bounded native syntax parser as direct
cell writes; malformed expressions fail the complete import. Import does not
implicitly calculate formulas; run the explicit native recalculation command
or mutation when fresh cached results are required. Header mode atomically
installs the worksheet AutoFilter and a canonical frozen pane below the header.
Frozen pane state is readable at /Sheet/freeze, is set through the typed
batch/Rust/MCP contract, and is removed through the ordinary typed remove
mutation. Strict/transitional SpreadsheetML and unknown view content are
preserved; unsupported pane content reports nativeMutable=false and fails
closed on mutation.
Native Spreadsheet formula calculation builds a deterministic bounded
dependency graph across worksheets, ranges, spills, and workbook- or
worksheet-scoped names. The closed built-in registry implements
SUM, AVERAGE, MIN, MAX, COUNT, COUNTA, ABS, SQRT, POWER,
MOD, ROUND, IF, IFERROR, AND, OR, NOT, CONCAT,
CONCATENATE, ROW, COLUMN, SEQUENCE, TRANSPOSE, PI, and NA.
Operators and typed blank, number, text, boolean, and Spreadsheet error values
participate in scalar or rectangular array calculation.
The read-only Rust calculation API leaves package bytes unchanged. The editor,
versioned batch, replay, CLI office native recalculate, and standard MCP
recalculate-spreadsheet-formulas mutation atomically write typed OOXML
caches, canonical array anchors, spill children, and calculated-workbook
metadata. Spill children are read-only; edit or remove their formula anchor.
Exact replay accepts canonical formula storage and natively cached array
anchors. It fails closed for physical distinctions typed mutations cannot
reproduce, including explicit t="normal" storage and uncached or malformed
array anchors.
ListObject structured references resolve table names or display names.
Sales[Qty] and Sales[[Qty]:[Price]] select data rows; #All, #Data,
#Headers, and #Totals select structural rows; and Sales[@Qty],
Sales[[#This Row],[Qty]], or table-local [@Qty] select the current data row.
Table-local forms require the formula cell to be inside the inferred table.
Missing tables, columns, or requested structural rows, disjoint columns,
non-canonical forms, cycles, unsupported or qualified functions, and
external-workbook reads fail with stable typed errors and roll back the whole
batch. The engine never fetches an external workbook or falls back to a shell
or script runtime. One formula is limited to 8,192 characters, depth
128 (including nested named-reference resolution), and 8,192 AST nodes; one
reference value to 100,000 areas; one graph to 100,000 formulas, 1,000,000
edges, and 1,000,000 formula-cell reference visits; one materialized array or
function call to 100,000 cells; and one text result to 1 MiB.
One calculation pass is also limited to 100,000 cumulative spill children and
200,000 OOXML cell writes, plus 8 MiB of cumulative text-result bytes.
Native Spreadsheet tables use a separate closed ListObject contract. Add and
set own the workbook-wide name, optional distinct displayName, final
rectangular A1 range, one exact column identity per range column, header/totals
row state, typed filter criteria, built-in light/medium/dark style identity,
and first/last-column plus row/column-stripe flags; ordinary typed remove
owns deletion. When a header is enabled, its names are stamped into the first
row and the table-owned AutoFilter range excludes an enabled totals row. The
set lifecycle keeps common structured references consistent: changed table
names/display names and position-mapped column identities are rewritten across
cell formulas, defined names, conditional formats, data validations, charts,
and table formulas without touching string literals or external-workbook
references. Table-local references are rewritten only when their ListObject
context is provable. Unsafe local-reference geometry changes fail with
use.office.spreadsheet_table_formula_rewrite_unsupported, and remove
fails with use.office.spreadsheet_table_referenced while a live structured
reference still targets the table. All checks and rewrites share the table
mutation's atomic rollback boundary.
The editor rejects
Excel-identifier and A1/R1C1 name errors,
case-insensitive table/defined-name collisions, duplicate columns, missing data
rows, table/merge/worksheet-AutoFilter overlap, and unsafe relationship graphs.
Semantic reads expose stable /Sheet/table[N] and child column paths. Rust,
versioned batch, CLI, standard MCP, exact replay, and the Office Skill share the
same value while strict/transitional SpreadsheetML and supported unknown root
or style data are retained. Imported calculated columns, totals functions,
date-group/color/icon filters, unsupported embedded sort state, custom styles,
query tables, and external data remain explicit gaps and fail closed when a
lossless typed mutation cannot be proved. Exact mutable table and data ranges
can still be physically sorted through the separate sort contract.
The engine also creates, updates, reads,
queries, and removes typed hyperlinks. Word owns
external HTTP/HTTPS/mailto links and internal bookmark targets in body,
header, and footer paragraphs, with display text and tooltips; Spreadsheet
owns external links and internal workbook locations on cells or bounded
rectangular ranges, with display text and tooltips, auto-creating a missing
single linked cell; Presentation owns external shape-wide links and internal
jumps to existing slides, with optional tooltips. External targets reject
embedded credentials, active or relative schemes, and malformed URIs; semantic rendering
keeps every relationship inert and never fetches it. The same typed engine
creates, updates, reads, queries, and removes classic Office comments. Word
comments anchor to a main-document paragraph or run and expose stable
/comments/comment[N] paths. Spreadsheet comments are classic cell notes with
an author table, VML note drawing, and /SheetName/A1/comment paths, including
notes on otherwise blank cells. Presentation comments use legacy per-slide
comment and shared-author parts, optional EMU coordinates, and
/slide[N]/comment[M] paths. Removing an owning Word node, Spreadsheet cell or
range, or Presentation slide also removes its owned comment resources. This is
plain legacy-comment scope, not complete modern threaded-comment parity:
replies, resolved state, writable dates, rich bodies, Word header/footer
anchors, Spreadsheet threaded comments, and modern PowerPoint threaded
comments remain outside the typed contract. The engine can safely inspect
existing XML parts and replace non-OPC-metadata XML parts while preserving the
root QName and validating the final document. Known chart, header, and footer
part carriers can be created together with their content type and owner
relationship. The typed mutation layer also adds and removes Word paragraphs
and basic table/row/cell structures,
creates real Presentation DrawingML tables, appends grid-conformant rows,
fills underfull rows, edits cell text, and exposes table columns as stable
virtual paths. Columns can be inserted, resized in EMUs, removed, moved,
copied, or swapped while the grid, every row, and the graphic-frame width stay
in sync. Tables and structurally safe rows/cells can also be removed. It
upserts typed Spreadsheet text, number, boolean, and formula cells, removes
cells and bounded cell ranges, structurally inserts or deletes rows and columns,
and adds, removes, renames, reorders, or copies worksheets. It also exposes
typed move, copy, and swap mutations with zero-based or path-relative
placement. Word supports same-parent paragraph, table, row, cell, and run
moves and swaps plus identity-free paragraph, table, row, and run copies.
Spreadsheet supports worksheet arrangement and dense plain-row arrangement with
row/cell renumbering. Presentation supports slide arrangement, same-slide
top-level object movement/swaps, layout-only slide copies, and relationship-free
plain-shape copies with fresh non-visual identities. Cross-parent ownership
migration, formula-bearing or reference-rich row arrangement, identity-bearing
Word copies, table-cell copies, and relationship-owning Presentation copies fail
closed before save. Worksheet copy
clones the owned OPC relationship subgraph while preserving shared workbook
resources; removal garbage-collects only unshared descendants. Structural
Spreadsheet edits rewrite affected A1 formulas, defined names, worksheet
metadata, tables, comments, VML notes, drawing anchors, and chart references;
unsupported pivot and 3D-reference cases fail closed before save. Presentation
slides, text shapes, and basic tables also support native add/remove. PNG, JPEG,
and GIF can be embedded as real Word inline pictures, Spreadsheet one-cell
drawing anchors, and Presentation slide pictures; semantic reads and
reference-aware removal use the same cross-format Picture contract. Saves are
atomic and reject a changed source revision instead of overwriting another
writer.
Cross-format template merge replaces {{key}} text in Word document and
auxiliary text parts, Spreadsheet string cells, and Presentation slides and
notes while preserving split-run formatting and reporting unresolved keys.
The native document engine does not require Microsoft Office, LibreOffice,
OfficeCLI, Python, Node.js, or .NET. LibreOffice may be used only by optional
CI interoperability checks and is never part of document execution. Optional
PNG screenshot output requires the browser feature and a ready A3S Browser
provider because it captures the native semantic HTML through the existing
Browser contract.
The explicit office native CLI exposes in-process blank creation, reads,
typed add/set/remove/move/copy/swap, scoped literal/regex replacement,
rich-text, exact Spreadsheet merged-cell, stable Spreadsheet physical sorting
with persisted sort state, bounded CSV/TSV import with typed inference and
header filter/freeze behavior, explicit Spreadsheet formula recalculation,
worksheet/table AutoFilter, data-validation, conditional-format, defined-name,
ListObject table, hyperlink, and legacy-comment operations, constrained raw
XML access,
known typed part carriers, exact replay artifacts for a constrained canonical
subset, visible PNG/JPEG/GIF pictures, and atomic mutation batches, plus
dependency-free template merge and semantic rendering today. HTML and SVG are
available for Word, Spreadsheet, and Presentation; bounded annotated and issue
views are available for all three formats; and Browser-injected PNG screenshots
are available for all three formats. An authenticated, loopback-only foreground
watch provides full saved-revision refresh for all three formats without a
resident pipe or mutation endpoint. mcp serve office-native exposes the same
editor, annotated/issue analysis, and screenshot composition through typed
standard MCP tools and bounded in-memory sessions.
The packaged a3s-office Skill exposes the same product boundaries to
agents without starting OfficeCLI. Discover its metadata with
office skills list, read only its SKILL.md with
office skills get a3s-office, append its four format/MCP references with
--full, or locate the installed directory with office skills path. The
capability snapshot binds the Skill path and lowercase SHA-256 so a resident
host can verify the bytes before loading them. Resident Code hosts receive the
native engine as canonical route use/office targeting office-native; a ready
OfficeCLI installation is projected separately as use/office-compat targeting
office-compat.
Other 0.1.x commands and the default mcp serve office target still use a
compatibility backend pinned to OfficeCLI 1.0.136. This is a migration
boundary, not a native-promotion claim. The default routes will be promoted
only after mutation, fidelity, rendering, compatibility, and cross-application
interoperability gates pass. The first real compatibility CLI command prepares
that pinned provider when first-use policy allows. In Code, the native Office
worker requests office_install_compat through parent confirmation only when
the requested operation is outside the native surface.
The native MCP process exposes 12 document tools plus the confirmed
office_install_compat compatibility installer: office_validate,
office_create, office_open, office_list, office_get, office_query,
office_view, office_raw_xml, office_apply_batch,
office_merge_template, office_save, and office_close. It accepts no shell
command string and defines no A3S RPC dialect; stdio carries only standard MCP.
Each process owns at most 64 sessions. Mutation batches are atomic in memory,
limited to 10,000 mutations and 8 MiB of JSON, and remain unsaved until
office_save. Results are limited to 8 MiB, raw XML responses to 1 MiB, and
queries to at most 1,000 returned nodes. office_close rejects dirty sessions
unless the caller saves or explicitly sets discard=true. office_view
accepts html and svg for all three formats in addition to text, annotated,
outline, and statistics. The typed annotated view flattens stable semantic
paths, node types, text, styles, and observed formatting; its limit is 1
through 1,000 and defaults to 200. The issues view accepts an optional typed
issueType and a limit from 1 through 1,000, defaulting to 200. It also
accepts screenshot for all three formats; that mode requires a no-clobber
local output ending in .png and accepts an optional timeoutMs from 1
through 120,000.
Native issue analysis is conservative and read-only. It currently reports
missing picture alternative text, missing or incompatible internal part
relationships, formulas without cached results, formulas that reference a
missing worksheet, cached or explicit formula errors, and low contrast between
explicit RGB run text and its own shape fill. Reports include stable category,
subtype, severity, path, context, and suggestion fields; filtering happens
before the bounded result window, and count, returned, and truncated
remain explicit. It does not infer text overflow, object overlap, theme or
inherited colors, or Microsoft Office layout behavior. A clean report is not a
full fidelity or interoperability certification.
Native render artifacts are deterministic, standalone, and network-free. They
contain no timestamp or source path, escape document text and attributes, carry
stable semantic paths as data-path, and embed only validated internal
PNG/JPEG/GIF parts as data: URLs. HTML declares a restrictive CSP and uses a
sparse observed-cell representation instead of expanding large Spreadsheet
gaps. Each render is bounded to 16 MiB while it is composed. CLI --output
publishes through an atomic no-clobber file operation; inline MCP output remains
subject to the stricter 8 MiB structured-result limit. These are semantic
previews, not a Microsoft Office layout-fidelity claim. Screenshot mode stages
the same deterministic HTML privately, opens its file:// URL through the
existing PageRenderer, and validates one regular PNG plus its size and
SHA-256 receipt before atomic no-clobber publication. It defaults to a 30-second
deadline, caps the deadline at 120 seconds, and caps the PNG at 64 MiB. It does
not fetch external relationships or consult OfficeCLI.
The optional Browser facade can also capture one exact Rust unit locator. It
stages only that unit's HTML, rejects locator conflicts before Browser work,
requires the final URL to remain the private staged file:// URL, and binds
the PNG receipt to the selected unit and source-HTML SHA-256. The underlying
Browser contract does not yet attest viewport, engine/version, fonts, DPI,
locale, and page geometry as one deterministic render profile, so this capture
is still semantic-preview evidence rather than a Parser-ready layout raster.
The Rust API additionally exposes bounded natural-unit inventory and rendering.
DOCX remains one document-scoped unit until real pagination exists; XLSX units
are exact one-based worksheet index/name pairs; PPTX units are exact one-based
slides. Inventory rejects duplicate identities; render_unit emits only the
selected worksheet or slide and rejects a wrong kind, position, name/index
pair, or output bound.
These unit renders preserve semantic paths for downstream evidence but remain
semantic previews rather than page-layout evidence.
The native Rust API separately exposes the object-safe, Send + Sync
NativeOfficeLayoutRenderer boundary and strict source/unit/profile receipts.
NativeOfficePptxImageLayoutRenderer is the first layout-authoritative
implementation. It accepts only a slide containing one opaque PNG that covers
the complete declared slide surface with no crop, rotation, flip, effects, or
sibling visual objects. The PNG aspect ratio must exactly match the slide, so
the implementation returns the original embedded bytes without reflow or
resampling. It rehashes the source before and after work, validates the full
locator/ordinal/path identity, stages output atomically with no overwrite,
rehashes the published pixels, and records the engine binary, physical surface,
DPI, viewport, locale, timezone, empty font manifest, renderer configuration,
and explicit source-layout authority in a deterministic profile. DOCX, XLSX,
and richer PPTX slides return use.office.layout_unsupported.
With the Rust pdfium feature, NativeOfficePdfiumLayoutRenderer provides a
second browser-neutral implementation for PDF. Construction requires an
explicit PDFium Chromium/7881 dynamic-library path and a SHA-256 host font
manifest; the provider copies and rehashes that binary in private staging and
never downloads it. source_revision admits a regular source under an explicit
byte/deadline bound. inventory_pages returns every page or fails instead of
truncating, using strict one-based /page[N] identities and integer media/crop
boxes in millipoints. Each page records effective rotation, physical micrometers,
and DPI-derived pixels. inspect_page remains the convenience path that
inventories and selects in one call. Large-document consumers can instead call
inspect_inventoried_page for constant-scope selection from one previously
validated complete inventory. render still reads and verifies the immutable
source, renders the actual selected page, and rejects any profile drift before
publishing exactly one PNG with the same timeout, byte-limit, no-clobber,
rehash, and receipt checks. Corrupt, password-protected, zero-page, over-limit,
missing-page, unsupported, and mutated inputs have stable typed failures. Only
one content-addressed PDFium binary may be bound per process. This optional core
feature does not depend on a3s-use-browser or chromiumoxide.
The semantic HTML/SVG/Browser screenshot path cannot construct either source-layout receipt.
office native watch <file> renders the same bounded all-format HTML, binds
only 127.0.0.1, selects an ephemeral port by default, and prints a URL with a
fresh 256-bit capability token. Every page, status response, and standard SSE
stream requires that token or its HttpOnly same-site cookie and validates the
exact loopback Host. The wrapper runs its own fixed script while the document
preview stays in a sandboxed iframe under the renderer's script-free CSP.
Atomic saves from another office native process trigger a full refresh.
Transient missing or invalid revisions leave the last valid preview visible,
publish a typed error state, and retry until recovery. The server is read-only:
it has no mutation/RPC endpoint, never opens an external relationship, and
does not observe unsaved office-native MCP sessions until office_save.
--timeout-ms bounds automated runs; otherwise Ctrl+C stops the foreground
server. Interactive editing, selection/mark overlays, and layout goldens remain
open.
Native batch input is an ordinary JSON document, not an RPC protocol. The current schema is:
The whole batch rolls back if any mutation fails. Inputs are limited to 8 MiB
and 10,000 mutations. The version 1 mutation set is replace-text, set-text,
set-text-format, set-cell-format, add-data-validation,
set-data-validation, add-conditional-format, set-conditional-format,
add-named-range, set-named-range, add-spreadsheet-table,
set-spreadsheet-table, add-spreadsheet-auto-filter,
set-spreadsheet-auto-filter, sort-spreadsheet-range,
import-spreadsheet-delimited, set-spreadsheet-frozen-pane, merge-cells,
unmerge-cells, recalculate-spreadsheet-formulas,
set-hyperlink, set-comment, set-table-column-width,
set-cell-value, add-paragraph,
add-table, add-table-row, add-table-column, add-table-cell,
add-comment, add-worksheet, insert-rows, delete-rows, insert-columns,
delete-columns, rename-worksheet, move-worksheet, copy-worksheet,
move, copy, swap, replace-xml-part, add-part, add-slide, add-shape,
add-image, and remove.
A data-validation mutation uses the same atomic document and standard MCP
payload. Remove a rule with the ordinary typed remove mutation:
Each rule accepts 1–1,024 disjoint ranges and each worksheet accepts at most
65,534 rules. Formulas are limited to 255 characters; prompt/error titles to
32, prompts to 255, and error messages to 225. List and custom rules reject
operators and formula2; comparison rules require an operator and require
formula2 only for between or notBetween. Invalid or overlapping input
rolls back the complete in-memory batch.
A conditional-format mutation uses one complete closed rule value. CLI set
can merge omitted options, while batch and standard MCP set replace the complete
value:
Closed classic predicates plus data bars, two/three-color scales, and standard 3/4/5-icon sets are supported. Threshold, range, priority, shared-range, and loss-preservation failures roll back the whole batch. Rule formulas are stored, not evaluated, and the semantic preview is not Excel rendering evidence.
A named-range mutation uses one complete scoped value. Deletion reuses the
ordinary typed remove mutation:
Use set-named-range with a stable path and a complete namedRange value.
Names are limited to 255 characters, refs to 8,192, comments to 255, and a
workbook to 65,536 defined names. Workbook-scoped bare A1 refs, leading =,
cross-workbook refs without external-link parts, reserved Office-managed names,
duplicate (name, scope) identities, and ListObject table-name collisions fail
atomically. Use the explicit scope worksheet:workbook for a local name on a
worksheet literally named workbook.
A worksheet AutoFilter mutation uses one complete range-and-columns value.
Table filters use the same column objects:
Use set-spreadsheet-auto-filter with /Sheet/autofilter and a complete
filter; ordinary typed remove deletes it. CLI set preserves an omitted
range, replaces all criteria when one or more --filter objects are supplied,
and uses --clear-filters for an explicit empty criterion list. Column offsets
are zero-based and unique inside the range. Imported date-group/color/icon
filters, embedded sort state, extensions, and unknown content are readable but
nativeMutable=false. Use the separate physical sort mutation for supported
ranges; it does not flatten an unsupported imported AutoFilter.
A Spreadsheet physical sort mutation owns an ordered, stable multi-key value:
The path may instead be /Sheet1 to auto-detect the used range. Keys are
unique absolute A:XFD columns within that range; 1–64 keys and at most
100,000 selected cells are accepted. Numbers precede text, blanks remain last
in both directions, and rows equal across every key retain source order. A
partial-column range moves only its cells, preserving cells outside the range
and destination row properties. Exact mutable table and worksheet-AutoFilter
ranges, or their exact data ranges, are supported. Formulas, totals rows,
intersecting merges, pivots, unknown sort state, and non-lossless drawing
movement fail the whole batch before save.
Read persisted metadata at /Sheet1/sort and ordered
/Sheet1/sort/key[N]. An ordinary remove of /Sheet1/sort removes only the
SpreadsheetML sort state; it does not restore the prior physical row order.
Supported record-bound hyperlinks, comments/VML notes, validations,
conditional formatting, protected ranges, ignored errors, and drawing anchors
follow the row permutation. The worksheet used dimension is recomputed and
chart caches are cleared. Exact replay emits the same
sort-spreadsheet-range mutation.
A Spreadsheet delimited import embeds bounded content in the typed batch or MCP request; filesystem paths remain a CLI-only concern:
format is csv or tsv. Header mode replaces the worksheet AutoFilter range
and its canonical frozen pane in the same transaction, so inspect those nodes
before importing into a populated sheet. Set a pane independently with
set-spreadsheet-frozen-pane and remove it through /Sheet/freeze:
A Spreadsheet table mutation uses one complete ListObject value. CLI set
preserves omitted fields; batch, Rust, and standard MCP replacements supply the
complete table:
Use set-spreadsheet-table with a stable path and complete table; use
ordinary typed remove for deletion. Styles are none, light 1–21, medium
1–28, or dark 1–11. none requires all style flags to be false. The final range
must leave at least one data row after enabled header and totals rows and must
not intersect another table, a merge, or a worksheet-level AutoFilter. Table
filters require an enabled header; --clear-filters clears their criteria
without removing the table-owned AutoFilter range.
An image mutation uses the same versioned batch boundary:
The native engine validates decoded format signatures and structure, bounds
bytes and pixel dimensions, infers a missing axis from the source aspect ratio,
and inserts a visible OOXML picture object. Word uses an inline DrawingML run,
Spreadsheet uses a one-cell drawing anchor, and Presentation uses a slide
picture. Removal deletes the XML object and an unused image relationship, then
deletes the media part and content-type declaration only when no relationship
anywhere in the package still targets it. Direct CLI image inputs must be
regular, non-symlink files no larger than 64 MiB. Normal CLI output never
contains image data; createdImage and batch createdImages receipts contain
only paths, owner/media parts, relationship ID, format, and final dimensions.
OOXML SVG image embedding is not implemented yet; the all-format SVG semantic preview is an output format and does not alter the package. Correct OOXML SVG image support requires an SVG part plus a raster fallback rather than treating SVG as an ordinary bitmap.
Image replacement, crop, rotation, effects, compression controls, floating Word wrapping, Spreadsheet two-cell sizing, and rich layout rendering also remain outside this bounded add/read/remove milestone.
office native dump produces a stricter versioned batch artifact, also as
ordinary JSON:
The first dump scope is the complete document (/). It accepts only content
that current typed mutations can reproduce byte-for-byte at the OOXML part-map
level: plain Word paragraphs and rectangular tables, Spreadsheet worksheets,
typed defined names, typed cells, typed worksheet/table AutoFilters, typed
ListObject tables, stable physical row order with supported typed sort state,
canonical frozen panes and import date styles, merged ranges, typed
data-validation rules, canonical typed conditional-format rules, and natively
recalculable formula caches and canonical cached dynamic-array spills;
plus Presentation slides with plain one-run text shapes and canonical basic
tables.
Headers, notes,
media, custom or non-canonical table styling, rich text, non-canonical package resources,
and every other lossy case fail with
use.office.dump_unsupported; nothing is silently flattened or omitted.
Replay requires the exact A3S blank template identified by baseSha256.
batch checks that precondition before mutation and checks resultSha256
afterward. A failed result check restores the original in-memory package before
any save. Dump files are limited to 8 MiB and 10,000 mutations, refuse to
overwrite an existing path, and use a 1 MiB inline-output limit. This is a
portable Office batch artifact, not RPC and not a universal action envelope.
office native merge opens a .docx, .xlsx, or .pptx template, performs a
single-pass replacement, validates the resulting OPC/semantic document, and
atomically writes a separate output. The template and output may not identify
the same file. The output is no-clobber by default; --force is the only way to
replace an existing destination, and it never authorizes modifying the template
in place.
Merge data must be a JSON object. Literal top-level keys take precedence over
flattened nested paths: {"user.name":"literal","user":{"name":"nested"}}
resolves {{user.name}} to literal. Nested objects use dot paths and arrays
use bracket paths such as {{items[0].name}}. Replacement is deliberately
single pass, so a value containing {{another.key}} remains literal and is
reported as unresolved rather than recursively substituted. Results include the
replacement count, sorted used keys, sorted unresolved placeholders, and sorted
changed OOXML parts.
Word merge covers the main document, headers, footers, footnotes, endnotes, and
comments. Presentation merge covers slides and notes. Spreadsheet merge covers
inline strings, direct t="str" values, and referenced shared rich strings;
shared-string replacements are counted per referencing cell and phonetic runs
are left untouched. A resolved placeholder in a numeric, boolean, error, or
otherwise unsupported cell fails closed instead of coercing the cell type.
Data files are limited to 8 MiB and must be regular, non-symlink files. Flattened data is additionally bounded by entry count, nesting depth, key length, and total bytes. XML-forbidden replacement characters fail the whole in-memory transaction before any output is created. This native path does not invoke OfficeCLI, Microsoft Office, LibreOffice, Python, Node.js, or .NET.
General text replacement is separate from template merge. replace-text uses
an explicit semantic path and either case-sensitive, non-overlapping literal
matching or a linear-time Rust regular expression. Word / covers the main
document plus headers, footers, footnotes, endnotes, and comments; narrower
body, header/footer, paragraph, run, table, cell, hyperlink, and comment paths
stay within their source part. Spreadsheet accepts /, a worksheet, or one
cell/rectangular range and edits only string cells. A scoped shared-string edit
clones the rich shared-string item and redirects selected cells when other
cells still reference the original. Presentation accepts /,
slide/object/text paths, and /slide[N]/notes; slide scopes do not implicitly
include notes. Phonetic Spreadsheet text is never changed.
One operation accepts at most 64 KiB of find expression, 1 MiB of replacement
text, 100,000 semantic matches, 64 MiB of expanded replacement text, and a
100,000-cell Spreadsheet scope. Regex matches must consume text. Results report
matchCount, changed, and sorted changedParts; zero matches are a
successful unchanged result. Batch results add these receipts under
textReplacements. All replacements are single pass, preserve split-run
ownership by assigning new text to the first matched run, retain unknown XML,
support strict and transitional OOXML, and participate in normal batch rollback
and post-mutation validation.
Raw replacement is also available inside the same atomic batch:
Only existing XML parts may be replaced. [Content_Types].xml, root and
part-level relationship files, binary parts, DTDs, external entities, non-UTF-8
input, and replacement roots with a different local name or namespace are
rejected. Direct raw-set input is limited to 8 MiB. Inline raw output is
limited to 1 MiB; use its --output option to export larger original part bytes
without modifying the Office package. Raw export refuses to overwrite an
existing destination. Every replacement runs through the normal semantic and
OPC post-mutation validation, and any failure rolls back the whole batch.
Typed part creation is also batchable:
The batch result keeps the existing ordered paths ledger, adds swaps
receipts containing the post-mutation first and second paths, and adds
createdParts receipts containing part, ownerPart, relationshipId, and
type. Text replacement receipts are reported separately under
textReplacements so a successful zero-match operation remains distinguishable
from a content change. Word supports chart, header, and footer carriers at /;
Spreadsheet supports chart carriers under a worksheet; Presentation supports
chart carriers under a slide. A carrier is a valid blank XML part with content
type and owner relationship. It is not visible in document layout until a typed
operation or explicit XML replacement references the returned relationship ID
from the owner XML.
Typed formatting is batchable through the same public mutation contract:
fontSizeCentipoints is an integer count of 1/100 point; the CLI accepts the
equivalent point value through --font-size. underline accepts none,
single, or double, and script accepts baseline, superscript, or
subscript. strikethrough is supported by Word and Spreadsheet;
Presentation rejects it before mutation. textCase, highlight, and
language apply to Word and Presentation runs. doubleStrikethrough applies
only to Word. The portable highlight palette is none, the six bright colors,
black/white, and the dark or light gray/color variants exposed by the typed
schema. An empty format object, invalid BCP-47 shape, unknown properties,
invalid RGB components, and unsupported target/property combinations fail the
whole batch. Spreadsheet style records are cloned and deduplicated without
replacing unrelated style children or attributes.
Spreadsheet cell presentation uses its own typed mutation rather than adding
non-text properties to set-text-format:
numberFormat accepts an explicit Excel format code or general, number,
currency, accounting, percent, scientific, text, date, time, or
datetime. Format codes are limited to 255 characters, four sections, and
balanced quotes/brackets. Fill is either none or one solid 24-bit RGB color.
Each border side is an explicit none or line value. Lines accept thin,
medium, thick, double, dashed, dotted, dashDot, dashDotDot,
hair, mediumDashed, mediumDashDot, mediumDashDotDot, or
slantDashDot, plus an optional 24-bit RGB color. The shared diagonal line is
controlled independently from diagonalUp and diagonalDown. Vertical
alignment accepts top, center, bottom, justify, or
distributed; rotation accepts 0–180 or 255 for stacked text; indentation is
0–255; and reading order is context, left-to-right, or right-to-left.
Unknown fields, empty format objects, invalid values, and non-Spreadsheet
targets fail the whole batch. Native semantic HTML/SVG previews expose the
observed values as inert data-* attributes; they do not claim Excel layout
fidelity.
Spreadsheet merged cells are batchable through two closed mutations:
Use unmerge-cells with the exact same path to remove the merge. Range order
and case are normalized. An exact repeated merge and an absent exact unmerge
are unchanged successes. A partial overlap, a range intersecting a Spreadsheet
table, or any unmerge range that intersects but does not exactly equal an
existing merge fails the complete batch. The latter error reports
validRanges; callers must unmerge each exact range rather than request a
destructive sweep. Strict and
transitional OOXML are retained, unknown mergeCells data is preserved, and
removing the final merge fails closed if deleting its container would discard
unknown attributes or children. Semantic cell reads expose merge and
mergeAnchor; range reads expose merge=true|false; and mergeCell queries
return stable nodes. HTML/SVG carry the same facts only as inert attributes.
Hyperlinks use the same typed batch contract and remain inert data:
Use { "kind": "internal", "location": "section_1" } for a Word
bookmark, Sheet1!B2 for a Spreadsheet location, or /slide[2] for a
Presentation slide jump. Word accepts body, header, and footer paragraph paths
when adding and the returned hyperlink path when updating. Spreadsheet accepts
one cell or a bounded rectangular range; only a missing single cell is created,
and a range link does not rewrite cell contents. Presentation accepts a shape
or its hyperlink path and does not accept separate display text. Removing a
hyperlink or its owning paragraph, cell/range, shape, or slide garbage-collects
only an unused hyperlink or slide relationship. Strict and transitional OOXML
namespaces are preserved.
Legacy comments use their own typed batch variants rather than generic properties:
Use set-comment with a partial update object and the stable returned path.
Word accepts author, initials, and plain text on main-document comments;
Spreadsheet accepts author and plain text for classic cell notes; Presentation
also accepts a complete position. Removing a comment uses the ordinary typed
remove mutation. Unknown OOXML attributes and extension nodes survive these
updates, and strict/transitional relationship and root dialects are retained.
Modern threaded comments and replies, resolved state, writable comment dates,
rich comment bodies, Word header/footer anchors, and Spreadsheet threaded
comments are intentionally not represented yet.
Typed Spreadsheet content values use an explicit nested type, for example:
Formula mutation removes one optional leading =, parses the bounded body into
a source-spanned typed AST, stores the original normalized OOXML formula text,
and marks the workbook for recalculation. It does not implicitly calculate the
workbook. The parser covers scalar and error literals, Excel operator
precedence, function calls and omitted arguments, parentheses and array
constants, names and structured references, A1 cell/row/column references with
quoted, 3D, or external qualifiers, and range/intersection/union operators.
Invalid syntax returns use.office.spreadsheet_formula_invalid with zero-based
UTF-8 byte and character offsets before any package mutation. Structural edits
continue to rewrite supported A1 references without evaluating formulas.
NativeOfficeDocument::formula_dependency_graph and
calculate_spreadsheet_formulas provide read-only graph and calculation
results. NativeOfficeEditor::recalculate_spreadsheet_formulas, the
recalculate-spreadsheet-formulas batch/MCP mutation, exact replay, and the
CLI command above atomically persist supported cached values and spills. Excel
formula breadth beyond the closed native registry, disjoint or non-canonical
structured-reference forms, qualified functions, external-workbook
calculation, and full cross-application conformance remain rich-Spreadsheet
delivery gates.
The native package, semantic, and editor APIs are available directly to Rust callers:
Managed compatibility installation accepts only approved HTTPS release
origins, bounds the download, verifies the publisher SHA-256, stages outside
the active version, and activates atomically. Compatibility execution sets
OFFICECLI_SKIP_UPDATE=1 so upgrades remain explicit A3S operations.
The native engine does not copy OfficeCLI's private resident protocol. The
explicit office-native target now provides typed in-process sessions over its
own standard MCP surface. Until the default-route promotion, a lost
compatibility response can return
use.office.outcome_unknown; callers must not retry it automatically.
See Native Office Engine for the complete requirements, compatibility scope, safety invariants, delivery gates, and migration plan.