{"id":51057075,"url":"https://github.com/artpar/puppt","last_synced_at":"2026-06-22T22:04:25.269Z","repository":{"id":362006646,"uuid":"1256837854","full_name":"artpar/puppt","owner":"artpar","description":"Go CLI for inspecting, editing, creating, validating, reviewing, and rendering editable PowerPoint .pptx files.","archived":false,"fork":false,"pushed_at":"2026-06-10T08:18:27.000Z","size":31857,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T08:23:06.594Z","etag":null,"topics":["automation","cli","document-automation","go","ooxml","openxml","powerpoint","pptx","presentationml","rendering"],"latest_commit_sha":null,"homepage":"https://github.com/artpar/puppt#readme","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/artpar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"docs/SUPPORT_MATRIX.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-02T06:11:28.000Z","updated_at":"2026-06-10T08:18:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/artpar/puppt","commit_stats":null,"previous_names":["artpar/puppt"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/artpar/puppt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artpar%2Fpuppt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artpar%2Fpuppt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artpar%2Fpuppt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artpar%2Fpuppt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/artpar","download_url":"https://codeload.github.com/artpar/puppt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artpar%2Fpuppt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34667007,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","cli","document-automation","go","ooxml","openxml","powerpoint","pptx","presentationml","rendering"],"created_at":"2026-06-22T22:04:24.685Z","updated_at":"2026-06-22T22:04:25.264Z","avatar_url":"https://github.com/artpar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Puppt\n\n[![Release](https://img.shields.io/github/v/release/artpar/puppt?include_prereleases\u0026sort=semver)](https://github.com/artpar/puppt/releases)\n[![CI](https://github.com/artpar/puppt/actions/workflows/ci.yml/badge.svg)](https://github.com/artpar/puppt/actions/workflows/ci.yml)\n[![Release workflow](https://github.com/artpar/puppt/actions/workflows/release.yml/badge.svg)](https://github.com/artpar/puppt/actions/workflows/release.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/artpar/puppt.svg)](https://pkg.go.dev/github.com/artpar/puppt)\n[![Go Report Card](https://goreportcard.com/badge/github.com/artpar/puppt)](https://goreportcard.com/report/github.com/artpar/puppt)\n\nPuppt is a Go CLI for inspecting, editing, validating, reviewing, and\nrendering editable PowerPoint `.pptx` files.\n\nIt is built for agent and automation workflows where a deck must stay editable:\nPuppt reads the PowerPoint Open XML package, plans mutations before writing,\nrejects ambiguous or unsupported edits before mutation, and preserves unrelated\ndeck content wherever the package structure allows it.\n\n## What You Can Do\n\n- Inspect decks and return structured facts as JSON: slide order, titles,\n  visible text, notes, media, layouts, masters, metadata, and unsupported\n  content signals.\n- Plan targeted edits without writing output, so agents and humans can review\n  what will change before mutation.\n- Edit supported content, including text, notes, metadata, slide order, slide\n  add/delete/move/duplicate operations, image replacement, and simple editable\n  shape additions.\n- Validate package structure and expected content after edits.\n- Review changes by combining prior command results, inspection facts, skipped\n  items, unsupported items, and validation status.\n- Render a slide to PNG through Puppt-owned Go code for visual review and\n  diagnostics.\n\n## Quick Start\n\nDownload release artifacts and checksums from\n[GitHub Releases](https://github.com/artpar/puppt/releases).\n\nInstall from source:\n\n```sh\ngo install github.com/artpar/puppt/cmd/puppt@latest\n```\n\nBuild the local binary:\n\n```sh\nmake build\n```\n\n## Usage Examples\n\nPuppt works best as a tight loop: inspect the real `.pptx`, plan a targeted\nchange, write a new editable deck, review the result, and render the slides that\nneed a visual check.\n\nThe screenshots below are committed render outputs from the local renderer\ncorpus; use the same commands with any media-heavy `.pptx`.\n\n### Inspect\n\nUse `inspect` to turn a slide into stable JSON targets: text object IDs, text\nruns, and media relationship targets.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003eCommand\u003c/th\u003e\n    \u003cth\u003eSlide\u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cpre\u003e\u003ccode class=\"language-sh\"\u003e./bin/puppt inspect testdata/realworld-ppts/EPA-generate-2021-presentation.pptx --json |\n  jq '{status, slide:(\n    .inspection.slides[] |\n    select(.number == 2) |\n    {\n      number,\n      title,\n      part,\n      text_objects: [.visible_text[] | {object_id, runs}],\n      image_refs: [.images[] | {object_id, relationship, target, content_type}]\n    }\n  )}'\u003c/code\u003e\u003c/pre\u003e\n      \u003cpre\u003e\u003ccode class=\"language-json\"\u003e{\n  \"status\": \"ok\",\n  \"slide\": {\n    \"number\": 2,\n    \"title\": \"Energy 101: The big picture\",\n    \"part\": \"ppt/slides/slide2.xml\",\n    \"text_objects\": [\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#shape-2\",\n        \"runs\": [\n          \"Energy 101: The big picture\"\n        ]\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#shape-3\",\n        \"runs\": [\n          \"Primary energy resources\",\n          \"Fossil:  coal, natural gas, petroleum\",\n          \"Non-fossil, non-renewable:  uranium\",\n          \"Renewable: wind, solar, hydro, geothermal, biomass\",\n          \"Technologies to convert primary resources to \",\n          \"useable energy like electricity, gasoline, …\",\n          \"Petroleum Refineries\",\n          \"Electric Power Generation\",\n          \"End-use sectors\",\n          \"Residential\",\n          \"Commercial\",\n          \"Industrial \",\n          \"Transportation\",\n          \"Energy services – \",\n          \"What do people actually need and want?  \",\n          \"Mobility\",\n          \" (vehicle miles of travel) or \",\n          \"accessibility \",\n          \"(accessing education, work, shopping), \",\n          \"lighting\",\n          \" (lumens of light), \",\n          \"comfort\",\n          \" (space heating and cooling).  Energy is a “derived demand”\"\n        ]\n      }\n    ],\n    \"image_refs\": [\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId8\",\n        \"relationship\": \"rId8\",\n        \"target\": \"ppt/media/image12.png\",\n        \"content_type\": \"image/png\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId3\",\n        \"relationship\": \"rId3\",\n        \"target\": \"ppt/media/image7.jpeg\",\n        \"content_type\": \"image/jpeg\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId7\",\n        \"relationship\": \"rId7\",\n        \"target\": \"ppt/media/image11.png\",\n        \"content_type\": \"image/png\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId6\",\n        \"relationship\": \"rId6\",\n        \"target\": \"ppt/media/image10.png\",\n        \"content_type\": \"image/png\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId11\",\n        \"relationship\": \"rId11\",\n        \"target\": \"ppt/media/image15.png\",\n        \"content_type\": \"image/png\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId5\",\n        \"relationship\": \"rId5\",\n        \"target\": \"ppt/media/image9.png\",\n        \"content_type\": \"image/png\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId10\",\n        \"relationship\": \"rId10\",\n        \"target\": \"ppt/media/image14.png\",\n        \"content_type\": \"image/png\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId4\",\n        \"relationship\": \"rId4\",\n        \"target\": \"ppt/media/image8.jpeg\",\n        \"content_type\": \"image/jpeg\"\n      },\n      {\n        \"object_id\": \"ppt/slides/slide2.xml#rId9\",\n        \"relationship\": \"rId9\",\n        \"target\": \"ppt/media/image13.jpeg\",\n        \"content_type\": \"image/jpeg\"\n      }\n    ]\n  }\n}\u003c/code\u003e\u003c/pre\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/assets/readme/epa-generate-slide-2.png\" alt=\"Inspected slide 2 render\" width=\"390\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Render\n\nUse `render` to produce PNGs from the `.pptx` itself. The JSON tells you which\nslide part was painted and where the images were written.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003eCommand\u003c/th\u003e\n    \u003cth\u003eRendered PNGs\u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cpre\u003e\u003ccode class=\"language-sh\"\u003e./bin/puppt render \\\n  testdata/realworld-ppts/EPA-generate-2021-presentation.pptx \\\n  --slides 1-3 \\\n  --dpi 72 \\\n  --out 'docs/assets/readme/epa-generate-slide-{slide}.png' \\\n  --json |\n  jq '{status, outputs, renders, unsupported_count:(.unsupported|length)}'\u003c/code\u003e\u003c/pre\u003e\n      \u003cpre\u003e\u003ccode class=\"language-json\"\u003e{\n  \"status\": \"ok\",\n  \"outputs\": [\n    \"docs/assets/readme/epa-generate-slide-1.png\",\n    \"docs/assets/readme/epa-generate-slide-2.png\",\n    \"docs/assets/readme/epa-generate-slide-3.png\"\n  ],\n  \"unsupported_count\": 0\n}\u003c/code\u003e\u003c/pre\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"docs/assets/readme/epa-generate-slide-1.png\" alt=\"Rendered slide 1\" width=\"240\"\u003e\u003cbr\u003e\n      \u003cimg src=\"docs/assets/readme/epa-generate-slide-2.png\" alt=\"Rendered slide 2\" width=\"240\"\u003e\u003cbr\u003e\n      \u003cimg src=\"docs/assets/readme/epa-generate-slide-3.png\" alt=\"Rendered slide 3\" width=\"240\"\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Edit\n\nUse the object id from `inspect` to mutate one editable object without touching\nunrelated slide content.\n\nSave this as `.tmp/readme-edit-visual/replace-title.json`:\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003eCommand\u003c/th\u003e\n    \u003cth\u003eBefore / After\u003c/th\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cpre\u003e\u003ccode class=\"language-json\"\u003e{\n  \"operation\": \"replace_text\",\n  \"target\": {\n    \"type\": \"object_id\",\n    \"object_id\": \"ppt/slides/slide2.xml#shape-2\"\n  },\n  \"replacement\": \"Energy 101: Edited with Puppt\"\n}\u003c/code\u003e\u003c/pre\u003e\n      \u003cpre\u003e\u003ccode class=\"language-sh\"\u003e./bin/puppt edit \\\n  testdata/realworld-ppts/EPA-generate-2021-presentation.pptx \\\n  --edit .tmp/readme-edit-visual/replace-title.json \\\n  --out .tmp/readme-edit-visual/epa-generate-edited.pptx \\\n  --json |\n  jq '{status, summary, changes, validation}'\u003c/code\u003e\u003c/pre\u003e\n      \u003cpre\u003e\u003ccode class=\"language-json\"\u003e{\n  \"status\": \"ok\",\n  \"summary\": {\n    \"human\": \"Applied replace_text with 1 change(s).\"\n  },\n  \"validation\": {\n    \"valid\": true,\n    \"warnings\": [],\n    \"errors\": []\n  }\n}\u003c/code\u003e\u003c/pre\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003cstrong\u003eBefore\u003c/strong\u003e\u003cbr\u003e\n      \u003cimg src=\"docs/assets/readme/epa-generate-slide-2.png\" alt=\"Before text edit\" width=\"300\"\u003e\u003cbr\u003e\n      \u003cstrong\u003eAfter\u003c/strong\u003e\u003cbr\u003e\n      \u003cimg src=\"docs/assets/readme/epa-generate-slide-2-after-edit.png\" alt=\"After text edit\" width=\"300\"\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Commands\n\n| Command | Use |\n| --- | --- |\n| `inspect` | Read a `.pptx` deck and return structured facts. |\n| `plan` | Resolve targets and validate an edit request without writing output. |\n| `edit` | Apply supported targeted edits and write a new `.pptx`. |\n| `validate` | Check package structure and expected content. |\n| `review` | Summarize deck changes for agents and human reviewers. |\n| `render` | Render one slide to a PNG image. |\n| `version` | Print Puppt version information. |\n\nRun command help for exact flags:\n\n```sh\npuppt --help\npuppt \u003ccommand\u003e --help\n```\n\nDuring development, use:\n\n```sh\ngo run ./cmd/puppt --help\n```\n\n## Editing Model\n\nPuppt treats `.pptx` files as structured Open XML packages, not as screenshots.\nThe normal edit flow is:\n\n1. Inspect the deck to find stable targets.\n2. Plan the edit and check whether the target is ready, ambiguous, missing, or\n   unsupported.\n3. Apply the edit only when the plan is supported.\n4. Validate the written deck.\n5. Review the result as JSON for downstream agents or human reviewers.\n\nAmbiguous targets and unsupported advanced visual edits are rejected before the\ndeck is mutated. Supported edits are written through Puppt-owned package\nhandling so unrelated parts of the deck stay intact.\n\n## Rendering\n\n`puppt render` is a Puppt-owned Go renderer. It does not shell out to\nLibreOffice, PowerPoint, Keynote, browser renderers, SaaS renderers, or\nimage-conversion tools.\n\nThe renderer currently covers practical static PPTX content including slide\ndimensions, backgrounds, themes, layouts and masters, placeholders, pictures,\ncommon image metadata, shape fills and outlines, connectors, text, bullets,\ntables, selected shadows/effects, simple diagram fallback drawings, and explicit\nJSON reports for content that is not painted or only partially painted.\n\nRenderer parity is still in progress. Puppt is useful for visual review and\ndiagnostics today, but final renderer conformance is not claimed yet. See\n`docs/RENDERING.md`, `docs/RENDERER_COMPLETION_GOAL.md`, and\n`docs/RENDERER_COMPLETION_CHECKLIST.md` for the current renderer status and\ncompletion path.\n\n## Current State\n\nPuppt has fixture-backed v1 workflows for inspection, edit planning, supported\nmutations, image replacement, simple editable additions, validation, review, and\nrendering. Full production-grade compliance is\nnot claimed yet.\n\nAll required v1 command names are implemented: `inspect`, `plan`, `edit`,\n`validate`, `review`, `render`, and `version`.\n\n## Development\n\nRun the baseline test suite:\n\n```sh\ngo test ./...\n```\n\nBuild the local binary:\n\n```sh\nmake build\n```\n\nRun the repository verification handoff:\n\n```sh\nmake verify\n```\n\n## Docs\n\nUser workflows:\n\n- [Commands](docs/COMMANDS.md)\n- [Plan examples](docs/PLAN_EXAMPLES.md)\n- [Failure modes](docs/FAILURE_MODES.md)\n- [Acceptance workflow](docs/ACCEPTANCE.md)\n\nCapability and status:\n\n- [Status](docs/STATUS.md)\n- [Support matrix](docs/SUPPORT_MATRIX.md)\n- [Rendering](docs/RENDERING.md)\n\nEngineering and completion:\n\n- [Renderer completion goal](docs/RENDERER_COMPLETION_GOAL.md)\n- [Renderer milestones](docs/renderer-milestones/00-INDEX.md)\n- [Build and release](docs/BUILD_RELEASE.md)\n- [Technical KT](docs/TECHNICAL_KT.md)\n\n## Implementation Language\n\nThe product core, CLI, public API surface, tests, and fixtures are implemented\nin Go.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartpar%2Fpuppt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartpar%2Fpuppt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartpar%2Fpuppt/lists"}