diff --git a/skills/gws/SKILL.md b/skills/gws/SKILL.md new file mode 100644 index 00000000..7d99c9b4 --- /dev/null +++ b/skills/gws/SKILL.md @@ -0,0 +1,89 @@ +--- +name: using-gws +description: >- + Interacts with Google Workspace via the gws CLI for Calendar, Gmail, Drive, + Sheets, and Docs. Checks calendars, triages email, searches Drive, reads + spreadsheets, and runs cross-service workflows like morning briefings and + meeting prep. Triggers on any mention of calendar, meetings, schedule, email, + inbox, unread mail, Google Drive, spreadsheets, documents, tasks, or requests + like "what's my day look like" and "morning briefing" — even without + explicitly mentioning Google. +user-invocable: true +metadata: + hybridclaw: + tags: + - google + - workspace + - calendar + - gmail + - drive + - sheets + - docs + - tasks + related_skills: + - google-workspace + install: + - kind: npm + package: "@googleworkspace/cli" + bins: + - gws +--- + +# Google Workspace via gws CLI + +## Step 1: Check auth before anything else + +Run `gws auth status` (no API call, instant) and parse the JSON output. +If `auth_method` is `"none"`, tell the user: + +> Run `gws auth login` in your terminal to connect your Google account. + +That's it. Don't explain OAuth, GCP projects, scopes, or alternatives. +The default login flow works for both personal Gmail and Workspace accounts. + +## Step 2: Act immediately + +Do not ask clarifying questions. Run the command with sensible defaults: + +- Calendar → `primary` calendar, user's timezone +- Gmail → `userId: me`, unread inbox +- Drive → search by name keywords the user mentioned +- Sheets → search Drive first if user gave a name, not an ID + +Only ask for clarification when there are genuinely ambiguous results (e.g., +multiple spreadsheets matching a search). + +## Step 3: Pick the right commands + +**Calendar**: See [references/calendar.md](references/calendar.md) +**Gmail**: See [references/gmail.md](references/gmail.md) +**Drive & Sheets & Docs**: See [references/drive-docs-sheets.md](references/drive-docs-sheets.md) +**Cross-service workflows**: See [references/workflows.md](references/workflows.md) + +For any service not covered above, use `gws --help` to discover +available resources and methods. The raw syntax is: + +``` +gws --params '{"key": "val"}' --json '{"body": "data"}' +``` + +## Confirmation rules + +Confirm before actions that **affect other people**: +- Sending email +- Inviting attendees to events +- Sharing files or folders + +Do **not** confirm for actions that only affect the user: +- Blocking time on their own calendar +- Creating personal reminders or tasks +- Creating a private document or spreadsheet + +The reason: asking "are you sure you want to block 2-4pm?" when the user +just told you to block 2-4pm is friction, not safety. + +## Presenting results + +Format JSON output into readable summaries. Group calendar events by day. +Show email as sender + subject + snippet. Render sheets data as Markdown +tables. Never dump raw JSON unless the user asks for it. diff --git a/skills/gws/references/calendar.md b/skills/gws/references/calendar.md new file mode 100644 index 00000000..3400decf --- /dev/null +++ b/skills/gws/references/calendar.md @@ -0,0 +1,41 @@ +# Calendar Commands + +## Helper commands (prefer these) + +```bash +gws calendar +agenda --today +gws calendar +agenda --tomorrow +gws calendar +agenda --week +gws calendar +agenda --days 7 +gws calendar +agenda --week --calendar "Work" + +gws calendar +insert \ + --summary "Team standup" \ + --start "2026-03-25T10:00:00" \ + --end "2026-03-25T10:30:00" \ + --location "Room 3A" \ + --attendee alice@example.com \ + --meet + +gws calendar events quickAdd \ + --params '{"calendarId": "primary", "text": "Lunch with Alice tomorrow at noon"}' +``` + +## Common raw commands + +```bash +# Free/busy check +gws calendar freebusy query \ + --json '{"timeMin": "2026-03-25T00:00:00Z", "timeMax": "2026-03-26T00:00:00Z", "items": [{"id": "primary"}]}' + +# List all calendars +gws calendar calendarList list + +# Delete an event +gws calendar events delete --params '{"calendarId": "primary", "eventId": "EVENT_ID"}' + +# Update an event (patch) +gws calendar events patch \ + --params '{"calendarId": "primary", "eventId": "EVENT_ID"}' \ + --json '{"summary": "Updated title"}' +``` diff --git a/skills/gws/references/drive-docs-sheets.md b/skills/gws/references/drive-docs-sheets.md new file mode 100644 index 00000000..e9721ac0 --- /dev/null +++ b/skills/gws/references/drive-docs-sheets.md @@ -0,0 +1,57 @@ +# Drive, Docs & Sheets Commands + +## Drive + +```bash +# Search for files by name +gws drive files list --params '{"q": "name contains '\''budget'\''", "pageSize": 10}' + +# Search for spreadsheets specifically +gws drive files list --params '{"q": "mimeType='\''application/vnd.google-apps.spreadsheet'\'' and name contains '\''Q1'\''", "pageSize": 10}' + +# List recent files +gws drive files list --params '{"pageSize": 10, "orderBy": "modifiedTime desc"}' + +# Upload a file +gws drive +upload ./report.pdf --name "Q1 Report" + +# Download a file +gws drive files get --params '{"fileId": "FILE_ID", "alt": "media"}' -o ./file.pdf + +# Export Google Doc as PDF +gws drive files export --params '{"fileId": "DOC_ID", "mimeType": "application/pdf"}' -o ./doc.pdf + +# Create a folder +gws drive files create --json '{"name": "Project Files", "mimeType": "application/vnd.google-apps.folder"}' +``` + +## Sheets + +```bash +# Read a range +gws sheets +read --spreadsheet "SPREADSHEET_ID" --range "Sheet1!A1:D10" + +# Append rows +gws sheets +append \ + --spreadsheet "SPREADSHEET_ID" \ + --json-values '[["Name", "Score"], ["Alice", 95]]' + +# Create a new spreadsheet +gws sheets spreadsheets create --json '{"properties": {"title": "Budget Tracker"}}' + +# Get spreadsheet metadata +gws sheets spreadsheets get --params '{"spreadsheetId": "ID"}' +``` + +## Docs + +```bash +# Create a document +gws docs documents create --json '{"title": "Meeting Notes"}' + +# Read a document +gws docs documents get --params '{"documentId": "DOC_ID"}' + +# Append text +gws docs +write --document "DOC_ID" --text "New section content here" +``` diff --git a/skills/gws/references/gmail.md b/skills/gws/references/gmail.md new file mode 100644 index 00000000..0cbb0ad6 --- /dev/null +++ b/skills/gws/references/gmail.md @@ -0,0 +1,37 @@ +# Gmail Commands + +## Helper commands (prefer these) + +```bash +gws gmail +triage +gws gmail +triage --max 5 +gws gmail +triage --query "from:boss subject:urgent" + +gws gmail +read --id MESSAGE_ID + +gws gmail +send \ + --to recipient@example.com \ + --subject "Meeting notes" \ + --body "Here are the notes..." \ + --attach ./notes.pdf + +gws gmail +reply --message-id MSG_ID --body "Thanks, sounds good." +gws gmail +reply-all --message-id MSG_ID --body "Agreed." +gws gmail +forward --message-id MSG_ID --to someone@example.com +``` + +## Common raw commands + +```bash +# Search messages +gws gmail users messages list --params '{"userId": "me", "q": "from:sarah subject:contract", "maxResults": 10}' + +# Get full message +gws gmail users messages get --params '{"userId": "me", "id": "MESSAGE_ID"}' + +# List labels +gws gmail users labels list --params '{"userId": "me"}' + +# List threads +gws gmail users threads list --params '{"userId": "me", "maxResults": 5}' +``` diff --git a/skills/gws/references/workflows.md b/skills/gws/references/workflows.md new file mode 100644 index 00000000..fa039fc8 --- /dev/null +++ b/skills/gws/references/workflows.md @@ -0,0 +1,39 @@ +# Cross-Service Workflows + +## Built-in workflows + +```bash +# Morning briefing: today's meetings + open tasks +gws workflow +standup-report + +# Prep for next meeting: agenda, attendees, linked docs +gws workflow +meeting-prep + +# Weekly overview: meetings + unread counts +gws workflow +weekly-digest + +# Convert email to task +gws workflow +email-to-task + +# Announce a file in Chat +gws workflow +file-announce +``` + +## Manual multi-step patterns + +When a built-in workflow doesn't fit, chain commands. Examples: + +**"Check email then schedule with important senders":** +1. `gws gmail +triage` → get unread emails +2. Pick the important senders from the results +3. `gws calendar +insert --summary "..." --attendee sender@...` → create event (confirm with user first since it involves attendees) + +**"Find a spreadsheet and extract data":** +1. `gws drive files list --params '{"q": "name contains '\''sales'\''..."}'` → find the file +2. `gws sheets +read --spreadsheet "ID" --range "Sheet1!A1:Z100"` → read the data +3. Present the relevant numbers to the user + +**"Block time and reschedule a conflict":** +1. `gws calendar +agenda --today` → find existing events +2. `gws calendar +insert --summary "Deep Work" --start ... --end ...` → create the block (no confirmation needed for personal blocks) +3. `gws calendar events patch --params '{"calendarId": "primary", "eventId": "..."}' --json '{"start": ..., "end": ...}'` → move the conflicting event