Most AI + PPTX tools create slides. I built one that only edits speaker notes — the text presenters read while presenting.
Here's the technical deep dive.
The Problem
30-slide quarterly review deck, slides are done, speaker notes are empty on all 30 pages. Manual writing: 3-4 hours. python-pptx script: 1-2 hours of debugging XML mapping and escape characters.
There are 300+ AI presentation tools. 99% focus on creating slides. Almost none touch speaker notes.
PPTX Internals: What You Need to Know
PPTX files are ZIP archives of XML following ECMA-376 (ISO/IEC 29500). Unzip one and you'll see:
pptx-unpacked/
├── ppt/
│ ├── slides/
│ │ ├── slide1.xml
│ │ └── _rels/
│ │ └── slide1.xml.rels
│ ├── notesSlides/
│ │ ├── notesSlide1.xml
│ │ └── notesSlide2.xml
│ └── _rels/
│ └── presentation.xml.rels
└── [Content_Types].xml
Notes text lives in <a:t> tags (DrawingML namespace) inside ppt/notesSlides/notesSlideN.xml.
The notesSlide Mapping Trap
Here's the non-obvious part: notesSlide3.xml is NOT always slide 3.
When you delete, reorder, or edit slides across different PowerPoint versions, notes file numbering gets gaps or misalignments. The real mapping is in .rels files:
<!-- slide5.xml.rels -->
<Relationship Id="rId2"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide"
Target="../notesSlides/notesSlide3.xml"/>
This means slide 5's notes are in notesSlide3.xml. Edit by number, and you'll modify the wrong page.
The skill resolves this automatically:
for f in pptx-unpacked/ppt/slides/_rels/slide*.xml.rels; do
slide=$(basename "$f" .xml.rels)
notes=$(grep -o 'notesSlide[0-9]*\.xml' "$f" | head -1)
[ -n "$notes" ] && echo "$slide -> $notes"
done
How the Skill Works
Unpack PPTX → Resolve mapping → Read ALL slides → Generate drafts → User confirms → Write XML → Repack + verify
The critical design decision: read the whole deck before writing any notes. This prevents the common problem where page-by-page generation produces repetitive, disconnected notes.
XML Escape Handling
Notes text may contain special characters that must be escaped:
| Character | XML Escape | Required |
|---|---|---|
& |
& |
Always |
< |
< |
Always |
> |
> |
Recommended |
" |
" |
In attributes |
Multi-paragraph notes use separate <a:p> elements, each with its own <a:t> tag. You must preserve the full tag structure when editing.
Comparison with python-pptx
| Aspect | python-pptx | pptx-notes-editor |
|---|---|---|
| Programming required | Python | None (natural language) |
| Mapping detection | Manual | Automatic |
| Context analysis | Not supported | Reads whole deck first |
| XML escaping | Library handles | Skill handles |
| Writing styles | Fixed template | 4 styles + custom |
| Interactive confirm | No | Page-by-page approval |
| Notes export | Requires code | One command to Markdown |
Install
mkdir -p ~/.claude/skills/pptx-notes-editor && curl -fsSL https://raw.githubusercontent.com/cm8421/pptx-notes-editor/main/SKILL.md -o ~/.claude/skills/pptx-notes-editor/SKILL.md
/skill install @cm8421/pptx-notes-editor
Usage
Just say what you want:
"Rewrite speaker notes in narrative style"
"Export all notes to markdown"
"Add verbatim scripts to pages 5-10"
All operations are local — no file uploads, no API calls.
Top comments (0)