A Python library that simplifies editing Google Slides through an HTML-like abstraction
Project description
extraslide
A Python library that converts Google Slides to/from SML (Slide Markup Language) - an XML-based format optimized for AI agent editing.
Overview
extraslide enables AI agents (Claude Code, Codex, etc.) to read and edit Google Slides through a simple workflow:
- Pull - Download a presentation as editable SML files
- Edit - Agent modifies the SML based on user instructions
- Diff - Preview changes before applying (dry run)
- Push - Apply changes to Google Slides
The library handles all the complexity of the Google Slides API - agents just edit XML.
Installation
pip install extraslide
# or
uvx extraslide --help
The Pull-Edit-Diff-Push Workflow
Step 1: Pull
Download a presentation to a local folder:
uvx extraslide pull "https://docs.google.com/presentation/d/1abc.../edit"
This creates a folder structure:
1abc.../
presentation.json # Metadata (title, ID, dimensions)
id_mapping.json # clean_id -> google_object_id mapping
styles.json # Styles for each element (position, fill, stroke, text)
slides/
01/content.sml # Slide 1 content
02/content.sml # Slide 2 content
...
.pristine/
presentation.zip # Original state for diff comparison
.raw/
presentation.json # Raw API response (for debugging)
Step 2: Edit
The agent edits slides/NN/content.sml files based on user instructions. SML uses a minimal XML syntax:
<Slide>
<TextBox id="e1" x="100" y="50" w="500" h="80">
<P><T>Quarterly Report</T></P>
</TextBox>
<Rect id="e2" x="50" y="200" w="300" h="150"/>
</Slide>
Common edits:
- Change text content inside
<T>tags - Modify positions (
x,y) or sizes (w,h) - Add/delete elements
- Copy elements (duplicate with same ID, new position, omit w/h)
See copy-workflow.md for the copy-based editing guide.
Step 3: Diff (Preview)
See what changes will be applied without modifying the original:
uvx extraslide diff 1abc.../
This compares the current slides/ content against the .pristine/ copy and outputs the Google Slides API requests that would be generated. No API calls are made.
Step 4: Push
Apply the changes to Google Slides:
uvx extraslide push 1abc.../
The library sends a batchUpdate request to the Google Slides API. All edits appear in Google Drive version history with proper attribution.
SML Format
Each slide is stored as a separate content.sml file with minimal XML:
<Slide>
<TextBox id="e1" x="100" y="50" w="500" h="80">
<P><T>Title text</T></P>
</TextBox>
<Rect id="e2" x="50" y="200" w="300" h="150"/>
<Group id="g1" x="400" y="100">
<Ellipse id="e3" x="0" y="0" w="50" h="50"/>
<Ellipse id="e4" x="60" y="0" w="50" h="50"/>
</Group>
</Slide>
Elements
| Element | Description |
|---|---|
<TextBox> |
Text container with paragraphs |
<Rect>, <Ellipse>, <RoundRect> |
Basic shapes |
<Line> |
Lines and connectors |
<Image> |
Images |
<Table> |
Tables with <Row> and <Cell> |
<Group> |
Grouped elements (children use relative positions) |
<Video> |
Embedded videos |
<SheetsChart> |
Linked Google Sheets charts |
Text Content
Text uses a paragraph (<P>) and text run (<T>) structure:
<TextBox id="e1" x="50" y="100" w="400" h="200">
<P><T>Regular text </T><T>more text</T></P>
<P><T>Second paragraph</T></P>
</TextBox>
Positions and Sizes
All positions (x, y) and sizes (w, h) are in points:
<Rect id="e1" x="100" y="200" w="300" h="150"/>
For elements inside groups, positions are relative to the group's origin.
Copying Elements
To copy an element, duplicate its XML with:
- Same
idas the source element - New
x,yposition - Omit
wandh(this signals a copy)
<!-- Original -->
<Rect id="e1" x="100" y="100" w="200" h="100"/>
<!-- Copy (omit w/h to signal copy) -->
<Rect id="e1" x="400" y="100"/>
See copy-workflow.md for details.
CLI Reference
# Pull a presentation
uvx extraslide pull <url_or_id> [output_dir]
uvx extraslide pull "https://docs.google.com/presentation/d/1abc.../edit"
uvx extraslide pull "https://docs.google.com/presentation/d/1abc.../edit" ./my-folder
# Preview changes (dry run)
uvx extraslide diff <folder>
uvx extraslide diff ./1abc.../
# Apply changes
uvx extraslide push <folder>
uvx extraslide push ./1abc.../
Also works as a Python module:
python -m extraslide pull ...
python -m extraslide diff ...
python -m extraslide push ...
Important Notes
Re-pull After Push
After pushing changes, the local SML becomes stale. Always re-pull before making more edits:
uvx extraslide push ./1abc.../
uvx extraslide pull "https://docs.google.com/presentation/d/1abc.../edit" # Re-pull!
# Now safe to edit again
What Can Be Edited
- Text content and styling
- Shape properties (fill, stroke, position, size)
- Add/delete slides
- Add/delete elements
- Copy existing elements
- Tables (content and basic styling)
- Images (can reference existing, limited creation support)
- Charts (read-only, linked to source spreadsheet)
Styles
Element styles (fill, stroke, text formatting) are stored in styles.json and automatically applied when copying elements. You don't need to specify styles in the SML - just copy an element and modify the text/position.
Documentation
- Copy-Based Editing Guide - How to copy and modify elements
- SML Syntax Specification - Full format reference
Requirements
- Python 3.10+
- A valid Google Slides access token supplied by the caller
Project Status
Alpha - The library is functional but still evolving. SML format and CLI may change.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file extraslide-0.2.3.tar.gz.
File metadata
- Download URL: extraslide-0.2.3.tar.gz
- Upload date:
- Size: 239.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
636ee161151a8820d3dd3d33b9fa2e7eae15bbe9fabb2a0234b8904ba7d13a66
|
|
| MD5 |
7fef5978543a02122446dd4f2fa4301c
|
|
| BLAKE2b-256 |
1c935c00238dc0d5469c8ecbd58174ebc7b2d82f976b1d095042374ff1530a4d
|
Provenance
The following attestation bundles were made for extraslide-0.2.3.tar.gz:
Publisher:
publish-extraslide.yml on think41/extrasuite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
extraslide-0.2.3.tar.gz -
Subject digest:
636ee161151a8820d3dd3d33b9fa2e7eae15bbe9fabb2a0234b8904ba7d13a66 - Sigstore transparency entry: 1187948395
- Sigstore integration time:
-
Permalink:
think41/extrasuite@7a2d4f4cde64015b0a62a034f5af17cf14eb89c3 -
Branch / Tag:
refs/tags/extraslide-v0.2.3 - Owner: https://github.com/think41
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-extraslide.yml@7a2d4f4cde64015b0a62a034f5af17cf14eb89c3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file extraslide-0.2.3-py3-none-any.whl.
File metadata
- Download URL: extraslide-0.2.3-py3-none-any.whl
- Upload date:
- Size: 48.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b648709ee4af23bddd252d54f1b180c61bd508221fe341c93c1fe297d83b31e9
|
|
| MD5 |
214a0fdbe7a6d98fab86ce05cdb11d30
|
|
| BLAKE2b-256 |
47d81c8f8b427f8dce3f13a161156435d4ed1a7f24058924d1d67c8e85e90712
|
Provenance
The following attestation bundles were made for extraslide-0.2.3-py3-none-any.whl:
Publisher:
publish-extraslide.yml on think41/extrasuite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
extraslide-0.2.3-py3-none-any.whl -
Subject digest:
b648709ee4af23bddd252d54f1b180c61bd508221fe341c93c1fe297d83b31e9 - Sigstore transparency entry: 1187948402
- Sigstore integration time:
-
Permalink:
think41/extrasuite@7a2d4f4cde64015b0a62a034f5af17cf14eb89c3 -
Branch / Tag:
refs/tags/extraslide-v0.2.3 - Owner: https://github.com/think41
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-extraslide.yml@7a2d4f4cde64015b0a62a034f5af17cf14eb89c3 -
Trigger Event:
push
-
Statement type: