
powerpoint
PowerPoint slide deck generation and management using python-pptx with YAML-driven content and styling
- Installs
- 440
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/microsoft/hve-core --skill powerpoint- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads powerpoint automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
PowerPoint Skill
Generates, updates, and manages PowerPoint slide decks using python-pptx with YAML-driven content and styling definitions.
Overview
This skill provides Python scripts that consume YAML configuration files to produce PowerPoint slide decks. Each slide is defined by a content.yaml file describing its layout, text, and shapes. A style.yaml file defines dimensions, template configuration, layout mappings, metadata, and defaults.
SKILL.md covers technical reference: prerequisites, commands, script architecture, API constraints, and troubleshooting. For conventions and design rules (element positioning, visual quality, color and contrast, contextual styling), follow pptx.instructions.md.
Prerequisites
PowerShell
The Invoke-PptxPipeline.ps1 script handles virtual environment creation and dependency installation automatically via uv sync. Requires uv, Python 3.11+, and PowerShell 7+.
Installing uv
If uv is not installed, use a package manager that verifies the download against a published hash:
# Windows
winget install --id astral-sh.uv -e
# macOS / Linux (Homebrew)
brew install uv
To install from a release archive instead, download it from the uv releases page and check it against its .sha256 file before extracting.
System Dependencies (Export and Validation)
The Export and Validate actions require LibreOffice for PPTX-to-PDF conversion and optionally pdftoppm from poppler for PDF-to-JPG rendering. When pdftoppm is not available, PyMuPDF handles the image rendering.
The Validate action's vision-based checks require the GitHub Copilot CLI for model access.
# macOS
brew install --cask libreoffice
brew install poppler # optional, provides pdftoppm
# Linux
sudo apt-get install libreoffice poppler-utils
# Windows (winget preferred, choco fallback)
winget install TheDocumentFoundation.LibreOffice
# choco install libreoffice-still # alternative
# poppler: no winget package; use choco install poppler (optional, provides pdftoppm)
Copilot CLI (Vision Validation)
The validate_slides.py script uses the GitHub Copilot SDK to send slide images to vision-capable models. The Copilot CLI must be installed and authenticated:
# Install Copilot CLI
npm install -g @github/copilot-cli
# Authenticate (uses the same GitHub account as VS Code Copilot)
copilot auth login
# Verify
copilot --version
Required Files
style.yaml— Dimensions, defaults, template configuration, and metadatacontent.yaml— Per-slide content definition (text, shapes, images, layout)- (Optional)
content-extra.py— Custom Python for complex slide drawings
Content Directory Structure
All slide content lives under the working directory's content/ folder:
content/
├── global/
│ ├── style.yaml # Dimensions, defaults, template config, and theme metadata
│ └── voice-guide.md # Voice and tone guidelines
├── slide-001/
│ ├── content.yaml # Slide 1 content and layout
│ └── images/ # Slide-specific images
│ ├── background.png
│ └── background.yaml # Image metadata sidecar
├── slide-002/
│ ├── content.yaml # Slide 2 content and layout
│ ├── content-extra.py # Custom Python for complex drawings
│ └── images/
│ └── screenshot.png
├── slide-003/
│ ├── content.yaml
│ └── images/
│ ├── diagram.png
│ └── diagram.yaml
└── ...
Global Style Definition (style.yaml)
The global style.yaml defines dimensions, template configuration, layout mappings, metadata, and defaults. Color and font choices are specified per-element in each slide's content.yaml rather than centralized in the style file.
See the style.yaml template for the full template, field reference, and usage instructions.
Per-Slide Content Definition (content.yaml)
Each slide's content.yaml defines layout, text, shapes, and positioning. All position and size values are in inches. Color values use #RRGGBB hex format or @theme_name references.
Text contract: markdown-like list lines in textbox.text and shape.text are interpreted as PowerPoint lists during rendering. Unordered markers (-, +, *) become bulleted paragraphs, ordered markers (1., 1)) become auto-numbered paragraphs, and leading indentation maps to paragraph level.
See the content.yaml template for the full template, supported element types, supported shape types, and usage instructions.
Accessibility: each slide's title becomes the slide title that screen readers announce and navigate by, alt or decorative on an image sets its alternative text, and metadata.language in style.yaml sets the document and text language.
Complex Drawings (content-extra.py)
When a slide requires complex drawings that cannot be expressed through content.yaml element definitions, create a content-extra.py file in the slide folder. The render() function signature is fixed. The build script calls it after placing standard content.yaml elements.
See the content-extra.py template for the full template, function parameters, and usage guidelines.
Security Validation
content-extra.py execution is disabled by default. When a slide folder contains one and --allow-scripts is not passed, the build fails with an error naming the file. Pass --allow-scripts to authorize execution after reviewing the script.
When execution is authorized, the build script performs AST-based static analysis before running the file and rejects the patterns below. This analysis is a lint that catches obvious mistakes early. It is not a security boundary: a blocked module reached through an alias is not detected, and pathlib and open are permitted. Authorization is the control.
Allowed imports:
pptxand allpptx.*submodules- Safe standard-library modules (e.g.,
math,copy,json,re,pathlib,collections,itertools,functools,typing,enum,dataclasses,decimal,fractions,string,textwrap)
Blocked imports:
subprocess,os,shutil,socket,ctypes,signal,multiprocessing,threading,http,urllib,ftplib,smtplib,imaplib,poplib,xmlrpc,webbrowser,code,codeop,compileall,py_compile,zipimport,pkgutil,runpy,ensurepip,venv,sqlite3,tempfile,shelve,dbm,pickle,marshal,importlib,sys,telnetlib- Any third-party package not on the allowlist
Blocked builtins:
- Dangerous:
eval,exec,__import__,compile,breakpoint - Indirect bypass:
getattr,setattr,delattr,globals,locals,vars - Attribute-form calls onto
builtins,os,sys,subprocess, andimportlib(for examplebuiltins.eval(...))
--allow-scripts flag:
Pass --allow-scripts to authorize execution of content-extra.py files. Without it, a present script fails the build rather than being skipped, so a deck never silently loses custom drawings. The flag authorizes execution; it does not skip the lint.
This is a behavior change. A deck that previously built with a content-extra.py present now requires --allow-scripts, and a script relying on a blocked import no longer has a bypass.
python scripts/build_deck.py \
--content-dir content/ \
--style content/global/style.yaml \
--output slide-deck/presentation.pptx \
--allow-scripts
When validation fails, the build raises ContentExtraError with a message identifying the violation and file path.
Script Reference
The full command surface lives in references/script-reference.md: build a deck, build from a template, update specific slides, extract content from an existing PPTX, validate, export slides to images or SVG, dry-run validation, generate theme variants, and embed audio.
Script Architecture
The build and extraction scripts use shared modules in the scripts/ directory:
| Module | Purpose |
|---|---|
pptx_utils.py | Shared utilities: exit codes, logging configuration, slide filter parsing, unit conversion (emu_to_inches()), YAML loading |
pptx_colors.py | Color resolution (#hex, @theme, dict with brightness), theme color map (16 entries) |
pptx_fonts.py | Font resolution, family normalization, weight suffix handling, alignment mapping |
pptx_shapes.py | Shape constant map (29 entries + circle alias), auto-shape name mapping, rotation utilities |
pptx_fills.py | Solid, gradient, and pattern fill application/extraction; line/border styling with dash styles |
pptx_text.py | Text frame properties (margins, auto-size, vertical anchor), paragraph properties (spacing, level), run properties (underline, hyperlink), markdown-like list parsing to bullet/auto-number paragraphs |
pptx_tables.py | Table element creation and extraction with cell merging, banding, and per-cell styling |
pptx_charts.py | Chart element creation and extraction for 12 chart types (column, bar, line, pie, scatter, bubble, etc.) |
validate_deck.py | PPTX-only validation for speaker notes and slide count |
validate_geometry.py | Structural validation for element edge margins, adjacent gaps, boundary overflow, and title clearance |
validate_slides.py | Vision-based slide issue detection and quality validation via Copilot SDK with built-in checks and plain-text per-slide output |
render_pdf_images.py | PDF-to-JPG rendering via PyMuPDF with optional slide-number-based naming |
generate_themes.py | Theme variant generation from a base content directory using a color mapping YAML file |
embed_audio.py | WAV audio embedding into PPTX slides with per-slide file matching and off-screen audio icon placement |
export_svg.py | PPTX-to-SVG export via LibreOffice PDF conversion and PyMuPDF SVG rendering |
python-pptx Constraints
- python-pptx does NOT support SVG images. Always convert to PNG via
cairosvgorPillow. - python-pptx cannot create new slide masters or layouts programmatically. Use blank layouts or start from a template PPTX with the
--templateargument. - Transitions and animations are preserved when opening and saving existing files, but cannot be created or modified via the API.
- When extracting content, slide master and layout inheritance means many text elements have no inline styling. Add explicit font properties in content YAML before rebuilding.
- The Export and Validate actions require LibreOffice for PPTX-to-PDF conversion. The PowerShell orchestrator checks for LibreOffice availability before starting and provides platform-specific install instructions if missing.
- Accessing
background.fillon slides with inherited backgrounds replaces them withNoFill. Checkslide.follow_master_backgroundbefore accessing the fill property. - Gradient fills use the python-pptx
GradientFillAPI withGradientStopobjects. Each stop specifies a position (0–100) and a color. - Theme colors resolve via
MSO_THEME_COLORenum. Brightness adjustments apply through the color format'sbrightnessproperty. - Template-based builds load layouts by name or index. Layout name resolution falls back to index 6 (blank) when no match is found.
Security Considerations
This skill processes PDF files via PyMuPDF, which wraps the MuPDF C library. MuPDF parses untrusted binary structures (cross-reference tables, stream objects, font definitions) and historical CVEs have shown that memory-safety bugs in C parsers can lead to crashes, memory disclosure, or in rare cases code execution.
Mitigations in place
scripts/pdf_safety.pyvalidates every PDF (existence, regular-file, size <= 100 MB,%PDF-magic bytes, page count <= 1000) before callingfitz.open().- All
fitzoperations are wrapped insafe_open_pdf(), which converts MuPDF exceptions into typedPdfSafetyErrorsubclasses (PdfTooLargeError,PdfInvalidFormatError,PdfTooManyPagesError,PdfParseError,PdfRenderError). pymupdfis version-pinned inpyproject.toml(>=1.27.1,<2.0) to track security fixes without silently adopting a major-version API change.
Defense-in-depth note: the 5-byte
%PDF-magic check is a necessary but not sufficient guarantee of structural validity. A crafted small file that begins with%PDF-still reaches the MuPDF parser, where memory-safety bugs may exist. Callers MUST keep PyMuPDF patched against the latest advisories (tracked via microsoft/hve-core#1020 /pip-audit) and continue to treat such inputs as untrusted. ThePdfSafetyErrorhierarchy (PdfTooLargeError,PdfInvalidFormatError,PdfTooManyPagesError,PdfParseError,PdfRenderError) is one defense layer alongside the version pin and CVE monitoring; no single layer is sufficient on its own.
Accepted risk
These mitigations reduce but do not eliminate the C-extension attack surface. Consumers SHOULD treat PDF inputs from outside this skill's PPTX-to-PDF pipeline as untrusted and apply additional sandboxing (subprocess, container) before feeding adversarial input.
Update policy
Re-check NVD and OSV advisories for MuPDF and PyMuPDF quarterly and on every pip-audit alert.
Cross-references
- microsoft/hve-core#1018 — original hardening request
- microsoft/hve-core#1020 — pip-audit CI for ongoing CVE monitoring (separate effort)
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| SVG runtime error | python-pptx cannot embed SVG | Convert to PNG via cairosvg before adding |
| Text overlay between elements | Insufficient vertical spacing | Follow element positioning conventions in pptx.instructions.md |
| Width overflow off-slide | Element extends beyond slide boundary | Follow element positioning conventions in pptx.instructions.md |
| Bright accent color unreadable as fill | White text on bright background | Darken accent to ~60% saturation for box fills |
| Background fill replaced with NoFill | Accessed background.fill on inherited background | Check slide.follow_master_background before accessing |
| Missing speaker notes | Notes not specified in content.yaml | Add speaker_notes field to every content slide |
| LibreOffice not found during Validate | Validate exports slides to images first | Install LibreOffice: brew install --cask libreoffice (macOS) |
uv not found | uv package manager not installed | Install uv: winget install --id astral-sh.uv -e (Windows) or brew install uv (macOS/Linux); see Installing uv above |
| Python not found by uv | No Python 3.11+ on PATH | Install via uv python install 3.11 or pyenv install 3.11 |
uv sync fails | Missing or corrupt .venv | Delete .venv/ at the skill root and re-run uv sync |
| Import errors in scripts | Dependencies not installed or stale venv | Run uv sync from the skill root to recreate the environment |
Environment Recovery
When scripts fail due to missing modules, import errors, or a corrupt virtual environment, recover with:
cd "<powerpoint-skill-root>"
rm -rf .venv
uv sync
Resolve <powerpoint-skill-root> from the loaded skill location before running the command.
This recreates the virtual environment from scratch using pyproject.toml as the single source of truth. The Invoke-PptxPipeline.ps1 orchestrator runs uv sync automatically on each invocation unless -SkipVenvSetup is passed.
When uv itself is not available, install it first (see Installing uv above), then retry. When Python 3.11+ is not available, run uv python install 3.11 to have uv fetch and manage the interpreter.
FAQ
What does the powerpoint skill do?
PowerPoint slide deck generation and management using python-pptx with YAML-driven content and styling
How do I install powerpoint?
Run npx skills add https://github.com/microsoft/hve-core --skill powerpoint in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/powerpoint/ (personal) or .claude/skills/powerpoint/ (project).
Which AI agents can use powerpoint?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is powerpoint safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains powerpoint?
It is published by microsoft in microsoft/hve-core, and it is an official skill from the maker of the technology it covers. It has 440 recorded installs.
More from microsoft/hve-core
owasp-top-10
microsoft/hve-core
OWASP Top 10 for Web Applications (2025) knowledge base for identifying, assessing, and remediating web application security risks.
secure-by-design
microsoft/hve-core
Open the skill to read its SKILL.md instructions.
owasp-docker
microsoft/hve-core
OWASP Docker Top 6 knowledge base for identifying, assessing, and remediating Docker container security risks.
owasp-cicd
microsoft/hve-core
Open the skill to read its SKILL.md instructions.
owasp-infrastructure
microsoft/hve-core
Open the skill to read its SKILL.md instructions.
owasp-agentic
microsoft/hve-core
Open the skill to read its SKILL.md instructions.
Popular docs & writing skills
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
lark-markdown
open.feishu.cn
飞书 Markdown:查看、创建、上传、编辑和比较飞书中的原生 Markdown 文件。当用户要操作飞书 Markdown 文件,或比较其远端版本及本地草稿时使用。纯本地 Markdown 文件操作不触发本 skill。不负责将 Markdown 导入为飞书在线文档,也不负责文件搜索、权限、评论、移动、删除等云空间管理操作。
writing-beats
mattpocock/skills
Writing, exploit; assemble raw material into a journey of beats, grounding each term before a beat leans on it.
writing-shape
mattpocock/skills
Writing, exploit: shape raw material into an article, paragraph by paragraph.
writing-fragments
mattpocock/skills
Writing, explore: mine raw fragments, no structure yet.
writing-for-agents
mattpocock/skills
Writing documents for agents. Use when creating or editing skills, or modifying AGENTS.md or CLAUDE.md.