Resources
4Install
npx skillscat add cgk-platform/cgk/openclaw-skills-google-workspace Install via the SkillsCat registry.
Google Workspace
Create polished, presentation-ready Google Slides, Docs, Sheets, and manage Drive files via Google Workspace APIs with per-profile OAuth credentials.
CRITICAL RULES
- NEVER pass markdown to any command. No
#,**,-,1., or```. The script REJECTS markdown and exits with an error. - ALWAYS use
docs build-richfor documents. Do NOT fall back to element-by-element. If build-rich fails, report the error. - ALWAYS use
sheets build-richfor new spreadsheets. Element-by-element sheets commands are for live editing of existing sheets only. - All files are auto-shared with org. Use
--link-sharefor public links,--share EMAILfor individual sharing. - ALWAYS use
add-chartfor numerical data — render charts, don't just list numbers. - Every document must have heading hierarchy, styled tables, and visual structure.
How to Build Beautiful Documents
Rich Document Builder (Docs) — ALWAYS USE THIS
Build the entire document in one command via JSON spec piped to stdin. Automatically builds a .docx with python-docx, uploads to Drive as a native Google Doc, and org-shares.
cat <<'EOF' | gog docs build-rich --title "Monthly Report" --folder FOLDER_ID --share user@example.com
{
"theme": {"dark": "1A1A2E", "accent": "E94560", "accent2": "0F3460", "lightBg": "F5F5F5", "medGray": "666666"},
"header": "Confidential",
"footer": "Generated March 2026",
"sections": [{
"children": [
{"type": "heading", "level": 1, "text": "Monthly Performance Report", "color": "1A1A2E"},
{"type": "subtitle", "text": "March 2026 — Brand Name"},
{"type": "accentBar", "color": "E94560"},
{"type": "kpiRow", "items": [
{"value": "$42K", "label": "Revenue", "bg": "0F3460"},
{"value": "3.8x", "label": "ROAS", "bg": "2E7D32"},
{"value": "186", "label": "Orders", "bg": "1565C0"}
]},
{"type": "heading", "level": 2, "text": "Executive Summary"},
{"type": "paragraph", "text": "Revenue grew 10.5% this month driven by strong organic performance."},
{"type": "callout", "title": "Key Insight", "body": "Top performers drove 60% of revenue.", "bg": "E8F5E9"},
{"type": "divider"},
{"type": "heading", "level": 2, "text": "Ad Performance"},
{"type": "table", "headers": ["Ad Name", "ROAS", "Spend", "Revenue"],
"rows": [["Morning Routine", "4.2x", "$1.2K", "$5.0K"], ["Product Hero", "2.8x", "$800", "$2.2K"]],
"style": {"headerBg": "0F3460", "zebra": true}},
{"type": "heading", "level": 2, "text": "Key Findings"},
{"type": "bullets", "items": ["Organic traffic up 15%", "Paid ROAS improved 12%", "Email conversion steady at 4.2%"]},
{"type": "heading", "level": 2, "text": "Recommendations"},
{"type": "numberedList", "items": ["Scale top performers", "Test new UGC formats", "Refresh static ads"]}
]
}]
}
EOFFlags: --title, --folder DRIVE_ID, --link-share, --share EMAIL, --output /local/path.docx (local-only, skip upload), --spec-file /path/to/spec.json (alternative to stdin).
Batch: gog docs build-rich-batch --spec-file specs.json --folder ID --link-share --parallel 4
Rich Document JSON Spec — All 18 Element Types
{"type": "heading", "level": 1, "text": "Title", "color": "1A1A2E"}
{"type": "subtitle", "text": "Subtitle text"}
{"type": "paragraph", "text": "Body text"}
{"type": "paragraph", "runs": [{"text": "Bold ", "bold": true}, {"text": "and italic", "italic": true, "color": "E94560"}]}
{"type": "accentBar", "color": "E94560"}
{"type": "divider"}
{"type": "kpiRow", "items": [{"value": "$42K", "label": "Revenue", "bg": "0F3460"}]}
{"type": "callout", "title": "Note", "body": "Important info here", "bg": "E8F5E9"}
{"type": "table", "headers": ["A","B"], "rows": [["1","2"]], "style": {"headerBg": "0F3460", "zebra": true, "zebraColor": "F5F5F5"}}
{"type": "richTable", "headers": ["A","B"], "rows": [[{"text": "Bold cell", "bold": true, "bg": "FFF3E0"}, "Normal"]]}
{"type": "bullets", "items": ["Item 1", "Item 2"]}
{"type": "numberedList", "items": ["Step 1", "Step 2"]}
{"type": "personaCard", "name": "Sarah", "role": "Marketing Manager", "details": ["25-34", "Urban"], "bg": "F5F5F5"}
{"type": "conceptHeader", "title": "STRATEGY", "subtitle": "Q2 growth plan", "color": "1A1A2E"}
{"type": "tag", "text": "HIGH PRIORITY", "color": "E94560"}
{"type": "pageBreak"}
{"type": "spacer", "height": 12}
{"type": "image", "path": "/absolute/path/to/image.png", "width": 5.0}Theme: Colors are 6-char hex without #. Keys: dark, accent, accent2, lightBg, medGray.
Defaults: Arial 11pt, US Letter, 0.8" margins. Header/footer via top-level "header" and "footer" strings.
Multi-section: Each object in "sections" array starts on a new page.
Rich Presentation Builder (Slides) -- ALWAYS USE THIS
Build an entire presentation in one command via JSON spec. Automatically builds a .pptx with python-pptx, uploads to Drive as a native Google Slides deck, and org-shares.
cat <<'EOF' | gog slides build-rich --title "Q1 Review" --folder FOLDER_ID --link-share
{
"theme": {"dark": "1A1A2E", "accent": "E94560", "accent2": "0F3460", "lightBg": "F5F5F5", "medGray": "666666"},
"slides": [
{"type": "title_slide", "title": "Q1 Performance Review", "subtitle": "March 2026"},
{"type": "section", "title": "Executive Summary"},
{"type": "kpi_row", "title": "Key Metrics", "metrics": [
{"value": "$42K", "label": "Revenue", "bg": "0F3460"},
{"value": "3.8x", "label": "ROAS", "bg": "2E7D32"},
{"value": "186", "label": "Orders", "bg": "1565C0"},
{"value": "+10.5%", "label": "Growth", "bg": "E94560"}
]},
{"type": "bullets", "title": "Growth Drivers", "items": ["Organic traffic up 15%", "Paid ROAS improved 12%", "Email conversion steady at 4.2%"]},
{"type": "table", "title": "Ad Performance", "headers": ["Ad Name", "ROAS", "Spend", "Revenue"],
"rows": [["Morning Routine", "4.2x", "$1.2K", "$5.0K"], ["Product Hero", "2.8x", "$800", "$2.2K"]],
"style": {"headerBg": "0F3460", "zebra": true}},
{"type": "chart", "title": "Revenue Trend", "chartType": "bar",
"categories": ["Jan", "Feb", "Mar"],
"series": [{"name": "Revenue", "values": [32000, 38000, 42000]}]},
{"type": "two_column", "title": "Strategy vs Results",
"left": {"heading": "Strategy", "body": "Focus on UGC content and scaling top performers"},
"right": {"heading": "Results", "body": "UGC drove 3.2x ROAS, top performers scaled 40%"}},
{"type": "closing", "title": "Thank You", "subtitle": "Questions?"}
]
}
EOFFlags: --title, --folder DRIVE_ID, --link-share, --share EMAIL, --output /local/path.pptx (local-only, skip upload), --spec-file /path/to/spec.json.
Batch: gog slides build-rich-batch --spec-file specs.json --folder ID --link-share --parallel 4
Rich Presentation JSON Spec -- All 11 Slide Types
{"type": "title_slide", "title": "Title", "subtitle": "Subtitle", "notes": "Speaker notes"}
{"type": "section", "title": "Section Name"}
{"type": "content", "title": "Heading", "body": "Body text"}
{"type": "bullets", "title": "Heading", "items": ["Item 1", "Item 2"]}
{"type": "kpi_row", "title": "Metrics", "metrics": [{"value": "$42K", "label": "Revenue", "bg": "0F3460"}]}
{"type": "table", "title": "Data", "headers": ["A","B"], "rows": [["1","2"]], "style": {"headerBg": "0F3460", "zebra": true}}
{"type": "two_column", "title": "Compare", "left": {"heading": "Left", "body": "..."}, "right": {"heading": "Right", "body": "..."}}
{"type": "image", "title": "Visual", "path": "/path/to/image.png", "caption": "Caption text"}
{"type": "chart", "title": "Chart", "chartType": "bar|line|pie|area|scatter|doughnut", "categories": [...], "series": [{"name": "...", "values": [...]}]}
{"type": "blank", "background": "FFFFFF", "elements": [{"type": "text", "text": "...", "x": 1, "y": 1, "fontSize": 14, "bold": true}]}
{"type": "closing", "title": "Thank You", "subtitle": "Questions?"}Theme: Colors are 6-char hex without #. Keys: dark, accent, accent2, lightBg, medGray.
Speaker notes: Add "notes": "..." to any slide spec.
Dimensions: Default 13.333 x 7.5 inches (16:9 widescreen). Override with "slideWidth" and "slideHeight".
Presentation Tools (Slides) -- Element-by-Element (Legacy)
For editing existing Google Slides or adding individual slides to an existing presentation:
# Always start with create + theme
gog slides create "Title Here" --clean
gog slides apply-theme PRES_ID
# LAYOUT PRESETS — pre-styled professional slide templates
gog slides add-layout PRES_ID title --data '{"title":"...","subtitle":"..."}'
gog slides add-layout PRES_ID kpi --data '{"title":"...","kpis":[{"value":"$42K","label":"Revenue"},{"value":"3.8x","label":"ROAS"}]}'
gog slides add-layout PRES_ID section --data '{"title":"Section Name"}'
gog slides add-layout PRES_ID two-column --data '{"title":"...","body":"Left column text","rightBody":"Right column text"}'
gog slides add-layout PRES_ID content --data '{"title":"Key Findings","content":"Body text with analysis and insights goes here."}'
gog slides add-layout PRES_ID closing --data '{"title":"...","subtitle":"..."}'
# CUSTOM SLIDES — blank canvas with your own elements
gog slides add-slide PRES_ID --layout BLANK
gog slides add-text PRES_ID SLIDE_IDX "Heading" --heading heading2 --style '{"y":20}'
gog slides add-text PRES_ID SLIDE_IDX "Analysis text below the data" --style '{"y":280,"fontSize":14}'
gog slides add-table PRES_ID SLIDE_IDX --data '[["Col1","Col2"],["val1","val2"]]' --style '{"headerColor":"#1a73e8","zebra":true}'
gog slides add-chart PRES_ID SLIDE_IDX --data '{"labels":[...],"datasets":[{"label":"...","values":[...]}]}' --type line|bar|pie
# OTHER ELEMENTS
gog slides add-image PRES_ID SLIDE_IDX --url URL --x 50 --y 50 --width 300 --height 200
gog slides add-shape PRES_ID SLIDE_IDX --type RECTANGLE --style '{"fillColor":"#1a73e8","x":0,"y":0,"width":720,"height":5}'
gog slides set-background PRES_ID SLIDE_IDX --color "#f5f5f5"Chart types: line, bar, pie, column, area, scatter
Layout presets: title, section, kpi, two-column, closing, content
Spreadsheet Pattern (Sheets) -- Rich Builder (PREFERRED)
ALWAYS use build-rich for new spreadsheets. It creates a fully formatted .xlsx with openpyxl, uploads to Drive as Google Sheets, and optionally link-shares -- all in one command.
ALWAYS use formulas, not hardcoded calculations. If a cell's value can be computed from other cells, write a formula.
# Build a complete spreadsheet from JSON spec (pipe or --spec-file)
echo '{"title":"Sales Dashboard","sheets":[{"name":"Summary","frozenRows":1,"autoFilter":"A1:D1","columnWidths":{"A":25,"B":15,"C":15,"D":15},"data":[["Metric","Value","Change","Impact"],["Revenue",42000,0.105,null],["ROAS",3.8,0.12,null]],"formulas":{"D2":"=B2*C2","D3":"=B3*C3"},"styles":[{"range":"A1:D1","bold":true,"backgroundColor":"1a73e8","textColor":"FFFFFF","alignment":"center"},{"range":"B2:B4","numberFormat":"$#,##0","textColor":"0000FF"},{"range":"C2:C4","numberFormat":"0.0%"}],"conditionalFormats":[{"range":"C2:C10","type":"greaterThan","value":0,"fill":"E8F5E9","fontColor":"2E7D32"}],"charts":[{"type":"bar","title":"Revenue","dataRange":"A1:B4","position":"F2","width":15,"height":10}]}]}' | gog sheets build-rich --title "Sales Dashboard" --link-share
# Batch build multiple spreadsheets
gog sheets build-rich-batch --spec-file specs.json --link-share --parallel 4
# Analyze a sheet
gog sheets analyze SHEET_ID
gog sheets analyze --file /tmp/report.xlsx
# Query/filter data
gog sheets query SHEET_ID --filter '{"Region":"West","Revenue":{">":50000}}' --sort Revenue --limit 10
gog sheets query SHEET_ID --groupby Region --agg '{"Revenue":"sum","Orders":"count"}'
# Download -> edit -> re-upload workflow
gog sheets download SHEET_ID --output /tmp/report.xlsx
echo '{"formulas":{"C11":"=SUM(C2:C10)"},"styles":[{"range":"B2:B10","numberFormat":"$#,##0"}]}' | gog sheets edit SHEET_ID --link-shareFinancial Model Color Coding
| Color | Meaning | Hex |
|---|---|---|
| Blue text | Input values (hardcoded) | 0000FF |
| Black text | Formulas/calculations | 000000 |
| Green text | Cross-sheet references | 008000 |
| Yellow background | Attention/review needed | FFFF00 |
Spreadsheet Pattern (Sheets) -- Element-by-Element (Legacy)
For live interaction with existing Google Sheets (reading shared sheets, updating recurring reports):
# Create with frozen header
gog sheets create "Sales Dashboard" --frozen-rows 1
# Write data
gog sheets write SHEET_ID --range A1 \
--data '[["Date","Revenue","Orders","ROAS"],["2026-02-14","$6200","26","3.2x"],["2026-02-15","$7100","31","3.5x"]]'
# Style header row
gog sheets format SHEET_ID --range A1:D1 \
--style '{"bold":true,"backgroundColor":"#1a73e8","textColor":"#ffffff","horizontalAlignment":"CENTER"}'
# Auto-resize columns
gog sheets auto-resize SHEET_ID
# Add native chart
gog sheets add-chart SHEET_ID --range A1:B4 --type barCommand Reference
Auth
| Command | Description |
|---|---|
auth status |
Check if credentials exist and are valid |
Slides (Presentations) -- Rich Builder (PREFERRED)
| Command | Description |
|---|---|
slides build-rich [--title T] [--folder ID] [--link-share] [--share EMAIL] [--output PATH] [--spec-file F] |
Build rich presentation from JSON spec, upload as Google Slides (auto org-shared) |
slides build-rich-batch [--folder ID] [--link-share] [--parallel N] [--spec-file F] |
Parallel batch build from JSON array of specs |
Slides (Presentations) -- Live API (Element-by-Element)
| Command | Description |
|---|---|
slides create <title> [--clean] |
Create a new presentation (--clean removes placeholder text) |
slides get <pres_id> |
Get presentation structure (slide IDs, elements) |
slides add-slide <pres_id> [--layout LAYOUT] [--index N] |
Add a slide |
slides add-text <pres_id> <slide_idx> <text> [--style JSON] [--heading H] |
Add a styled text box |
slides add-table <pres_id> <slide_idx> --data JSON [--style JSON] |
Add a styled table |
slides add-image <pres_id> <slide_idx> --url URL [--x --y --width --height EMU] |
Add image from URL |
slides add-shape <pres_id> <slide_idx> --type TYPE [--style JSON] |
Add a shape |
slides set-background <pres_id> <slide_idx> --color HEX|--image URL |
Set slide background |
slides apply-theme <pres_id> [--set-backgrounds] |
Apply brand colors (auto-detects profile) |
slides add-chart <pres_id> <slide_idx> --data JSON --type TYPE |
Add a chart |
slides add-layout <pres_id> PRESET [--data JSON] |
Add a preset layout slide |
slides export <pres_id> --format pdf|pptx|png|svg [--output PATH] |
Export presentation |
slides batch-update <pres_id> --requests JSON |
Raw batchUpdate for advanced use |
Layout presets: title, section, kpi, two-column, closing, content
Slide layouts: BLANK, TITLE, TITLE_AND_BODY, SECTION_HEADER, TITLE_ONLY, ONE_COLUMN_TEXT, MAIN_POINT, BIG_NUMBER, CAPTION_ONLY, TITLE_AND_TWO_COLUMNS
Docs (Documents) -- Rich Builder (PREFERRED)
| Command | Description |
|---|---|
docs build-rich [--title T] [--folder ID] [--link-share] [--share EMAIL] [--output PATH] [--spec-file F] |
Build rich document from JSON spec, upload as Google Doc (auto org-shared) |
docs build-rich-batch [--folder ID] [--link-share] [--parallel N] [--spec-file F] |
Parallel batch build from JSON array of specs |
docs create <title> |
Create an empty document (auto org-shared) |
docs get <doc_id> |
Get document structure and heading outline |
docs export <doc_id> --format pdf|docx|md|html|epub [--output PATH] |
Export document |
Docs (Documents) -- Live API (Element-by-Element)
For editing existing Google Docs or simple additions:
| Command | Description |
|---|---|
docs add-text <doc_id> <text> [--style STYLE] [--text-style JSON] |
Add styled text (REJECTS markdown) |
docs add-table <doc_id> --data JSON [--style JSON] |
Add a styled table |
docs add-image <doc_id> --url URL [--width PT] [--height PT] |
Insert inline image |
docs add-section <doc_id> --title TEXT |
Add section break + H1 heading (new page) |
docs add-list <doc_id> --items JSON [--type bullet|numbered] |
Add bulleted/numbered list |
docs add-page-break <doc_id> |
Insert page break |
docs add-divider <doc_id> |
Add visual divider line |
docs add-header <doc_id> --text TEXT |
Add page header |
docs add-footer <doc_id> --text TEXT |
Add page footer |
Text styles: title, subtitle, heading1-heading6, normal
Sheets (Spreadsheets) -- Rich Builder (PREFERRED)
| Command | Description |
|---|---|
sheets build-rich [--title T] [--folder ID] [--link-share] [--output PATH] [--spec-file F] |
Build rich spreadsheet from JSON spec (stdin or file), upload to Drive |
sheets build-rich-batch [--folder ID] [--link-share] [--parallel N] [--spec-file F] |
Parallel batch build from JSON array of specs |
sheets analyze [SHEET_ID] [--file PATH] [--sheet NAME] |
Analyze structure + data stats (pandas describe, dtypes, nulls) |
sheets query [SHEET_ID] [--file PATH] [--filter JSON] [--groupby COL] [--agg JSON] [--sort COL] [--limit N] [--sheet NAME] |
Filter, aggregate, sort spreadsheet data |
sheets download <SHEET_ID> [--output PATH] |
Download Google Sheet as .xlsx |
sheets edit <SHEET_ID> [--spec-file F] [--link-share] |
Edit existing sheet (download -> modify -> re-upload) |
Sheets (Spreadsheets) -- Live API (Element-by-Element)
| Command | Description |
|---|---|
sheets create <title> [--frozen-rows N] |
Create spreadsheet |
sheets get <sheet_id> |
Get metadata and sheet list |
sheets read <sheet_id> [--range A1:Z100] |
Read data |
sheets write <sheet_id> --range A1 --data JSON |
Write data |
sheets format <sheet_id> --range RANGE --style JSON |
Format cells |
sheets add-chart <sheet_id> --range RANGE --type TYPE |
Add native chart |
sheets add-tab <sheet_id> --title NAME [--color HEX] |
Add new tab |
sheets conditional-format <sheet_id> --range RANGE --rule JSON |
Add conditional formatting |
sheets auto-resize <sheet_id> [--columns 0:10] |
Auto-fit column widths |
Chart types: bar, line, pie, column, area, scatter
Drive (File Management)
| Command | Description |
|---|---|
drive list [--folder ID] [--type slides|docs|sheets] |
List files |
drive share <file_id> --email EMAIL --role reader|writer|commenter |
Share file |
drive move <file_id> --to FOLDER_ID |
Move file |
drive upload <local_path> [--folder ID] [--mime-type TYPE] |
Upload file |
drive create-folder <name> [--parent ID] |
Create folder |
Rich Spreadsheet JSON Spec Format
Full reference for sheets build-rich and sheets edit JSON specs:
{
"title": "Spreadsheet Title",
"sheets": [
{
"name": "Tab Name",
"tabColor": "1a73e8",
"frozenRows": 1,
"frozenCols": 0,
"autoFilter": "A1:D1",
"columnWidths": { "A": 25, "B": 15, "C": 15 },
"data": [
["Header1", "Header2", "Header3"],
["val1", 42000, 0.105]
],
"formulas": {
"C3": "=B2*B3",
"B5": "=SUM(B2:B4)"
},
"styles": [
{
"range": "A1:D1",
"bold": true,
"italic": false,
"fontSize": 12,
"fontFamily": "Arial",
"textColor": "FFFFFF",
"backgroundColor": "1a73e8",
"alignment": "center",
"wrapText": true,
"numberFormat": "$#,##0"
}
],
"conditionalFormats": [
{
"range": "C2:C10",
"type": "greaterThan",
"value": 0,
"fill": "E8F5E9",
"fontColor": "2E7D32"
},
{
"range": "C2:C10",
"type": "lessThan",
"value": 0,
"fill": "FFEBEE",
"fontColor": "C62828"
},
{ "range": "B2:B10", "type": "between", "start": 100, "end": 500, "fill": "FFF3E0" },
{ "range": "A2:A10", "type": "containsText", "text": "Error", "fill": "FFCDD2" },
{ "range": "D2:D10", "type": "colorScale", "startColor": "FF0000", "endColor": "00FF00" },
{ "range": "E2:E10", "type": "dataBar", "color": "638EC6" }
],
"charts": [
{
"type": "bar",
"title": "Chart Title",
"dataRange": "A1:B4",
"position": "F2",
"width": 15,
"height": 10
}
]
}
]
}Supported chart types: bar, line, pie, area, scatter
Supported conditional format types: greaterThan, lessThan, equal, between, containsText, colorScale, dataBar
Number format examples: $#,##0, $#,##0.00, 0.0%, #,##0, 0.00, yyyy-mm-dd
Data Formats
Table data (--data)
2D JSON array where first row is headers:
[
["Header 1", "Header 2", "Header 3"],
["Row 1 Col 1", "Row 1 Col 2", "Row 1 Col 3"]
]Table style (--style for tables)
{
"headerColor": "#1a73e8",
"headerTextColor": "#ffffff",
"zebra": true,
"zebraColor": "#f8f9fa",
"borderColor": "#dadce0",
"fontSize": 10
}Chart data (--data for charts)
{
"title": "Revenue Trend",
"labels": ["Mon", "Tue", "Wed", "Thu", "Fri"],
"xAxisTitle": "Day",
"yAxisTitle": "Revenue ($)",
"datasets": [{ "label": "This Week", "values": [6200, 7100, 8400, 9200, 11100] }]
}Error Handling
| Error | Cause | Fix |
|---|---|---|
| "Markdown detected" | Passed markdown to add-text | Use structured commands (--style, add-list, add-table) |
| "Not configured for this profile" | No OAuth credentials | Run setup_oauth.py |
| "Token expired" | Auto-refreshes on next use | Retry the command |
| "403 Forbidden" | API not enabled | Enable API in Cloud Console |
| "404 Not Found" | Invalid document/presentation ID | Verify the ID from the URL |
Per-Profile Isolation
- Each profile has its own
credentials/google-workspace-oauth.json - OAuth client ID shared across profiles (project-level)
- Workspace root auto-detected via script path
- Other profiles' credentials invisible due to Docker overlay mounts