Deckuse is a local-first, schema-driven Office document automation engine for coding agents. It turns document editing into an explicit, reviewable workflow: open a versioned workspace, inspect and target its structure, apply JSON commands, validate the result, and export a new document.
The engine is built around format adapters. PPTX and DOCX are implemented. XLSX, Keynote, and Numbers adapters return FORMAT_NOT_IMPLEMENTED today, so agents fail clearly instead of silently producing unsafe edits.
Deckuse is a local-first, schema-driven Office document automation engine for coding agents. It opens a document into a versioned workspace, lets an agent inspect and target its structure with semantic addresses (slide:1/shape:2), applies explicit mutations, validates the result, and exports a new document.
This repository is the community edition (edition=community). See docs/edition.md. Shared source here is the source of truth, published as @deckflow/deckuse; the commercial edition is a private thin overlay (deckuse-commercial) that registers a PptxEditionExtension for gated writes and may add proprietary packages.
PPTX and DOCX are implemented (protocol 2.0). XLSX, Keynote, and Numbers adapters deliberately return FORMAT_NOT_IMPLEMENTED; they are not supported editing targets yet.
Install the canonical package, then read the bundled Skill from the CLI you will actually run.
npm install --cache ./.npm-cache @deckflow/deckuse ./node_modules/.bin/deckuse skill-path --json
Read the absolute file in data.nextAction.path. For an existing installation,
run the same command with that installed binary. Managed jobs can use the
bootstrap below with --handoff-json. The unscoped package is deprecated.
From a reviewed checkout, run the managed bootstrap with an exact published version, an unused job directory, and an existing cache root approved by the host. The script prints the verified local CLI path.
sh scripts/managed-bootstrap.sh 1.9.3 ./deckuse-job /path/to/approved-cache
The script allocates an empty cache per job and stops with npm's failure code if lookup or installation fails. If the host cannot provide an approved cache or install location, stop and report that prerequisite. Use the returned binary for the example below.
Run this in a fresh directory with a writable npm cache. The installed binary and example come from the same package version.
npm install --cache ./.npm-cache @deckflow/deckuse set -e deckuse_cli=./node_modules/.bin/deckuse "$deckuse_cli" agent-context --format pptx --scenario create --json "$deckuse_cli" new ./example-workspace --blank --json "$deckuse_cli" apply --workspace ./example-workspace --input ./node_modules/@deckflow/deckuse/skills/deckuse/examples/create-blank-pptx.json --request-id create-1 --expect-revision 1 --json "$deckuse_cli" validate --workspace ./example-workspace --json "$deckuse_cli" export ./example.pptx --workspace ./example-workspace --json
The example contains CLI apply operations. For first drafts, data.applyContract gives units, common enum values and directly usable operations. Request --include-schema when you need the protocol contract. Export and structural validation work without a browser. For optional preview, use render --preflight --json to check converter and browser setup.
The Deckuse skill guides your agent through editing presentations and Word documents. The CLI performs the document operations.
Run this from the project where you use your agent:
npx skills add deckflow/deckuse
Select your agent and installation scope when prompted. Use project scope for the current project or user scope to make the skill available across projects. For manual installation, copy the full skills/deckuse/ directory into your agent's skills directory. See the agent directory reference.
If you installed the skill first, run deckuse --version to check whether the CLI is available. If it is missing, follow Installation. If you already installed the CLI, use the command above when you want your agent to use Deckuse. For a version-pinned setup, install the skill from the release tag that matches your npm package version.
Once both are available, ask your agent for a concrete task, such as “Use Deckuse to update the figures in report.pptx and export a revised copy.”
Deckuse lets an agent modify an existing presentation without recreating it from scratch. When you have no source file, deckuse new bootstraps a workspace from the bundled blank template. Its workflow is deliberately structural rather than visual:
existing.pptx → init ─┐
├→ list / get → set / add → validate → export
blank template → new ─┘
Every successful write automatically commits a Git revision, updates operations.jsonl, rebuilds package.pptx, and refreshes .deckuse/index.json. Use undo to revert writes and history to inspect the operation log.
It preserves untouched XML and unknown package parts where possible. It is not a full PowerPoint rendering or layout engine and cannot reliably judge whether a slide is visually attractive or whether a layout is visually correct. Use monitor for live HTML preview and render to screenshot one slide to PNG for agent visual review. Semantic diff / branch remain deferred past Phase 1a.
Deckuse is designed for document changes that need to be precise, repeatable, and auditable:
- Recurring content updates — refresh dates, metrics, names, pricing, and disclaimers without rebuilding a presentation.
- Customer and market variants — create controlled versions with explicit selectors and reviewable operations.
- Content governance — query sensitive or outdated content, inspect every match, and validate before export.
- Agent-driven automation — use structured JSON, revision checks, dry runs, atomic batches, and operation logs in larger workflows.
Requires Node.js 20.19.0 or later.
npm install -g @deckflow/deckuse
This installs the deckuse CLI globally.
# Create a workspace from an existing presentation (revision starts at 1). deckuse init input.pptx ./workspace --json # Or start from the bundled blank 16:9 template (no input.pptx needed). deckuse new ./workspace --json # Inventory and read live properties with provenance. deckuse status --workspace ./workspace --json deckuse list slides --workspace ./workspace --json deckuse list shapes --workspace ./workspace --slide 1 --json deckuse get slide:1/shape:2 --workspace ./workspace --resolve both --json # Mutate with semantic targets (one write = one revision). deckuse set text slide:1/shape:2 --workspace ./workspace --value 'Hello' --json deckuse set slide:1/shape:2 --workspace ./workspace --font.size 42 --fill.color '#0A2930' --json deckuse add shape --workspace ./workspace --slide 1 --type text --name Title --x 0 --y 0 --width 914400 --height 457200 --json # Validate, history, undo, export. deckuse validate --workspace ./workspace --json deckuse history --workspace ./workspace --json deckuse undo --workspace ./workspace --steps 1 --json deckuse export ./out.pptx --workspace ./workspace --json # Default export rebuilds package.pptx from source/ (use --from-package to copy the snapshot only). # Live HTML preview; conversion starts when a browser subscribes. deckuse monitor --workspace ./workspace --port 4173 # Background daemon: start / status (lists all when --workspace omitted) / stop [--all] deckuse monitor start --workspace ./workspace --port 0 deckuse monitor status --json deckuse monitor stop --workspace ./workspace # Screenshot one slide to PNG for visual review (requires Chrome / Chromium / Edge). deckuse render --page 1 --workspace ./workspace --json
Global options include --workspace, --json, --dry-run, --expect-revision, and --reason. Run deckuse --help or deckuse <command> --help for the full CLI contract.
Workspace layout:
workspace/
source/ # unpacked OPC package; writes modify this directory
package.pptx # live Office snapshot rebuilt from source (not in Git)
.deckuse/ # manifest, index, operations.jsonl, ignored monitor output
.git/ # workspace version history
.gitignore # ignores package.* and other generated files
apply accepts a transaction file ({ "operations": [...] }), a single JSON mutation, a JSON array, or JSON Lines. One invocation can apply many write commands; multiple commands run as one atomic batch. Use --input - (the default) to read from standard input. Legacy ElementRef mutations remain supported. When invoked without a subcommand, the CLI accepts one complete protocol 2.0 JSON command on standard input.
Command results use a JSON envelope (ok, command, revision, data / error). Exit status 0 means success, 1 means that a command failed, and 2 means CLI usage or parsing failure.
Prefer search text / search shape and list for Phase 1a inventory. query remains available for back-compat and accepts either a selector string or a structured selector in a command. Space-separated terms are combined with AND.
| Syntax | Meaning |
|---|---|
* or all |
Match every indexed element. |
kind=textbox |
Match an element kind by case-insensitive substring. |
text=Quarter |
Match text that contains the literal value. |
text~=pattern |
Match text with a Unicode regular expression. |
hasText=true |
Match elements that contain text. |
slide=256, id=256:10, name=Title |
Filter by slide ID, element ID, or name. |
Use query results as the source of stable element references. A reference includes a document ID and an element ID or structural path; array positions are not stable identifiers.
These examples use only the current PPTX capabilities. They describe workflows that an agent can compose from Deckuse primitives, rather than claiming that Deckuse independently performs reasoning, copywriting, or visual review.
Request: “Change every FY2025 reference to FY2026, and do not change anything else.”
Use query first to review the affected elements, then perform a literal replaceText and validate before exporting.
deckuse init master.pptx ./year-update --json deckuse query ./year-update 'text=FY2025' --limit 1000 --json cat > year-update.json <<'EOF' { "type": "replaceText", "find": "FY2025", "replace": "FY2026" } EOF deckuse apply ./year-update --input year-update.json --json deckuse validate ./year-update --json
After the write completes, ./year-update/package.pptx is rebuilt automatically as the latest snapshot.
The review query limits the change to known occurrences; replaceText performs the approved bulk mutation while leaving unrelated objects intact. Without a selector, it updates the most specific indexed text nodes rather than ancestor containers that aggregate descendant text.
Request: “Replace the old product name with the new product name everywhere.”
This is the same safe review-and-replace pattern. Search the exact old name first, then use replaceText with a literal value. For variations such as punctuation or spacing, use a regular-expression replacement only after checking the query output.
{
"type": "replaceText",
"find": "Legacy Platform",
"replace": "Unified Platform"
}For a more constrained change, include a selector in the command, for example "selector": "slide=256", so only one slide is eligible.
Request: “List the slide titles and summarize what this deck covers.”
Run inspect to retrieve the indexed presentation structure, then query text-bearing objects. The calling agent can group the returned objects by slide ID, identify title-like objects by their names, positions, or text, and generate a summary from the extracted text.
deckuse init briefing.pptx ./outline --json
deckuse inspect ./outline --depth 2 --json
deckuse query ./outline 'hasText=true' --limit 10000 --jsonDeckuse supplies the structured source data. The agent, not Deckuse, is responsible for deciding which text is a title and for writing the summary.
Request: “Find old customer names, dates, product names, URLs, and required disclaimer text before this deck is sent.”
Query for each known risk and inspect the returned references. Absence checks work the same way: query for the required text and flag an empty result. An agent can produce a QA report without modifying the presentation, or prepare narrowly targeted setText / replaceText commands for approved fixes.
deckuse query ./workspace 'text=Customer A' --limit 1000 --json deckuse query ./workspace 'text~=https?://' --limit 1000 --json deckuse query ./workspace 'text=Required disclaimer' --limit 1000 --json
This is content and structural QA, not visual QA. Use render / monitor only as a human or agent review aid; Deckuse does not detect overlap or judge layout quality.
Request: “On slide 7, change the title to Enterprise Strategy; change nothing else.”
First query that slide and title text, then take the returned ref and send a setText command. The ref prevents an ambiguous global replacement.
{
"type": "setText",
"ref": {
"documentId": "./workspace",
"elementId": "256:10"
},
"text": "Enterprise Strategy"
}Element IDs are presentation-specific examples. Always use an ID returned by the current workspace rather than copying this value.
Request: “Make every approved title 28 pt and use the approved typeface.”
Use a query to identify title objects, have the agent review or filter the returned references, and apply setProperties once for each approved reference. setProperties targets one reference at a time; it does not accept a selector itself.
{
"type": "setProperties",
"ref": {
"documentId": "./workspace",
"elementId": "256:8"
},
"properties": {
"fontSize": 28,
"fontFamily": "Approved Sans",
"bold": true
}
}The same command can set fill, stroke (also border, outline, or line), textColor, italic, underline, name, and hidden. Unknown property keys fail with INVALID_COMMAND.
Request: “Move every approved title slightly lower.”
Query and select the intended title references, inspect their current geometry, and issue one setTransform command per object with explicit coordinates. This is a structural geometry operation; do not market it as automatic layout correction without visual validation.
{
"type": "setTransform",
"ref": {
"documentId": "./workspace",
"elementId": "256:8"
},
"transform": {
"x": 914400,
"y": 731520,
"width": 8229600,
"height": 685800
}
}Transform coordinates are OOXML EMUs. Preserve x, width, and height from the inspected object when only changing its vertical position.
Request: “Create a version for a prospective customer. Update the customer name and approved account-specific copy, but preserve the design.”
Create a separate workspace for each output from the approved master. Query the placeholders or existing customer text, apply only reviewed replacements, validate, and use the automatically updated package.pptx.
deckuse init approved-master.pptx ./customer-a --json deckuse query ./customer-a 'text=Customer Name' --json # Apply reviewed replacements for this customer only. deckuse apply ./customer-a --input customer-a.jsonl --json deckuse validate ./customer-a --json
Separate workspaces prevent one customer’s edits from leaking into another output. Replace only the objects the approval process allows the agent to modify.
Request: “Generate regional and enterprise variants from the approved presentation.”
Initialize a fresh workspace from the same master for every variant. Each variant receives its own command file and output path. Prefer apply with a JSON array, JSONL, or { "operations": [...] }: multiple write commands in one invocation run as one atomic batch (if one fails, none persist). The protocol batch command form remains supported.
[
{
"type": "replaceText",
"find": "Default Message",
"replace": "Regional Message"
},
{
"type": "replaceText",
"find": "Default Offer",
"replace": "Enterprise Offer"
}
]deckuse apply ./regional --input regional.json --json
This preserves a single approved source deck while making every variant reproducible from an explicit change set.
Request: “Inspect this deck, identify the requested edits, make them, and export a revised PPTX.”
Give the agent this loop: initialize a workspace, inspect or query before every targeted change, generate explicit JSON commands, apply them, validate the package, and use the rebuilt package.pptx as the export. Store the command file and command results alongside the task when auditability matters.
Deckuse gives the agent stable references, selectors, transactions, validation, and a deterministic export path. The agent provides task interpretation and decides which operations are appropriate.
- Persistent workspaces, revision-conflict detection, dry runs, atomic batches, and an operation log.
inspect,list,get,search, and back-compatquery/getText; stable references include slide ID, part URI, cNvPr ID, and ancestor path when available.setTextandreplaceText, including literal or regular-expression replacement in an optional selector scope. Without a selector,replaceTextprefers leaf text nodes over ancestor containers that aggregate descendant text. Newlines insetTextbecome separate paragraphs. CLI--valueunescapes\n/\tunless--text-raw; use--blocks/ protocolblocks(optional per-blockruns[]for intra-paragraph styling) for multi-style KPI paragraphs.addShapeaccepts inlineblocks,fill, andstrokein one command.- Geometry accepts EMU numbers or unit strings (
px@ 96 DPI,pt,cm,mm,in,%of slide).alignElements/deckuse aligndistributes or aligns targets into absolute EMU writes. Same-batch forward refs by shapenamework afteraddShapeinside oneapply. setTransformfor explicit object position, size, rotation, and flip changes.setPropertiesfor common shape and text properties, includingparagraph.align(aliasescenter/left/…),paragraph.level,bullet,filltransparency,hyperlink,wrap,anchor/valign, andcornerRadius.- Add, duplicate, remove, and rebind slides to another layout (
setSlideLayout/deckuse set slide-layout); layout refs accept index,layout:N,slide:N, display name, or basename. Rebind updates the relationship only (does not edit layout parts). Duplicated slides clone mutable notes and chart parts while layouts and media can be shared safely. - Add shapes/text boxes (optional
rolewrites ap:phplaceholder), straight connectors (line/connector), elbow/curved connectors, arrow presets, groups, pictures (from a file path or base64), tables, charts (cache-only), and embedded video/audio; duplicate or remove elements. rolemust be an OOXML placeholder type (title,body,subTitle,ctrTitle, …). Common aliases likesubtitle→subTitleare normalized; non-OOXML labels (for examplecard) are rejected so PowerPoint does not prompt to repair.- Address placeholders with
slide:N/placeholder:<type>(for exampletitle,body,subTitle,ctrTitle). Targetslide:N/shape:X/run:Kto style a single run. replacePicturereplaces a picture’s embedded media in place while retaining its element reference and layer order.- Table-cell addressing by table ID, row, and column; table row/column insert and delete via
setProperties; cellfill; speaker-note reading and text editing (notes parts are created automatically when writingslide:N/notesif missing). Tables supportheight: "auto", themesminimal/zebra, andalignColumns. - Create charts (
bar/column/line/pie/ limitedcombodual-axis) and edit chart title, series-name, cached values, data labels, series colors, and value format codes. When an embedded workbook exists, Deckuse emitsEMBEDDED_WORKBOOK_NOT_SYNCHRONIZEDrather than claiming that workbook data was updated. Advanced charts (other families, ChartEx) are preserve-only in the community edition. Communityrendermay not show custom series colors faithfully — verify chart XML or PowerPoint. - List and resolve master, layout, and theme parts; community edition rejects writes to those parts (
UNSUPPORTED_CAPABILITY). Master/layout editing is available in the commercial edition repository. monitorfor live HTML preview (monitor start|status|stop; use--port 0for an ephemeral port) andrenderfor single-slide PNG screenshots (--scalesupported; deck2html + Playwright).deckuse schemaprints command JSON Schema;deckuse measureestimates text box size heuristically.- Preservation of unknown parts and untouched nodes. ZIP files are recompressed, so fidelity is defined by uncompressed data for untouched entries rather than ZIP byte identity.
Agent quick reference: docs/agent-cookbook.md. Requires CLI >= 1.2.0.
Word uses the same workspace loop as PPTX (new / init, list, apply, validate, export, undo) but not the slide canvas. deckuse new ./workspace --format docx starts from a blank document. init report.docx unpacks an existing file. Snapshot file is package.docx.
- Addresses:
body/p:3(1-based; tables are not paragraphs),body/p:3/run:0(0-based run),para:<w14:paraId>,bookmark:<name>,body/table:1/row:2/cell:1/p:1.style:Heading1is readable; applying a style usesparagraph.styleand does not editstyles.xml. setText,replaceText(matches across runs inside one paragraph, including text split byw:proofErr),setProperties(fontSize,bold,italic,underline,textColor,fontFamily,paragraph.align,paragraph.style).addParagraph(namewrites a bookmark for same-batchbookmark:refs),addTable,insertBreak(page). CLI:deckuse add paragraph|table|break.- Slide commands (
addShape,xfrmSet,alignElements, …) returnUNSUPPORTED_CAPABILITY. - Tracked changes, fields, comments, content controls, and equations are preserved. A command that would have to rewrite them fails instead of stripping them.
- Community edition does not write style definitions, numbering definitions, theme, or settings parts.
rendersupports PPTX and DOCX through deck2html → HTML → Playwright screenshots. DOCX page numbers follow HTML pagination and may differ from Word.
{
"type": "setProperties",
"ref": { "documentId": "./workspace", "elementId": "256:8" },
"properties": {
"stroke": { "color": "0000FF", "width": 1.5 },
"fill": "none",
"textColor": "111111",
"fontSize": 18,
"fontFamily": "Approved Sans",
"bold": true
}
}stroke and fill accept a hexadecimal color string. Use none, false, or null for no stroke or fill. stroke.width is in points and defaults to 1.
The complete command schema is at schema/command.schema.json. The TypeScript package entry point is @deckflow/deckuse.
- Deckuse does not implement the full PowerPoint DrawingML surface, animation editing, SmartArt editing, OLE editing, or macro editing.
- It is not a full PowerPoint rendering or layout engine.
monitorandrenderprovide HTML/PNG review aids only; do not rely on them to assess visual quality, detect overlap, or automatically improve slide design. - Chart creation and edits update OOXML chart caches only; embedded Excel workbooks are not rewritten.
- Embedded video/audio use a generated poster frame; playback timing and advanced media options are not edited.
- Duplicated slides clone notes and chart parts and reuse layouts, themes, and media. Complex custom XML extensions are retained but not edited semantically.
setTextandreplaceTextcollapse multi-run text within each paragraph into one run while retaining the first run’s style; newlines insetTextcreate separate paragraphs.
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm buildIntegration write smoke (curated fixtures, default --batch, semantic gate):
pnpm build pnpm test:integration-writes:smoke
Large corpus scans (optional / nightly):
pnpm test:integration-writes:corpus -- /path/to/pptx-docx-dir
pnpm test:openability -- ./path/to/package.pptx # LibreOffice; or --osascript on macOSSee agent reliability for JSON error handling,
transaction recovery, nonempty-directory protection, and snapshot-consistent
render --pages 1,3-5 / render --all workflows. Use schema --list --json
to discover batchable commands, including addSlide.