compono
Agent-oriented, code-based PPTX/DOCX generation. Describe a deck or document as typed primitives — an LLM agent never writes raw coordinates or touches OOXML.
compono lets an LLM agent (or a human) describe a slide deck as data —
headers, bullet text, stats, tables, charts, images, process sequences,
shapes — and get back a real, editable .pptx file. The agent never writes
raw x/y/w/h coordinates: a constraint-based layout resolver computes
every position from a small set of typed primitives.
Every rendered element is a genuine, editable native shape (p:sp, p:pic,
p:graphicFrame) — never a flattened image or embedded video. Open the
result in PowerPoint and drag a box around; it's a real object, not a
picture of one.
compono also generates .docx documents — its second output format, for
linear content (proposals, reports) rather than slides, with its own
smaller primitive set (heading, paragraph, bullet_list, table,
image, chart, ...). See DOCX generation for the full
write-up; the rest of this README covers the original .pptx path.
Building a JS/TS agent harness instead of a Python one? See
compono-js — a parallel TypeScript port of the same
schema/resolver/validator/render pipeline, plus review(), Inspire, and
DOCX generation, plus an MCP server — same primitive-JSON contracts,
independent implementation and version.
Why compono
Ask an LLM to write raw python-pptx (or drive a browser-based renderer
like pptx.js) and you get code littered with hand-picked EMU coordinates —
the model has to simultaneously invent content and do pixel-perfect
layout math it's genuinely bad at. The usual failure modes: overlapping
boxes, text running off the slide, margins that drift slide to slide,
titles crammed against the edge. None of that is a content problem; it's
a coordinates problem.
compono removes coordinates from the agent's job entirely:
- You describe intent, not geometry.
{"primitive": "grid", "columns": 2, ...}, notleft=Inches(0.6), top=Inches(1.9), width=.... A directional, flexbox-style resolver computes every real position. - A cheap pre-flight check, before paying render cost.
validate(spec)catches schema errors, layout impossibilities, and text overflow — measured against real glyph metrics, not guessed — in milliseconds, with no file write. Bad specs get a structured{slide, primitive, field, error, detail, fix}back, not a broken.pptxor a stack trace. - A design-quality pass, still optional.
review(spec)— contrast, whitespace, image-fit, font-size-near-overflow, style — flags things a human designer would notice that "renders successfully" doesn't catch. - Nothing is ever a flattened image. Every primitive is a real, editable OOXML shape or graphicFrame. A generated table is a real table; a generated chart has live, editable series data. Open the file and it's actually still a deck, not a picture of one.
The result: an agent's job shrinks to "pick the right primitives and content," and a resolver + validator handle everything spatial.
Install
pip install compono
# or
uv add compono
Quickstart
from compono import render_deck
spec = {
"slides": [
{
"header": {"title": "Q3 Results", "subtitle": "Engineering team"},
"body": [
{
"primitive": "text",
"mode": "bullets",
"content": [
"Shipped the new layout resolver",
"Cut render time by 40%",
"Zero overflow bugs in production",
],
"emphasis_indices": [1],
}
],
}
]
}
report = render_deck(spec, "deck.pptx")
print(report.pptx_path, report.warnings)
Or from the command line:
compono validate spec.json
compono render spec.json -o deck.pptx
How an agent should use this
The intended loop is validate, fix, render — not "render and hope":
- Build a spec (plain
dict/JSON — whatever your tool-calling naturally produces). validate(spec)— cheap, no file write. If.validisFalse, apply each error'sfixfield directly and re-validate.- Optionally
review(spec)once it validates — apply suggestions that matter for this deck, ignore the rest; it never blocks anything. render_deck(spec, output_path)— writes the real.pptx. It refuses to write anything on a validation failure, so a broken spec never produces a broken file.
compono reference (or compono.reference() in Python) prints the same
full reference an MCP client or Claude Code skill would get — useful if
you're wiring up a different agent framework and want the whole primitive
catalog and error shape in one shot.
Documentation
- Getting started — install, quickstart, core concepts
- API reference — verbs, error shape, the feedback loop, design review
- Primitives — one page per primitive, with fields and runnable examples
- Templates and fonts —
Deck.template,font_family - CLI
- MCP server —
compono-mcp, and what to do when compono has no context - Inspire — scan liked decks into a style profile/skill, structure and style only, never literal content
- DOCX generation — compono's second output format, for linear documents rather than slides
- compono-js — TypeScript port (pptx via pptxgenjs, plus review/Inspire/DOCX) and its MCP server, for JS/TS agent harnesses
- Claude Code plugin
- Examples — rendered screenshots across genres, from real
examples/*.jsonspecs
(Absolute links, not relative — this README is also rendered as-is on PyPI, which can't resolve links to other files in the repo.)
Agents: the full reference in one file is compono reference /
compono.reference(), or
skills/compono/SKILL.md
— that's the doc written for you, not this page.
Contributing
See CONTRIBUTING.md
for dev setup, branching, and code style. If you're using Claude Code,
.claude/README.md
describes the build-workflow skill, review subagent, and commit/format
hooks set up for this repo.
Metadata
Release files for compono 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| compono-0.5.0.tar.gz | 140.4 kB | Without provenance | Details for compono-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| compono-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for compono-0.5.0-py3-none-any.whl |
Total release size: 288.1 kB
Release files / compono-0.5.0.tar.gz
| Download URL | compono-0.5.0.tar.gz |
|---|---|
| Size | 140.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b03e7497607b0ff60cd0120912c44deea68ebbf7d1fc89d740fe5515ca367df
|
|
BLAKE2b-256 checksum How to use checksums |
a4a1f274a13f28311467fe969e4513c059ebc36e31b266a9c24001d7af1a011e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / compono-0.5.0-py3-none-any.whl
| Download URL | compono-0.5.0-py3-none-any.whl |
|---|---|
| Size | 147.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
507b302d470610ec43a17024b0029a80e5ad4c226ada72e961324f2eceeac2c7
|
|
BLAKE2b-256 checksum How to use checksums |
753e022f9dbf9a9c45e85a0ab8b8563a59e4d51868c81fa8c2cb006a06dad3d0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for compono 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.