Sync busy time from any ICS/iCal calendar to Microsoft Exchange as "Blocked" slots. Works with Google Calendar, iCloud, Outlook.com, Nextcloud, Fastmail, Proton Calendar, or any CalDAV server that publishes an ICS feed.
Requires Python 3.12+.
bash
cd ~/.openclaw/skills/calin
bash install.sh
This creates a Python venv and installs icalendar, msal, recurring-ical-events, and requests.
Add to ~/.calintegration/.env (created by installer with chmod 600):
text
CALINT_ICS_URL=<your-ics-feed-url>
CALINT_MS_CLIENT_ID=<azure-app-client-id>
CALINT_MS_TENANT_ID=<azure-app-tenant-id>
# Optional: sync to a specific Exchange calendar (defaults to primary)
# CALINT_MS_CALENDAR_ID=<calendar-id>
Where to find your ICS URL:
ProviderLocationGoogle CalendarSettings > your calendar > Integrate > "Secret address in iCal format"iCloudCalendar app > right-click calendar > Share > Public Calendar > copy URLOutlook.comSettings > Calendar > Shared calendars > Publish > ICS linkNextcloudCalendar > three-dot menu > Copy subscription linkFastmailSettings > Calendars > Share/export > ICS URL
Azure AD app (free, no client secret needed):
http://localhost:8400bash
cd ~/.openclaw/skills/calin
venv/bin/python main.py setup
This opens a browser for one-time Microsoft login. Tokens are cached locally.
Run these from the skill directory:
CommandWhat it doesvenv/bin/python main.py syncRun one sync cyclevenv/bin/python main.py statusShow last sync time and event countvenv/bin/python main.py clearRemove all synced events from Exchangevenv/bin/python main.py setupRe-run authentication setup
The installer generates a launchd plist for automatic sync every 5 minutes:
bash
cd ~/.openclaw/skills/calin
bash install.sh
cp com.calintegration.sync.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.calintegration.sync.plist
Change detection uses a hash of start time + end time + all-day flag. Only changed events trigger API calls.
~/.calintegration/.env with chmod 600 permissions~/.calintegration/ms_token.json with chmod 600 permissions~/.calintegration/ directory with chmod 700EndpointPurposeAuthYour ICS URL (HTTPS)Read calendar eventsURL contains secret tokenlogin.microsoftonline.comMicrosoft OAuth token exchangePKCE flowgraph.microsoft.com/v1.0Create/update/delete Exchange eventsBearer token
text
ICS Feed (read-only) --> [CalIn on your machine] --> Microsoft Graph API (write)
|
~/.calintegration/ (local state)
No data is sent to any third party. All processing happens locally.