agentsclimarketplace

Gsheet model

Skill NovateStudioGit/novate-studio-skills/ecommerce/gsheet-model

Build or rebuild a formatted, multi-section financial model directly on a user's LIVE Google Sheet via the Composio v3 REST API (no Apps Script paste, no broken MCP Tool Router). Authors + formats tabs end to end — build the grid in Python, write via Composio REST, read-back verify, colour-band format. Use when the user says "build this into the sheet", "add a section to the planner", "rebuild this tab", "put returns into the model", or `/gsheet-model`. The author-and-format path proven on the ExampleBrand numbers sheet. NOT /ecom-data-analyst (that reads + analyses a catalog, doesn't author live tabs), NOT /gsheet-bridge (Apps Script paste — the fallback for when Composio is down), NOT /sheet-create (creates a NEW blank sheet). See memory composio-connection-broken for the full recipe + gotchas.From its SKILL.md

Install
npx -y skills add NovateStudioGit/novate-studio-skills --skill gsheet-model

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

  • 0 stars0 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

7.4 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it

/gsheet-model — author & format a live Google Sheet model via Composio REST

Stand up or rebuild a calculator / financial model directly on the user's live multi-tab Google Sheet, fully automated, no copy-paste. This became possible once we learned to drive Composio through its REST API directly instead of the MCP "Tool Router" connect flow (which is broken vendor-side). Everything here is the hardened recipe from the ExampleBrand build — read memory composio-connection-broken for the source of truth; this skill is the operational playbook.

When to use vs siblings:

  • This skill — author/format/rebuild tabs on a live sheet via Composio REST. Default when Composio is working.
  • /gsheet-bridge — the Apps-Script-paste fallback for when Composio is down. Same job, clunkier path.
  • /ecom-data-analyst — read + analyse a catalog (doesn't author formatted tabs).
  • /sheet-create — make a brand-new blank sheet.

0. Auth (do this first, every run)

  • API key: never hardcode it. Pull the live key at runtime: claude mcp get composio → the X-API-Key: header (or the composio entry in ~/.claude.json). The helper does this for you.
  • Endpoint base: https://backend.composio.dev/api/v3 (v1 is retired).
  • Connected account (ExampleBrand Google): ca_xxxxxxxxxxxx, user_id pg-test-xxxxxxxxxxxx. BOTH user_id and connected_account_id are required on every execute call (omitting user_id → error 1811). For a different account, re-list connections.
  • Every tool call: POST /tools/execute/{TOOL_SLUG} with body {"user_id":..., "connected_account_id":..., "arguments":{...}}.
  • POST via curl, not python urllib — this Mac's python has no CA bundle (SSLCertVerificationError). Build the JSON in python, write to a tmp file, curl --data @file. The helper (scripts/gsheet.py) already does this.

1. The operations (tool slugs)

NeedToolKey args
Read valuesGOOGLESHEETS_BATCH_GETspreadsheet_id, ranges:[ "Tab!A1:Z40" ]
Read FORMULASGOOGLESHEETS_GET_SPREADSHEET_BY_DATA_FILTERspreadsheetId, includeGridData:true, dataFilters:[{a1Range}] → each cell's userEnteredValue.formulaValue
Write a blockGOOGLESHEETS_BATCH_UPDATEspreadsheet_id, sheet_name, first_cell_location (A1), valueInputOption:"USER_ENTERED", values (2D)
Format cellsGOOGLESHEETS_FORMAT_CELLspreadsheet_id, worksheet_id (sheetId), 0-based start/end_row/col_index, + red/green/blue (0-1), bold, italic, fontSize
Add a tabGOOGLESHEETS_ADD_SHEETspreadsheetId, properties:{title}
Insert rows/colsGOOGLESHEETS_INSERT_DIMENSIONinsert_dimension:{range:{sheetId,dimension:"ROWS",startIndex,endIndex}, inheritFromBefore:false}
Clear valuesGOOGLESHEETS_CLEAR_VALUESspreadsheet_id, range
Tab list + sheetIdsGOOGLESHEETS_GET_SPREADSHEET_INFOspreadsheet_id → sheets[].properties.{title,sheetId}

GOOGLESHEETS_FORMAT_CELL does ONLY background colour + bold/italic/underline/fontSize. No borders, no number format ($/%/comma), no text colour, no column width. Those four are manual one-clicks the user does (tell them).

2. The build workflow

  1. Read first. Pull the target tab's structure (values, and FORMULAS via includeGridData if splicing into an existing model). Map columns/rows by their LABELS, never by remembered addresses.
  2. Build the grid in Python with row positions as VARIABLES (R_TOTAL=23, DATA0=80...) and derive every formula reference off those vars. Hardcoded row numbers break the moment a section shifts. Keep ONE shared assumptions block and reference it cross-tab (tab-qualified, e.g. 'COGS + BEROAS'!$T$3) so all tabs move in lockstep.
  3. Avoid the merge trap. A rebuild on an existing tab inherits leftover merged cells (CLEAR_VALUES does NOT remove merges) — writes land only in a merge's top-left and the rest read blank. So for a fresh layout, ADD_SHEET a clean tab. To add INTO a live model, INSERT_DIMENSION blank rows (Google auto-adjusts same-sheet AND cross-sheet refs, so nothing downstream breaks) then populate.
  4. Write the block with BATCH_UPDATE. Batch many cells into ONE values block — don't loop single-cell writes (per-minute read quota throttles you at ~15; 429 → wait 30-60s, retry).
  5. Verify by behaviour, not by eyeballing the script. Read back: totals correct, no #DIV/0!/#ERROR!, and INJECT a sample data row to confirm computed columns actually flow. Don't "fix" working formulas off a readback hunch — test it.
  6. Format with restrained, consistent colour bands (one palette, not rainbow): section-header band, highlight input cells (one accent), highlight the answer row, light tint for auto-calculated cells. Then tell the user the manual finish: auto-fit columns, add borders, apply #,##0 number format.

3. Gotcha checklist (every one cost real time on ExampleBrand)

  • AND()/OR() do NOT short-circuit → AND(C>0, D/C>=x) still divides on blank rows → #DIV/0! that poisons SUM. Guard: =IF(C>0, IF(D/C>=x,1,0), 0).
  • A label written USER_ENTERED that STARTS with = + - @ is parsed as a formula → #ERROR!. Use a plain bold label for subtotals, not "= Revenue gap".
  • zsh: never name a shell var UID (reserved → "bad math expression"); use EID.
  • CHECK BEFORE OVERWRITING a column: read the exact target range first; don't assume empty because you only read up to column L. (We overwrote Target CAC/ROAS this way — recover via Sheets File ▸ Version history; there's no API for it.)
  • Never rename the tab a cross-tab formula points to.
  • Returns/chargebacks etc.: keep assumptions in ONE block, reference cross-tab; tab-qualify or refs silently resolve local.

4. Helper

scripts/gsheet.py (stdlib only, shells to curl) wraps the operations: read_values, read_formulas, write_block, format_cell, add_sheet, insert_rows, clear, plus sheet_ids(). It auto-pulls the API key from claude mcp get composio. Import it or copy the calls. Default account/user are the ExampleBrand ones — pass account=/user= to override.

from gsheet import write_block, read_formulas, format_cell
write_block(SHEET_ID, "META PLANNER", "A1", grid)          # grid = 2D list
read_formulas(SHEET_ID, "FINANCIAL MODELING!B22:C40")      # {A1: formula}
format_cell(SHEET_ID, worksheet_id, 3,4, 1,6, bold=True, rgb=(0.85,0.73,0.40))

Always end a build by reading back and reporting the verified numbers, then naming the manual finish (borders / number format / column widths) since the API can't do them.

What ships with it: 1 file

6.9 KB alongside SKILL.md, 1 of them executable

scripts/

Gives 0 of the 12 instructions most finance skills give in ~1.8k tokens

Counted across 469 of the 469 authors here whose files we hold, read 2026-08-07

  • Extract date vendor amount and descriptionin 15 of 469, across 3 files
  • Scan folder for invoice filesin 14 of 469, across 2 files
  • Rename files to standard formatin 14 of 469, across 2 files
  • Show organization plan before movingin 14 of 469, across 2 files
  • Generate summary CSVin 14 of 469, across 2 files
  • Organize files by categoryin 13 of 469, across 1 file
  • Preserve original filesin 13 of 469, across 1 file
  • Flag files missing critical infoin 13 of 469, across 1 file
  • Produce the requested output filein 9 of 469, across 4 files
  • Build best, base, and worst case scenariosin 9 of 469, across 5 files
  • Implement backoff if rate limit errors occurin 8 of 469, across 3 files
  • Determine the weighted average cost of capitalin 8 of 469, across 4 files

Said here and by no other author read

  • pull the api key at runtime
  • send post requests via curl not python
  • pass both user id and connected account id
  • read target tab structure first
  • map columns and rows by labels
  • build the grid in python with row position variables

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. 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.