Apple Reminder to Obsidian Sync Script
This blog post dives into a powerful AppleScript for syncing reminders with markdown files. It details how to log sync processes, check for updates in lists, and efficiently create and save markdown files for modified reminders. With clear explanations on leveraging file paths and timestamps, it ...

on run {outputFolderPath}
-- Convert input path to text and ensure it ends with a slash
set outputFolder to outputFolderPath as text
if outputFolder does not end with "/" then
set outputFolder to outputFolder & "/"
end if
-- Path for storing last sync timestamp and logs
set timestampFile to outputFolder & ".last_sync"
set logFile to outputFolder & "sync_log.txt"
-- Initialize logging
my writeToLog(logFile, "Starting sync process...")
my writeToLog(logFile, "Output folder: " & outputFolder)
-- Get last sync time
set lastSync to my getLastSyncTime(timestampFile)
my writeToLog(logFile, "Last sync time: " & (lastSync as text))
tell application "Reminders"
set successCount to 0
set updateCount to 0
set totalLists to count of every list
my writeToLog(logFile, "Found " & totalLists & " total lists")
-- Process each list
repeat with aList in every list
set listName to name of aList
my writeToLog(logFile, "Checking list: " & listName)
-- Check if file exists
set filePath to outputFolder & my getSafeFileName(listName) & ".md"
set needsUpdate to my fileNeedsCreation(filePath)
if not needsUpdate then
-- Check if any reminders in the list have been modified
my writeToLog(logFile, " Checking reminders for modifications...")
repeat with aReminder in every reminder in aList
try
set reminderModDate to modification date of aReminder
if reminderModDate is not missing value and reminderModDate > lastSync then
my writeToLog(logFile, " Found modified reminder: " & (get name of aReminder))
set needsUpdate to true
exit repeat
end if
end try
end repeat
end if
if needsUpdate then
my writeToLog(logFile, " Updates needed - writing file")
-- Create markdown content for this list
set markdown to "# " & listName & return & return
-- Add all reminders in the list
repeat with aReminder in every reminder in aList
set markdown to markdown & "- " & (get name of aReminder) & return
end repeat
-- Save the file
try
my writeToLog(logFile, " Saving to file: " & filePath)
set fileRef to open for access POSIX file filePath with write permission
write markdown to fileRef
close access fileRef
set updateCount to updateCount + 1
my writeToLog(logFile, " Successfully saved file")
on error errorMessage
my writeToLog(logFile, " Error saving " & listName & ": " & errorMessage)
try
close access fileRef
end try
end try
else
my writeToLog(logFile, " No updates needed for this list")
end if
set successCount to successCount + 1
end repeat
-- Save new timestamp
my writeToLog(logFile, "Saving new sync timestamp...")
my saveLastSyncTime(timestampFile, current date)
set finalMessage to "Sync complete: " & updateCount & " lists updated out of " & totalLists & " total lists"
my writeToLog(logFile, finalMessage)
return finalMessage
end tell
end run
-- Write to log file with timestamp
on writeToLog(logFile, logMessage)
set timestamp to do shell script "date '+%Y-%m-%d %H:%M:%S'"
set logLine to timestamp & " " & logMessage & return
try
set fileRef to (open for access POSIX file logFile with write permission) as text
write logLine to fileRef starting at eof
close access fileRef
on error
try
close access fileRef
end try
end try
end writeToLog
-- Get safe filename
on getSafeFileName(thisName)
set safeFileName to my replaceText(thisName, " ", "_")
set safeFileName to my replaceText(safeFileName, "/", "_")
return safeFileName
end getSafeFileName
-- Check if file needs to be created
on fileNeedsCreation(filePath)
try
POSIX file filePath as alias
return false
on error
return true
end try
end fileNeedsCreation
-- Get last sync time from file
on getLastSyncTime(timestampFile)
try
POSIX file timestampFile as alias
set fileRef to open for access POSIX file timestampFile
set timestamp to read fileRef as text
close access fileRef
return date timestamp
on error
my writeToLog(timestampFile, "No previous sync timestamp found - using default date")
return date "Saturday, 1. January 2000 at 12:00:00 AM"
end try
end getLastSyncTime
-- Save last sync time to file
on saveLastSyncTime(timestampFile, syncTime)
try
set fileRef to open for access POSIX file timestampFile with write permission
write (syncTime as text) to fileRef
close access fileRef
on error
my writeToLog(timestampFile, "Error saving timestamp")
end try
end saveLastSyncTime
-- Helper function to replace text
on replaceText(someText, oldItem, newItem)
set AppleScript's text item delimiters to oldItem
set theItems to text items of someText
set AppleScript's text item delimiters to newItem
set newText to theItems as text
set AppleScript's text item delimiters to ""
return newText
end replaceText
Comments ()