From beautiful-pptx
.pptx/슬라이드/덱/발표자료를 만들거나 편집·읽을 때 발동. "deck", "slides", "presentation", ".pptx", "발표자료", "PPT 만들어줘", "슬라이드로 정리", "피치덱", "디펜스 슬라이드" 등이 언급되면 사용. 신규 생성(스펙·마크다운→pptxgenjs 빌드), 회사 템플릿 편집(Anthropic office 스크립트), 기존 .pptx 읽기(markitdown) 세 갈래를 모두 처리한다.
How this skill is triggered — by the user, by Claude, or both
Slash command
/beautiful-pptx:beautiful-pptxThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
발표 덱을 코드로 생성·편집·검수하는 스킬. 엔진은 **pptxgenjs**. 디자인은 WCAG·Tufte·assertion-evidence 같은 정량 규칙을 코드 린트로 박제해서, "AI 티 나는 못생긴 슬라이드"를 생성 단계에서 막는다.
CONTRACT.mdDESIGN.mdPRESETS.mddeck.jsexamples/cot-demo.jsonexamples/defense.jsonexamples/example.jsonexamples/exec.jsonexamples/pitch.jsonexamples/research-talk.jsonlib/assets.jslib/build.jslib/components.jslib/core.jslib/imagegen.jslib/presets.jslib/tokens.jspackage-lock.jsonpackage.jsonscripts/README.md발표 덱을 코드로 생성·편집·검수하는 스킬. 엔진은 pptxgenjs. 디자인은 WCAG·Tufte·assertion-evidence 같은 정량 규칙을 코드 린트로 박제해서, "AI 티 나는 못생긴 슬라이드"를 생성 단계에서 막는다.
상세 규율은 곁의 두 문서로 분리:
| 길 | 언제 | 무엇으로 |
|---|---|---|
| (A) 신규 생성 | "처음부터 만들어줘", 내용·주제만 있을 때 | 개요 → deckSpec JSON 또는 마크다운 → deck.js build (pptxgenjs) |
| (B) 템플릿 편집 | 회사·기존 .pptx 양식을 채우거나 고칠 때 | Anthropic office/ 스크립트(unpack→편집→clean→pack). 있으면 호출, 없으면 (A)로 폴백 |
| (C) 읽기 | 기존 .pptx 내용을 텍스트로 뽑을 때 | markitdown deck.pptx (있으면). 없으면 unpack 후 XML 텍스트 추출 |
대부분 요청은 (A). 사용자가 "이 템플릿에 맞춰" / 특정 .pptx를 주면 (B). "이 발표 내용 요약해줘"면 (C).
핵심 원칙: 발표 덱은 사용자와 함께 설계하는 것이지, 주제만 받고 얕게 찍어내는 게 아니다. 특히 논문·기술 내용은 8~12장으로 절대 다 못 담는다 — 깊이를 먼저 합의한다.
사용자가 안 알려준 항목은 AskUserQuestion으로 묻되, 각 선택지에 가이드라인을 붙여 준다(karpathy식 — 그냥 묻지 말고 권고를 함께). 파악할 것:
가이드라인 예시(이렇게 권고하며 묻는다): "논문 발표면 정밀(25~35장)을 권합니다 — 8장으론 방법·결과를 제대로 못 보여줍니다. 핵심 결과 그림은 한 장에 하나씩(assertion-evidence), 짧으면 백업으로 빼고요. 어느 깊이로 갈까요?"
합의한 깊이·프리셋으로 슬라이드별 제목 + 유형을 표로 제시(아직 빌드 X). 정밀 깊이면 한 섹션을 한 장에 욱여넣지 말고 여러 장으로 펼친다 — 예: 방법을 방법 개요 → 세부 단계1 → 세부 단계2 → 직관 그림 4장으로, 결과는 그림 하나당 슬라이드 하나. "제목 스택 테스트"(제목만 읽어도 논리 성립)로 점검하고 사용자가 수정·승인.
deck.js build. 반환에 린트 경고 배열이 온다.개요·인테이크 단계를 건너뛰지 마라. "그냥 빨리"라고 해도 깊이 한 번, 슬라이드 제목 목록 한 번은 확인받고 간다.
엔진이 전역 설치라 NODE_PATH를 잡아준다. 또는 스킬 폴더에서 npm install 한 번 하면 로컬 resolve.
# 전역 설치 resolve
NODE_PATH=$(npm root -g) node deck.js build spec.json out.pptx
# 또는 스킬 폴더에서 로컬 설치 후
cd ~/.claude/skills/beautiful-pptx && npm install
node deck.js build spec.json out.pptx
# 엔진 점검(예제 스펙으로 빌드)
node deck.js smoke
build는 {path, lint}를 반환. lint는 [{rule, level, msg}] 배열 — level:'fail'이 하나라도 있으면 고치고 다시 빌드한다.
공개 입력은 이 JSON 하나(CONTRACT §5):
{
"theme": "slate", "mode": "light",
"preset": "research-talk", "layout": "16x9",
"slides": [
{ "type": "cover", "title": "...", "subtitle": "...", "meta": "발표자·날짜", "notes": "..." },
{ "type": "keymsg", "title": "X는 Y 조건에서 Z만큼 개선된다", "chart": {...}, "source": "..." },
{ "type": "kpi", "title": "...", "items": [{ "value": "37%", "label": "...", "interp": "...", "color": "ok" }] },
{ "type": "chart", "title": "...", "chartType": "bar", "data": [...], "takeaway": "so-what 한 줄", "source": "..." },
{ "type": "closing", "title": "감사합니다 / Q&A", "contact": "..." }
]
}
마크다운 입력도 받는다: parseDeck(md) 가 H1=섹션, H2=슬라이드, 표=chart/kpi 후보, frontmatter=theme/preset/layout으로 변환. 유형이 비면 chooseLayout이 휴리스틱으로 채운다(숫자 1~2개→kpi, A vs B→compare, 연도 나열→timeline, 인용부호→quote, 그 외→keymsg).
cover 표지 · section 섹션 구분 · keymsg 핵심 메시지(assertion-evidence) · kpi 수치 카드 · chart 차트+so-what · compare 2단 비교 · timeline 타임라인 · process 프로세스 박스 · quote 인용 · closing 마무리 · backup 백업.
각 유형의 좌표·구조는 DESIGN.md 아키타입 9종 참고.
지킬 것만 추리면:
grid/col()에서 산출.| 프리셋 | 언제 | 논리 | 제목 스타일 | 분량 |
|---|---|---|---|---|
research-talk | 학회 구두발표(12~15분) | 귀납(결론 끝) | assertion(문장) | 12~15장 |
defense | 박사·석사 디펜스/심사 | 귀납·Swath&Dive | assertion | 25~35장 |
exec | 임원 보고 | 연역(답 먼저) | action title(동사) | 8~15장 |
pitch | 투자 피치덱 | 연역·내러티브 | 메시지·임팩트 | 10~12장 |
핵심 갈림: 연구/학술은 근거를 쌓아 마지막에 결론(귀납·assertion), 비즈니스는 답을 먼저 놓고 근거로 내려간다(연역·action title). 프리셋이 슬라이드 시퀀스를 골격으로 깔아준다.
빌드 직후 lint가 자동으로 슬라이드를 스캔한다. 규칙 ID(level):
L_ELEMENTS(fail) 시각요소 >6 · L_FONT(fail) 본문 <18pt / 제목 <24ptL_TITLELINE(fail) 제목 밑 액센트 라인 · L_CONTRAST(fail) 대비 <4.5:1(대형 bold는 <3)L_TEXTONLY(warn) 시각요소 0 텍스트만 · L_CENTERBODY(warn) 본문 장문 가운데정렬L_ACTIONTITLE(warn) exec/pitch인데 제목이 동사 없는 명사구 · L_DENSITY(warn) 본문 한글 >150자L_SOURCE(warn) chart/kpi인데 source 비어있음fail은 반드시 고친다. warn은 사용자에게 알리고 판단을 맡긴다.
산출 게이트(있으면): pack 검증으로 OOXML 스키마 "새 에러 0"일 때만 방출. 깨진 XML 차단.
렌더한 슬라이드 JPG를 신선한 눈으로 볼 때 체크:
markitdown이나 unpack 텍스트에서 lorem|xxxx|TODO|placeholder grep으로 6번을 자동 탐지.
이런 슬라이드가 나오면 "AI가 만든 티"가 난다. 린트가 잡지만 사람이 한 번 더 본다:
~/.claude/skills/chat-understanding/가 깔려 있으면, 슬라이드 텍스트·스피커노트에 그 스킬의 문체·레벨·AI티 점검을 적용한다. 슬라이드 제목과 노트가 "살펴보겠습니다", "다양한/전반적으로" 같은 AI투를 안 쓰도록, 결론 먼저·숫자 해석 병기 원칙을 따르도록 다듬는다. 없으면 그냥 건너뛴다.
슬라이드에 AI 생성 이미지를 넣으려면 이미지 생성 API 주소만 지정하면 된다. MCP 불필요 — 빌드 엔진이 HTTP로 직접 호출한다.
설정(둘 중 하나):
BP_IMAGE_API_URL(필수) · BP_IMAGE_API_KIND(openai|a1111|comfy|generic, 기본 openai) · BP_IMAGE_API_MODEL · BP_IMAGE_API_KEY."imageApi": { "url":"http://<로컬머신>:<포트>", "kind":"openai", "model":"...", "key":"..." }.사용: 슬라이드 스펙에 "imagePrompt": "..." 를 넣으면 그 프롬프트로 이미지를 생성해 채운다.
cover: 풀블리드 히어로 이미지 + 어두운 오버레이(텍스트 가독성 보장).keymsg 등: 본문 시각 자리에 인라인.# 예: 로컬 머신의 OpenAI 호환 이미지 서버
BP_IMAGE_API_URL=http://192.168.0.10:8000 BP_IMAGE_API_KIND=openai \
node deck.js build spec.json out.pptx
규율(중요): 정확한 숫자·라벨은 imagePrompt에 넣지 마라. 최강 모델(Nano Banana Pro 포함)도 이미지 속 긴·정밀 텍스트는 100% 신뢰 못 한다. 이미지는 히어로·추상 배경·일러스트·개념도에만 쓰고, 수치·차트·제목은 우리 엔진이 진짜 텍스트로 얹는다(정확·편집 가능). 이게 "이쁨 + 정확"의 최적해다.
로컬 모델 권고(2026 기준): 라이선스 자유 = Qwen-Image-2512 + Qwen-Image-Edit-2511(Apache). 텍스트·디자인 최강 = Ideogram 4.0(가중치 비상업). 히어로·멀티참조 = FLUX.2 dev(비상업). ComfyUI/SD-WebUI를 OpenAI 호환 또는 a1111 형식으로 노출하면 위 kind로 바로 붙는다.
이 환경은 헤드리스 서버다. 빌드한 .pptx는 화면에 안 뜬다. 사용자에게 경로를 알려주고 scp/다운로드로 받으라고 안내한다:
# 예: 로컬로 내려받기
scp user@server:~/.claude/skills/beautiful-pptx/out.pptx ./
QA용 PDF/JPG를 만들었으면 그 경로도 같이 알려준다.
npx claudepluginhub security-engineer/beautiful-pptx --plugin beautiful-pptxScans the codebase for `ponytail:` comments and compiles a debt ledger of deliberate shortcuts and deferrals, flagging entries with no upgrade path.