| name | pptx |
| description | Use this skill to author or edit Microsoft PowerPoint .pptx files. Covers generating decks from scratch (HTML+PptxGenJS, Marp markdown-to-slides, or python-pptx), editing existing decks in place, and validating output. For READING existing .pptx files, use the harness `read` tool — do not invoke this skill. Triggers: 'build a deck', 'create slides', 'edit slide N', 'add a chart slide'. Does NOT apply to .pdf, .docx, .xlsx, or .ppt (legacy). |
PPTX authoring and editing
Reading is not in scope. To read an existing .pptx, use the harness read tool (markitdown extracts slide text). This skill is for writing and editing.
Quick reference
| Goal | Use |
|---|
| Generate a deck from scratch (HTML/CSS) | scripts/generate_pptxgenjs.js |
| Generate a deck from markdown | scripts/generate_marp.sh |
| Build slides programmatically | python-pptx directly |
| Edit a shape on an existing slide | scripts/edit_shape.py (JSON patch) |
| Add or remove a slide | unpack → edit → pack |
| QA a deck deterministically | scripts/deterministic_qa.py |
| Validate before delivery | scripts/validate.py |
Generation modalities
HTML/CSS via PptxGenJS (preferred for visual fidelity):
node scripts/generate_pptxgenjs.js deck.json out.pptx
deck.json describes slides as a JSON tree; the script invokes PptxGenJS (and html2pptx for HTML inputs) to produce a fully-editable .pptx. Best for branded decks with gradients, custom fonts, complex shapes.
Markdown via Marp:
bash scripts/generate_marp.sh deck.md out.pptx
Best for content-heavy decks (lectures, reports) where markdown is more natural than JSON.
Programmatic via python-pptx:
Best when shapes are computed (e.g., one slide per data row). Requires manual EMU positioning.
Editing existing decks
Three-step pattern, like docx:
python scripts/unpack.py input.pptx workdir/
python scripts/pack.py workdir/ output.pptx
python scripts/validate.py output.pptx
For surgical shape edits without unpacking, use edit_shape.py:
python scripts/edit_shape.py input.pptx \
--slide 2 --shape "Title 1" --op set_text --value "New title"
JSON patch ops: set_text, set_position (EMU), set_size, recolor, delete.
OOXML gotchas specific to pptx
- Use
defusedxml.minidom, NOT xml.etree.ElementTree. ElementTree corrupts presentation namespaces during round-tripping. unpack.py and pack.py use minidom; if you write your own XML manipulation, do the same.
- EMU units everywhere. 1 inch = 914400 EMU. Slide positions, sizes, font sizes (in pt × 100) all use derived EMU values.
- Placeholders vs free shapes. Placeholders inherit from slide masters; free shapes don't. Editing a placeholder's text is
<a:t> content; editing its layout requires master-slide changes.
- Don't pretty-print pptx XML on pack. Whitespace-significant runs (
<a:r>) break if reformatted. pack.py preserves the original whitespace.
- Slide cloning is more than a file copy. Use
unpack + pack — manual file copies miss the rIds in _rels/ and the Content_Types.xml registration.
Deterministic QA loop
After every generation, run:
python scripts/thumbnail.py deck.pptx thumbs/
python scripts/deterministic_qa.py deck.pptx > qa.json
deterministic_qa.py checks:
- Shape bounding boxes don't extend past slide edges
- No two shapes overlap with > 50% area intersection
- Font sizes ≥ 11pt for body text, ≥ 18pt for titles
- All placeholders are filled (no
Click to add title defaults)
- Bullet lists don't exceed 7 items per slide
Output is JSON listing each violation with slide number and shape id. Fix violations and re-render.
(A vision-model QA pass is intentionally out of scope for v1. Add --use-vision later if deterministic checks miss layout issues.)
Validation gate
Always run validate.py before declaring done. Schema-validates against ECMA-376 PresentationML XSDs, checks rId consistency, content-type registration.
Out of scope
- Reading: use the
read tool.
- SmartArt creation (limited python-pptx support).
- Complex embedded charts beyond what python-pptx exposes.
- Slide transitions / animations (rarely matter for legal output).
- Vision-model layout review (deferred to v2).