A free, secure, and unlimited solution to sync multiple Google calendars into one unified "Busy Time" calendar using Google Apps Script.
The Problem: Active lifestyle, flexible schedule, remote work culture. When you have multiple calendar accounts (I'm juggling 4 at the moment, so I know what I'm talking about), sharing real availability becomes a mess. You need automation that shows your actual busy/free time to both family and teammates without compromising privacy or flexibility.
Why Not Calendly and other SaaS Solutions?
- 🔒 Privacy concerns - Full calendar access to third parties. You have to pray they don't sell your data and actually care about security (usually, they don't)
- 🔗 Not native - Recipients must click external links instead of seeing your schedule directly in their calendar
- 📧 Single calendar limitation - Must choose one "main" calendar for invitations, losing flexibility
- 💰 You have to pay for simple feature just for syncing busy/free time
Why Not Zapier? Complex setup, recurring costs, and limitations when Google Calendar API + Apps Script natively supports everything for free.
How I Got Here:
After trying everything, I found Sync Multiple Google Calendars by karbassi. Loved the concept, but it wasn't suitable for active life with many events and far-ahead planning culture. The delete-and-recreate approach was hitting Google's API limits daily.
So I used Cursor to completely rewrite the algorithm, making it sync each event individually on create/change/delete. Now it handles any busy bee schedule within API limitations.
- ✅ Smart sync by changes only - Updates, creates, or deletes only what changed
- ✅ Year-ahead syncing that works - 365 days future without hitting API limits
- ✅ Multiple source calendars - Sync from unlimited calendars simultaneously
- ✅ Fast & efficient - < 30 seconds typical runtime, uses batch API requests
- ✅ Event-based triggers - Syncs automatically when calendars update (near-instant)
- ✅ Smart filtering - Skips "free" events, preserves locations
- ✅ Free & unlimited - No third-party services or subscriptions
- ✅ Duplicate Prevention: Handles concurrent executions safely with LockService
- ✅ Timezone independent - Works regardless of where you travel
- ✅ Developer-friendly - Open source, well-documented, CLI setup for AI agents
- ✅ No data sharing: Events never leave your Google account
- ✅ Privacy-focused - Runs entirely in your Google account, no external servers
- ✅ You're in control: Open source, modify as needed
- ✅ Secure by default: Uses Google's OAuth for authentication
Choose your setup method:
- UI-Based Setup ← Start here! Browser-only, no command-line tools needed
- CLI-Based Setup ← For developers who want local editing and Git workflow, with clasp, the Apps Script CLI to streamline development with AI coding agents.
The sync uses an intelligent update approach that only modifies events that have actually changed:
- Trigger fires when any source calendar updates (or on schedule)
- Fetch phase: Get events from all source calendars and the busy calendar
- Compare phase: Match events using tracking metadata and compare content
- Categorize phase: Events are categorized as:
- Create: New events that don't exist yet
- Update: Existing events that have changed (title, time, location, etc.)
- Delete: Events removed from source calendars
- Skip: Unchanged events (no API calls needed)
- Execute phase: Only create, update, or delete events that actually changed
- Done: Changes appear in target calendar with minimal API usage
| Data | Synced? | Notes |
|---|---|---|
| Event title | ✅ Yes | With prefix like [personal] |
| Start/end time | ✅ Yes | Preserves original timezone |
| Location | ✅ Yes | For context |
| Conference links | ✅ Yes | Zoom, Meet, etc. |
| Description | ❌ No | Privacy |
| Attendees | ❌ No | Privacy |
| Free/transparent events | ❌ No | Not shown as busy |
For developers interested in how the smart sync works under the hood:
-
Event Tracking: Uses Google Calendar's
extendedProperties.privateto store:sourceCalendarId- Which source calendar the event came fromsourceEventId- Original event ID in the source calendarsourceLastModified- Timestamp for tracking changessyncVersion- Schema version for future compatibility
-
Matching Logic: Creates composite keys (
calendarId:eventId) to match source events with synced events, enabling O(1) lookups during comparison -
Change Detection: Compares these fields to determine if an update is needed:
- Title (with calendar prefix like
[personal]) - Start/end times (including
dateTime,date, andtimeZone) - Location
- Conference data (Zoom, Meet links, etc.)
- Title (with calendar prefix like
-
Duplicate Prevention: Multi-layer deduplication strategy:
- Content-based hashing (calendar + time + title + location)
- In-memory deduplication during categorization
- Live calendar queries for concurrent execution safety
-
Error Handling: Calendar access failures (permissions revoked, calendar deleted) are caught and logged. Events from inaccessible calendars remain in the busy calendar until access is restored, preventing accidental deletion.
-
Pagination Support: Handles calendars with 2,500+ events by processing multiple pages of results from the Calendar API
Having issues? See the detailed troubleshooting sections in the setup guides:
Vibe-coded by: Alex Samson with Cursor AI assistant.
Inspired by: karbassi/sync-multiple-google-calendars by Ali Karbassi - Original concept of syncing multiple calendars with prefixes. The core sync logic has been completely rewritten to use smart updates instead of delete-and-recreate.
BatchRequest library: tanaikech/BatchRequest by Tanaike - Efficient batch API request handling