Polyptych Studio
Turn a source essay (markdown) into visual media. Polyptych Studio ships two
fully independent pipelines — a slide deck generator and a single-page
infographic generator — built on multi-provider text generation (Gemini,
OpenAI, xAI, Anthropic, Vertex AI) and multi-provider image generation (Gemini,
OpenAI, xAI, Vertex AI via pixbridge).
Full documentation — tutorial, how-to guides, reference, and architecture explanation.
Pipelines
Each pipeline takes a source essay (markdown) and produces a different kind of visual output.
| Pipeline | Command | Output | Use case |
|---|---|---|---|
| Slide | polyptych deck |
Presentation deck (10–30 slides with images) | Essay-to-slides conversion |
| Infographic | polyptych infographic |
Single-page infographic(s), N variants | Quick visual summary of key data |
Both run unattended end-to-end: the LLM text tasks (slide: task1→task7;
infographic: i0→i2) run first, then image generation.
Both infographics above were generated by Polyptych Studio itself from
examples/about-polyptych-studio.mdusing theinfographicpipeline and thesemi-flat-vectorstyle.
For more examples, see the AI-generated part of my homepage: jdinkla.github.io/ai-generated.
Installation
Install the published package (the distribution and import name is polyptych;
this repository is polyptych-studio):
pip install polyptych # or: uv add polyptych
Or work from a clone of this repo:
uv sync
Optional external tool: ImageMagick (brew install imagemagick) for
collecting a slide deck into a PDF via just create-pdf.
Environment variables
Set a key for each provider you intend to use (copy .envrc.example to .envrc,
or export them however you manage secrets):
| Provider | Environment variable |
|---|---|
| Gemini (text + image) | GOOGLE_API_KEY |
| OpenAI (text + gpt-image-2) | OPENAI_API_KEY |
| xAI / Grok | XAI_API_KEY |
| Anthropic Claude | ANTHROPIC_API_KEY |
| Vertex AI | Application Default Credentials (gcloud auth application-default login) |
Quick start
An example source (examples/scene.md, a short noir scene) ships with the repo.
# Infographic (3 text tasks + images)
uv run polyptych infographic examples/scene.md -o generated/my-infographic
# Slide deck
uv run polyptych deck examples/scene.md -o generated/my-slides
With style presets
A few example visual-style presets ship under prompts/style-transfer/
(anime/, editorial/, infographic/, noir/, period-art/). Point --style
at any preset markdown file, or author your own (see
Write Style Prompts):
uv run polyptych deck examples/scene.md --style prompts/style-transfer/noir/cinematic-illustrative-noir.md
uv run polyptych infographic examples/scene.md --style prompts/style-transfer/infographic/semi-flat-vector.md
Presets, resume, and selective regeneration
# Reusable provider/size/quality bundles from image-presets.yaml
uv run polyptych deck examples/scene.md --image-preset openai-high
# Resume from image generation (text tasks already done)
uv run polyptych deck examples/scene.md -o generated/my-slides --from images
# Regenerate specific slides only
uv run polyptych deck examples/scene.md -o generated/my-slides --from images --slides 3,7,12
See the Resume Pipeline guide for details.
Use just --list for all workflow shortcuts and the
CLI Reference for the full flag set.
Operating modes
The system can be driven two ways:
- Python CLI — run
polyptychdirectly (or viajusttargets). Best for scripts, CI, batch runs, and reproducible pipelines. - Agent skills — inside Claude Code, use slash commands such as
/run-pipeline; inside Codex, invoke the same repository workflows as$run-pipeline,$run-local-pipeline,$infographic,$review-regen, or$edit-output. Best for exploration, guided iteration, and running text tasks with the active coding agent as the LLM (zero external API cost for text). The shared skill list is in CLAUDE.md, with Codex-specific entry guidance in AGENTS.md.
Both surfaces share the same task templates, schemas, and output layout. See Operating Modes for the comparison.
Codex setup
Open the repository as a Codex project. Codex automatically discovers
AGENTS.md, the shared skills under .agents/skills/, the read-only
prompt_consistency_reviewer under .codex/agents/, and the project hooks in
.codex/hooks.json. Review and trust the hooks when Codex prompts; they block
edits to secrets-bearing .env* files and format changed Python files.
Project structure
src/
common/ # Shared utilities (usage logging)
polyptych/ # Pipelines, CLI, models, tasks
pipeline.py # Pipeline orchestration (slide + infographic mixins)
cli.py # polyptych CLI
models/ # Pydantic schemas (slide.py, infographic.py)
tasks/ # Task implementations (task_01..task_07, task_i0..task_i2)
prompts/
tasks/ # Task prompt templates
style-transfer/ # Example visual style presets
providers/ # Provider-specific best practices
docs/ # Documentation (tutorial, how-to, reference, explanation)
model_config.yaml # Per-task LLM model tier configuration
image_model_config.yaml # Per-provider image generation model configuration
image-presets.yaml # Reusable image-generation presets
pipeline-presets.yaml # Pipeline-specific behavior presets
justfile # Common workflow shortcuts
Image generation is provided by the pixbridge
PyPI package (pixbridge CLI), which supports Gemini, OpenAI, xAI, and Vertex.
Using Vertex AI
gcloud auth login
gcloud auth application-default login
Vertex AI uses Application Default Credentials. The vertex text and image
providers use the same Gemini models but route through Google Cloud.
Continuous integration
.github/workflows/ci.yml runs on every pull request and on pushes to main,
gating three checks (a failure in any fails the build):
| Check | Command |
|---|---|
| Lint | uv run ruff check src/ |
| Type check | uv run pyright src/ |
| Unit tests | uv run pytest -m "not integration" tests/ |
Run the same locally with just lint, just typecheck, just test.
Integration tests (@pytest.mark.integration) are excluded — they call real,
paid LLM / image APIs. All dependencies (including pixbridge) resolve from
PyPI, so CI needs no special access.
License
Release files for polyptych 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| polyptych-0.3.2.tar.gz | 261.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| polyptych-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 504.4 kB
Release files / polyptych-0.3.2.tar.gz
| Download URL | polyptych-0.3.2.tar.gz |
|---|---|
| Size | 261.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fdf2e15286dc2f273d09995af5a68ac253bc5d329e6b6c202c5ebd38e1f4a07d
|
|
BLAKE2b-256 checksum How to use checksums |
1cde8b5473c45c241ad224719fc784488ed5f917996f19d2537739eeac5c59f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / polyptych-0.3.2-py3-none-any.whl
| Download URL | polyptych-0.3.2-py3-none-any.whl |
|---|---|
| Size | 243.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74fe83c477060fae31d6c05d216927dd6f705b524b3234af4c4062be0c9fbd80
|
|
BLAKE2b-256 checksum How to use checksums |
9b0fbe3ee885049d849f578c70d6610429fd9726ef08474c5d1a8b6b6251a36a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|