Skip to content
Content
Skill

/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;

From plugin
hands-on-deck
2021 skill
Install
$ npx -y skills add EveryInc/hands-on-deck --skill hands-on-deck --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/hands-on-deck

Context preview

The summary Claude sees to decide when to auto-load this skill.

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;

SKILL.md

hands-on-deck.SKILL.md
name: hands-on-deck
description: "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."

hands-on-deck — agent-native PPTX manipulation

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):

  • ALL slide indices are 0-based, everywhere. Shapes are addressed by stable native ids (`s12`) or unique shape name.
  • Positions and sizes are inches from the slide's top-left.
  • Patches are atomic: every op is pre-validated (all errors reported at once, with the slide's real shape listing), then applied all-or-nothing.

**Full reference**: `python scripts/deck.py docs` — prints every op with semantics and recipes; needs no file. Read it before writing your first patch.

The edit loop

# 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.

Patch ops at a glance

{"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, "anchor":"MIDDLE"},
  {"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`):

  • **Vertical centering is `anchor`, not `alignment`**: `alignment` (set-text) is HORIZONTAL; to center text in a box taller than the text, set `"anchor":"MIDDLE"` (TOP|MIDDLE|BOTTOM) on set-style or set-text. `inspect` reports it when it's not the default top. html2patch sets it automatically from the slide's CSS (flex/grid centering).
  • **set-text inherits formatting**: new paragraph *i* inherits ALL formatting of old paragraph *i* — pass plain strings for routine replacement. Pass objects to override (`{"text":"Big","font_size":28}`), or `"runs"` for mixed in-paragraph formatting. Table cells: add `"cell":[row,col]`.
  • **Prefer duplicate/copy-shape over add-shape** when a styled donor exists — new shapes start from PowerPoint defaults, not the deck's design language.
  • **add-shape `"name"`** lets later ops in the same patch target the shape it creates.
  • **Transitions only on request**: never add slide transitions unless the user explicitly asks — applied uninvited or inconsistently they're annoying, not polish. When asked, default to one subtle type (fade) across the whole deck.
  • **Alignment is linted, advisory**: `inspect`/`apply` report a `misaligned` issue when a shape's load-bearing edge sits a hair (0.03"–0.15") off a gridline ≥3 other shapes share — the near-miss that reads as sloppy. Act on it (move/resize the edge to the named coordinate) or ignore it: intentional asymmetry is real, so it never fails the build, and apply reports only a *newly introduced* near-miss.
  • Keep new text comparable in length to the old, or let `fix` repair the overflow.

Creating slides from HTML (html2patch)

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 o

Read more
Ships withhands-on-deck

Agent-native PowerPoint manipulation. One CLI — deck.py — lets AI agents inspect, edit, create, and verify .pptx files with the fidelity of a human operator: atomic JSON patches in, linted decks out.

Get the whole plugin
Stats
202
Stars
14
Forks
Active
Maintenance
Python
Language
MIT
License
5d ago
Last commit
2mo ago
Created

Repo: EveryInc/hands-on-deck