Smart calendar and reminders synchronization script for Logseq journals using icalPal on macOS.
- π Calendar Integration: Syncs events from macOS Calendar app
- β° Reminders Support: Syncs reminders from macOS Reminders app
- π― Calendar Filtering: Whitelist specific calendars to include/exclude
- π Smart Parsing: Intelligent parsing of scheduled reminders vs regular events
- π Logseq Integration: Automatic journal entry creation with proper formatting
- ποΈ Backup Protection: Automatic backup of existing content before updates
- π Comprehensive Logging: Detailed logging with DEBUG mode support
- π Native Notifications: macOS notifications on sync completion
- β‘ Incremental Updates: Updates existing agenda sections without losing other content
- π Auto-detect icalPal: Works with Homebrew tap, gem user-install, or any custom path
- macOS (tested on macOS 13+)
- icalPal version 3.9.1+ (4.2.0 recommended via Homebrew tap)
- Logseq with iCloud sync enabled
- Zsh shell (default on modern macOS)
- Ruby with gem support (only if installing icalPal via
gem install)
Recommended β Homebrew tap (most reliable, includes 4.2.0):
brew install ajrosen/tap/icalPalThis installs icalPal (and the lowercase alias icalpal) into /opt/homebrew/bin/, with all Ruby dependencies handled by Homebrew. No need to manage GEM_HOME or PATH.
Alternative β RubyGems (note the case):
gem install icalPal
β οΈ Note: the gem name isicalPal(capital P). The lowercase formicalpalwill fail withERROR: Could not find a valid gem 'icalpal'.
β οΈ icalPal 4.2.0 has a known build issue when installed via plaingem installagainst a Homebrew-managed Ruby (read-only Cellar). If you hitGem::FilePermissionErrororTypeError: no implicit conversion of Gem::FilePermissionError into String, use the Homebrew tap above instead. See upstream issue #54 for details. Versions 3.9.1 through 4.1.1 install cleanly viagem install.
Verify installation:
icalPal --version
# Should report 3.9.1 or later (4.2.0 recommended)# Download directly
curl -O https://raw.githubusercontent.com/nicfab/logseq-calendar-sync/main/logseq-calendar-sync.sh
# Make executable
chmod +x logseq-calendar-sync.sh
# Move to a location of your choice (optional)
mv logseq-calendar-sync.sh ~/bin/icalPal reads default options from ~/.icalpal β note: this is a single file, not a directory or a YAML config. Each line is a CLI flag. To enforce 24-hour times and a stable date format, create the file like this:
cat > ~/.icalpal <<'EOF'
--tf %H:%M
--df %Y-%m-%d
--sort start_date
EOFSee
icalPal --helpfor all available flags.
The script auto-detects icalPal from your PATH and falls back to common gem user-install locations. In most cases you don't need to set anything. If you want to pin a specific binary, edit the script or export the variable before running:
export ICALPAL=/opt/homebrew/bin/icalPalOther variables you may want to customize at the top of the script:
# Logseq vault path (default for iCloud sync)
VAULT="$HOME/Library/Mobile Documents/iCloud~com~logseq~logseq/Documents/journals"
# Calendars to include (case sensitive)
ALLOWED_CALENDARS=("Calendar" "Personal" "Work" "Family")
# Enable debug logging
DEBUG=false
# Log file (default: $HOME/.local/share/logseq-calendar-sync/sync.log)
LOG_FILE="$HOME/.local/share/logseq-calendar-sync/sync.log"If the auto-detection picks the wrong binary, find available installations with:
which icalPal
which icalpal
gem environment | grep "EXECUTABLE DIRECTORY"To find your exact calendar names:
icalPal calendarsTo list reminders/tasks:
# tasksDueBefore is the icalPal 3.9.1+ command (replaces the older 'reminders')
icalPal tasksDueBefore --days 1Use the exact names (case sensitive) in the ALLOWED_CALENDARS array.
./logseq-calendar-sync.shDEBUG=true ./logseq-calendar-sync.shSet up a cron job for automatic syncing:
# Edit crontab
crontab -e
# Add entry for sync every 30 minutes during work hours
*/30 8-18 * * 1-5 /path/to/logseq-calendar-sync.sh
# Or sync every hour
0 * * * * /path/to/logseq-calendar-sync.shCreate a LaunchAgent for better macOS integration:
# Create plist file
cat > ~/Library/LaunchAgents/com.user.logseq-calendar-sync.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.logseq-calendar-sync</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/logseq-calendar-sync.sh</string>
</array>
<key>StartInterval</key>
<integer>1800</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
# Load the agent
launchctl load ~/Library/LaunchAgents/com.user.logseq-calendar-sync.plistThe script creates a structured agenda in your daily Logseq journal:
# Today's Agenda
## Events
- **09:00** - Team Meeting _(Work)_
- **all day event** - Conference _(Work)_
- **14:30** - Doctor Appointment _(Personal)_
## Reminders
- **10:00** - Call client _(Work Tasks)_
- **reminder** - Buy groceries _(Personal)_
- π
Upcoming: 5 reminders in the next 7 days
---
_Last sync: 14:32:15_- Data Retrieval: Uses icalPal to fetch today's events and reminders
- Intelligent Filtering:
- Excludes calendars not in the whitelist
- Separates regular events from scheduled reminders
- Filters out completed and recurring reminders
- Smart Parsing:
- Handles both timed and all-day events
- Cross-references reminder data for accurate list names
- Counts upcoming reminders for the next 7 days
- Journal Integration:
- Creates or updates the "Today's Agenda" section
- Preserves existing journal content
- Creates automatic backups before modifications
- Logging & Notifications: Comprehensive logging with macOS notifications
icalPal 3.9.1+ required
- The script uses the
tasksDueBeforecommand introduced in icalPal 3.9.1. - 4.2.0 is recommended via the Homebrew tap (
brew install ajrosen/tap/icalPal).
gem install icalPal -v 4.2.0 fails with Gem::FilePermissionError or TypeError
This is an upstream bug specific to plain gem install against a Homebrew-managed Ruby β see ajrosen/icalPal#54. Use the Homebrew tap instead:
brew install ajrosen/tap/icalPalicalPal not found
The script auto-detects icalPal and icalpal in PATH and falls back to common gem user-install locations. If it still fails, install via Homebrew or set the ICALPAL variable:
export ICALPAL=/path/to/icalPal
./logseq-calendar-sync.shPermission denied
chmod +x logseq-calendar-sync.shNo events/reminders showing
- Check calendar permissions in System Settings β Privacy & Security β Calendars (and Reminders)
- Verify calendar names in
ALLOWED_CALENDARSmatch exactly (case sensitive) - Run with
DEBUG=trueto see detailed processing
iCloud sync issues
- Ensure Logseq iCloud sync is enabled and working
- Check the
VAULTpath points to your actual Logseq directory
Enable debug logging to troubleshoot issues:
DEBUG=true ./logseq-calendar-sync.shCheck the log file for detailed information:
tail -f ~/.local/share/logseq-calendar-sync/sync.log- Added: auto-detect of
icalPal/icalpalbinary viacommand -v, with fallback to common gem user-install locations. No more hardcoded paths required for typical Homebrew or gem installations. - Added: explicit Homebrew tap installation as the recommended path (
brew install ajrosen/tap/icalPal), which avoids the upstreamgem installbuild failure on Homebrew-managed Ruby. - Added: troubleshooting section with reference to upstream issue #54 for users hitting the 4.2.0 install error.
- Added: optional
ICALPALenvironment variable to override the detected binary. - Changed: default
LOG_FILElocation moved to$HOME/.local/share/logseq-calendar-sync/sync.log(XDG-style state directory) instead of the previous$HOME/Scripts/. - Fixed: documentation of the icalPal config β
~/.icalpalis a single file with one CLI flag per line, not a directory containing a YAML file. - Fixed: corrected the
gem installcommand to use the proper case (icalPal, noticalpal). - Fixed: corrected the upstream icalPal repository link (was pointing to a non-existent repo).
- Fixed: minor whitespace and consistency cleanup.
- BREAKING: Updated for icalPal 3.9.1 compatibility
- Replaced
reminderscommand withtasksDueBefore(icalPal 3.9.1+ requirement) - Updated all reminder-related functions to use new API
- Added version compatibility checks in documentation
- Initial release
- Full calendar and reminders synchronization
- Smart filtering and parsing capabilities
- Automatic backup system
Project developed with the support of Claude by Anthropic, under careful human oversight provided by me.
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes
- Test thoroughly
- Submit a pull request
MIT License
Copyright (c) 2025 Nicola Fabiano
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.