| name | officecli |
| description | Create, analyze, proofread, and modify Office documents (.docx, .xlsx, .pptx) using the officecli CLI tool. First read the complete builtin://officecli/SKILL.md to get skillToken; this SKILL.md read does not require skillToken. Calls without the correct skillToken will fail and must be retried. |
officecli
AI-friendly CLI for .docx, .xlsx, .pptx. Single binary, no dependencies, no Office installation needed.
IMPORTANT: How to Use This Tool
This is a dedicated built-in tool named officecli. You MUST follow these rules:
-
Do NOT use shell_command to run officecli commands. The gateway will block any attempt to run officecli through shell_command. Always use this officecli tool directly.
-
Executing commands (skillToken required):
- Every
exec value MUST start with the officecli prefix.
- You MUST include the
skillToken returned from reading this skill.
- Example:
officecli({"exec": "officecli create report.docx", "skillToken": "<token>"})
-
The exec field always requires the officecli command prefix. Do NOT omit it.
- Correct:
"exec": "officecli help"
- Correct:
"exec": "officecli create file.docx"
- Wrong:
"exec": "help"
- Wrong:
"exec": "create file.docx"
-
Command snippets in this skill are CLI syntax. When this skill shows officecli ... in a code block, execute that command by putting the full line in the built-in tool's exec field with the required skillToken.
Prerequisites
The officecli binary must be installed and available in PATH before this tool can be enabled.
Use officecli --version to verify. If not installed, enable it via the admin UI or install manually
from https://github.com/iOfficeAI/OfficeCLI/releases.
Strategy
L1 (read) -> L2 (DOM edit) -> L3 (raw XML). Always prefer higher layers. Add --json for structured output.
Before document work, check Specialized Skills near the bottom of this file.
Generic decks, pitch decks, Morph decks, academic papers, financial models, and
dashboards need their own officecli load_skill <name> rules before creating
or heavily editing the artifact. The base skill explains commands; the
specialized skill explains document quality.
Help System (IMPORTANT)
When unsure about property names, value formats, or command syntax, ALWAYS run help instead of guessing. One help query beats guess-fail-retry loops.
officecli help is equivalent to officecli --help, and officecli <cmd> --help is equivalent to officecli help <cmd>.
Gateway execution examples:
officecli({"exec": "officecli help", "skillToken": "<token>"})
officecli({"exec": "officecli help docx", "skillToken": "<token>"})
officecli({"exec": "officecli help docx paragraph", "skillToken": "<token>"})
officecli({"exec": "officecli help docx set paragraph", "skillToken": "<token>"})
officecli({"exec": "officecli help pptx shape --json", "skillToken": "<token>"})
CLI syntax examples:
officecli help
officecli help docx
officecli help docx paragraph
officecli help docx set paragraph
officecli help docx paragraph --json
Format aliases: word -> docx, excel -> xlsx, ppt/powerpoint -> pptx. Verbs: add, set, get, query, remove.
Resident Mode
Every command auto-starts a resident on first access when available, with a short idle timeout, so file-lock conflicts are automatically avoided. Explicit open/close is still recommended for longer sessions:
officecli({"exec": "officecli open report.pptx", "skillToken": "<token>"})
officecli({"exec": "officecli set report.pptx ...", "skillToken": "<token>"})
officecli({"exec": "officecli close report.pptx", "skillToken": "<token>"})
officecli open report.docx
officecli set report.docx ...
officecli close report.docx
Opt out of auto-start with OFFICECLI_NO_AUTO_RESIDENT=1.
Quick Start
PPT:
officecli({"exec": "officecli create slides.pptx", "skillToken": "<token>"})
officecli({"exec": "officecli add slides.pptx / --type slide --prop title=\"Q4 Report\" --prop background=1A1A2E", "skillToken": "<token>"})
officecli({"exec": "officecli add slides.pptx '/slide[1]' --type shape --prop text=\"Revenue grew 25%\" --prop x=2cm --prop y=5cm --prop font=Arial --prop size=24 --prop color=FFFFFF", "skillToken": "<token>"})
Word:
officecli({"exec": "officecli create report.docx", "skillToken": "<token>"})
officecli({"exec": "officecli add report.docx /body --type paragraph --prop text=\"Executive Summary\" --prop style=Heading1", "skillToken": "<token>"})
officecli({"exec": "officecli add report.docx /body --type paragraph --prop text=\"Revenue increased by 25% year-over-year.\"", "skillToken": "<token>"})
Excel:
officecli({"exec": "officecli create data.xlsx", "skillToken": "<token>"})
officecli({"exec": "officecli set data.xlsx /Sheet1/A1 --prop value=\"Name\" --prop bold=true", "skillToken": "<token>"})
officecli({"exec": "officecli set data.xlsx /Sheet1/A2 --prop value=\"Alice\"", "skillToken": "<token>"})
PowerPoint Quality Workflow
For .pptx, first load exactly one matching specialized skill:
officecli({"exec": "officecli load_skill pptx", "skillToken": "<token>"})
Then follow the rules it prints. At minimum:
- Set explicit geometry on every non-placeholder shape:
x, y, w/width, h/height.
- Set explicit typography on text shapes: font, size, color, and alignment where supported.
- Use one idea per slide. Split dense bullet slides instead of shrinking text.
- Every content slide should include a non-text visual: shape system, picture, chart, icon, table, or diagram.
- Add speaker notes on content slides with
--type notes when generating a real deck.
- Verify after generation with
view outline, view stats --json, view issues --json, and a rendered preview (view html or view screenshot).
- Treat text overflow and off-slide geometry as blocking issues. Fix them before declaring the file done.
Common failure mode: creating only a title and one default text box per slide
produces a valid PowerPoint file, but not a designed presentation. Default text
boxes start at x=0cm y=0cm and 10cm x 5cm; they usually look unplaced and
can overlap or overflow.
REQUIRED: WPS Compatibility Fix
OfficeCLI writes <Application>OfficeCLI/x.x.x</Application> into docProps/app.xml when creating files. WPS Office does not recognize this application identifier and will refuse to open the file ("format not recognized").
After every officecli create, you MUST run this cleanup step:
officecli raw-set <file> docProps/app.xml --xpath "//ap:Application" --action delete
Example full flow:
officecli({"exec": "officecli create report.docx", "skillToken": "<token>"})
officecli({"exec": "officecli raw-set report.docx docProps/app.xml --xpath \"//ap:Application\" --action delete", "skillToken": "<token>"})
This applies to all formats (.docx, .xlsx, .pptx). Do NOT skip this step.
L1: Create, Read & Inspect
officecli create <file>
officecli view <file> <mode>
officecli get <file> <path> --depth N
officecli query <file> <selector>
officecli validate <file>
view modes
| Mode | Description | Useful flags |
|---|
outline | Document structure | |
stats | Statistics (pages, words, shapes) | |
issues | Formatting/content/structure problems | --type format|content|structure, --limit N |
text | Plain text extraction | --start N --end N, --max-lines N |
annotated | Text with formatting annotations | |
html | Static HTML snapshot, same renderer as watch, no server needed | --browser, --page N (docx), --start N --end N (pptx) |
screenshot / svg / pdf / forms | PNG via headless browser / SVG (pptx slide) / PDF via exporter plugin / form-fields JSON via format-handler plugin | -o, --screenshot-width/-height, pptx --grid N |
Use view html for one-shot snapshots (CI artifacts, archival, diffing); use watch when you need live refresh or browser-side click-to-select.
Useful render checks:
officecli view <file> html -o preview.html
officecli view <file> screenshot -o slide.png
officecli view <file> issues --json
get
Any XML path via element localName. Use --depth N to expand children. Add --json for structured output. Default text output is grep-friendly: path (type) "text" key=val key=val ...
officecli get report.docx '/body/p[3]' --depth 2 --json
officecli get slides.pptx '/slide[1]' --depth 1
officecli get data.xlsx '/Sheet1/B2' --json
Stable ID Addressing
Elements with stable IDs return @attr=value paths instead of positional indices. Prefer these in multi-step workflows because positional indices shift on insert/delete, while stable IDs do not.
/slide[1]/shape[@id=550950021] # PPT shape
/slide[1]/table[@id=1388430425]/tr[1]/tc[2] # PPT table
/body/p[@paraId=1A2B3C4D] # Word paragraph
/comments/comment[@commentId=1] # Word comment
PPT also accepts @name= (for example shape[@name=Title 1]), with morph !! prefix awareness. Elements without stable IDs (slide, run, tr/tc, row) fall back to positional indices.
query
CSS-like selectors: [attr=value], [attr!=value], [attr~=text], [attr>=value], [attr<=value], :contains("text"), :empty, :has(formula), :no-alt.
officecli query report.docx 'paragraph[style=Normal] > run[font!=Arial]'
officecli query slides.pptx 'shape[fill=FF0000]'
Watch & Interactive Selection
Live HTML preview that auto-refreshes on every file change. Browsers can click, shift-click, or box-drag to select shapes; the CLI can read the current browser selection and act on it.
officecli watch <file> [--port N]
officecli unwatch <file>
officecli goto <file> <path>
Open the printed http://localhost:N URL. Click to select; shift/cmd/ctrl-click to multi-select; drag from empty space to box-select. PPT/Word use blue outline; Excel uses native-style green selection (double-click cell to edit inline; drag a chart to reposition).
get <file> selected - read what the user clicked
officecli get <file> selected [--json]
Returns DocumentNodes for whatever is currently selected. Empty result if nothing selected. Exit code is nonzero if no watch is running.
PATHS=$(officecli get deck.pptx selected --json | jq -r '.data.Results[].path')
for p in $PATHS; do officecli set deck.pptx "$p" --prop fill=FF0000; done
Key properties
- Selection survives file edits. Paths use stable
@id= form.
- All connected browsers share one selection. Last-write-wins.
- Same-file single-watch. A given file can have only one watch process at a time.
- Group shapes select as a whole. Drilling into individual children of a group is not supported in v1.
- Coverage:
.pptx shapes/pictures/tables/charts/connectors/groups; .docx top-level paragraphs and tables. Inherited layout/master decorations and Word nested elements (table cells, run-level) are not addressable. .xlsx does not emit data-path; mark/selection on xlsx always resolve stale=true.
Marks - edit proposals waiting for review
Use mark when changes need human review BEFORE they hit the file. Marks live in the watch process only; a separate set pipeline applies accepted ones. For one-shot changes use set directly; for permanent file annotations use add --type comment (Word native).
officecli mark <file> <path> [--prop find=... color=... note=... tofix=... regex=true] [--json]
officecli unmark <file> [--path <p> | --all] [--json]
officecli get-marks <file> [--json]
Props: find (literal or regex when regex=true; raw form find='r"[abc]"'), color (hex / rgb(...) / 22 named whitelist), note, tofix (drives apply pipeline). Path must be data-path format from watch HTML; see subskills for full pipeline.
L2: DOM Operations
set - modify properties
officecli set <file> <path> --prop key=value [--prop ...]
Any XML attribute is settable via element path (found via get --depth N), even attributes not currently present. Without find=, set applies format to the entire element.
Value formats:
| Type | Format | Examples |
|---|
| Colors | Hex (with/without #), named, RGB, theme | FF0000, #FF0000, red, rgb(255,0,0), accent1..accent6 |
| Spacing | Unit-qualified | 12pt, 0.5cm, 1.5x, 150% |
| Dimensions | EMU or suffixed | 914400, 2.54cm, 1in, 72pt, 96px |
Dotted-attr aliases are accepted on shape/run/paragraph/table/row/cell/section/styles, for example --prop font.color=red --prop font.bold=true --prop font.size=14pt. Run officecli help <fmt> <element> for the full list.
find - format or replace matched text
Use find= with set to target specific text for formatting or replacement. Format props are separate --prop flags; do not nest them.
officecli set doc.docx '/body/p[1]' --prop find=weather --prop bold=true --prop color=red
officecli set doc.docx '/body/p[1]' --prop 'find=\d+%' --prop regex=true --prop color=red
officecli set doc.docx / --prop find=draft --prop replace=final
officecli set slides.pptx / --prop find=draft --prop replace=final
Path controls search scope: / = whole document, /body/p[1] or /slide[N]/shape[M] = specific element, /header[1] / /footer[1] = headers/footers.
Notes:
- Case-sensitive by default. Case-insensitive:
--prop 'find=(?i)error' --prop regex=true.
- Matches work across run boundaries.
- No match = silent success.
--json includes "matched": N.
- Excel: only
find + replace is supported; find + format props are not.
add - add elements or clone
officecli add <file> <parent> --type <type> [--prop ...]
officecli add <file> <parent> --type <type> --after <path> [--prop ...]
officecli add <file> <parent> --type <type> --before <path> [--prop ...]
officecli add <file> <parent> --type <type> --index N [--prop ...]
officecli add <file> <parent> --from <path>
--after, --before, and --index are mutually exclusive. No position flag means append to end.
Element types (with aliases):
| Format | Types |
|---|
| pptx | slide (incl. hidden), shape (font.latin/ea/cs, direction=rtl, underline.color, effective.X+effective.X.src; arrow alias for rightArrow; slideMaster/slideLayout typed add/set/remove), picture (SVG, brightness/contrast/glow/shadow, rotation, link, tooltip), chart (direction=rtl, pieOfPie, barOfPie, axisLine/gridline per-attr setters, animation+chartBuild=byCategory|bySeries, line dropLines/hiLowLines/upDownBars, anchor=x,y,w,h shorthand), table (cell direction=rtl, fill/background, built-in PowerPoint style catalogue, /col[C] get + swap/copyFrom, row/col Move/CopyFrom), row (tr), connector (from/to accept @name=, startshape/endshape SetByPath), group (link, tooltip, deep walk by get/query/add/remove), video/audio (loop, autoStart alias), equation, notes (direction=rtl, lang), comment (legacy + modern p188 threaded round-trip), animation (15 emphasis + 16 exit presets, multi-effect chains, motion-path presets, repeat/restart/autoReverse, chart animations), transition (12 p15 presets + morph/p14), paragraph (para), run, zoom, ole (preview=, full dump round-trip via add-part+raw-set), placeholder (phType=...), model3d (rotation=ax,ay,az; full dump round-trip), smartart (dump round-trip via add-part). |
| docx | paragraph (direction/font.latin/ea/cs, bold.cs/italic.cs/size.cs, lang.latin/ea/cs, wordWrap, framePr.*, tabs shorthand), run (lang slots, direction, underline.color, position half-pts, revision.type=ins|del|format|moveFrom|moveTo + revision.action=accept|reject with .author/.date, /revision[@author=X] selector for filtered accept/reject), table (direction=rtl, hMerge, virtual column ops: add/remove/move/copyfrom on /body/tbl[N]/col), row (tr), cell (td), image, header/footer (direction), section (pageNumFmt full enum, direction=rtl, rtlGutter, pgBorders=box), bookmark, comment, footnote, endnote, formfield, sdt, chart, equation, field (28 types), hyperlink, style (direction, indents, pbdr, lineSpacing on Add/Set), toc, watermark, break, ole, num/abstractNum/lvl, tab, textbox/shape (full Add+Get; geometry, fill, line, wrap, alt, anchor). docDefaults.rtl, autoHyphenation, get / exposes locale + /comments /footnotes /endnotes. create --minimal for raw OOXML scaffolding. |
| xlsx | sheet (visible/hidden/veryHidden, print margins, printTitleRows/Cols, rightToLeft sheetView, cascade-aware rename), row (c{N}= cell-content shorthand; add accepts --from /Sheet/col[L]; formula-ref rewrite on insert), col (formula-ref rewrite, named-range follow on move), cell (type=richtext+runs, merge=range/sweep, direction=rtl, phonetic; --shift left|up on remove, shift=right|down on add; formula auto-detect; OFFSET/INDIRECT in calc), chart (per-axis RTL/title, anchor=x,y,w,h, pareto), image (SVG), comment (direction=rtl), table (listobject), namedrange (definedname, volatile, [@name=X]; formula-body inlined at parse), pivottable (cache CoW + cross-pivot sharing, labelFilter, topN, fillDownLabels, calculatedField), sparkline, validation, autofilter, shape, textbox, CF (databar/colorscale/iconset/formulacf/cellIs/topN/aboveAverage), ole, csv. Query supports merge/mergedrange. Workbook: password. Shape selector enumerates leaves inside grpSp. |
Pivot tables (xlsx)
officecli add data.xlsx /Sheet1 --type pivottable \
--prop source="Sheet1!A1:E100" --prop rows=Region,Category \
--prop cols=Year --prop values="Sales:sum,Qty:count" \
--prop grandTotals=rows --prop subtotals=off --prop sort=asc
Key props: rows, cols, values (Field:func[:showDataAs]), filters, source, position, layout (compact/outline/tabular), repeatLabels, blankRows, aggregate, showDataAs (percent_of_total/row/col, running_total), grandTotals, subtotals, sort. Aggregators: sum, count, average, max, min, product, stdDev, stdDevp, var, varp, countNums. Date columns auto-group. Run officecli help xlsx pivottable for full schema.
Document-level properties (all formats)
officecli set doc.docx / --prop docDefaults.font=Arial --prop docDefaults.fontSize=11pt
officecli set doc.docx / --prop protection=forms --prop evenAndOddHeaders=true
officecli set data.xlsx / --prop calc.mode=manual --prop calc.refMode=r1c1
officecli set slides.pptx / --prop defaultFont=Arial --prop show.loop=true --prop print.what=handouts
Run officecli help <format> / for all document-level properties (docDefaults, docGrid, CJK spacing, calc, print, show, theme, extended).
Sort (xlsx)
officecli set data.xlsx /Sheet1 --prop sort="C desc" --prop sortHeader=true
officecli set data.xlsx '/Sheet1/A1:D100' --prop sort="A asc" --prop sortHeader=true
Format: COL DIR[, COL DIR ...]. Rejects ranges with merged cells or formulas. Sidecar metadata (hyperlinks, comments, conditional formatting, drawings) follows rows automatically.
Text-anchored insert (--after find:X / --before find:X)
Locate an insertion point by text match within a paragraph. Inline types (run, picture, hyperlink) insert within the paragraph; block types (table, paragraph) auto-split it. PPT only supports inline.
officecli add doc.docx '/body/p[1]' --type run --after find:weather --prop text=" (sunny)"
officecli add doc.docx '/body/p[1]' --type table --after "find:First sentence." --prop rows=2 --prop cols=2
Clone
officecli add <file> / --from '/slide[1]' copies with all cross-part relationships.
move, swap, remove
officecli move <file> <path> [--to <parent>] [--index N] [--after <path>] [--before <path>]
officecli swap <file> <path1> <path2>
officecli remove <file> '/body/p[4]'
When using --after or --before, --to can be omitted because the target container is inferred from the anchor.
batch - multiple operations in one save cycle
Continues on error by default and returns exit 1 if any item fails. Use --stop-on-error to abort on the first failure. --force is the docx-protection bypass.
officecli dump <file> [<path>] emits a replayable batch JSON for round-trip. .docx has full coverage; .pptx covers text/tables/pictures/charts/notes/theme plus OLE/3D/video/audio/SmartArt/morph/p15 transitions via raw-set passthrough. Path defaults to / (whole document); pass a subtree path (/body, /body/p[N], /body/tbl[N], /theme, /settings, /numbering, /styles) to scope the dump. officecli refresh <file.docx> recalculates TOC page numbers / PAGE / cross-references after replay. officecli plugins list extends support to .doc, .hwpx, and .pdf export.
echo '[
{"command":"set","path":"/Sheet1/A1","props":{"value":"Name","bold":"true"}},
{"command":"set","path":"/Sheet1/B1","props":{"value":"Score","bold":"true"}}
]' | officecli batch data.xlsx --json
officecli batch data.xlsx --commands '[{"op":"set","path":"/Sheet1/A1","props":{"value":"Done"}}]' --json
officecli batch data.xlsx --input updates.json --force --json
Supports: add, set, get, query, remove, move, swap, view, raw, raw-set, validate. Fields: command (or op), path, parent, type, from, to, index, after, before, props, selector, mode, depth, part, xpath, action, xml.
L3: Raw XML
Use when L2 cannot express what you need. No xmlns declarations needed; prefixes are auto-registered.
officecli raw <file> <part>
officecli raw-set <file> <part> --xpath "..." --action replace --xml '<w:p>...</w:p>'
officecli add-part <file> <parent>
raw-set actions: append, prepend, insertbefore, insertafter, replace, remove, delete, setattr. The project WPS cleanup flow uses delete for docProps/app.xml; when in doubt, run officecli help <format> raw for available parts and action names.
Common Pitfalls
| Pitfall | Correct Approach |
|---|
Using shell_command for officecli | Use this officecli tool directly |
Omitting officecli prefix in exec | Always write "exec": "officecli ..." |
--name "foo" | Use --prop name="foo"; all attributes go through --prop |
Unquoted [N] paths in zsh/bash | Always quote: '/slide[1]' or "/slide[1]" |
PPT shape[1] for content | shape[1] is typically the title placeholder. Use shape[2]+ for content shapes |
/shape[myname] | Name indexing not supported. Use numeric index or @name= (PPT only) |
| Guessing property names | Run officecli help <format> <element> to see exact names |
| Modifying an open file | Close the file in Office/WPS first |
\n in shell strings | Use \\n for newlines in --prop text="..."; use batch JSON for real newline characters |
$ in shell text | --prop text="$15M" strips $15. Use single quotes: --prop text='$15M', or heredoc batch |
| Bullet-only PPT slides | Load pptx skill and create explicit layout, visuals, typography, and notes |
| Default PPT text box placement | Set x, y, width, height, font size, and colors explicitly |
Specialized Skills
officecli load_skill <name> prints extra rules for a specific artifact type. Load one specialized skill per artifact before creating or substantially editing it.
Loading rule:
- Pick the most specific match in "When to use"; if none fits, load the format default (
word / pptx / excel).
- Scenes already contain the format default's rules. Load one skill per artifact; never stack multiple specialized skills for the same artifact.
- Loaded rules persist across turns; do not re-load each reply.
- Two distinct artifacts require two separate loads.
Word (.docx)
| Name | When to use |
|---|
word | Reports, letters, memos, proposals, generic documents |
academic-paper | Journal / conference / thesis: APA / Chicago / IEEE / MLA citations, equations, SEQ + PAGEREF cross-refs, multi-column journal layout, bibliography. NOT for business reports or letters (route those to word) |
PowerPoint (.pptx)
| Name | When to use |
|---|
pptx | Generic decks: board reviews, sales decks, all-hands, product launches |
pitch-deck | Fundraising only: seed / Series A-C / SAFE / convertible / strategic raise. NOT for sales / product / board decks (route those to pptx) |
morph-ppt | Cinematic Morph-animated presentations. NOT for static decks (route those to pptx) |
morph-ppt-3d | 3D Morph: GLB models, camera moves, depth. NOT for 2D-only Morph (route those to morph-ppt) |
Excel (.xlsx)
| Name | When to use |
|---|
excel | Generic workbooks, formulas, pivots, trackers |
financial-model | Financial models, scenarios, projections. NOT for general data analysis (route those to excel) |
data-dashboard | CSV/tabular data -> KPI / analytics / executive dashboards with charts and sparklines. NOT for raw data tracking (route those to excel) |
Example: a fundraising deck task -> officecli load_skill pitch-deck -> use the printed rules.
Notes
- Paths are 1-based (XPath convention):
'/body/p[3]' = third paragraph.
--index is 0-based (array convention): --index 0 = first position.
- Excel exception: for
add --type row and add --type col, --index N is 1-based (matches OOXML RowIndex / column letter index). --index 5 inserts at row 5 / column 5.
- After modifications, verify with
validate and/or view issues.
- When unsure, run
officecli help <format> <element> instead of guessing.
Companion Tools
The officecli skill only owns .docx / .xlsx / .pptx documents. Any
secondary files (Markdown notes, JSON dumps from officecli view --json, unit
fixtures, extracted plain text) must go through the other bundled skills:
- Persist or rewrite secondary files with
multi_edit_file so the gateway has
a reviewable diff and path allowlist enforcement; do not use
shell_command redirection, Set-Content, or here-documents for that.
- Inspect the current contents of those files with
read_file so output is
line-numbered and size-capped; do not use shell_command with cat,
Get-Content, type, sed, head, or tail.
- Never wrap an
officecli invocation inside shell_command. The gateway
rejects that path. Call this officecli tool directly.