Export calendar events from macOS to ICS files and upload to a SFTP server.
macOS Calendar Exporter is a Python tool specifically designed to export events from Mac calendars. It generates ICS files containing your calendar events and can automatically upload them to an SFTP server, making it perfect e.g. for Home Assistant integration without needing direct API access to calendar services.
- Mac Calendar Access: Uses macOS Swift EventKit to access your calendars
- Timezone Support: Properly handles european timezones (CET/CEST)
- Privacy Mode: Only exports event titles and times by default (descriptions optional)
- SFTP Upload: Automatically uploads to your specified server
- macOS with Calendar app
- Python 3.7+
- Any calendar synced with macOS Calendar app
- Calendar app permissions enabled for Terminal/VSCode
- Clone this repository:
git clone https://github.com/nodomain/mac-calendar-exporter.git
cd mac-calendar-exporter- Use the setup script to install and configure:
./setup-and-run.shThis will:
- Create a virtual environment
- Install required packages
- Configure your settings
- Run an initial export
Edit the .env file to customize your settings:
| Setting | Description | Default | Required |
|---|---|---|---|
CALENDAR_NAMES |
Comma-separated list of calendar names to export | Calendar |
No |
DAYS_AHEAD |
Number of days ahead to export events for | 30 |
No |
ICS_FILE |
Path to output ICS file | ./calendar_export.ics |
No |
ICS_CALENDAR_NAME |
Name of the calendar in the ICS file | Exported Calendar |
No |
INCLUDE_DETAILS |
Include event descriptions and locations | false |
No |
TITLE_LENGTH_LIMIT |
Maximum length for event titles (0 for unlimited) | 36 |
No |
ENABLE_SFTP |
Enable SFTP upload | false |
No |
SFTP_HOST |
SFTP server hostname | Yes, if SFTP enabled | |
SFTP_PORT |
SFTP server port | 22 |
No |
SFTP_USERNAME |
SFTP username | Yes, if SFTP enabled | |
SFTP_PASSWORD |
SFTP password | Yes, if no key file | |
SFTP_KEY_FILE |
Path to SSH private key for SFTP | Yes, if no password | |
SFTP_REMOTE_PATH |
Remote path to upload file to (including filename) | Yes, if SFTP enabled | |
LOG_LEVEL |
Logging level (DEBUG, INFO, WARNING, ERROR) |
INFO |
No |
Run the exporter manually:
./setup-and-run.shOr directly using Python:
python -m mac_calendar_exporter.mainSet up automatic exports on a schedule using cron (more reliable than launchd):
- Use the provided setup script:
./examples/cron-setup.shThis script will:
- Create a cron job that runs every 15 minutes
- Make sure the run-exporter.sh script is executable
- Set up logging to
/tmp/mac-calendar-exporter.log
- Verify the cron job was created:
crontab -l- To edit the schedule manually:
crontab -eThen modify the timing pattern. For example:
*/15 * * * *= every 15 minutes0 */1 * * *= hourly0 4 * * *= daily at 4am
macOS also provides launchd, but it can be more complex to set up correctly:
- Copy the example plist file:
cp examples/cc.nodomain.mac-calendar-exporter.plist ~/Library/LaunchAgents/- Edit the file to use absolute paths:
nano ~/Library/LaunchAgents/cc.nodomain.mac-calendar-exporter.plist- Try loading with:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/cc.nodomain.mac-calendar-exporter.plistNote: Modern macOS versions are more restrictive with launchd jobs. If you encounter issues, use the cron scheduling method instead.
Recent versions of macOS have stricter security restrictions on launchd jobs. If you encounter issues loading the plist file:
-
Try a simple test job first:
cp examples/test-launchd.plist ~/Library/LaunchAgents/ launchctl load ~/Library/LaunchAgents/test-launchd.plist
-
Use full paths in your plist file:
<string>/Users/YOUR_USERNAME/src/mac-calendar-exporter/examples/run-exporter.sh</string>
-
For modern macOS, the legacy
launchctl loadcommand may not work. Try:launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/cc.nodomain.mac-calendar-exporter.plist
-
To see detailed error messages, run as root:
sudo launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/cc.nodomain.mac-calendar-exporter.plist
-
As an alternative to launchd, consider using
crontab:crontab -e # Then add this line to run every 15 minutes: */15 * * * * /Users/YOUR_USERNAME/src/mac-calendar-exporter/examples/run-exporter.sh
Make sure you've granted permission for Terminal/VSCode to access the Calendar app:
- Go to System Settings > Privacy & Security > Calendar
- Enable access for Terminal, VSCode, or other apps you use to run the exporter
- Check that your SFTP server is running and accessible
- Verify credentials (username/password)
- Make sure your SFTP_REMOTE_PATH includes the filename (e.g.,
/path/to/directory/calendar.ics) - Test the connection manually:
sftp username@hostname
If you encounter issues with the launchd job not running correctly:
- Check the error logs in
/tmp/mac-calendar-exporter.errand/tmp/mac-calendar-exporter.out - Make sure the launcher script has the correct permissions:
chmod +x examples/run-exporter.sh - Check that the
WorkingDirectoryin the plist file is set to your actual project path - Verify the Python virtual environment is properly set up and activated by the launcher script
- Try running the launcher script manually to test:
./examples/run-exporter.sh
- Upload the ICS file to your Home Assistant server using SFTP
- Configure the Calendar integration in Home Assistant:
# configuration.yaml
calendar:
- platform: ics
name: Office Calendar
url: /config/www/calendar.icsMIT