google-workspace
SkillCommunicationGmail, Calendar, Drive, Contacts, Sheets, and Docs integration via gws
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the google-workspace skill
What this skill tells your AI
The instructions your AI receives, as published by graniet/kheish in skills/productivity/google-workspace/SKILL.md and read by ahel’s review.
Kheish Compatibility
This skill is repo-local and stays inactive until explicitly activated.
When the original instructions refer to legacy tool names, use these Kheish mappings:
terminal=>bashweb_extract=>web_fetch, plusweb_searchwhen discovery is neededsearch_files=>grep_searchandglob_searchbrowser_*tools require a browser-capable surfaced tool or MCP; if none is available, use the closest available surface and say so explicitly
When the instructions mention local helper files, resolve them from ${KHEISH_SKILL_DIR}.
Google Workspace
Gmail, Calendar, Drive, Contacts, Sheets, and Docs — powered by gws (Google's official Rust CLI). The skill provides a backward-compatible Python wrapper that handles OAuth token refresh and delegates to gws.
Architecture
google_api.py → gws_bridge.py → gws CLI
(argparse compat) (token refresh) (Google APIs)
setup.pyhandles OAuth2 (headless-compatible, works on CLI/Telegram/Discord)gws_bridge.pyrefreshes the Kheish token and injects it intogwsviaGOOGLE_WORKSPACE_CLI_TOKENgoogle_api.pyprovides the same CLI interface as v1 but delegates togws
References
references/gmail-search-syntax.md— Gmail search operators (is:unread, from:, newer_than:, etc.)
Scripts
scripts/setup.py— OAuth2 setup (run once to authorize)scripts/gws_bridge.py— Token refresh bridge to gws CLIscripts/google_api.py— Backward-compatible API wrapper (delegates to gws)
Prerequisites
Install gws:
cargo install google-workspace-cli
# or via npm (recommended, downloads prebuilt binary):
npm install -g @googleworkspace/cli
# or via Homebrew:
brew install googleworkspace-cli
Verify: gws --version
First-Time Setup
The setup is fully non-interactive — you drive it step by step so it works on CLI, Telegram, Discord, or any platform.
Define a shorthand first:
GWORKSPACE_SKILL_DIR=".agents/skills/productivity/google-workspace"
PYTHON_BIN="${PYTHON_BIN:-python3}"
GSETUP="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/setup.py"
Step 0: Check if already set up
$GSETUP --check
If it prints AUTHENTICATED, skip to Usage — setup is already done.
Step 1: Triage — ask the user what they need
Question 1: "What Google services do you need? Just email, or also Calendar/Drive/Sheets/Docs?"
- Email only → Use the
himalayaskill instead — simpler setup. - Calendar, Drive, Sheets, Docs (or email + these) → Continue below.
Partial scopes: Users can authorize only a subset of services. The setup script accepts partial scopes and warns about missing ones.
Question 2: "Does your Google account use Advanced Protection?"
- No / Not sure → Normal setup.
- Yes → Workspace admin must add the OAuth client ID to allowed apps first.
Step 2: Create OAuth credentials (one-time, ~5 minutes)
Tell the user:
- Go to https://console.cloud.google.com/apis/credentials
- Create a project (or use an existing one)
- Enable the APIs you need (Gmail, Calendar, Drive, Sheets, Docs, People)
- Credentials → Create Credentials → OAuth 2.0 Client ID → Desktop app
- Download JSON and tell me the file path
$GSETUP --client-secret /path/to/client_secret.json
Step 3: Get authorization URL
$GSETUP --auth-url
Send the URL to the user. After authorizing, they paste back the redirect URL or code.
Step 4: Exchange the code
$GSETUP --auth-code "THE_URL_OR_CODE_THE_USER_PASTED"
Step 5: Verify
$GSETUP --check
Should print AUTHENTICATED. Token refreshes automatically from now on.
Usage
All commands go through the API script:
GWORKSPACE_SKILL_DIR=".agents/skills/productivity/google-workspace"
PYTHON_BIN="${PYTHON_BIN:-python3}"
GAPI="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/google_api.py"
Gmail
$GAPI gmail search "is:unread" --max 10
$GAPI gmail get MESSAGE_ID
$GAPI gmail send --to user@example.com --subject "Hello" --body "Message text"
$GAPI gmail send --to user@example.com --subject "Report" --body "<h1>Q4</h1>" --html
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me."
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID
Calendar
$GAPI calendar list
$GAPI calendar create --summary "Standup" --start 2026-03-01T10:00:00+01:00 --end 2026-03-01T10:30:00+01:00
$GAPI calendar create --summary "Review" --start ... --end ... --attendees "alice@co.com,bob@co.com"
$GAPI calendar delete EVENT_ID
Drive
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5
Contacts
$GAPI contacts list --max 20
Sheets
$GAPI sheets get SHEET_ID "Sheet1!A1:D10"
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[["Name","Score"],["Alice","95"]]'
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[["new","row","data"]]'
Docs
$GAPI docs get DOC_ID
Direct gws access (advanced)
For operations not covered by the wrapper, use gws_bridge.py directly:
GBRIDGE="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/gws_bridge.py"
$GBRIDGE calendar +agenda --today --format table
$GBRIDGE gmail +triage --labels --format json
$GBRIDGE drive +upload ./report.pdf
$GBRIDGE sheets +read --spreadsheet SHEET_ID --range "Sheet1!A1:D10"
Output Format
All commands return JSON via gws --format json. Key output shapes:
- Gmail search/triage: Array of message summaries (sender, subject, date, snippet)
- Gmail get/read: Message object with headers and body text
- Gmail send/reply: Confirmation with message ID
- Calendar list/agenda: Array of event objects (summary, start, end, location)
- Calendar create: Confirmation with event ID and htmlLink
- Drive search: Array of file objects (id, name, mimeType, webViewLink)
- Sheets get/read: 2D array of cell values
- Docs get: Full document JSON (use
body.contentfor text extraction) - Contacts list: Array of person objects with names, emails, phones
Parse output with jq or read JSON directly.
Rules
- Never send email or create/delete events without confirming with the user first.
- Check auth before first use — run
setup.py --check. - Use the Gmail search syntax reference for complex queries.
- Calendar times must include timezone — ISO 8601 with offset or UTC.
- Respect rate limits — avoid rapid-fire sequential API calls.
Troubleshooting
| Problem | Fix |
|---|---|
NOT_AUTHENTICATED | Run setup Steps 2-5 |
REFRESH_FAILED | Token revoked — redo Steps 3-5 |
gws: command not found | Install: npm install -g @googleworkspace/cli |
HttpError 403 | Missing scope — $GSETUP --revoke then redo Steps 3-5 |
HttpError 403: Access Not Configured | Enable API in Google Cloud Console |
| Advanced Protection blocks auth | Admin must allowlist the OAuth client ID |
Revoking Access
$GSETUP --revoke
Signals
- GitHub stars
- 221
- Forks
- 18
- Last commit
- Jul 2026
ahel review
S4info
community integration, published by graniet, not googleK1binfo
installs-packagesK6low
bundled executables the agent is told to runK1binfo
installs-packages (in scripts/setup.py)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
google-workspace-graniet- Source
- github.com/graniet/kheish