Odp
Agent skills and helper scripts for OpenDocument Format files (ODT, ODP, ODS, ODG)
npx -y skills add leiverkus/open-document-skills --skill odpAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Create, read, edit, convert, repair, or inspect OpenDocument Presentation files (.odp) — including bidirectional conversion to PPTX/PPT via headless LibreOffice. Supports shape animations (entrance, exit, emphasis, motion paths), slide transitions, master-page customization, and a template ecosystem (curated branded designs + inspector/extractor tools).
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
25.8 KB, as published. Nobody here has run it
ODP creation, editing, and analysis
Overview
An .odp file is an OpenDocument ZIP package for presentations. Important package files:
mimetype- should be the first ZIP entry and stored uncompressed asapplication/vnd.oasis.opendocument.presentationcontent.xml- slides, shapes, text boxes, images, speaker notesstyles.xml- presentation, drawing, and text stylesmeta.xml- document metadatasettings.xml- application settingsMETA-INF/manifest.xml- package manifestPictures/...- embedded media
Quick Reference
| Task | Preferred approach |
|---|---|
| Create branded deck | Start from an .odp template, clone slides/masters, edit XML |
| Create simple structured deck | Generate ODP package XML directly |
| Convert PPTX/HTML/SVG to ODP | Use LibreOffice only when the source already exists or interoperability requires it |
| Extract text | Use scripts/extract_text.py or parse content.xml |
| Preserve template layout | Edit the existing ODP package XML and media references |
| Visual QA | Convert to PDF or slide images and inspect every slide |
Tool Checks
Before starting a real ODP task, check available tools:
which pandoc
Resolve the LibreOffice command as described in docs/soffice-resolver.md.
LibreOffice is the preferred engine for ODP conversion and rendering. Pandoc is not a full ODP authoring or inspection tool.
Reading and Inspecting
For raw inspection:
unzip -l input.odp
python -m zipfile -e input.odp unpacked_odp
Slide content is usually in content.xml under draw:page elements. Extract text with an XML parser, keeping namespace handling explicit.
Bundled scripts for common inspection tasks:
# Extract visible slide text and speaker notes.
python scripts/extract_text.py input.odp
python scripts/extract_text.py input.odp --json
# Inspect package files, media references, slide metadata, notes, and master pages.
python scripts/inspect_package.py input.odp
For the full script reference, see docs/script-reference.md.
Useful things to inspect:
draw:pageelements for slide order and namesdraw:frameanddraw:text-boxfor positioned contenttext:pandtext:listfor visible slide textpresentation:notesfor speaker notesdraw:imagereferences for embedded media
content.xml Structure
An ODP presentation normally stores slides in content.xml under this broad path:
office:document-content
office:body
office:presentation
draw:page
Each draw:page is one slide. Important attributes commonly include:
draw:name- slide name, often visible in Impress navigationdraw:style-name- slide/page style referencedraw:master-page-name- links the slide to a master pagepresentation:presentation-page-layout-name- placeholder/layout behaviorpresentation:use-header-name,presentation:use-footer-name,presentation:use-date-time-name- header/footer/date-time bindings when present
Typical slide children:
draw:frame- positioned container for text boxes, images, objects, charts, or pluginsdraw:text-boxinsidedraw:frame- text box contenttext:p,text:span,text:list- visible text runs and listsdraw:image- embedded or linked image reference, usually viaxlink:hrefdraw:custom-shape,draw:rect,draw:ellipse,draw:line,draw:connector,draw:path- vector shapespresentation:notes- speaker notes and notes-page content for that slideanim:par/ animation elements - slide animations or transitions when present
Speaker Notes
Speaker notes live inside the slide's draw:page, usually as a presentation:notes child. Notes may contain their own drawing page/frame structure, not just plain text:
draw:page
... visible slide shapes ...
presentation:notes
draw:page-thumbnail
draw:frame
draw:text-box
text:p
When extracting notes, gather text under presentation:notes separately from visible slide text. When editing visible slide text, avoid accidentally modifying notes text with broad text:p searches.
Master Pages
Master pages are usually defined in styles.xml, not content.xml, under:
office:document-styles
office:master-styles
style:master-page
Slides connect to masters through draw:page/@draw:master-page-name. A style:master-page can reference page layouts and include background shapes, logos, footer placeholders, and presentation placeholders. Common attributes and children include:
style:name- the value referenced bydraw:master-page-namestyle:page-layout-name- page size and margins through a page layout styledraw:frame,draw:rect,draw:image,draw:text-box- master-level visible/background objectspresentation:placeholderor presentation classes on frames - title/body/footer/date placeholders
When changing a repeated background, footer, logo, or title placeholder, inspect the matching style:master-page first. Editing each slide separately is only appropriate when the content is slide-specific.
Slide Layouts
ODF models slides as a flat two-layer reference, not a PowerPoint-style master
hierarchy: each draw:page independently names a master page (the chrome —
background, header/footer) and a slide layout (style:presentation-page-layout
— the placeholder zone arrangement). create_minimal_odp.py ships six standard
layouts: title-slide, title-content (default), two-content,
section-header, title-only, and blank.
# Generate a deck with per-slide layouts and an extra master:
python scripts/create_minimal_odp.py deck.json deck.odp
# Reassign layout/master on existing slides (placeholder frames are repositioned):
python scripts/set_layout.py deck.odp --slide 2 --layout two-content -o deck.odp
python scripts/set_layout.py deck.odp --slide all --master Brand -o deck.odp
python scripts/list_masters.py deck.odp # masters + layouts + per-slide usage
Spec shape — a layout key per slide selects the layout; content keys fill its
zones (title, subtitle, body, body_left, body_right); a top-level
masters array adds extra master pages, and a slide's master key picks one:
{
"masters": [{"name": "Brand", "background_color": "#02416C"}],
"slides": [
{"layout": "title-slide", "master": "Brand", "title": "Q1 Review", "subtitle": "2026"},
{"layout": "two-content", "title": "Regions", "body_left": ["North"], "body_right": ["South"]}
]
}
Specs without a layout key behave exactly as before — title/body fill the
title-content layout. Generator masters carry a background_color; for dark
master backgrounds pair them with branded text styles via
inject_styles_from_file. validate_refs.py flags slides whose master or
slide-layout reference does not resolve.
Style and Layout Links
ODP content uses many name-based references across content.xml and styles.xml:
draw:style-namepoints to drawing/graphic stylestext:style-namepoints to paragraph or text stylesdraw:text-style-namecan control text inside drawing objectspresentation:style-nameand presentation layout names can control placeholder behaviordraw:master-page-namepoints from a slide to a master page
Before deleting or renaming a style or master page, search both content.xml and styles.xml for the name. Broken style references often render as layout shifts rather than obvious validation errors.
Creating ODP Files
ODP is an XML package and can be generated directly. Do not default to PPTX as an intermediate just because PPTX tooling exists.
Choose the creation path by fidelity needs:
| Scenario | Use |
|---|---|
| Branded deck, recurring layouts, exact master/footer/logo behavior | Template-first ODP |
| Simple generated deck with title/body/image/diagram slides | Direct ODP XML generation |
| Existing PPTX/HTML/SVG source or explicit cross-format conversion | LibreOffice conversion fallback |
Template-First ODP
Use this when visual consistency matters or a user provides an .odp template.
- Extract the template.
- Inspect
styles.xmlmaster pages andcontent.xmlslide structures. - Clone a known-good
draw:pagefor each needed layout. - Replace text, media references, and coordinates with XML-aware edits.
- Add images under
Pictures/and updateMETA-INF/manifest.xml. - Repack and run the full QA loop.
This is usually the safest path for branded or institutional decks because it preserves master pages, placeholders, fonts, footers, and page settings.
Direct ODP XML Generation
Use this for simple or highly structured generated decks. Generate a minimal package with:
mimetypecontent.xmlstyles.xmlmeta.xmlsettings.xmlMETA-INF/manifest.xml- optional
Pictures/...
Minimum slide structure:
office:body
office:presentation
draw:page draw:name="Slide 1" draw:master-page-name="Default"
draw:frame svg:x="1cm" svg:y="1cm" svg:width="24cm" svg:height="2cm"
draw:text-box
text:p text:style-name="Title"
When generating directly, keep the first version deliberately small: title/body/image slides, a small style set, one or two masters, and no animations until the PDF/PNG render is stable.
Conversion Fallback
Use LibreOffice conversion when the source already exists in another format or when interoperability is the actual task:
# Resolve SOFFICE as shown in Tool Checks.
"$SOFFICE" --headless --convert-to odp source.pptx --outdir out
"$SOFFICE" --headless --convert-to pdf out/source.odp --outdir qa
Treat conversion as lossy until QA proves otherwise. Check fonts, images, connectors, masters, notes, and placeholder behavior after every conversion.
Presentation Styling and Branding
create_minimal_odp.py emits a designed default theme, not raw frames:
- A real
drawing-pagestyle (dp-default) sets the slide background and is referenced by the master page throughdraw:style-name. - Each
draw:framereferences agraphic-family style (gr-title,gr-body,gr-notes,gr-image) withdraw:fill="none"anddraw:stroke="none". Without a graphic style a frame inherits LibreOffice's default fill and renders as a blue box — always give generated frames an explicitdraw:style-name. - Paragraph styles
Title/Body/Notescarry an explicitfo:color.
Two ways to brand a deck:
-
Whole-theme swap — write a curated
styles.xmlthat redefines the same named styles (dp-default,gr-title,gr-body,Title,Body, masterDefault, layoutScreen) and inject it:from odp_common import embed_pictures, inject_styles_from_file inject_styles_from_file("base.odp", "branded-styles.xml", "styled.odp") embed_pictures("styled.odp", {"Pictures/logo.png": "logo.png"}, "deck.odp")Because content references styles by name, no edit to
content.xmlis needed. See examples/deck/ for a complete branded-deck build. -
Per-master tweak — use
customize_master.pyfor a background colour, header/footer, page numbers, or a logo on one master page. The background colour is written into thedrawing-pagestyle the master references (setting it on the master element itself does not render).
Themes
create_minimal_odp.py accepts --theme NAME — a curated colour palette and
font pairing applied to the whole deck. Five themes:
| Theme | Feel |
|---|---|
corporate-blue | clean corporate blue |
warm-editorial | cream background, terracotta serif — reports, essays |
high-contrast | black on white, bold — accessibility, print |
slate-mono | slate palette, monospaced headings — technical decks |
forest | deep green, sans heading + serif body |
python scripts/create_minimal_odp.py deck.json deck.odp --theme slate-mono
Without --theme the output is unchanged. A theme sets the default slide
background; a per-master background_color in the masters array still
overrides it. Themes name fonts as stacks with a Liberation fallback, so a
themed deck renders even where the first-choice font is absent. For branding
beyond the five themes, use a template (next section).
Templates
A template is a complete branded design (styles + master pages + slide layouts + assets like a logo) packaged as a directory. The skill ships three templates and three tools to work with them — themes are quick palette+font tweaks; templates are full branded designs.
Shipped templates
skills/odp/templates/:
| Template | Look |
|---|---|
dao-conference | deep-blue background (#02416C), Nunito Sans, logo bottom-right. Conference / grant decks. |
academic-blue | cream background, navy Lato headings, Source Serif body. Long academic talks. |
minimalist-mono | near-white background, JetBrains Mono headings, Inter body. Technical talks, post-mortems. |
Apply a template
apply_template.py is the one-call wrapper for injection + asset embedding +
validation. The agent's standard branding workflow:
# Build a base deck
python scripts/create_minimal_odp.py spec.json deck.odp
# Apply a shipped template by name
python scripts/apply_template.py deck.odp \
--template-name dao-conference -o branded.odp
# Or apply by path (e.g. a user-supplied template directory)
python scripts/apply_template.py deck.odp \
--template /path/to/my-template -o branded.odp
Inspect a template
Before picking a layout per slide, ask what the template offers:
python scripts/inspect_template.py \
skills/odp/templates/dao-conference/styles.xml --json
Output is JSON with master_pages (each with background colour, frames,
placeholder classes), presentation_page_layouts (each with placeholder
zones and their geometry), paragraph_styles, graphic_styles, and
font_face_decls. Use this to drive per-slide layout and master
choices in your generation spec.
Extract a new template
To turn an existing .odp/.otp/.pptx into a reusable template:
python scripts/extract_template.py investor-pitch.pptx \
--name pitch-warm --outdir skills/odp/templates/ \
--license CC-BY-4.0 --source "https://example.com/template"
The extractor filters office:automatic-styles to keep only what master
pages reference (and parent-style chains), copies master-page-referenced
images from Pictures/, and writes LICENSE.txt/PROVENANCE.md/README.md
metadata. PPTX inputs are auto-converted via the v1.11 OOXML bridge.
Template structure
Each template directory has:
styles.xml— the branded theme.Pictures/(optional) — master-page assets likelogo.png.LICENSE.txt,PROVENANCE.md,README.md— metadata.
Templates live inside skills/odp/ so install_skills.py bundles them
into every installation (Smithery, skills.sh, Claude Code plugin).
Bundled Scripts
For creation and editing scripts, see docs/script-reference.md. All scripts use the Python standard library and are invoked as:
python scripts/<script_name>.py [args]
Keep direct generation deliberately small unless a task needs more: title/body/image slides, simple notes, a small style set, and QA-rendered output.
ODP Slide Design Checklist
Use this checklist when creating or materially redesigning ODP slides. ODP decks should be designed for LibreOffice Impress rendering first, then checked for export stability.
Master and Layout Discipline
- Put repeated backgrounds, logos, slide numbers, footers, and section markers on master pages, not duplicated on every slide.
- Use a small set of master pages/layouts; too many near-duplicate masters make XML edits and QA brittle.
- Keep title, body, footer, date, and page-number placeholders aligned across related masters.
- Verify that each slide's
draw:master-page-namepoints to the intended master after conversions or cloning. - For section divider slides, use a dedicated master or layout rather than manually overriding many objects.
Text and Typography
- Use fonts likely to exist on the target system, or verify export output after font substitution.
- Keep text boxes slightly larger than the expected text; Impress line breaking can differ from PowerPoint or browser renderers.
- Avoid tiny text below 12 pt for projected decks; use 14-18 pt as a safer body range.
- Keep title boxes high and consistent, but allow enough vertical space for two-line titles.
- Prefer real list structures where practical; avoid manually typed bullets if later XML editing is expected.
Shapes, Connectors, and Diagrams
- Use connector objects for diagrams that need to stay attached to shapes; verify routing after moving shapes.
- Leave enough spacing around connector endpoints so rerouting does not cross labels.
- Keep grouped objects simple. Deeply nested groups are harder to edit safely in
content.xml. - Use consistent stroke widths and arrowheads across a deck; conversion can make small inconsistencies more visible.
- For process diagrams, align objects numerically or through template duplication rather than eyeballing every slide.
Images and Media
- Embed critical images in the ODP package rather than linking to local files.
- Preserve image aspect ratios; set crop/frame behavior deliberately.
- Use sufficient image resolution for PDF export, but avoid enormous media that makes ODP editing slow.
- Check
META-INF/manifest.xmlafter adding images manually. - Prefer SVG for simple icons and diagrams if LibreOffice renders them correctly in the target environment; otherwise render to PNG at adequate resolution.
Export-Stable Visual Choices
- Avoid relying on subtle transparency, complex gradients, shadows, or blend effects unless PDF/PNG QA proves they survive.
- Keep charts and embedded objects simple, or rasterize/export them deliberately when fidelity matters more than editability.
- Use high contrast for projected decks and PDF handouts.
- Keep important content away from slide edges; exported PDFs may expose tight margins.
- Avoid animation-dependent meaning unless the user explicitly needs a live Impress deck.
Slide Composition
- Every slide should have a clear visual hierarchy: title, primary content, supporting detail.
- Use one dominant idea per slide; split crowded ODP slides rather than shrinking text.
- Align objects to a consistent grid or repeated coordinates.
- Reserve master-level footer/navigation space so content does not collide with it.
- For diagram-heavy slides, include enough whitespace around labels and connectors for export drift.
Editing Existing ODP Files
For content/layout-preserving edits:
- Extract the package.
- Parse
content.xmlwith an XML library. - Edit slide text, images, or shape attributes while preserving namespaces and style names.
- Add new media under
Pictures/and updateMETA-INF/manifest.xml. - Repack with
mimetypefirst and uncompressed. - Convert to PDF/images for visual QA.
Repack pattern:
cd unpacked_odp
zip -0 -X ../output.odp mimetype
zip -r -X ../output.odp . -x mimetype
QA (Required)
Assume generated or edited ODP files have problems until proven otherwise. ODP round-trips through LibreOffice can change fonts, connector routing, image sizing, placeholder behavior, and master-page inheritance.
Content QA
Extract visible text and notes:
python scripts/extract_text.py output.odp
python scripts/extract_text.py output.odp --json > qa/text.json
Check:
- slide count and order
- missing, duplicated, or stale slide text
- speaker notes preserved separately from visible slide text
- leftover placeholder text such as
Lorem,TODO,XXXX, or template instructions - expected title/body/footer text on slides using master placeholders
Package QA
Inspect the package before visual review:
python scripts/inspect_package.py output.odp > qa/package.json
Check:
mimetypeis firstcontent.xml,styles.xml,meta.xml, andMETA-INF/manifest.xmlexist- media referenced by
draw:image/@xlink:hrefexists in the package - slides reference existing master pages through
draw:master-page-name - slides with expected speaker notes report
has_notes: true - frame and image counts look plausible after edits
If you changed masters, backgrounds, logos, footers, or placeholders, inspect both content.xml and styles.xml for broken style/master references before rendering.
Visual Design Loop
Rendering is a design step, not only a final check. Render an early draft, look at it, fix what is wrong, then continue — do not build the whole deck blind and render once at the end.
python scripts/render.py output.odp --outdir qa --contact-sheet # all slides in one image
python scripts/render.py output.odp --outdir qa --png # one PNG per slide
python scripts/render.py output.odp --outdir qa # PDF only
python scripts/render.py output.odp --outdir qa --notes # + slides+notes PDF
python scripts/render.py output.odp --outdir qa --notes-only # + notes-only PDF
--notes / --notes-only use LibreOffice's impress_pdf_Export
filter (ExportNotesPages / ExportOnlyNotesPages) and write
<stem>-with-notes.pdf / <stem>-notes.pdf alongside the default
slide-only PDF — useful for reviewing speaker notes or producing a
handout for the presenter.
The contact sheet composes every slide into a single labelled grid image — the best way to judge cross-slide consistency (alignment, colours, repeated master elements) at a glance. Open it and actually look at it.
Inspect every rendered slide. Look for:
- text overflow, clipped titles, or text shifted outside frames
- missing images, wrong crop/aspect ratio, or low-resolution replacements
- connectors detached from shapes or routed awkwardly
- master-page backgrounds, logos, footers, or slide numbers missing
- notes accidentally visible on the slide canvas
- font substitution changing line breaks or causing crowding
- charts or embedded objects rasterized poorly
- slide size or orientation mismatches
- unexpected animation/transition loss if those mattered to the request
Verification Loop
The final pass of a loop you should already be running while building the deck:
- Extract content and package summaries.
- Render to a contact sheet or PDF/PNG and look at it.
- List concrete issues found, even if minor.
- Fix the ODP source, package XML, or intermediate source deck.
- Re-run the relevant extraction/inspection/rendering steps.
- Do not deliver until a final pass shows no unresolved content, package, or visual issues relevant to the user's request.
For template-based decks, always verify at least one slide using each master page/layout that was touched.
Format Conversion (PowerPoint: PPTX/PPT)
For one-shot conversion between ODP and Microsoft PowerPoint formats,
convert.py wraps soffice --headless --convert-to with an isolated temp
profile:
# ODP → PPTX:
python scripts/convert.py deck.odp --to pptx --outdir qa
# PPTX → ODP (the bridge: edit a PowerPoint deck with our skills, then export back):
python scripts/convert.py source.pptx --to odp --outdir qa
python scripts/add_animation.py qa/source.odp --slide 1 --shape "title" \
--effect "entrance:fade-in" -o edited.odp
python scripts/convert.py edited.odp --to pptx --outdir qa
# Legacy MS PowerPoint 97-2003 (.ppt):
python scripts/convert.py deck.odp --to ppt --outdir qa
python scripts/convert.py legacy.ppt --to odp --outdir qa
Fidelity caveat: soffice handles text, basic shapes, images, and master
pages well. Slide layouts (the ODF presentation-page-layout introduced in
v1.8) map approximately to PowerPoint slide layouts but are not perfectly
equivalent. Animations and transitions usually round-trip; some advanced
SMIL motion paths or custom-path effects may simplify or be dropped. Fonts
in particular substitute very differently across PowerPoint, LibreOffice
Impress, and Keynote — always render the output in the target application
before delivering.
For text documents, use the odt skill's convert.py (ODT ↔ DOCX/DOC);
for spreadsheets, the ods skill's convert.py (ODS ↔ XLSX/XLS). The
script enforces format families — cross-family conversions are rejected
with a clear hint.
ODP Notes
- ODP uses drawing coordinates and style references; minor XML edits can have large visual effects.
- Fonts may substitute differently in LibreOffice, PowerPoint, and browser previewers. Render with the target app when possible.
- Keep aspect ratios explicit for images.
- Prefer template-based work for branded decks.
See also
Part of the open-document-skills suite: