Files
claude-code/skills/gmail/SKILL.md
OpenCode Test d9332ae118 Add tiered model delegation for gmail operations
Implements cost-efficient gmail operations by delegating to appropriate
model tiers via Claude CLI subprocess. Simple fetches use no LLM,
summarization and triage delegate to Sonnet, complex reasoning stays
with Opus (PA). Uses subscription instead of API key.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 21:35:32 -08:00

5.4 KiB

name, description, allowed-tools
name description allowed-tools
gmail Gmail read access via direct Python API - search, check unread, detect urgent emails
Bash

Gmail Skill

Access Gmail via direct Python API calls. Uses OAuth credentials at ~/.gmail-mcp/.

Use the tiered delegation helper for cost-efficient operations. Uses Claude CLI with your subscription (no API key needed):

GMAIL_PY=~/.claude/mcp/gmail/venv/bin/python
HELPER=~/.claude/mcp/delegation/gmail_delegate.py

# Haiku tier - list unread (no LLM call, just fetches)
$GMAIL_PY $HELPER check-unread --days 7

# Sonnet tier - summarize emails (spawns claude --model sonnet)
$GMAIL_PY $HELPER summarize --query "from:github.com"

# Sonnet tier - triage urgent (spawns claude --model sonnet)
$GMAIL_PY $HELPER urgent

When to Use Each Tier

Request Type Command Model
"Check my email" check-unread Haiku
"How many unread?" check-unread Haiku
"Summarize X" summarize --query "X" Sonnet
"What's urgent?" urgent Sonnet
"What should I prioritize?" (PA direct) Opus

Usage

For any Gmail request, use Bash to run the Python helper:

GMAIL_CREDENTIALS_PATH=~/.gmail-mcp/credentials.json ~/.claude/mcp/gmail/venv/bin/python << 'EOF'
from gmail_mcp.utils.GCP.gmail_auth import get_gmail_service
from collections import defaultdict

service = get_gmail_service()

# Your query here
results = service.users().messages().list(userId='me', q='is:unread newer_than:3d', maxResults=25).execute()
messages = results.get('messages', [])

for msg in messages:
    detail = service.users().messages().get(userId='me', id=msg['id'], format='metadata', metadataHeaders=['From', 'Subject', 'Date']).execute()
    headers = {h['name']: h['value'] for h in detail['payload']['headers']}
    print(f"From: {headers.get('From', 'Unknown')}")
    print(f"Subject: {headers.get('Subject', '(no subject)')}")
    print(f"Date: {headers.get('Date', 'Unknown')}")
    print("---")
EOF

Query Patterns

Request Gmail Query
Unread is:unread
Last N days newer_than:Nd
From sender from:email@example.com
With attachments has:attachment
Important is:important
Urgent keywords subject:(urgent OR asap OR "action required")

Common Tasks

Check unread (grouped by sender)

GMAIL_CREDENTIALS_PATH=~/.gmail-mcp/credentials.json ~/.claude/mcp/gmail/venv/bin/python << 'EOF'
from gmail_mcp.utils.GCP.gmail_auth import get_gmail_service
from collections import defaultdict
service = get_gmail_service()
results = service.users().messages().list(userId='me', q='is:unread newer_than:7d', maxResults=25).execute()
by_sender = defaultdict(list)
for msg in results.get('messages', []):
    detail = service.users().messages().get(userId='me', id=msg['id'], format='metadata', metadataHeaders=['From', 'Subject']).execute()
    headers = {h['name']: h['value'] for h in detail['payload']['headers']}
    sender = headers.get('From', 'Unknown').split('<')[0].strip().strip('"')
    by_sender[sender].append(headers.get('Subject', '(no subject)')[:50])
for sender, subjects in sorted(by_sender.items(), key=lambda x: -len(x[1])):
    print(f"* {sender} ({len(subjects)})")
    for s in subjects[:2]: print(f"  - {s}")
    if len(subjects) > 2: print(f"  - ...+{len(subjects)-2} more")
EOF

Check urgent

GMAIL_CREDENTIALS_PATH=~/.gmail-mcp/credentials.json ~/.claude/mcp/gmail/venv/bin/python << 'EOF'
from gmail_mcp.utils.GCP.gmail_auth import get_gmail_service
service = get_gmail_service()
results = service.users().messages().list(userId='me', q='is:unread newer_than:3d (subject:urgent OR subject:asap OR subject:"action required" OR is:important)', maxResults=15).execute()
for msg in results.get('messages', []):
    detail = service.users().messages().get(userId='me', id=msg['id'], format='metadata', metadataHeaders=['From', 'Subject', 'Date']).execute()
    headers = {h['name']: h['value'] for h in detail['payload']['headers']}
    print(f"From: {headers.get('From', 'Unknown')}")
    print(f"Subject: {headers.get('Subject', '(no subject)')}")
    print(f"Date: {headers.get('Date', 'Unknown')}")
    print("---")
EOF

Model Selection

Gmail operations use tiered delegation per model-policy.json:

Model Use For Examples
Haiku Fetch, count, list, simple search "How many unread?", "List from X"
Sonnet Summarize, categorize, extract "Summarize this email", "Group by topic"
Opus Prioritize, analyze, cross-reference "What should I handle first?"

Delegation Pattern

When invoking gmail operations, the PA should:

  1. Classify the request — Is it fetch-only, summarization, or analysis?
  2. Delegate appropriately:
    • Haiku: API calls + simple formatting
    • Sonnet: API calls + content understanding
    • Opus: Only for strategic reasoning
  3. Escalate if needed — If lower tier can't handle it, escalate

Implementation Note

Until Task tool delegation is available, the PA executes gmail operations directly but should mentally "account" for which tier the work belongs to. This policy enables future cost optimization when subagent spawning is implemented.

Policy

  • Read-only operations only
  • Summarize results (don't dump raw content)
  • Report metadata, not full body unless asked
  • Start with lowest capable model tier
  • Escalate only when task complexity requires