# Gsheet

> Create or update a clean, scannable Google Sheet from tabular content, matching the locked house style (Geist font, black/white bold centred frozen header row, CLIP text wrapping, numeric columns centred, text left-aligned, auto-sized columns) via the {{GOOGLE_ACCOUNT}} OAuth helper. Trigger with /gsheet or whenever the user asks to "create/build/make a Google Sheet", turn a table/list/CSV/data into a Google Sheet, or format data as a spreadsheet.

- Skill: `harsh719/gsheet` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add harsh719/gsheet`
- Raw SKILL.md: https://api.skillmd.com/api/skills/harsh719/gsheet/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: harsh719 (https://skillmd.com/u/harsh719)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/harsh719/gsheet

---

<!-- SETUP:BEGIN -->
## Before you run this skill

This skill is brand-neutral. It reads its brand, palette and endpoints from
`brand.config.json` at the repo root.

**On first use, do this before anything else:**

1. Run `python3 brandkit.py`. It prints the config source and any placeholder
   that is still unset.
2. If it says `configured: False`, copy `brand.config.example.json` to
   `brand.config.json`.
3. Ask the operator for each value under `missing`, then write them in. Do not
   guess a brand name, a domain, or a colour.
4. Anything the skill writes out should be passed through
   `brandkit.fill(text)`, which swaps every `{{TOKEN}}` for its configured value
   and remaps the default palette to the operator's.

Text below uses `{{TOKEN}}` where a value is operator-specific. Treat an
unresolved `{{TOKEN}}` in your output as a bug, not as literal copy.

<!-- SETUP:END -->

# Google Sheet Builder

Turns any tabular content (a table, list, CSV, export, metrics dump) into a clean,
scannable Google Sheet that matches the locked house formatting standard, every
time, without re-asking about formatting.

## When to use

- `/gsheet` is typed.
- The user asks to create / build / make a Google Sheet.
- The user hands over a table, list, CSV, or data and wants it as a formatted
  Google Sheet.

## The formatting spec (locked — applied automatically, do not re-ask)

`build_gsheet.py` applies all of this on every run. You never hand-build the
batchUpdate requests.

- **Font:** Geist everywhere (header, body, every tab).
- **Header row:** 13pt, bold, black background, white text, centred, and frozen.
  Visually distinct from the body.
- **Cell wrapping:** CLIP on every cell by default.
- **Numeric columns** (counts, percentages, currency, IDs, scores) are
  centre-aligned. A column counts as numeric when ≥60% of its cells read as
  numbers (including `$1,200`, `45%`, leading-zero IDs).
- **Text columns** are left-aligned.
- **Long text:** break it into multiple short lines inside the cell using `\n`
  in the source value. CLIP wrapping keeps each line clean; row height grows to
  fit. Never leave a long paragraph as one unreadable line.
- **Columns** are auto-resized to fit content; vertical alignment is middle.

Readability and professional presentation over compactness. Keep formatting
uniform across every tab in the workbook.

## How to run

1. **Write the content spec** as a JSON file (in the scratchpad dir). Shape:

```json
{
  "title": "Workbook Title",
  "share": "email@domain.com",
  "sheets": [
    {
      "name": "Tab name",
      "header": ["Name", "Count", "Status", "Notes"],
      "rows": [
        ["Alpha", 12, "Active", "Short note."],
        ["Beta", 7, "Paused", "First line.\nSecond line.\nThird line."]
      ]
    }
  ]
}
```

   - Multiple tabs: add more entries to `"sheets"`.
   - Single tab shortcut: put `"header"` and `"rows"` at the top level, omit
     `"sheets"`.
   - Numbers can be raw (`12`) or strings (`"12"`, `"45%"`, `"$1,200"`); the
     builder coerces clean integers/decimals to real numbers so they stay
     summable, and keeps currency/percent/leading-zero values as text.
   - Put `\n` inside any long cell value to break it into readable lines.

2. **Run the builder** through a virtualenv with the Google API client installed (
   {{GOOGLE_ACCOUNT}} OAuth token):

```bash
cd "{{WORKSPACE_DIR}} - Second Brain/scripts/push_to_drive"
./.venv/bin/python ~/.claude/skills/gsheet/build_gsheet.py <spec.json>
```

   - Creates a NEW spreadsheet and prints its URL.
   - To update an existing sheet: `--sheet-id <ID>` (clears the named tabs and
     rewrites + reformats them; adds any tabs that don't exist yet).
   - To share: `--share email@domain.com` (defaults to writer) or
     `--share email@domain.com:reader`. `"share"` in the spec works too.

3. **Give the user the URL.** Keep internal/strategy sheets private to
   {{GOOGLE_ACCOUNT}}; share to specific people only, never `anyone-with-link`.

## Auth

The builder reads `token.json` + `credentials.json` from your
`scripts/push_to_drive` directory by default. Override with `GSHEET_AUTH_DIR`
(or it falls back to `GDOC_AUTH_DIR`). The cached token already carries the
`spreadsheets` + `drive.file` scopes. If the token is expired, run the project's
`reauth.py` first.

## Notes

- Ragged rows are auto-padded to the header width, so you don't have to keep
  every row the same length.
- `--sheet-id` is idempotent per tab: it clears and rewrites the named tabs, so
  you can iterate on data and re-run safely.
- Prefer multiple short columns over one wide column of long text; when a cell
  must hold a lot, pre-break it with `\n` into bullet-style lines.

