A complete native-ODF skill set for agents — generate, edit, validate, brand, and convert all four OpenDocument formats (ODT / ODP / ODS / ODG) without a DOCX detour.
Four self-contained skills for Codex, Claude Code, OpenCode, and any agent runtime that supports the SKILL.md convention. Production-deep across all four OpenDocument formats: generation, structure-preserving edits, scholarly authoring (footnotes, citations, MathML, generated indexes), curated templates and themes, RelaxNG validation, bidirectional bridges to DOCX / XLSX / PPTX, and PDF rendering — all driven from stdlib-only Python with LibreOffice as an optional QA companion.
A branded title slide generated from a JSON spec and rendered with LibreOffice — a curated theme injected as styles.xml, in pure Python. See examples/deck.
# Generate, edit, validate, version — all from the agent shell:
python skills/odt/scripts/create_from_markdown.py article.md doc.odt # rich text from Markdown
python skills/odt/scripts/replace_text.py doc.odt "{{NAME}}" "Patrick" -o out.odt
python skills/odt/scripts/pack_fodt.py out.odt -o out.fodt # diff-friendly XML
python skills/odt/scripts/validate_refs.py out.odt| Skill | LibreOffice app | Smithery | Triggers |
|---|---|---|---|
odt |
Writer | smithery.ai/skills/leiverkus/odt | author from Markdown, edit ODT, footnotes, citations (BibTeX/CSL-JSON), bookmarks, cross-references, figure/table sequences, MathML formulas, generated indexes, tracked changes, 5 shipped templates (grant proposal, academic paper, letterhead, CV, dissertation), DOCX bridge, render to PDF |
odp |
Impress | smithery.ai/skills/leiverkus/odp | clone slide, edit notes, add image, named slide layouts, multiple master pages, animations (entrance/exit/emphasis/motion), slide transitions, master-page customization, 3 shipped templates (dao-conference, academic-blue, minimalist-mono), PPTX bridge, render deck |
ods |
Calc | smithery.ai/skills/leiverkus/ods | set cells/formulas, named ranges, dropdowns + data validation, embedded charts (bar/line/pie/scatter), conditional formatting, pivot tables, XLSX bridge, export CSV, recalculate |
odg |
Draw | smithery.ai/skills/leiverkus/odg | edit labels, add shape image, glue points, connectors with shape binding, groups, flowcharts, org charts, export SVG/PNG |
- Native ODF — with an OOXML bridge. Generation and editing stay native (no font drift, no lost styles); when interop demands it,
convert.pyper skill round-trips through Microsoft Office formats (DOCX / XLSX / PPTX, plus legacy DOC / XLS / PPT) via headless LibreOffice. No tool in the agent ecosystem covers both directions natively. - Stdlib-only core. Every generator, validator, and edit script runs without
pip install—xml.etree.ElementTreeandzipfileonly. LibreOffice is optional, needed for rendering, formula recalculation, generated-index refresh, and the OOXML bridge. - Structure-preserving edits.
replace_textkeeps inline children (text:span,text:note,text:bookmark,text:a) intact;add_imageupdates the manifest andmeta.xml;replace_cellshandles typed values and formulas. No tool flattens your formatting. - Scholarly authoring, end-to-end. Footnotes, endnotes, citations (BibTeX or CSL-JSON), cross-references, MathML formulas (LaTeX→MathML via Pandoc), and generated indexes (table of contents, bibliography, illustration/table index, alphabetical index) — refreshed via headless LibreOffice. The only ODF-agent suite with this depth.
- Curated template ecosystem. Five English-first ODT templates (grant proposal, academic paper, letterhead, CV, dissertation) and three branded ODP templates ship in-box; an
inspect_template/extract_template/apply_templatetoolchain lets users bring their own from any.odt/.ott/.docx/.odp/.otp/.pptx. Templates are bundled into every Smithery / skills.sh / Claude Code plugin install. - Audit- and Git-friendly. Every edit writes
meta:modification-date,meta:generator, and incrementsmeta:editing-cycles. Pack to flat ODF (.fodt/.fodp/.fods/.fodg) andgit diffshows real, reviewable changes — embedded images and all. - Tested. 450 unit, integration, and property-based tests on every push across Python 3.10–3.13. CI installs LibreOffice so the render / recalc / convert / index-refresh paths are exercised, validates against the OASIS ODF 1.3 RelaxNG schema with
--strict, and runstests/test_corpus.pyagainst LibreOffice-roundtripped real-world fixtures to catch regressions native-LO files would surface.
| Skill | Generation | Editing | Format-specific |
|---|---|---|---|
| ODT | spec-driven; Markdown → ODT with rich inline (text:span, links, GFM tables, footnotes); 5 shipped templates |
structure-preserving text/image edits; bulk restyle; block insert/delete; table editing (rows, columns, cells); tracked changes; comments | footnotes, citations (BibTeX/CSL-JSON), cross-references, MathML, generated indexes (TOC, bibliography, illustration/alphabetical index) |
| ODP | spec-driven with six standard slide layouts and multiple master pages; 3 shipped templates | per-slide layout/master reassignment; clone slide; add image; master-page customization (background, header/footer, logo) | animations (entrance/exit/emphasis/motion paths), slide transitions, contact-sheet visual design loop |
| ODS | spec-driven, themed header rows | typed cells, formulas, named ranges, data validation (dropdowns + range constraints) | embedded charts (bar/line/pie/scatter), conditional formatting, pivot tables (computed + refreshable), formula recalc via soffice |
| ODG | spec-driven with role-styled shapes; per-shape styling keys | edit labels; add shape image; per-shape colours | connectors with shape binding, glue points, groups; flowcharts, org charts; PDF/SVG/PNG export |
Shared by all four: --theme NAME (5 curated palette + font pairings); RelaxNG --strict validation against the OASIS ODF 1.3 schema; flat-ODF roundtrip; render.py to PDF / per-page PNG / contact sheet; MIME-byte-detected image embedding; meta.xml lifecycle on every edit; bidirectional convert.py to/from the matching Microsoft Office format (ODT ↔ DOCX/DOC, ODS ↔ XLSX/XLS, ODP ↔ PPTX/PPT).
The skills ship as a toolbox so an agent can compose freely — but for human users, docs/workflows.md opens with a goal-oriented cookbook: paste-and-edit pipelines for the most common outcomes.
| Recipe | Outcome |
|---|---|
| Grant proposal | briefing + bibliography → branded ODT + PDF (template + citations + TOC + bibliography) |
| Conference deck | outline → branded ODP + contact-sheet preview |
| Academic paper | Markdown + refs.bib → IMRaD ODT with bibliography |
| Dissertation skeleton | spec → dissertation ODT with all four index types populated |
| Spreadsheet report | data → ODS with named ranges + chart + recalc |
| DOCX interop bridge | DOCX in → ODT edit → DOCX out |
Fork the examples. Each recipe is also a reference pipeline that you adapt into a one-command script — exactly the pattern of the shipped build_*.py examples:
examples/dao/build_grant_proposal.py— DAO-branded German grant proposal end-to-end (forks recipe #1)examples/deck/build_deck.py— branded ODP deck end-to-end (forks recipe #2)examples/diagram/build_diagram.py— branded flowchart end-to-end
Copy one of these into your project, swap the inputs (spec.json, refs.bib, template choice), and you have a single-command pipeline tailored to your workflow. Each is a thin orchestrator over the same skill scripts the recipes call.
- In-place native-OOXML editing (open
.docx/.xlsx/.pptx, edit as DOCX/XLSX/PPTX, save back as DOCX/XLSX/PPTX) — usepython-docx,openpyxl,python-pptx, orpandoc. One-shot conversion in either direction ships viaconvert.py; for sustained DOCX work the natural pattern isconvert.py → edit as ODF → convert.pyback. - Master-page inheritance chains — ODF has no such concept; slides reference a master page and a slide layout independently, both supported.
See ROADMAP.md for the trajectory across the v0.2 – v1.13 releases.
Detailed documentation lives in docs/index.md:
- Installation
- Agent Compatibility
- OpenDocument Workflows
- Script Reference
- Library API
- Repository Layout
The skills are available through three channels — pick what fits your setup:
Browse and install via smithery.ai. Install one or more skills directly through the Smithery UI: odt, odp, ods, odg.
The repository is also a Claude Code plugin marketplace. Add it once, then install the plugin — all four skills come bundled:
/plugin marketplace add leiverkus/open-document-skills
/plugin install open-document-skills@leiverkus-skills
/plugin marketplace update pulls later releases.
The vercel-labs/skills CLI installs across Claude Code, Codex, Cursor, OpenCode, and 50+ other agents:
# List skills in the repo
npx skills add leiverkus/open-document-skills --list
# Install all four globally for Claude Code
npx skills add leiverkus/open-document-skills --skill '*' -a claude-code -g
# Install only ODT into your project
npx skills add leiverkus/open-document-skills --skill odtInstall all four skills at once via the bundled Python installer:
python3 scripts/install_skills.pyBy default, the installer writes to $CODEX_HOME/skills when CODEX_HOME is set, otherwise to:
~/.codex/skillsIf your setup uses the older .agents directory, install there explicitly:
python3 scripts/install_skills.py --target agentsExisting skill directories are skipped by default. To intentionally overwrite the installed copies:
python3 scripts/install_skills.py --target agents --replaceFor OpenCode global skills:
python3 scripts/install_skills.py --target opencodeTo install project-local OpenCode skills:
python3 scripts/install_skills.py --target opencode --dest .opencode/skillsFor Claude Code, this repository can be used as a skill-focused plugin because it contains .claude-plugin/plugin.json and a top-level skills/ directory. To create a plugin bundle at a chosen destination:
python3 scripts/install_skills.py --target claude --dest ./dist/open-document-skillsThen add or install that plugin directory in Claude Code.
To install from a local checkout:
git clone https://github.com/leiverkus/open-document-skills.git
cd open-document-skills
python3 scripts/install_skills.pyThe shared library behind the four skills is published to PyPI as
open-document-lib. Use it
directly in any Python project — no skill bundling required:
pip install open-document-libfrom odf_lib import pack_flat_odf, replace_text_in_element, validate_against_schemaThe core has no dependencies beyond the standard library; [validate]
pulls in lxml for RelaxNG validation and [scholarly] pulls in
bibtexparser. See docs/library-api.md for the
full public API.
Core scripts use only the Python standard library.
Recommended optional tools:
- LibreOffice, for rendering/export/recalculation workflows
pdftoppmfrom Poppler, when you want PDF pages rendered to images- Pandoc, for some conversion fallback workflows
Install all optional tools on macOS with Homebrew:
brew install --cask libreoffice
brew install poppler pandocInstall all optional tools on Windows with winget:
winget install --id TheDocumentFoundation.LibreOffice -e
winget install --id oschwartz10612.Poppler -e
winget install --id JohnMacFarlane.Pandoc -eInstall all optional tools on Ubuntu with apt:
sudo apt-get update
sudo apt-get install -y libreoffice poppler-utils pandocLibreOffice usually provides soffice inside the app bundle, not directly on the shell PATH:
/Applications/LibreOffice.app/Contents/MacOS/sofficeThe render/recalc scripts look for that macOS path automatically. They also check common Linux and Windows locations.
Runnable examples live in examples/. They are meant as a practical first test layer for users of the skills:
python examples/build_examples.pyThis creates ODT, ODP, ODS, and ODG files in examples/output/, then validates their package references. The generated output directory is ignored by Git.
For optional LibreOffice QA:
python examples/build_examples.py --renderOn macOS, add --png when Poppler is installed with Homebrew and PNG page previews are useful:
python examples/build_examples.py --render --pngSome workflows are intentionally optional because they require LibreOffice:
- render ODT/ODP/ODG to PDF or images
- export ODG to SVG/PNG
- recalculate ODS formulas
- refresh generated indexes in ODT (table of contents, bibliography, alphabetical index)
- convert between ODF and Microsoft Office formats (DOCX/XLSX/PPTX, and legacy DOC/XLS/PPT)
- round-trip conversions from Markdown/HTML
The skills treat these as QA or interoperability steps. Native ODF package generation and XML-safe edits remain the preferred path when the target deliverable is an ODF file.
Every format has pack_* and unpack_* scripts that convert between the zipped ODF package and a flat single-XML file (.fodt, .fodp, .fods, .fodg). The flat form is part of the OASIS specification, opens directly in LibreOffice, and produces readable diffs under Git. Embedded images are inlined as base64 on pack and extracted back to Pictures/ on unpack.
python skills/odt/scripts/pack_fodt.py document.odt -o document.fodt
git diff document.fodt
python skills/odt/scripts/unpack_fodt.py document.fodt -o document.odtSee docs/workflows.md for details.
The helpers are pure-Python and stream through ZIP packages without loading LibreOffice. End-to-end CLI latency on a representative laptop:
| Format | Document | Create | Edit | Validate |
|---|---|---|---|---|
| ODT | 2000 paragraphs | 55 ms | 54 ms (replace_text) |
48 ms |
| ODS | 100 000 cells (1000×100) | 398 ms | 428 ms (replace_cells) |
689 ms |
| ODP | 100 slides | 45 ms | 42 ms (clone_slide) |
42 ms |
| ODG | 500 shapes | 47 ms | — | 44 ms |
Every timing includes Python interpreter startup (~40 ms), so small
documents are startup-bound; large spreadsheets are the heaviest case and
still finish well under a second. Reproduce or re-measure with
benchmarks/run_benchmarks.py. Numbers are
indicative and machine-dependent.
Development setup, the test loop, and the release checklist live in CONTRIBUTING.md. Version history is in CHANGELOG.md; planned work is in ROADMAP.md.
MIT. See LICENSE.