AI-first CLI for Google Slides — deterministic, JSON-native, agent-optimized
Project description
slides-agent
AI-first CLI for Google Slides — optimized for agents, scriptable, non-interactive, and JSON-native.
slides-agent gives AI agents (and humans) a deterministic, low-level interface to inspect and modify Google Slides presentations. Every command returns structured JSON. Every mutating command supports --dry-run. Every command has --help, --examples, and --schema.
Table of Contents
- Design Principles
- Installation
- Authentication Setup
- Quick Start
- Command Reference
- Agent Workflow Examples
- Output Format
- Error Model
- Safety Features
- JSON Schema Reference
- Development
Design Principles
| Principle | What it means |
|---|---|
| AI-first | Every command is non-interactive, scriptable, and JSON-friendly. |
| Deterministic | Outputs have stable IDs. The same command always returns the same shape. |
| Inspectable | deck inspect gives agents everything they need to plan before mutating. |
| Safe by default | --dry-run on all mutating commands. Fail loudly on ambiguous inputs. |
| Idempotent where possible | text replace and template fill can be re-run safely. |
| Verbose | Unusually detailed --help, --examples, and --schema on every command. |
Installation
Requirements: Python 3.12+
# Clone the repository
git clone <repo-url>
cd slides-goog
# Install (editable mode recommended for development)
pip install -e .
# Verify
slides-agent --version
slides-agent --help
For production use:
pip install slides-agent
Authentication Setup
slides-agent uses Google OAuth2. You need a client_secret.json file from Google Cloud Console.
Step 1 — Create a Google Cloud Project
- Go to console.cloud.google.com
- Create a new project (or select an existing one)
- Enable the Google Slides API and Google Drive API:
- APIs & Services → Library → "Google Slides API" → Enable
- APIs & Services → Library → "Google Drive API" → Enable
Step 2 — Create OAuth2 Credentials
- APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client ID
- Application type: Desktop app
- Download the JSON file — this is your
client_secret.json
Step 3 — Authenticate
slides-agent auth login --credentials-file ~/Downloads/client_secret.json
Your browser opens. Grant access. The token is cached at ~/.config/slides-agent/token.json.
Step 4 — Verify
slides-agent auth status
{
"ok": true,
"authenticated": true,
"token_file": "/Users/you/.config/slides-agent/token.json",
"token_exists": true,
"expired": false,
"scopes": [
"https://www.googleapis.com/auth/presentations",
"https://www.googleapis.com/auth/drive"
],
"client_id": "..."
}
Environment Variables
| Variable | Description |
|---|---|
SLIDES_AGENT_CREDENTIALS |
Path to client_secret.json (overrides --credentials-file) |
SLIDES_AGENT_TOKEN_FILE |
Override the token cache path (default: ~/.config/slides-agent/token.json) |
Quick Start
# 1. Find your presentation ID from the URL:
# https://docs.google.com/presentation/d/<PRESENTATION_ID>/edit
PRES_ID="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"
# 2. Inspect the full structure
slides-agent deck inspect --presentation-id $PRES_ID --pretty
# 3. List all slides and their IDs
slides-agent slide list --presentation-id $PRES_ID | jq '[.slides[] | {slide_id, slide_index}]'
# 4. Get all elements on slide 1
slides-agent element list --presentation-id $PRES_ID --slide-id <slide_id>
# 5. Replace all {{customer}} tokens
slides-agent text replace --presentation-id $PRES_ID --find '{{customer}}' --replace 'Acme Corp'
# 6. Set speaker notes
slides-agent notes set --presentation-id $PRES_ID --slide-id <slide_id> --text 'Talk track...'
Command Reference
How to Find IDs
Presentation ID: The segment between /d/ and /edit in the Google Slides URL:
https://docs.google.com/presentation/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms/edit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is your presentation_id
Slide IDs and Element IDs: Run deck inspect or slide list and extract from the JSON output:
slides-agent deck inspect --presentation-id <id> | jq '.presentation.slides[].slide_id'
slides-agent element list --presentation-id <id> --slide-id <sid> | jq '.elements[].element_id'
auth
Manage Google OAuth2 credentials.
auth login
slides-agent auth login --credentials-file /path/to/client_secret.json
| Flag | Description |
|---|---|
--credentials-file / -c |
Path to client_secret.json. Env: SLIDES_AGENT_CREDENTIALS. |
--pretty |
Pretty-print output. |
Output:
{
"ok": true,
"authenticated": true,
"token_file": "/Users/you/.config/slides-agent/token.json",
"scopes": ["https://www.googleapis.com/auth/presentations", "..."],
"message": "Login successful. Token cached."
}
auth status
slides-agent auth status
slides-agent auth status --pretty
Returns the current authentication state without making API calls.
auth logout
slides-agent auth logout
Deletes the cached token file. Does not revoke the token on Google's servers.
deck
Presentation-level operations.
deck inspect
slides-agent deck inspect --presentation-id <id>
slides-agent deck inspect --presentation-id <id> --pretty
slides-agent deck inspect --presentation-id <id> --schema # emit JSON schema
Returns the complete presentation structure: all slides, all elements, all text, all images, speaker notes, and theme references.
This is the foundation for agent planning. Run it first.
| Flag | Description |
|---|---|
--presentation-id / -p |
Presentation ID (required). |
--pretty |
Pretty-print output. |
--examples |
Show usage examples. |
--schema |
Emit JSON schema for the output. |
Output shape: See examples/sample_inspect.json.
Key output fields:
presentation.slides[].slide_id— use in slide/notes commandspresentation.slides[].elements[].element_id— use in text/image commandspresentation.slides[].elements[].placeholder_type—TITLE,BODY,SUBTITLE, etc.presentation.slides[].elements[].text.raw_text— current text contentpresentation.slides[].notes_text— current speaker notes
Examples:
# Get all slide IDs
slides-agent deck inspect -p abc123 | jq '[.presentation.slides[].slide_id]'
# Find all TITLE elements
slides-agent deck inspect -p abc123 | jq '[.presentation.slides[].elements[] | select(.placeholder_type == "TITLE") | {slide_id: .element_id, text: .text.raw_text}]'
# Get all text content across the deck
slides-agent deck inspect -p abc123 | jq '[.presentation.slides[].elements[] | select(.text != null) | .text.raw_text]'
deck duplicate
slides-agent deck duplicate --presentation-id <id> --title "QBR v2"
Creates an exact copy of the presentation. Returns the new presentation ID and URL.
| Flag | Description |
|---|---|
--presentation-id / -p |
Source presentation ID. |
--title / -t |
Title for the new presentation. |
Output:
{
"ok": true,
"original_presentation_id": "abc123",
"new_presentation_id": "xyz789",
"new_title": "QBR v2",
"drive_url": "https://docs.google.com/presentation/d/xyz789/edit",
"warnings": [],
"errors": []
}
slide
Slide-level operations.
slide list
slides-agent slide list --presentation-id <id>
slides-agent slide list --presentation-id <id> | jq '[.slides[] | {slide_id, slide_index, layout_name}]'
Returns all slides with their IDs, indices, layouts, and element summaries.
slide inspect
slides-agent slide inspect --presentation-id <id> --slide-id <slide_id>
Full detail for a single slide — all elements, text, transforms, and notes.
slide create
slides-agent slide create --presentation-id <id> --layout TITLE_AND_BODY
slides-agent slide create --presentation-id <id> --layout BLANK --insertion-index 2
slides-agent slide create --presentation-id <id> --dry-run
| Flag | Description |
|---|---|
--insertion-index / -i |
0-based position (appends at end if omitted). |
--layout |
Layout preset: BLANK, CAPTION_ONLY, TITLE, TITLE_AND_BODY, TITLE_AND_TWO_COLUMNS, TITLE_ONLY, ONE_COLUMN_TEXT, MAIN_POINT, BIG_NUMBER. |
--dry-run |
Preview without applying. |
Output includes the new slide's objectId so you can immediately target it.
slide delete
slides-agent slide delete --presentation-id <id> --slide-id <slide_id> --force
slides-agent slide delete --presentation-id <id> --slide-id <slide_id> --dry-run
⚠️ Irreversible. Use --dry-run first. Use --force to skip the confirmation prompt in non-interactive mode.
slide duplicate
slides-agent slide duplicate --presentation-id <id> --slide-id <slide_id>
Copies a slide immediately after the original. Returns the new slide's ID.
slide reorder
slides-agent slide reorder --presentation-id <id> --slide-id <slide_id> --insertion-index 0
Moves a slide to a 0-based index position.
slide background
slides-agent slide background --presentation-id <id> --slide-id <slide_id> --color '#1A73E8'
slides-agent slide background --presentation-id <id> --slide-id <slide_id> --color 'FFFFFF'
Changes the background color of a single slide to a solid color.
element
Inspect and list page elements.
element list
slides-agent element list --presentation-id <id> --slide-id <slide_id>
slides-agent element list --presentation-id <id> --slide-id <slide_id> --type image
slides-agent element list --presentation-id <id> --slide-id <slide_id> | jq '.elements[] | {element_id, element_type, placeholder_type}'
| Flag | Description |
|---|---|
--type / -t |
Filter by type: shape, image, table, chart, video, line, group. |
Element types:
shape— Text boxes and placeholders (these contain text)image— Bitmap imagestable— Data tableschart— Embedded Sheets chartsvideo— Embedded videosline— Lines and connectorsgroup— Grouped elements
element inspect
slides-agent element inspect --presentation-id <id> --slide-id <slide_id> --element-id <element_id>
Full detail for one element: type, placeholder, full text with paragraph/run structure, image URLs, bounding box, and transform.
text
Read and mutate slide text.
text replace
slides-agent text replace --presentation-id <id> --find '{{customer}}' --replace 'Acme Corp'
slides-agent text replace --presentation-id <id> --find 'DRAFT' --replace 'FINAL' --no-match-case
slides-agent text replace --presentation-id <id> --find '{{date}}' --replace '2025-01-15' --dry-run
Replaces all occurrences of a string across the entire presentation (all slides, all elements, all notes). Uses the Slides API replaceAllText request.
This is the recommended way to fill template placeholders like {{customer}}, {{date}}, {{version}}.
| Flag | Description |
|---|---|
--find / -f |
The text to search for. |
--replace / -r |
The replacement text. |
--match-case / --no-match-case |
Case sensitivity (default: case-sensitive). |
--dry-run |
Preview the API request without applying. |
Output:
{
"ok": true,
"presentation_id": "abc123",
"applied_operations": [
{"type": "replace_text", "find": "{{customer}}", "replace": "Acme Corp", "occurrences_changed": 3}
],
"warnings": [],
"errors": []
}
text set
slides-agent text set --presentation-id <id> --slide-id <sid> --element-id <eid> --text "New Title"
slides-agent text set --presentation-id <id> --slide-id <sid> --element-id <eid> --text $'Line 1\nLine 2'
slides-agent text set --presentation-id <id> --slide-id <sid> --element-id <eid> --text "Draft" --dry-run
Replaces all text in a specific element. The element is first cleared, then the new text is inserted. Element styling is preserved; inline formatting is reset.
text append
slides-agent text append --presentation-id <id> --slide-id <sid> --element-id <eid> --text '\nNew bullet'
Appends text to the end of an element's existing content.
text clear
slides-agent text clear --presentation-id <id> --slide-id <sid> --element-id <eid>
slides-agent text clear --presentation-id <id> --slide-id <sid> --element-id <eid> --dry-run
Removes all text from an element.
text get
slides-agent text get --presentation-id <id> --slide-id <sid> --element-id <eid>
slides-agent text get --presentation-id <id> --slide-id <sid> --element-id <eid> | jq -r '.text.raw_text'
Returns the text content of an element, including the full paragraph/run structure.
notes
Speaker notes operations.
notes get
slides-agent notes get --presentation-id <id> --slide-id <slide_id>
slides-agent notes get --presentation-id <id> --slide-id <slide_id> | jq -r '.notes_text'
Returns the plain text of the speaker notes for a slide.
notes set
slides-agent notes set --presentation-id <id> --slide-id <slide_id> --text 'Talk track...'
slides-agent notes set --presentation-id <id> --slide-id <slide_id> --text $'Point 1\nPoint 2\nPoint 3'
slides-agent notes set --presentation-id <id> --slide-id <slide_id> --text 'Notes' --dry-run
Replaces the speaker notes for a slide with new text.
notes clear
slides-agent notes clear --presentation-id <id> --slide-id <slide_id>
Removes all speaker notes from a slide.
image
Image operations.
image insert
# From a URL (image must be publicly accessible)
slides-agent image insert --presentation-id <id> --slide-id <sid> \
--url 'https://example.com/logo.png' \
--left 457200 --top 457200 \
--width 3657600 --height 1828800
# From a local file (uploads to Drive first)
slides-agent image insert --presentation-id <id> --slide-id <sid> \
--file ./hero.png \
--left 0 --top 0
EMU conversion: 1 inch = 914400 EMU. A standard 10-inch wide slide is 9144000 EMU.
| Flag | Description |
|---|---|
--url |
Publicly accessible image URL. |
--file |
Local image file (uploads to Drive). |
--left |
Left offset in EMUs (default: 0). |
--top |
Top offset in EMUs (default: 0). |
--width |
Width in EMUs. |
--height |
Height in EMUs. |
image replace
slides-agent image replace --presentation-id <id> --slide-id <sid> \
--element-id <image_element_id> \
--url 'https://example.com/new-logo.png'
Swaps the image content of an existing element. Position and size are preserved.
image resize
slides-agent image resize --presentation-id <id> --slide-id <sid> --element-id <eid> \
--left 457200 --top 457200 --width 4572000 --height 2571750
Repositions and/or resizes an image element.
theme
Apply style presets deck-wide.
theme list-presets
slides-agent theme list-presets --pretty
slides-agent theme list-presets | jq '[.presets[].name]'
Lists all built-in theme presets. Available presets:
| Name | Description |
|---|---|
corporate-blue |
Google Blue primary, white background, Google Sans font |
dark-professional |
Dark navy background, Roboto font, light text |
minimal-clean |
White background, Open Sans font, minimal accent |
theme apply
# Apply a built-in preset
slides-agent theme apply --presentation-id <id> --preset corporate-blue
# Apply a custom spec file
slides-agent theme apply --presentation-id <id> --spec-file ./my_theme.json
# Preview without applying
slides-agent theme apply --presentation-id <id> --preset dark-professional --dry-run
# Get the schema for the spec file format
slides-agent theme apply --schema
Theme spec format (see examples/sample_theme.json):
{
"name": "my-theme",
"colors": [
{"name": "primary", "hex_color": "#1A73E8"},
{"name": "secondary", "hex_color": "#34A853"}
],
"title_font": {"family": "Google Sans", "size_pt": 36, "bold": true},
"body_font": {"family": "Google Sans", "size_pt": 14},
"background_color": "#FFFFFF"
}
How it works: Updates font family, size, color, and background on all shape elements across all slides. Titles use title_font; all other text shapes use body_font. This is a deck-wide style layer — it does not modify the underlying Google Slides theme/master object.
template
Create and fill presentation templates.
Template Token Syntax
Use double-brace tokens in your slide text:
{{customer}} → Acme Corporation
{{quarter}} → Q1 2025
{{date}} → January 15, 2025
{{arr}} → $4.2M
template inspect
slides-agent template inspect --presentation-id <id>
slides-agent template inspect --presentation-id <id> | jq '[.tokens | keys]'
Scans all text across all slides and returns every {{token}} found, along with which slide IDs contain each token.
Output:
{
"ok": true,
"presentation_id": "abc123",
"token_count": 4,
"tokens": {
"customer": ["slide_1", "slide_3"],
"quarter": ["slide_1"],
"date": ["slide_2"],
"arr": ["slide_4"]
},
"unfilled": ["customer", "date", "arr", "quarter"],
"warnings": [],
"errors": []
}
template fill
slides-agent template fill --presentation-id <id> --values-file ./values.json
slides-agent template fill --presentation-id <id> --values-file ./values.json --dry-run
Fills all {{token}} placeholders from a JSON values file:
{
"customer": "Acme Corporation",
"quarter": "Q1 2025",
"date": "January 15, 2025",
"arr": "$4.2M"
}
Tokens not present in the values file are left unchanged and reported as warnings.
template create
# Duplicate a template and fill it in one step
slides-agent template create \
--template-id <template_presentation_id> \
--title "Acme QBR Q1 2025" \
--values-file ./acme_values.json
Duplicates a template presentation and optionally fills all token placeholders. The new presentation's ID and URL are returned.
patch
Plan and apply structured operation sets.
The patch workflow is the safest way to make multiple changes to a presentation. It follows an explicit plan → review → apply sequence.
Patch Workflow
Step 1 — Build an operations file:
[
{"type": "update_text", "presentation_id": "abc123", "slide_id": "g1", "element_id": "title_1", "text": "New Title"},
{"type": "replace_text", "presentation_id": "abc123", "find": "{{customer}}", "replace": "Acme Corp"},
{"type": "set_notes", "presentation_id": "abc123", "slide_id": "g1", "text": "Talk track..."},
{"type": "create_slide", "presentation_id": "abc123", "insertion_index": 2, "layout": "TITLE_AND_BODY"},
{"type": "delete_slide", "presentation_id": "abc123", "slide_id": "g5"},
{"type": "change_background", "presentation_id": "abc123", "slide_id": "g1", "color_hex": "#1A73E8"}
]
Step 2 — Validate:
slides-agent patch plan --presentation-id abc123 --operations-file ops.json > plan.json
Step 3 — Review: Check unresolved_references and validation_warnings in plan.json.
Step 4 — Apply:
slides-agent patch apply --plan-file plan.json
Step 5 — Verify:
slides-agent deck inspect --presentation-id abc123 --pretty
Supported Operation Types
| Type | Required Fields |
|---|---|
update_text |
presentation_id, slide_id, element_id, text |
replace_text |
presentation_id, find, replace |
set_notes |
presentation_id, slide_id, text |
create_slide |
presentation_id, insertion_index?, layout? |
delete_slide |
presentation_id, slide_id |
duplicate_slide |
presentation_id, slide_id |
reorder_slide |
presentation_id, slide_id, insertion_index |
insert_image |
presentation_id, slide_id, image_url |
replace_image |
presentation_id, slide_id, element_id, image_url |
change_background |
presentation_id, slide_id?, color_hex |
update_style |
presentation_id, slide_id, element_id, + style fields |
See slides-agent schema show patch-plan for the full schema.
patch plan
slides-agent patch plan --presentation-id <id> --operations-file ops.json
slides-agent patch plan --presentation-id <id> --operations-file ops.json > plan.json
slides-agent patch plan --presentation-id <id> --operations-file ops.json --pretty
slides-agent patch plan --schema # emit operation JSON schema
Validates all operations against the current presentation. Returns a PatchPlan JSON with:
operations— the validated operation listunresolved_references— IDs that couldn't be foundvalidation_warnings— non-blocking issues
Does not mutate anything.
patch apply
slides-agent patch apply --plan-file plan.json
slides-agent patch apply --plan-file plan.json --dry-run
slides-agent patch apply --plan-file plan.json --skip-validation # apply even with unresolved refs
Applies a validated plan. Re-validates ID references before applying. Operations are applied in order via batchUpdate. Returns a PatchApplyReport with succeeded and failed counts.
patch validate
slides-agent patch validate --plan-file plan.json
Re-validates a plan file against the current presentation state without applying it. Useful for checking that IDs haven't changed since the plan was created.
export
Export presentations.
export pdf
slides-agent export pdf --presentation-id <id> --output ./deck.pdf
slides-agent export pdf --presentation-id <id> --output /tmp/presentation.pdf --pretty
Exports the presentation as a PDF using the Google Drive export API.
export pptx
slides-agent export pptx --presentation-id <id> --output ./deck.pptx
Exports the presentation as a PowerPoint (.pptx) file.
export json
# Export parsed model to stdout
slides-agent export json --presentation-id <id>
# Export to a file
slides-agent export json --presentation-id <id> --output deck.json --pretty
# Export raw API response
slides-agent export json --presentation-id <id> --raw | jq '.slides[0].pageElements'
Exports the presentation as JSON. By default, uses the parsed PresentationSummary model format (same as deck inspect). Use --raw to get the unmodified Google Slides API response.
schema
Emit JSON schemas for all command inputs and outputs.
# List all available schemas
slides-agent schema list
# Show a schema
slides-agent schema show presentation
slides-agent schema show patch-plan | jq '.properties'
slides-agent schema show error
# Get the schema for update_text operations
slides-agent schema show patch-operation-update-text > update-text-schema.json
Available schemas:
| Name | Description |
|---|---|
presentation |
Full PresentationSummary (deck inspect output) |
slide |
SlideSummary (slide list/inspect output) |
element |
PageElement (element list/inspect output) |
text-content |
TextContent model |
theme-spec |
ThemeSpec input for theme apply |
patch-plan |
PatchPlan output from patch plan |
patch-apply |
PatchApplyReport output from patch apply |
patch-operation-update-text |
Schema for update_text operations |
patch-operation-replace-text |
Schema for replace_text operations |
patch-operation-set-notes |
Schema for set_notes operations |
patch-operation-create-slide |
Schema for create_slide operations |
patch-operation-delete-slide |
Schema for delete_slide operations |
patch-operation-duplicate-slide |
Schema for duplicate_slide operations |
patch-operation-reorder-slide |
Schema for reorder_slide operations |
patch-operation-insert-image |
Schema for insert_image operations |
patch-operation-replace-image |
Schema for replace_image operations |
patch-operation-change-background |
Schema for change_background operations |
patch-operation-update-style |
Schema for update_style operations |
error |
AgentError error envelope |
deck-inspect |
DeckInspectOutput |
deck-duplicate |
DeckDuplicateOutput |
slide-list |
SlideListOutput |
slide-mutation |
SlideMutationOutput |
theme-apply |
ThemeApplyOutput |
Agent Workflow Examples
Workflow 1: Inspect → Plan → Apply
PRES_ID="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"
# 1. Full inspection
slides-agent deck inspect --presentation-id $PRES_ID > inspection.json
# 2. Extract slide and element IDs for planning
SLIDE_1=$(cat inspection.json | jq -r '.presentation.slides[0].slide_id')
TITLE_EL=$(cat inspection.json | jq -r '.presentation.slides[0].elements[] | select(.placeholder_type == "TITLE") | .element_id')
# 3. Build operations file
cat > ops.json <<EOF
[
{"type": "update_text", "presentation_id": "$PRES_ID", "slide_id": "$SLIDE_1", "element_id": "$TITLE_EL", "text": "Updated Title"},
{"type": "set_notes", "presentation_id": "$PRES_ID", "slide_id": "$SLIDE_1", "text": "New talk track."},
{"type": "replace_text", "presentation_id": "$PRES_ID", "find": "{{customer}}", "replace": "Acme Corp"}
]
EOF
# 4. Validate
slides-agent patch plan --presentation-id $PRES_ID --operations-file ops.json > plan.json
cat plan.json | jq '.unresolved_references'
# 5. Apply
slides-agent patch apply --plan-file plan.json
# 6. Verify
slides-agent deck inspect --presentation-id $PRES_ID | jq '.presentation.slides[0].elements[].text.raw_text'
Workflow 2: Template → Fill → Export
TEMPLATE_ID="template_presentation_id"
VALUES='{"customer": "Acme Corp", "quarter": "Q2 2025", "date": "April 1, 2025"}'
# 1. Inspect the template to verify tokens
slides-agent template inspect --presentation-id $TEMPLATE_ID
# 2. Create and fill in one step
echo $VALUES > values.json
RESULT=$(slides-agent template create \
--template-id $TEMPLATE_ID \
--title "Acme QBR Q2 2025" \
--values-file values.json)
NEW_ID=$(echo $RESULT | jq -r '.new_presentation_id')
# 3. Export as PDF
slides-agent export pdf --presentation-id $NEW_ID --output ./acme-qbr-q2-2025.pdf
Workflow 3: Bulk Notes Update
PRES_ID="abc123"
# Get all slide IDs
SLIDE_IDS=$(slides-agent slide list --presentation-id $PRES_ID | jq -r '[.slides[].slide_id] | @tsv')
# Build operations for notes
python3 -c "
import json, sys
slide_ids = sys.argv[1].split()
notes = ['Opening remarks', 'Key metrics', 'Roadmap overview', 'Q&A']
ops = [{'type': 'set_notes', 'presentation_id': '$PRES_ID', 'slide_id': sid, 'text': notes[i % len(notes)]} for i, sid in enumerate(slide_ids)]
print(json.dumps(ops, indent=2))
" "$SLIDE_IDS" > notes_ops.json
# Plan and apply
slides-agent patch plan --presentation-id $PRES_ID --operations-file notes_ops.json > plan.json
slides-agent patch apply --plan-file plan.json
Output Format
Every command returns JSON to stdout.
Success Envelope (mutating commands)
{
"ok": true,
"presentation_id": "abc123",
"applied_operations": [
{
"type": "update_text",
"slide_id": "g1a2b3",
"element_id": "title_1",
"detail": {}
}
],
"warnings": [],
"errors": []
}
Dry-Run Envelope
{
"ok": true,
"dry_run": true,
"presentation_id": "abc123",
"would_apply": [
{"deleteText": {"objectId": "title_1", "textRange": {"type": "ALL"}}},
{"insertText": {"objectId": "title_1", "insertionIndex": 0, "text": "New Title"}}
],
"warnings": [],
"errors": []
}
Error Model
All errors return a structured JSON object with a stable error_code:
{
"ok": false,
"error_code": "not_found",
"detail": "Slide 'g99x' not found in presentation 'abc123'.",
"hint": "Run `slides-agent slide list` to get valid slide IDs.",
"field": null,
"raw": null
}
Error Codes
| Code | Meaning | Common Causes |
|---|---|---|
auth_error |
OAuth failure | Token expired, wrong scopes, not logged in |
not_found |
Resource doesn't exist | Wrong presentation/slide/element ID |
invalid_reference |
ID wrong type | Targeting an image with text set |
validation_error |
Bad input | Invalid JSON, missing required field, wrong format |
unsupported_operation |
Not supported | Feature not in MVP |
api_error |
Google API error | Unexpected API rejection |
rate_limited |
Quota exceeded | Too many requests |
conflict |
Concurrent modification | Presentation edited simultaneously |
io_error |
File I/O failure | File not found, permission denied |
Safety Features
| Feature | Description |
|---|---|
--dry-run |
All mutating commands support this. Returns would_apply with API requests instead of applying them. |
--force |
Required on destructive operations (e.g., slide delete) to skip confirmation in non-interactive mode. |
--no-input compatible |
No hidden prompts by default. Use --force for automation. |
| Plan/apply workflow | patch plan validates all IDs before patch apply mutates anything. |
| Loud failures | Ambiguous selectors fail with not_found or invalid_reference rather than guessing. |
| Token cache | OAuth tokens are cached locally and never logged or printed. |
JSON Schema Reference
Get JSON schemas for any input or output type:
# List all schemas
slides-agent schema list
# Get a schema
slides-agent schema show presentation > presentation-schema.json
slides-agent schema show patch-plan > patch-plan-schema.json
slides-agent schema show error > error-schema.json
Use schemas for:
- Validating your operations files before running
patch plan - Generating type definitions in your agent code
- Documentation and API contracts
Development
Setup
# Clone and install in dev mode
git clone <repo>
cd slides-goog
pip install -e ".[dev]"
Run Tests
pytest tests/ -v
pytest tests/ --cov=slides_agent --cov-report=html
Tests use mocked Google API responses — no real credentials required.
Project Structure
src/slides_agent/
├── main.py # Root Typer app
├── core/
│ ├── auth.py # OAuth2 flow and credential storage
│ ├── api.py # Google Slides and Drive API clients
│ ├── models.py # Shared Pydantic v2 models
│ ├── parser.py # Google API response → Pydantic model parsers
│ ├── output.py # JSON output helpers
│ └── errors.py # Structured error model
├── commands/
│ ├── auth.py # `slides-agent auth *`
│ ├── deck.py # `slides-agent deck *`
│ ├── slide.py # `slides-agent slide *`
│ ├── element.py # `slides-agent element *`
│ ├── text.py # `slides-agent text *`
│ ├── notes.py # `slides-agent notes *`
│ ├── image.py # `slides-agent image *`
│ ├── theme.py # `slides-agent theme *`
│ ├── template.py # `slides-agent template *`
│ ├── patch.py # `slides-agent patch *`
│ ├── export.py # `slides-agent export *`
│ └── schema.py # `slides-agent schema *`
└── schemas/
├── deck.py # DeckInspectOutput, DeckDuplicateOutput
├── slide.py # SlideListOutput, SlideMutationOutput
├── patch.py # PatchPlan, PatchApplyReport, operation types
└── theme.py # ThemeApplyOutput, ThemeListOutput
Adding a New Command
- Add a function to the relevant file in
commands/ - Add Pydantic output schema to
schemas/if needed - Register with
@app.command("command-name") - Add
--examplesand--schemaflags - Write tests in
tests/test_<module>.py
Lint
ruff check src/ tests/
ruff format src/ tests/
Project details
Release history Release notifications | RSS feed
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 slides_agent-0.1.0.tar.gz.
File metadata
- Download URL: slides_agent-0.1.0.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
785ca54f567f9ec415a9d6d3751b3009004abe85a4fa4615c666141f3ce0823e
|
|
| MD5 |
ec97807e877042ffaa77a47dea812c7e
|
|
| BLAKE2b-256 |
97b8597c7f1ebbacf76e33656e793e45844a0aee25faca6b3c00061eea36647d
|
File details
Details for the file slides_agent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: slides_agent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3384f79034c903b5a482511454224a871448d95658a2a1af16c807e9c91db744
|
|
| MD5 |
b89dbd1cc36813b41cd33c058a65f117
|
|
| BLAKE2b-256 |
03fcfb524e482eefcca1f1e448ea4055d8bb23575cfb90115e5d6e38409ddb21
|