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:
- Run
python3 brandkit.py. It prints the config source and any placeholder
that is still unset.
- If it says
configured: False, copy brand.config.example.json to
brand.config.json.
- Ask the operator for each value under
missing, then write them in. Do not
guess a brand name, a domain, or a colour.
- 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.
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
- Write the content spec as a JSON file (in the scratchpad dir). Shape:
{
"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.
- Run the builder through a virtualenv with the Google API client installed (
{{GOOGLE_ACCOUNT}} OAuth token):
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.
- 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.
1---2name: gsheet3description: 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.4---5<!-- SETUP:BEGIN -->6## Before you run this skill78This skill is brand-neutral. It reads its brand, palette and endpoints from9`brand.config.json` at the repo root.1011**On first use, do this before anything else:**12131. Run `python3 brandkit.py`. It prints the config source and any placeholder14 that is still unset.152. If it says `configured: False`, copy `brand.config.example.json` to16 `brand.config.json`.173. Ask the operator for each value under `missing`, then write them in. Do not18 guess a brand name, a domain, or a colour.194. Anything the skill writes out should be passed through20 `brandkit.fill(text)`, which swaps every `{{TOKEN}}` for its configured value21 and remaps the default palette to the operator's.2223Text below uses `{{TOKEN}}` where a value is operator-specific. Treat an24unresolved `{{TOKEN}}` in your output as a bug, not as literal copy.2526<!-- SETUP:END -->2728# Google Sheet Builder2930Turns any tabular content (a table, list, CSV, export, metrics dump) into a clean,31scannable Google Sheet that matches the locked house formatting standard, every32time, without re-asking about formatting.3334## When to use3536- `/gsheet` is typed.37- The user asks to create / build / make a Google Sheet.38- The user hands over a table, list, CSV, or data and wants it as a formatted39 Google Sheet.4041## The formatting spec (locked — applied automatically, do not re-ask)4243`build_gsheet.py` applies all of this on every run. You never hand-build the44batchUpdate requests.4546- **Font:** Geist everywhere (header, body, every tab).47- **Header row:** 13pt, bold, black background, white text, centred, and frozen.48 Visually distinct from the body.49- **Cell wrapping:** CLIP on every cell by default.50- **Numeric columns** (counts, percentages, currency, IDs, scores) are51 centre-aligned. A column counts as numeric when ≥60% of its cells read as52 numbers (including `$1,200`, `45%`, leading-zero IDs).53- **Text columns** are left-aligned.54- **Long text:** break it into multiple short lines inside the cell using `\n`55 in the source value. CLIP wrapping keeps each line clean; row height grows to56 fit. Never leave a long paragraph as one unreadable line.57- **Columns** are auto-resized to fit content; vertical alignment is middle.5859Readability and professional presentation over compactness. Keep formatting60uniform across every tab in the workbook.6162## How to run63641. **Write the content spec** as a JSON file (in the scratchpad dir). Shape:6566```json67{68 "title": "Workbook Title",69 "share": "email@domain.com",70 "sheets": [71 {72 "name": "Tab name",73 "header": ["Name", "Count", "Status", "Notes"],74 "rows": [75 ["Alpha", 12, "Active", "Short note."],76 ["Beta", 7, "Paused", "First line.\nSecond line.\nThird line."]77 ]78 }79 ]80}81```8283 - Multiple tabs: add more entries to `"sheets"`.84 - Single tab shortcut: put `"header"` and `"rows"` at the top level, omit85 `"sheets"`.86 - Numbers can be raw (`12`) or strings (`"12"`, `"45%"`, `"$1,200"`); the87 builder coerces clean integers/decimals to real numbers so they stay88 summable, and keeps currency/percent/leading-zero values as text.89 - Put `\n` inside any long cell value to break it into readable lines.90912. **Run the builder** through a virtualenv with the Google API client installed (92 {{GOOGLE_ACCOUNT}} OAuth token):9394```bash95cd "{{WORKSPACE_DIR}} - Second Brain/scripts/push_to_drive"96./.venv/bin/python ~/.claude/skills/gsheet/build_gsheet.py <spec.json>97```9899 - Creates a NEW spreadsheet and prints its URL.100 - To update an existing sheet: `--sheet-id <ID>` (clears the named tabs and101 rewrites + reformats them; adds any tabs that don't exist yet).102 - To share: `--share email@domain.com` (defaults to writer) or103 `--share email@domain.com:reader`. `"share"` in the spec works too.1041053. **Give the user the URL.** Keep internal/strategy sheets private to106 {{GOOGLE_ACCOUNT}}; share to specific people only, never `anyone-with-link`.107108## Auth109110The builder reads `token.json` + `credentials.json` from your111`scripts/push_to_drive` directory by default. Override with `GSHEET_AUTH_DIR`112(or it falls back to `GDOC_AUTH_DIR`). The cached token already carries the113`spreadsheets` + `drive.file` scopes. If the token is expired, run the project's114`reauth.py` first.115116## Notes117118- Ragged rows are auto-padded to the header width, so you don't have to keep119 every row the same length.120- `--sheet-id` is idempotent per tab: it clears and rewrites the named tabs, so121 you can iterate on data and re-run safely.122- Prefer multiple short columns over one wide column of long text; when a cell123 must hold a lot, pre-break it with `\n` into bullet-style lines.