← Back to Skills Marketplace
fuco99

google-sheets-soha

by Nguyễn Tiến Phan · GitHub ↗ · v1.0.2 · MIT-0
cross-platform ⚠ suspicious
96
Downloads
0
Stars
0
Active Installs
3
Versions
Install in OpenClaw
/install google-sheets-soha
Description
Read and analyze data from Google Sheets. Trigger when the user mentions "Google Sheet", "spreadsheet", "sheet", sends a docs.google.com/spreadsheets link, o...
README (SKILL.md)

\r \r

Google Sheets Skill\r

\r Fetches data from Google Sheets via the Google Sheets API v4, caches it on disk, and answers user questions about the data.\r \r ---\r \r

Session Memory\r

\r Maintain the following context throughout the conversation. Update it as new information is learned:\r \r

SHEET_CONTEXT = {\r
  spreadsheetId: null,   // Active Sheet ID\r
  activeTab: null,       // Current tab being worked on\r
  tabs: [],              // Cached list of tab names\r
  headers: {},           // Cached headers per tab: { tabName: [...] }\r
  rawData: {},           // Cached rows per tab: { tabName: [[...]] }\r
  cacheFile: null,       // Path to on-disk cache file\r
}\r
```\r
\r
**Rules:**\r
- Once `spreadsheetId` is known → use it for all subsequent turns, never ask again\r
- Once a cache file exists and is within TTL → skip the API call\r
- Always check session context before asking the user for anything\r
\r
---\r
\r
## Step 1 — Get the Sheet ID\r
\r
Check in this order:\r
1. `SHEET_CONTEXT.spreadsheetId` already set → use it directly\r
2. URL in the message → extract the ID between `/d/` and `/edit`:\r
   `https://docs.google.com/spreadsheets/d/**SHEET_ID**/edit`\r
3. User provides the ID directly → save and use it\r
4. Not found anywhere → ask **exactly once**:\r
\r
> "Could you share the Google Sheet link or Sheet ID? I'll remember it for the rest of our conversation 😊"\r
\r
Once received → save to `SHEET_CONTEXT.spreadsheetId` immediately and proceed.\r
\r
---\r
\r
## Step 2 — Fetch Data from Google Sheets API\r
\r
Use **Google Sheets API v4**. Choose the auth method based on the sheet type:\r
\r
### Option A: Public sheet (Anyone with the link)\r
\r
```bash\r
# List tabs\r
curl -s "https://sheets.googleapis.com/v4/spreadsheets/{SHEET_ID}?key={GOOGLE_API_KEY}&fields=sheets.properties" \\r
  | python3 -c "import sys,json; d=json.load(sys.stdin); [print(s['properties']['title']) for s in d['sheets']]"\r
\r
# Fetch tab data\r
curl -s "https://sheets.googleapis.com/v4/spreadsheets/{SHEET_ID}/values/{TAB_NAME}!A1:Z1000?key={GOOGLE_API_KEY}" \\r
  | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get('values',[])))"\r
```\r
\r
### Option B: Private sheet (Service Account)\r
\r
```python\r
import os, json\r
from google.oauth2 import service_account\r
from googleapiclient.discovery import build\r
\r
creds = service_account.Credentials.from_service_account_file(\r
    os.environ["GOOGLE_SERVICE_ACCOUNT_JSON"],\r
    scopes=["https://www.googleapis.com/auth/spreadsheets.readonly"]\r
)\r
service = build("sheets", "v4", credentials=creds)\r
\r
# List tabs\r
meta = service.spreadsheets().get(spreadsheetId=SHEET_ID).execute()\r
tabs = [s["properties"]["title"] for s in meta["sheets"]]\r
\r
# Fetch tab data\r
result = service.spreadsheets().values().get(\r
    spreadsheetId=SHEET_ID,\r
    range=f"{TAB_NAME}!A1:Z1000"\r
).execute()\r
rows = result.get("values", [])\r
```\r
\r
Save results to `SHEET_CONTEXT.headers[tabName]` and `SHEET_CONTEXT.rawData[tabName]`.\r
\r
---\r
\r
## Step 3 — Disk Cache\r
\r
Cache fetched data to avoid redundant API calls across turns.\r
\r
### Cache path\r
```\r
~/.openclaw/workspace/.cache/sheets/{spreadsheetId}/{tabName}.json\r
```\r
\r
### Cache file structure\r
```json\r
{\r
  "spreadsheetId": "abc123",\r
  "tabName": "Sheet1",\r
  "fetchedAt": 1710000000,\r
  "ttl": 300,\r
  "headers": ["Name", "Status", "Date"],\r
  "rows": [\r
    ["Task A", "Done", "2024-01-01"],\r
    ["Task B", "Pending", "2024-01-02"]\r
  ]\r
}\r
```\r
\r
### Cache script (run via exec tool)\r
\r
```python\r
import os, json, time, shutil\r
\r
CACHE_DIR = os.path.expanduser("~/.openclaw/workspace/.cache/sheets")\r
TTL = 300  # 5 minutes — increase to 3600 for rarely-changing data\r
\r
def cache_path(sheet_id, tab):\r
    d = os.path.join(CACHE_DIR, sheet_id)\r
    os.makedirs(d, exist_ok=True)  # auto-creates on first use\r
    return os.path.join(d, f"{tab.replace('/', '_')}.json")\r
\r
def load_cache(sheet_id, tab):\r
    path = cache_path(sheet_id, tab)\r
    if not os.path.exists(path):\r
        return None\r
    with open(path) as f:\r
        c = json.load(f)\r
    if time.time() - c.get("fetchedAt", 0) > c.get("ttl", TTL):\r
        return None  # expired — will re-fetch\r
    return c\r
\r
def save_cache(sheet_id, tab, headers, rows):\r
    path = cache_path(sheet_id, tab)\r
    with open(path, "w") as f:\r
        json.dump({\r
            "spreadsheetId": sheet_id,\r
            "tabName": tab,\r
            "fetchedAt": int(time.time()),\r
            "ttl": TTL,\r
            "headers": headers,\r
            "rows": rows\r
        }, f, ensure_ascii=False)\r
\r
def clear_cache(sheet_id=None):\r
    target = os.path.join(CACHE_DIR, sheet_id) if sheet_id else CACHE_DIR\r
    if os.path.exists(target):\r
        shutil.rmtree(target)\r
```\r
\r
### Cache flow\r
\r
```python\r
cached = load_cache(SHEET_ID, TAB_NAME)\r
if cached:\r
    headers, rows = cached["headers"], cached["rows"]\r
else:\r
    # fetch from API...\r
    headers, rows = fetched_rows[0], fetched_rows[1:]\r
    save_cache(SHEET_ID, TAB_NAME, headers, rows)\r
```\r
\r
### When to clear cache\r
\r
| User says | Action |\r
|---|---|\r
| "refresh", "reload", "get latest data" | `clear_cache(SHEET_ID)` then re-fetch |\r
| "clear cache" | `clear_cache()` — wipes everything |\r
| TTL expired | Automatically re-fetches on next request |\r
| User switches to a new sheet | Keep old cache, create new cache for the new sheet |\r
\r
---\r
\r
## Step 4 — Answer the User\r
\r
- Always state which **sheet/tab** the data is from\r
- Use **markdown tables** when displaying multiple rows\r
- Reply in the **same language as the user**\r
- If data exceeds 500 rows, analyze the first 200 and ask if the user wants to narrow the range\r
\r
---\r
\r
## Configuration in openclaw.json\r
\r
Add under `skills.entries` (top-level, not inside `agents`):\r
\r
### Public sheet\r
```json\r
{\r
  "skills": {\r
    "entries": {\r
      "google-sheets-soha": {\r
        "enabled": true,\r
        "env": {\r
          "GOOGLE_API_KEY": "AIza..."\r
        }\r
      }\r
    }\r
  }\r
}\r
```\r
\r
### Private sheet\r
```json\r
{\r
  "skills": {\r
    "entries": {\r
      "google-sheets-soha": {\r
        "enabled": true,\r
        "env": {\r
          "GOOGLE_SERVICE_ACCOUNT_JSON": "/home/node/.openclaw/google-sa.json"\r
        }\r
      }\r
    }\r
  }\r
}\r
```\r
\r
---\r
\r
## Error Handling\r
\r
| Situation | Action |\r
|---|---|\r
| Sheet ID not provided | Ask once, save when received |\r
| API returns 403 | Sheet is private → guide user to share with service account email |\r
| API returns 404 | Wrong Sheet ID → ask again |\r
| `GOOGLE_API_KEY` not set | Guide user to add it in `openclaw.json` |\r
| Tab not found | List `SHEET_CONTEXT.tabs` and ask user to pick |\r
| Data too large | Analyze first 200 rows, notify user |\r
| `python3` not found | Run: `apt-get install -y python3` inside container |
Usage Guidance
This skill appears to do what it claims, but check the following before enabling: (1) It needs either a Google API key (public sheets) or a Service Account JSON file path (private sheets). Only provide the minimum credential required. (2) The skill caches sheet contents and remembers the active Sheet ID under ~/.openclaw/workspace/.cache/sheets — if that data is sensitive, consider the cache TTL or clear the cache after use. (3) The repository/homepage fields are placeholders (github.com/your-username/...) — verify the source/trustworthiness of the published repo and maintainer before installing. (4) There is a minor metadata parsing glitch (registry shows [object Object]) — confirm the env var configuration in your OpenClaw config matches what the SKILL.md frontmatter declares.
Capability Analysis
Type: OpenClaw Skill Name: google-sheets-soha Version: 1.0.2 The skill contains instructions for the agent to execute shell commands and Python scripts using unsanitized user-controlled variables (SHEET_ID, TAB_NAME), which presents a risk for command injection and path traversal within the cache management logic (SKILL.md). Furthermore, the error handling section explicitly directs the agent to perform system-level modifications ('apt-get install -y python3'), and the README.md includes defensive language pre-emptively dismissing security warnings as platform false positives. While these behaviors align with the stated goal of managing Google Sheets data, the lack of input validation and the request for privileged execution meet the criteria for a suspicious classification.
Capability Assessment
Purpose & Capability
Name/description match the actual behavior: fetching Google Sheets via Sheets API v4 using either a public API key or a service account, and using python3/curl for fetches. The declared binaries and primary credential are appropriate for the stated capability.
Instruction Scope
SKILL.md instructs the agent to fetch sheet metadata and values, run local python3 scripts, and cache results on disk under ~/.openclaw/workspace/.cache/sheets. This is within scope for a Sheets-reading skill, but the skill persists spreadsheetId in session context and caches sheet contents locally (TTL default 5 minutes) — users should be aware cached sheet contents and the remembered Sheet ID are stored on disk and used for subsequent turns.
Install Mechanism
Instruction-only skill with no install/spec downloads. No code is pulled from external URLs during install — lowest-risk install mechanism.
Credentials
Only Google-related credentials are requested (GOOGLE_API_KEY for public sheets, GOOGLE_SERVICE_ACCOUNT_JSON for private sheets). That is proportional. Minor inconsistency: the frontmatter marks the env vars as not required while primaryEnv is set to GOOGLE_SERVICE_ACCOUNT_JSON and the registry metadata shows malformed env entries ([object Object]) — likely a metadata parsing issue but worth verifying before enabling.
Persistence & Privilege
always:false and agent-invocation allowed (normal). The skill writes cache files under its own workspace path and stores session context in-memory for the conversation; it does not request system-wide privileges or alter other skills' configuration.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install google-sheets-soha
  3. After installation, invoke the skill by name or use /google-sheets-soha
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.2
- Added detailed metadata: environment variable descriptions, repository link, license, and explicit API host permissions. - Security section clarifies the read-only data access, purpose of external requests, and local execution of scripts. - Environment variables for both public (GOOGLE_API_KEY) and private (GOOGLE_SERVICE_ACCOUNT_JSON) sheet access are now documented and optional. - No code or logic changes—documentation and metadata improvements only.
v1.0.1
Version 1.0.1 of google-sheets-soha makes no file or functional changes. - No code changes or new features introduced - All existing logic, behaviors, and API integrations remain the same
v1.0.0
Initial release of google-sheets-soha skill: - Enables reading and analyzing data from Google Sheets via API, with context retention across a session. - Automatically caches sheet/tab data on disk to minimize repeated API calls, with auto-refresh and user-driven cache clearing. - Supports both public and private Google Sheets (API key or service account). - Activates on typical sheet-related language or when users share Google Sheet links. - Handles basic errors such as missing sheet IDs, access errors, and large datasets, providing clear user guidance.
Metadata
Slug google-sheets-soha
Version 1.0.2
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 3
Frequently Asked Questions

What is google-sheets-soha?

Read and analyze data from Google Sheets. Trigger when the user mentions "Google Sheet", "spreadsheet", "sheet", sends a docs.google.com/spreadsheets link, o... It is an AI Agent Skill for Claude Code / OpenClaw, with 96 downloads so far.

How do I install google-sheets-soha?

Run "/install google-sheets-soha" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is google-sheets-soha free?

Yes, google-sheets-soha is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does google-sheets-soha support?

google-sheets-soha is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created google-sheets-soha?

It is built and maintained by Nguyễn Tiến Phan (@fuco99); the current version is v1.0.2.

💬 Comments