$npx -y skills add anthropics/skills --skill pptxUse this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used else
| 1 | # PPTX creation, editing, and analysis |
| 2 | |
| 3 | A `.pptx` is a ZIP archive of XML files. Choose your approach by task: |
| 4 | |
| 5 | | Task | Approach | |
| 6 | |---|---| |
| 7 | | **Create** a new deck | Write a `pptxgenjs` script — see gotchas below | |
| 8 | | **Edit** an existing deck, or build from a template | unzip → edit `ppt/slides/slideN.xml` → zip | |
| 9 | | **Read** content | `markitdown deck.pptx` (one block per slide under `<!-- Slide number: N -->` markers); visual grid: `python scripts/thumbnail.py deck.pptx` | |
| 10 | |
| 11 | ## Scripts |
| 12 | |
| 13 | Paths are relative to this skill's directory. Everything else is plain Python, `node`, or shell. |
| 14 | |
| 15 | | Script | What it does | |
| 16 | |---|---| |
| 17 | | `scripts/thumbnail.py deck.pptx [prefix]` | Labeled grid of every slide, for picking template layouts. `.pptx` only. Pass `prefix` — it defaults to `thumbnails`, which overwrites the grids of any other deck done in the same directory | |
| 18 | | `scripts/add_slide.py unpacked/ slide2.xml [--after slideN.xml]` | Duplicate a slide (or a `slideLayoutN.xml`) with all the package bookkeeping. Also takes a `.pptx` directly with `-o out.pptx` | |
| 19 | | `scripts/clean.py unpacked/` | Delete slides, media, and rels no longer referenced. Run **after** `<p:sldIdLst>` is final | |
| 20 | | `scripts/office/validate.py deck.pptx [--original src.pptx]` | Schema, relationship, content-type, chart and slide checks; each failure names its fix. Pass `--original` for any template-derived deck — it baselines the schema checks against the template, so the template's own XSD errors don't read as yours | |
| 21 | | `scripts/office/soffice.py --headless --convert-to pdf deck.pptx` | LibreOffice wrapper — bare `soffice` hangs in this sandbox | |
| 22 | |
| 23 | ## Creating with pptxgenjs — gotchas |
| 24 | |
| 25 | `pptxgenjs` is preinstalled — do not run `npm install` first; write the script and `require('pptxgenjs')` directly. Only if that require fails: `npm install pptxgenjs`. The model knows the API; these are the footguns: |
| 26 | |
| 27 | - **Set `pres.layout` before adding slides.** The default canvas is `LAYOUT_16x9` = **10" × 5.625"**, not 13.3" wide. Coordinates past the edge are written, not clamped — the shape just isn't on the slide. (`LAYOUT_WIDE` is 13.3" × 7.5".) |
| 28 | - **Hex colors: never `#`, never 8 digits.** `color: "FF0000"`. Both `"#FF0000"` and alpha baked into the hex (`"00000020"`) **corrupt the file**. For translucency: `transparency: 0-100` on fills and images, `opacity: 0.0-1.0` on shadows — each is silently ignored on the other. |
| 29 | - **pptxgenjs mutates option objects in place** (converts values to EMU on first use). Never share one `shadow`/options object across two `add*` calls — build a fresh object each time. |
| 30 | - **Shadow `offset` must be ≥ 0** — a negative offset corrupts the file. To cast a shadow upward, use `angle: 270` with a positive offset. |
| 31 | - **`letterSpacing` is silently ignored** — the real option is `charSpacing`. |
| 32 | - **Lists:** `bullet: true` on each item, never a literal `•` (renders double bullets). Set `breakLine: true` on every array item except the last. Space bulleted paragraphs with `paraSpaceAfter`, not `lineSpacing` (huge gaps). |
| 33 | - **One `new pptxgen()` per output file** — never reuse an instance. |
| 34 | - **`rectRadius` only works on `ROUNDED_RECTANGLE`**, not `RECTANGLE`. |
| 35 | - **Gradient fills aren't supported** — use a gradient image as the background instead. |
| 36 | - **Text boxes have built-in internal padding** — set `margin: 0` whenever text must align with a shape, line, or icon at the same x. |
| 37 | - **Speaker notes go in `slide.addNotes("...")`** (plain text, once per slide), never in a text box on the slide. |
| 38 | - **Keep charts native.** Use `addChart()` for everything PowerPoint can chart (pass an array of `{type, data, options}` for combos). For PowerPoint-native features the library doesn't expose (trendlines, error bars), compute the extra series yourself or post-process the generated OOXML — do not fall back to a rendered image. Only chart types PowerPoint has no native form for (Sankey, network, chord) go in as images. |
| 39 | - **Default charts render bare** — no title, no data labels, dated palette. Set `showTitle` + `title`, `showValue: true` + `dataLabelPosition`, `chartColors: [...]` from your palette, and quiet the frame (`catAxisLabelColor`/`valAxisLabelC |