openclaw/skills/gws-calendar/SKILL.md
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.
npx skillsauth add Dbochman/dotfiles gws-calendarInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Access Google Calendar via the gws CLI at /opt/homebrew/bin/gws. Credentials are AES-256-GCM encrypted at ~/.config/gws/.
| Account | Owner | Flag |
|---------|-------|------|
| [email protected] | Dylan | Default (no flag needed) |
| [email protected] | Julia | --account [email protected] |
| [email protected] | Dylan (spam) | --account [email protected] |
| [email protected] | OpenClaw | --account [email protected] |
When Dylan asks about "my calendar", use default. When he says "Julia's calendar", use her account.
All commands follow: gws calendar <resource> <method> [--params '<JSON>'] [--json '<JSON>'] [--account <email>]
--params = URL/query parameters (calendarId, timeMin, maxResults, etc.)--json = request body (for create/update)--account = target account (omit for Dylan)gws calendar calendarList list
# Today's 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"
}'
# Next 7 days
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"
}'
# Julia's events today
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"
}' --account [email protected]
# All calendars (use calendarList first, then query each)
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).
gws calendar events get --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}'
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"
}'
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": "[email protected]"}
]
}'
gws calendar events insert --params '{"calendarId": "primary"}' --json '{
"summary": "Vacation",
"start": {"date": "2026-03-15"},
"end": {"date": "2026-03-16"}
}'
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"]
}'
| 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 |
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": "[email protected]"}],
"conferenceData": {
"createRequest": {"requestId": "meet-1", "conferenceSolutionKey": {"type": "hangoutsMeet"}}
}
}'
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.
gws calendar events delete --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}'
gws calendar freebusy query --json '{
"timeMin": "2026-03-10T00:00:00-05:00",
"timeMax": "2026-03-10T23:59:59-05:00",
"items": [
{"id": "[email protected]"},
{"id": "[email protected]"}
]
}'
First get the event, then patch the attendee status:
# Get the event to find your attendee entry
gws calendar events get --params '{"calendarId": "primary", "eventId": "<eventId>"}'
# Accept/decline by updating the event
gws calendar events patch --params '{
"calendarId": "primary",
"eventId": "<eventId>"
}' --json '{
"attendees": [{"email": "[email protected]", "responseStatus": "accepted"}]
}'
For any command, check available parameters:
gws schema calendar.events.list
gws schema calendar.events.insert
primary = default calendar for the account2026-03-10T09:00:00-05:00)singleEvents: true + orderBy: startTime when listing to expand recurring eventsrecurrence array with RRULE_ suffix) for single-instance changesgws outputs JSON by default — pipe through jq or parse directlydevelopment
Search the web for current information, news, facts, and answers. Use when asked questions about current events, needing to look something up, finding websites, researching topics, or when you need up-to-date information beyond your training data.
development
Summarize any URL, YouTube video, podcast, PDF, or file into concise text. Use when asked to read an article, summarize a link, get the gist of a video or podcast, extract content from a URL, or when you need to understand what a web page or document contains.
development
Play music via Spotify and control Google Home speakers. Use when asked to play music, songs, artists, playlists, podcasts, or control speakers/volume/audio.
testing
Create new OpenClaw skills, modify and improve existing skills, and measure skill performance with evals. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy. Also use when asked to "make a skill", "turn this into a skill", "improve this skill", or "test this skill".