A Claude Code plugin that parses PPTX templates into markdown templates, generates editable PPTX files from markdown, and supports interactive slide revision — all without image-based rendering. Markdown is the single source of truth.
- Features
- Overview
- Installation
- Quick Start
- Pipeline Architecture
- Skills Reference
- Markdown Format
- Language Support
- Dependencies
- Complete End-to-End Example
- Output Artifact Verification
- Environment Variables
- Contributing
- License
- Template Parsing — Reads a PPTX template and outputs a structured markdown file with placeholder annotations (
<!-- ph:idx type:TYPE -->) - PPTX Generation — Converts markdown back to a PPTX that faithfully reproduces the template's visual layout
- Interactive Revision — 3-step interview workflow to revise specific slides and regenerate PPTX
- Rich Content Support — Tables, charts (bar/pie/line), images, multi-column layouts
- Bilingual Output — Korean (
ko) and English (en) guide comments viaLANGenv variable - 100% Editable — All content is inserted as native python-pptx objects (no image rendering)
agent4ppt is a Claude Code / OpenClaw plugin that solves a common problem for researchers, engineers, and presenters: maintaining a PPTX slide deck through iterations is tedious and error-prone when the content lives inside binary files.
- Editing a PPTX template manually is time-consuming and breaks consistency
- AI-assisted slide generation often relies on screenshot/image pipelines that produce non-editable output
- No reliable way to version-control slide content alongside code or documentation
agent4ppt introduces a three-skill pipeline where a human-readable markdown file is the single source of truth for all slide content:
PPTX Template → /parse-ppt-template → Markdown Template
↓ (edit content)
Markdown Content
↓
/generate-ppt → PPTX Output (editable)
/revise-ppt → Interactive revision loop
| Principle | Description |
|---|---|
| No image rendering | All PPTX objects are created via python-pptx native API. Output is always fully editable in PowerPoint / LibreOffice Impress. |
| Markdown as truth | Slide content, layout metadata, and revision history all live in a .md file. The PPTX template is referenced only, never modified. |
| Stable placeholder identity | Placeholders are identified by idx (the python-pptx integer index), making round-trips and re-ordering slides safe. |
| Bilingual by design | All user-facing strings (guide comments, prompts, error messages) support Korean and English via the LANG environment variable. |
| Graceful degradation | Optional LibreOffice previews enhance the revision workflow but are never required; the core pipeline runs with Python alone. When a body placeholder is missing from the layout, content is inserted via a textbox fallback (or image fallback for image content). |
- Researchers who want to generate slide decks from structured markdown notes
- Engineers who need to automate slide generation in CI/CD or scripted workflows
- Claude Code / OpenClaw users who want a composable skill that integrates naturally with AI-assisted workflows
- Anyone who prefers editing slides as text rather than clicking through PowerPoint
Before installing agent4ppt, ensure your environment meets these requirements:
| Requirement | Version | Notes |
|---|---|---|
| Python | ≥ 3.10 | Required. Check: python3 --version |
| pip | any | Required. Check: pip --version |
| python-pptx | ≥ 0.6.21 | Auto-installed by scripts/install.sh |
| pyyaml | ≥ 6.0 | Auto-installed by scripts/install.sh |
| markdown-it-py | ≥ 3.0 | Auto-installed by scripts/install.sh |
| LibreOffice | any | (Optional) PNG slide previews in /revise-ppt |
The three Python packages (python-pptx, pyyaml, markdown-it-py) are installed automatically by the bundled installer script. Only Python ≥ 3.10 and pip must be present beforehand.
No image-based rendering: agent4ppt uses
python-pptxdirectly to write native PPTX objects (text frames, tables, charts). The output is always fully editable in PowerPoint or LibreOffice Impress.
Install agent4ppt in two commands:
claude plugin marketplace add JinwangMok/agent4ppt
claude plugin install agent4pptThe installer automatically runs scripts/install.sh which checks Python ≥ 3.10, installs the three required packages, and reports the optional LibreOffice dependency.
After installation, the three skills (/parse-ppt-template, /generate-ppt, /revise-ppt) are available directly in your Claude Code session.
agent4ppt follows the Agent Skills standard (SKILL.md format), making it compatible with OpenClaw and other Agent Skills-compatible runtimes.
Installation steps:
# Step 1: Clone the repository
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
# Step 2: Install Python dependencies
bash scripts/install.sh --no-register
# Step 3: Register with OpenClaw (point to the cloned directory)
# openclaw skill add ./agent4ppt
# — or — add the GitHub URL to your OpenClaw skill sources:
# openclaw skill add https://github.com/JinwangMok/agent4pptOpenClaw discovers skills automatically via the SKILL.md file in the repository root. Each skill entry defines:
| SKILL.md field | Value |
|---|---|
trigger |
/parse-ppt-template, /generate-ppt, /revise-ppt |
entry |
skills/<name>/<script>.py |
requires_python |
>=3.10 |
dependencies |
python-pptx>=0.6.21, pyyaml>=6.0, markdown-it-py>=3.0 |
After registration, the three slash commands are available inside your OpenClaw session.
agent4ppt is also compatible with Codex CLI. After cloning and installing dependencies:
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
bash scripts/install.sh
# Run skills directly via Python
python skills/parse-ppt-template/parse_template.py template.pptx --output slides.md
python skills/generate-ppt/generate_ppt.py slides.md --output output.pptx
python skills/revise-ppt/revise_ppt.py slides.mdIf you prefer manual setup without any agent runtime:
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
pip install python-pptx pyyaml markdown-it-py1. Verify the installation
After installing via any method above, confirm all required dependencies are available:
python3 -c "import pptx, yaml; from markdown_it import MarkdownIt; print('agent4ppt: all dependencies OK')"You should see: agent4ppt: all dependencies OK
2. Configure output language
agent4ppt reads the LANG POSIX environment variable to choose Korean or English for guide comments and prompts. Set it once in your shell profile:
# Korean output (add to ~/.bashrc or ~/.zshrc)
export LANG=ko_KR.UTF-8
# English output (default — no explicit setting needed)
export LANG=en_US.UTF-8You can also override the language per-invocation:
/parse-ppt-template template.pptx --lang ko # Korean for this run only
/revise-ppt slides.md --lang en # English for this run onlyLanguage priority: --lang flag > frontmatter lang: field > $LANG environment variable > en (default)
3. Optional: enable PNG slide previews (LibreOffice)
The /revise-ppt skill can show PNG slide thumbnails during the interactive review workflow. This requires LibreOffice:
# Ubuntu / Debian
sudo apt install libreoffice
# macOS (Homebrew)
brew install --cask libreofficeWithout LibreOffice the skill degrades gracefully to a plain-text slide summary — the core parse/generate/revise functionality is unaffected.
4. Claude Code plugin settings (optional)
agent4ppt's behavior is fully controlled via command-line arguments and the LANG environment variable. No changes to ~/.claude/settings.json are required. To set a persistent language preference inside Claude Code:
// ~/.claude/settings.json
{
"env": {
"LANG": "ko_KR.UTF-8"
}
}/parse-ppt-template my_template.pptx
# → Generates my_template.mdOpen my_template.md and fill in your content between the placeholder comments.
/generate-ppt my_template.md
# → Generates output.pptx (or the fname from frontmatter)/revise-ppt my_template.mdagent4ppt is built around a markdown-first pipeline. The markdown file is the single source of truth; the PPTX template is referenced once in the YAML frontmatter (template field) and never modified.
┌─────────────────────────────────────────────────────────────────┐
│ agent4ppt Pipeline │
│ │
│ PPTX Template │
│ (read-only) │
│ │ │
│ ▼ /parse-ppt-template │
│ Markdown Template ──────────────────────────────────────────► │
│ (YAML frontmatter + slide sections + <!-- ph:idx --> comments) │
│ │ │
│ │ (user fills content) │
│ ▼ │
│ Markdown Content File │
│ │ ┌──────────────────────────────────┐ │
│ ├── /generate-ppt ─► PPTX Output │ │
│ │ │ (uses template from frontmatter) │ │
│ │ └──────────────────────────────────┘ │
│ │ │
│ └── /revise-ppt ──► (3-step interview) │
│ │ │
│ ├── update markdown in-place │
│ └── invoke /generate-ppt │
└─────────────────────────────────────────────────────────────────┘
| Stage | Input | Output | Key operation |
|---|---|---|---|
| parse | *.pptx template |
*.md with <!-- ph:idx type:TYPE --> |
python-pptx reads slide layouts; idx-based placeholder mapping written to markdown |
| generate | *.md content file |
*.pptx presentation |
Frontmatter template field resolves the source PPTX; each ph:idx block written to the matching placeholder |
| revise | *.md content file |
updated *.md + *.pptx |
Interactive 3-step interview patches the markdown, then delegates to generate |
templatein frontmatter is authoritative — The path stored intemplate:inside the markdown frontmatter is the only reference to the source PPTX. All three skills resolve the template from this field; there is no separate configuration file.- Placeholder identity = python-pptx
idx— Placeholders are identified by their integeridxas returned by python-pptx, not by position or name. This makes re-ordering slides safe and ensures stable round-trips. - No image rendering — All content is inserted as native python-pptx objects (text frames, tables, charts). The PPTX output is fully editable in PowerPoint / LibreOffice Impress.
- PNG preview is optional — LibreOffice headless provides visual previews in the
revise-pptworkflow. The skill degrades gracefully to a plain-text slide summary when LibreOffice is absent. - Markdown is lossless — A
parse → edit → generateround-trip produces a PPTX that faithfully reproduces the template layout. Re-parsing the generated PPTX would yield an equivalent markdown. - Preserved passthrough — Slide transitions, animations, speaker notes, and master slide properties are not modeled in markdown and are not destroyed; they survive the parse → generate roundtrip unchanged.
Each placeholder annotation encodes two distinct concerns:
| Concern | Attribute | Description |
|---|---|---|
| Template contract | type:TYPE |
What a placeholder demands — the kind of content it accepts (title, body, picture, chart, etc.). This is the binding contract between markdown and the PPTX template. |
| Spatial layout | pos:(x,y) size:WxH |
Where the placeholder lives on the slide. Informational metadata only; never used to reposition content. |
generate-ppt only reads ph:idx and type:; the pos: and size: values from parse-ppt-template output are silently carried through and ignored during generation. They serve as documentation for the human editor.
Each pipeline stage produces a verifiable artifact:
| Stage | Artifact | Validation |
|---|---|---|
| parse | *.md file |
YAML frontmatter template field present; <!-- ph:idx --> comments match template placeholder count |
| generate | *.pptx file |
python-pptx can open the file; slide count matches markdown --- separator count |
| revise | updated *.md + *.pptx |
Revision comments resolved or annotated; PPTX timestamp newer than original |
Parse a PPTX template file and generate a markdown template with placeholder annotations. Placeholders are identified by python-pptx idx-based indexing and annotated with <!-- ph:idx type:TYPE --> HTML comments.
Usage:
/parse-ppt-template <pptx_file> [--output <output.md>] [--lang ko|en] [--layouts-only]
Executed via: python skills/parse-ppt-template/parse_template.py
Arguments:
| Argument | Required | Default | Description |
|---|---|---|---|
pptx_file |
✅ | — | Path to the PPTX template file |
--output, -o |
❌ | <input>.md |
Output path for the generated markdown template |
--lang, -l |
❌ | $LANG or en |
Language for guide comments in the output (ko | en) |
--layouts-only |
❌ | false |
Generate one section per layout definition instead of per slide |
Returns: A markdown file written to --output.
| Exit code | Meaning |
|---|---|
0 |
Success — markdown written and all verification checks passed |
1 |
Input/IO error (file not found, missing dependency, etc.) |
2 |
Verification failure — markdown was written but failed structural invariant checks |
Success markers (machine-checkable):
[agent4ppt] Markdown template written → <path>
[agent4ppt] Verification passed ✓ (N section(s), template_path confirmed, idx annotations present)
Output format:
The generated markdown file contains:
- YAML frontmatter —
template,fname,title,subTitle,date,author,langfields - Slide sections separated by
--- - Layout indicator
> layout: Nat the top of each slide section - Layout name comment
<!-- layout_name: NAME -->(informational) - Placeholder annotations
<!-- ph:idx type:TYPE pos:(x,y) size:WxH -->with spatial metadata - Guide comments
<!-- Enter the ... -->(in the selected language) explaining each placeholder - Content placeholders with example content ready to fill
Placeholder type values:
| Type | python-pptx placeholder kind |
|---|---|
title |
Title |
center_title |
Center Title |
subtitle |
Subtitle |
body |
Body |
object |
Object (generic) |
picture |
Picture |
table |
Table |
chart |
Chart / diagram |
media |
Media clip |
ftr |
Footer |
dt |
Date |
sldnum |
Slide number |
Examples:
# Basic — output written to same directory as template
/parse-ppt-template "GIST NetAI PPT Theme.pptx"
# Specify output path and Korean guide comments
/parse-ppt-template "GIST NetAI PPT Theme.pptx" --output slides_template.md --lang ko
# One section per layout (for templates with no slide content)
/parse-ppt-template my_template.pptx --layouts-only --output layouts.mdExample output:
---
template: ./GIST NetAI PPT Theme.pptx
fname: output.pptx
title: ""
subTitle: ""
date: ""
author: ""
lang: en
---
> layout: 0
<!-- layout_name: Title Slide -->
<!-- ph:0 type:center_title pos:(0.9167",1.75") size:7.6548"×0.7547" -->
<!-- Enter the centered slide title -->
# Slide Title
<!-- ph:1 type:subtitle pos:(0.9167",2.6495") size:5.588"×0.8832" -->
<!-- Enter the subtitle -->
Subtitle text here
---
> layout: 1
<!-- ph:0 type:title pos:(0.4583",0.25") size:8.5"×1.2" -->
<!-- Enter the slide title -->
# Section Header
<!-- ph:1 type:body pos:(0.4583",1.5") size:8.5"×4.5" -->
<!-- Enter the main body content. Supports bullets, bold, italic. -->
- Bullet one
- Bullet twoError handling:
| Condition | Behaviour |
|---|---|
pptx_file not found |
Exits 1, prints error to stderr |
File has no .pptx extension |
Warning printed, continues |
Missing dependency (python-pptx, pyyaml) |
Exits 1, prints install instructions |
| PPTX file is corrupt or unreadable | Exits 1, prints error to stderr |
| Structural verification fails after writing | Exits 2, prints failure details to stderr |
Generate an editable PPTX file from a markdown file. Reads the PPTX template path from the markdown frontmatter, maps each <!-- ph:idx --> block to the corresponding placeholder, and converts markdown tables, chart YAML blocks, and images to native python-pptx objects.
Usage:
/generate-ppt <markdown_file> [--output <output.pptx>] [--lang ko|en] [--dry-run]
Executed via: python skills/generate-ppt/generate_ppt.py
Arguments:
| Argument | Required | Default | Description |
|---|---|---|---|
markdown_file |
✅ | — | Path to the markdown content file |
--output, -o |
❌ | frontmatter.fname or <input>.pptx |
Output PPTX file path |
--lang, -l |
❌ | $LANG or en |
Language for warning/info messages (ko | en) |
--dry-run |
❌ | false |
Validate inputs and build slides in memory without writing the PPTX file |
Returns: A PPTX file at the output path. Exit code 0 on success, 1 on error.
Success marker (machine-checkable):
[agent4ppt] PPTX generated → <path>
Frontmatter fields:
| Field | Required | Description |
|---|---|---|
template |
✅ | Relative or absolute path to the PPTX template |
fname |
❌ | Default output filename (e.g. output.pptx) |
title |
❌ | Presentation title (metadata) |
subTitle |
❌ | Presentation subtitle (metadata) |
date |
❌ | Presentation date string |
author |
❌ | Author name |
lang |
❌ | Language override (en or ko). Takes precedence over $LANG and --lang. |
Slide section structure:
> layout: N ← layout index (0-based), required
<!-- ph:0 type:title --> ← placeholder annotation (idx=0, type=title)
# My Slide Title ← content for this placeholder
<!-- ph:1 type:body -->
- Bullet one
- Bullet two
- **Bold text** and *italic*Supported content types:
| Type | Syntax | Notes |
|---|---|---|
| Plain text | Any text | Written as-is |
| Headings | # Title, ## Sub |
Leading # stripped for title/subtitle placeholders |
| Bullet list | - item or * item |
Up to 9 indent levels |
| Numbered list | 1. item |
Treated as bullets |
| Bold | **text** |
run.font.bold = True |
| Italic | *text* |
run.font.italic = True |
| Link | [text](url) |
Underlined text; hyperlink relationship not inserted |
| Image |  |
For picture or object placeholders |
| Table | GFM markdown table | First row becomes bold header |
| Chart | ```chart YAML block |
Bar, column, line, pie charts |
| Multi-column | ||| separator |
Splits content; first column fills the placeholder |
Chart block syntax:
<!-- ph:2 type:chart -->
```chart
type: bar # bar | column | line | pie
title: My Chart
categories: [Q1, Q2, Q3, Q4]
series:
- name: Revenue
values: [100, 150, 120, 200]
- name: Expenses
values: [80, 90, 100, 110]
```Examples:
# Generate PPTX — output filename comes from frontmatter fname field
/generate-ppt slides.md
# Override output path
/generate-ppt slides.md --output final_presentation.pptx
# Korean messages
/generate-ppt slides.md --lang ko
# Dry-run: validate markdown structure without writing a PPTX file
/generate-ppt slides.md --dry-runFull markdown example:
---
template: ./GIST NetAI PPT Theme.pptx
fname: my_presentation.pptx
title: "Research Overview"
subTitle: "GIST NetAI Lab"
date: "2026-03-22"
author: "Jinwang Mok"
lang: en
---
> layout: 0
<!-- ph:0 type:title -->
# Research Overview
<!-- ph:1 type:subtitle -->
GIST NetAI Lab · 2026
---
> layout: 2
<!-- ph:0 type:title -->
# Benchmark Results
<!-- ph:1 type:table -->
| Model | Accuracy | Latency (ms) |
|-------|----------|--------------|
| Ours | 94.2% | 12 |
| Base | 88.7% | 15 |
---
> layout: 3
<!-- ph:0 type:title -->
# Training Loss
<!-- ph:1 type:chart -->
```chart
type: line
title: Training Loss
categories: [Epoch 1, Epoch 2, Epoch 3, Epoch 4, Epoch 5]
series:
- name: Train
values: [1.8, 1.2, 0.9, 0.7, 0.6]
- name: Val
values: [2.0, 1.5, 1.1, 0.9, 0.8]
**Error handling:**
| Condition | Behaviour |
|-----------|-----------|
| `markdown_file` not found | Exits 1, prints error to stderr |
| `template` frontmatter field missing | Exits 1, prints error to stderr |
| Template PPTX file not found | Exits 1, prints error to stderr |
| Layout index out of range | Warning printed, uses layout 0 |
| Placeholder `idx` not found in slide | Warning printed, placeholder skipped |
| Image file not found | Warning printed, placeholder left empty |
| Invalid chart YAML | Warning printed, placeholder left empty |
| Body placeholder not in layout | Warning printed, content inserted via textbox/image fallback |
| Missing dependencies | Exits 1, prints install instructions |
---
### /revise-ppt
Interactively revise an existing presentation through a **3-step interview workflow**: select target slides, describe changes per slide, apply edits to the markdown source and regenerate the PPTX. Optionally renders PNG slide previews via LibreOffice headless; falls back to markdown text when LibreOffice is unavailable.
**Usage:**
/revise-ppt <markdown_file> [--pptx <pptx_file>] [--output <output.pptx>] [--lang ko|en]
Executed via: `python skills/revise-ppt/revise_ppt.py`
**Arguments:**
| Argument | Required | Default | Description |
|----------|----------|---------|-------------|
| `markdown_file` | ✅ | — | Path to the markdown source file to revise (the single source of truth) |
| `--pptx` | ❌ | derived from `frontmatter.fname` | Path to the existing PPTX file used for PNG preview generation |
| `--output`, `-o` | ❌ | `frontmatter.fname` or `<markdown>.pptx` | Output path for the regenerated PPTX |
| `--lang`, `-l` | ❌ | `$LANG` or `en` | Language for interview prompts (`ko` \| `en`) |
**Returns:** The `markdown_file` is **updated in place**. A new PPTX is generated by delegating to `generate-ppt`. Exit code `0` on success, `1` on error.
**Success markers:**
[agent4ppt] PPTX generated → ← emitted by the generate-ppt subprocess Revision complete! Updated file: ← emitted by revise-ppt
**Workflow — 3 steps:**
**Step 1 — Select target slides**
=== Slide Revision Workflow === Your presentation has 8 slide(s).
STEP 1: Which slides would you like to revise? Enter slide numbers separated by commas (e.g. 1,3,5), a range (e.g. 2-4), or 'all':
2,4-6
**Selection syntax:**
| Input | Meaning |
|-------|---------|
| `1,3,5` | Slides 1, 3, and 5 |
| `2-4` | Slides 2, 3, and 4 |
| `2~4` | Same as `2-4` |
| `all` | All slides |
| `*` | All slides |
| `모두` | All slides (Korean alias) |
**Step 2 — Describe changes per slide**
STEP 2: Let's go through each selected slide.
--- Slide 2 (layout: 1) --- Slide 2 preview: /path/to/my_presentation_previews/slide_2.png
Describe your changes. Examples:
- Change title to 'New Title'
- Replace bullet 2 with 'Updated content'
- Change layout to layout 3
- Replace chart with new data
- Add image path/to/image.png Your instructions for slide 2:
Change title to 'Updated Results'
**Supported instruction patterns (applied automatically):**
| Pattern | Example | Effect |
|---------|---------|--------|
| Change title | `Change title to 'New Title'` | Replaces title placeholder heading |
| Change layout | `Change layout to 3` | Updates `> layout: N` in the section |
| Free-form | Any other text | Appended as `<!-- REVISION: ... -->` comment for manual review |
**Step 3 — Apply and regenerate**
STEP 3: Applying changes and regenerating PPTX... Applying changes to slide 2... Applying changes to slide 4... Regenerating PPTX... [agent4ppt] PPTX generated → ./my_presentation.pptx
Revision complete! Updated file: ./my_presentation.pptx Markdown updated: ./slides.md PPTX regenerated: ./my_presentation.pptx
**Revision state tracking:**
A JSON state file `<markdown_stem>_revision_state.json` is created after Step 1 and updated after Step 3:
```json
{
"markdown_path": "/absolute/path/to/slides.md",
"pptx_path": "/absolute/path/to/output.pptx",
"iteration_count": 1
}
iteration_countincrements after each successful revision cycle- State persists across multiple invocations for resumable multi-round editing
- File path is deterministic:
<markdown_stem>_revision_state.jsonin the same directory as the markdown file
PNG preview:
When LibreOffice is installed, slide previews are generated to a deterministic directory (<pptx_stem>_previews/) next to the PPTX file — verifiable without prior knowledge of temporary directory names:
libreoffice --headless --convert-to png --outdir <pptx_stem>_previews/ presentation.pptxIf LibreOffice is not found, a plain-text .txt file is written to the same deterministic path with a text summary of the slide's placeholder content. The revise-ppt skill works fully without LibreOffice — only the visual preview is affected.
Install LibreOffice:
# Ubuntu / Debian
sudo apt install libreoffice
# macOS (Homebrew)
brew install --cask libreofficeExamples:
# Standard interactive revision (auto-detects PPTX from frontmatter fname)
/revise-ppt slides.md
# Provide PPTX path explicitly for PNG preview generation
/revise-ppt slides.md --pptx final_presentation.pptx
# Specify explicit output PPTX path
/revise-ppt slides.md --output revised_v2.pptx
# Korean prompts
/revise-ppt slides.md --lang koError handling:
| Condition | Behaviour |
|---|---|
markdown_file not found |
Exits 1, prints error to stderr |
| No slides selected | Exits 0, prints advisory message |
| LibreOffice not found | Warning printed, falls back to text preview |
generate-ppt subprocess fails |
Stderr from subprocess printed, exits 1 |
KeyboardInterrupt (Ctrl-C) |
Exits 0 with [agent4ppt] Cancelled. |
| Missing dependencies | Exits 1, prints install instructions |
The markdown file is the canonical document — not a serialization or export format. All content edits are made in markdown; the PPTX is always regenerated from it. The template: field in YAML frontmatter is the sole authoritative reference to the source PPTX; no secondary path or configuration file exists.
Every markdown file must begin with YAML frontmatter delimited by ---:
| Field | Required | Description |
|---|---|---|
template |
✅ | Path to the source PPTX template. Relative paths are resolved from the markdown file's directory. This is the sole authoritative reference to the source PPTX — no secondary path exists. |
fname |
❌ | Default output PPTX filename (e.g. output.pptx). Overridden by --output. |
title |
❌ | Presentation title (written to PPTX metadata) |
subTitle |
❌ | Presentation subtitle |
date |
❌ | Date string |
author |
❌ | Author name |
lang |
❌ | Language override (en or ko). Takes precedence over $LANG and --lang. |
After the frontmatter, slides are separated by ---. Each slide section begins with a layout reference (> layout: N, 0-based), followed by one or more placeholder blocks:
> layout: 1
<!-- layout_name: Content Slide -->
<!-- ph:0 type:title pos:(0.46",0.25") size:8.5"×1.2" -->
# Slide Title
<!-- ph:1 type:body pos:(0.46",1.5") size:8.5"×4.5" -->
- First bullet point
- Second bullet point
- Nested bullet
- **Bold text** and *italic*Placeholder annotation fields:
| Field | Meaning |
|---|---|
ph:N |
python-pptx placeholder index (idx), 0-based integer |
type:TYPE |
Template contract — the kind of content the placeholder accepts |
pos:(x,y) |
Spatial layout — horizontal and vertical position (informational) |
size:WxH |
Spatial layout — width and height (informational) |
Each placeholder annotation encodes two distinct concerns in a single line:
| Concern | Attribute | Role |
|---|---|---|
| Template contract | type:TYPE |
What content the placeholder accepts. This is the binding semantic contract; it determines which markdown syntax is valid (title/body/picture/chart/table/…). |
| Spatial layout | pos: and size: |
Where the placeholder lives on the slide. Informational metadata preserved passthrough; generate-ppt does not use these values for positioning. |
Below is a complete example showing all supported content types:
---
template: ./my_template.pptx
fname: output.pptx
title: "My Presentation"
subTitle: "2026 Annual Report"
date: "2026-03-22"
author: "Jinwang Mok"
lang: en
---
> layout: 0
<!-- ph:0 type:title -->
# My Presentation
<!-- ph:1 type:body -->
Welcome to the annual report.
---
> layout: 2
<!-- ph:0 type:title -->
# Sales Data
<!-- ph:1 type:table -->
| Quarter | Revenue | Growth |
|---------|---------|--------|
| Q1 | $1.2M | +12% |
| Q2 | $1.5M | +25% |
| Q3 | $1.3M | +8% |
| Q4 | $1.8M | +38% |
<!-- ph:2 type:chart -->
```chart
type: bar
title: Quarterly Revenue
categories: [Q1, Q2, Q3, Q4]
series:
- name: Revenue (M$)
values: [1.2, 1.5, 1.3, 1.8]layout: 3
layout: 4
Left column content
- Item A
- Item B
|||
Right column content
- Item C
- Item D
### Placeholder Types
| `type` | Description |
|--------|-------------|
| `title` | Slide title text box |
| `body` | Main content area (bullets, text) |
| `picture` | Image placeholder |
| `chart` | Chart placeholder |
| `table` | Table placeholder |
| `object` | Generic object / multi-content area |
---
## Language Support
Set the output language for guide comments and prompts:
```bash
# Via environment variable
export LANG=ko # Korean
export LANG=en # English (default)
# Via command-line flag
/parse-ppt-template template.pptx --lang ko
/revise-ppt slides.md --lang en
Language priority: --lang flag > $LANG environment variable > en (default)
pip install python-pptx pyyaml markdown-it-py
# or use the bundled installer:
bash scripts/install.shLibreOffice is required only for the PNG slide preview feature in /revise-ppt. Without it, the skill gracefully falls back to markdown text display.
| Platform | Install Command |
|---|---|
| Ubuntu/Debian | sudo apt install libreoffice |
| macOS (Homebrew) | brew install --cask libreoffice |
| Windows | Download from libreoffice.org |
# 1. Parse the PPTX template into a markdown template
/parse-ppt-template "GIST NetAI PPT Theme.pptx" --output my_talk.md
# 2. Edit my_talk.md — fill in slide content, add tables/charts/images
# (use your editor or ask Claude to fill in the content)
# 3. Generate the PPTX from the markdown
/generate-ppt my_talk.md
# 4. Review the result and interactively revise if needed
/revise-ppt my_talk.mdEach skill emits a machine-readable success marker and exits with code 0. You can verify the pipeline non-interactively:
# Verify parse-ppt-template output
python skills/parse-ppt-template/parse_template.py template.pptx --output out.md
echo "Exit: $?" # 0=success+verified, 2=written but verification failed
grep -q "^template:" out.md && echo "PASS: frontmatter present"
grep -qP "ph:\d+ type:\w+" out.md && echo "PASS: placeholders found"
# Verify generate-ppt output
python skills/generate-ppt/generate_ppt.py out.md --output out.pptx
echo "Exit: $?" # Must be 0
python -c "from pptx import Presentation; p=Presentation('out.pptx'); print('PASS: slides =', len(p.slides))"
# Verify roundtrip fidelity
python -c "
from pptx import Presentation
p = Presentation('out.pptx')
slides_pptx = len(p.slides)
import re
md = open('out.md').read()
body = md.split('---\n', 2)[-1]
slides_md = len(re.split(r'\n---\s*\n', body.strip()))
assert slides_pptx == slides_md, f'Mismatch: pptx={slides_pptx} md={slides_md}'
print('PASS: slide count matches')
"
# Verify revision state (after running /revise-ppt)
python -c "
import json
state = json.load(open('out_revision_state.json'))
assert 'markdown_path' in state
assert 'iteration_count' in state
print('PASS: revision state valid, iteration_count =', state['iteration_count'])
"| Variable | Description |
|---|---|
LANG |
POSIX locale string used to auto-detect output language (e.g. ko_KR.UTF-8 → Korean). Standard system variable; no need to set explicitly on Korean-locale systems. |
Contributions are welcome! agent4ppt is an open-source project and your improvements, bug reports, and ideas help make it better for everyone.
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/<your-username>/agent4ppt.git cd agent4ppt
- Create a branch for your change:
git checkout -b feature/my-improvement
- Install dependencies and run the test suite to confirm everything passes:
bash scripts/install.sh pytest
- Make your changes — add tests for any new functionality
- Verify tests still pass:
pytest --tb=short
- Commit with a clear, descriptive message
- Push your branch and open a Pull Request against
main
| Area | Guideline |
|---|---|
| Code style | Follow PEP 8. Use type hints for public functions. |
| Tests | All new features must include pytest tests under tests/. Maintain ≥ 80 % coverage for changed modules. |
| No image rendering | All PPTX content must be inserted via python-pptx native objects. Image-based rendering PRs will not be merged. |
| Bilingual docs | Any user-facing string additions must include both English (en) and Korean (ko) variants in the i18n dictionaries. |
| Markdown as source of truth | Changes to the markdown schema must be backward-compatible, or include a migration note. |
| Dependencies | New runtime dependencies require a strong justification. Dev-only dependencies are fine. |
Please open a GitHub Issue and include:
- OS and Python version (
python3 --version) - agent4ppt version (see
plugin.json) - The exact command you ran
- Full error output (stdout + stderr)
- Minimal reproducible example (the PPTX template or markdown file if possible)
# Clone and enter the repository
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
# Install runtime dependencies
bash scripts/install.sh
# Install dev extras (pytest, coverage)
pip install pytest pytest-cov
# Run all tests
pytest
# Run with coverage report
pytest --cov=agent4ppt --cov=skills --cov-report=term-missingThis project follows a simple rule: be respectful and constructive. Harassment or discriminatory language in any form will not be tolerated.
MIT License — Copyright (c) 2026 Jinwang Mok
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
See the full license text in LICENSE.
agent4ppt 是一个 Claude Code 插件,可将 PPTX 模板解析为 Markdown 模板,从 Markdown 生成可编辑的 PPTX 文件,并支持交互式幻灯片修订——无需基于图像的渲染。Markdown 是唯一的数据来源(Single Source of Truth)。
- 模板解析 — 读取 PPTX 模板,输出带有占位符注释(
<!-- ph:idx type:TYPE -->)的结构化 Markdown 文件 - PPTX 生成 — 将 Markdown 转换回 PPTX,忠实还原模板的视觉布局
- 交互式修订 — 3步问答工作流,用于修订特定幻灯片并重新生成 PPTX
- 丰富内容支持 — 表格、图表(条形图/饼图/折线图)、图片、多列布局
- 双语输出 — 通过
LANG环境变量支持韩语(ko)和英语(en)指南注释 - 100% 可编辑 — 所有内容均以原生 python-pptx 对象插入(无图像渲染)
使用两行命令安装 agent4ppt:
claude plugin marketplace add JinwangMok/agent4ppt
claude plugin install agent4ppt安装程序自动运行 scripts/install.sh,检查 Python ≥ 3.10,安装三个必需包,并提示可选的 LibreOffice 依赖。
安装后,三个技能(/parse-ppt-template、/generate-ppt、/revise-ppt)可在 Claude Code 会话中直接使用。
agent4ppt 遵循 Agent Skills 标准(SKILL.md 格式),兼容 OpenClaw 及其他 Agent Skills 兼容运行时。
# 克隆仓库
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
# 安装依赖
bash scripts/install.shOpenClaw 通过仓库根目录的 SKILL.md 自动发现技能。要注册到 OpenClaw,指向克隆的目录或将仓库 URL 添加到 OpenClaw 技能源。
agent4ppt 也兼容 Codex CLI。克隆并安装依赖后:
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
bash scripts/install.sh
# 通过 Python 直接运行技能
python skills/parse-ppt-template/parse_template.py template.pptx --output slides.md
python skills/generate-ppt/generate_ppt.py slides.md --output output.pptx
python skills/revise-ppt/revise_ppt.py slides.md如果不使用任何代理运行时:
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
pip install python-pptx pyyaml markdown-it-py| 依赖项 | 版本 | 用途 |
|---|---|---|
| Python | ≥ 3.10 | 运行环境 |
| python-pptx | ≥ 0.6.21 | PPTX 读写 |
| pyyaml | ≥ 6.0 | Frontmatter 解析 |
| markdown-it-py | ≥ 3.0 | Markdown 解析 |
| LibreOffice | 任意版本 | PNG 幻灯片预览 (可选) |
/parse-ppt-template my_template.pptx
# → 生成 my_template.md打开 my_template.md,在占位符注释之间填写内容。
/generate-ppt my_template.md
# → 生成 output.pptx(或 frontmatter 中的 fname 值)/revise-ppt my_template.mdagent4ppt 基于 Markdown 优先的流水线。Markdown 文件是单一数据来源;PPTX 模板仅在 YAML frontmatter 的 template 字段中被引用一次,且从不被修改。
┌─────────────────────────────────────────────────────────────────┐
│ agent4ppt 流水线 │
│ │
│ PPTX 模板 │
│ (只读) │
│ │ │
│ ▼ /parse-ppt-template │
│ Markdown 模板 ─────────────────────────────────────────────► │
│ (YAML frontmatter + 幻灯片节 + <!-- ph:idx --> 注释) │
│ │ │
│ │ (用户填写内容) │
│ ▼ │
│ Markdown 内容文件 │
│ │ ┌──────────────────────────────────┐ │
│ ├── /generate-ppt ─► PPTX 输出 │ │
│ │ │ (使用 frontmatter 中的模板) │ │
│ │ └──────────────────────────────────┘ │
│ │ │
│ └── /revise-ppt ──► (3步问答) │
│ │ │
│ ├── 就地修改 Markdown │
│ └── 调用 /generate-ppt │
└─────────────────────────────────────────────────────────────────┘
| 阶段 | 输入 | 输出 | 核心操作 |
|---|---|---|---|
| 解析 | *.pptx 模板 |
含 <!-- ph:idx type:TYPE --> 的 *.md |
python-pptx 读取幻灯片布局;基于 idx 的占位符映射写入 Markdown |
| 生成 | *.md 内容文件 |
*.pptx 演示文稿 |
Frontmatter template 字段解析源 PPTX;每个 ph:idx 块写入匹配的占位符 |
| 修订 | *.md 内容文件 |
更新后的 *.md + *.pptx |
3步问答修补 Markdown,然后委托生成 |
- frontmatter 中的
template是权威来源 —template:字段中存储的路径是源 PPTX 的唯一引用。三个技能都从此字段解析模板;没有单独的配置文件。 - 占位符标识 = python-pptx
idx— 占位符通过 python-pptx 返回的整数idx标识,而非位置或名称。这使幻灯片重排安全,并确保稳定的往返转换。 - 无图像渲染 — 所有内容均以原生 python-pptx 对象插入(文本框、表格、图表)。PPTX 输出在 PowerPoint / LibreOffice Impress 中完全可编辑。
- PNG 预览为可选 — LibreOffice headless 在
revise-ppt工作流中提供视觉预览。当 LibreOffice 不可用时,技能会优雅地降级为纯文本幻灯片摘要。 - Markdown 无损 —
解析 → 编辑 → 生成往返转换生成的 PPTX 忠实再现模板布局。
每个流水线阶段均产生可验证的工件:
| 阶段 | 工件 | 验证方法 |
|---|---|---|
| 解析 | *.md 文件 |
YAML frontmatter 含 template: 字段;<!-- ph:idx --> 注释数与模板占位符数匹配 |
| 生成 | *.pptx 文件 |
python-pptx 可打开文件;幻灯片数与 Markdown --- 分隔符数匹配 |
| 修订 | 更新的 *.md + *.pptx |
修订注释已解决或已标注;PPTX 时间戳比原始更新 |
解析 PPTX 模板文件,生成带有占位符注释的 Markdown 模板。占位符由 python-pptx idx 索引标识,并以 <!-- ph:idx type:TYPE --> HTML 注释标注。
用法:
/parse-ppt-template <pptx文件> [--output <输出.md>] [--lang ko|en] [--layouts-only]
执行方式:python skills/parse-ppt-template/parse_template.py
参数:
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
pptx文件 |
✅ | — | PPTX 模板文件路径 |
--output,-o |
❌ | <输入文件名>.md |
生成的 Markdown 模板输出路径 |
--lang,-l |
❌ | $LANG 或 en |
输出指南注释语言(ko | en) |
--layouts-only |
❌ | false |
按布局定义而非按幻灯片生成各节 |
返回值:
将 Markdown 文件写入 --output。成功时退出码为 0,失败时为 1。
成功标记(机器可检测):
[agent4ppt] Markdown template written → <路径>
占位符类型值:
| 类型 | python-pptx 占位符类型 |
|---|---|
title |
标题(Title) |
center_title |
居中标题(Center Title) |
subtitle |
副标题(Subtitle) |
body |
正文(Body) |
object |
通用对象(Object) |
picture |
图片(Picture) |
table |
表格(Table) |
chart |
图表(Chart) |
media |
媒体剪辑(Media clip) |
ftr |
页脚(Footer) |
dt |
日期(Date) |
sldnum |
幻灯片编号(Slide number) |
示例:
# 基本用法
/parse-ppt-template "GIST NetAI PPT Theme.pptx"
# 指定输出路径和韩语指南注释
/parse-ppt-template "GIST NetAI PPT Theme.pptx" --output slides_template.md --lang ko
# 按布局生成各节(适用于无内容的模板)
/parse-ppt-template my_template.pptx --layouts-only --output layouts.md输出示例:
---
template: ./GIST NetAI PPT Theme.pptx
fname: output.pptx
title: ""
subTitle: ""
date: ""
author: ""
lang: en
---
> layout: 0
<!-- ph:0 type:title -->
# 幻灯片标题
<!-- ph:1 type:body -->
在此输入内容
---
> layout: 1
<!-- ph:0 type:center_title -->
# 节标题
<!-- ph:1 type:subtitle -->
节副标题文字错误处理:
| 条件 | 行为 |
|---|---|
找不到 pptx文件 |
退出码 1,输出错误信息 |
文件无 .pptx 扩展名 |
输出警告,继续执行 |
缺少依赖项(python-pptx、pyyaml) |
退出码 1,输出安装说明 |
从 Markdown 文件生成可编辑的 PPTX 文件。从 Markdown frontmatter 中读取 PPTX 模板路径,将每个 <!-- ph:idx --> 块映射到相应的占位符,并将 Markdown 表格、图表 YAML 块和图片转换为原生 python-pptx 对象。
用法:
/generate-ppt <markdown文件> [--output <输出.pptx>] [--lang ko|en]
执行方式:python skills/generate-ppt/generate_ppt.py
参数:
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
markdown文件 |
✅ | — | Markdown 内容文件路径 |
--output,-o |
❌ | frontmatter.fname 或 <输入>.pptx |
输出 PPTX 文件路径 |
--lang,-l |
❌ | $LANG 或 en |
警告/信息消息语言(ko | en) |
返回值:
在指定输出路径生成 PPTX 文件。成功时退出码为 0,失败时为 1。
成功标记(机器可检测):
[agent4ppt] PPTX generated → <路径>
Frontmatter 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
template |
✅ | PPTX 模板的相对或绝对路径。相对路径基于 Markdown 文件的目录解析。 |
fname |
❌ | 默认输出文件名(例如 output.pptx),可通过 --output 覆盖 |
title |
❌ | 演示文稿标题(元数据) |
subTitle |
❌ | 演示文稿副标题(元数据) |
date |
❌ | 演示文稿日期字符串 |
author |
❌ | 作者姓名 |
lang |
❌ | 语言覆盖(en 或 ko),优先级高于 $LANG 和 --lang |
幻灯片节结构:
> layout: N ← 布局索引(从 0 开始),必填
<!-- ph:0 type:title --> ← 占位符注释(idx=0, type=title)
# 我的幻灯片标题 ← 此占位符的内容
<!-- ph:1 type:body -->
- 项目一
- 项目二
- **加粗文本**和*斜体*支持的内容类型:
| 类型 | 语法 | 备注 |
|---|---|---|
| 纯文本 | 任意文本 | 原样写入 |
| 标题 | # 标题,## 副标题 |
title/subtitle 占位符中去掉前导 # |
| 项目符号列表 | - 项目 或 * 项目 |
最多 9 级缩进 |
| 编号列表 | 1. 项目 |
作为项目符号处理 |
| 加粗 | **文本** |
run.font.bold = True |
| 斜体 | *文本* |
run.font.italic = True |
| 链接 | [文本](url) |
下划线文本;不插入超链接关系 |
| 图片 |  |
用于 picture 或 object 占位符 |
| 表格 | GFM Markdown 表格 | 第一行为粗体标题 |
| 图表 | ```chart YAML 块 |
条形图、柱形图、折线图、饼图 |
| 多列 | ||| 分隔符 |
拆分内容;第一列填充占位符 |
图表块语法:
<!-- ph:2 type:chart -->
```chart
type: bar # bar | column | line | pie
title: 我的图表
categories: [Q1, Q2, Q3, Q4]
series:
- name: 收入
values: [100, 150, 120, 200]
- name: 支出
values: [80, 90, 100, 110]
```示例:
# 生成 PPTX——输出文件名来自 frontmatter fname 字段
/generate-ppt slides.md
# 覆盖输出路径
/generate-ppt slides.md --output final_presentation.pptx
# 使用中文/英语消息
/generate-ppt slides.md --lang en完整 Markdown 示例:
---
template: ./GIST NetAI PPT Theme.pptx
fname: my_presentation.pptx
title: "研究概述"
subTitle: "GIST NetAI 实验室"
date: "2026-03-22"
author: "Jinwang Mok"
lang: en
---
> layout: 0
<!-- ph:0 type:title -->
# 研究概述
<!-- ph:1 type:subtitle -->
GIST NetAI 实验室 · 2026
---
> layout: 2
<!-- ph:0 type:title -->
# 基准测试结果
<!-- ph:1 type:table -->
| 模型 | 准确率 | 延迟 (ms) |
|------|--------|-----------|
| 我们 | 94.2% | 12 |
| 基线 | 88.7% | 15 |
---
> layout: 3
<!-- ph:0 type:title -->
# 训练损失
<!-- ph:1 type:chart -->
```chart
type: line
title: 训练损失
categories: [Epoch 1, Epoch 2, Epoch 3, Epoch 4, Epoch 5]
series:
- name: 训练集
values: [1.8, 1.2, 0.9, 0.7, 0.6]
- name: 验证集
values: [2.0, 1.5, 1.1, 0.9, 0.8]
**错误处理:**
| 条件 | 行为 |
|------|------|
| 找不到 `markdown文件` | 退出码 1,输出错误信息 |
| frontmatter 中缺少 `template` 字段 | 退出码 1,输出错误信息 |
| 找不到模板 PPTX 文件 | 退出码 1,输出错误信息 |
| 布局索引超出范围 | 输出警告,使用布局 0 |
| 幻灯片中找不到占位符 `idx` | 输出警告,跳过该占位符 |
| 找不到图片文件 | 输出警告,占位符留空 |
| 无效的图表 YAML | 输出警告,占位符留空 |
| 缺少依赖项 | 退出码 1,输出安装说明 |
---
### /revise-ppt
通过 **3步问答工作流**交互式修订现有演示文稿:选择目标幻灯片 → 逐幻灯片描述修改 → 应用编辑到 Markdown 源文件并重新生成 PPTX。可通过 LibreOffice headless 渲染 PNG 幻灯片预览;若 LibreOffice 不可用,则回退到 Markdown 文本显示。
**用法:**
/revise-ppt <markdown文件> [--pptx <pptx文件>] [--output <输出.pptx>] [--lang ko|en]
执行方式:`python skills/revise-ppt/revise_ppt.py`
**参数:**
| 参数 | 必填 | 默认值 | 说明 |
|------|------|--------|------|
| `markdown文件` | ✅ | — | 要修订的 Markdown 源文件路径(唯一数据来源) |
| `--pptx` | ❌ | 从 `frontmatter.fname` 自动派生 | 用于 PNG 预览生成的现有 PPTX 文件路径 |
| `--output`,`-o` | ❌ | `frontmatter.fname` 或 `<markdown>.pptx` | 重新生成的 PPTX 输出路径 |
| `--lang`,`-l` | ❌ | `$LANG` 或 `en` | 问答提示语言(`ko` \| `en`) |
**返回值:**
`markdown文件`**就地更新**。新 PPTX 通过委托 `generate-ppt` 生成。成功时退出码为 `0`,失败时为 `1`。
**成功标记:**
[agent4ppt] PPTX generated → <路径> Revision complete! Updated file: <路径>
**工作流——3 步:**
**第1步 — 选择目标幻灯片**
=== 幻灯片修订工作流 === 您的演示文稿共有 8 张幻灯片。
第1步:您要修订哪些幻灯片? 请输入幻灯片编号,以逗号分隔(例如 1,3,5),范围表示(例如 2-4),或输入 'all':
2,4-6
**幻灯片选择语法:**
| 输入 | 含义 |
|------|------|
| `1,3,5` | 第 1、3、5 张幻灯片 |
| `2-4` | 第 2、3、4 张幻灯片 |
| `2~4` | 同 `2-4` |
| `all` | 所有幻灯片 |
| `*` | 所有幻灯片 |
**第2步 — 逐幻灯片描述修改**
第2步:逐一处理选中的幻灯片。
--- 幻灯片 2(布局:1)--- [预览 PNG: /tmp/agent4ppt_preview_xyz/slides2.png]
请描述您的修改。示例:
- 将标题改为"新标题"
- 将第 2 个项目符号替换为"更新的内容"
- 将布局改为布局 3
- 用新数据替换图表
- 添加图片 路径/to/image.png 幻灯片 2 的修改说明:
将标题改为"更新的结果"
**支持的修改模式(自动应用):**
| 模式 | 示例 | 效果 |
|------|------|------|
| 更改标题 | `将标题改为"新标题"` | 替换标题占位符标题 |
| 更改布局 | `将布局改为 3` | 更新节中的 `> layout: N` |
| 自由格式 | 其他任意文本 | 以 `<!-- REVISION: ... -->` 注释附加,等待人工审查 |
**第3步 — 应用并重新生成**
第3步:正在应用更改并重新生成 PPTX... 正在对幻灯片 2 应用更改... 正在对幻灯片 4 应用更改... 正在重新生成 PPTX... [agent4ppt] PPTX generated → ./my_presentation.pptx 修订完成!更新的文件:./my_presentation.pptx
**PNG 预览:**
LibreOffice 已安装时,使用以下命令生成幻灯片预览:
```bash
libreoffice --headless --convert-to png --outdir /tmp/agent4ppt_preview_<id> presentation.pptx
若未找到 LibreOffice,则显示幻灯片占位符内容的纯文本摘要。revise-ppt 技能无需 LibreOffice 即可完整运行——仅视觉预览功能受影响。
安装 LibreOffice:
# Ubuntu / Debian
sudo apt install libreoffice
# macOS (Homebrew)
brew install --cask libreoffice示例:
# 标准交互式修订(从 frontmatter fname 自动检测 PPTX)
/revise-ppt slides.md
# 明确提供 PPTX 路径
/revise-ppt slides.md --pptx final_presentation.pptx
# 指定输出路径
/revise-ppt slides.md --output revised_v2.pptx
# 使用英语提示
/revise-ppt slides.md --lang en错误处理:
| 条件 | 行为 |
|---|---|
找不到 markdown文件 |
退出码 1,输出错误信息 |
| 未选择任何幻灯片 | 退出码 0,输出提示信息 |
| 找不到 LibreOffice | 输出警告,回退到文本预览 |
generate-ppt 子进程失败 |
输出子进程 stderr,退出码 1 |
KeyboardInterrupt(Ctrl-C) |
输出 [agent4ppt] Cancelled.,退出码 0 |
| 缺少依赖项 | 退出码 1,输出安装说明 |
以下是展示所有支持内容类型的完整示例:
---
template: ./my_template.pptx
fname: output.pptx
title: "我的演示文稿"
subTitle: "2026 年度报告"
date: "2026-03-22"
author: "Jinwang Mok"
lang: en
---
> layout: 0
<!-- ph:0 type:title -->
# 我的演示文稿
<!-- ph:1 type:body -->
欢迎来到年度报告。
---
> layout: 2
<!-- ph:0 type:title -->
# 销售数据
<!-- ph:1 type:table -->
| 季度 | 营收 | 增长率 |
|------|-------|--------|
| Q1 | $1.2M | +12% |
| Q2 | $1.5M | +25% |
| Q3 | $1.3M | +8% |
| Q4 | $1.8M | +38% |
<!-- ph:2 type:chart -->
```chart
type: bar
title: 季度营收
categories: [Q1, Q2, Q3, Q4]
series:
- name: 营收(百万美元)
values: [1.2, 1.5, 1.3, 1.8]layout: 3
layout: 4
左列内容
- 项目 A
- 项目 B
|||
右列内容
- 项目 C
- 项目 D
### 占位符类型
| `type` | 说明 |
|--------|------|
| `title` | 幻灯片标题文本框 |
| `body` | 主要内容区域(项目符号、文本) |
| `picture` | 图片占位符 |
| `chart` | 图表占位符 |
| `table` | 表格占位符 |
| `object` | 通用对象/多内容区域 |
---
## 语言支持
设置指南注释和提示的输出语言:
```bash
# 通过环境变量设置
export LANG=ko # 韩语
export LANG=en # 英语(默认)
# 通过命令行标志设置
/parse-ppt-template template.pptx --lang ko
/revise-ppt slides.md --lang en
语言优先级:--lang 标志 > $LANG 环境变量 > en(默认值)
pip install python-pptx pyyaml markdown-it-py
# 或使用内置安装脚本:
bash scripts/install.shLibreOffice 仅用于 /revise-ppt 中的 PNG 幻灯片预览功能。未安装时,技能会优雅地回退到 Markdown 文本显示。
| 平台 | 安装命令 |
|---|---|
| Ubuntu/Debian | sudo apt install libreoffice |
| macOS (Homebrew) | brew install --cask libreoffice |
| Windows | 从 libreoffice.org 下载 |
# 1. 将 PPTX 模板解析为 Markdown 模板
/parse-ppt-template "GIST NetAI PPT Theme.pptx" --output my_talk.md
# 2. 编辑 my_talk.md — 填写幻灯片内容,添加表格/图表/图片
# (使用编辑器或请 Claude 帮助填写内容)
# 3. 从 Markdown 生成 PPTX
/generate-ppt my_talk.md
# 4. 查看结果,如有需要可进行交互式修订
/revise-ppt my_talk.md每个技能均输出机器可读的成功标记并以退出码 0 退出。您可以非交互式地验证流水线:
# 验证 parse-ppt-template 输出
python skills/parse-ppt-template/parse_template.py template.pptx --output out.md
echo "退出码: $?" # 必须为 0
grep -q "^template:" out.md && echo "PASS: frontmatter 存在"
grep -q "ph:[0-9]" out.md && echo "PASS: 占位符已找到"
# 验证 generate-ppt 输出
python skills/generate-ppt/generate_ppt.py out.md --output out.pptx
echo "退出码: $?" # 必须为 0
python -c "from pptx import Presentation; p=Presentation('out.pptx'); print('PASS: 幻灯片数 =', len(p.slides))"| 变量 | 说明 |
|---|---|
LANG |
用于自动检测输出语言的 POSIX 区域设置字符串(例如 ko_KR.UTF-8 → 韩语)。这是标准系统变量,在韩语区域设置的系统上无需手动设置。 |
MIT © 2026 Jinwang Mok
PPTX 템플릿을 마크다운 템플릿으로 파싱하고, 마크다운에서 편집 가능한 PPTX 파일을 생성하며, 대화형 슬라이드 수정을 지원하는 Claude Code 플러그인 — 이미지 기반 렌더링 없이 사용 가능합니다. 마크다운이 단일 진실 원천(single source of truth)입니다.
- 템플릿 파싱 — PPTX 템플릿을 읽어 플레이스홀더 주석(
<!-- ph:idx type:TYPE -->)이 포함된 구조화된 마크다운 파일을 출력 - PPTX 생성 — 마크다운을 다시 PPTX로 변환하여 템플릿의 시각적 레이아웃을 충실하게 재현
- 대화형 수정 — 특정 슬라이드를 수정하고 PPTX를 재생성하는 3단계 인터뷰 워크플로우
- 다양한 콘텐츠 지원 — 표, 차트(막대/파이/선형), 이미지, 다중 컬럼 레이아웃
- 이중 언어 출력 —
LANG환경 변수를 통한 한국어(ko) 및 영어(en) 가이드 주석 - 100% 편집 가능 — 모든 콘텐츠는 네이티브 python-pptx 객체로 삽입(이미지 렌더링 없음)
agent4ppt는 연구자, 엔지니어, 발표자가 흔히 겪는 문제를 해결하는 Claude Code / OpenClaw 플러그인입니다: 콘텐츠가 바이너리 파일 내부에 있을 때 PPTX 슬라이드 덱을 반복적으로 수정하는 작업은 번거롭고 오류가 발생하기 쉽습니다.
- PPTX 템플릿을 수동으로 편집하는 것은 시간이 많이 걸리고 일관성을 깨뜨림
- AI 지원 슬라이드 생성이 스크린샷/이미지 파이프라인에 의존하여 편집 불가능한 출력을 생성
- 코드나 문서와 함께 슬라이드 콘텐츠를 버전 관리할 신뢰할 수 있는 방법이 없음
agent4ppt는 3개 스킬 파이프라인을 제공합니다. 사람이 읽을 수 있는 마크다운 파일이 모든 슬라이드 콘텐츠의 단일 진실 원천(Single Source of Truth)입니다:
PPTX 템플릿 → /parse-ppt-template → 마크다운 템플릿
↓ (콘텐츠 편집)
마크다운 콘텐츠
↓
/generate-ppt → PPTX 출력 (편집 가능)
/revise-ppt → 대화형 수정 루프
| 원칙 | 설명 |
|---|---|
| 이미지 렌더링 없음 | 모든 PPTX 객체는 python-pptx 네이티브 API를 통해 생성됩니다. 출력은 항상 PowerPoint / LibreOffice Impress에서 완전히 편집 가능합니다. |
| 마크다운이 진실 | 슬라이드 콘텐츠, 레이아웃 메타데이터, 수정 기록이 모두 .md 파일에 저장됩니다. PPTX 템플릿은 참조만 될 뿐 수정되지 않습니다. |
| 안정적인 플레이스홀더 식별 | 플레이스홀더는 idx(python-pptx 정수 인덱스)로 식별되어 라운드트립과 슬라이드 순서 변경이 안전합니다. |
| 설계상 이중 언어 | 모든 사용자 향 문자열(가이드 주석, 프롬프트, 오류 메시지)은 LANG 환경 변수를 통해 한국어와 영어를 지원합니다. |
| 자연스러운 폴백 | 선택적 LibreOffice 미리보기가 수정 워크플로우를 향상시키지만 필수는 아닙니다. 핵심 파이프라인은 Python만으로 실행됩니다. |
- 구조화된 마크다운 노트에서 슬라이드 덱을 생성하려는 연구자
- CI/CD 또는 스크립트 워크플로우에서 슬라이드 생성을 자동화하려는 엔지니어
- AI 지원 워크플로우와 자연스럽게 통합되는 구성 가능한 스킬을 원하는 Claude Code / OpenClaw 사용자
- PowerPoint를 클릭하는 것보다 텍스트로 슬라이드를 편집하기를 선호하는 모든 분
agent4ppt를 설치하기 전에 다음 요구 사항을 확인하세요:
| 요구 사항 | 버전 | 비고 |
|---|---|---|
| Python | ≥ 3.10 | 필수. 확인: python3 --version |
| pip | 모든 버전 | 필수. 확인: pip --version |
| python-pptx | ≥ 0.6.21 | scripts/install.sh가 자동 설치 |
| pyyaml | ≥ 6.0 | scripts/install.sh가 자동 설치 |
| markdown-it-py | ≥ 3.0 | scripts/install.sh가 자동 설치 |
| LibreOffice | 모든 버전 | (선택 사항) /revise-ppt에서 PNG 슬라이드 미리보기 |
세 가지 Python 패키지(python-pptx, pyyaml, markdown-it-py)는 번들 설치 스크립트가 자동으로 설치합니다. Python ≥ 3.10과 pip만 미리 준비되어 있으면 됩니다.
이미지 기반 렌더링 없음: agent4ppt는
python-pptx를 직접 사용하여 네이티브 PPTX 객체(텍스트 프레임, 표, 차트)를 작성합니다. 출력 파일은 PowerPoint 또는 LibreOffice Impress에서 항상 완전히 편집 가능합니다.
두 줄 명령으로 agent4ppt를 설치하세요:
claude plugin marketplace add JinwangMok/agent4ppt
claude plugin install agent4ppt설치 프로그램은 자동으로 scripts/install.sh를 실행하여 Python ≥ 3.10을 확인하고, 세 가지 필수 패키지를 설치하며, 선택적 LibreOffice 의존성을 안내합니다.
설치 후 세 가지 스킬(/parse-ppt-template, /generate-ppt, /revise-ppt)을 Claude Code 세션에서 바로 사용할 수 있습니다.
agent4ppt는 Agent Skills 표준(SKILL.md 형식)을 준수하여 OpenClaw 및 기타 Agent Skills 호환 런타임에서 사용할 수 있습니다.
설치 단계:
# 1단계: 저장소 클론
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
# 2단계: Python 의존성 설치
bash scripts/install.sh --no-register
# 3단계: OpenClaw에 등록 (클론된 디렉토리 지정)
# openclaw skill add ./agent4ppt
# — 또는 — 저장소 URL을 OpenClaw 스킬 소스에 추가:
# openclaw skill add https://github.com/JinwangMok/agent4pptOpenClaw는 저장소 루트의 SKILL.md를 통해 스킬을 자동 감지합니다. 각 스킬 항목은 다음을 정의합니다:
| SKILL.md 필드 | 값 |
|---|---|
trigger |
/parse-ppt-template, /generate-ppt, /revise-ppt |
entry |
skills/<이름>/<스크립트>.py |
requires_python |
>=3.10 |
dependencies |
python-pptx>=0.6.21, pyyaml>=6.0, markdown-it-py>=3.0 |
등록 후 세 가지 슬래시 명령을 OpenClaw 세션 내에서 사용할 수 있습니다.
agent4ppt는 Codex CLI와도 호환됩니다. 클론 및 의존성 설치 후:
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
bash scripts/install.sh
# Python으로 스킬 직접 실행
python skills/parse-ppt-template/parse_template.py template.pptx --output slides.md
python skills/generate-ppt/generate_ppt.py slides.md --output output.pptx
python skills/revise-ppt/revise_ppt.py slides.md에이전트 런타임 없이 수동 설정을 선호하는 경우:
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
pip install python-pptx pyyaml markdown-it-py1. 설치 확인
위의 어느 방법으로든 설치한 후, 모든 필수 의존성이 사용 가능한지 확인하세요:
python3 -c "import pptx, yaml; from markdown_it import MarkdownIt; print('agent4ppt: all dependencies OK')"출력 결과: agent4ppt: all dependencies OK
2. 출력 언어 설정
agent4ppt는 LANG POSIX 환경 변수를 읽어 가이드 주석 및 프롬프트의 언어(한국어/영어)를 결정합니다. 쉘 프로파일에 한 번 설정하세요:
# 한국어 출력 (~/.bashrc 또는 ~/.zshrc에 추가)
export LANG=ko_KR.UTF-8
# 영어 출력 (기본값 — 별도 설정 불필요)
export LANG=en_US.UTF-8개별 실행 시 언어를 재정의할 수도 있습니다:
/parse-ppt-template template.pptx --lang ko # 이번 실행만 한국어
/revise-ppt slides.md --lang en # 이번 실행만 영어언어 우선순위: --lang 플래그 > 마크다운 frontmatter lang: 필드 > $LANG 환경 변수 > en (기본값)
3. 선택 사항: PNG 슬라이드 미리보기 활성화 (LibreOffice)
/revise-ppt 스킬은 대화형 검토 워크플로우 중 PNG 슬라이드 썸네일을 표시할 수 있습니다. 이 기능은 LibreOffice가 필요합니다:
# Ubuntu / Debian
sudo apt install libreoffice
# macOS (Homebrew)
brew install --cask libreofficeLibreOffice가 없으면 스킬은 일반 텍스트 슬라이드 요약으로 자연스럽게 폴백됩니다 — 핵심 파싱/생성/수정 기능에는 영향이 없습니다.
4. Claude Code 플러그인 설정 (선택 사항)
agent4ppt의 동작은 명령줄 인수와 LANG 환경 변수로 완전히 제어됩니다. ~/.claude/settings.json 변경은 필요하지 않습니다. Claude Code 내에서 영구적인 언어 기본값을 설정하려면:
// ~/.claude/settings.json
{
"env": {
"LANG": "ko_KR.UTF-8"
}
}/parse-ppt-template my_template.pptx
# → my_template.md 생성my_template.md를 열어 플레이스홀더 주석 사이에 콘텐츠를 입력하세요.
/generate-ppt my_template.md
# → output.pptx 생성 (또는 frontmatter의 fname 값)/revise-ppt my_template.mdagent4ppt는 마크다운 우선 파이프라인을 기반으로 합니다. 마크다운 파일이 단일 진실 원천(single source of truth)이며, PPTX 템플릿은 YAML frontmatter의 template 필드에서 한 번만 참조되고 수정되지 않습니다.
┌─────────────────────────────────────────────────────────────────┐
│ agent4ppt 파이프라인 │
│ │
│ PPTX 템플릿 │
│ (읽기 전용) │
│ │ │
│ ▼ /parse-ppt-template │
│ 마크다운 템플릿 ─────────────────────────────────────────────► │
│ (YAML frontmatter + 슬라이드 섹션 + <!-- ph:idx --> 주석) │
│ │ │
│ │ (사용자가 콘텐츠 입력) │
│ ▼ │
│ 마크다운 콘텐츠 파일 │
│ │ ┌──────────────────────────────────┐ │
│ ├── /generate-ppt ─► PPTX 출력 │ │
│ │ │ (frontmatter의 템플릿 사용) │ │
│ │ └──────────────────────────────────┘ │
│ │ │
│ └── /revise-ppt ──► (3단계 인터뷰) │
│ │ │
│ ├── 마크다운 인플레이스 수정 │
│ └── /generate-ppt 실행 │
└─────────────────────────────────────────────────────────────────┘
| 단계 | 입력 | 출력 | 핵심 작업 |
|---|---|---|---|
| 파싱 | *.pptx 템플릿 |
<!-- ph:idx type:TYPE -->이 포함된 *.md |
python-pptx가 슬라이드 레이아웃을 읽고 idx 기반 플레이스홀더 매핑을 마크다운에 작성 |
| 생성 | *.md 콘텐츠 파일 |
*.pptx 프레젠테이션 |
Frontmatter template 필드가 소스 PPTX를 찾아내고 각 ph:idx 블록이 매칭 플레이스홀더에 작성됨 |
| 수정 | *.md 콘텐츠 파일 |
업데이트된 *.md + *.pptx |
3단계 인터뷰로 마크다운을 패치한 후 generate에 위임 |
- frontmatter의
template이 권위적 — 마크다운 frontmatter의template:필드에 저장된 경로가 소스 PPTX에 대한 유일한 참조입니다. 세 가지 스킬 모두 이 필드에서 템플릿을 찾으며, 별도의 설정 파일이 없습니다. - 플레이스홀더 식별 = python-pptx
idx— 플레이스홀더는 위치나 이름이 아닌 python-pptx가 반환하는 정수idx로 식별됩니다. 이로 인해 슬라이드 순서 변경이 안전하고 안정적인 라운드트립이 보장됩니다. - 이미지 렌더링 없음 — 모든 콘텐츠는 네이티브 python-pptx 객체(텍스트 프레임, 표, 차트)로 삽입됩니다. PPTX 출력은 PowerPoint / LibreOffice Impress에서 완전히 편집 가능합니다.
- PNG 미리보기는 선택 사항 — LibreOffice 헤드리스가
revise-ppt워크플로우에서 시각적 미리보기를 제공합니다. LibreOffice가 없을 때 스킬은 일반 텍스트 슬라이드 요약으로 자연스럽게 폴백됩니다. - 마크다운은 무손실 —
파싱 → 편집 → 생성라운드트립은 템플릿 레이아웃을 충실하게 재현하는 PPTX를 생성합니다. - 패스스루 보존 — 슬라이드 전환, 애니메이션, 발표자 노트, 마스터 슬라이드 속성은 마크다운에서 모델링되지 않으며 파괴되지도 않습니다.
파싱 → 생성라운드트립을 통해 변경 없이 유지됩니다.
각 플레이스홀더 주석은 두 가지 별개의 관심사를 인코딩합니다:
| 관심사 | 속성 | 설명 |
|---|---|---|
| 템플릿 계약 | type:TYPE |
플레이스홀더가 요구하는 것 — 허용하는 콘텐츠의 종류(title, body, picture, chart 등). 마크다운과 PPTX 템플릿 사이의 구속력 있는 계약입니다. |
| 공간적 레이아웃 | pos:(x,y) size:WxH |
플레이스홀더가 슬라이드에서 위치하는 곳. 정보 제공용 메타데이터로만 사용되며 콘텐츠 재배치에는 절대 사용되지 않습니다. |
generate-ppt는 ph:idx와 type:만 읽습니다. parse-ppt-template 출력의 pos: 및 size: 값은 생성 시 조용히 전달되어 무시됩니다. 이 값들은 사람 편집자를 위한 문서 역할을 합니다.
각 파이프라인 단계에서 검증 가능한 아티팩트가 생성됩니다:
| 단계 | 아티팩트 | 검증 방법 |
|---|---|---|
| 파싱 | *.md 파일 |
YAML frontmatter template 필드 존재 여부; <!-- ph:idx --> 주석이 템플릿 플레이스홀더 수와 일치 |
| 생성 | *.pptx 파일 |
python-pptx로 파일 열기 가능; 슬라이드 수가 마크다운 --- 구분자 수와 일치 |
| 수정 | 업데이트된 *.md + *.pptx |
수정 주석이 해결되거나 주석 처리됨; PPTX 타임스탬프가 원본보다 새로움 |
PPTX 템플릿 파일을 파싱하여 플레이스홀더 주석이 포함된 마크다운 템플릿을 생성합니다. 플레이스홀더는 python-pptx idx 기반 인덱싱으로 식별되며 <!-- ph:idx type:TYPE --> HTML 주석으로 표시됩니다.
사용법:
/parse-ppt-template <pptx_파일> [--output <출력.md>] [--lang ko|en] [--layouts-only]
실행 경로: python skills/parse-ppt-template/parse_template.py
인수:
| 인수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
pptx_파일 |
✅ | — | PPTX 템플릿 파일 경로 |
--output, -o |
❌ | <입력파일명>.md |
생성된 마크다운 템플릿의 출력 경로 |
--lang, -l |
❌ | $LANG 또는 en |
출력의 가이드 주석 언어(ko | en) |
--layouts-only |
❌ | false |
슬라이드별 대신 레이아웃 정의별로 하나의 섹션 생성 |
반환값: --output에 마크다운 파일이 작성됩니다.
| 종료 코드 | 의미 |
|---|---|
0 |
성공 — 마크다운이 작성되었고 모든 검증 확인이 통과됨 |
1 |
입력/IO 오류 (파일 없음, 의존성 누락 등) |
2 |
검증 실패 — 마크다운은 작성되었으나 구조적 불변 확인에 실패 |
성공 마커 (기계로 확인 가능):
[agent4ppt] Markdown template written → <경로>
[agent4ppt] Verification passed ✓ (N section(s), template_path confirmed, idx annotations present)
출력 형식:
생성된 마크다운 파일에는 다음이 포함됩니다:
- YAML frontmatter —
template,fname,title,subTitle,date,author,lang필드 - 슬라이드 섹션 —
---으로 구분 - 레이아웃 표시자 — 각 슬라이드 섹션 시작 부분의
> layout: N - 레이아웃 이름 주석 —
<!-- layout_name: NAME -->(정보 제공용) - 플레이스홀더 주석 — 공간 메타데이터가 포함된
<!-- ph:idx type:TYPE pos:(x,y) size:WxH --> - 가이드 주석 — 각 플레이스홀더를 설명하는
<!-- Enter the ... -->(선택한 언어로) - 콘텐츠 플레이스홀더 — 바로 채울 수 있는 예시 콘텐츠 포함
플레이스홀더 type 값:
| 타입 | 설명 |
|---|---|
title |
슬라이드 제목 |
center_title |
가운데 제목 |
subtitle |
부제목 |
body |
본문(목록, 텍스트) |
object |
일반 개체 |
picture |
이미지 |
table |
표 |
chart |
차트/다이어그램 |
media |
미디어 클립 |
ftr |
바닥글 |
dt |
날짜 |
sldnum |
슬라이드 번호 |
예시:
# 기본 설정 — 출력은 템플릿과 같은 디렉토리에 작성됨
/parse-ppt-template "GIST NetAI PPT Theme.pptx"
# 출력 경로와 한국어 가이드 주석 지정
/parse-ppt-template "GIST NetAI PPT Theme.pptx" --output slides_template.md --lang ko
# 레이아웃별 하나의 섹션 (슬라이드 콘텐츠가 없는 템플릿용)
/parse-ppt-template my_template.pptx --layouts-only --output layouts.md예시 출력:
---
template: ./GIST NetAI PPT Theme.pptx
fname: output.pptx
title: ""
subTitle: ""
date: ""
author: ""
lang: ko
---
> layout: 0
<!-- layout_name: Title Slide -->
<!-- ph:0 type:center_title pos:(0.9167",1.75") size:7.6548"×0.7547" -->
<!-- 가운데 슬라이드 제목을 입력하세요 -->
# 슬라이드 제목
<!-- ph:1 type:subtitle pos:(0.9167",2.6495") size:5.588"×0.8832" -->
<!-- 부제목을 입력하세요 -->
부제목 텍스트
---
> layout: 1
<!-- ph:0 type:title pos:(0.4583",0.25") size:8.5"×1.2" -->
<!-- 슬라이드 제목을 입력하세요 -->
# 섹션 헤더
<!-- ph:1 type:body pos:(0.4583",1.5") size:8.5"×4.5" -->
<!-- 주요 본문 콘텐츠를 입력하세요. 목록, 굵게, 기울임 지원. -->
- 항목 하나
- 항목 둘오류 처리:
| 조건 | 동작 |
|---|---|
pptx_파일을 찾을 수 없음 |
종료 코드 1, stderr에 오류 출력 |
파일에 .pptx 확장자 없음 |
경고 출력 후 계속 진행 |
의존성 누락 (python-pptx, pyyaml) |
종료 코드 1, 설치 안내 출력 |
| PPTX 파일 손상 또는 읽을 수 없음 | 종료 코드 1, stderr에 오류 출력 |
| 작성 후 구조 검증 실패 | 종료 코드 2, stderr에 실패 세부 사항 출력 |
마크다운 파일에서 편집 가능한 PPTX 파일을 생성합니다. 마크다운 frontmatter에서 PPTX 템플릿 경로를 읽고, 각 <!-- ph:idx --> 블록을 해당 플레이스홀더에 매핑하며, 마크다운 표, 차트 YAML 블록, 이미지를 네이티브 python-pptx 객체로 변환합니다.
사용법:
/generate-ppt <마크다운_파일> [--output <출력.pptx>] [--lang ko|en] [--dry-run]
실행 경로: python skills/generate-ppt/generate_ppt.py
인수:
| 인수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
마크다운_파일 |
✅ | — | 마크다운 콘텐츠 파일 경로 |
--output, -o |
❌ | frontmatter.fname 또는 <입력>.pptx |
출력 PPTX 파일 경로 |
--lang, -l |
❌ | $LANG 또는 en |
경고/정보 메시지 언어(ko | en) |
--dry-run |
❌ | false |
PPTX 파일을 작성하지 않고 입력을 검증하고 슬라이드를 메모리에서 빌드 |
반환값: 출력 경로에 PPTX 파일. 성공 시 종료 코드 0, 오류 시 1.
성공 마커 (기계로 확인 가능):
[agent4ppt] PPTX generated → <경로>
Frontmatter 필드:
| 필드 | 필수 | 설명 |
|---|---|---|
template |
✅ | PPTX 템플릿의 상대 또는 절대 경로 |
fname |
❌ | 기본 출력 파일명 (예: output.pptx) |
title |
❌ | 프레젠테이션 제목 (메타데이터) |
subTitle |
❌ | 프레젠테이션 부제목 (메타데이터) |
date |
❌ | 프레젠테이션 날짜 문자열 |
author |
❌ | 저자 이름 |
lang |
❌ | 언어 재정의(en 또는 ko). $LANG 및 --lang보다 우선합니다. |
슬라이드 섹션 구조:
> layout: N ← 레이아웃 인덱스 (0부터 시작), 필수
<!-- ph:0 type:title --> ← 플레이스홀더 주석 (idx=0, type=title)
# 슬라이드 제목 ← 이 플레이스홀더의 콘텐츠
<!-- ph:1 type:body -->
- 항목 1
- 항목 2
- **굵은 텍스트** 및 *기울임 텍스트*지원하는 콘텐츠 유형:
| 유형 | 구문 | 비고 |
|---|---|---|
| 일반 텍스트 | 임의의 텍스트 | 그대로 작성됨 |
| 제목 | # 제목, ## 소제목 |
제목/부제목 플레이스홀더에서 앞의 # 제거됨 |
| 글머리 기호 목록 | - 항목 또는 * 항목 |
최대 9단계 들여쓰기 |
| 번호 매기기 목록 | 1. 항목 |
글머리 기호로 처리됨 |
| 굵게 | **텍스트** |
run.font.bold = True |
| 기울임 | *텍스트* |
run.font.italic = True |
| 링크 | [텍스트](url) |
밑줄 텍스트; 하이퍼링크 관계는 삽입되지 않음 |
| 이미지 |  |
picture 또는 object 플레이스홀더용 |
| 표 | GFM 마크다운 표 | 첫 번째 행은 굵은 헤더가 됨 |
| 차트 | ```chart YAML 블록 |
막대, 컬럼, 선형, 파이 차트 |
| 다중 컬럼 | ||| 구분자 |
콘텐츠 분할; 첫 번째 컬럼이 플레이스홀더를 채움 |
차트 블록 구문:
<!-- ph:2 type:chart -->
```chart
type: bar # bar | column | line | pie
title: 나의 차트
categories: [Q1, Q2, Q3, Q4]
series:
- name: 매출
values: [100, 150, 120, 200]
- name: 비용
values: [80, 90, 100, 110]
```예시:
# PPTX 생성 — 출력 파일명은 frontmatter fname 필드에서 가져옴
/generate-ppt slides.md
# 출력 경로 직접 지정
/generate-ppt slides.md --output final_presentation.pptx
# 한국어 메시지
/generate-ppt slides.md --lang ko
# 드라이런 — 파일 작성 없이 검증만 수행
/generate-ppt slides.md --dry-run전체 마크다운 예시:
---
template: ./GIST NetAI PPT Theme.pptx
fname: my_presentation.pptx
title: "연구 개요"
subTitle: "GIST NetAI 연구실"
date: "2026-03-22"
author: "진왕 목"
lang: ko
---
> layout: 0
<!-- ph:0 type:title -->
# 연구 개요
<!-- ph:1 type:subtitle -->
GIST NetAI 연구실 · 2026
---
> layout: 2
<!-- ph:0 type:title -->
# 벤치마크 결과
<!-- ph:1 type:table -->
| 모델 | 정확도 | 지연시간 (ms) |
|------|--------|--------------|
| 우리 | 94.2% | 12 |
| 기반 | 88.7% | 15 |
---
> layout: 3
<!-- ph:0 type:title -->
# 학습 손실
<!-- ph:1 type:chart -->
```chart
type: line
title: 학습 손실
categories: [에포크 1, 에포크 2, 에포크 3, 에포크 4, 에포크 5]
series:
- name: 학습
values: [1.8, 1.2, 0.9, 0.7, 0.6]
- name: 검증
values: [2.0, 1.5, 1.1, 0.9, 0.8]
**오류 처리:**
| 조건 | 동작 |
|------|------|
| `마크다운_파일`을 찾을 수 없음 | 종료 코드 1, stderr에 오류 출력 |
| `template` frontmatter 필드 누락 | 종료 코드 1, stderr에 오류 출력 |
| 템플릿 PPTX 파일을 찾을 수 없음 | 종료 코드 1, stderr에 오류 출력 |
| 레이아웃 인덱스 범위 초과 | 경고 출력, 레이아웃 0 사용 |
| 슬라이드에서 플레이스홀더 `idx`를 찾을 수 없음 | 경고 출력, 플레이스홀더 건너뜀 |
| 이미지 파일을 찾을 수 없음 | 경고 출력, 플레이스홀더 비워둠 |
| 잘못된 차트 YAML | 경고 출력, 플레이스홀더 비워둠 |
| 의존성 누락 | 종료 코드 1, 설치 안내 출력 |
---
### /revise-ppt
**3단계 인터뷰 워크플로우**를 통해 기존 프레젠테이션을 대화형으로 수정합니다. 대상 슬라이드 선택 → 슬라이드별 변경 사항 설명 → 마크다운 소스에 편집 사항 적용 후 PPTX 재생성. LibreOffice 헤드리스를 통해 PNG 슬라이드 미리보기를 선택적으로 렌더링하며, LibreOffice가 없을 때는 마크다운 텍스트로 폴백됩니다.
**사용법:**
/revise-ppt <마크다운_파일> [--pptx <pptx_파일>] [--output <출력.pptx>] [--lang ko|en]
실행 경로: `python skills/revise-ppt/revise_ppt.py`
**인수:**
| 인수 | 필수 | 기본값 | 설명 |
|------|------|--------|------|
| `마크다운_파일` | ✅ | — | 수정할 마크다운 소스 파일 경로 (단일 진실 원천) |
| `--pptx` | ❌ | `frontmatter.fname`에서 파생 | PNG 미리보기 생성에 사용되는 기존 PPTX 경로 |
| `--output`, `-o` | ❌ | `frontmatter.fname` 또는 `<마크다운>.pptx` | 재생성된 PPTX의 출력 경로 |
| `--lang`, `-l` | ❌ | `$LANG` 또는 `en` | 인터뷰 프롬프트 언어(`ko` \| `en`) |
**반환값:** `마크다운_파일`이 **인플레이스로 업데이트**됩니다. 새 PPTX는 `generate-ppt`에 위임하여 생성됩니다. 성공 시 종료 코드 `0`, 오류 시 `1`.
**성공 마커:**
[agent4ppt] PPTX generated → <경로> ← generate-ppt 서브프로세스에서 출력 Revision complete! Updated file: <경로> ← revise-ppt에서 출력
**워크플로우 — 3단계:**
**1단계 — 대상 슬라이드 선택**
=== 슬라이드 수정 워크플로우 === 프레젠테이션에 슬라이드가 8개 있습니다.
1단계: 어떤 슬라이드를 수정하시겠습니까? 슬라이드 번호를 쉼표로 구분하여 입력하거나 (예: 1,3,5), 범위로 입력하거나 (예: 2-4), 'all'을 입력하세요:
2,4-6
**슬라이드 선택 구문:**
| 입력 | 의미 |
|------|------|
| `1,3,5` | 슬라이드 1, 3, 5 |
| `2-4` | 슬라이드 2, 3, 4 |
| `2~4` | `2-4`와 동일 |
| `all` | 모든 슬라이드 |
| `*` | 모든 슬라이드 |
| `모두` | 모든 슬라이드 (한국어 별칭) |
**2단계 — 슬라이드별 변경 사항 설명**
2단계: 선택한 각 슬라이드를 살펴보겠습니다.
--- 슬라이드 2 (레이아웃: 1) --- 슬라이드 2 미리보기: /경로/to/my_presentation_previews/slide_2.png
변경 사항을 설명하세요. 예시:
- Change title to 'New Title'
- Replace bullet 2 with 'Updated content'
- Change layout to layout 3 슬라이드 2에 대한 지시 사항:
Change title to 'Updated Results'
**자동으로 적용되는 지시 패턴:**
| 패턴 | 예시 | 효과 |
|------|------|------|
| 제목 변경 | `Change title to 'New Title'` | 제목 플레이스홀더 제목을 교체 |
| 레이아웃 변경 | `Change layout to 3` | 섹션의 `> layout: N`을 업데이트 |
| 자유 형식 | 기타 텍스트 | 수동 검토를 위해 `<!-- REVISION: ... -->` 주석으로 추가됨 |
**3단계 — 적용 및 재생성**
3단계: 변경 사항을 적용하고 PPTX를 재생성합니다... 슬라이드 2에 변경 사항 적용 중... 슬라이드 4에 변경 사항 적용 중... PPTX 재생성 중... [agent4ppt] PPTX generated → ./my_presentation.pptx
Revision complete! Updated file: ./my_presentation.pptx Markdown updated: ./slides.md PPTX regenerated: ./my_presentation.pptx
**수정 상태 추적:**
1단계 이후에 JSON 상태 파일 `<마크다운_줄기>_revision_state.json`이 생성됩니다:
```json
{
"markdown_path": "/절대/경로/to/slides.md",
"pptx_path": "/절대/경로/to/output.pptx",
"iteration_count": 1
}
iteration_count는 각 성공적인 수정 사이클 후에 증가하여 재개 가능한 다중 라운드 편집을 지원합니다.
PNG 미리보기:
LibreOffice가 설치된 경우, 슬라이드 미리보기는 <pptx_줄기>_previews/ 디렉토리에 확정적으로 생성됩니다. LibreOffice가 없는 경우 텍스트 요약 파일로 자동 폴백됩니다.
예시:
# 표준 대화형 수정
/revise-ppt slides.md
# PNG 미리보기 생성을 위해 PPTX 경로 명시 지정
/revise-ppt slides.md --pptx final_presentation.pptx
# 명시적 출력 PPTX 경로 지정
/revise-ppt slides.md --output revised_v2.pptx
# 한국어 프롬프트
/revise-ppt slides.md --lang ko오류 처리:
| 조건 | 동작 |
|---|---|
마크다운_파일을 찾을 수 없음 |
종료 코드 1, stderr에 오류 출력 |
| 슬라이드 미선택 | 종료 코드 0, 안내 메시지 출력 |
| LibreOffice를 찾을 수 없음 | 경고 출력, 텍스트 미리보기로 폴백 |
generate-ppt 서브프로세스 실패 |
서브프로세스 stderr 출력, 종료 코드 1 |
KeyboardInterrupt (Ctrl-C) |
[agent4ppt] Cancelled. 출력 후 종료 코드 0 |
| 의존성 누락 | 종료 코드 1, 설치 안내 출력 |
마크다운 파일은 직렬화 형식이 아닌 정식(canonical) 문서 그 자체입니다. 모든 콘텐츠 편집은 마크다운에서 이루어지며, PPTX는 항상 마크다운으로부터 재생성됩니다.
모든 마크다운 파일은 ---으로 구분된 YAML frontmatter로 시작해야 합니다:
| 필드 | 필수 | 설명 |
|---|---|---|
template |
✅ | 소스 PPTX 템플릿 경로. 상대 경로는 마크다운 파일 기준. 소스 PPTX에 대한 유일한 권위 있는 참조 |
fname |
❌ | 기본 출력 PPTX 파일명 (예: output.pptx) |
title |
❌ | 프레젠테이션 제목 (PPTX 메타데이터) |
subTitle |
❌ | 프레젠테이션 부제목 |
date |
❌ | 날짜 문자열 |
author |
❌ | 저자 이름 |
lang |
❌ | 언어 재정의(en 또는 ko). $LANG 및 --lang보다 우선 |
frontmatter 이후, 슬라이드는 ---으로 구분됩니다. 각 슬라이드 섹션은 레이아웃 참조(> layout: N)로 시작하고, 플레이스홀더 블록이 이어집니다:
> layout: 1
<!-- layout_name: Content Slide -->
<!-- ph:0 type:title pos:(0.46",0.25") size:8.5"×1.2" -->
# 슬라이드 제목
<!-- ph:1 type:body pos:(0.46",1.5") size:8.5"×4.5" -->
- 첫 번째 글머리 기호
- 두 번째 글머리 기호
- 중첩 글머리 기호
- **굵은 텍스트** 및 *기울임 텍스트*각 플레이스홀더 주석은 하나의 줄에 두 가지 별개의 관심사를 인코딩합니다:
| 관심사 | 속성 | 역할 |
|---|---|---|
| 템플릿 계약 | type:TYPE |
플레이스홀더가 허용하는 콘텐츠. 이것이 구속력 있는 의미론적 계약이며, 유효한 마크다운 구문을 결정합니다 (title/body/picture/chart/table/…). |
| 공간적 레이아웃 | pos: 및 size: |
슬라이드에서 플레이스홀더가 위치하는 곳. 패스스루로 보존되는 정보 제공용 메타데이터이며, generate-ppt는 이 값들을 위치 결정에 사용하지 않습니다. |
지원하는 모든 콘텐츠 유형을 보여주는 완전한 예시:
---
template: ./my_template.pptx
fname: output.pptx
title: "나의 프레젠테이션"
subTitle: "2026 연간 보고서"
date: "2026-03-22"
author: "진왕 목"
lang: ko
---
> layout: 0
<!-- ph:0 type:title -->
# 나의 프레젠테이션
<!-- ph:1 type:body -->
연간 보고서에 오신 것을 환영합니다.
---
> layout: 2
<!-- ph:0 type:title -->
# 판매 데이터
<!-- ph:1 type:table -->
| 분기 | 매출 | 성장률 |
|------|-------|--------|
| Q1 | $1.2M | +12% |
| Q2 | $1.5M | +25% |
| Q3 | $1.3M | +8% |
| Q4 | $1.8M | +38% |
<!-- ph:2 type:chart -->
```chart
type: bar
title: 분기별 매출
categories: [Q1, Q2, Q3, Q4]
series:
- name: 매출 (백만 달러)
values: [1.2, 1.5, 1.3, 1.8]layout: 3
layout: 4
왼쪽 컬럼 내용
- 항목 A
- 항목 B
|||
오른쪽 컬럼 내용
- 항목 C
- 항목 D
### 플레이스홀더 유형
| `type` | 설명 |
|--------|------|
| `title` | 슬라이드 제목 텍스트 상자 |
| `body` | 주요 콘텐츠 영역(목록, 텍스트) |
| `picture` | 이미지 플레이스홀더 |
| `chart` | 차트 플레이스홀더 |
| `table` | 표 플레이스홀더 |
| `object` | 일반 개체/다중 콘텐츠 영역 |
---
## 언어 지원
가이드 주석 및 프롬프트의 출력 언어 설정:
```bash
# 환경 변수로 설정
export LANG=ko # 한국어
export LANG=en # 영어 (기본값)
# 명령줄 플래그로 설정
/parse-ppt-template template.pptx --lang ko
/revise-ppt slides.md --lang en
언어 우선순위: --lang 플래그 > $LANG 환경 변수 > en (기본값)
pip install python-pptx pyyaml markdown-it-py
# 또는 번들 설치 스크립트 사용:
bash scripts/install.shLibreOffice는 /revise-ppt의 PNG 슬라이드 미리보기 기능에만 필요합니다. 설치되지 않은 경우 마크다운 텍스트 표시로 자연스럽게 폴백됩니다.
| 플랫폼 | 설치 명령 |
|---|---|
| Ubuntu/Debian | sudo apt install libreoffice |
| macOS (Homebrew) | brew install --cask libreoffice |
| Windows | libreoffice.org에서 다운로드 |
# 1. PPTX 템플릿을 마크다운 템플릿으로 파싱
/parse-ppt-template "GIST NetAI PPT Theme.pptx" --output my_talk.md
# 2. my_talk.md 편집 — 슬라이드 콘텐츠 입력, 표/차트/이미지 추가
# (편집기를 사용하거나 Claude에게 콘텐츠 입력을 요청)
# 3. 마크다운에서 PPTX 생성
/generate-ppt my_talk.md
# 4. 결과를 검토하고 필요하면 대화형으로 수정
/revise-ppt my_talk.md각 스킬은 기계가 읽을 수 있는 성공 마커를 출력하고 종료 코드 0으로 종료합니다. 파이프라인을 비대화형으로 검증할 수 있습니다:
# parse-ppt-template 출력 검증
python skills/parse-ppt-template/parse_template.py template.pptx --output out.md
echo "종료 코드: $?" # 0=성공+검증됨, 2=작성되었으나 검증 실패
grep -q "^template:" out.md && echo "PASS: frontmatter 존재"
grep -qP "ph:\d+ type:\w+" out.md && echo "PASS: 플레이스홀더 발견"
# generate-ppt 출력 검증
python skills/generate-ppt/generate_ppt.py out.md --output out.pptx
echo "종료 코드: $?" # 반드시 0이어야 함
python -c "from pptx import Presentation; p=Presentation('out.pptx'); print('PASS: 슬라이드 수 =', len(p.slides))"
# 라운드트립 충실도 검증
python -c "
from pptx import Presentation
p = Presentation('out.pptx')
slides_pptx = len(p.slides)
import re
md = open('out.md').read()
body = md.split('---\n', 2)[-1]
slides_md = len(re.split(r'\n---\s*\n', body.strip()))
assert slides_pptx == slides_md, f'불일치: pptx={slides_pptx} md={slides_md}'
print('PASS: 슬라이드 수 일치')
"
# 수정 상태 검증 (/revise-ppt 실행 후)
python -c "
import json
state = json.load(open('out_revision_state.json'))
assert 'markdown_path' in state
assert 'iteration_count' in state
print('PASS: 수정 상태 유효, iteration_count =', state['iteration_count'])
"| 변수 | 설명 |
|---|---|
LANG |
출력 언어 자동 감지에 사용되는 POSIX 로케일 문자열 (예: ko_KR.UTF-8 → 한국어). 표준 시스템 변수로, 한국어 로케일 시스템에서는 별도로 설정할 필요가 없습니다. |
기여를 환영합니다! agent4ppt는 오픈소스 프로젝트이며 개선 사항, 버그 리포트, 아이디어 모두 환영합니다.
- GitHub에서 저장소를 Fork합니다
- 로컬에 Clone합니다:
git clone https://github.com/<your-username>/agent4ppt.git cd agent4ppt
- 변경사항을 위한 브랜치를 생성합니다:
git checkout -b feature/my-improvement
- 의존성을 설치하고 테스트 스위트가 통과하는지 확인합니다:
bash scripts/install.sh pytest
- 변경을 수행합니다 — 새로운 기능에는 반드시 테스트를 포함시키세요
- 테스트가 통과하는지 확인합니다:
pytest --tb=short
- 명확하고 설명적인 메시지로 커밋합니다
- 브랜치를 Push하고
main을 대상으로 Pull Request를 엽니다
| 영역 | 가이드라인 |
|---|---|
| 코드 스타일 | PEP 8 준수. 공개 함수에는 타입 힌트를 사용하세요. |
| 테스트 | 모든 새로운 기능은 tests/ 하위에 pytest 테스트를 포함해야 합니다. 변경된 모듈의 커버리지는 80% 이상을 유지하세요. |
| 이미지 렌더링 금지 | 모든 PPTX 콘텐츠는 python-pptx 네이티브 객체를 통해 삽입해야 합니다. 이미지 기반 렌더링 PR은 병합되지 않습니다. |
| 이중 언어 문서 | 사용자에게 보이는 문자열을 추가할 때는 i18n 딕셔너리에 영어(en)와 한국어(ko) 모두 포함해야 합니다. |
| 마크다운 우선 | 마크다운 스키마 변경은 하위 호환성을 유지하거나 마이그레이션 노트를 포함해야 합니다. |
| 의존성 | 새로운 런타임 의존성은 강력한 이유가 필요합니다. 개발 전용 의존성은 괜찮습니다. |
GitHub 이슈를 열고 다음을 포함해 주세요:
- OS 및 Python 버전 (
python3 --version) - agent4ppt 버전 (
plugin.json참조) - 실행한 정확한 명령
- 전체 오류 출력 (stdout + stderr)
- 최소 재현 가능한 예시 (가능하면 PPTX 템플릿 또는 마크다운 파일)
# 저장소 클론 및 진입
git clone https://github.com/JinwangMok/agent4ppt.git
cd agent4ppt
# 런타임 의존성 설치
bash scripts/install.sh
# 개발용 패키지 설치 (pytest, coverage)
pip install pytest pytest-cov
# 모든 테스트 실행
pytest
# 커버리지 리포트 포함 실행
pytest --cov=agent4ppt --cov=skills --cov-report=term-missing이 프로젝트는 간단한 규칙을 따릅니다: 서로 존중하고 건설적으로 행동하세요. 어떤 형태의 괴롭힘이나 차별적 언행도 허용되지 않습니다.
MIT 라이선스 — Copyright (c) 2026 Jinwang Mok
본 소프트웨어 및 관련 문서 파일(이하 "소프트웨어")의 사본을 취득하는 모든 사람에게 소프트웨어를 제한 없이 사용, 복사, 수정, 병합, 출판, 배포, 서브라이선스 및/또는 판매할 수 있는 권한이 무료로 부여됩니다. 소프트웨어를 제공받은 사람이 동일한 조건 하에 소프트웨어를 사용할 수 있도록 허가하는 것을 포함합니다.
위의 저작권 고지와 본 허가 고지는 소프트웨어의 모든 사본 또는 중요한 부분에 포함되어야 합니다.
소프트웨어는 상품성, 특정 목적에 대한 적합성 및 비침해에 대한 보증을 포함하되 이에 국한되지 않는 어떠한 종류의 명시적 또는 묵시적 보증 없이 "있는 그대로" 제공됩니다.
전체 라이선스 텍스트는 LICENSE를 참조하세요.
