Help us improve
Share bugs, ideas, or general feedback.
From hands-on-deck
Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes reading, analyzing, or extracting content from presentations; editing text, images, styles, or layout of existing decks; creating new slides, shapes, tables, or pictures; reordering, duplicating, or merging slides across decks; and verifying decks visually. Trigger whenever the user mentions a deck, slides, a presentation, or a .pptx filename.
npx claudepluginhub everyinc/hands-on-deckHow this skill is triggered — by the user, by Claude, or both
Slash command
/hands-on-deck:hands-on-deckThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
One tool does everything: `scripts/deck.py`. You write a JSON *patch* describing your edits; deck.py validates and executes it atomically, then lints the result. You never need to open slide XML for routine work.
Creates p5.js generative art with seeded randomness, noise fields, and interactive parameter exploration. Use for algorithmic art, flow fields, or particle systems.
Share bugs, ideas, or general feedback.
One tool does everything: scripts/deck.py. You write a JSON patch describing your edits; deck.py validates and executes it atomically, then lints the result. You never need to open slide XML for routine work.
Golden rules (the tool enforces and repeats these):
s12) or unique shape name.Full reference: python scripts/deck.py docs — prints every op with semantics and recipes; needs no file. Read it before writing your first patch.
# 1. READ — cheap orientation first, full JSON only when about to write a patch
python scripts/deck.py deck.pptx inspect --slide 3 --brief # one line per shape
python scripts/deck.py deck.pptx inspect --slide 3 # full JSON: text+formatting, image rIds, geometry, issues
python scripts/deck.py deck.pptx inspect --issues # only shapes with geometric problems
# 2. WRITE — one patch, many ops, atomic; chain repair + render of touched slides
python scripts/deck.py deck.pptx apply patch.json -o out.pptx --fix --render img/
# 3. VERIFY — look at what you changed
# (render names files slide-<0-based-index>.jpg to match inspect)
python scripts/deck.py deck.pptx diff out.pptx # structural changelog, no rendering
--fix runs deterministic geometry repair on the slides you touched (grows/shrinks/nudges overflowing text; never auto-moves pictures). Its residue report lists what still needs judgment, with a suggested op. Always look at the rendered image before declaring success.
{"ops": [
{"op":"set-text", "slide":3, "shape":"s12", "text":["Title", "Subtitle"]},
{"op":"swap-image", "slide":3, "shape":"s9", "image":"/abs/new.png"},
{"op":"swap-image", "media":"image13.png", "image":"/abs/logo.png"},
{"op":"replace-text","scope":"deck", "from":"Old Name", "to":"New Name"},
{"op":"replace-color","scope":"deck", "from":"E8A33D", "to":"F8DE6E"},
{"op":"set-theme", "colors":{"accent1":"BB7B19"}, "fonts":{"major":"Georgia"}},
{"op":"set-props", "title":"Q3 Review", "author":"Acme"},
{"op":"set-slide", "slide":3, "hidden":true, "background":"0F5258"},
{"op":"set-slide", "slide":3, "transition":{"type":"fade","speed":"med"}},
{"op":"set-notes", "slide":3, "notes":"speaker notes"},
{"op":"move", "slide":3, "shape":"s12", "to":[1.0,2.5]},
{"op":"resize", "slide":3, "shape":"s12", "size":[4.0,1.5]},
{"op":"set-style", "slide":3, "shape":"s12", "font_size":18, "fill":"0B3D3A", "rotation":6},
{"op":"delete", "slide":3, "shape":"s12"},
{"op":"duplicate", "slide":3, "shape":"s12", "offset":[0,1.2], "text":["Fourth pillar"]},
{"op":"copy-shape", "from_slide":8, "shape":"s12", "slide":3, "at":[1.0,2.0]},
{"op":"reorder", "slide":3, "shape":"s12", "z":"back"},
{"op":"add-shape", "slide":3, "kind":"textbox", "at":[1,2], "size":[4,1.5], "text":["…"], "name":"card"},
{"op":"add-picture", "slide":3, "image":"/abs/img.png", "at":[1,2], "width":4},
{"op":"add-table", "slide":3, "at":[1,2], "size":[8,3], "rows":[["A","B"],["1","2"]]},
{"op":"add-slide", "layout":"Blank", "at":5},
{"op":"add-row", "slide":3, "shape":"s12", "cells":["a","b"]},
{"op":"delete-col", "slide":3, "shape":"s12", "col":1}
]}
Key semantics (details in docs):
{"text":"Big","font_size":28}), or "runs" for mixed in-paragraph formatting. Table cells: add "cell":[row,col]."name" lets later ops in the same patch target the shape it creates.fix repair the overflow.When a slide should be DESIGNED from scratch — free-form layout, no styled donor to duplicate — write it as HTML/CSS and compile it into a patch. The browser is used as a measuring engine; the output is ordinary deck.py ops.
Before writing any slide HTML, read designing-slides.md — how to design for this medium: subject-derived palettes, refusing the default AI-deck looks, the token plan, projection type sizes, and what survives compilation. The pipeline below is mechanical; that file is taste.
python scripts/html2patch.py slide.html --deck deck.pptx --layout Blank -o patch.json
python scripts/deck.py deck.pptx apply patch.json -o out.pptx --render img/
<body> is the slide at 96px/inch: 16:9 → width:1280px; height:720px.
Content overflowing the body is a compile error.<p>, <h1>–<h6>, <ul>/<ol> (numbered), <table>, or
any element with inline-only content (figcaption, blockquote…). Divs with
background / border / border-radius / linear-gradient become styled rects;
<img> becomes a picture (local files only; object-fit: cover becomes a
real crop); <table> becomes a real table with per-cell fills and measured
column widths.<b>/<i>/<u>/<span style> become formatted runs; <a href>
becomes a real hyperlink. CSS padding
maps to text insets; text-transform, transform:rotate, and vertical
writing-mode are honored. Use installed fonts (Arial, Georgia, …).add-slide, --layout picks
the template layout); --slide N targets an existing slide instead. Multiple
files compile into ONE atomic patch.--fix first — geometry is browser-measured,
so look at the render before repairing; run fix only if the render shows
a real problem.covered_by flag on display-size text without
zooming that exact shape: render --slide N --crop l,t,w,h --scale 2.
Serif faces wrap differently in PowerPoint than in the browser — a clipped
last line is invisible at thumbnail size, especially when it falls behind
a picture.pip install playwright && playwright install chromium.python scripts/deck.py deck.pptx slides 0,3,3,5 -o out.pptx # keep these, in this order; repeat = duplicate
python scripts/deck.py deck.pptx merge module.pptx --slides 0,2 --at 12 -o out.pptx
python scripts/deck.py deck.pptx merge --list-layouts # choose a layout for imported slides
slides the template down to the target slide sequence (duplicating repeated layouts).merge in any reusable modules.replace-text patch for global renames (scope master catches footers).inspect --slide N for shape ids, then set-text / swap-image only what you name — nothing else is touched.apply --fix --render img/ and look at every touched slide.render -o img/ --slide 3,7 — JPGs named slide-<index>.jpg; --crop l,t,w,h --scale 2 zooms a region (inches, same coordinates as inspect). Hidden slides render only when explicitly listed.diff other.pptx — text/geometry/media/notes changelog without rendering.python scripts/thumbnail.py deck.pptx --cols 4 (optional second arg = output filename prefix).When no op expresses the change (animations, exotic effects):
python scripts/deck.py deck.pptx xml get --slide 5 -o slide5.xml # pretty-printed, editable
python scripts/deck.py deck.pptx xml set slide5.xml --slide 5 -o out.pptx # parse-checked, lint-checked
Out of scope by design (use the escape hatch or PowerPoint itself): creating native charts, shape animations (slide transitions ARE covered — set-slide "transition"; verify them with inspect/diff, since renders are static), embedded video/OLE, merged table cells.
python-pptx and Pillow (pip install python-pptx Pillow)render and thumbnails: LibreOffice (soffice) and Poppler (pdftoppm)