diff --git a/.changeset/migrate-yaml-to-toml.md b/.changeset/migrate-yaml-to-toml.md new file mode 100644 index 00000000..96ede8bb --- /dev/null +++ b/.changeset/migrate-yaml-to-toml.md @@ -0,0 +1,5 @@ +--- +"@googleworkspace/cli": patch +--- + +Migrated the internal AI skills registry (personas and recipes) from YAML to TOML. This allows us to drop the unmaintained serde_yaml dependency, improving the project's supply chain security posture. diff --git a/Cargo.lock b/Cargo.lock index 4450ddd2..f040a8d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -939,13 +939,13 @@ dependencies = [ "reqwest", "serde", "serde_json", - "serde_yaml", "serial_test", "sha2", "tempfile", "thiserror 2.0.18", "tokio", "tokio-util", + "toml", "tracing", "tracing-appender", "tracing-subscriber", @@ -2403,28 +2403,24 @@ dependencies = [ ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "serde_spanned" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", "serde", ] [[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "indexmap", + "form_urlencoded", "itoa", "ryu", "serde", - "unsafe-libyaml", ] [[package]] @@ -2865,6 +2861,47 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" version = "0.5.3" @@ -3065,12 +3102,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "untrusted" version = "0.9.0" @@ -3665,6 +3696,15 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/crates/google-workspace-cli/Cargo.toml b/crates/google-workspace-cli/Cargo.toml index f1564603..1c5a6f79 100644 --- a/crates/google-workspace-cli/Cargo.toml +++ b/crates/google-workspace-cli/Cargo.toml @@ -58,7 +58,7 @@ chrono-tz = "0.10" iana-time-zone = "0.1" mail-builder = "0.4" async-trait = "0.1.89" -serde_yaml = "0.9.34" +toml = "0.8" percent-encoding = "2.3.2" zeroize = { version = "1.8.2", features = ["derive"] } tracing = "0.1" diff --git a/crates/google-workspace-cli/registry/personas.toml b/crates/google-workspace-cli/registry/personas.toml new file mode 100644 index 00000000..5912bead --- /dev/null +++ b/crates/google-workspace-cli/registry/personas.toml @@ -0,0 +1,190 @@ +[[personas]] +name = "exec-assistant" +title = "Executive Assistant" +description = "Manage an executive's schedule, inbox, and communications." +services = [ "gmail", "calendar", "drive", "chat" ] +workflows = [ "+standup-report", "+meeting-prep", "+weekly-digest" ] +instructions = [ + "Start each day with `gws workflow +standup-report` to get the executive's agenda and open tasks.", + "Before each meeting, run `gws workflow +meeting-prep` to see attendees, description, and linked docs.", + "Triage the inbox with `gws gmail +triage --max 10` — prioritize emails from direct reports and leadership.", + "Schedule meetings with `gws calendar +insert` — always check for conflicts first using `gws calendar +agenda`.", + "Draft replies with `gws gmail +send` — keep tone professional and concise." +] +tips = [ + "Always confirm calendar changes with the executive before committing.", + "Use `--format table` for quick visual scans of agenda and triage output.", + "Check `gws calendar +agenda --week` on Monday mornings for weekly planning." +] + +[[personas]] +name = "project-manager" +title = "Project Manager" +description = "Coordinate projects — track tasks, schedule meetings, and share docs." +services = [ "drive", "sheets", "calendar", "gmail", "chat" ] +workflows = [ "+standup-report", "+weekly-digest", "+file-announce" ] +instructions = [ + "Start the week with `gws workflow +weekly-digest` for a snapshot of upcoming meetings and unread items.", + "Track project status in Sheets using `gws sheets +append` to log updates.", + "Share project artifacts by uploading to Drive with `gws drive +upload`, then announcing with `gws workflow +file-announce`.", + "Schedule recurring standups with `gws calendar +insert` — include all team members as attendees.", + "Send status update emails to stakeholders with `gws gmail +send`." +] +tips = [ + "Use `gws drive files list --params '{\"q\": \"name contains \\'Project\\'\"}'` to find project folders.", + "Pipe triage output through `jq` for filtering by sender or subject.", + "Use `--dry-run` before any write operations to preview what will happen." +] + +[[personas]] +name = "hr-coordinator" +title = "HR Coordinator" +description = "Handle HR workflows — onboarding, announcements, and employee comms." +services = [ "gmail", "calendar", "drive", "chat" ] +workflows = [ "+email-to-task", "+file-announce" ] +instructions = [ + "For new hire onboarding, create calendar events for orientation sessions with `gws calendar +insert`.", + "Upload onboarding docs to a shared Drive folder with `gws drive +upload`.", + "Announce new hires in Chat spaces with `gws workflow +file-announce` to share their profile doc.", + "Convert email requests into tracked tasks with `gws workflow +email-to-task`.", + "Send bulk announcements with `gws gmail +send` — use clear subject lines." +] +tips = [ + "Always use `--sanitize` for PII-sensitive operations.", + "Create a dedicated 'HR Onboarding' calendar for tracking orientation schedules." +] + +[[personas]] +name = "sales-ops" +title = "Sales Operations" +description = "Manage sales workflows — track deals, schedule calls, client comms." +services = [ "gmail", "calendar", "sheets", "drive" ] +workflows = [ "+meeting-prep", "+email-to-task", "+weekly-digest" ] +instructions = [ + "Prepare for client calls with `gws workflow +meeting-prep` to review attendees and agenda.", + "Log deal updates in a tracking spreadsheet with `gws sheets +append`.", + "Convert follow-up emails into tasks with `gws workflow +email-to-task`.", + "Share proposals by uploading to Drive with `gws drive +upload`.", + "Get a weekly sales pipeline summary with `gws workflow +weekly-digest`." +] +tips = [ + "Use `gws gmail +triage --query 'from:client-domain.com'` to filter client emails.", + "Schedule follow-up calls immediately after meetings to maintain momentum.", + "Keep all client-facing documents in a dedicated shared Drive folder." +] + +[[personas]] +name = "it-admin" +title = "IT Administrator" +description = "Administer IT — monitor security and configure Workspace." +services = [ "gmail", "drive", "calendar" ] +workflows = [ "+standup-report" ] +instructions = [ + "Start the day with `gws workflow +standup-report` to review any pending IT requests.", + "Monitor suspicious login activity and review audit logs.", + "Configure Drive sharing policies to enforce organizational security." +] +tips = [ + "Always use `--dry-run` before bulk operations.", + "Review `gws auth status` regularly to verify service account permissions." +] + +[[personas]] +name = "content-creator" +title = "Content Creator" +description = "Create, organize, and distribute content across Workspace." +services = [ "docs", "drive", "gmail", "chat", "slides" ] +workflows = [ "+file-announce" ] +instructions = [ + "Draft content in Google Docs with `gws docs +write`.", + "Organize content assets in Drive folders — use `gws drive files list` to browse.", + "Share finished content by announcing in Chat with `gws workflow +file-announce`.", + "Send content review requests via email with `gws gmail +send`.", + "Upload media assets to Drive with `gws drive +upload`." +] +tips = [ + "Use `gws docs +write` for quick content updates — it handles the Docs API formatting.", + "Keep a 'Content Calendar' in a shared Sheet for tracking publication schedules.", + "Use `--format yaml` for human-readable output when debugging API responses." +] + +[[personas]] +name = "customer-support" +title = "Customer Support Agent" +description = "Manage customer support — track tickets, respond, escalate issues." +services = [ "gmail", "sheets", "chat", "calendar" ] +workflows = [ "+email-to-task", "+standup-report" ] +instructions = [ + "Triage the support inbox with `gws gmail +triage --query 'label:support'`.", + "Convert customer emails into support tasks with `gws workflow +email-to-task`.", + "Log ticket status updates in a tracking sheet with `gws sheets +append`.", + "Escalate urgent issues to the team Chat space.", + "Schedule follow-up calls with customers using `gws calendar +insert`." +] +tips = [ + "Use `gws gmail +triage --labels` to see email categories at a glance.", + "Set up Gmail filters for auto-labeling support requests.", + "Use `--format table` for quick status dashboard views." +] + +[[personas]] +name = "event-coordinator" +title = "Event Coordinator" +description = "Plan and manage events — scheduling, invitations, and logistics." +services = [ "calendar", "gmail", "drive", "chat", "sheets" ] +workflows = [ "+meeting-prep", "+file-announce", "+weekly-digest" ] +instructions = [ + "Create event calendar entries with `gws calendar +insert` — include location and attendee lists.", + "Prepare event materials and upload to Drive with `gws drive +upload`.", + "Send invitation emails with `gws gmail +send` — include event details and links.", + "Announce updates in Chat spaces with `gws workflow +file-announce`.", + "Track RSVPs and logistics in Sheets with `gws sheets +append`." +] +tips = [ + "Use `gws calendar +agenda --days 30` for long-range event planning.", + "Create a dedicated calendar for each major event series.", + "Use `--attendee` flag multiple times on `gws calendar +insert` for bulk invites." +] + +[[personas]] +name = "team-lead" +title = "Team Lead" +description = "Lead a team — run standups, coordinate tasks, and communicate." +services = [ "calendar", "gmail", "chat", "drive", "sheets" ] +workflows = [ + "+standup-report", + "+meeting-prep", + "+weekly-digest", + "+email-to-task" +] +instructions = [ + "Run daily standups with `gws workflow +standup-report` — share output in team Chat.", + "Prepare for 1:1s with `gws workflow +meeting-prep`.", + "Get weekly snapshots with `gws workflow +weekly-digest`.", + "Delegate email action items with `gws workflow +email-to-task`.", + "Track team OKRs in a shared Sheet with `gws sheets +append`." +] +tips = [ + "Use `gws calendar +agenda --week --format table` for weekly team calendar views.", + "Pipe standup reports to Chat with `gws chat spaces messages create`.", + "Use `--sanitize` for any operations involving sensitive team data." +] + +[[personas]] +name = "researcher" +title = "Researcher" +description = "Organize research — manage references, notes, and collaboration." +services = [ "drive", "docs", "sheets", "gmail" ] +workflows = [ "+file-announce" ] +instructions = [ + "Organize research papers and notes in Drive folders.", + "Write research notes and summaries with `gws docs +write`.", + "Track research data in Sheets — use `gws sheets +append` for data logging.", + "Share findings with collaborators via `gws workflow +file-announce`.", + "Request peer reviews via `gws gmail +send`." +] +tips = [ + "Use `gws drive files list` with search queries to find specific documents.", + "Keep a running log of experiments and findings in a shared Sheet.", + "Use `--format csv` when exporting data for analysis tools." +] diff --git a/crates/google-workspace-cli/registry/personas.yaml b/crates/google-workspace-cli/registry/personas.yaml deleted file mode 100644 index 2aac86af..00000000 --- a/crates/google-workspace-cli/registry/personas.yaml +++ /dev/null @@ -1,167 +0,0 @@ -# Persona Packs — Role-based skill bundles for AI agents -# -# Each persona defines a role-based context with: -# - name: unique id (used as directory name: persona-{name}) -# - title: human-readable name -# - description: when to use this persona -# - services: which gws services this persona commonly uses -# - workflows: which workflow commands are relevant -# - instructions: step-by-step guidance for agents adopting this role -# - tips: useful reminders - -personas: - - name: exec-assistant - title: Executive Assistant - description: "Manage an executive's schedule, inbox, and communications." - services: [gmail, calendar, drive, chat] - workflows: ["+standup-report", "+meeting-prep", "+weekly-digest"] - instructions: - - "Start each day with `gws workflow +standup-report` to get the executive's agenda and open tasks." - - "Before each meeting, run `gws workflow +meeting-prep` to see attendees, description, and linked docs." - - "Triage the inbox with `gws gmail +triage --max 10` — prioritize emails from direct reports and leadership." - - "Schedule meetings with `gws calendar +insert` — always check for conflicts first using `gws calendar +agenda`." - - "Draft replies with `gws gmail +send` — keep tone professional and concise." - tips: - - "Always confirm calendar changes with the executive before committing." - - "Use `--format table` for quick visual scans of agenda and triage output." - - "Check `gws calendar +agenda --week` on Monday mornings for weekly planning." - - - name: project-manager - title: Project Manager - description: "Coordinate projects — track tasks, schedule meetings, and share docs." - services: [drive, sheets, calendar, gmail, chat] - workflows: ["+standup-report", "+weekly-digest", "+file-announce"] - instructions: - - "Start the week with `gws workflow +weekly-digest` for a snapshot of upcoming meetings and unread items." - - "Track project status in Sheets using `gws sheets +append` to log updates." - - "Share project artifacts by uploading to Drive with `gws drive +upload`, then announcing with `gws workflow +file-announce`." - - "Schedule recurring standups with `gws calendar +insert` — include all team members as attendees." - - "Send status update emails to stakeholders with `gws gmail +send`." - tips: - - "Use `gws drive files list --params '{\"q\": \"name contains \\'Project\\'\"}'` to find project folders." - - "Pipe triage output through `jq` for filtering by sender or subject." - - "Use `--dry-run` before any write operations to preview what will happen." - - - name: hr-coordinator - title: HR Coordinator - description: "Handle HR workflows — onboarding, announcements, and employee comms." - services: [gmail, calendar, drive, chat] - workflows: ["+email-to-task", "+file-announce"] - instructions: - - "For new hire onboarding, create calendar events for orientation sessions with `gws calendar +insert`." - - "Upload onboarding docs to a shared Drive folder with `gws drive +upload`." - - "Announce new hires in Chat spaces with `gws workflow +file-announce` to share their profile doc." - - "Convert email requests into tracked tasks with `gws workflow +email-to-task`." - - "Send bulk announcements with `gws gmail +send` — use clear subject lines." - tips: - - "Always use `--sanitize` for PII-sensitive operations." - - "Create a dedicated 'HR Onboarding' calendar for tracking orientation schedules." - - - name: sales-ops - title: Sales Operations - description: "Manage sales workflows — track deals, schedule calls, client comms." - services: [gmail, calendar, sheets, drive] - workflows: ["+meeting-prep", "+email-to-task", "+weekly-digest"] - instructions: - - "Prepare for client calls with `gws workflow +meeting-prep` to review attendees and agenda." - - "Log deal updates in a tracking spreadsheet with `gws sheets +append`." - - "Convert follow-up emails into tasks with `gws workflow +email-to-task`." - - "Share proposals by uploading to Drive with `gws drive +upload`." - - "Get a weekly sales pipeline summary with `gws workflow +weekly-digest`." - tips: - - "Use `gws gmail +triage --query 'from:client-domain.com'` to filter client emails." - - "Schedule follow-up calls immediately after meetings to maintain momentum." - - "Keep all client-facing documents in a dedicated shared Drive folder." - - - name: it-admin - title: IT Administrator - description: "Administer IT — monitor security and configure Workspace." - services: [gmail, drive, calendar] - workflows: ["+standup-report"] - instructions: - - "Start the day with `gws workflow +standup-report` to review any pending IT requests." - - "Monitor suspicious login activity and review audit logs." - - "Configure Drive sharing policies to enforce organizational security." - tips: - - "Always use `--dry-run` before bulk operations." - - "Review `gws auth status` regularly to verify service account permissions." - - - name: content-creator - title: Content Creator - description: "Create, organize, and distribute content across Workspace." - services: [docs, drive, gmail, chat, slides] - workflows: ["+file-announce"] - instructions: - - "Draft content in Google Docs with `gws docs +write`." - - "Organize content assets in Drive folders — use `gws drive files list` to browse." - - "Share finished content by announcing in Chat with `gws workflow +file-announce`." - - "Send content review requests via email with `gws gmail +send`." - - "Upload media assets to Drive with `gws drive +upload`." - tips: - - "Use `gws docs +write` for quick content updates — it handles the Docs API formatting." - - "Keep a 'Content Calendar' in a shared Sheet for tracking publication schedules." - - "Use `--format yaml` for human-readable output when debugging API responses." - - - name: customer-support - title: Customer Support Agent - description: "Manage customer support — track tickets, respond, escalate issues." - services: [gmail, sheets, chat, calendar] - workflows: ["+email-to-task", "+standup-report"] - instructions: - - "Triage the support inbox with `gws gmail +triage --query 'label:support'`." - - "Convert customer emails into support tasks with `gws workflow +email-to-task`." - - "Log ticket status updates in a tracking sheet with `gws sheets +append`." - - "Escalate urgent issues to the team Chat space." - - "Schedule follow-up calls with customers using `gws calendar +insert`." - tips: - - "Use `gws gmail +triage --labels` to see email categories at a glance." - - "Set up Gmail filters for auto-labeling support requests." - - "Use `--format table` for quick status dashboard views." - - - name: event-coordinator - title: Event Coordinator - description: "Plan and manage events — scheduling, invitations, and logistics." - services: [calendar, gmail, drive, chat, sheets] - workflows: ["+meeting-prep", "+file-announce", "+weekly-digest"] - instructions: - - "Create event calendar entries with `gws calendar +insert` — include location and attendee lists." - - "Prepare event materials and upload to Drive with `gws drive +upload`." - - "Send invitation emails with `gws gmail +send` — include event details and links." - - "Announce updates in Chat spaces with `gws workflow +file-announce`." - - "Track RSVPs and logistics in Sheets with `gws sheets +append`." - tips: - - "Use `gws calendar +agenda --days 30` for long-range event planning." - - "Create a dedicated calendar for each major event series." - - "Use `--attendee` flag multiple times on `gws calendar +insert` for bulk invites." - - - name: team-lead - title: Team Lead - description: "Lead a team — run standups, coordinate tasks, and communicate." - services: [calendar, gmail, chat, drive, sheets] - workflows: ["+standup-report", "+meeting-prep", "+weekly-digest", "+email-to-task"] - instructions: - - "Run daily standups with `gws workflow +standup-report` — share output in team Chat." - - "Prepare for 1:1s with `gws workflow +meeting-prep`." - - "Get weekly snapshots with `gws workflow +weekly-digest`." - - "Delegate email action items with `gws workflow +email-to-task`." - - "Track team OKRs in a shared Sheet with `gws sheets +append`." - tips: - - "Use `gws calendar +agenda --week --format table` for weekly team calendar views." - - "Pipe standup reports to Chat with `gws chat spaces messages create`." - - "Use `--sanitize` for any operations involving sensitive team data." - - - name: researcher - title: Researcher - description: "Organize research — manage references, notes, and collaboration." - services: [drive, docs, sheets, gmail] - workflows: ["+file-announce"] - instructions: - - "Organize research papers and notes in Drive folders." - - "Write research notes and summaries with `gws docs +write`." - - "Track research data in Sheets — use `gws sheets +append` for data logging." - - "Share findings with collaborators via `gws workflow +file-announce`." - - "Request peer reviews via `gws gmail +send`." - tips: - - "Use `gws drive files list` with search queries to find specific documents." - - "Keep a running log of experiments and findings in a shared Sheet." - - "Use `--format csv` when exporting data for analysis tools." diff --git a/crates/google-workspace-cli/registry/recipes.toml b/crates/google-workspace-cli/registry/recipes.toml new file mode 100644 index 00000000..8440ca1b --- /dev/null +++ b/crates/google-workspace-cli/registry/recipes.toml @@ -0,0 +1,496 @@ +[[recipes]] +name = "label-and-archive-emails" +title = "Label and Archive Gmail Threads" +description = "Apply Gmail labels to matching messages and archive them to keep your inbox clean." +category = "productivity" +services = [ "gmail" ] +steps = [ + "Search for matching emails: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"from:notifications@service.com\"}' --format table`", + "Apply a label: `gws gmail users messages modify --params '{\"userId\": \"me\", \"id\": \"MESSAGE_ID\"}' --json '{\"addLabelIds\": [\"LABEL_ID\"]}'`", + "Archive (remove from inbox): `gws gmail users messages modify --params '{\"userId\": \"me\", \"id\": \"MESSAGE_ID\"}' --json '{\"removeLabelIds\": [\"INBOX\"]}'`" +] + +[[recipes]] +name = "draft-email-from-doc" +title = "Draft a Gmail Message from a Google Doc" +description = "Read content from a Google Doc and use it as the body of a Gmail message." +category = "productivity" +services = [ "docs", "gmail" ] +steps = [ + "Get the document content: `gws docs documents get --params '{\"documentId\": \"DOC_ID\"}'`", + "Copy the text from the body content", + "Send the email: `gws gmail +send --to recipient@example.com --subject 'Newsletter Update' --body 'CONTENT_FROM_DOC'`" +] + +[[recipes]] +name = "organize-drive-folder" +title = "Organize Files into Google Drive Folders" +description = "Create a Google Drive folder structure and move files into the right locations." +category = "productivity" +services = [ "drive" ] +steps = [ + "Create a project folder: `gws drive files create --json '{\"name\": \"Q2 Project\", \"mimeType\": \"application/vnd.google-apps.folder\"}'`", + "Create sub-folders: `gws drive files create --json '{\"name\": \"Documents\", \"mimeType\": \"application/vnd.google-apps.folder\", \"parents\": [\"PARENT_FOLDER_ID\"]}'`", + "Move existing files into folder: `gws drive files update --params '{\"fileId\": \"FILE_ID\", \"addParents\": \"FOLDER_ID\", \"removeParents\": \"OLD_PARENT_ID\"}'`", + "Verify structure: `gws drive files list --params '{\"q\": \"FOLDER_ID in parents\"}' --format table`" +] + +[[recipes]] +name = "share-folder-with-team" +title = "Share a Google Drive Folder with a Team" +description = "Share a Google Drive folder and all its contents with a list of collaborators." +category = "productivity" +services = [ "drive" ] +steps = [ + "Find the folder: `gws drive files list --params '{\"q\": \"name = '\\''Project X'\\'' and mimeType = '\\''application/vnd.google-apps.folder'\\''\"}'`", + "Share as editor: `gws drive permissions create --params '{\"fileId\": \"FOLDER_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"colleague@company.com\"}'`", + "Share as viewer: `gws drive permissions create --params '{\"fileId\": \"FOLDER_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"stakeholder@company.com\"}'`", + "Verify permissions: `gws drive permissions list --params '{\"fileId\": \"FOLDER_ID\"}' --format table`" +] + +[[recipes]] +name = "email-drive-link" +title = "Email a Google Drive File Link" +description = "Share a Google Drive file and email the link with a message to recipients." +category = "productivity" +services = [ "drive", "gmail" ] +steps = [ + "Find the file: `gws drive files list --params '{\"q\": \"name = '\\''Quarterly Report'\\''\"}'`", + "Share the file: `gws drive permissions create --params '{\"fileId\": \"FILE_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"client@example.com\"}'`", + "Email the link: `gws gmail +send --to client@example.com --subject 'Quarterly Report' --body 'Hi, please find the report here: https://docs.google.com/document/d/FILE_ID'`" +] + +[[recipes]] +name = "create-doc-from-template" +title = "Create a Google Doc from a Template" +description = "Copy a Google Docs template, fill in content, and share with collaborators." +category = "productivity" +services = [ "drive", "docs" ] +steps = [ + "Copy the template: `gws drive files copy --params '{\"fileId\": \"TEMPLATE_DOC_ID\"}' --json '{\"name\": \"Project Brief - Q2 Launch\"}'`", + "Get the new doc ID from the response", + "Add content: `gws docs +write --document-id NEW_DOC_ID --text '## Project: Q2 Launch\n\n### Objective\nLaunch the new feature by end of Q2.'`", + "Share with team: `gws drive permissions create --params '{\"fileId\": \"NEW_DOC_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"team@company.com\"}'`" +] + +[[recipes]] +name = "create-expense-tracker" +title = "Create a Google Sheets Expense Tracker" +description = "Set up a Google Sheets spreadsheet for tracking expenses with headers and initial entries." +category = "productivity" +services = [ "sheets", "drive" ] +steps = [ + "Create spreadsheet: `gws drive files create --json '{\"name\": \"Expense Tracker 2025\", \"mimeType\": \"application/vnd.google-apps.spreadsheet\"}'`", + "Add headers: `gws sheets +append --spreadsheet SHEET_ID --range 'Sheet1' --values '[\"Date\", \"Category\", \"Description\", \"Amount\"]'`", + "Add first entry: `gws sheets +append --spreadsheet SHEET_ID --range 'Sheet1' --values '[\"2025-01-15\", \"Travel\", \"Flight to NYC\", \"450.00\"]'`", + "Share with manager: `gws drive permissions create --params '{\"fileId\": \"SHEET_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"manager@company.com\"}'`" +] + +[[recipes]] +name = "copy-sheet-for-new-month" +title = "Copy a Google Sheet for a New Month" +description = "Duplicate a Google Sheets template tab for a new month of tracking." +category = "productivity" +services = [ "sheets" ] +steps = [ + "Get spreadsheet details: `gws sheets spreadsheets get --params '{\"spreadsheetId\": \"SHEET_ID\"}'`", + "Copy the template sheet: `gws sheets spreadsheets sheets copyTo --params '{\"spreadsheetId\": \"SHEET_ID\", \"sheetId\": 0}' --json '{\"destinationSpreadsheetId\": \"SHEET_ID\"}'`", + "Rename the new tab: `gws sheets spreadsheets batchUpdate --params '{\"spreadsheetId\": \"SHEET_ID\"}' --json '{\"requests\": [{\"updateSheetProperties\": {\"properties\": {\"sheetId\": 123, \"title\": \"February 2025\"}, \"fields\": \"title\"}}]}'`" +] + +[[recipes]] +name = "block-focus-time" +title = "Block Focus Time on Google Calendar" +description = "Create recurring focus time blocks on Google Calendar to protect deep work hours." +category = "scheduling" +services = [ "calendar" ] +steps = [ + "Create recurring focus block: `gws calendar events insert --params '{\"calendarId\": \"primary\"}' --json '{\"summary\": \"Focus Time\", \"description\": \"Protected deep work block\", \"start\": {\"dateTime\": \"2025-01-20T09:00:00\", \"timeZone\": \"America/New_York\"}, \"end\": {\"dateTime\": \"2025-01-20T11:00:00\", \"timeZone\": \"America/New_York\"}, \"recurrence\": [\"RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\"], \"transparency\": \"opaque\"}'`", + "Verify it shows as busy: `gws calendar +agenda`" +] + +[[recipes]] +name = "reschedule-meeting" +title = "Reschedule a Google Calendar Meeting" +description = "Move a Google Calendar event to a new time and automatically notify all attendees." +category = "scheduling" +services = [ "calendar" ] +steps = [ + "Find the event: `gws calendar +agenda`", + "Get event details: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`", + "Update the time: `gws calendar events patch --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\", \"sendUpdates\": \"all\"}' --json '{\"start\": {\"dateTime\": \"2025-01-22T14:00:00\", \"timeZone\": \"America/New_York\"}, \"end\": {\"dateTime\": \"2025-01-22T15:00:00\", \"timeZone\": \"America/New_York\"}}'`" +] + +[[recipes]] +name = "create-gmail-filter" +title = "Create a Gmail Filter" +description = "Create a Gmail filter to automatically label, star, or categorize incoming messages." +category = "productivity" +services = [ "gmail" ] +steps = [ + "List existing labels: `gws gmail users labels list --params '{\"userId\": \"me\"}' --format table`", + "Create a new label: `gws gmail users labels create --params '{\"userId\": \"me\"}' --json '{\"name\": \"Receipts\"}'`", + "Create a filter: `gws gmail users settings filters create --params '{\"userId\": \"me\"}' --json '{\"criteria\": {\"from\": \"receipts@example.com\"}, \"action\": {\"addLabelIds\": [\"LABEL_ID\"], \"removeLabelIds\": [\"INBOX\"]}}'`", + "Verify filter: `gws gmail users settings filters list --params '{\"userId\": \"me\"}' --format table`" +] + +[[recipes]] +name = "schedule-recurring-event" +title = "Schedule a Recurring Meeting" +description = "Create a recurring Google Calendar event with attendees." +category = "scheduling" +services = [ "calendar" ] +steps = [ + "Create recurring event: `gws calendar events insert --params '{\"calendarId\": \"primary\"}' --json '{\"summary\": \"Weekly Standup\", \"start\": {\"dateTime\": \"2024-03-18T09:00:00\", \"timeZone\": \"America/New_York\"}, \"end\": {\"dateTime\": \"2024-03-18T09:30:00\", \"timeZone\": \"America/New_York\"}, \"recurrence\": [\"RRULE:FREQ=WEEKLY;BYDAY=MO\"], \"attendees\": [{\"email\": \"team@company.com\"}]}'`", + "Verify it was created: `gws calendar +agenda --days 14 --format table`" +] + +[[recipes]] +name = "find-free-time" +title = "Find Free Time Across Calendars" +description = "Query Google Calendar free/busy status for multiple users to find a meeting slot." +category = "scheduling" +services = [ "calendar" ] +steps = [ + "Query free/busy: `gws calendar freebusy query --json '{\"timeMin\": \"2024-03-18T08:00:00Z\", \"timeMax\": \"2024-03-18T18:00:00Z\", \"items\": [{\"id\": \"user1@company.com\"}, {\"id\": \"user2@company.com\"}]}'`", + "Review the output to find overlapping free slots", + "Create event in the free slot: `gws calendar +insert --summary 'Meeting' --attendee user1@company.com --attendee user2@company.com --start '2024-03-18T14:00:00' --end '2024-03-18T14:30:00'`" +] + +[[recipes]] +name = "bulk-download-folder" +title = "Bulk Download Drive Folder" +description = "List and download all files from a Google Drive folder." +category = "productivity" +services = [ "drive" ] +steps = [ + "List files in folder: `gws drive files list --params '{\"q\": \"'\\''FOLDER_ID'\\'' in parents\"}' --format json`", + "Download each file: `gws drive files get --params '{\"fileId\": \"FILE_ID\", \"alt\": \"media\"}' -o filename.ext`", + "Export Google Docs as PDF: `gws drive files export --params '{\"fileId\": \"FILE_ID\", \"mimeType\": \"application/pdf\"}' -o document.pdf`" +] + +[[recipes]] +name = "find-large-files" +title = "Find Largest Files in Drive" +description = "Identify large Google Drive files consuming storage quota." +category = "productivity" +services = [ "drive" ] +steps = [ + "List files sorted by size: `gws drive files list --params '{\"orderBy\": \"quotaBytesUsed desc\", \"pageSize\": 20, \"fields\": \"files(id,name,size,mimeType,owners)\"}' --format table`", + "Review the output and identify files to archive or move" +] + +[[recipes]] +name = "create-shared-drive" +title = "Create and Configure a Shared Drive" +description = "Create a Google Shared Drive and add members with appropriate roles." +category = "productivity" +services = [ "drive" ] +steps = [ + "Create shared drive: `gws drive drives create --params '{\"requestId\": \"unique-id-123\"}' --json '{\"name\": \"Project X\"}'`", + "Add a member: `gws drive permissions create --params '{\"fileId\": \"DRIVE_ID\", \"supportsAllDrives\": true}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"member@company.com\"}'`", + "List members: `gws drive permissions list --params '{\"fileId\": \"DRIVE_ID\", \"supportsAllDrives\": true}'`" +] + +[[recipes]] +name = "log-deal-update" +title = "Log Deal Update to Sheet" +description = "Append a deal status update to a Google Sheets sales tracking spreadsheet." +category = "sales" +services = [ "sheets", "drive" ] +steps = [ + "Find the tracking sheet: `gws drive files list --params '{\"q\": \"name = '\\''Sales Pipeline'\\'' and mimeType = '\\''application/vnd.google-apps.spreadsheet'\\''\"}'`", + "Read current data: `gws sheets +read --spreadsheet SHEET_ID --range \"Pipeline!A1:F\"`", + "Append new row: `gws sheets +append --spreadsheet SHEET_ID --range 'Pipeline' --values '[\"2024-03-15\", \"Acme Corp\", \"Proposal Sent\", \"$50,000\", \"Q2\", \"jdoe\"]'`" +] + +[[recipes]] +name = "collect-form-responses" +title = "Check Form Responses" +description = "Retrieve and review responses from a Google Form." +category = "productivity" +services = [ "forms" ] +steps = [ + "List forms: `gws forms forms list` (if you don't have the form ID)", + "Get form details: `gws forms forms get --params '{\"formId\": \"FORM_ID\"}'`", + "Get responses: `gws forms forms responses list --params '{\"formId\": \"FORM_ID\"}' --format table`" +] + +[[recipes]] +name = "post-mortem-setup" +title = "Set Up Post-Mortem" +description = "Create a Google Docs post-mortem, schedule a Google Calendar review, and notify via Chat." +category = "engineering" +services = [ "docs", "calendar", "chat" ] +steps = [ + "Create post-mortem doc: `gws docs +write --title 'Post-Mortem: [Incident]' --body '## Summary\\n\\n## Timeline\\n\\n## Root Cause\\n\\n## Action Items'`", + "Schedule review meeting: `gws calendar +insert --summary 'Post-Mortem Review: [Incident]' --attendee team@company.com --start '2026-03-16T14:00:00' --end '2026-03-16T15:00:00'`", + "Notify in Chat: `gws chat +send --space spaces/ENG_SPACE --text '🔍 Post-mortem scheduled for [Incident].'`" +] + +[[recipes]] +name = "create-task-list" +title = "Create a Task List and Add Tasks" +description = "Set up a new Google Tasks list with initial tasks." +category = "productivity" +services = [ "tasks" ] +steps = [ + "Create task list: `gws tasks tasklists insert --json '{\"title\": \"Q2 Goals\"}'`", + "Add a task: `gws tasks tasks insert --params '{\"tasklist\": \"TASKLIST_ID\"}' --json '{\"title\": \"Review Q1 metrics\", \"notes\": \"Pull data from analytics dashboard\", \"due\": \"2024-04-01T00:00:00Z\"}'`", + "Add another task: `gws tasks tasks insert --params '{\"tasklist\": \"TASKLIST_ID\"}' --json '{\"title\": \"Draft Q2 OKRs\"}'`", + "List tasks: `gws tasks tasks list --params '{\"tasklist\": \"TASKLIST_ID\"}' --format table`" +] + +[[recipes]] +name = "review-overdue-tasks" +title = "Review Overdue Tasks" +description = "Find Google Tasks that are past due and need attention." +category = "productivity" +services = [ "tasks" ] +steps = [ + "List task lists: `gws tasks tasklists list --format table`", + "List tasks with status: `gws tasks tasks list --params '{\"tasklist\": \"TASKLIST_ID\", \"showCompleted\": false}' --format table`", + "Review due dates and prioritize overdue items" +] + +[[recipes]] +name = "watch-drive-changes" +title = "Watch for Drive Changes" +description = "Subscribe to change notifications on a Google Drive file or folder." +category = "engineering" +services = [ "events" ] +steps = [ + "Create subscription: `gws events subscriptions create --json '{\"targetResource\": \"//drive.googleapis.com/drives/DRIVE_ID\", \"eventTypes\": [\"google.workspace.drive.file.v1.updated\"], \"notificationEndpoint\": {\"pubsubTopic\": \"projects/PROJECT/topics/TOPIC\"}, \"payloadOptions\": {\"includeResource\": true}}'`", + "List active subscriptions: `gws events subscriptions list`", + "Renew before expiry: `gws events +renew --subscription SUBSCRIPTION_ID`" +] + +[[recipes]] +name = "create-classroom-course" +title = "Create a Google Classroom Course" +description = "Create a Google Classroom course and invite students." +category = "education" +services = [ "classroom" ] +steps = [ + "Create the course: `gws classroom courses create --json '{\"name\": \"Introduction to CS\", \"section\": \"Period 1\", \"room\": \"Room 101\", \"ownerId\": \"me\"}'`", + "Invite a student: `gws classroom invitations create --json '{\"courseId\": \"COURSE_ID\", \"userId\": \"student@school.edu\", \"role\": \"STUDENT\"}'`", + "List enrolled students: `gws classroom courses students list --params '{\"courseId\": \"COURSE_ID\"}' --format table`" +] + +[[recipes]] +name = "create-meet-space" +title = "Create a Google Meet Conference" +description = "Create a Google Meet meeting space and share the join link." +category = "scheduling" +services = [ "meet", "gmail" ] +steps = [ + "Create meeting space: `gws meet spaces create --json '{\"config\": {\"accessType\": \"OPEN\"}}'`", + "Copy the meeting URI from the response", + "Email the link: `gws gmail +send --to team@company.com --subject 'Join the meeting' --body 'Join here: MEETING_URI'`" +] + +[[recipes]] +name = "review-meet-participants" +title = "Review Google Meet Attendance" +description = "Review who attended a Google Meet conference and for how long." +category = "productivity" +services = [ "meet" ] +steps = [ + "List recent conferences: `gws meet conferenceRecords list --format table`", + "List participants: `gws meet conferenceRecords participants list --params '{\"parent\": \"conferenceRecords/CONFERENCE_ID\"}' --format table`", + "Get session details: `gws meet conferenceRecords participants participantSessions list --params '{\"parent\": \"conferenceRecords/CONFERENCE_ID/participants/PARTICIPANT_ID\"}' --format table`" +] + +[[recipes]] +name = "create-presentation" +title = "Create a Google Slides Presentation" +description = "Create a new Google Slides presentation and add initial slides." +category = "productivity" +services = [ "slides" ] +steps = [ + "Create presentation: `gws slides presentations create --json '{\"title\": \"Quarterly Review Q2\"}'`", + "Get the presentation ID from the response", + "Share with team: `gws drive permissions create --params '{\"fileId\": \"PRESENTATION_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"team@company.com\"}'`" +] + +[[recipes]] +name = "save-email-attachments" +title = "Save Gmail Attachments to Google Drive" +description = "Find Gmail messages with attachments and save them to a Google Drive folder." +category = "productivity" +services = [ "gmail", "drive" ] +steps = [ + "Search for emails with attachments: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"has:attachment from:client@example.com\"}' --format table`", + "Get message details: `gws gmail users messages get --params '{\"userId\": \"me\", \"id\": \"MESSAGE_ID\"}'`", + "Download attachment: `gws gmail users messages attachments get --params '{\"userId\": \"me\", \"messageId\": \"MESSAGE_ID\", \"id\": \"ATTACHMENT_ID\"}'`", + "Upload to Drive folder: `gws drive +upload --file ./attachment.pdf --parent FOLDER_ID`" +] + +[[recipes]] +name = "send-team-announcement" +title = "Announce via Gmail and Google Chat" +description = "Send a team announcement via both Gmail and a Google Chat space." +category = "communication" +services = [ "gmail", "chat" ] +steps = [ + "Send email: `gws gmail +send --to team@company.com --subject 'Important Update' --body 'Please review the attached policy changes.'`", + "Post in Chat: `gws chat +send --space spaces/TEAM_SPACE --text '📢 Important Update: Please check your email for policy changes.'`" +] + +[[recipes]] +name = "create-feedback-form" +title = "Create and Share a Google Form" +description = "Create a Google Form for feedback and share it via Gmail." +category = "productivity" +services = [ "forms", "gmail" ] +steps = [ + "Create form: `gws forms forms create --json '{\"info\": {\"title\": \"Event Feedback\", \"documentTitle\": \"Event Feedback Form\"}}'`", + "Get the form URL from the response (responderUri field)", + "Email the form: `gws gmail +send --to attendees@company.com --subject 'Please share your feedback' --body 'Fill out the form: FORM_URL'`" +] + +[[recipes]] +name = "sync-contacts-to-sheet" +title = "Export Google Contacts to Sheets" +description = "Export Google Contacts directory to a Google Sheets spreadsheet." +category = "productivity" +services = [ "people", "sheets" ] +steps = [ + "List contacts: `gws people people listDirectoryPeople --params '{\"readMask\": \"names,emailAddresses,phoneNumbers\", \"sources\": [\"DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE\"], \"pageSize\": 100}' --format json`", + "Create a sheet: `gws sheets +append --spreadsheet SHEET_ID --range 'Contacts' --values '[\"Name\", \"Email\", \"Phone\"]'`", + "Append each contact row: `gws sheets +append --spreadsheet SHEET_ID --range 'Contacts' --values '[\"Jane Doe\", \"jane@company.com\", \"+1-555-0100\"]'`" +] + +[[recipes]] +name = "share-event-materials" +title = "Share Files with Meeting Attendees" +description = "Share Google Drive files with all attendees of a Google Calendar event." +category = "productivity" +services = [ "calendar", "drive" ] +steps = [ + "Get event attendees: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`", + "Share file with each attendee: `gws drive permissions create --params '{\"fileId\": \"FILE_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"attendee@company.com\"}'`", + "Verify sharing: `gws drive permissions list --params '{\"fileId\": \"FILE_ID\"}' --format table`" +] + +[[recipes]] +name = "create-vacation-responder" +title = "Set Up a Gmail Vacation Responder" +description = "Enable a Gmail out-of-office auto-reply with a custom message and date range." +category = "productivity" +services = [ "gmail" ] +steps = [ + "Enable vacation responder: `gws gmail users settings updateVacation --params '{\"userId\": \"me\"}' --json '{\"enableAutoReply\": true, \"responseSubject\": \"Out of Office\", \"responseBodyPlainText\": \"I am out of the office until Jan 20. For urgent matters, contact backup@company.com.\", \"restrictToContacts\": false, \"restrictToDomain\": false}'`", + "Verify settings: `gws gmail users settings getVacation --params '{\"userId\": \"me\"}'`", + "Disable when back: `gws gmail users settings updateVacation --params '{\"userId\": \"me\"}' --json '{\"enableAutoReply\": false}'`" +] + +[[recipes]] +name = "create-events-from-sheet" +title = "Create Google Calendar Events from a Sheet" +description = "Read event data from a Google Sheets spreadsheet and create Google Calendar entries for each row." +category = "productivity" +services = [ "sheets", "calendar" ] +steps = [ + "Read event data: `gws sheets +read --spreadsheet SHEET_ID --range \"Events!A2:D\"`", + "For each row, create a calendar event: `gws calendar +insert --summary 'Team Standup' --start '2026-01-20T09:00:00' --end '2026-01-20T09:30:00' --attendee alice@company.com --attendee bob@company.com`" +] + +[[recipes]] +name = "plan-weekly-schedule" +title = "Plan Your Weekly Google Calendar Schedule" +description = "Review your Google Calendar week, identify gaps, and add events to fill them." +category = "scheduling" +services = [ "calendar" ] +steps = [ + "Check this week's agenda: `gws calendar +agenda`", + "Check free/busy for the week: `gws calendar freebusy query --json '{\"timeMin\": \"2025-01-20T00:00:00Z\", \"timeMax\": \"2025-01-25T00:00:00Z\", \"items\": [{\"id\": \"primary\"}]}'`", + "Add a new event: `gws calendar +insert --summary 'Deep Work Block' --start '2026-01-21T14:00:00' --end '2026-01-21T16:00:00'`", + "Review updated schedule: `gws calendar +agenda`" +] + +[[recipes]] +name = "share-doc-and-notify" +title = "Share a Google Doc and Notify Collaborators" +description = "Share a Google Docs document with edit access and email collaborators the link." +category = "productivity" +services = [ "drive", "docs", "gmail" ] +steps = [ + "Find the doc: `gws drive files list --params '{\"q\": \"name contains '\\''Project Brief'\\'' and mimeType = '\\''application/vnd.google-apps.document'\\''\"}'`", + "Share with editor access: `gws drive permissions create --params '{\"fileId\": \"DOC_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"reviewer@company.com\"}'`", + "Email the link: `gws gmail +send --to reviewer@company.com --subject 'Please review: Project Brief' --body 'I have shared the project brief with you: https://docs.google.com/document/d/DOC_ID'`" +] + +[[recipes]] +name = "backup-sheet-as-csv" +title = "Export a Google Sheet as CSV" +description = "Export a Google Sheets spreadsheet as a CSV file for local backup or processing." +category = "productivity" +services = [ "sheets", "drive" ] +steps = [ + "Get spreadsheet details: `gws sheets spreadsheets get --params '{\"spreadsheetId\": \"SHEET_ID\"}'`", + "Export as CSV: `gws drive files export --params '{\"fileId\": \"SHEET_ID\", \"mimeType\": \"text/csv\"}'`", + "Or read values directly: `gws sheets +read --spreadsheet SHEET_ID --range 'Sheet1' --format csv`" +] + +[[recipes]] +name = "save-email-to-doc" +title = "Save a Gmail Message to Google Docs" +description = "Save a Gmail message body into a Google Doc for archival or reference." +category = "productivity" +services = [ "gmail", "docs" ] +steps = [ + "Find the message: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"subject:important from:boss@company.com\"}' --format table`", + "Get message content: `gws gmail users messages get --params '{\"userId\": \"me\", \"id\": \"MSG_ID\"}'`", + "Create a doc with the content: `gws docs documents create --json '{\"title\": \"Saved Email - Important Update\"}'`", + "Write the email body: `gws docs +write --document-id DOC_ID --text 'From: boss@company.com\nSubject: Important Update\n\n[EMAIL BODY]'`" +] + +[[recipes]] +name = "compare-sheet-tabs" +title = "Compare Two Google Sheets Tabs" +description = "Read data from two tabs in a Google Sheet to compare and identify differences." +category = "productivity" +services = [ "sheets" ] +steps = [ + "Read the first tab: `gws sheets +read --spreadsheet SHEET_ID --range \"January!A1:D\"`", + "Read the second tab: `gws sheets +read --spreadsheet SHEET_ID --range \"February!A1:D\"`", + "Compare the data and identify changes" +] + +[[recipes]] +name = "batch-invite-to-event" +title = "Add Multiple Attendees to a Calendar Event" +description = "Add a list of attendees to an existing Google Calendar event and send notifications." +category = "scheduling" +services = [ "calendar" ] +steps = [ + "Get the event: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`", + "Add attendees: `gws calendar events patch --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\", \"sendUpdates\": \"all\"}' --json '{\"attendees\": [{\"email\": \"alice@company.com\"}, {\"email\": \"bob@company.com\"}, {\"email\": \"carol@company.com\"}]}'`", + "Verify attendees: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`" +] + +[[recipes]] +name = "forward-labeled-emails" +title = "Forward Labeled Gmail Messages" +description = "Find Gmail messages with a specific label and forward them to another address." +category = "productivity" +services = [ "gmail" ] +steps = [ + "Find labeled messages: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"label:needs-review\"}' --format table`", + "Get message content: `gws gmail users messages get --params '{\"userId\": \"me\", \"id\": \"MSG_ID\"}'`", + "Forward via new email: `gws gmail +send --to manager@company.com --subject 'FW: [Original Subject]' --body 'Forwarding for your review:\n\n[Original Message Body]'`" +] + +[[recipes]] +name = "generate-report-from-sheet" +title = "Generate a Google Docs Report from Sheet Data" +description = "Read data from a Google Sheet and create a formatted Google Docs report." +category = "productivity" +services = [ "sheets", "docs", "drive" ] +steps = [ + "Read the data: `gws sheets +read --spreadsheet SHEET_ID --range \"Sales!A1:D\"`", + "Create the report doc: `gws docs documents create --json '{\"title\": \"Sales Report - January 2025\"}'`", + "Write the report: `gws docs +write --document-id DOC_ID --text '## Sales Report - January 2025\n\n### Summary\nTotal deals: 45\nRevenue: $125,000\n\n### Top Deals\n1. Acme Corp - $25,000\n2. Widget Inc - $18,000'`", + "Share with stakeholders: `gws drive permissions create --params '{\"fileId\": \"DOC_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"cfo@company.com\"}'`" +] diff --git a/crates/google-workspace-cli/registry/recipes.yaml b/crates/google-workspace-cli/registry/recipes.yaml deleted file mode 100644 index e407404e..00000000 --- a/crates/google-workspace-cli/registry/recipes.yaml +++ /dev/null @@ -1,560 +0,0 @@ -# Curated Recipe Registry — Real-world Google Workspace workflows -# -# Each recipe defines a reusable multi-step task with: -# - name: unique id (directory: recipe-{name}) -# - title: human-readable name -# - description: compact intent (under 130 chars) -# - category: domain -# - services: which gws services this recipe uses -# - steps: concrete gws commands -# - caution: optional warning for destructive operations - -recipes: - - - # ============================================================ - # GMAIL WORKFLOWS - # ============================================================ - - name: label-and-archive-emails - title: Label and Archive Gmail Threads - description: "Apply Gmail labels to matching messages and archive them to keep your inbox clean." - category: productivity - services: [gmail] - steps: - - "Search for matching emails: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"from:notifications@service.com\"}' --format table`" - - "Apply a label: `gws gmail users messages modify --params '{\"userId\": \"me\", \"id\": \"MESSAGE_ID\"}' --json '{\"addLabelIds\": [\"LABEL_ID\"]}'`" - - "Archive (remove from inbox): `gws gmail users messages modify --params '{\"userId\": \"me\", \"id\": \"MESSAGE_ID\"}' --json '{\"removeLabelIds\": [\"INBOX\"]}'`" - - - - - name: draft-email-from-doc - title: Draft a Gmail Message from a Google Doc - description: "Read content from a Google Doc and use it as the body of a Gmail message." - category: productivity - services: [docs, gmail] - steps: - - "Get the document content: `gws docs documents get --params '{\"documentId\": \"DOC_ID\"}'`" - - "Copy the text from the body content" - - "Send the email: `gws gmail +send --to recipient@example.com --subject 'Newsletter Update' --body 'CONTENT_FROM_DOC'`" - - # ============================================================ - # GOOGLE DRIVE WORKFLOWS - # ============================================================ - - name: organize-drive-folder - title: Organize Files into Google Drive Folders - description: "Create a Google Drive folder structure and move files into the right locations." - category: productivity - services: [drive] - steps: - - "Create a project folder: `gws drive files create --json '{\"name\": \"Q2 Project\", \"mimeType\": \"application/vnd.google-apps.folder\"}'`" - - "Create sub-folders: `gws drive files create --json '{\"name\": \"Documents\", \"mimeType\": \"application/vnd.google-apps.folder\", \"parents\": [\"PARENT_FOLDER_ID\"]}'`" - - "Move existing files into folder: `gws drive files update --params '{\"fileId\": \"FILE_ID\", \"addParents\": \"FOLDER_ID\", \"removeParents\": \"OLD_PARENT_ID\"}'`" - - "Verify structure: `gws drive files list --params '{\"q\": \"FOLDER_ID in parents\"}' --format table`" - - - name: share-folder-with-team - title: Share a Google Drive Folder with a Team - description: "Share a Google Drive folder and all its contents with a list of collaborators." - category: productivity - services: [drive] - steps: - - "Find the folder: `gws drive files list --params '{\"q\": \"name = '\\''Project X'\\'' and mimeType = '\\''application/vnd.google-apps.folder'\\''\"}'`" - - "Share as editor: `gws drive permissions create --params '{\"fileId\": \"FOLDER_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"colleague@company.com\"}'`" - - "Share as viewer: `gws drive permissions create --params '{\"fileId\": \"FOLDER_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"stakeholder@company.com\"}'`" - - "Verify permissions: `gws drive permissions list --params '{\"fileId\": \"FOLDER_ID\"}' --format table`" - - - name: email-drive-link - title: Email a Google Drive File Link - description: "Share a Google Drive file and email the link with a message to recipients." - category: productivity - services: [drive, gmail] - steps: - - "Find the file: `gws drive files list --params '{\"q\": \"name = '\\''Quarterly Report'\\''\"}'`" - - "Share the file: `gws drive permissions create --params '{\"fileId\": \"FILE_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"client@example.com\"}'`" - - "Email the link: `gws gmail +send --to client@example.com --subject 'Quarterly Report' --body 'Hi, please find the report here: https://docs.google.com/document/d/FILE_ID'`" - - # ============================================================ - # GOOGLE DOCS WORKFLOWS - # ============================================================ - - name: create-doc-from-template - title: Create a Google Doc from a Template - description: "Copy a Google Docs template, fill in content, and share with collaborators." - category: productivity - services: [drive, docs] - steps: - - "Copy the template: `gws drive files copy --params '{\"fileId\": \"TEMPLATE_DOC_ID\"}' --json '{\"name\": \"Project Brief - Q2 Launch\"}'`" - - "Get the new doc ID from the response" - - "Add content: `gws docs +write --document-id NEW_DOC_ID --text '## Project: Q2 Launch\n\n### Objective\nLaunch the new feature by end of Q2.'`" - - "Share with team: `gws drive permissions create --params '{\"fileId\": \"NEW_DOC_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"team@company.com\"}'`" - - # ============================================================ - # GOOGLE SHEETS WORKFLOWS - # ============================================================ - - name: create-expense-tracker - title: Create a Google Sheets Expense Tracker - description: "Set up a Google Sheets spreadsheet for tracking expenses with headers and initial entries." - category: productivity - services: [sheets, drive] - steps: - - "Create spreadsheet: `gws drive files create --json '{\"name\": \"Expense Tracker 2025\", \"mimeType\": \"application/vnd.google-apps.spreadsheet\"}'`" - - "Add headers: `gws sheets +append --spreadsheet SHEET_ID --range 'Sheet1' --values '[\"Date\", \"Category\", \"Description\", \"Amount\"]'`" - - "Add first entry: `gws sheets +append --spreadsheet SHEET_ID --range 'Sheet1' --values '[\"2025-01-15\", \"Travel\", \"Flight to NYC\", \"450.00\"]'`" - - "Share with manager: `gws drive permissions create --params '{\"fileId\": \"SHEET_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"manager@company.com\"}'`" - - - name: copy-sheet-for-new-month - title: Copy a Google Sheet for a New Month - description: "Duplicate a Google Sheets template tab for a new month of tracking." - category: productivity - services: [sheets] - steps: - - "Get spreadsheet details: `gws sheets spreadsheets get --params '{\"spreadsheetId\": \"SHEET_ID\"}'`" - - "Copy the template sheet: `gws sheets spreadsheets sheets copyTo --params '{\"spreadsheetId\": \"SHEET_ID\", \"sheetId\": 0}' --json '{\"destinationSpreadsheetId\": \"SHEET_ID\"}'`" - - "Rename the new tab: `gws sheets spreadsheets batchUpdate --params '{\"spreadsheetId\": \"SHEET_ID\"}' --json '{\"requests\": [{\"updateSheetProperties\": {\"properties\": {\"sheetId\": 123, \"title\": \"February 2025\"}, \"fields\": \"title\"}}]}'`" - - # ============================================================ - # GOOGLE CALENDAR WORKFLOWS - # ============================================================ - - name: block-focus-time - title: Block Focus Time on Google Calendar - description: "Create recurring focus time blocks on Google Calendar to protect deep work hours." - category: scheduling - services: [calendar] - steps: - - "Create recurring focus block: `gws calendar events insert --params '{\"calendarId\": \"primary\"}' --json '{\"summary\": \"Focus Time\", \"description\": \"Protected deep work block\", \"start\": {\"dateTime\": \"2025-01-20T09:00:00\", \"timeZone\": \"America/New_York\"}, \"end\": {\"dateTime\": \"2025-01-20T11:00:00\", \"timeZone\": \"America/New_York\"}, \"recurrence\": [\"RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\"], \"transparency\": \"opaque\"}'`" - - "Verify it shows as busy: `gws calendar +agenda`" - - - name: reschedule-meeting - title: Reschedule a Google Calendar Meeting - description: "Move a Google Calendar event to a new time and automatically notify all attendees." - category: scheduling - services: [calendar] - steps: - - "Find the event: `gws calendar +agenda`" - - "Get event details: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`" - - "Update the time: `gws calendar events patch --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\", \"sendUpdates\": \"all\"}' --json '{\"start\": {\"dateTime\": \"2025-01-22T14:00:00\", \"timeZone\": \"America/New_York\"}, \"end\": {\"dateTime\": \"2025-01-22T15:00:00\", \"timeZone\": \"America/New_York\"}}'`" - - # ============================================================ - # EMAIL / GMAIL - # ============================================================ - - - - name: create-gmail-filter - title: Create a Gmail Filter - description: "Create a Gmail filter to automatically label, star, or categorize incoming messages." - category: productivity - services: [gmail] - steps: - - "List existing labels: `gws gmail users labels list --params '{\"userId\": \"me\"}' --format table`" - - "Create a new label: `gws gmail users labels create --params '{\"userId\": \"me\"}' --json '{\"name\": \"Receipts\"}'`" - - "Create a filter: `gws gmail users settings filters create --params '{\"userId\": \"me\"}' --json '{\"criteria\": {\"from\": \"receipts@example.com\"}, \"action\": {\"addLabelIds\": [\"LABEL_ID\"], \"removeLabelIds\": [\"INBOX\"]}}'`" - - "Verify filter: `gws gmail users settings filters list --params '{\"userId\": \"me\"}' --format table`" - - # ============================================================ - # CALENDAR / SCHEDULING - # ============================================================ - - - - name: schedule-recurring-event - title: Schedule a Recurring Meeting - description: "Create a recurring Google Calendar event with attendees." - category: scheduling - services: [calendar] - steps: - - "Create recurring event: `gws calendar events insert --params '{\"calendarId\": \"primary\"}' --json '{\"summary\": \"Weekly Standup\", \"start\": {\"dateTime\": \"2024-03-18T09:00:00\", \"timeZone\": \"America/New_York\"}, \"end\": {\"dateTime\": \"2024-03-18T09:30:00\", \"timeZone\": \"America/New_York\"}, \"recurrence\": [\"RRULE:FREQ=WEEKLY;BYDAY=MO\"], \"attendees\": [{\"email\": \"team@company.com\"}]}'`" - - "Verify it was created: `gws calendar +agenda --days 14 --format table`" - - - name: find-free-time - title: Find Free Time Across Calendars - description: "Query Google Calendar free/busy status for multiple users to find a meeting slot." - category: scheduling - services: [calendar] - steps: - - "Query free/busy: `gws calendar freebusy query --json '{\"timeMin\": \"2024-03-18T08:00:00Z\", \"timeMax\": \"2024-03-18T18:00:00Z\", \"items\": [{\"id\": \"user1@company.com\"}, {\"id\": \"user2@company.com\"}]}'`" - - "Review the output to find overlapping free slots" - - "Create event in the free slot: `gws calendar +insert --summary 'Meeting' --attendee user1@company.com --attendee user2@company.com --start '2024-03-18T14:00:00' --end '2024-03-18T14:30:00'`" - - # ============================================================ - # DRIVE / FILE MANAGEMENT - # ============================================================ - - name: bulk-download-folder - title: Bulk Download Drive Folder - description: "List and download all files from a Google Drive folder." - category: productivity - services: [drive] - steps: - - "List files in folder: `gws drive files list --params '{\"q\": \"'\\''FOLDER_ID'\\'' in parents\"}' --format json`" - - "Download each file: `gws drive files get --params '{\"fileId\": \"FILE_ID\", \"alt\": \"media\"}' -o filename.ext`" - - "Export Google Docs as PDF: `gws drive files export --params '{\"fileId\": \"FILE_ID\", \"mimeType\": \"application/pdf\"}' -o document.pdf`" - - - name: find-large-files - title: Find Largest Files in Drive - description: "Identify large Google Drive files consuming storage quota." - category: productivity - services: [drive] - steps: - - "List files sorted by size: `gws drive files list --params '{\"orderBy\": \"quotaBytesUsed desc\", \"pageSize\": 20, \"fields\": \"files(id,name,size,mimeType,owners)\"}' --format table`" - - "Review the output and identify files to archive or move" - - - name: create-shared-drive - title: Create and Configure a Shared Drive - description: "Create a Google Shared Drive and add members with appropriate roles." - category: productivity - services: [drive] - steps: - - "Create shared drive: `gws drive drives create --params '{\"requestId\": \"unique-id-123\"}' --json '{\"name\": \"Project X\"}'`" - - "Add a member: `gws drive permissions create --params '{\"fileId\": \"DRIVE_ID\", \"supportsAllDrives\": true}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"member@company.com\"}'`" - - "List members: `gws drive permissions list --params '{\"fileId\": \"DRIVE_ID\", \"supportsAllDrives\": true}'`" - - - - # ============================================================ - # SHEETS / DATA - # ============================================================ - - name: log-deal-update - title: Log Deal Update to Sheet - description: "Append a deal status update to a Google Sheets sales tracking spreadsheet." - category: sales - services: [sheets, drive] - steps: - - "Find the tracking sheet: `gws drive files list --params '{\"q\": \"name = '\\''Sales Pipeline'\\'' and mimeType = '\\''application/vnd.google-apps.spreadsheet'\\''\"}'`" - - "Read current data: `gws sheets +read --spreadsheet SHEET_ID --range \"Pipeline!A1:F\"`" - - "Append new row: `gws sheets +append --spreadsheet SHEET_ID --range 'Pipeline' --values '[\"2024-03-15\", \"Acme Corp\", \"Proposal Sent\", \"$50,000\", \"Q2\", \"jdoe\"]'`" - - - name: collect-form-responses - title: Check Form Responses - description: "Retrieve and review responses from a Google Form." - category: productivity - services: [forms] - steps: - - "List forms: `gws forms forms list` (if you don't have the form ID)" - - "Get form details: `gws forms forms get --params '{\"formId\": \"FORM_ID\"}'`" - - "Get responses: `gws forms forms responses list --params '{\"formId\": \"FORM_ID\"}' --format table`" - - # ============================================================ - # CHAT / TEAM COMMUNICATION - # ============================================================ - # ============================================================ - # ENGINEERING - # ============================================================ - - name: post-mortem-setup - title: Set Up Post-Mortem - description: "Create a Google Docs post-mortem, schedule a Google Calendar review, and notify via Chat." - category: engineering - services: [docs, calendar, chat] - steps: - - "Create post-mortem doc: `gws docs +write --title 'Post-Mortem: [Incident]' --body '## Summary\\n\\n## Timeline\\n\\n## Root Cause\\n\\n## Action Items'`" - - "Schedule review meeting: `gws calendar +insert --summary 'Post-Mortem Review: [Incident]' --attendee team@company.com --start '2026-03-16T14:00:00' --end '2026-03-16T15:00:00'`" - - "Notify in Chat: `gws chat +send --space spaces/ENG_SPACE --text '🔍 Post-mortem scheduled for [Incident].'`" - - # ============================================================ - # TASKS - # ============================================================ - - name: create-task-list - title: Create a Task List and Add Tasks - description: "Set up a new Google Tasks list with initial tasks." - category: productivity - services: [tasks] - steps: - - "Create task list: `gws tasks tasklists insert --json '{\"title\": \"Q2 Goals\"}'`" - - "Add a task: `gws tasks tasks insert --params '{\"tasklist\": \"TASKLIST_ID\"}' --json '{\"title\": \"Review Q1 metrics\", \"notes\": \"Pull data from analytics dashboard\", \"due\": \"2024-04-01T00:00:00Z\"}'`" - - "Add another task: `gws tasks tasks insert --params '{\"tasklist\": \"TASKLIST_ID\"}' --json '{\"title\": \"Draft Q2 OKRs\"}'`" - - "List tasks: `gws tasks tasks list --params '{\"tasklist\": \"TASKLIST_ID\"}' --format table`" - - - name: review-overdue-tasks - title: Review Overdue Tasks - description: "Find Google Tasks that are past due and need attention." - category: productivity - services: [tasks] - steps: - - "List task lists: `gws tasks tasklists list --format table`" - - "List tasks with status: `gws tasks tasks list --params '{\"tasklist\": \"TASKLIST_ID\", \"showCompleted\": false}' --format table`" - - "Review due dates and prioritize overdue items" - - # ============================================================ - # CONTACTS / PEOPLE - # ============================================================ - - - # ============================================================ - # EVENT SUBSCRIPTIONS - # ============================================================ - - name: watch-drive-changes - title: Watch for Drive Changes - description: "Subscribe to change notifications on a Google Drive file or folder." - category: engineering - services: [events] - steps: - - "Create subscription: `gws events subscriptions create --json '{\"targetResource\": \"//drive.googleapis.com/drives/DRIVE_ID\", \"eventTypes\": [\"google.workspace.drive.file.v1.updated\"], \"notificationEndpoint\": {\"pubsubTopic\": \"projects/PROJECT/topics/TOPIC\"}, \"payloadOptions\": {\"includeResource\": true}}'`" - - "List active subscriptions: `gws events subscriptions list`" - - "Renew before expiry: `gws events +renew --subscription SUBSCRIPTION_ID`" - - # ============================================================ - # CLASSROOM - # ============================================================ - - name: create-classroom-course - title: Create a Google Classroom Course - description: "Create a Google Classroom course and invite students." - category: education - services: [classroom] - steps: - - "Create the course: `gws classroom courses create --json '{\"name\": \"Introduction to CS\", \"section\": \"Period 1\", \"room\": \"Room 101\", \"ownerId\": \"me\"}'`" - - "Invite a student: `gws classroom invitations create --json '{\"courseId\": \"COURSE_ID\", \"userId\": \"student@school.edu\", \"role\": \"STUDENT\"}'`" - - "List enrolled students: `gws classroom courses students list --params '{\"courseId\": \"COURSE_ID\"}' --format table`" - - # ============================================================ - # MEET - # ============================================================ - - name: create-meet-space - title: Create a Google Meet Conference - description: "Create a Google Meet meeting space and share the join link." - category: scheduling - services: [meet, gmail] - steps: - - "Create meeting space: `gws meet spaces create --json '{\"config\": {\"accessType\": \"OPEN\"}}'`" - - "Copy the meeting URI from the response" - - "Email the link: `gws gmail +send --to team@company.com --subject 'Join the meeting' --body 'Join here: MEETING_URI'`" - - - name: review-meet-participants - title: Review Google Meet Attendance - description: "Review who attended a Google Meet conference and for how long." - category: productivity - services: [meet] - steps: - - "List recent conferences: `gws meet conferenceRecords list --format table`" - - "List participants: `gws meet conferenceRecords participants list --params '{\"parent\": \"conferenceRecords/CONFERENCE_ID\"}' --format table`" - - "Get session details: `gws meet conferenceRecords participants participantSessions list --params '{\"parent\": \"conferenceRecords/CONFERENCE_ID/participants/PARTICIPANT_ID\"}' --format table`" - - # ============================================================ - # KEEP - # ============================================================ - # ============================================================ - # SLIDES - # ============================================================ - - name: create-presentation - title: Create a Google Slides Presentation - description: "Create a new Google Slides presentation and add initial slides." - category: productivity - services: [slides] - steps: - - "Create presentation: `gws slides presentations create --json '{\"title\": \"Quarterly Review Q2\"}'`" - - "Get the presentation ID from the response" - - "Share with team: `gws drive permissions create --params '{\"fileId\": \"PRESENTATION_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"team@company.com\"}'`" - - - - # ============================================================ - # CONSUMER PRODUCTIVITY - # ============================================================ - - name: save-email-attachments - title: Save Gmail Attachments to Google Drive - description: "Find Gmail messages with attachments and save them to a Google Drive folder." - category: productivity - services: [gmail, drive] - steps: - - "Search for emails with attachments: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"has:attachment from:client@example.com\"}' --format table`" - - "Get message details: `gws gmail users messages get --params '{\"userId\": \"me\", \"id\": \"MESSAGE_ID\"}'`" - - "Download attachment: `gws gmail users messages attachments get --params '{\"userId\": \"me\", \"messageId\": \"MESSAGE_ID\", \"id\": \"ATTACHMENT_ID\"}'`" - - "Upload to Drive folder: `gws drive +upload --file ./attachment.pdf --parent FOLDER_ID`" - - # ============================================================ - # CROSS-SERVICE WORKFLOWS - # ============================================================ - - name: send-team-announcement - title: Announce via Gmail and Google Chat - description: "Send a team announcement via both Gmail and a Google Chat space." - category: communication - services: [gmail, chat] - steps: - - "Send email: `gws gmail +send --to team@company.com --subject 'Important Update' --body 'Please review the attached policy changes.'`" - - "Post in Chat: `gws chat +send --space spaces/TEAM_SPACE --text '📢 Important Update: Please check your email for policy changes.'`" - - - name: create-feedback-form - title: Create and Share a Google Form - description: "Create a Google Form for feedback and share it via Gmail." - category: productivity - services: [forms, gmail] - steps: - - "Create form: `gws forms forms create --json '{\"info\": {\"title\": \"Event Feedback\", \"documentTitle\": \"Event Feedback Form\"}}'`" - - "Get the form URL from the response (responderUri field)" - - "Email the form: `gws gmail +send --to attendees@company.com --subject 'Please share your feedback' --body 'Fill out the form: FORM_URL'`" - - - name: sync-contacts-to-sheet - title: Export Google Contacts to Sheets - description: "Export Google Contacts directory to a Google Sheets spreadsheet." - category: productivity - services: [people, sheets] - steps: - - "List contacts: `gws people people listDirectoryPeople --params '{\"readMask\": \"names,emailAddresses,phoneNumbers\", \"sources\": [\"DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE\"], \"pageSize\": 100}' --format json`" - - "Create a sheet: `gws sheets +append --spreadsheet SHEET_ID --range 'Contacts' --values '[\"Name\", \"Email\", \"Phone\"]'`" - - "Append each contact row: `gws sheets +append --spreadsheet SHEET_ID --range 'Contacts' --values '[\"Jane Doe\", \"jane@company.com\", \"+1-555-0100\"]'`" - - # ============================================================ - # CONSUMER — COLLABORATION - # ============================================================ - - name: share-event-materials - title: Share Files with Meeting Attendees - description: "Share Google Drive files with all attendees of a Google Calendar event." - category: productivity - services: [calendar, drive] - steps: - - "Get event attendees: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`" - - "Share file with each attendee: `gws drive permissions create --params '{\"fileId\": \"FILE_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"attendee@company.com\"}'`" - - "Verify sharing: `gws drive permissions list --params '{\"fileId\": \"FILE_ID\"}' --format table`" - # ============================================================ - # GMAIL — ORGANIZATION - # ============================================================ - - name: create-vacation-responder - title: Set Up a Gmail Vacation Responder - description: "Enable a Gmail out-of-office auto-reply with a custom message and date range." - category: productivity - services: [gmail] - steps: - - "Enable vacation responder: `gws gmail users settings updateVacation --params '{\"userId\": \"me\"}' --json '{\"enableAutoReply\": true, \"responseSubject\": \"Out of Office\", \"responseBodyPlainText\": \"I am out of the office until Jan 20. For urgent matters, contact backup@company.com.\", \"restrictToContacts\": false, \"restrictToDomain\": false}'`" - - "Verify settings: `gws gmail users settings getVacation --params '{\"userId\": \"me\"}'`" - - "Disable when back: `gws gmail users settings updateVacation --params '{\"userId\": \"me\"}' --json '{\"enableAutoReply\": false}'`" - - # ============================================================ - # DRIVE — FILE OPERATIONS - # ============================================================ - # ============================================================ - # SHEETS — DATA WORKFLOWS - # ============================================================ - - name: create-events-from-sheet - title: Create Google Calendar Events from a Sheet - description: "Read event data from a Google Sheets spreadsheet and create Google Calendar entries for each row." - category: productivity - services: [sheets, calendar] - steps: - - "Read event data: `gws sheets +read --spreadsheet SHEET_ID --range \"Events!A2:D\"`" - - "For each row, create a calendar event: `gws calendar +insert --summary 'Team Standup' --start '2026-01-20T09:00:00' --end '2026-01-20T09:30:00' --attendee alice@company.com --attendee bob@company.com`" - - # ============================================================ - # CALENDAR — PLANNING - # ============================================================ - - name: plan-weekly-schedule - title: Plan Your Weekly Google Calendar Schedule - description: "Review your Google Calendar week, identify gaps, and add events to fill them." - category: scheduling - services: [calendar] - steps: - - "Check this week's agenda: `gws calendar +agenda`" - - "Check free/busy for the week: `gws calendar freebusy query --json '{\"timeMin\": \"2025-01-20T00:00:00Z\", \"timeMax\": \"2025-01-25T00:00:00Z\", \"items\": [{\"id\": \"primary\"}]}'`" - - "Add a new event: `gws calendar +insert --summary 'Deep Work Block' --start '2026-01-21T14:00:00' --end '2026-01-21T16:00:00'`" - - "Review updated schedule: `gws calendar +agenda`" - # ============================================================ - # MULTI-SERVICE PROJECT SETUP - # ============================================================ - # ============================================================ - # DOCS — COLLABORATION - # ============================================================ - - name: share-doc-and-notify - title: Share a Google Doc and Notify Collaborators - description: "Share a Google Docs document with edit access and email collaborators the link." - category: productivity - services: [drive, docs, gmail] - steps: - - "Find the doc: `gws drive files list --params '{\"q\": \"name contains '\\''Project Brief'\\'' and mimeType = '\\''application/vnd.google-apps.document'\\''\"}'`" - - "Share with editor access: `gws drive permissions create --params '{\"fileId\": \"DOC_ID\"}' --json '{\"role\": \"writer\", \"type\": \"user\", \"emailAddress\": \"reviewer@company.com\"}'`" - - "Email the link: `gws gmail +send --to reviewer@company.com --subject 'Please review: Project Brief' --body 'I have shared the project brief with you: https://docs.google.com/document/d/DOC_ID'`" - - # ============================================================ - # SHEETS — BACKUP - # ============================================================ - - name: backup-sheet-as-csv - title: Export a Google Sheet as CSV - description: "Export a Google Sheets spreadsheet as a CSV file for local backup or processing." - category: productivity - services: [sheets, drive] - steps: - - "Get spreadsheet details: `gws sheets spreadsheets get --params '{\"spreadsheetId\": \"SHEET_ID\"}'`" - - "Export as CSV: `gws drive files export --params '{\"fileId\": \"SHEET_ID\", \"mimeType\": \"text/csv\"}'`" - - "Or read values directly: `gws sheets +read --spreadsheet SHEET_ID --range 'Sheet1' --format csv`" - - # ============================================================ - # CALENDAR — TEAM - # ============================================================ - # ============================================================ - # DRIVE — CLEANUP - # ============================================================ - # ============================================================ - # GMAIL — ARCHIVING - # ============================================================ - - name: save-email-to-doc - title: Save a Gmail Message to Google Docs - description: "Save a Gmail message body into a Google Doc for archival or reference." - category: productivity - services: [gmail, docs] - steps: - - "Find the message: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"subject:important from:boss@company.com\"}' --format table`" - - "Get message content: `gws gmail users messages get --params '{\"userId\": \"me\", \"id\": \"MSG_ID\"}'`" - - "Create a doc with the content: `gws docs documents create --json '{\"title\": \"Saved Email - Important Update\"}'`" - - "Write the email body: `gws docs +write --document-id DOC_ID --text 'From: boss@company.com\nSubject: Important Update\n\n[EMAIL BODY]'`" - - # ============================================================ - # SHEETS — FORMULAS - # ============================================================ - # ============================================================ - # REPETITIVE WORKFLOWS - # ============================================================ - # ============================================================ - # GMAIL — AUTOMATED REPLIES - # ============================================================ - - - # ============================================================ - # DRIVE — BATCH OPERATIONS - # ============================================================ - - - # ============================================================ - # SHEETS — DATA SYNC - # ============================================================ - - name: compare-sheet-tabs - title: Compare Two Google Sheets Tabs - description: "Read data from two tabs in a Google Sheet to compare and identify differences." - category: productivity - services: [sheets] - steps: - - "Read the first tab: `gws sheets +read --spreadsheet SHEET_ID --range \"January!A1:D\"`" - - "Read the second tab: `gws sheets +read --spreadsheet SHEET_ID --range \"February!A1:D\"`" - - "Compare the data and identify changes" - - # ============================================================ - # CALENDAR — COORDINATION - # ============================================================ - - name: batch-invite-to-event - title: Add Multiple Attendees to a Calendar Event - description: "Add a list of attendees to an existing Google Calendar event and send notifications." - category: scheduling - services: [calendar] - steps: - - "Get the event: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`" - - "Add attendees: `gws calendar events patch --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\", \"sendUpdates\": \"all\"}' --json '{\"attendees\": [{\"email\": \"alice@company.com\"}, {\"email\": \"bob@company.com\"}, {\"email\": \"carol@company.com\"}]}'`" - - "Verify attendees: `gws calendar events get --params '{\"calendarId\": \"primary\", \"eventId\": \"EVENT_ID\"}'`" - - # ============================================================ - # GMAIL — NOTIFICATION ROUTING - # ============================================================ - - name: forward-labeled-emails - title: Forward Labeled Gmail Messages - description: "Find Gmail messages with a specific label and forward them to another address." - category: productivity - services: [gmail] - steps: - - "Find labeled messages: `gws gmail users messages list --params '{\"userId\": \"me\", \"q\": \"label:needs-review\"}' --format table`" - - "Get message content: `gws gmail users messages get --params '{\"userId\": \"me\", \"id\": \"MSG_ID\"}'`" - - "Forward via new email: `gws gmail +send --to manager@company.com --subject 'FW: [Original Subject]' --body 'Forwarding for your review:\n\n[Original Message Body]'`" - - # ============================================================ - # DOCS + SHEETS — CROSS-SERVICE - # ============================================================ - - name: generate-report-from-sheet - title: Generate a Google Docs Report from Sheet Data - description: "Read data from a Google Sheet and create a formatted Google Docs report." - category: productivity - services: [sheets, docs, drive] - steps: - - "Read the data: `gws sheets +read --spreadsheet SHEET_ID --range \"Sales!A1:D\"`" - - "Create the report doc: `gws docs documents create --json '{\"title\": \"Sales Report - January 2025\"}'`" - - "Write the report: `gws docs +write --document-id DOC_ID --text '## Sales Report - January 2025\n\n### Summary\nTotal deals: 45\nRevenue: $125,000\n\n### Top Deals\n1. Acme Corp - $25,000\n2. Widget Inc - $18,000'`" - - "Share with stakeholders: `gws drive permissions create --params '{\"fileId\": \"DOC_ID\"}' --json '{\"role\": \"reader\", \"type\": \"user\", \"emailAddress\": \"cfo@company.com\"}'`" - diff --git a/crates/google-workspace-cli/src/generate_skills.rs b/crates/google-workspace-cli/src/generate_skills.rs index e9d18941..ce265407 100644 --- a/crates/google-workspace-cli/src/generate_skills.rs +++ b/crates/google-workspace-cli/src/generate_skills.rs @@ -24,8 +24,8 @@ use crate::services; use clap::Command; use std::path::Path; -const PERSONAS_YAML: &str = include_str!("../registry/personas.yaml"); -const RECIPES_YAML: &str = include_str!("../registry/recipes.yaml"); +const PERSONAS_TOML: &str = include_str!("../registry/personas.toml"); +const RECIPES_TOML: &str = include_str!("../registry/recipes.toml"); /// Methods blocked from skill generation. /// Format: (service_alias, resource, method). @@ -202,12 +202,11 @@ pub async fn handle_generate_skills(args: &[String]) -> Result<(), GwsError> { } } - // Generate Personas if filter .as_ref() .is_none_or(|f| "persona".contains(f.as_str()) || "personas".contains(f.as_str())) { - if let Ok(registry) = serde_yaml::from_str::(PERSONAS_YAML) { + if let Ok(registry) = toml::from_str::(PERSONAS_TOML) { eprintln!( "Generating skills for {} personas...", registry.personas.len() @@ -229,7 +228,7 @@ pub async fn handle_generate_skills(args: &[String]) -> Result<(), GwsError> { } } } else { - eprintln!("WARNING: Failed to parse personas.yaml"); + eprintln!("WARNING: Failed to parse personas.toml"); } } @@ -238,7 +237,7 @@ pub async fn handle_generate_skills(args: &[String]) -> Result<(), GwsError> { .as_ref() .is_none_or(|f| "recipe".contains(f.as_str()) || "recipes".contains(f.as_str())) { - if let Ok(registry) = serde_yaml::from_str::(RECIPES_YAML) { + if let Ok(registry) = toml::from_str::(RECIPES_TOML) { eprintln!( "Generating skills for {} recipes...", registry.recipes.len() @@ -260,7 +259,7 @@ pub async fn handle_generate_skills(args: &[String]) -> Result<(), GwsError> { } } } else { - eprintln!("WARNING: Failed to parse recipes.yaml"); + eprintln!("WARNING: Failed to parse recipes.toml"); } } @@ -983,10 +982,8 @@ mod tests { #[test] fn test_registry_references() { - let personas: PersonaRegistry = - serde_yaml::from_str(PERSONAS_YAML).expect("valid personas yaml"); - let recipes: RecipeRegistry = - serde_yaml::from_str(RECIPES_YAML).expect("valid recipes yaml"); + let personas: PersonaRegistry = toml::from_str(PERSONAS_TOML).expect("valid personas toml"); + let recipes: RecipeRegistry = toml::from_str(RECIPES_TOML).expect("valid recipes toml"); // Valid services mapped by api_name or alias let all_services = services::SERVICES;