atris/skills/slides/SKILL.md
Google Slides integration via AtrisOS API. List, create, read, and update presentations. Add slides, text, shapes, images. Export to PDF. Use when user asks about slides, presentations, decks, or pitch decks.
npx skillsauth add atrislabs/atris slidesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Drop this in
~/.claude/skills/slides/SKILL.mdand Claude Code becomes your presentation assistant.
Google Slides shares OAuth with Google Drive. If Drive is connected, Slides works automatically. If not:
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
# Check if Drive is connected (Slides piggybacks on Drive)
curl -s "https://api.atris.ai/api/integrations/google-drive/status" -H "Authorization: Bearer $TOKEN"
# If not connected, start Drive OAuth (includes Slides scope)
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/start" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"next_url":"https://atris.ai/dashboard/settings"}'
Base: https://api.atris.ai/api/integrations/google-slides
All requests require: -H "Authorization: Bearer $TOKEN"
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations?page_size=20" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations/{presentation_id}" \
-H "Authorization: Bearer $TOKEN"
curl -s -X POST "https://api.atris.ai/api/integrations/google-slides/presentations" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Q1 2026 Review"}'
All slide mutations use the batch-update endpoint. This is the most powerful endpoint — it can add slides, insert text, add shapes, images, change formatting, and more.
curl -s -X POST "https://api.atris.ai/api/integrations/google-slides/presentations/{id}/batch-update" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"requests": [...]}'
{
"requests": [
{
"createSlide": {
"insertionIndex": 1,
"slideLayoutReference": {
"predefinedLayout": "BLANK"
}
}
}
]
}
Available layouts: BLANK, TITLE, TITLE_AND_BODY, TITLE_AND_TWO_COLUMNS, TITLE_ONLY, SECTION_HEADER, SECTION_TITLE_AND_DESCRIPTION, ONE_COLUMN_TEXT, MAIN_POINT, BIG_NUMBER
{
"requests": [
{
"createSlide": {
"insertionIndex": 0,
"slideLayoutReference": {
"predefinedLayout": "TITLE"
},
"placeholderIdMappings": [
{"layoutPlaceholder": {"type": "TITLE"}, "objectId": "titleId"},
{"layoutPlaceholder": {"type": "SUBTITLE"}, "objectId": "subtitleId"}
]
}
},
{
"insertText": {
"objectId": "titleId",
"text": "Q1 2026 Review"
}
},
{
"insertText": {
"objectId": "subtitleId",
"text": "Atris Labs - Confidential"
}
}
]
}
{
"requests": [
{
"insertText": {
"objectId": "ELEMENT_ID",
"text": "Hello, world!"
}
}
]
}
{
"requests": [
{
"createShape": {
"objectId": "myTextBox1",
"shapeType": "TEXT_BOX",
"elementProperties": {
"pageObjectId": "SLIDE_ID",
"size": {
"width": {"magnitude": 400, "unit": "PT"},
"height": {"magnitude": 50, "unit": "PT"}
},
"transform": {
"scaleX": 1, "scaleY": 1,
"translateX": 100, "translateY": 200,
"unit": "PT"
}
}
}
},
{
"insertText": {
"objectId": "myTextBox1",
"text": "Custom text here"
}
}
]
}
{
"requests": [
{
"createImage": {
"objectId": "myImage1",
"url": "https://example.com/image.png",
"elementProperties": {
"pageObjectId": "SLIDE_ID",
"size": {
"width": {"magnitude": 300, "unit": "PT"},
"height": {"magnitude": 200, "unit": "PT"}
},
"transform": {
"scaleX": 1, "scaleY": 1,
"translateX": 150, "translateY": 100,
"unit": "PT"
}
}
}
}
]
}
{
"requests": [
{
"replaceAllText": {
"containsText": {"text": "{{company_name}}"},
"replaceText": "Atris Labs"
}
}
]
}
{
"requests": [
{
"deleteObject": {
"objectId": "SLIDE_OR_ELEMENT_ID"
}
}
]
}
{
"requests": [
{
"updateTextStyle": {
"objectId": "ELEMENT_ID",
"style": {
"bold": true,
"fontSize": {"magnitude": 24, "unit": "PT"},
"foregroundColor": {
"opaqueColor": {"rgbColor": {"red": 0.2, "green": 0.2, "blue": 0.8}}
}
},
"fields": "bold,fontSize,foregroundColor"
}
}
]
}
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations/{id}/pages/{page_id}" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations/{id}/pages/{page_id}/thumbnail" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations/{id}/export" \
-H "Authorization: Bearer $TOKEN"
Returns {"pdf_base64": "...", "content_type": "application/pdf"}.
POST /presentations with titlehttps://docs.google.com/presentation/d/{id}GET /presentationsGET /presentations/{id} to see current slidesGET /presentations/{id}/exportGET /presentations/{id} to find element IDsGET /presentations/{id}{{placeholder}} patterns for template-based decks| Error | Meaning | Solution |
|-------|---------|----------|
| Drive not connected | No Drive OAuth token | Connect Google Drive first |
| 403 insufficient_scope | Token missing presentations scope | Reconnect Drive to get updated scopes |
| 404 not_found | Presentation doesn't exist | Check presentation ID |
| 400 invalid_request | Bad batch update request | Check request format against API docs |
# Get token
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
# List presentations
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations" -H "Authorization: Bearer $TOKEN"
# Create presentation
curl -s -X POST "https://api.atris.ai/api/integrations/google-slides/presentations" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"title":"My Deck"}'
# Get presentation (with all slides)
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations/PRES_ID" -H "Authorization: Bearer $TOKEN"
# Add a slide with text
curl -s -X POST "https://api.atris.ai/api/integrations/google-slides/presentations/PRES_ID/batch-update" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"requests":[{"createSlide":{"slideLayoutReference":{"predefinedLayout":"TITLE_AND_BODY"}}}]}'
# Export as PDF
curl -s "https://api.atris.ai/api/integrations/google-slides/presentations/PRES_ID/export" -H "Authorization: Bearer $TOKEN"
development
Wake a team member by name — 'gm <member>' or 'wake up <member>' — and run ONE closed-loop tick: boot, inbox, claim, one bounded slice, verify, commit+push, proof, receipt. Optionally dispatch the build to an engine (codex/cursor/devin). Triggers on: gm, good morning, wake up <member>, wake the team, run a tick as <member>.
development
Dispatch coding work to an installed terminal agent — Codex, Cursor, or Devin — as an interchangeable worker engine. Claude orchestrates: writes the bounded prompt, the engine builds, Claude verifies and lands. Triggers on: use codex, use cursor, use devin, engine, dispatch to, worker agent, second opinion build.
development
Live RL tuner for skills. Watches skill invocations, reads user reaction, proposes targeted SKILL.md overlay edits, requires explicit approval, writes scorecards. The in-session half of the skill-RL loop (Path B). Triggers on: tune, sharpen, skill feedback, that was shit, that was great, make X better.
development
Run one RL improvement tick on the workspace via POST /api/improve. Ships one verifiable change, scores it, writes the scorecard. The thing you pay for. Triggers on: improve, make this better, ship one thing, run a tick, get smarter.