Google Workspace CLI (gws)
CLI for Gmail, Calendar, Drive, Sheets, Docs, Slides, Tasks, People, Chat, Meet, Forms, Keep, Admin, and cross-service workflows.
Binary: /opt/homebrew/bin/gws
Command Pattern
gws <service> <resource> [sub-resource] <method> [flags]
Every command accepts:
--params <JSON> — URL/query parameters
--json <JSON> — request body (POST/PATCH/PUT)
--upload <PATH> — file to upload as media content
--output <PATH> — path for binary responses (downloads)
--format json|table|yaml|csv — output format (default: json)
--page-all / --page-limit N — auto-paginate
--dry-run — validate locally without sending
Quick Reference — Helper Commands (prefer these)
| Command |
Purpose |
R/W |
gws gmail +triage [--max N] [--query Q] |
Unread inbox summary |
R |
gws gmail +send --to EMAIL --subject S --body T |
Send plaintext email |
W |
gws gmail +watch --project GCP |
Stream new emails (Pub/Sub) |
R |
gws calendar +agenda [--today|--tomorrow|--week|--days N] |
Upcoming events |
R |
gws calendar +insert --summary T --start ISO --end ISO |
Create event |
W |
gws drive +upload FILE [--parent ID] [--name N] |
Upload file |
W |
gws sheets +read --spreadsheet ID --range R |
Read range (e.g. Sheet1!A1:D10) |
R |
gws sheets +append --spreadsheet ID --values "a,b,c" |
Append row (or --json-values) |
W |
gws docs +write --document ID --text T |
Append text to doc |
W |
gws chat +send --space spaces/ID --text T |
Post to Chat space |
W |
gws workflow +standup-report |
Today's meetings + open tasks |
R |
gws workflow +meeting-prep [--calendar ID] |
Next meeting details |
R |
gws workflow +email-to-task --message-id ID |
Email → Task |
W |
gws workflow +weekly-digest |
Week's meetings + unread |
R |
gws workflow +file-announce --file-id ID --space SPACE |
Announce file in Chat |
W |
Common Patterns
Gmail
# Triage unread (table for humans)
gws gmail +triage --max 10 --format table
# Search
gws gmail users messages list --params '{"userId":"me","q":"from:amazon newer_than:7d","maxResults":5}'
# Read full message
gws gmail users messages get --params '{"userId":"me","id":"MSG_ID","format":"full"}'
# Read headers only (faster)
gws gmail users messages get --params '{"userId":"me","id":"MSG_ID","format":"metadata","metadataHeaders":["Subject","From","Date"]}'
# Archive (remove INBOX)
gws gmail users messages modify --params '{"userId":"me","id":"MSG_ID"}' --json '{"removeLabelIds":["INBOX"]}'
# Trash
gws gmail users messages trash --params '{"userId":"me","id":"MSG_ID"}'
# Bulk label
gws gmail users messages batchModify --params '{"userId":"me"}' --json '{"ids":["ID1","ID2"],"addLabelIds":["Label_123"]}'
Calendar
# Today (Europe/Berlin default works with RFC3339 +02:00/+01:00)
gws calendar +agenda --today --format table
# Create simple event
gws calendar +insert \
--summary 'AGENCY Meetup' \
--start '2026-04-14T18:00:00+02:00' \
--end '2026-04-14T19:00:00+02:00' \
--location 'https://us02web.zoom.us/j/8991032224' \
--description 'Zoom: https://us02web.zoom.us/j/8991032224'
# Event WITH Google Meet link (helper doesn't support — use raw)
gws calendar events insert \
--params '{"calendarId":"primary","conferenceDataVersion":1}' \
--json '{
"summary":"Sync",
"start":{"dateTime":"2026-04-15T14:00:00+02:00"},
"end":{"dateTime":"2026-04-15T15:00:00+02:00"},
"conferenceData":{"createRequest":{"requestId":"req-'$(date +%s)'","conferenceSolutionKey":{"type":"hangoutsMeet"}}}
}'
# Update event
gws calendar events patch --params '{"calendarId":"primary","eventId":"EID"}' --json '{"summary":"New title"}'
# Delete
gws calendar events delete --params '{"calendarId":"primary","eventId":"EID"}'
# List all calendars
gws calendar calendarList list --format table
Drive
# Upload to root
gws drive +upload ./report.pdf
# Upload to folder
gws drive +upload ./data.csv --parent FOLDER_ID --name 'Sales Data.csv'
# Search files
gws drive files list --params '{"q":"name contains \"report\" and mimeType=\"application/pdf\"","pageSize":10}'
# Download
gws drive files get --params '{"fileId":"FID","alt":"media"}' --output ./local.pdf
# Create folder
gws drive files create --json '{"name":"MyFolder","mimeType":"application/vnd.google-apps.folder"}'
# Share with user
gws drive permissions create --params '{"fileId":"FID"}' --json '{"role":"reader","type":"user","emailAddress":"user@example.com"}'
Sheets
# Read
gws sheets +read --spreadsheet SID --range 'Sheet1!A1:D10' --format table
# Append single row (simple values)
gws sheets +append --spreadsheet SID --values 'Alice,100,true'
# Append multiple rows
gws sheets +append --spreadsheet SID --json-values '[["a","b"],["c","d"]]'
Tasks
gws tasks tasklists list
gws tasks tasks list --params '{"tasklist":"@default"}'
gws tasks tasks insert --params '{"tasklist":"@default"}' --json '{"title":"My task","notes":"Details","due":"2026-04-20T00:00:00Z"}'
gws tasks tasks patch --params '{"tasklist":"@default","task":"TID"}' --json '{"status":"completed"}'
Chat
# Find space
gws chat spaces list --format table
# Post message
gws chat +send --space spaces/AAAAxxxx --text 'Hello team!'
People / Contacts
gws people people connections list --params '{"resourceName":"people/me","personFields":"names,emailAddresses","pageSize":100}'
gws people people searchContacts --params '{"query":"John","readMask":"names,emailAddresses"}'
Critical Notes
- userId: Every Gmail raw call needs
"userId":"me" in params.
- RFC3339 times: Calendar uses full ISO with offset (
2026-04-14T18:00:00+02:00). "Z" for UTC.
- Meet links:
+insert does NOT add conferencing — use raw events.insert with conferenceDataVersion=1 and conferenceData.createRequest.
- Pagination:
--page-all emits NDJSON (one JSON object per page). --page-limit N caps pages.
- Schema discovery:
gws schema <service>.<resource>.<method> — e.g. gws schema gmail.users.messages.list.
- Filters:
gmail.settings.basic scope required — special manual OAuth flow (see references/api_reference.md).
- Write confirmation: Always confirm with user before
+send, +insert, +email-to-task, +file-announce, drive files delete, events delete, messages trash.
- Format choice:
--format table for human-readable summaries; default json for scripting/piping to jq.
OAuth Setup
- GCP project:
n8n-automations-454016
- Credentials:
~/.config/gws/credentials.json
- Configured scopes:
gmail.modify, gmail.settings.basic, drive, spreadsheets, tasks, calendar, documents, chat.messages, contacts.readonly
gmail.settings.basic scope needs manual OAuth (Python localhost listener on port 8085) — gws auth login --scopes cannot request it directly.
Full API Reference
For full command inventory, all raw API calls, pagination, labels, drafts, filters, and admin APIs, see references/api_reference.md.
1---2name: gws3description: This skill should be used when interacting with Google Workspace services via the gws CLI — Gmail (search, triage, send, labels, filters, drafts), Calendar (agenda, events, Meet conferencing), Drive (upload, list, share, download), Sheets (read, append), Docs, Tasks, Chat (send), People/Contacts, and cross-service workflows (standup, meeting prep, weekly digest, email-to-task). Triggers on queries like "check my email", "search Gmail", "send email", "calendar agenda", "create calendar event", "upload to Drive", "read spreadsheet", "create a task", "triage inbox", "find contact", "post to Chat".4---5
6# Google Workspace CLI (gws)
7
8CLI for Gmail, Calendar, Drive, Sheets, Docs, Slides, Tasks, People, Chat, Meet, Forms, Keep, Admin, and cross-service workflows.
9
10Binary: `/opt/homebrew/bin/gws`
11
12## Command Pattern
13
14```
15gws <service> <resource> [sub-resource] <method> [flags]
16```
17
18Every command accepts:
19- `--params <JSON>` — URL/query parameters
20- `--json <JSON>` — request body (POST/PATCH/PUT)
21- `--upload <PATH>` — file to upload as media content
22- `--output <PATH>` — path for binary responses (downloads)
23- `--format json|table|yaml|csv` — output format (default: json)
24- `--page-all` / `--page-limit N` — auto-paginate
25- `--dry-run` — validate locally without sending
26
27## Quick Reference — Helper Commands (prefer these)
28
29| Command | Purpose | R/W |
30|---|---|---|
31| `gws gmail +triage [--max N] [--query Q]` | Unread inbox summary | R |
32| `gws gmail +send --to EMAIL --subject S --body T` | Send plaintext email | W |
33| `gws gmail +watch --project GCP` | Stream new emails (Pub/Sub) | R |
34| `gws calendar +agenda [--today\|--tomorrow\|--week\|--days N]` | Upcoming events | R |
35| `gws calendar +insert --summary T --start ISO --end ISO` | Create event | W |
36| `gws drive +upload FILE [--parent ID] [--name N]` | Upload file | W |
37| `gws sheets +read --spreadsheet ID --range R` | Read range (e.g. `Sheet1!A1:D10`) | R |
38| `gws sheets +append --spreadsheet ID --values "a,b,c"` | Append row (or `--json-values`) | W |
39| `gws docs +write --document ID --text T` | Append text to doc | W |
40| `gws chat +send --space spaces/ID --text T` | Post to Chat space | W |
41| `gws workflow +standup-report` | Today's meetings + open tasks | R |
42| `gws workflow +meeting-prep [--calendar ID]` | Next meeting details | R |
43| `gws workflow +email-to-task --message-id ID` | Email → Task | W |
44| `gws workflow +weekly-digest` | Week's meetings + unread | R |
45| `gws workflow +file-announce --file-id ID --space SPACE` | Announce file in Chat | W |
46
47## Common Patterns
48
49### Gmail
50```bash
51# Triage unread (table for humans)
52gws gmail +triage --max 10 --format table
53
54# Search
55gws gmail users messages list --params '{"userId":"me","q":"from:amazon newer_than:7d","maxResults":5}'
56
57# Read full message
58gws gmail users messages get --params '{"userId":"me","id":"MSG_ID","format":"full"}'
59
60# Read headers only (faster)
61gws gmail users messages get --params '{"userId":"me","id":"MSG_ID","format":"metadata","metadataHeaders":["Subject","From","Date"]}'
62
63# Archive (remove INBOX)
64gws gmail users messages modify --params '{"userId":"me","id":"MSG_ID"}' --json '{"removeLabelIds":["INBOX"]}'
65
66# Trash
67gws gmail users messages trash --params '{"userId":"me","id":"MSG_ID"}'
68
69# Bulk label
70gws gmail users messages batchModify --params '{"userId":"me"}' --json '{"ids":["ID1","ID2"],"addLabelIds":["Label_123"]}'
71```
72
73### Calendar
74```bash
75# Today (Europe/Berlin default works with RFC3339 +02:00/+01:00)
76gws calendar +agenda --today --format table
77
78# Create simple event
79gws calendar +insert \
80 --summary 'AGENCY Meetup' \
81 --start '2026-04-14T18:00:00+02:00' \
82 --end '2026-04-14T19:00:00+02:00' \
83 --location 'https://us02web.zoom.us/j/8991032224' \
84 --description 'Zoom: https://us02web.zoom.us/j/8991032224'
85
86# Event WITH Google Meet link (helper doesn't support — use raw)
87gws calendar events insert \
88 --params '{"calendarId":"primary","conferenceDataVersion":1}' \
89 --json '{
90 "summary":"Sync",
91 "start":{"dateTime":"2026-04-15T14:00:00+02:00"},
92 "end":{"dateTime":"2026-04-15T15:00:00+02:00"},
93 "conferenceData":{"createRequest":{"requestId":"req-'$(date +%s)'","conferenceSolutionKey":{"type":"hangoutsMeet"}}}
94 }'
95
96# Update event
97gws calendar events patch --params '{"calendarId":"primary","eventId":"EID"}' --json '{"summary":"New title"}'
98
99# Delete
100gws calendar events delete --params '{"calendarId":"primary","eventId":"EID"}'
101
102# List all calendars
103gws calendar calendarList list --format table
104```
105
106### Drive
107```bash
108# Upload to root
109gws drive +upload ./report.pdf
110
111# Upload to folder
112gws drive +upload ./data.csv --parent FOLDER_ID --name 'Sales Data.csv'
113
114# Search files
115gws drive files list --params '{"q":"name contains \"report\" and mimeType=\"application/pdf\"","pageSize":10}'
116
117# Download
118gws drive files get --params '{"fileId":"FID","alt":"media"}' --output ./local.pdf
119
120# Create folder
121gws drive files create --json '{"name":"MyFolder","mimeType":"application/vnd.google-apps.folder"}'
122
123# Share with user
124gws drive permissions create --params '{"fileId":"FID"}' --json '{"role":"reader","type":"user","emailAddress":"user@example.com"}'
125```
126
127### Sheets
128```bash
129# Read
130gws sheets +read --spreadsheet SID --range 'Sheet1!A1:D10' --format table
131
132# Append single row (simple values)
133gws sheets +append --spreadsheet SID --values 'Alice,100,true'
134
135# Append multiple rows
136gws sheets +append --spreadsheet SID --json-values '[["a","b"],["c","d"]]'
137```
138
139### Tasks
140```bash
141gws tasks tasklists list
142gws tasks tasks list --params '{"tasklist":"@default"}'
143gws tasks tasks insert --params '{"tasklist":"@default"}' --json '{"title":"My task","notes":"Details","due":"2026-04-20T00:00:00Z"}'
144gws tasks tasks patch --params '{"tasklist":"@default","task":"TID"}' --json '{"status":"completed"}'
145```
146
147### Chat
148```bash
149# Find space
150gws chat spaces list --format table
151
152# Post message
153gws chat +send --space spaces/AAAAxxxx --text 'Hello team!'
154```
155
156### People / Contacts
157```bash
158gws people people connections list --params '{"resourceName":"people/me","personFields":"names,emailAddresses","pageSize":100}'
159gws people people searchContacts --params '{"query":"John","readMask":"names,emailAddresses"}'
160```
161
162## Critical Notes
163
164- **userId**: Every Gmail raw call needs `"userId":"me"` in params.
165- **RFC3339 times**: Calendar uses full ISO with offset (`2026-04-14T18:00:00+02:00`). "Z" for UTC.
166- **Meet links**: `+insert` does NOT add conferencing — use raw `events.insert` with `conferenceDataVersion=1` and `conferenceData.createRequest`.
167- **Pagination**: `--page-all` emits NDJSON (one JSON object per page). `--page-limit N` caps pages.
168- **Schema discovery**: `gws schema <service>.<resource>.<method>` — e.g. `gws schema gmail.users.messages.list`.
169- **Filters**: `gmail.settings.basic` scope required — special manual OAuth flow (see `references/api_reference.md`).
170- **Write confirmation**: Always confirm with user before `+send`, `+insert`, `+email-to-task`, `+file-announce`, `drive files delete`, `events delete`, `messages trash`.
171- **Format choice**: `--format table` for human-readable summaries; default `json` for scripting/piping to `jq`.
172
173## OAuth Setup
174
175- GCP project: `n8n-automations-454016`
176- Credentials: `~/.config/gws/credentials.json`
177- Configured scopes: `gmail.modify`, `gmail.settings.basic`, `drive`, `spreadsheets`, `tasks`, `calendar`, `documents`, `chat.messages`, `contacts.readonly`
178- `gmail.settings.basic` scope needs manual OAuth (Python localhost listener on port 8085) — `gws auth login --scopes` cannot request it directly.
179
180## Full API Reference
181
182For full command inventory, all raw API calls, pagination, labels, drafts, filters, and admin APIs, see `references/api_reference.md`.