Files
claude-code/plans/2025-01-02-gcal-design.md
OpenCode Test f09d74dd96 Mark gcal implementation checklist complete
OAuth setup and subcommand testing verified.
Natural language fallback remains to test.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 22:15:45 -08:00

5.8 KiB

Google Calendar Integration Design

Date: 2025-01-02 Status: Approved Primary Use Case: Agenda overview

Overview

Build a /gcal slash command for Google Calendar access, following the same architectural pattern as /gmail:

  • OAuth credentials (reuse existing ~/.gmail-mcp/)
  • Python API wrapper with tiered delegation
  • Skill file defining usage patterns
  • Read-only by default

Architecture

User types /gcal
       │
       ▼
   Command (gcal.md)
       │
       ├─→ invokes: skill:gcal
       │
       ▼
   Skill determines tier
       │
       ├─→ Haiku: today, tomorrow, week, next (fetch + format)
       └─→ Sonnet: summary (fetch + analyze)
       │
       ▼
   Python helper (gcal_delegate.py)
       │
       ├─→ Google Calendar API via OAuth
       └─→ Returns structured JSON
       │
       ▼
   PA formats response for user

Components

File Format Purpose
~/.claude/commands/gcal.md Markdown Slash command definition
~/.claude/skills/gcal/SKILL.md Markdown Usage patterns and routing
~/.claude/mcp/delegation/gcal_delegate.py Python API wrapper + delegation
~/.gmail-mcp/credentials.json JSON OAuth credentials (add Calendar scope)

Command Interface

Subcommands

Subcommand Description Tier
today Today's agenda Haiku
tomorrow Tomorrow's agenda Haiku
week Next 7 days, grouped by day Haiku
next Next upcoming event Haiku
summary Smart analysis of your week Sonnet

Routing

/gcal                → Smart default (today if before 6pm, tomorrow if after)
/gcal today          → Today's agenda
/gcal tomorrow       → Tomorrow's agenda
/gcal week           → Next 7 days, grouped by day
/gcal next           → Next upcoming event only
/gcal summary        → Sonnet-powered week analysis
/gcal <natural>      → PA interprets intent, routes to appropriate subcommand

Hybrid Approach

  1. Exact subcommand match first: today, tomorrow, week, next, summary
  2. Natural language fallback:
    • "what's on today" → today
    • "this week" → week
    • "next meeting" → next
    • "am I busy tomorrow" → tomorrow
    • "give me an overview" → summary
  3. Ambiguous input: Ask for clarification

Smart Default

from datetime import datetime
def default_view():
    return "today" if datetime.now().hour < 18 else "tomorrow"

Output Format

Simple List (today/tomorrow/next)

📅 Today — Thursday, Jan 2

  9:00 AM   Team standup (30m)
            📍 Zoom · 👥 5 attendees

 10:30 AM   1:1 with Sarah (45m)
            📍 Conference Room B

  2:00 PM   Project review (1h)
            📍 Google Meet · 👥 8 attendees
            📝 Q4 roadmap discussion

No more events today.

Grouped by Day (week)

📅 This Week — Jan 2-8

━━━ Thursday, Jan 2 ━━━
  9:00 AM   Team standup (30m)
  2:00 PM   Project review (1h)

━━━ Friday, Jan 3 ━━━
  11:00 AM  Client call (1h)

━━━ Monday, Jan 6 ━━━
  (no events)

...

Context Fields

  • 📍 Location or meeting link
  • 👥 Attendee count
  • 📝 Description snippet (first ~50 chars)

Smart Summary (Sonnet)

"Your week is front-loaded — Thursday and Friday are packed with 6 meetings totaling 5.5 hours. Monday-Wednesday are mostly clear, good for deep work. Heads up: the Client call Friday overlaps with your blocked focus time."

Python Helper

Structure

#!/usr/bin/env python3
"""
Google Calendar Delegation Helper

Usage:
    gcal_delegate.py today
    gcal_delegate.py tomorrow
    gcal_delegate.py week
    gcal_delegate.py next
    gcal_delegate.py summary
"""

SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
CREDENTIALS_PATH = "~/.gmail-mcp/credentials.json"

# Core functions
def get_calendar_service()     # OAuth flow, returns Calendar API client
def fetch_events(start, end)   # Returns list of event dicts
def format_event(event)        # Extracts: time, title, location, attendees, description
def delegate(model, prompt)    # Calls Claude CLI for Sonnet-tier tasks

# Subcommand handlers
def cmd_today()      # fetch_events for today, format, return JSON
def cmd_tomorrow()   # fetch_events for tomorrow
def cmd_week()       # fetch_events for 7 days, group by date
def cmd_next()       # fetch next single event
def cmd_summary()    # fetch week, delegate to Sonnet for analysis

Output Format

{
  "tier": "haiku",
  "operation": "today",
  "date": "2025-01-02",
  "events": [...],
  "count": 3
}

OAuth Setup

One-Time Setup

  1. Go to Google Cloud Console → APIs & Services
  2. Enable "Google Calendar API"
  3. OAuth consent screen → Add scope: calendar.readonly
  4. Delete local token: rm ~/.gmail-mcp/token.json
  5. Run /gcal today — triggers re-auth with new scope

Scope Detection

Helper detects missing scope and prompts:

Calendar scope not authorized. Run:
  rm ~/.gmail-mcp/token.json
  Then retry /gcal today to re-authenticate.

Delegation Tiers

Tier Operations Reason
Haiku today, tomorrow, week, next Fetch + format only
Sonnet summary Requires analysis
Opus (reserved) Strategic planning if needed

Policy

  • Read-only operations only
  • Show context (attendees, location) by default
  • Summarize results, don't dump raw data
  • Start with lowest capable model tier

Implementation Checklist

  • Add Calendar scope to GCP OAuth app
  • Create ~/.claude/skills/gcal/SKILL.md
  • Create ~/.claude/commands/gcal.md
  • Create ~/.claude/mcp/delegation/gcal_delegate.py
  • Test OAuth re-authorization
  • Test all subcommands
  • Test natural language fallback