agentsclimarketplace

Google sheets apps script

Skill gabriel-dantas98/tapioca/skills/google-sheets-apps-script

Self-service Google Sheets and Google Docs automation via Apps Script and browser mode (no GCP for end users). Prefer markdown for Google Docs (appendMarkdown, tables, images, doc tabs). Guides non-technical users on fresh machines, onboard unregistered files, and performs CRUD, styling, comments, tabs (Sheets + Docs), upload, and rich document editing. Use via /tapioca:google-sheets-apps-script (tapioca plugin) or standalone in Cursor/Claude Code when the user mentions Google Sheets, Google Docs, planilha, documento, markdown docs, or Apps Script web app setup.From its SKILL.md

Install
npx -y skills add gabriel-dantas98/tapioca --skill google-sheets-apps-script

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

12.9 KB, as published. Nobody here has run it

Google Sheets & Docs Agent (Apps Script)

Audience: non-technical users. Agent runs all terminal. User opens links, clicks Google UI, pastes URLs.

Onboarding: wizard.md — Sheets or Docs, one question per turn.

Runtime paths (tapioca plugin + standalone)

Both IDEs share the same registry and browser profile (~/.config/google-sheets-agent/).

Resolve SKILL_ROOT before any CLI call — directory that contains this SKILL.md:

InstallSKILL_ROOT
tapioca plugin (preferred)<plugin-root>/skills/google-sheets-apps-script — invoke /tapioca:google-sheets-apps-script
tapioca dev (repo clone)skills/google-sheets-apps-script/ (relative to repo root)
Cursor standalone~/.cursor/skills/google-sheets-apps-script/
Claude Code standalone~/.claude/skills/google-sheets-apps-script/
CLI="$SKILL_ROOT/scripts/sheets_agent.py"

Upstream gist (standalone install only): https://gist.github.com/gabriel-dantas98/6ad86b6bfab840703ec214f228c3004b

Comment replies: pass "host": "cursor" in Cursor or "host": "claude" in Claude Desktop/Code (CLI auto-injects when omitted).


Resource types

TypeUser saysURL patternCLI flag
Spreadsheetplanilha/spreadsheets/d/...--spreadsheet-url
Documentdoc / Google Docs/document/d/...--document-url

Check registration:

python3 .../sheets_agent.py status --document-url "https://docs.google.com/document/d/.../edit"
python3 .../sheets_agent.py status --spreadsheet-url "https://docs.google.com/spreadsheets/d/.../edit"

Unregistered → wizard. Never call until registered: true.


Google Docs — prefer Markdown

Write structured content with appendMarkdown, not plain appendDoc. The agent drafts markdown; Apps Script renders headings, lists, bold, links, tables, and images into native Google Docs styling.

actionpurpose
appendMarkdownPreferred — render markdown block at end (markdown or text)
appendTable2D rows array → styled table (headerRow default true)
appendImageImage from public url or driveFileId (+ optional maxWidth, alt); pass index (0-based body child index) to insert at a position instead of appending, tabId to target a doc tab
readDocfull text + optional paragraph structure
listDocheadings, paragraph count (heading index is a paragraph index, not a body-child index)
docChildren / listChildrenlist every body child with its 0-based child index, type, heading, and text preview — the map you need to compute safe startChild/endChild for deleteElements (paragraph indices from listDoc do NOT match child indices when tables/images exist); tab-aware via tabId
appendDocsingle plain paragraph only (fallback)
insertDoc / replaceDoc / styleDoc / commentDoc / deleteDocsurgical edits
deleteElements / deleteRangedelete a contiguous range of top-level body children by index (startChild, endChild, inclusive, 0-based); tab-aware via tabId; keeps the body non-empty. Google Docs forbids removing the terminal paragraph of a section — insert content after it first, or exclude it from the range
readDocCommentsread native Google Docs comment threads (+ replies)
replyDocCommentreply in a native comment thread (commentId + text)
resolveDocCommentmark thread resolved (commentId, optional resolved)
batchmix markdown, tables, images, and low-level ops
python3 .../sheets_agent.py call \
  --document-url "https://docs.google.com/document/d/.../edit" \
  --payload '{"action":"appendMarkdown","markdown":"# Report\n\n**Status:** green\n\n| KPI | Value |\n| --- | --- |\n| Uptime | 99.9% |"}'

Full markdown/table/image spec: docs-reference.md


Golden rules

  1. One step per message — ask, wait, confirm, next
  2. No jargon — "link da planilha", "aba", never "spreadsheetId" or "deployment"
  3. User pastes full URLs — agent parses IDs
  4. Agent runs all CLI — never tell the user to run python, npm, or terminal
  5. When in doubt, ask — destructive/ambiguous ops need confirmation
  6. Celebrate wins — "Aba criada ✓", "Planilha conectada ✓"
  7. Unregistered sheet — never call API until wizard completes
  8. Google Docs content — draft markdown, call appendMarkdown; use appendTable / appendImage when data is structured or visual
  9. Native comment replies — every replyDocComment MUST include host attribution. Pass "host": "cursor" in Cursor or "host": "claude" in Claude Desktop; CLI auto-injects when omitted. Apps Script appends \n\n> replied from {host} — never skip. After fixing doc feedback, reply Fixed (or equivalent) and set "resolve": true.

Every request — decision flow

1. setup (silent on first use if not ready)
   bash .../scripts/setup.sh          # fresh machine
   python3 .../sheets_agent.py setup --check-only

2. status
   python3 .../sheets_agent.py status [--spreadsheet-url URL]

3. Branch:
   ├─ skill_ready: false     → skill missing on disk (tapioca: reinstall plugin; standalone: gist install.sh) — agent only
   ├─ registered: false    → wizard.md (one question per turn)
   ├─ browser_ready: false → browser-auth (explain login window to user)
   └─ all true               → understand intent → listSheets/read if needed → plan → call

4. On call errors → wizard.md error table → fix → retry

User asks to edit a sheet without URL: ask for link first, then status --spreadsheet-url.

User gives URL but registered: false: "Essa planilha ainda não está conectada" → wizard from step 0.

User gives URL and registered: true: skip onboarding, go to work (still confirm destructive ops).


Fresh machine (agent only — user sees nothing technical)

Run once per machine before any spreadsheet work:

bash "$SKILL_ROOT/scripts/setup.sh"
python3 "$SKILL_ROOT/scripts/sheets_agent.py" setup --check-only

Installs: python3, playwright, chromium browser. No global npm required.

If SKILL_ROOT missing (not on tapioca plugin path):

# standalone fallback — tapioca users should clone the plugin instead
gh gist view 6ad86b6bfab840703ec214f228c3004b --filename install.sh > /tmp/gs-install.sh
# fetch gist files, then: bash /tmp/gs-install.sh ~/.cursor/skills/google-sheets-apps-script

Onboarding unregistered spreadsheets

Follow wizard.md. Summary:

StepUser doesAgent does
0New sheet or paste URLparse, status --spreadsheet-url
1Paste spreadsheet URLcheck registered
2aPaste script URL (if clasp)clasp_bootstrap.sh — full deploy
2bApps Script UI clickswait for web app /exec URL → register
3Login in browser windowbrowser-auth
4Confirm A1 test cellcall update A1

Prefer clasp when clasp_logged_in: true (agent deploys Code.gs — user only opens Apps Script once for script URL).

Manual path when no clasp: user clicks Extensions → Apps Script → Deploy; agent pastes Code.gs content in chat if needed.


When to ask the user (mandatory)

SituationExample question
Unregistered spreadsheet"Cola o link da planilha que ainda não conectamos."
Destructive action"Posso apagar a aba Sheet1? Não tem undo fácil."
Ambiguous tab"Vi Finance e Financeiro — qual aba?"
Vague request"Quer kanban, financeiro, ou cap table?"
Overwrite content"Já tem dados — substituo ou crio aba nova?"
Multiple spreadsheets"Qual planilha? Cola o link."

OK without asking: explicit values, read-only ops, user said "pode fazer", single registered sheet + clear target.


Daily use (registered + browser ready)

python3 "$SKILL_ROOT/scripts/sheets_agent.py" call \
  --spreadsheet-url "https://docs.google.com/spreadsheets/d/.../edit" \
  --payload '{"action":"read","range":"A1:G10","sheetName":"Finance"}'

If only one spreadsheet registered, --spreadsheet-url optional.

Login expired → browser-auth → tell user: "Vou abrir o Google de novo."


Capabilities

Cells

actionpurposekey fields
readread values/formulas/notesrange, sheetName?, includeNotes?
updateset cell(s)range, value or values, sheetName?
createappend/insert rowvalues, row?, sheetName?
deleteclear/delete rowsrange, row, rows[], sheetName?
styleformatrange, style: { bold, background, fontColor, numberFormat, ... }
commentcell noterange, text
batchmany opsops: [...]

Tabs (Sheets) — v2.4.0+

Works with --spreadsheet-url or shared deploy via --document-url (routes by action, not URL).

actionaliasespurpose
listSheetslistTabslist all tabs
createSheetcreateTabnew tab (name, optional tabColor, index, activate)
renameSheetrenameTabrename (sheetName + newName)
deleteSheetdeleteTabremove — ask first
tabColorsetTabColortab color

Tabs (Google Docs) — v2.6.0+

Organizational doc tabs (URL ?tab=t.xxx). Requires Docs API advanced service on the Apps Script project.

actionpurpose
listDocTabslist tabs (tabId, title, index)
createDocTabnew tab (name)
renameDocTabrename (tabId, name)

Write into a specific tab: appendMarkdown with tabId.

python3 .../sheets_agent.py call --document-url "..." \
  --payload '{"action":"createDocTab","name":"Current Knowledge Ingestion"}'

python3 .../sheets_agent.py call --document-url "..." \
  --payload '{"action":"appendMarkdown","tabId":"t.xxx","markdown":"# Section\n\nContent..."}'

Upload + canvas export — v2.5+

python3 .../sheets_agent.py upload --file image.png --document-url "..." --append
python3 .../sheets_agent.py canvas-export --manifest report.canvas.json

See canvas-export-reference.md and docs-reference.md.

python3 .../sheets_agent.py call --spreadsheet-url "..." \
  --payload '{"action":"createTab","name":"Runway","tabColor":"#059669"}'

python3 .../sheets_agent.py call --spreadsheet-url "..." \
  --payload '{"action":"renameTab","sheetName":"Sheet1","newName":"Finance"}'

Details + examples: reference.md


Agent recipes

Read before write on existing workbooks:

python3 .../sheets_agent.py call ... --payload '{"action":"listSheets"}'
python3 .../sheets_agent.py call ... --payload '{"action":"read","sheetName":"Finance","range":"A1:G30"}'

Range width: A1:G7 = 7 columns — match values width.

Redeploy / fix outdated script:

bash .../scripts/clasp_bootstrap.sh --spreadsheet-url "..." --script-id "..." --update-only
# or user pastes new /exec URL → register

Maintainer automation (agent only — never show to end users)

ToolWhen
clasp_bootstrap.shclasp logged in — push + deploy + register
bootstrapOAuth client configured — Apps Script API
setup.shfresh machine

Rules

  • Wizard = one question per turn — see wizard.md
  • Never call on unregistered spreadsheet
  • Never send end user to GCP / API tokens / terminal
  • Prefer --spreadsheet-url over deployment ids
  • Split large batch if payload too big

Files

FilePurpose
wizard.mdNon-technical onboarding messages
templates/Code.gsApps Script v1.2.0+
scripts/setup.shFresh machine deps
scripts/clasp_bootstrap.shAutomated deploy
scripts/sheets_agent.pyCLI
canvas-export-reference.mdManifest → PNG (agnostic export)
reference.mdActions + troubleshooting

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.