Google Sheets API via curl. Use this skill to read, write, and manage spreadsheet data programmatically.
/plugin marketplace add vm0-ai/api0/plugin install api0@api0This skill inherits all available tools. When active, it can use any tool Claude has access to.
Use the Google Sheets API via direct curl calls to read, write, and manage spreadsheet data.
Official docs:
https://developers.google.com/sheets/api
Use this skill when you need to:
Create Google Cloud Project
Configure OAuth Consent Screen
Create OAuth Client ID
https://developers.google.com/oauthplaygroundGet Refresh Token
https://www.googleapis.com/auth/spreadsheetsSet Environment Variables
export GOOGLE_SHEETS_CLIENT_ID="your-client-id"
export GOOGLE_SHEETS_CLIENT_SECRET="your-client-secret"
export GOOGLE_SHEETS_REFRESH_TOKEN="your-refresh-token"
bash -c 'curl -s -X POST "https://oauth2.googleapis.com/token" -d "client_id=$GOOGLE_SHEETS_CLIENT_ID" -d "client_secret=$GOOGLE_SHEETS_CLIENT_SECRET" -d "refresh_token=$GOOGLE_SHEETS_REFRESH_TOKEN" -d "grant_type=refresh_token"' | jq -r '.access_token' > /tmp/sheets_token.txt
# Verify token was obtained
head -c 20 /tmp/sheets_token.txt && echo "..."
Then use $(cat /tmp/sheets_token.txt) inside bash -c wrappers for API calls.
gcloud auth activate-service-account --key-file=service-account.json
export GOOGLE_ACCESS_TOKEN=$(gcloud auth print-access-token)
For publicly accessible sheets, you can use an API key:
export GOOGLE_API_KEY="your-api-key"
Important: When using
$VARin a command that pipes to another command, wrap the command containing$VARinbash -c '...'. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"' | jq .
All examples below use ${GOOGLE_ACCESS_TOKEN}. Before running, either:
GOOGLE_ACCESS_TOKEN="ya29.xxx...", or${GOOGLE_ACCESS_TOKEN} with $(cat /tmp/sheets_token.txt) in each commandImportant: In range notation like
Sheet1!A1:D10, the!must be URL encoded as%21in the URL path (e.g.,Sheet1%21A1:D10). All examples below use this encoding.
Base URL: https://sheets.googleapis.com/v4/spreadsheets
Finding your Spreadsheet ID:
The spreadsheet ID is in the URL: https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/edit
Get information about a spreadsheet (sheets, properties):
bash -c 'curl -s "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}"' | jq '{title: .properties.title, sheets: [.sheets[].properties | {sheetId, title}]}'
Read a range of cells:
bash -c 'curl -s "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1%21A1:D10" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}"' | jq '.values'
Read all data from a sheet:
bash -c 'curl -s "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}"' | jq '.values'
For publicly accessible sheets:
bash -c 'curl -s "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1%21A1:D10?key=${GOOGLE_API_KEY}"' | jq '.values'
Update a range of cells:
bash -c 'curl -s -X PUT "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1%21A1:C1?valueInputOption=USER_ENTERED" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{\"values\": [[\"Name\", \"Email\", \"Status\"]]}"' | jq '.updatedCells'
valueInputOption:
RAW: Values are stored as-isUSER_ENTERED: Values are parsed as if typed by user (formulas evaluated)Add new rows to the end of a sheet:
bash -c 'curl -s -X POST "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1%21A:C:append?valueInputOption=USER_ENTERED&insertDataOption=INSERT_ROWS" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{\"values\": [[\"John Doe\", \"john@example.com\", \"Active\"]]}"' | jq '.updates | {updatedRange, updatedRows}'
Read multiple ranges in one request:
bash -c 'curl -s "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values:batchGet?ranges=Sheet1%21A1:B5&ranges=Sheet1%21D1:E5" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}"' | jq '.valueRanges'
Update multiple ranges in one request:
bash -c 'curl -s -X POST "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values:batchUpdate" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{\"valueInputOption\": \"USER_ENTERED\", \"data\": [{\"range\": \"Sheet1!A1\", \"values\": [[\"Header 1\"]]}, {\"range\": \"Sheet1!B1\", \"values\": [[\"Header 2\"]]}]}"' | jq '.totalUpdatedCells'
Clear a range of cells:
bash -c 'curl -s -X POST "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1%21A2:C100:clear" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{}"' | jq '.clearedRange'
Create a new spreadsheet:
bash -c 'curl -s -X POST "https://sheets.googleapis.com/v4/spreadsheets" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{\"properties\": {\"title\": \"My New Spreadsheet\"}, \"sheets\": [{\"properties\": {\"title\": \"Data\"}}]}"' | jq '{spreadsheetId, spreadsheetUrl}'
Add a new sheet to an existing spreadsheet:
bash -c 'curl -s -X POST "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}:batchUpdate" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{\"requests\": [{\"addSheet\": {\"properties\": {\"title\": \"New Sheet\"}}}]}"' | jq '.replies[0].addSheet.properties'
Delete a sheet from a spreadsheet (use sheetId from metadata):
bash -c 'curl -s -X POST "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}:batchUpdate" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}" -H "Content-Type: application/json" -d "{\"requests\": [{\"deleteSheet\": {\"sheetId\": 123456789}}]}"' | jq '.'
Find cells containing specific text (read all then filter):
bash -c 'curl -s "https://sheets.googleapis.com/v4/spreadsheets/${SPREADSHEET_ID}/values/Sheet1" -H "Authorization: Bearer ${GOOGLE_ACCESS_TOKEN}"' | jq '[.values[] | select(.[0] | ascii_downcase | contains("search_term"))]'
| Notation | Description |
|---|---|
Sheet1!A1 | Single cell A1 in Sheet1 |
Sheet1!A1:B2 | Range from A1 to B2 |
Sheet1!A:A | Entire column A |
Sheet1!1:1 | Entire row 1 |
Sheet1!A1:C | From A1 to end of column C |
'Sheet Name'!A1 | Sheet names with spaces need quotes |
gcloud auth print-access-tokenUSER_ENTERED for formulas, RAW for literal strings%20)