[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EEHXMJS5MKC09CWZ778JHQ":3,"skill-same:01M6EEHXMJS5MKC09CWZ778JHQ":48},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":21,"linkOnly":22,"markdownContent":23,"markdownBody":23,"frontMatter":24,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":30,"ownerHtmlUrl":31,"ownerBlogUrl":6,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M6EEHXMJS5MKC09CWZ778JHQ","calendar-integration",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fcalendar-integration\u002FSKILL.md",[],[18,19,20],"integration","calendar","calendar integration","2026-11-10 10:12:30",false,"# Calendar Integration\n\n## Overview\n\nThis skill helps AI agents integrate with Google Calendar and Microsoft Outlook Calendar. It covers authentication, event CRUD, recurring events, availability\u002Ffree-busy queries, webhook notifications, and building scheduling features like booking pages and meeting coordinators.\n\n## Instructions\n\n### Google Calendar API v3\n\n#### Authentication\n```typescript\nimport { google } from 'googleapis';\n\n\u002F\u002F OAuth 2.0 (user context)\nconst oauth2Client = new google.auth.OAuth2(\n  process.env.GOOGLE_CLIENT_ID,\n  process.env.GOOGLE_CLIENT_SECRET,\n  process.env.GOOGLE_REDIRECT_URI\n);\nconst authUrl = oauth2Client.generateAuthUrl({\n  access_type: 'offline',\n  scope: ['https:\u002F\u002Fwww.googleapis.com\u002Fauth\u002Fcalendar'],\n});\nconst { tokens } = await oauth2Client.getToken(authorizationCode);\noauth2Client.setCredentials(tokens);\nconst calendar = google.calendar({ version: 'v3', auth: oauth2Client });\n\n\u002F\u002F Service Account (server-to-server, domain-wide delegation)\nconst auth = new google.auth.GoogleAuth({\n  keyFile: '\u002Fpath\u002Fto\u002Fservice-account-key.json',\n  scopes: ['https:\u002F\u002Fwww.googleapis.com\u002Fauth\u002Fcalendar'],\n  clientOptions: { subject: 'user@company.com' },\n});\n```\n\n#### Create Events\n```typescript\n\u002F\u002F Timed event with attendees and Meet link\nconst event = await calendar.events.insert({\n  calendarId: 'primary',\n  requestBody: {\n    summary: 'Sprint Planning',\n    description: 'Plan sprint 14 tasks and capacity.',\n    start: { dateTime: '2026-03-01T14:00:00', timeZone: 'America\u002FNew_York' },\n    end: { dateTime: '2026-03-01T15:00:00', timeZone: 'America\u002FNew_York' },\n    attendees: [{ email: 'sarah@company.com' }, { email: 'mike@company.com' }],\n    conferenceData: {\n      createRequest: { requestId: 'req-' + Date.now(), conferenceSolutionKey: { type: 'hangoutsMeet' } },\n    },\n  },\n  conferenceDataVersion: 1,\n  sendUpdates: 'all',\n});\n\n\u002F\u002F Recurring event\nawait calendar.events.insert({\n  calendarId: 'primary',\n  requestBody: {\n    summary: 'Daily Standup',\n    start: { dateTime: '2026-03-01T09:30:00', timeZone: 'America\u002FNew_York' },\n    end: { dateTime: '2026-03-01T09:45:00', timeZone: 'America\u002FNew_York' },\n    recurrence: ['RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;UNTIL=20260630T000000Z'],\n  },\n});\n```\n\n#### RRULE Reference\n```\nDaily:          RRULE:FREQ=DAILY;COUNT=30\nWeekly:         RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR\nBiweekly:       RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU\nMonthly (date): RRULE:FREQ=MONTHLY;BYMONTHDAY=1\nMonthly (day):  RRULE:FREQ=MONTHLY;BYDAY=2TU\nWith end date:  RRULE:FREQ=WEEKLY;BYDAY=MO;UNTIL=20261231T000000Z\n```\n\n#### Query, Update, Delete\n```typescript\n\u002F\u002F List upcoming events (next 7 days)\nconst { data } = await calendar.events.list({\n  calendarId: 'primary',\n  timeMin: new Date().toISOString(),\n  timeMax: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),\n  singleEvents: true, orderBy: 'startTime', maxResults: 50,\n});\n\n\u002F\u002F Update event\nawait calendar.events.patch({\n  calendarId: 'primary', eventId,\n  requestBody: { summary: 'Sprint Planning (MOVED)', start: { dateTime: '2026-03-02T14:00:00', timeZone: 'America\u002FNew_York' }, end: { dateTime: '2026-03-02T15:00:00', timeZone: 'America\u002FNew_York' } },\n  sendUpdates: 'all',\n});\n\n\u002F\u002F Delete event\nawait calendar.events.delete({ calendarId: 'primary', eventId, sendUpdates: 'all' });\n```\n\n#### Free\u002FBusy Query\n```typescript\nconst { data } = await calendar.freebusy.query({\n  requestBody: {\n    timeMin: '2026-03-01T09:00:00-05:00',\n    timeMax: '2026-03-01T18:00:00-05:00',\n    timeZone: 'America\u002FNew_York',\n    items: [{ id: 'sarah@company.com' }, { id: 'mike@company.com' }],\n  },\n});\n\u002F\u002F data.calendars['sarah@company.com'].busy → array of { start, end } blocks\n```\n\n### Microsoft Outlook Calendar (Graph API)\n\n#### Authentication\n```typescript\nimport { ClientSecretCredential } from '@azure\u002Fidentity';\nimport { Client } from '@microsoft\u002Fmicrosoft-graph-client';\nimport { TokenCredentialAuthenticationProvider } from '@microsoft\u002Fmicrosoft-graph-client\u002FauthProviders\u002FazureTokenCredentials';\n\nconst credential = new ClientSecretCredential(\n  process.env.AZURE_TENANT_ID, process.env.AZURE_CLIENT_ID, process.env.AZURE_CLIENT_SECRET\n);\nconst authProvider = new TokenCredentialAuthenticationProvider(credential, {\n  scopes: ['https:\u002F\u002Fgraph.microsoft.com\u002F.default'],\n});\nconst graphClient = Client.initWithMiddleware({ authProvider });\n```\n\n#### Create Events & Query\n```typescript\n\u002F\u002F Create event with Teams meeting\nconst event = await graphClient.api(`\u002Fusers\u002F${userId}\u002Fevents`).post({\n  subject: 'Sprint Planning',\n  start: { dateTime: '2026-03-01T14:00:00', timeZone: 'America\u002FNew_York' },\n  end: { dateTime: '2026-03-01T15:00:00', timeZone: 'America\u002FNew_York' },\n  attendees: [\n    { emailAddress: { address: 'sarah@company.com' }, type: 'required' },\n  ],\n  isOnlineMeeting: true,\n  onlineMeetingProvider: 'teamsForBusiness',\n});\n\n\u002F\u002F List events in date range\nconst events = await graphClient.api(`\u002Fusers\u002F${userId}\u002FcalendarView`)\n  .query({ startDateTime: '2026-03-01T00:00:00Z', endDateTime: '2026-03-07T23:59:59Z' })\n  .select('subject,start,end,location,isOnlineMeeting')\n  .orderby('start\u002FdateTime').top(50).get();\n\n\u002F\u002F Find meeting times (smart scheduling)\nconst suggestions = await graphClient.api(`\u002Fusers\u002F${userId}\u002FfindMeetingTimes`).post({\n  attendees: [\n    { emailAddress: { address: 'sarah@company.com' }, type: 'required' },\n  ],\n  timeConstraint: { timeslots: [{\n    start: { dateTime: '2026-03-01T09:00:00', timeZone: 'America\u002FNew_York' },\n    end: { dateTime: '2026-03-05T18:00:00', timeZone: 'America\u002FNew_York' },\n  }] },\n  meetingDuration: 'PT1H',\n  maxCandidates: 5,\n});\n```\n\n### API Comparison\n\n| Feature | Google Calendar | Outlook (Graph) |\n|---------|----------------|-----------------|\n| Auth | Google OAuth 2.0 | Azure AD OAuth 2.0 |\n| Video meeting | Google Meet | Teams (isOnlineMeeting) |\n| Free\u002Fbusy | freebusy.query | getSchedule \u002F findMeetingTimes |\n| Webhooks | Push notifications (7 day max) | Subscriptions (3 day max) |\n| Recurring | RRULE strings | Structured recurrence object |\n| Smart scheduling | Not built-in | findMeetingTimes (ranked) |\n\n## Examples\n\n### Example 1: Schedule a team meeting across calendars\n**User prompt:** \"Find a 1-hour slot next week when Sarah, Mike, and Conference Room B are all free, then create a Sprint Planning meeting with a Google Meet link.\"\n\nThe agent will:\n1. Call `calendar.freebusy.query` with all three calendar IDs for next week's business hours\n2. Parse the busy blocks to find common free 1-hour windows\n3. Present the available slots to the user\n4. Create the event with `calendar.events.insert` including attendees, Meet link (`conferenceDataVersion: 1`), and send notifications to all attendees\n\n### Example 2: Set up a recurring standup with Outlook\n**User prompt:** \"Create a daily standup meeting at 9:30 AM ET on weekdays in Microsoft Teams for our engineering team, running through June 2026.\"\n\nThe agent will:\n1. Authenticate with Microsoft Graph API using the configured Azure AD credentials\n2. Call `graphClient.api('\u002Fusers\u002F{userId}\u002Fevents').post()` with `isOnlineMeeting: true`, `onlineMeetingProvider: 'teamsForBusiness'`, and a weekly recurrence pattern for Monday-Friday\n3. Set the recurrence range with `startDate: '2026-03-01'` and `endDate: '2026-06-30'`\n4. Add all engineering team members as required attendees and return the Teams join URL\n\n## Guidelines\n\n- Always specify `timeZone` — never rely on server timezone for calendar operations\n- Use `singleEvents: true` (Google) or `calendarView` (Outlook) to expand recurring events\n- Free\u002Fbusy before creating — check availability, don't just double-book\n- Webhook renewal — both Google (7d max) and Outlook (3d max) require renewal jobs\n- Use sync tokens (Google) \u002F delta queries (Outlook) for efficient polling\n- Buffer time between events — back-to-back meetings are a UX problem\n- ISO 8601 for all date handling — never parse dates as strings manually\n- Send meeting updates to attendees (`sendUpdates: 'all'`) — silent changes cause confusion\n- Rate limits: Google ~10 QPS per user, Graph ~10,000 per 10 min per app per tenant\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Fcalendar-integration",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill calendar-integration",{"tool":40,"command":41},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill calendar-integration",{"tool":43,"command":44},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill calendar-integration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fcalendar-integration\u002FSKILL.md",true,[],[49,63,73,82,88,95],{"skillNo":50,"name":51,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":52,"categories":53,"keywords":59,"publishedAt":21},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[54],{"categoryNo":55,"categoryName":56,"taxonomyType":57,"taxonomyTypeDesc":58},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[60,61,62],"model","model hierarchy","model hierarchy skill",{"skillNo":64,"name":65,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":69,"publishedAt":21},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[68],{"categoryNo":55,"categoryName":56,"taxonomyType":57,"taxonomyTypeDesc":58},[70,71,72],"MCP","zoom","zoom mcp",{"skillNo":74,"name":75,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":21},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[79,80,81,71],"sdk","zoom apps sdk","apps",{"skillNo":83,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":21},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[84],{"skillNo":89,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":94,"publishedAt":21},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[93],{"categoryNo":55,"categoryName":56,"taxonomyType":57,"taxonomyTypeDesc":58},[90],{"skillNo":96,"name":97,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":100,"publishedAt":21},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[97]]