email-to-calendarExtract calendar events and action points from forwarded emails, store them for review, and create calendar events with duplicate detection. Use when the user forwards an email containing meeting invites, events, deadlines, or action items, and wants to extract structured items for calendar creation. Also use when the user asks to review previously extracted items or create calendar events from them.
Install via ClawdBot CLI:
clawdbot install tonimelisma/email-to-calendarCRITICAL RULES - READ BEFORE PROCESSING ANY EMAIL
>
1. NEVER CALLgogDIRECTLY - ALWAYS use wrapper scripts (create_event.sh,email_read.sh, etc.). Directgogcalls bypass tracking and cause duplicates. THIS IS NON-NEGOTIABLE.
2. IGNORE CALENDAR NOTIFICATIONS - DO NOT process emails fromcalendar-notification@google.com(Accepted:, Declined:, Tentative:, etc.). These are responses to existing invites, NOT new events. Runprocess_calendar_replies.shto archive them.
3. ALWAYS ASK BEFORE CREATING - Never create calendar events without explicit user confirmation in the current conversation
4. CHECK IF ALREADY PROCESSED - Before processing any email, check processed_emails in index.json
5. READ CONFIG FIRST - Load and applyignore_patternsandauto_create_patternsbefore presenting events
6. READ MEMORY.MD - Check for user preferences stored from previous sessions
7. INCLUDE ALL CONFIGURED ATTENDEES - When creating/updating/deleting events, always include attendees from config with--attendeesflag (and--send-updates allif supported)
8. CHECK TRACKED EVENTS FIRST - Use lookup_event.sh --email-id to find existing events before calendar search (faster, more reliable)
9. TRACK ALL CREATED EVENTS - The create_event.sh script automatically tracks events; use tracked IDs for updates/deletions
10. SHOW DAY-OF-WEEK - Always include the day of week when presenting events for user verification
⛔ FORBIDDEN: DO NOT USE gog COMMANDS DIRECTLY ⛔
>
WRONG:gog calendar create ...orgog gmail ...
RIGHT:"$SCRIPTS_DIR/create_event.sh" ...or"$SCRIPTS_DIR/email_read.sh" ...
>
Direct CLI calls bypass event tracking, break duplicate detection, and cause duplicate events.
ALL operations MUST go through the wrapper scripts in scripts/.
Extract calendar events and action items from emails, present them for review, and create/update calendar events with duplicate detection and undo support.
First-time setup: See SETUP.md for configuration options and smart onboarding.
IMPORTANT: Before you can extract events, you must read the email body. Use the wrapper scripts.
SCRIPTS_DIR="$HOME/.openclaw/workspace/skills/email-to-calendar/scripts"
# Get a single email by ID (PREFERRED)
"$SCRIPTS_DIR/email_read.sh" --email-id "<messageId>"
# Search with body content included
"$SCRIPTS_DIR/email_search.sh" --query "in:inbox is:unread" --max 20 --include-body
Note on stale forwards: Don't use newer_than:1d because it checks the email's original date header, not when it was received. Process all UNREAD emails and rely on the "already processed" check.
SCRIPTS_DIR="$HOME/.openclaw/workspace/skills/email-to-calendar/scripts"
CONFIG_FILE="$HOME/.config/email-to-calendar/config.json"
INDEX_FILE="$HOME/.openclaw/workspace/memory/email-extractions/index.json"
# Start activity logging
"$SCRIPTS_DIR/activity_log.sh" start-session
# Check email mode
EMAIL_MODE=$(jq -r '.email_mode // "forwarded"' "$CONFIG_FILE")
# Check if email was already processed
EMAIL_ID="<the email message ID>"
if jq -e ".extractions[] | select(.email_id == \"$EMAIL_ID\")" "$INDEX_FILE" > /dev/null 2>&1; then
"$SCRIPTS_DIR/activity_log.sh" log-skip --email-id "$EMAIL_ID" --subject "Subject" --reason "Already processed"
exit 0
fi
# Load ignore/auto-create patterns
IGNORE_PATTERNS=$(jq -r '.event_rules.ignore_patterns[]' "$CONFIG_FILE")
AUTO_CREATE_PATTERNS=$(jq -r '.event_rules.auto_create_patterns[]' "$CONFIG_FILE")
DIRECT mode: Scan all unread emails for event indicators (dates, times, meeting keywords).
FORWARDED mode: Only process emails with forwarded indicators (Fwd:, forwarded message headers).
Read the email and extract events as structured data. Include for each event:
URL Extraction Rule: ALWAYS scan the email for URLs and include the most relevant one at the BEGINNING of the event description.
Scan the email for deadline patterns that indicate action is required before the event:
Common Deadline Patterns:
When a deadline is found:
Apply event rules, then present with numbered selection:
I found the following potential events:
1. ~~ELAC Meeting (Feb 2, Monday at 8:15 AM)~~ - SKIP (matches ignore pattern)
2. **Team Offsite (Feb 2-6, Sun-Thu)** - PENDING
3. **Staff Development Day (Feb 12, Wednesday)** - AUTO-CREATE
Reply with numbers to create (e.g., '2, 3'), 'all', or 'none'.
STOP AND WAIT for user response.
After presenting, record pending invites for follow-up reminders:
# Record pending invites using add_pending.sh
"$SCRIPTS_DIR/add_pending.sh" \
--email-id "$EMAIL_ID" \
--email-subject "$EMAIL_SUBJECT" \
--events-json '[{"title":"Event Name","date":"2026-02-15","time":"14:00","status":"pending"}]'
ALWAYS check before creating any event:
# Step 1: Check local tracking first (fast)
TRACKED=$("$SCRIPTS_DIR/lookup_event.sh" --email-id "$EMAIL_ID")
if [ "$(echo "$TRACKED" | jq 'length')" -gt 0 ]; then
EXISTING_EVENT_ID=$(echo "$TRACKED" | jq -r '.[0].event_id')
fi
# Step 2: If not found, try summary match
if [ -z "$EXISTING_EVENT_ID" ]; then
TRACKED=$("$SCRIPTS_DIR/lookup_event.sh" --summary "$EVENT_TITLE")
fi
# Step 3: Fall back to calendar search using wrapper script
if [ -z "$EXISTING_EVENT_ID" ]; then
"$SCRIPTS_DIR/calendar_search.sh" --calendar-id "$CALENDAR_ID" --from "${EVENT_DATE}T00:00:00" --to "${EVENT_DATE}T23:59:59"
fi
Use LLM semantic matching for fuzzy duplicates (e.g., "Team Offsite" vs "Team Offsite 5-6pm").
Use create_event.sh (recommended) - handles date parsing, tracking, and changelog:
# Create new event
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"Event Title" \
"February 11, 2026" \
"9:00 AM" \
"5:00 PM" \
"Description" \
"$ATTENDEE_EMAILS" \
"" \
"$EMAIL_ID"
# Update existing event (pass event_id as 8th parameter)
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"Updated Title" \
"February 11, 2026" \
"10:00 AM" \
"6:00 PM" \
"Updated description" \
"$ATTENDEE_EMAILS" \
"$EXISTING_EVENT_ID" \
"$EMAIL_ID"
For direct gog commands and advanced options, see references/gog-commands.md.
Email disposition (mark as read and/or archive) is handled automatically by create_event.sh based on config settings. No manual step needed - emails are dispositioned after event creation.
To manually disposition an email:
"$SCRIPTS_DIR/disposition_email.sh" --email-id "$EMAIL_ID"
To process calendar reply emails (accepts, declines, tentatives):
"$SCRIPTS_DIR/process_calendar_replies.sh" # Process all
"$SCRIPTS_DIR/process_calendar_replies.sh" --dry-run # Preview only
# End activity session
"$SCRIPTS_DIR/activity_log.sh" end-session
--rrule "RRULE:FREQ=DAILY;COUNT=N"Format event descriptions in this order:
*** ACTION REQUIRED: [ACTION] BY [DATE] ***
Event Link: [URL]
Example WITH deadline:
*** ACTION REQUIRED: GET TICKETS BY FEB 15 ***
Event Link: https://example.com/tickets
Spring Concert at Downtown Theater
Doors open at 7 PM
VIP meet & greet available
Example WITHOUT deadline:
Event Link: https://example.com/event
Spring Concert at Downtown Theater
Doors open at 7 PM
Consider it a duplicate if:
Always update existing events rather than creating duplicates.
When an event has a deadline (RSVP, registration, ticket purchase, etc.), create TWO calendar events:
1. Main Event (as normal, but with warning in description):
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"Spring Concert" \
"March 1, 2026" \
"7:00 PM" \
"10:00 PM" \
"*** ACTION REQUIRED: GET TICKETS BY FEB 15 ***
Event Link: https://example.com/tickets
Spring Concert at Downtown Theater
Doors open at 7 PM" \
"$ATTENDEE_EMAILS" \
"" \
"$EMAIL_ID"
2. Deadline Reminder Event (separate event on the deadline date):
# Use create_event.sh for deadline reminders too (ensures tracking)
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"DEADLINE: Get tickets for Spring Concert" \
"2026-02-15" \
"09:00" \
"09:30" \
"Action required: Get tickets
Event Link: https://example.com/tickets
Main event: Spring Concert on March 1, 2026" \
"" \
"" \
"$EMAIL_ID"
Deadline Event Properties:
DEADLINE: [Action] for [Event Name]When creating events with deadlines, send a notification email to alert the user:
# Load config
CONFIG_FILE="$HOME/.config/email-to-calendar/config.json"
USER_EMAIL=$(jq -r '.deadline_notifications.email_recipient // .gmail_account' "$CONFIG_FILE")
NOTIFICATIONS_ENABLED=$(jq -r '.deadline_notifications.enabled // false' "$CONFIG_FILE")
# Send notification if enabled (using wrapper script)
if [ "$NOTIFICATIONS_ENABLED" = "true" ]; then
"$SCRIPTS_DIR/email_send.sh" \
--to "$USER_EMAIL" \
--subject "ACTION REQUIRED: Get tickets for Spring Concert by Feb 15" \
--body "A calendar event has been created that requires your action.
Event: Spring Concert
Date: March 1, 2026
Deadline: February 15, 2026
Action Required: Get tickets
Link: https://example.com/tickets
Calendar events created:
- Main event: Spring Concert (March 1)
- Deadline reminder: DEADLINE: Get tickets for Spring Concert (Feb 15)
---
This notification was sent by the email-to-calendar skill."
fi
When to send notifications:
deadline_notifications.enabled is true in config# Start session
"$SCRIPTS_DIR/activity_log.sh" start-session
# Log skipped emails
"$SCRIPTS_DIR/activity_log.sh" log-skip --email-id "abc" --subject "Newsletter" --reason "No events"
# Log events
"$SCRIPTS_DIR/activity_log.sh" log-event --email-id "def" --title "Meeting" --action created
# End session
"$SCRIPTS_DIR/activity_log.sh" end-session
# Show recent activity
"$SCRIPTS_DIR/activity_log.sh" show --last 3
Changes can be undone within 24 hours:
# List recent changes
"$SCRIPTS_DIR/changelog.sh" list --last 10
# List undoable changes
"$SCRIPTS_DIR/undo.sh" list
# Undo most recent change
"$SCRIPTS_DIR/undo.sh" last
# Undo specific change
"$SCRIPTS_DIR/undo.sh" --change-id "chg_20260202_143000_001"
Events not immediately actioned are tracked for reminders:
# Add pending invites (after presenting events to user)
"$SCRIPTS_DIR/add_pending.sh" \
--email-id "$EMAIL_ID" \
--email-subject "Party Invite" \
--events-json '[{"title":"Birthday Party","date":"2026-02-15","time":"14:00","status":"pending"}]'
# List pending invites (JSON)
"$SCRIPTS_DIR/list_pending.sh"
# Human-readable summary
"$SCRIPTS_DIR/list_pending.sh" --summary
# Update reminder tracking
"$SCRIPTS_DIR/list_pending.sh" --summary --update-reminded
# Auto-dismiss after 3 ignored reminders
"$SCRIPTS_DIR/list_pending.sh" --summary --auto-dismiss
# Look up by email ID
"$SCRIPTS_DIR/lookup_event.sh" --email-id "19c1c86dcc389443"
# Look up by summary
"$SCRIPTS_DIR/lookup_event.sh" --summary "Staff Development"
# List all tracked events
"$SCRIPTS_DIR/lookup_event.sh" --list
# Validate events exist (removes orphans)
"$SCRIPTS_DIR/lookup_event.sh" --email-id "abc" --validate
| File | Purpose |
|------|---------|
| ~/.config/email-to-calendar/config.json | User configuration |
| ~/.openclaw/workspace/memory/email-extractions/ | Extracted data |
| ~/.openclaw/workspace/memory/email-extractions/index.json | Processing index |
| ~/.openclaw/workspace/memory/email-to-calendar/events.json | Event tracking |
| ~/.openclaw/workspace/memory/email-to-calendar/pending_invites.json | Pending invites |
| ~/.openclaw/workspace/memory/email-to-calendar/activity.json | Activity log |
| ~/.openclaw/workspace/memory/email-to-calendar/changelog.json | Change history |
| ~/.openclaw/workspace/skills/email-to-calendar/scripts/ | Utility scripts |
| ~/.openclaw/workspace/skills/email-to-calendar/MEMORY.md | User preferences |
Handles common formats:
All times assumed local timezone. Time zone info preserved in descriptions.
Generated Mar 1, 2026
HR teams managing company-wide meetings, training sessions, and social events receive numerous email invitations. This skill automates extraction of event details like dates, times, and registration links from these emails, presenting them for quick review and calendar entry to reduce manual entry errors and ensure no events are missed.
Researchers and university staff handle emails about conference submissions, deadlines, and presentation schedules. The skill detects deadlines for paper submissions and extracts event URLs, allowing users to easily add these to their calendars with reminders, streamlining academic planning and compliance with key dates.
Freelancers receive project proposals and meeting invites via email from multiple clients. This skill scans emails for meeting times and project deadlines, presenting them for confirmation before calendar creation, helping freelancers manage their schedules efficiently and avoid double-booking across different projects.
Medical professionals and patients get emails about appointments, follow-ups, and health seminars. The skill extracts appointment details and any associated registration links, enabling quick calendar updates with reminders, which improves attendance rates and reduces no-shows in healthcare settings.
Nonprofit organizers receive emails about fundraising galas, volunteer meetings, and donation deadlines. This skill identifies event dates and RSVP deadlines, presenting them for review to ensure all key dates are tracked in calendars, aiding in event planning and donor engagement efforts.
Offer the skill as a premium subscription service with tiered plans (e.g., basic for individuals, pro for teams, enterprise for organizations). Revenue comes from monthly or annual fees, with features like advanced analytics, priority support, and custom integrations driving higher-tier subscriptions.
Provide a free version with limited features (e.g., basic event extraction) and charge for premium add-ons like deadline detection, undo support, or integration with specific calendar providers. Revenue is generated through one-time purchases or microtransactions for enhanced functionality.
License the skill to businesses for internal use, with custom pricing based on the number of users or email volume. Revenue comes from upfront licensing fees and ongoing maintenance contracts, targeting industries like corporate HR or event management that require robust, scalable solutions.
💬 Integration Tip
Always use the provided wrapper scripts instead of direct gog commands to ensure proper event tracking and avoid duplicates, and check config files for user preferences before processing emails.
Interact with Google Calendar via the Google Calendar API – list upcoming events, create new events, update or delete them. Use this skill when you need programmatic access to your calendar from OpenClaw.
Read, search, and manage Outlook emails and calendar via Microsoft Graph API. Use when the user asks about emails, inbox, Outlook, Microsoft mail, calendar events, or scheduling.
Google Calendar via gcalcli: today-only agenda by default, bounded meaning-first lookup via agenda scans, and fast create/delete with verification--optimized for low tool calls and minimal output.
This skill should be used when interacting with Apple Calendar on macOS. Use it for listing calendars, viewing events, creating/updating/deleting calendar events, and checking availability/free-busy times. Triggers on requests like "check my calendar", "schedule a meeting", "what's on my schedule", "am I free tomorrow", or any calendar-related operations.
Access and manage Google Calendar events with gogcli for cross-calendar agendas, keyword search, and filtered outputs avoiding unwanted calendars like holidays.
Daily morning rollup of important emails and calendar events at 8am with AI-generated summaries