| name | gws-calendar |
| description | View, create, and manage Google Calendar events for Dylan, Julia, or other accounts. Use when asked about schedule, appointments, meetings, calendar, what's coming up, free time, conflicts, or availability. |
| allowed-tools | Bash(calendar:*) |
| metadata | {"openclaw":{"emoji":"📅","requires":{"bins":["gws"]}}} |
Google Calendar (gws)
Access Google Calendar via the gws CLI at /opt/homebrew/bin/gws. Credentials are AES-256-GCM encrypted at ~/.config/gws/.
Read references/gws-cli.md before selecting an account, changing authentication, or executing a write.
Accounts
| Account | Owner | Service-command selection |
|---|
| ${DYLAN_EMAIL} | Dylan | GOOGLE_WORKSPACE_CLI_ACCOUNT=${DYLAN_EMAIL} |
| ${JULIA_EMAIL} | Julia | GOOGLE_WORKSPACE_CLI_ACCOUNT=${JULIA_EMAIL} |
| ${STARMARKET_GMAIL} | Dylan (spam) | GOOGLE_WORKSPACE_CLI_ACCOUNT=${STARMARKET_GMAIL} |
| ${OPENCLAW_EMAIL} | OpenClaw | GOOGLE_WORKSPACE_CLI_ACCOUNT=${OPENCLAW_EMAIL} |
When Dylan asks about "my calendar", use default. When he says "Julia's calendar", use her account.
Command Pattern
All raw API commands follow: GOOGLE_WORKSPACE_CLI_ACCOUNT=<email> gws calendar <resource> <method> [--params '<JSON>'] [--json '<JSON>']
--params = URL/query parameters (calendarId, timeMin, maxResults, etc.)
--json = request body (for create/update)
- Omit the environment prefix for Dylan's default account.
List Calendars
gws calendar calendarList list
List Events
gws calendar events list --params '{
"calendarId": "primary",
"timeMin": "2026-03-05T00:00:00-05:00",
"timeMax": "2026-03-06T00:00:00-05:00",
"singleEvents": true,
"orderBy": "startTime"
}'
gws calendar events list --params '{
"calendarId": "primary",
"timeMin": "2026-03-05T00:00:00-05:00",
"timeMax": "2026-03-12T00:00:00-05:00",
"singleEvents": true,
"orderBy": "startTime"
}'
GOOGLE_WORKSPACE_CLI_ACCOUNT=${JULIA_EMAIL} gws calendar events list --params '{
"calendarId": "primary",
"timeMin": "2026-03-05T00:00:00-05:00",
"timeMax": "2026-03-06T00:00:00-05:00",
"singleEvents": true,
"orderBy": "startTime"
}'
gws calendar events list --params '{
"calendarId": "<calendarId>",
"timeMin": "...",
"timeMax": "...",
"singleEvents": true,
"orderBy": "startTime"
}'
Important: Always compute timeMin/timeMax as RFC3339 timestamps with timezone. Use America/New_York (-05:00 EST / -04:00 EDT).
Get a Single Event
gws calendar events get --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}'
Search Events
Use the q parameter:
gws calendar events list --params '{
"calendarId": "primary",
"q": "dinner",
"timeMin": "2026-03-01T00:00:00-05:00",
"timeMax": "2026-03-31T00:00:00-05:00",
"singleEvents": true,
"orderBy": "startTime"
}'
Create an Event
gws calendar events insert --params '{"calendarId": "primary"}' --json '{
"summary": "Team Standup",
"description": "Daily sync",
"location": "Zoom",
"start": {"dateTime": "2026-03-10T09:00:00-05:00", "timeZone": "America/New_York"},
"end": {"dateTime": "2026-03-10T09:30:00-05:00", "timeZone": "America/New_York"},
"attendees": [
{"email": "person@example.com"}
]
}'
All-day event
gws calendar events insert --params '{"calendarId": "primary"}' --json '{
"summary": "Vacation",
"start": {"date": "2026-03-15"},
"end": {"date": "2026-03-16"}
}'
Recurring event
gws calendar events insert --params '{"calendarId": "primary"}' --json '{
"summary": "Weekly Standup",
"start": {"dateTime": "2026-03-10T09:00:00-05:00", "timeZone": "America/New_York"},
"end": {"dateTime": "2026-03-10T09:15:00-05:00", "timeZone": "America/New_York"},
"recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"]
}'
Common RRULE patterns
| Pattern | RRULE |
|---|
| Every Monday | RRULE:FREQ=WEEKLY;BYDAY=MO |
| Every weekday | RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR |
| Biweekly Tuesday | RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU |
| Daily | RRULE:FREQ=DAILY |
| 1st of every month | RRULE:FREQ=MONTHLY;BYMONTHDAY=1 |
| First Friday of every month | RRULE:FREQ=MONTHLY;BYDAY=1FR |
| Weekly until end of year | RRULE:FREQ=WEEKLY;BYDAY=WE;UNTIL=20261231T235959Z |
With Google Meet
gws calendar events insert --params '{"calendarId": "primary", "conferenceDataVersion": 1}' --json '{
"summary": "1:1 with Alice",
"start": {"dateTime": "2026-03-10T14:00:00-05:00", "timeZone": "America/New_York"},
"end": {"dateTime": "2026-03-10T14:30:00-05:00", "timeZone": "America/New_York"},
"attendees": [{"email": "attendee@example.com"}],
"conferenceData": {
"createRequest": {"requestId": "meet-1", "conferenceSolutionKey": {"type": "hangoutsMeet"}}
}
}'
Update an Event
gws calendar events patch --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}' --json '{
"summary": "New Title",
"start": {"dateTime": "2026-03-10T10:00:00-05:00", "timeZone": "America/New_York"},
"end": {"dateTime": "2026-03-10T10:30:00-05:00", "timeZone": "America/New_York"}
}'
Use patch (not update) to only change specified fields.
Delete an Event
gws calendar events delete --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}'
Check Free/Busy
gws calendar freebusy query --json '{
"timeMin": "2026-03-10T00:00:00-05:00",
"timeMax": "2026-03-10T23:59:59-05:00",
"items": [
{"id": "${DYLAN_EMAIL}"},
{"id": "${JULIA_EMAIL}"}
]
}'
Respond to an Invitation
First get the event, then patch the attendee status:
gws calendar events get --params '{"calendarId": "primary", "eventId": "<eventId>"}'
gws calendar events patch --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}' --json '{
"attendees": [{"email": "${DYLAN_EMAIL}", "responseStatus": "accepted"}]
}'
API Schema
For any command, check available parameters:
gws schema calendar.events.list
gws schema calendar.events.insert
Notes
- Default account: ${DYLAN_EMAIL}
- Always confirm with Dylan before creating, updating, or deleting events
- When creating events on Julia's calendar, double-confirm since it affects her schedule
- Calendar ID
primary = default calendar for the account
- Times must be RFC3339 with timezone (e.g.,
2026-03-10T09:00:00-05:00)
- Use
singleEvents: true + orderBy: startTime when listing to expand recurring events
- When the user says "weekly", "recurring", etc. -> use
recurrence array with RRULE
- Always confirm recurrence pattern before creating
- For recurring event modifications, use the instance eventId (contains
_ suffix) for single-instance changes
gws outputs JSON by default — pipe through jq or parse directly