From work
ALWAYS invoke this skill when sanitizing, cleaning up, auditing, or aligning a PowerPoint (.pptx) deck — slide-master and layout structure, layout type attributes, stray fonts, non-theme colors, or layout naming. NEVER hand-edit pptx XML without this skill.
How this skill is triggered — by the user, by Claude, or both
Slash command
/work:sanitizing-powerpoint [path/to/deck.pptx][path/to/deck.pptx]The summary Claude sees in its skill listing — used to decide when to auto-load this skill
<objective>
The deliverable is a repaired .pptx whose every untouched part is identical to the original — only the parts that fixed a finding differ.
<core_rules> Five rules govern every run. Violating any of them corrupts a deck or silently discards the work.
~$<name>.pptx lock file means PowerPoint holds the deck. It regenerates the file from memory on its next save and discards any external edit. Stop and ask the user to close PowerPoint.app.xml. PowerPoint regenerates docProps/app.xml (the "Fonts Used" / titles manifest) from deck content on every save. Editing only app.xml is undone on the next save. Fix the parts that hold the real data; app.xml then stays correct on its own.<repackaging>). A deck reviewer sees a minimal diff, not a wholesale re-save.</core_rules>
Run these steps in order. Steps 2 and 6 use the bundled scripts in ``.Locate and guard. Resolve the .pptx path the user named. Check for a sibling ~$<name>.pptx lock file (ls the directory). If present, STOP — PowerPoint has the deck open; ask the user to close it before continuing.
Audit. Run pptx_audit.py on the deck. It reads the package read-only and reports findings across the six dimensions in <audit_dimensions>. Read the full report.
Present and scope. Show the user the findings grouped by dimension. Mechanical fixes (layout type, font redirect) and judgment fixes (color mapping, layout renames) are different — surface the judgment ones explicitly. Use AskUserQuestion to get per-dimension or per-finding approval. Fix only what the user approves.
Extract. Unzip the deck into a temporary working directory outside any git repository (e.g. under /tmp). Never extract into the deck's own folder.
Apply approved fixes. Edit the extracted XML part by part, following ${CLAUDE_SKILL_DIR}/references/audit-and-fix.md. Handle one dimension at a time, and track every changed part.
Repackage and verify. Run pptx_repack.py with the original deck, the working directory, and an output path. It rebuilds the package preserving every untouched part's content and the original member order, then verifies (see <repackaging>). Do not hand-roll the repackage.
Back up and swap. Re-check the lock file (step 1) — if PowerPoint reopened the deck, stop. Copy the original to a timestamped backup (an _archive/ sibling, or <name>_pre-sanitize-<date>.pptx). Copy the repaired file over the original.
Confirm. Run pptx_audit.py on the now-live file. Confirm the approved findings are resolved and no new finding appeared.
<audit_dimensions>
The audit covers six dimensions. references/audit-and-fix.md gives the detection method and the exact XML transformation for each.
| # | Dimension | What it catches |
|---|---|---|
| 1 | Structure | Orphaned layout parts, broken r:id references, missing content-type overrides, layouts duplicated within a master, unregistered masters |
| 2 | Layout types | A layout's type attribute (blank, secHead, title, titleOnly, obj, cust, …) not matching its actual content — e.g. an empty layout typed cust instead of blank |
| 3 | Fonts | Typefaces that are not the theme's major/minor font — stray buFont bullet fonts, theme script-fallbacks, hardcoded run fonts |
| 4 | Colors | Hardcoded <a:srgbClr> values where a theme <a:schemeClr> exists for the same color |
| 5 | Naming | Layout names that deviate from the deck's own dominant naming pattern; PowerPoint dedup artifacts (1_-prefixed names) |
| 6 | Trim | Masters and layouts used by zero slides, unused themes, sensitivity labels (docMetadata/LabelInfo.xml), Office add-ins (ppt/webextensions/) |
Dimension 5 is inferred, never imposed: the audit detects the pattern the deck already uses most (commonly <Type> | <MasterName>) and flags only the outliers. It never invents a convention.
</audit_dimensions>
[Content_Types].xml stays the first member; all other members keep their original order. Some readers depend on this.pptx_repack.py rebuilds the archive from the original, substituting only the parts that changed in the working directory, then verifies — and exits non-zero on failure:
unzip -t equivalent)..xml and .rels part in the output archive.It also reports the member-count delta against the original. This is informational, not enforced: dimension 6 (trim) deliberately removes parts, and the script has no way to distinguish an approved trim from an accidental drop, so a changed count is printed as a note rather than gated by exit code. Compare it against the trim findings the user approved in step 3.
NEVER repackage by extracting everything and re-zipping with default tooling — that reorders members and can recompress parts in ways some readers reject. Always use pptx_repack.py.
| Script | Purpose | Usage |
|---|---|---|
scripts/pptx_audit.py | Read-only six-dimension audit; prints a findings report. --json for machine-readable output. | python3 "${CLAUDE_SKILL_DIR}/scripts/pptx_audit.py" <deck.pptx> |
scripts/pptx_repack.py | Content-surgical repackage of a working directory back into a .pptx, with verification. | python3 "${CLAUDE_SKILL_DIR}/scripts/pptx_repack.py" <original.pptx> <workdir> <out.pptx> |
The audit script never writes. The repack script writes only its named output file.
<failure_modes> Failures from real usage. Each one cost a wrong diagnosis or a lost edit.
Mistaking multi-master UX for corruption
Home → Layout gallery shows only the layouts of the current slide's master. A layout on a different master is simply not shown there.Overwriting a deck PowerPoint has open
~$<name>.pptx lock file signals this.Fixing app.xml and nothing else
docProps/app.xml's "Fonts Used" list and changed nothing else; it reappeared on the next save.app.xml from deck content on every save. app.xml is a derived manifest, not a source of truth.buFont, theme fonts). app.xml corrects itself on the next save.Redirecting a bullet font to a font without the glyph
buFont from Arial to a theme font that lacked U+2022; bullets rendered as blank or tofu.buFont, confirm the target font covers every buChar codepoint the deck uses (U+2022 is the common one).Assuming a layout rename needs slide relinking
<p:cSld name="…"> is display-only.<p:cSld name> freely. No relinking is needed; the rename cannot break a reference.</failure_modes>
<success_criteria> A sanitizing run is complete when:
pptx_repack.py verification (ZIP integrity, XML well-formedness); any member-count change matches the trim scope approved in step 3.pptx_audit.py on the live file confirms the approved findings are resolved and no new finding appeared.</success_criteria>
<reference_guides>
| File | When to read |
|---|---|
references/opc-structure.md | Before the first audit — the package anatomy, the master→layout→slide relationship chain, the layout type enum |
references/audit-and-fix.md | During steps 3 and 5 — the detection method and exact XML transformation for each of the six dimensions |
</reference_guides>
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub outcomeeng/plugins --plugin work