[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71QDX76WDJE7Y37H47RYZFA":3,"skill-same:01M71QDX76WDJE7Y37H47RYZFA":102},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":58,"commitSha":59,"skillDirectory":60,"forksCount":13,"repositoryHtmlUrl":61,"repositoryHomepageUrl":6,"ownerHtmlUrl":62,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":63,"install":64,"resources":77},"01M71QDX76WDJE7Y37H47RYZFA","google-workspace",null,"Gmail, Calendar, Drive, Docs, Sheets via gws CLI or Python.","gjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN","gjbvsjjvgm-sketch","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F278511911?v=4","01M71F3JXKZQ70H2KCHHTXKZDA","01M71PENEVFN19DBZFNHJPCHQ7",0,"MIT","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"google","google workspace","workspace","sheets","gmail","contacts","hermes-agent","nous research","via","gws","calendar","hermes","OAuth","email","https","research","himalaya","github","python","cli","2026-11-10 13:02:02",false,"---\nname: google-workspace\ndescription: \"Gmail, Calendar, Drive, Docs, Sheets via gws CLI or Python.\"\nversion: 1.0.0\nauthor: Nous Research\nlicense: MIT\nmetadata:\n  hermes:\n    tags: [Google, Gmail, Calendar, Drive, Sheets, Docs, Contacts, Email, OAuth]\n    homepage: https:\u002F\u002Fgithub.com\u002FNousResearch\u002Fhermes-agent\n    related_skills: [himalaya]\n---\n\n# Google Workspace\n\nGmail, Calendar, Drive, Contacts, Sheets, and Docs — through Hermes-managed OAuth and a thin CLI wrapper. When `gws` is installed, the skill uses it as the execution backend for broader Google Workspace coverage; otherwise it falls back to the bundled Python client implementation.\n\n## References\n\n- `references\u002Fgmail-search-syntax.md` — Gmail search operators (is:unread, from:, newer_than:, etc.)\n\n## Scripts\n\n- `scripts\u002Fsetup.py` — OAuth2 setup (run once to authorize)\n- `scripts\u002Fgoogle_api.py` — compatibility wrapper CLI. It prefers `gws` for operations when available, while preserving Hermes' existing JSON output contract.\n\n## First-Time Setup\n\nThe setup is fully non-interactive — you drive it step by step so it works\non CLI, Telegram, Discord, or any platform.\n\nDefine a shorthand first:\n\n```bash\nGSETUP=\"python ${HERMES_HOME:-$HOME\u002F.hermes}\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fsetup.py\"\n```\n\n### Step 0: Check if already set up\n\n```bash\n$GSETUP --check\n```\n\nIf it prints `AUTHENTICATED`, skip to Usage — setup is already done.\n\n### Step 1: Triage — ask the user what they need\n\nBefore starting OAuth setup, ask the user TWO questions:\n\n**Question 1: \"What Google services do you need? Just email, or also\nCalendar\u002FDrive\u002FSheets\u002FDocs?\"**\n\n- **Email only** → They don't need this skill at all. Use the `himalaya` skill\n  instead — it works with a Gmail App Password (Settings → Security → App\n  Passwords) and takes 2 minutes to set up. No Google Cloud project needed.\n  Load the himalaya skill and follow its setup instructions.\n\n- **Email + Calendar** → Continue with this skill, but use\n  `--services email,calendar` during auth so the consent screen only asks for\n  the scopes they actually need.\n\n- **Calendar\u002FDrive\u002FSheets\u002FDocs only** → Continue with this skill and use a\n  narrower `--services` set like `calendar,drive,sheets,docs`.\n\n- **Full Workspace access** → Continue with this skill and use the default\n  `all` service set.\n\n**Question 2: \"Does your Google account use Advanced Protection (hardware\nsecurity keys required to sign in)? If you're not sure, you probably don't\n— it's something you would have explicitly enrolled in.\"**\n\n- **No \u002F Not sure** → Normal setup. Continue below.\n- **Yes** → Their Workspace admin must add the OAuth client ID to the org's\n  allowed apps list before Step 4 will work. Let them know upfront.\n\n### Step 2: Create OAuth credentials (one-time, ~5 minutes)\n\nTell the user:\n\n> You need a Google Cloud OAuth client. This is a one-time setup:\n>\n> 1. Create or select a project:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fprojectselector2\u002Fhome\u002Fdashboard\n> 2. Enable the required APIs from the API Library:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fapis\u002Flibrary\n>    Enable: Gmail API, Google Calendar API, Google Drive API,\n>    Google Sheets API, Google Docs API, People API\n> 3. Create the OAuth client here:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fapis\u002Fcredentials\n>    Credentials → Create Credentials → OAuth 2.0 Client ID\n> 4. Application type: \"Desktop app\" → Create\n> 5. If the app is still in Testing, add the user's Google account as a test user here:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fauth\u002Faudience\n>    Audience → Test users → Add users\n> 6. Download the JSON file and tell me the file path\n>\n> Important Hermes CLI note: if the file path starts with `\u002F`, do NOT send only the bare path as its own message in the CLI, because it can be mistaken for a slash command. Send it in a sentence instead, like:\n> `The JSON file path is: \u002Fhome\u002Fuser\u002FDownloads\u002Fclient_secret_....json`\n\nOnce they provide the path:\n\n```bash\n$GSETUP --client-secret \u002Fpath\u002Fto\u002Fclient_secret.json\n```\n\nIf they paste the raw client ID \u002F client secret values instead of a file path,\nwrite a valid Desktop OAuth JSON file for them yourself, save it somewhere\nexplicit (for example `~\u002FDownloads\u002Fhermes-google-client-secret.json`), then run\n`--client-secret` against that file.\n\n### Step 3: Get authorization URL\n\nUse the service set chosen in Step 1. Examples:\n\n```bash\n$GSETUP --auth-url --services email,calendar --format json\n$GSETUP --auth-url --services calendar,drive,sheets,docs --format json\n$GSETUP --auth-url --services all --format json\n```\n\nThis returns JSON with an `auth_url` field and also saves the exact URL to\n`~\u002F.hermes\u002Fgoogle_oauth_last_url.txt`.\n\nAgent rules for this step:\n- Extract the `auth_url` field and send that exact URL to the user as a single line.\n- Tell the user that the browser will likely fail on `http:\u002F\u002Flocalhost:1` after approval, and that this is expected.\n- Tell them to copy the ENTIRE redirected URL from the browser address bar.\n- If the user gets `Error 403: access_denied`, send them directly to `https:\u002F\u002Fconsole.cloud.google.com\u002Fauth\u002Faudience` to add themselves as a test user.\n\n### Step 4: Exchange the code\n\nThe user will paste back either a URL like `http:\u002F\u002Flocalhost:1\u002F?code=4\u002F0A...&scope=...`\nor just the code string. Either works. The `--auth-url` step stores a temporary\npending OAuth session locally so `--auth-code` can complete the PKCE exchange\nlater, even on headless systems:\n\n```bash\n$GSETUP --auth-code \"THE_URL_OR_CODE_THE_USER_PASTED\" --format json\n```\n\nIf `--auth-code` fails because the code expired, was already used, or came from\nan older browser tab, it now returns a fresh `fresh_auth_url`. In that case,\nimmediately send the new URL to the user and have them retry with the newest\nbrowser redirect only.\n\n### Step 5: Verify\n\n```bash\n$GSETUP --check\n```\n\nShould print `AUTHENTICATED`. Setup is complete — token refreshes automatically from now on.\n\n### Notes\n\n- Token is stored at `~\u002F.hermes\u002Fgoogle_token.json` and auto-refreshes.\n- Pending OAuth session state\u002Fverifier are stored temporarily at `~\u002F.hermes\u002Fgoogle_oauth_pending.json` until exchange completes.\n- If `gws` is installed, `google_api.py` points it at the same `~\u002F.hermes\u002Fgoogle_token.json` credentials file. Users do not need to run a separate `gws auth login` flow.\n- To revoke: `$GSETUP --revoke`\n\n## Usage\n\nAll commands go through the API script. Set `GAPI` as a shorthand:\n\n```bash\nGAPI=\"python ${HERMES_HOME:-$HOME\u002F.hermes}\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fgoogle_api.py\"\n```\n\n### Gmail\n\n```bash\n# Search (returns JSON array with id, from, subject, date, snippet)\n$GAPI gmail search \"is:unread\" --max 10\n$GAPI gmail search \"from:boss@company.com newer_than:1d\"\n$GAPI gmail search \"has:attachment filename:pdf newer_than:7d\"\n\n# Read full message (returns JSON with body text)\n$GAPI gmail get MESSAGE_ID\n\n# Send\n$GAPI gmail send --to user@example.com --subject \"Hello\" --body \"Message text\"\n$GAPI gmail send --to user@example.com --subject \"Report\" --body \"\u003Ch1>Q4\u003C\u002Fh1>\u003Cp>Details...\u003C\u002Fp>\" --html\n$GAPI gmail send --to user@example.com --subject \"Hello\" --from '\"Research Agent\" \u003Cuser@example.com>' --body \"Message text\"\n\n# Reply (automatically threads and sets In-Reply-To)\n$GAPI gmail reply MESSAGE_ID --body \"Thanks, that works for me.\"\n$GAPI gmail reply MESSAGE_ID --from '\"Support Bot\" \u003Cuser@example.com>' --body \"Thanks\"\n\n# Labels\n$GAPI gmail labels\n$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID\n$GAPI gmail modify MESSAGE_ID --remove-labels UNREAD\n```\n\n### Calendar\n\n```bash\n# List events (defaults to next 7 days)\n$GAPI calendar list\n$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z\n\n# Create event (ISO 8601 with timezone required)\n$GAPI calendar create --summary \"Team Standup\" --start 2026-03-01T10:00:00-06:00 --end 2026-03-01T10:30:00-06:00\n$GAPI calendar create --summary \"Lunch\" --start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z --location \"Cafe\"\n$GAPI calendar create --summary \"Review\" --start 2026-03-01T14:00:00Z --end 2026-03-01T15:00:00Z --attendees \"alice@co.com,bob@co.com\"\n\n# Delete event\n$GAPI calendar delete EVENT_ID\n```\n\n### Drive\n\n```bash\n$GAPI drive search \"quarterly report\" --max 10\n$GAPI drive search \"mimeType='application\u002Fpdf'\" --raw-query --max 5\n```\n\n### Contacts\n\n```bash\n$GAPI contacts list --max 20\n```\n\n### Sheets\n\n```bash\n# Read\n$GAPI sheets get SHEET_ID \"Sheet1!A1:D10\"\n\n# Write\n$GAPI sheets update SHEET_ID \"Sheet1!A1:B2\" --values '[[\"Name\",\"Score\"],[\"Alice\",\"95\"]]'\n\n# Append rows\n$GAPI sheets append SHEET_ID \"Sheet1!A:C\" --values '[[\"new\",\"row\",\"data\"]]'\n```\n\n### Docs\n\n```bash\n$GAPI docs get DOC_ID\n```\n\n## Output Format\n\nAll commands return JSON. Parse with `jq` or read directly. Key fields:\n\n- **Gmail search**: `[{id, threadId, from, to, subject, date, snippet, labels}]`\n- **Gmail get**: `{id, threadId, from, to, subject, date, labels, body}`\n- **Gmail send\u002Freply**: `{status: \"sent\", id, threadId}`\n- **Calendar list**: `[{id, summary, start, end, location, description, htmlLink}]`\n- **Calendar create**: `{status: \"created\", id, summary, htmlLink}`\n- **Drive search**: `[{id, name, mimeType, modifiedTime, webViewLink}]`\n- **Contacts list**: `[{name, emails: [...], phones: [...]}]`\n- **Sheets get**: `[[cell, cell, ...], ...]`\n\n## Rules\n\n1. **Never send email or create\u002Fdelete events without confirming with the user first.** Show the draft content and ask for approval.\n2. **Check auth before first use** — run `setup.py --check`. If it fails, guide the user through setup.\n3. **Use the Gmail search syntax reference** for complex queries — load it with `skill_view(\"google-workspace\", file_path=\"references\u002Fgmail-search-syntax.md\")`.\n4. **Calendar times must include timezone** — always use ISO 8601 with offset (e.g., `2026-03-01T10:00:00-06:00`) or UTC (`Z`).\n5. **Respect rate limits** — avoid rapid-fire sequential API calls. Batch reads when possible.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| `NOT_AUTHENTICATED` | Run setup Steps 2-5 above |\n| `REFRESH_FAILED` | Token revoked or expired — redo Steps 3-5 |\n| `HttpError 403: Insufficient Permission` | Missing API scope — `$GSETUP --revoke` then redo Steps 3-5 |\n| `HttpError 403: Access Not Configured` | API not enabled — user needs to enable it in Google Cloud Console |\n| `ModuleNotFoundError` | Run `$GSETUP --install-deps` |\n| Advanced Protection blocks auth | Workspace admin must allowlist the OAuth client ID |\n\n## Revoking Access\n\n```bash\n$GSETUP --revoke\n```\n","# Google Workspace\n\nGmail, Calendar, Drive, Contacts, Sheets, and Docs — through Hermes-managed OAuth and a thin CLI wrapper. When `gws` is installed, the skill uses it as the execution backend for broader Google Workspace coverage; otherwise it falls back to the bundled Python client implementation.\n\n## References\n\n- `references\u002Fgmail-search-syntax.md` — Gmail search operators (is:unread, from:, newer_than:, etc.)\n\n## Scripts\n\n- `scripts\u002Fsetup.py` — OAuth2 setup (run once to authorize)\n- `scripts\u002Fgoogle_api.py` — compatibility wrapper CLI. It prefers `gws` for operations when available, while preserving Hermes' existing JSON output contract.\n\n## First-Time Setup\n\nThe setup is fully non-interactive — you drive it step by step so it works\non CLI, Telegram, Discord, or any platform.\n\nDefine a shorthand first:\n\n```bash\nGSETUP=\"python ${HERMES_HOME:-$HOME\u002F.hermes}\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fsetup.py\"\n```\n\n### Step 0: Check if already set up\n\n```bash\n$GSETUP --check\n```\n\nIf it prints `AUTHENTICATED`, skip to Usage — setup is already done.\n\n### Step 1: Triage — ask the user what they need\n\nBefore starting OAuth setup, ask the user TWO questions:\n\n**Question 1: \"What Google services do you need? Just email, or also\nCalendar\u002FDrive\u002FSheets\u002FDocs?\"**\n\n- **Email only** → They don't need this skill at all. Use the `himalaya` skill\n  instead — it works with a Gmail App Password (Settings → Security → App\n  Passwords) and takes 2 minutes to set up. No Google Cloud project needed.\n  Load the himalaya skill and follow its setup instructions.\n\n- **Email + Calendar** → Continue with this skill, but use\n  `--services email,calendar` during auth so the consent screen only asks for\n  the scopes they actually need.\n\n- **Calendar\u002FDrive\u002FSheets\u002FDocs only** → Continue with this skill and use a\n  narrower `--services` set like `calendar,drive,sheets,docs`.\n\n- **Full Workspace access** → Continue with this skill and use the default\n  `all` service set.\n\n**Question 2: \"Does your Google account use Advanced Protection (hardware\nsecurity keys required to sign in)? If you're not sure, you probably don't\n— it's something you would have explicitly enrolled in.\"**\n\n- **No \u002F Not sure** → Normal setup. Continue below.\n- **Yes** → Their Workspace admin must add the OAuth client ID to the org's\n  allowed apps list before Step 4 will work. Let them know upfront.\n\n### Step 2: Create OAuth credentials (one-time, ~5 minutes)\n\nTell the user:\n\n> You need a Google Cloud OAuth client. This is a one-time setup:\n>\n> 1. Create or select a project:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fprojectselector2\u002Fhome\u002Fdashboard\n> 2. Enable the required APIs from the API Library:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fapis\u002Flibrary\n>    Enable: Gmail API, Google Calendar API, Google Drive API,\n>    Google Sheets API, Google Docs API, People API\n> 3. Create the OAuth client here:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fapis\u002Fcredentials\n>    Credentials → Create Credentials → OAuth 2.0 Client ID\n> 4. Application type: \"Desktop app\" → Create\n> 5. If the app is still in Testing, add the user's Google account as a test user here:\n>    https:\u002F\u002Fconsole.cloud.google.com\u002Fauth\u002Faudience\n>    Audience → Test users → Add users\n> 6. Download the JSON file and tell me the file path\n>\n> Important Hermes CLI note: if the file path starts with `\u002F`, do NOT send only the bare path as its own message in the CLI, because it can be mistaken for a slash command. Send it in a sentence instead, like:\n> `The JSON file path is: \u002Fhome\u002Fuser\u002FDownloads\u002Fclient_secret_....json`\n\nOnce they provide the path:\n\n```bash\n$GSETUP --client-secret \u002Fpath\u002Fto\u002Fclient_secret.json\n```\n\nIf they paste the raw client ID \u002F client secret values instead of a file path,\nwrite a valid Desktop OAuth JSON file for them yourself, save it somewhere\nexplicit (for example `~\u002FDownloads\u002Fhermes-google-client-secret.json`), then run\n`--client-secret` against that file.\n\n### Step 3: Get authorization URL\n\nUse the service set chosen in Step 1. Examples:\n\n```bash\n$GSETUP --auth-url --services email,calendar --format json\n$GSETUP --auth-url --services calendar,drive,sheets,docs --format json\n$GSETUP --auth-url --services all --format json\n```\n\nThis returns JSON with an `auth_url` field and also saves the exact URL to\n`~\u002F.hermes\u002Fgoogle_oauth_last_url.txt`.\n\nAgent rules for this step:\n- Extract the `auth_url` field and send that exact URL to the user as a single line.\n- Tell the user that the browser will likely fail on `http:\u002F\u002Flocalhost:1` after approval, and that this is expected.\n- Tell them to copy the ENTIRE redirected URL from the browser address bar.\n- If the user gets `Error 403: access_denied`, send them directly to `https:\u002F\u002Fconsole.cloud.google.com\u002Fauth\u002Faudience` to add themselves as a test user.\n\n### Step 4: Exchange the code\n\nThe user will paste back either a URL like `http:\u002F\u002Flocalhost:1\u002F?code=4\u002F0A...&scope=...`\nor just the code string. Either works. The `--auth-url` step stores a temporary\npending OAuth session locally so `--auth-code` can complete the PKCE exchange\nlater, even on headless systems:\n\n```bash\n$GSETUP --auth-code \"THE_URL_OR_CODE_THE_USER_PASTED\" --format json\n```\n\nIf `--auth-code` fails because the code expired, was already used, or came from\nan older browser tab, it now returns a fresh `fresh_auth_url`. In that case,\nimmediately send the new URL to the user and have them retry with the newest\nbrowser redirect only.\n\n### Step 5: Verify\n\n```bash\n$GSETUP --check\n```\n\nShould print `AUTHENTICATED`. Setup is complete — token refreshes automatically from now on.\n\n### Notes\n\n- Token is stored at `~\u002F.hermes\u002Fgoogle_token.json` and auto-refreshes.\n- Pending OAuth session state\u002Fverifier are stored temporarily at `~\u002F.hermes\u002Fgoogle_oauth_pending.json` until exchange completes.\n- If `gws` is installed, `google_api.py` points it at the same `~\u002F.hermes\u002Fgoogle_token.json` credentials file. Users do not need to run a separate `gws auth login` flow.\n- To revoke: `$GSETUP --revoke`\n\n## Usage\n\nAll commands go through the API script. Set `GAPI` as a shorthand:\n\n```bash\nGAPI=\"python ${HERMES_HOME:-$HOME\u002F.hermes}\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fgoogle_api.py\"\n```\n\n### Gmail\n\n```bash\n# Search (returns JSON array with id, from, subject, date, snippet)\n$GAPI gmail search \"is:unread\" --max 10\n$GAPI gmail search \"from:boss@company.com newer_than:1d\"\n$GAPI gmail search \"has:attachment filename:pdf newer_than:7d\"\n\n# Read full message (returns JSON with body text)\n$GAPI gmail get MESSAGE_ID\n\n# Send\n$GAPI gmail send --to user@example.com --subject \"Hello\" --body \"Message text\"\n$GAPI gmail send --to user@example.com --subject \"Report\" --body \"\u003Ch1>Q4\u003C\u002Fh1>\u003Cp>Details...\u003C\u002Fp>\" --html\n$GAPI gmail send --to user@example.com --subject \"Hello\" --from '\"Research Agent\" \u003Cuser@example.com>' --body \"Message text\"\n\n# Reply (automatically threads and sets In-Reply-To)\n$GAPI gmail reply MESSAGE_ID --body \"Thanks, that works for me.\"\n$GAPI gmail reply MESSAGE_ID --from '\"Support Bot\" \u003Cuser@example.com>' --body \"Thanks\"\n\n# Labels\n$GAPI gmail labels\n$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID\n$GAPI gmail modify MESSAGE_ID --remove-labels UNREAD\n```\n\n### Calendar\n\n```bash\n# List events (defaults to next 7 days)\n$GAPI calendar list\n$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z\n\n# Create event (ISO 8601 with timezone required)\n$GAPI calendar create --summary \"Team Standup\" --start 2026-03-01T10:00:00-06:00 --end 2026-03-01T10:30:00-06:00\n$GAPI calendar create --summary \"Lunch\" --start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z --location \"Cafe\"\n$GAPI calendar create --summary \"Review\" --start 2026-03-01T14:00:00Z --end 2026-03-01T15:00:00Z --attendees \"alice@co.com,bob@co.com\"\n\n# Delete event\n$GAPI calendar delete EVENT_ID\n```\n\n### Drive\n\n```bash\n$GAPI drive search \"quarterly report\" --max 10\n$GAPI drive search \"mimeType='application\u002Fpdf'\" --raw-query --max 5\n```\n\n### Contacts\n\n```bash\n$GAPI contacts list --max 20\n```\n\n### Sheets\n\n```bash\n# Read\n$GAPI sheets get SHEET_ID \"Sheet1!A1:D10\"\n\n# Write\n$GAPI sheets update SHEET_ID \"Sheet1!A1:B2\" --values '[[\"Name\",\"Score\"],[\"Alice\",\"95\"]]'\n\n# Append rows\n$GAPI sheets append SHEET_ID \"Sheet1!A:C\" --values '[[\"new\",\"row\",\"data\"]]'\n```\n\n### Docs\n\n```bash\n$GAPI docs get DOC_ID\n```\n\n## Output Format\n\nAll commands return JSON. Parse with `jq` or read directly. Key fields:\n\n- **Gmail search**: `[{id, threadId, from, to, subject, date, snippet, labels}]`\n- **Gmail get**: `{id, threadId, from, to, subject, date, labels, body}`\n- **Gmail send\u002Freply**: `{status: \"sent\", id, threadId}`\n- **Calendar list**: `[{id, summary, start, end, location, description, htmlLink}]`\n- **Calendar create**: `{status: \"created\", id, summary, htmlLink}`\n- **Drive search**: `[{id, name, mimeType, modifiedTime, webViewLink}]`\n- **Contacts list**: `[{name, emails: [...], phones: [...]}]`\n- **Sheets get**: `[[cell, cell, ...], ...]`\n\n## Rules\n\n1. **Never send email or create\u002Fdelete events without confirming with the user first.** Show the draft content and ask for approval.\n2. **Check auth before first use** — run `setup.py --check`. If it fails, guide the user through setup.\n3. **Use the Gmail search syntax reference** for complex queries — load it with `skill_view(\"google-workspace\", file_path=\"references\u002Fgmail-search-syntax.md\")`.\n4. **Calendar times must include timezone** — always use ISO 8601 with offset (e.g., `2026-03-01T10:00:00-06:00`) or UTC (`Z`).\n5. **Respect rate limits** — avoid rapid-fire sequential API calls. Batch reads when possible.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| `NOT_AUTHENTICATED` | Run setup Steps 2-5 above |\n| `REFRESH_FAILED` | Token revoked or expired — redo Steps 3-5 |\n| `HttpError 403: Insufficient Permission` | Missing API scope — `$GSETUP --revoke` then redo Steps 3-5 |\n| `HttpError 403: Access Not Configured` | API not enabled — user needs to enable it in Google Cloud Console |\n| `ModuleNotFoundError` | Run `$GSETUP --install-deps` |\n| Advanced Protection blocks auth | Workspace admin must allowlist the OAuth client ID |\n\n## Revoking Access\n\n```bash\n$GSETUP --revoke\n```\n",{"name":5,"author":43,"license":14,"version":44,"metadata":45,"description":7},"Nous Research","1.0.0",{"hermes":46},{"tags":47,"homepage":56,"related_skills":57},[48,49,50,51,52,53,54,55,30],"Google","Gmail","Calendar","Drive","Sheets","Docs","Contacts","Email","https:\u002F\u002Fgithub.com\u002FNousResearch\u002Fhermes-agent",[34],"main","6746276ba18cb774853eb61b3b9399658bc9bc5c","core\u002Fskills\u002Fproductivity\u002Fgoogle-workspace","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch","2026-04-28 17:01:03",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add gjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN --skill google-workspace",{"tool":70,"command":71},"bunx","bunx skills add gjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN --skill google-workspace",{"tool":73,"command":74},"pnpm","pnpm dlx skills add gjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN --skill google-workspace","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002FSKILL.md",true,[78,84,90,94,98],{"path":79,"resourceType":80,"resourceTypeDesc":81,"sizeBytes":82,"sourceHtmlUrl":83},"references\u002Fgmail-search-syntax.md","REFERENCE","参考文档",2150,"https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Freferences\u002Fgmail-search-syntax.md",{"path":85,"resourceType":86,"resourceTypeDesc":87,"sizeBytes":88,"sourceHtmlUrl":89},"scripts\u002F_hermes_home.py","SCRIPT","脚本",1630,"https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002F_hermes_home.py",{"path":91,"resourceType":86,"resourceTypeDesc":87,"sizeBytes":92,"sourceHtmlUrl":93},"scripts\u002Fgoogle_api.py",30051,"https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fgoogle_api.py",{"path":95,"resourceType":86,"resourceTypeDesc":87,"sizeBytes":96,"sourceHtmlUrl":97},"scripts\u002Fgws_bridge.py",3483,"https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fgws_bridge.py",{"path":99,"resourceType":86,"resourceTypeDesc":87,"sizeBytes":100,"sourceHtmlUrl":101},"scripts\u002Fsetup.py",15092,"https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fproductivity\u002Fgoogle-workspace\u002Fscripts\u002Fsetup.py",[103,146,171,187,206,225],{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":125,"publishedAt":38},"01M71QG27G1R2H2ZWEG4S0WTZT","writing-plans","Write implementation plans: bite-sized tasks, paths, code.","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fsoftware-development\u002Fwriting-plans\u002FSKILL.md",[109,114,117,122],{"categoryNo":110,"categoryName":111,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":115,"categoryName":116,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",{"categoryNo":123,"categoryName":124,"taxonomyType":120,"taxonomyTypeDesc":121},"01JBSEEDCAT000000000000036","内容创作者",[126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145],"writing","writing plans","plans","test-driven","test-driven-development","superpowers","design","workflow","code","tasks","subagent","code-review","review","documentation","write","paths","planning","development","test","implementation",{"skillNo":147,"name":130,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":157,"publishedAt":38},"01M71QFZYRTJXMAE551MRAKZ14","TDD: enforce RED-GREEN-REFACTOR, tests before code.","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fsoftware-development\u002Ftest-driven-development\u002FSKILL.md",[151,154],{"categoryNo":152,"categoryName":153,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":155,"categoryName":156,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000008","测试与质量",[158,143,144,159,160,161,162,131,126,163,134,136,164,165,166,167,168,128,169,170],"test driven development","driven","green","red-green-refactor","testing","debugging","systematic","refactor","systematic-debugging","enforce","tests","tdd","quality",{"skillNo":172,"name":166,"nameZh":6,"description":173,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":174,"categories":175,"keywords":177,"publishedAt":38},"01M71QFWR5Q8EYEQ6MCS3SM6MC","4-phase root cause debugging: understand bugs before fixing.","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fsoftware-development\u002Fsystematic-debugging\u002FSKILL.md",[176],{"categoryNo":155,"categoryName":156,"taxonomyType":112,"taxonomyTypeDesc":113},[178,163,164,129,179,180,130,131,126,136,181,182,143,183,128,184,144,185,186,29],"systematic debugging","problem","problem-solving","phase","bugs","root cause","root-cause","investigation","understand",{"skillNo":188,"name":189,"nameZh":6,"description":190,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":191,"categories":192,"keywords":198,"publishedAt":38},"01M71QFS9S04MD8JP747W5WM0N","subagent-driven-development","Execute plans via delegate_task subagents (2-stage review).","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fsoftware-development\u002Fsubagent-driven-development\u002FSKILL.md",[193,194,197],{"categoryNo":115,"categoryName":116,"taxonomyType":112,"taxonomyTypeDesc":113},{"categoryNo":195,"categoryName":196,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":123,"categoryName":124,"taxonomyType":120,"taxonomyTypeDesc":121},[199,136,143,159,129,130,200,201,131,126,133,134,137,138,202,203,128,204,205,144],"subagent driven development","delegate","delegation","subagents","parallel","stage","task",{"skillNo":207,"name":208,"nameZh":6,"description":209,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":210,"categories":211,"keywords":214,"publishedAt":38},"01M71QFQ1DBCVAZ511MXFE6T2V","requesting-code-review","Pre-commit review: security scan, quality gates, auto-fix.","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fsoftware-development\u002Frequesting-code-review\u002FSKILL.md",[212,213],{"categoryNo":152,"categoryName":153,"taxonomyType":112,"taxonomyTypeDesc":113},{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},[215,216,134,138,129,130,217,218,131,219,126,220,221,136,137,222,223,143,224,128],"code review","requesting code review","fix","auto-fix","auto","security scan","commit","verification","security","scan",{"skillNo":226,"name":227,"nameZh":6,"description":228,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":229,"categories":230,"keywords":232,"publishedAt":38},"01M71QFM7KWM540YR67FRN807Q","python-debugpy","Debug Python: pdb REPL + debugpy remote (DAP).","https:\u002F\u002Fgithub.com\u002Fgjbvsjjvgm-sketch\u002FWORM_V2_SOVEREIGN\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fsoftware-development\u002Fpython-debugpy\u002FSKILL.md",[231],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},[233,234,36,235,236,237,238,239,163,164,240,241,242,166,243,244,245,246,29,247],"debugpy","python debugpy","dap","inspect","post-mortem","pdb","remote","debugger","node","commands","debug","post","breakpoints","node-inspect","tui"]