gsheet-model — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited gsheet-model (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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:
/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.claude mcp get composio → the X-API-Key: header (or the composio entry in ~/.claude.json). The helper does this for you.https://backend.composio.dev/api/v3 (v1 is retired).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.POST /tools/execute/{TOOL_SLUG} with body {"user_id":..., "connected_account_id":..., "arguments":{...}}.curl --data @file. The helper (scripts/gsheet.py) already does this.| Need | Tool | Key args |
|---|---|---|
| Read values | GOOGLESHEETS_BATCH_GET | spreadsheet_id, ranges:[ "Tab!A1:Z40" ] |
| Read FORMULAS | GOOGLESHEETS_GET_SPREADSHEET_BY_DATA_FILTER | spreadsheetId, includeGridData:true, dataFilters:[{a1Range}] → each cell's userEnteredValue.formulaValue |
| Write a block | GOOGLESHEETS_BATCH_UPDATE | spreadsheet_id, sheet_name, first_cell_location (A1), valueInputOption:"USER_ENTERED", values (2D) |
| Format cells | GOOGLESHEETS_FORMAT_CELL | spreadsheet_id, worksheet_id (sheetId), 0-based start/end_row/col_index, + red/green/blue (0-1), bold, italic, fontSize |
| Add a tab | GOOGLESHEETS_ADD_SHEET | spreadsheetId, properties:{title} |
| Insert rows/cols | GOOGLESHEETS_INSERT_DIMENSION | insert_dimension:{range:{sheetId,dimension:"ROWS",startIndex,endIndex}, inheritFromBefore:false} |
| Clear values | GOOGLESHEETS_CLEAR_VALUES | spreadsheet_id, range |
| Tab list + sheetIds | GOOGLESHEETS_GET_SPREADSHEET_INFO | spreadsheet_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).
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.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.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).#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.#,##0 number format.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).= + - @ is parsed as a formula → #ERROR!. Use a plain bold label for subtotals, not "= Revenue gap".UID (reserved → "bad math expression"); use EID.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.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.