Design¶
This page gives the condensed rationale. The canonical, longer design document
is spec.md in
the repo root — written deliberately as the diff against
wordlive — and the staged
roadmap is in
IMPLEMENTATION.md.
Why pptlive exists¶
There is no good Python library for driving a live Microsoft PowerPoint session. The options today are:
| Library | Target | Mechanism |
|---|---|---|
python-pptx |
.pptx file on disk |
OOXML I/O |
pptlive |
Running POWERPNT.exe |
COM (pywin32) |
File-side libraries can't help when the user has the deck open — PowerPoint
holds the lock, and any change you make on disk is invisible until they close
and re-open. The round-trip (close the deck, let the agent write, re-open to
see it, close again) is slow and error-prone. COM is the only live path. And
raw pywin32 is brutally LLM-hostile: magic integer constants (MsoShapeType,
PpPlaceholderType, XlChartType), untyped late-bound dispatch, modal-dialog
footguns, STA threading rules.
xlwings exists for Excel; wordlive for Word. pptlive is the equivalent for
PowerPoint, with one extra goal: be first-class for LLM tool use, not
retrofitted.
Design principles¶
The four principles, in priority order:
- Politeness first. Default behaviour preserves the user's viewed
slide, shape/text
Selection, and focus. They keep editing — or presenting — alongside your script. Operations that must move the screen say so explicitly (deck.go_to(...), thedeck.showverbs,scope.allow_view_move()). Jumping the active slide is the PowerPoint equivalent of stomping the cursor — and more jarring, because it's a full-screen change. - Semantic anchors over
Selection. Operations target hierarchical named handles —ph:S:KIND,shape:S:N,shapeid:S:ID,para:S:N:P,cell:S:N:R:C,notes:S,comments:S— not the live selection. Anchors are stable enough to address in JSON and visible to an LLM as strings; the selection is neither. - Atomic undo. Every
deck.edit()block fences a single undo entry viaStartNewUndoEntry, so one Ctrl-Z reverts the whole intent — even though PowerPoint has no Word-styleUndoRecord. See Concepts. - Structured I/O. Reads return dataclasses / dicts; the CLI emits one JSON object per invocation; exit codes are deterministic. No string scraping anywhere. See the Errors page for the contract.
Underlying all four: an escape hatch. Every wrapper exposes .com. When
pptlive doesn't cover something, drop to raw COM rather than giving up.
The three things PowerPoint changes vs. Word¶
pptlive copies wordlive's structure almost verbatim. Three places where PowerPoint's object model forced a divergence:
- Atomic undo, by a different mechanism. Word brackets a block with
Application.UndoRecord. PowerPoint has no such bracket — but it groups consecutive in-session COM edits into one undo entry by default, andStartNewUndoEntry()is a verified boundary primitive. Soedit()fences on entry and the block is one Ctrl-Z. (One of three spec assumptions a live spike corrected.) - PowerPoint must be visible.
Application.Visible = Falseraises in most builds (verified: "Hiding the application window is not allowed"). Soconnect()has no hidden mode — politeness is about not moving the user's view, not about working unseen. - Anchors are hierarchical, not a global offset. There is no
document-wide character stream and no deck-wide
range:. Addressing is slide → shape → paragraph, slide-index first. z-order drifts as shapes are added/removed, soshape:S:Nis always resolved live and listings emit a stableShape.Id,Shape.Name, andalt_textfor re-identification.
What's out of scope¶
- Cross-platform support. COM is Windows-only. We don't pretend otherwise.
- Cloud co-authoring / PowerPoint on the web. Microsoft Graph is a different stack and a different problem.
- Full PowerPoint object-model coverage. Anything we don't cover is one
.comaccess away. - Replacing
python-pptx. Different surface, different problem. Generate a deck from scratch in a batch job? Usepython-pptx. Edit the deck the user is looking at? Use pptlive. - Designer / AI layout suggestions. Out of scope.
Architecture at a glance¶
your code / LLM
│
▼
┌───────────────────────────────────────────────────┐
│ pptlive public API │
│ attach / connect → PowerPoint │
│ │ │
│ ▼ │
│ Presentation │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ ▼ ▼ ▼ │
│ slides anchor_by_id show │
│ │ │ │
│ ▼ ▼ │
│ Slide → shapes → Shape ── is-a ──┐ │
│ │ ▼ │
│ ▼ Anchor │
│ Table / Chart (text, set_text,
│ format_text, …) │
└───────────────────────────────────────────────────┘
│
▼
EditScope (StartNewUndoEntry + SelectionSnapshot)
│
▼
pywin32 → PowerPoint.Application (COM, STA-threaded)
The library is intentionally flat: ~15 modules, no plugin system, no hierarchy
beyond PowerPoint → Presentation → Slide → Shape → Anchor. _com.py is the
only module that touches pywin32, which is what makes the whole surface
unit-testable against a fake-COM fixture with no PowerPoint installed.
What comes next¶
The staged build log is
IMPLEMENTATION.md;
the forward-looking work still open is
roadmap.md.
The current release covers the politeness / anchors / EditScope core, the
LLM-first CLI, the slide lifecycle (incl. named sections),
shapes & geometry (fill / border, z-order restacking, the delete-proof
shapeid:S:ID anchor, group / align / distribute / connectors),
text structure (paragraphs, font formatting, bullets, text-run
hyperlinks), tables (cells as cell:S:N:R:C anchors, row/column
add-delete, cell fill + borders), slide render + live selection (here:),
pictures (alt text, per-shape export, in-place re-source), charts
(embedded-Excel data) and SmartArt diagrams (node-tree read / set_nodes +
per-node formatting) — both with coarse recolor_text for dark-theme labels,
deck-wide styling via the theme and master (palette, heading/body fonts, master
text styles, background), headers/footers (slide-number, date,
footer text), slide transitions and whole-shape entrance/exit
animations, media (embedded audio/video,
auto-pacing) and narrated-video export via the async
CreateVideo, fuzzy find / replace across shapes / cells /
notes, threaded review comments, the whole-deck
snapshot vision read, explicit
save / save_as / PDF export, and live slide-show control
(deck.show). It also ships an optional MCP server for Claude Desktop
and other MCP clients.
The consistency-audit linter / regularizer
shipped its foundation (peer-mode + geometry rules, regularize, format_info);
its text / deck clusters and house-style profiles remain. Deferred, per
roadmap.md: the animation long tail (per-paragraph
levels, motion paths, effect-specific parameters, sequence reordering); media
long tail (poster frames, bookmarks, native recorded narration); 3-D shape
effects and non-solid backgrounds; deeper tables (merge/split, column width /
row height, built-in styles), charts (title/legend/axis authoring, per-element
targeting), and SmartArt (node-shape fill); durable file-persisted shape tags
and document properties/metadata; event sinks (SlideShowNextSlide,
WindowSelectionChange), an async wrapper, and full custom slide-layout
authoring (creating new layouts — distinct from the theme/master styling that
already ships).
Full design document¶
For the unabridged version — the original motivation, the error taxonomy in
more detail, the rejected alternatives, the resolved spikes, and the open
questions — see
spec.md in the
repo root.