Skip to content
Conduit

skill

pptx-math

Native PowerPoint equations from LaTeX. Converts LaTeX to OMML and injects it into .pptx — editable, vector equations instead of images or Unicode text. A companion to the pptx skill / python-pptx.

maenjh/pptx-mathcommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/maenjh/pptx-math itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 23, 2026

pptx-math

한국어 문서는 README.ko.md

Put real PowerPoint equations into .pptx files from LaTeX — not pictures of equations.

add_native_equation(box.text_frame,
    r"\Pr(y=1) = \sigma(\alpha + \beta_j \cdot z_j + \gamma \cdot \mathbf{x})")

The result is a native OMML equation: double-click it in PowerPoint and the equation editor opens. It is vector (never pixelates), it follows the theme color, and it is editable by whoever opens the deck.

No pandoc, no LaTeX distribution, no MathType. Standard library + python-pptx only.


Why this exists

python-pptx has no equation API. Every workaround is worse than it looks:

ApproachEditableQualityVerdict
Native OMML (this repo)Yes — equation editorVector, LaTeX-grade✅
Rendered PNG (matplotlib)No — it's an imageRasterizes when zoomedFallback only
Unicode text (σ(α + βⱼ zⱼ))Yes, but it's just textFractions, roots and ∑ collapse❌

The Unicode route is the one that gets used by default, and it silently destroys anything non-trivial. \sigma(z) = \frac{1}{1+e^{-z}} becomes σ(z) = 11 + e⁻ᶻ.

Relationship to the pptx skill

This is a companion, not a replacement. The pptx skill (and any python-pptx workflow) handles decks: layouts, text, tables, images, charts. It has no way to emit a native equation. pptx-math fills exactly that one gap and nothing else.

Typical division of labour:

pptx skill / python-pptx  →  build the deck, place the text boxes
pptx-math                 →  every place where math appears

When to use it

Use it whenever math reaches a slide — including a single italic variable in a sentence. Specifically:

  • Equations, math variables (x, r_A, β_j), Greek letters, sub/superscripts, fractions, ∑, ∫, matrices.
  • Generating a deck from a paper, PDF, or Markdown. Research slides almost always carry math, and it is easy to flatten it to Unicode without noticing. Inline variables inside prose (p, r_A, r_B, y) count.
  • Upgrading an existing deck whose equations were typed as plain text (Pr(y = 1) = σ(α + βj zj), rA, τ).

Do not convert acronyms, labels, or plain numbers — AUC, Elo, Δwin-rate, −31%p read worse in math italic.

Install

1. Claude Code plugin (recommended)

Two commands, nothing else to install:

/plugin marketplace add maenjh/pptx-math
/plugin install pptx-math

Update later with /plugin marketplace update pptx-math, remove with /plugin uninstall pptx-math.

2. One-line script

No plugin system, no Node — copies the skill into ~/.claude/skills/pptx-math:

curl -fsSL https://raw.githubusercontent.com/maenjh/pptx-math/main/install.sh | bash

It backs up any existing install and tells you if python-pptx is missing.

3. Manual

git clone --depth 1 https://github.com/maenjh/pptx-math.git /tmp/pptx-math
cp -R /tmp/pptx-math/skills/pptx-math ~/.claude/skills/

4. As a plain Python module

The converter does not need Claude at all.

git clone https://github.com/maenjh/pptx-math.git
pip install python-pptx            # matplotlib only for the image fallback
import sys; sys.path.insert(0, "pptx-math/skills/pptx-math/scripts")
from pptx_math import add_native_equation

Requirements

Python 3.9+ and python-pptx. Everything else is standard library. matplotlib is optional and only used by add_equation_image().

Once installed, the skill triggers on requests like "put an equation in this PPT", "build slides from this PDF", or "turn these variables into proper math notation".

Quick start

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx_math import add_native_equation, set_paragraph_segments, shape_census

prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6])
box = slide.shapes.add_textbox(Inches(1), Inches(2), Inches(11), Inches(1.2))

# Standalone equation
add_native_equation(box.text_frame,
    r"\Pr(y=1) = \sigma(\alpha + \beta_j \cdot z_j + \gamma \cdot \mathbf{x})",
    size=Pt(32), align="center", color="1F3864")

# Several equations, one per line
for eq in [r"\sigma(z) = \frac{1}{1+e^{-z}}",
           r"\hat{y} = \mathbf{w}^\top \mathbf{x} + b"]:
    add_native_equation(box.text_frame, eq, size=Pt(24), align="center")

prs.save("out.pptx")

Inline variables inside a sentence

The most common real-world case: a body bullet that mentions p, rA, rB, y and should read 𝑝, 𝑟_𝐴, 𝑟_𝐵, 𝑦. set_paragraph_segments() reuses the existing run's font, size, colour and indentation, so the layout does not shift at all.

para = body_shape.text_frame.paragraphs[3]
set_paragraph_segments(para, [
    ("text", "The paper writes "), ("math", "p"), ("text", ", "), ("math", "r_A"),
    ("text", ", "),                ("math", "r_B"), ("text", ", "), ("math", "y"),
    ("text", ", where "),          ("math", "p"),   ("text", " is the prompt."),
])

API

FunctionPurpose
add_native_equation(tf, latex, size, align, paragraph, color, display)Add a native equation. Pass paragraph= to append inline to an existing paragraph — paragraph properties are left untouched.
set_paragraph_segments(para, segments)Rebuild a paragraph from [("text", …), ("math", …)], preserving formatting.
add_text_run(para, text, template_run=)Append a plain run, cloning a run's formatting.
math_node(latex, size, color)Build just the <a14:m> lxml element, to place yourself.
add_equation_image(slide, latex, left, top, …)matplotlib mathtext PNG fallback.
latex_to_unicode(latex)Unicode approximation. Simple one-liners only.
shape_census(path)Per-slide shape inventory. Diff this before/after every save.
latex2omml.latex_to_omml(latex)The converter on its own.

Supported LaTeX

Sub/superscripts · \frac \dfrac · \sqrt[n]{} · \left( \right) · all Greek letters · \sum \prod \int \oint with limits · \mathbf \mathrm \mathbb \mathcal \text \operatorname · \hat \bar \vec \tilde \dot \overline · function names (\log \sin \max \Pr — a thin space is added automatically, and suppressed before ( or a subscript) · \begin{pmatrix} and friends · operators (\cdot \times \leq \approx \to \infty \top …) · spacing (\quad \,).

Unknown commands are printed by name rather than silently swallowed, so mistakes are visible in the output instead of vanishing.

Pitfalls that will bite you

These are not hypothetical — every one of them was hit while building this.

  1. Verify the shape count after every save. If you violate the PPTX schema ordering, PowerPoint "repairs" the file and deletes whole shapes without warning. You will not find out until someone opens the deck.
    before = shape_census(DECK); prs.save(DECK)
    assert before == shape_census(DECK)
    
    • a:p child order: pPr, (r|br|fld|a14:m)*, endParaRPr
    • a:pPr child order: lnSpc, spcBef, spcAft, bu*, tabLst, defRPr, extLst
  2. sz is in hundredths of a point. Passing Pt(36) writes the EMU value 457200 and the equation renders at a nonsense size. _sz() handles this — don't hand-write XML.
  3. Back up the user's file before editing it.
  4. Never open the original in PowerPoint to verify — open a copy. PowerPoint can write back to the original and persist its own repair.
  5. Don't change paragraph alignment when inserting inline. align defaults to "leave as-is" for this reason.
  6. Equations are not text runs, so they don't appear in .text or in text search. Check whether speaker notes or post-processing scripts depend on those strings.

See references/verification.md for the full verification procedure and a table of every bug encountered, with its cause.

Verification

LibreOffice renders OMML but ignores its font size (it imports the equation into its own formula engine), so it can confirm an equation exists but not how it looks. Size and alignment must be checked in real PowerPoint.

cp deck.pptx /tmp/verify.pptx         # never open the original
osascript -e 'tell application "Microsoft PowerPoint"
  open POSIX file "/tmp/verify.pptx"
  delay 6
  set d to presentation "verify.pptx"
  save d in POSIX file "/tmp/v.pdf" as save as PDF
  delay 4
  close d saving no
end tell'
pdftoppm -png -r 110 -f 10 -l 10 /tmp/v.pdf /tmp/page

Use presentation "name", never active presentation — the latter grabs whatever document the user happens to have in front, and close saving no will discard their unsaved work.

Examples

  • examples/demo.py — builds a deck comparing all three approaches side by side.

License

MIT

↑↓ navigate openesc close