Automating Reminders (JXA-first, AppleScript discovery)
Relationship to the macOS automation skill
-
Standalone for Reminders; reuse automating-mac-apps for permissions, shell helpers, and ObjC debugging patterns.
-
PyXA Installation: To use PyXA examples in this skill, see the installation instructions in automating-mac-apps skill (PyXA Installation section).
Core Framing
Reminders works like a database: everything is accessed via specifiers (references to objects). Start by exploring the Reminders dictionary in Script Editor (switch to JavaScript view). Read properties with methods like name() or id() ; write with assignments. Use .whose for efficient server-side filtering to minimize performance overhead. For creation, use constructors + .push() instead of make to avoid errors. Note: no native move command—use copy-delete instead. Priority: 1 (high), 5 (medium), 9 (low), 0 (none). Recurrence/location scripting is limited; use Shortcuts for advanced features.
Quickstart (create + alerts)
First, ensure Reminders permissions are granted (see automating-mac-apps for setup).
JXA:
try { const app = Application("Reminders");
// Get list by name, or fall back to first available list let list; try { list = app.lists.byName("Reminders"); list.name(); // Verify it exists } catch (e) { // Fall back to first available list const lists = app.lists(); if (lists.length === 0) { throw new Error("No reminder lists found"); } list = lists[0]; }
const r = app.Reminder({ name: "Prepare deck", body: "Client review", dueDate: new Date(Date.now() + 3864001000), // 3 days from now remindMeDate: new Date(Date.now() + 2864001000), // Reminder 1 day before due priority: 1 // High priority }); list.reminders.push(r); console.log("Reminder created in '" + list.name() + "'"); } catch (error) { console.error("Failed to create reminder: " + error.message); // Common errors: Permissions denied, list not found }
Note: The list name varies by system. Common names include "Reminders", "Inbox", or localized versions. Using app.lists()[0] as a fallback ensures the script works across different configurations.
PyXA (Recommended Modern Approach):
import PyXA from datetime import datetime, timedelta
try: reminders = PyXA.Reminders()
# Get Inbox list
inbox = reminders.lists().by_name("Inbox")
# Create reminder with due date and reminder alert
reminder = inbox.reminders().push({
"name": "Prepare deck",
"body": "Client review",
"due_date": datetime.now() + timedelta(days=3),
"remind_me_date": datetime.now() + timedelta(days=2),
"priority": 1 # High priority
})
print("Reminder created successfully")
except Exception as error: print(f"Failed to create reminder: {error}") # Common errors: Permissions denied, Inbox list not found
PyObjC with Scripting Bridge:
from ScriptingBridge import SBApplication from Foundation import NSDate
try: reminders = SBApplication.applicationWithBundleIdentifier_("com.apple.Reminders")
# Get Inbox list
lists = reminders.lists()
inbox = None
for lst in lists:
if lst.name() == "Inbox":
inbox = lst
break
if inbox:
# Create reminder
reminder = reminders.classForScriptingClass_("reminder").alloc().init()
reminder.setName_("Prepare deck")
reminder.setBody_("Client review")
# Set due date (3 days from now)
due_date = NSDate.dateWithTimeIntervalSinceNow_(3 * 24 * 60 * 60)
reminder.setDueDate_(due_date)
# Set reminder date (2 days from now)
remind_date = NSDate.dateWithTimeIntervalSinceNow_(2 * 24 * 60 * 60)
reminder.setRemindMeDate_(remind_date)
reminder.setPriority_(1) # High priority
# Add to inbox
inbox.reminders().addObject_(reminder)
print("Reminder created successfully")
else:
print("Inbox list not found")
except Exception as error: print(f"Failed to create reminder: {error}")
Workflow (default)
-
Discover: Open Script Editor, view Reminders dictionary in JavaScript mode to learn available properties.
-
Target List: Get your list by name (e.g., app.lists.byName('Work') ) or ID.
-
Filter: Use .whose for queries (e.g., reminders.whose({name: {_contains: 'meeting'}}) ). For dates, use _lessThan /_greaterThan .
-
Create: Build with Reminder({...}) then add via .push() to avoid errors.
-
Batch Operations: Collect IDs before changes, update/delete in batches.
-
Move: Copy item to new list, then delete original (no native move).
-
Advanced Features: For recurrence/location, call Shortcuts or clone template item.
Example: Filter overdue reminders:
const overdue = list.reminders.whose({dueDate: {_lessThan: new Date()}})();
Validation Checklist
After implementing Reminders automation:
-
Verify Reminders permissions granted
-
Test list access: app.lists().length > 0
-
Confirm reminder creation with valid dates
-
Check reminder appears in Reminders UI
-
Validate .whose queries return expected results
Common Pitfalls
-
Permission errors: Grant Reminders access in System Preferences > Security & Privacy.
-
-10024 errors: Use constructor + push instead of make.
-
Invalid dates: Validate before assignment.
-
Missing lists: Check existence with app.lists.byName(name) before use.
When Not to Use
-
For cross-platform task management (use Todoist API or similar)
-
When complex recurrence patterns are needed (limited JXA support; use Shortcuts)
-
For non-macOS platforms
-
When location-based reminders require programmatic setup (use Shortcuts)
What to Load
Load progressively as needed:
-
Basics: Start with automating-reminders/references/reminders-basics.md for specifiers and simple operations.
-
Recipes: Add automating-reminders/references/reminders-recipes.md for practical create/query/batch examples.
-
Advanced: For complex scenarios, load automating-reminders/references/reminders-advanced.md (priority, limits, debugging).
-
Dictionary: Reference automating-reminders/references/reminders-dictionary.md for full type mappings.
-
PyXA API Reference (complete class/method docs): automating-reminders/references/reminders-pyxa-api-reference.md