Use this skill when the OpenART registry selects tool.google_workspace.1a73bb6e82d43d1e for the current task.
Google Workspace Skill
Operate all Google Workspace services through the gws CLI from OpenClaw.
Prerequisites
- Node.js 18+
- A Google Cloud project with OAuth credentials
gwsCLI installed:npm install -g @googleworkspace/cli
Authentication
First-time setup (machine with browser)
bashgws auth setup # creates GCP project, enables APIs, logs in gws auth login -s drive,gmail,sheets,calendar # pick services you need
Headless server (no browser)
Complete auth on a machine with a browser, then export:
bashgws auth export --unmasked > credentials.json
Security notes:
- Set file permissions:
chmod 600 credentials.json- Do not commit credential files to git — add
credentials.jsonto your.gitignore- For production environments, prefer using a service account instead of user credentials
On the headless server:
bashexport GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/credentials.json
Service account
bashexport GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/service-account.json
Pre-obtained token
bashexport GOOGLE_WORKSPACE_CLI_TOKEN=$(gcloud auth print-access-token)
Priority: Token env > Credentials file env > gws auth login store > plaintext file.
Command Pattern
bashgws <service> <resource> <method> [--params '{}'] [--json '{}'] [flags]
All responses are structured JSON. Use jq for extraction.
Global Flags
| Flag | Purpose |
|---|---|
--dry-run | Preview request without executing |
--page-all | Stream all pages as NDJSON |
--fields 'a,b' | Select response fields |
--output table | Table output for humans |
Discover commands
bashgws --help # list all services gws drive --help # list resources in a service gws drive files --help # list methods on a resource gws schema drive.files.list # full request/response schema
Common Operations
Drive
bash# List recent files gws drive files list --params '{"pageSize": 10}' # Search files gws drive files list --params '{"q": "name contains '\''report'\''", "pageSize": 20}' # Upload a file gws drive +upload ./report.pdf # Download a file gws drive files get --params '{"fileId": "FILE_ID", "alt": "media"}' > output.pdf # Create a folder gws drive files create --json '{"name": "Project", "mimeType": "application/vnd.google-apps.folder"}' # Share a file gws drive permissions create \ --params '{"fileId": "FILE_ID"}' \ --json '{"role": "reader", "type": "user", "emailAddress": "user@example.com"}' # List all pages gws drive files list --params '{"pageSize": 100}' --page-all | jq -r '.files[].name'
Gmail
bash# List inbox messages gws gmail users-messages list --params '{"userId": "me", "maxResults": 10}' # Read a message gws gmail users-messages get --params '{"userId": "me", "id": "MSG_ID"}' # Send an email gws gmail users-messages send \ --params '{"userId": "me"}' \ --json '{"raw": "BASE64_ENCODED_EMAIL"}' # Search messages gws gmail users-messages list --params '{"userId": "me", "q": "from:boss@company.com is:unread"}' # List labels gws gmail users-labels list --params '{"userId": "me"}' # Create a filter gws gmail users-settings-filters create \ --params '{"userId": "me"}' \ --json '{"criteria": {"from": "noreply@example.com"}, "action": {"addLabelIds": ["LABEL_ID"], "removeLabelIds": ["INBOX"]}}'
Calendar
bash# List upcoming events gws calendar events list --params '{"calendarId": "primary", "timeMin": "2026-01-01T00:00:00Z", "maxResults": 10, "orderBy": "startTime", "singleEvents": true}' # Create an event gws calendar events insert \ --params '{"calendarId": "primary"}' \ --json '{"summary": "Team Sync", "start": {"dateTime": "2026-03-07T10:00:00+08:00"}, "end": {"dateTime": "2026-03-07T11:00:00+08:00"}, "attendees": [{"email": "user@example.com"}]}' # Delete an event gws calendar events delete --params '{"calendarId": "primary", "eventId": "EVENT_ID"}' # Find free/busy slots gws calendar freebusy query \ --json '{"timeMin": "2026-03-07T00:00:00Z", "timeMax": "2026-03-07T23:59:59Z", "items": [{"id": "user@example.com"}]}'
Sheets
bash# Create a spreadsheet gws sheets spreadsheets create --json '{"properties": {"title": "Q1 Budget"}}' # Read cell values gws sheets spreadsheets-values get --params '{"spreadsheetId": "SHEET_ID", "range": "Sheet1!A1:D10"}' # Write values gws sheets spreadsheets-values update \ --params '{"spreadsheetId": "SHEET_ID", "range": "Sheet1!A1", "valueInputOption": "USER_ENTERED"}' \ --json '{"values": [["Name", "Amount"], ["Rent", "2000"]]}' # Append a row gws sheets spreadsheets-values append \ --params '{"spreadsheetId": "SHEET_ID", "range": "Sheet1!A1", "valueInputOption": "USER_ENTERED"}' \ --json '{"values": [["New Item", "500"]]}'
Docs
bash# Create a document gws docs documents create --json '{"title": "Meeting Notes"}' # Get document content gws docs documents get --params '{"documentId": "DOC_ID"}' # Insert text (batchUpdate) gws docs documents batchUpdate \ --params '{"documentId": "DOC_ID"}' \ --json '{"requests": [{"insertText": {"location": {"index": 1}, "text": "Hello World\n"}}]}'
Chat
bash# List spaces gws chat spaces list # Send a message gws chat spaces messages create \ --params '{"parent": "spaces/SPACE_ID"}' \ --json '{"text": "Deploy complete ✅"}'
Tasks
bash# List task lists gws tasks tasklists list # List tasks gws tasks tasks list --params '{"tasklist": "TASKLIST_ID"}' # Create a task gws tasks tasks insert \ --params '{"tasklist": "TASKLIST_ID"}' \ --json '{"title": "Review PR", "due": "2026-03-10T00:00:00Z"}'
Admin (Directory)
bash# List users gws admin users list --params '{"domain": "example.com"}' # Get user details gws admin users get --params '{"userKey": "user@example.com"}'
Workflow Patterns
Pipeline: Find → Process → Act
bash# Find unread emails from boss, extract subjects gws gmail users-messages list --params '{"userId": "me", "q": "from:boss is:unread"}' \ | jq -r '.messages[].id' \ | while read id; do gws gmail users-messages get --params "{\"userId\": \"me\", \"id\": \"$id\"}" \ | jq -r '.payload.headers[] | select(.name=="Subject") | .value' done
Dry-run first
Always use --dry-run before destructive operations:
bashgws drive files delete --params '{"fileId": "FILE_ID"}' --dry-run
Tips
- Use
gws schema <method>to discover exact parameter names and types. - All commands accept
--paramsfor URL/query parameters and--jsonfor request body. - Pipe through
jqfor field extraction in agent pipelines. - Use
--page-allfor full result sets with automatic pagination. - Credentials are encrypted at rest (AES-256-GCM) with OS keyring.
Recipes
For 50+ ready-made workflow recipes (label & archive emails, organize Drive folders, schedule meetings, etc.), see the official recipe library.
Disclaimer
The gws CLI is not an officially supported Google product. It is a community/experimental tool. Use at your own discretion, and refer to the upstream repository for license and support details.
Troubleshooting
| Issue | Fix |
|---|---|
gws: command not found | npm install -g @googleworkspace/cli |
| Auth fails / scope error | gws auth login -s drive,gmail (pick specific services) |
| "Access blocked" on login | Add yourself as test user in GCP OAuth consent screen |
| Headless server | Export creds from a desktop, set GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE |
| Rate limited | Add delays between calls, reduce pageSize |


