Sync iCloud and Google Calendar

Keep using Apple Calendar. Let your tools and agents use Google Calendar. Sync new events and edits in both directions, with automatic deletion off by default.

icloud-google-calendar-sync is a free, open-source npm package. Run it on your own machine or server. No database or runtime dependencies. MIT licensed.

Managed sync · $5/month / Self-host for free / GitHub / npm / Release notes

Run it yourself, or have me run it

Self-hosted · Free

The full MIT-licensed package. You supply the hosting and scheduler. No paid feature gates.

Managed · $5/month

I set it up and host your scheduled sync. You choose the calendars and sync settings; I keep it running.

Early access, with manual onboarding. Message me on X to get set up.

The code stays open source. You’re paying for setup and hosting.

What syncs

For example: an agent adds “Dinner” at 7 pm in Google Calendar. The next sync copies it to iCloud. Move it to 7:30 in Apple Calendar, and the next sync updates the Google original.

Setup

You need Node.js 20 or later, access to both calendars, a Google Cloud OAuth client, and an Apple app-specific password.

Install the package:

npm install icloud-google-calendar-sync

  1. Connect Google. In Google Cloud, enable both the Calendar API and CalDAV API. Create a Desktop OAuth client, then use the package's auth google command to authorize access.
  2. Connect iCloud. Create an app-specific password at account.apple.com. Use it with your Apple ID email.
  3. Choose calendars. Run discover google and discover icloud, then add each pair to mirror.config.json. Keep credentials in environment variables.
  4. Preview. Run npx icloud-google-calendar-sync sync --dry to see planned changes without writing events.
  5. Sync. Run npx icloud-google-calendar-sync sync, then schedule it. Every five minutes is a reasonable starting point.

The full setup guide includes authentication commands and an example config. You can also run it as an HTTP handler and have a scheduler call your endpoint.

Deletion stays in your hands

By default, removing an original leaves its copy intact. Removing a copy recreates it on the next sync while the original exists. To remove an event completely, pause your scheduler, delete both copies, then resume it.

Two-way deletion is optional: explicitly set propagateDeletes: true on a pair. Leave it unset or false to keep automatic deletion off. This is the default from version 0.3.0.

Questions

Is this a browser extension or a hosted service?

The open-source package is a command-line tool and JavaScript library. Run it yourself, or choose the managed tier to have me host it. This page doesn’t collect calendar credentials; access is arranged during onboarding. Don’t send passwords in an X message.

Why not just add Google to Apple Calendar?

If you only want to see Google events in Apple Calendar, adding the Google account may be enough. This tool copies events between the underlying iCloud and Google calendars, so tools that only access Google can work with them too.

Why do I see duplicate events in Apple Calendar?

If both the Google calendar and its iCloud mirror are visible, you'll see both copies. Uncheck the mirrored Google calendar in Apple Calendar's sidebar. Separate source events with different IDs remain separate; the tool doesn't merge events just because their titles match.

Is sync instant?

No. It runs when you invoke the command or HTTP handler. The schedule you choose determines how often it checks. The default window covers the previous 30 days and the next 365 days.

Does it sync invitations?

It copies event details, not guest lists or invitation responses. Some Google events, including Gmail-generated reservations, reject edits; copying an event doesn't grant write access to its source.

Does it cost anything?

Self-hosting is free under the MIT license; your hosting provider may charge separately. Managed sync is $5/month for setup and hosting, with manual onboarding during early access.

Found a problem? Open a GitHub issue with the version and reproduction steps. Omit credentials and private event details.