
Automating Reminders
- 21 installs
- 39 repo stars
- Updated January 14, 2026
- spillwavesolutions/automating-mac-apps-plugin
Helps with ai & agent building tasks during AI-assisted development.
About
automating-reminders is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- automating-reminders
- AI & Agent Building
- AI-coding skill
Automating Reminders by the numbers
- 21 all-time installs (skills.sh)
- Ranked #10,289 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/spillwavesolutions/automating-mac-apps-plugin --skill automating-remindersAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 21 |
|---|---|
| repo stars | ★ 39 |
| Last updated | January 14, 2026 |
| Repository | spillwavesolutions/automating-mac-apps-plugin ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Automating Reminders (JXA-first, AppleScript discovery)
Relationship to the macOS automation skill
- Standalone for Reminders; reuse
automating-mac-appsfor permissions, shell helpers, and ObjC debugging patterns. - PyXA Installation: To use PyXA examples in this skill, see the installation instructions in
automating-mac-appsskill (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() + 3*86400*1000), // 3 days from now
remindMeDate: new Date(Date.now() + 2*86400*1000), // 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 foundPyObjC 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)
1) Discover: Open Script Editor, view Reminders dictionary in JavaScript mode to learn available properties. 2) Target List: Get your list by name (e.g., app.lists.byName('Work')) or ID. 3) Filter: Use .whose for queries (e.g., reminders.whose({name: {_contains: 'meeting'}})). For dates, use _lessThan/_greaterThan. 4) Create: Build with Reminder({...}) then add via .push() to avoid errors. 5) Batch Operations: Collect IDs before changes, update/delete in batches. 6) Move: Copy item to new list, then delete original (no native move). 7) 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
.whosequeries 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.mdfor specifiers and simple operations. - Recipes: Add
automating-reminders/references/reminders-recipes.mdfor 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.mdfor full type mappings. - PyXA API Reference (complete class/method docs):
automating-reminders/references/reminders-pyxa-api-reference.md
Reminders Advanced
Priority map (integers)
0none,1high,5medium,9low. Use integers; strings like "High" fail.
Recurrence/location gaps
- Complex recurrence and geofence triggers are not reliably scriptable via JXA.
- Workarounds:
- Call a Shortcuts workflow that creates recurring/location reminders.
- Keep a template reminder with the desired recurrence and duplicate via copy-delete.
Copy-delete move pattern
- No
movecommand; container is read-only. - Copy props → push clone to target list → delete original.
- Caveats: creationDate resets; UUID changes; subtasks must be handled separately if needed.
Date handling
- Use JS
Dateobjects; bridge converts to localNSDate. - "Date-only" due dates still carry a time; set to midnight or noon by convention.
whose stability
- When changing properties that affect the filter (e.g., completed), resolve IDs first:
const ids = spec.id();then loopbyId.- Batch writes are efficient: setting a property on a specifier sends one Apple Event.
Debugging
- Use
.properties()to inspect real property names/casing. - Common errors:
- -1700 (type mismatch) → missing
()or wrong type. - -1728 (can't get) → specifier failed; check existence.
- -10024 (can't make) → use constructor +
.pushinstead ofmake.
Reminders JXA Basics
Initialize
const app = Application("Reminders");
app.includeStandardAdditions = true; // optional UI/file helpersSpecifier vs data
app.lists→ specifier.app.lists.name()→ array of list names (one IPC).- Access by name/id:
app.lists.byName("Inbox"),app.lists.byId("..."). - Reminder specifier:
app.lists.byName("Inbox").reminders.
Reading
- Batch read:
list.reminders.name();list.reminders.id(). - Filter server-side:
list.reminders.whose({ completed: false }). - Date compare:
reminders.whose({ dueDate: { _lessThan: new Date() }}). - Operators:
_equals,_notEquals,_greaterThan,_lessThan,_beginsWith,_endsWith,_contains,_and,_or.
Writing
- Assign on specifier updates all matches:
reminders.priority = 1. - Use snapshots when modifying filter criteria: fetch
ids = spec.id()then loopbyId.
Creating (stable pattern)
const target = app.lists.byName("Inbox");
const r = app.Reminder({
name: "Draft review",
body: "Include metrics",
priority: 1,
dueDate: new Date()
});
target.reminders.push(r); // commit- Avoid
make;.pushis more reliable.
Moving
- No move command; implement copy-delete.
Reminders Dictionary & Types
Core objects
Application("Reminders")lists(element) →Listreminders(element of list or app) →Reminder
List
- Properties:
name,id,defaultList(app only) - Elements:
reminders
Reminder
name(string, R/W)body(string, R/W)completed(boolean, R/W)completionDate(date, R/W)creationDate(date, R/O)dueDate(date, R/W)remindMeDate(date, R/W)priority(integer, R/W; 0/1/5/9)id(string URL, R/O)container(list, R/O)
Commands
- Create: prefer
app.Reminder({...})+list.reminders.push(obj)(instead ofmake). - Delete:
app.delete(specifier)(batch friendly). - No move: use copy-delete.
Filters
.whoseon collections with operators:_equals,_notEquals,_greaterThan,_lessThan,_beginsWith,_endsWith,_contains,_and,_or.- Access properties on specifiers to batch read/write:
.name(),.id(),.priority = 1.
PyXA Reminders Module API Reference
New in PyXA version 0.0.1 - Control macOS Reminders using JXA-like syntax from Python.
This reference documents all classes, methods, properties, and enums in the PyXA Reminders module. For practical examples and usage patterns, see reminders-recipes.md.
Contents
- Class Hierarchy
- XARemindersApplication
- XARemindersList
- XARemindersReminder
- XARemindersAlarm
- XARemindersRecurrenceRule
- XARemindersAccount
- XARemindersDocument
- XARemindersWindow
- List Classes
- Enumerations
- Quick Reference Tables
---
Class Hierarchy
XAObject
├── XARemindersApplication
│ ├── XARemindersAccount
│ ├── XARemindersList
│ │ └── XARemindersReminder
│ │ ├── XARemindersAlarm
│ │ └── XARemindersRecurrenceRule
│ ├── XARemindersDocument
│ └── XARemindersWindow
└── List Classes
├── XARemindersAccountList
├── XARemindersListList
├── XARemindersReminderList
├── XARemindersAlarmList
└── XARemindersDocumentList---
XARemindersApplication
Bases: XAApplication
Main entry point for interacting with Reminders.app.
Properties
| Property | Type | Description |
|---|---|---|
default_account | XARemindersAccount | The default Reminders account |
default_list | XARemindersList | The default reminder list |
frontmost | bool | Whether Reminders is frontmost application |
name | str | Application name ("Reminders") |
version | str | Application version string |
Methods
accounts(filter=None) -> XARemindersAccountList
Returns a list of Reminders accounts matching the filter.
Parameters:
filter(dict | None) - Property-value pairs to filter by
Example:
import PyXA
app = PyXA.Application("Reminders")
accounts = app.accounts()
for account in accounts:
print(account.name)documents(filter=None) -> XARemindersDocumentList
Returns a list of open documents matching the filter.
Parameters:
filter(dict | None) - Property-value pairs to filter by
lists(filter=None) -> XARemindersListList
Returns reminder lists matching the filter.
Parameters:
filter(dict | None) - Property-value pairs to filter by
Example:
all_lists = app.lists()
inbox = app.lists().by_name("Inbox")reminders(filter=None) -> XARemindersReminderList
Returns all reminders across all lists matching the filter.
Parameters:
filter(dict | None) - Property-value pairs to filter by
Example:
all_reminders = app.reminders()
high_priority = app.reminders().by_priority(1)new_reminder(name='New Reminder', due_date=None, reminder_list=None) -> XARemindersReminder
Creates a new reminder.
Parameters:
name(str) - Name/title of the reminderdue_date(datetime | None) - Due date for the reminderreminder_list(XARemindersList | None) - List to add reminder to (uses default if None)
Returns: The newly created reminder
Example:
from datetime import datetime, timedelta
reminder = app.new_reminder(
name="Call dentist",
due_date=datetime.now() + timedelta(days=1),
reminder_list=app.lists().by_name("Personal")
)new_list(name='New List', color='#FF0000', emblem='symbol0') -> XARemindersList
Creates a new reminder list.
Parameters:
name(str) - Name of the listcolor(str) - Hex color code for the listemblem(str) - Icon/emblem name for the list
Returns: The newly created list
Example:
work_list = app.new_list(
name="Work Tasks",
color="#0000FF",
emblem="symbol1"
)make(specifier, properties=None, data=None)
Creates a new element without adding to any list. Use XAList.push() to add.
Parameters:
specifier(str | ObjectType) - Class name to create ('reminder', 'list')properties(dict) - Properties for the objectdata(Any) - Initialization data
---
XARemindersList
Bases: XAObject
Represents a reminder list with organizational features.
Properties
| Property | Type | Description |
|---|---|---|
id | str | Unique identifier for the list |
name | str | Name of the list |
color | str | Hex color code |
emblem | str | Icon/emblem name |
container | `XARemindersAccount | XARemindersList` |
sharing_status | bool | Whether the list is shared |
sharees | list | List of people the list is shared with |
subscription_url | str | URL for subscribing to the list |
summary | str | Summary description |
properties | dict | All list properties |
Methods
reminders(filter=None) -> XARemindersReminderList
Returns reminders in this list matching the filter.
Parameters:
filter(dict | None) - Property-value pairs to filter by
Example:
inbox = app.lists().by_name("Inbox")
incomplete = inbox.reminders().by_completed(False)show() -> XARemindersList
Shows the list in the Reminders application.
Returns: Self for method chaining
delete() -> None
Deletes the list and all its reminders.
Warning: This action is irreversible.
---
XARemindersReminder
Bases: XAObject
Represents an individual reminder item with full task management capabilities.
Properties
| Property | Type | Description |
|---|---|---|
id | str | Unique identifier |
name | str | Title of the reminder |
body | str | Notes/body text |
notes | str | Additional user notes |
due_date | `datetime | None` |
allday_due_date | `datetime | None` |
all_day | bool | Whether this is an all-day reminder |
completed | bool | Whether the reminder is completed |
completion_date | `datetime | None` |
flagged | bool | Whether the reminder is flagged |
priority | int | Priority level (see table below) |
creation_date | datetime | When the reminder was created |
modification_date | datetime | When the reminder was last modified |
remind_me_date | `datetime | None` |
container | `XARemindersList | XARemindersReminder` |
recurrence_rule | XARemindersRecurrenceRule | Recurrence settings |
url | XAURL | Associated URL |
properties | dict | All reminder properties |
Priority Values
| Value | Meaning |
|---|---|
0 | None (no priority) |
1-4 | High priority |
5 | Medium priority |
6-9 | Low priority |
Methods
alarms(filter=None) -> XARemindersAlarmList
Returns alarms associated with this reminder.
Parameters:
filter(dict | None) - Property-value pairs to filter by
move_to(list: XARemindersList) -> XARemindersReminder
Moves the reminder to a different list.
Parameters:
list(XARemindersList) - Target list to move to
Returns: Self for method chaining
Example:
reminder = inbox.reminders()[0]
reminder.move_to(app.lists().by_name("Work"))show() -> XARemindersReminder
Shows the reminder in the Reminders application.
Returns: Self for method chaining
delete() -> None
Deletes the reminder.
---
XARemindersAlarm
Bases: XAObject
Alarm configuration for reminders with date and location support.
Properties
| Property | Type | Description |
|---|---|---|
id | str | Unique identifier |
date | datetime | Alarm trigger date/time |
location | XALocation | Location for location-based alarm |
proximity_direction | str | 'arriving' or 'departing' for location alarms |
snoozed | bool | Whether the alarm has been snoozed |
Methods
set_date(date: datetime) -> None
Sets the alarm trigger date.
Parameters:
date(datetime) - Date and time to trigger the alarm
set_location(location: XALocation) -> None
Sets a location-based alarm.
Parameters:
location(XALocation) - Location that triggers the alarm
---
XARemindersRecurrenceRule
Bases: XAObject
Manages reminder repetition patterns.
Properties
| Property | Type | Description |
|---|---|---|
frequency | str | 'daily', 'weekly', 'monthly', or 'yearly' |
interval | int | Interval between occurrences |
end_date | datetime | When recurrence ends |
Methods
set_frequency(frequency: Literal['daily', 'weekly', 'monthly', 'yearly']) -> None
Sets the recurrence frequency.
Parameters:
frequency(str) - One of 'daily', 'weekly', 'monthly', 'yearly'
set_interval(interval: int) -> None
Sets the interval between occurrences.
Parameters:
interval(int) - Number of frequency units between occurrences
Example:
# Every 2 weeks
rule.set_frequency('weekly')
rule.set_interval(2)set_end_date(end_date: datetime) -> None
Sets when the recurrence should end.
Parameters:
end_date(datetime) - Date to stop recurring
---
XARemindersAccount
Bases: XAObject
Represents a Reminders account (iCloud, Exchange, etc.).
Properties
| Property | Type | Description |
|---|---|---|
id | str | Unique identifier |
name | str | Account name |
---
XARemindersDocument
Bases: XAObject
File-based document handling for Reminders.
Methods
save() -> XARemindersDocument
Saves the document.
Returns: Self for method chaining
close(save=True) -> None
Closes the document.
Parameters:
save(bool) - Whether to save before closing
---
XARemindersWindow
Bases: XAObject
Window management for Reminders application.
Properties
| Property | Type | Description |
|---|---|---|
document | XARemindersDocument | Document displayed in window |
Methods
lists(filter=None) -> XARemindersListList
Returns lists visible in this window.
reminders(filter=None) -> XARemindersReminderList
Returns reminders visible in this window.
save() -> XARemindersWindow
Saves the window's document.
close(save=True) -> None
Closes the window.
print(properties, show_dialog=True) -> XARemindersWindow
Prints the window content.
---
List Classes
PyXA provides list wrapper classes with fast enumeration and bulk property access.
XARemindersAccountList
Bulk methods for account lists:
accounts = app.accounts()
accounts.id() # -> list[str]
accounts.name() # -> list[str]Filter methods:
accounts.by_id("account-id")
accounts.by_name("iCloud")XARemindersListList
Bulk methods for reminder list collections:
lists = app.lists()
lists.id() # -> list[str]
lists.name() # -> list[str]
lists.color() # -> list[str]
lists.emblem() # -> list[str]
lists.sharing_status() # -> list[bool]
lists.properties() # -> list[dict]Filter methods:
lists.by_id("list-id")
lists.by_name("Work")
lists.by_color("#FF0000")
lists.by_sharing_status(True)XARemindersReminderList
Bulk methods for reminder collections:
reminders = app.reminders()
reminders.id() # -> list[str]
reminders.name() # -> list[str]
reminders.body() # -> list[str]
reminders.due_date() # -> list[datetime | None]
reminders.completed() # -> list[bool]
reminders.completion_date() # -> list[datetime | None]
reminders.flagged() # -> list[bool]
reminders.priority() # -> list[int]
reminders.creation_date() # -> list[datetime]
reminders.modification_date() # -> list[datetime]
reminders.remind_me_date() # -> list[datetime | None]
reminders.all_day() # -> list[bool]
reminders.properties() # -> list[dict]Filter methods:
reminders.by_id("reminder-id")
reminders.by_name("Call dentist")
reminders.by_completed(True)
reminders.by_completed(False)
reminders.by_flagged(True)
reminders.by_priority(1) # High priority
reminders.by_all_day(True)Bulk deletion:
completed = app.reminders().by_completed(True)
completed.delete() # Delete all completed remindersXARemindersAlarmList
Bulk methods for alarm collections:
alarms = reminder.alarms()
alarms.id() # -> list[str]
alarms.date() # -> list[datetime]
alarms.proximity_direction() # -> list[str]
alarms.snoozed() # -> list[bool]Filter methods:
alarms.by_snoozed(True)
alarms.by_proximity_direction("arriving")---
Enumerations
ObjectType
Creatable object types for make() method.
| Value | Description |
|---|---|
DOCUMENT | Document object |
LIST | Reminder list |
REMINDER | Individual reminder |
Usage:
from PyXA.apps.Reminders import XARemindersApplication
# Create using ObjectType enum
reminder = app.make(
XARemindersApplication.ObjectType.REMINDER,
properties={"name": "New Task", "priority": 1}
)Priority Constants
While not a formal enum, priority uses integer values:
| Value | Meaning | Usage |
|---|---|---|
0 | None | No priority set |
1 | High (highest) | priority=1 |
2-4 | High | Alternative high values |
5 | Medium | priority=5 |
6-9 | Low | priority=9 for lowest |
RecurrenceFrequency (String Literals)
| Value | Description |
|---|---|
'daily' | Repeats every day |
'weekly' | Repeats every week |
'monthly' | Repeats every month |
'yearly' | Repeats every year |
ProximityDirection (String Literals)
For location-based alarms:
| Value | Description |
|---|---|
'arriving' | Trigger when arriving at location |
'departing' | Trigger when leaving location |
---
Quick Reference Tables
Common Operations
| Task | Code |
|---|---|
| Get Reminders app | app = PyXA.Application("Reminders") |
| Get all lists | lists = app.lists() |
| Get list by name | inbox = app.lists().by_name("Inbox") |
| Get default list | default = app.default_list |
| Create new list | app.new_list("Work", color="#0000FF") |
| Get all reminders | reminders = app.reminders() |
| Get reminders in list | reminders = inbox.reminders() |
| Create reminder | app.new_reminder("Task", due_date=date) |
| Mark completed | reminder.completed = True |
| Set priority | reminder.priority = 1 |
| Delete reminder | reminder.delete() |
| Move reminder | reminder.move_to(other_list) |
Filtering Patterns
# Get incomplete reminders
incomplete = app.reminders().by_completed(False)
# Get high priority reminders
urgent = app.reminders().by_priority(1)
# Get flagged reminders
flagged = app.reminders().by_flagged(True)
# Get reminders from specific list
work_tasks = app.lists().by_name("Work").reminders()
# Chain filters (get incomplete flagged items)
inbox = app.lists().by_name("Inbox")
important = inbox.reminders().by_completed(False)
flagged_important = [r for r in important if r.flagged]Date Handling
from datetime import datetime, timedelta
# Due tomorrow
due_date = datetime.now() + timedelta(days=1)
# Remind 1 hour before due
remind_date = due_date - timedelta(hours=1)
# Create with dates
reminder = app.new_reminder(
name="Meeting prep",
due_date=due_date,
reminder_list=app.default_list
)
reminder.remind_me_date = remind_dateProperty Access Patterns
# Single object
reminder = app.reminders()[0]
print(reminder.name)
print(reminder.due_date)
print(reminder.completed)
# Bulk access on lists
reminders = app.reminders()
print(reminders.name()) # Returns list[str]
print(reminders.due_date()) # Returns list[datetime | None]
print(reminders.priority()) # Returns list[int]
# Filtering
incomplete = reminders.by_completed(False)
high_priority = reminders.by_priority(1)---
See Also
- PyXA Reminders Documentation - Official PyXA documentation
- reminders-recipes.md - Practical usage examples
- reminders-basics.md - JXA fundamentals
- reminders-advanced.md - Complex automation patterns
Reminders JXA Recipes
List discovery
const app = Application("Reminders");
const lists = app.lists.name(); // ["Inbox", "Personal", ...]Query active tasks in list
const inbox = app.lists.byName("Inbox");
const active = inbox.reminders.whose({ completed: false });
const names = active.name();Overdue → mark high priority in one batch
const now = new Date();
app.reminders.whose({ dueDate: { _lessThan: now }, completed: false }).priority = 1;Create reminder (constructor + push)
const work = app.lists.byName("Work");
const r = app.Reminder({
name: "Finalize Quarterly Review",
body: "Include automation metrics",
priority: 1,
remindMeDate: new Date()
});
work.reminders.push(r);Move reminder (copy-delete pattern)
function moveReminder(reminder, targetList) {
const props = {
name: reminder.name(),
body: reminder.body(),
priority: reminder.priority(),
dueDate: reminder.dueDate(),
remindMeDate: reminder.remindMeDate(),
completed: reminder.completed()
};
const clone = app.Reminder(props);
targetList.reminders.push(clone);
reminder.delete();
}
const src = app.reminders.byName("Finalize Quarterly Review");
moveReminder(src, app.lists.byName("Archive"));Delete completed items (batch)
const done = app.reminders.whose({ completed: true });
app.delete(done);Snapshot then mutate
const dueToday = app.reminders.whose({
dueDate: { _lessThan: new Date(new Date().setHours(23,59,59,999)) },
completed: false
});
const ids = dueToday.id();
ids.forEach(id => {
const r = app.reminders.byId(id);
r.completed = true;
});Create follow-ups from transcript text (pattern)
- Upstream meeting workflow can pass parsed action items from Voice Memos transcript into reminders:
const items = [
"Send recap to team",
"Draft proposal v2",
"Schedule follow-up demo"
];
const list = app.lists.byName("Follow-ups");
items.forEach(name => {
const r = app.Reminder({ name });
list.reminders.push(r);
});- Keep transcript parsing upstream; Reminders should receive clean action strings.
#!/usr/bin/env python3
"""
Complete Reminders Script - PyXA Implementation
Marks reminders as completed based on criteria
Usage: python complete_reminders.py "search pattern" [--list "List Name"] [--dry-run]
"""
import sys
import PyXA
def complete_reminders(search_pattern, list_name=None, dry_run=False):
"""Mark reminders as completed based on search pattern"""
try:
reminders_app = PyXA.Application("Reminders")
all_lists = reminders_app.lists()
completed_count = 0
found_count = 0
for lst in all_lists:
# Skip if specific list requested and this isn't it
if list_name and lst.name != list_name:
continue
list_reminders = lst.reminders()
for reminder in list_reminders:
title = reminder.name() or ""
# Check if reminder matches search pattern and is not already completed
if (search_pattern.lower() in title.lower() and
not reminder.completed()):
found_count += 1
if dry_run:
print(f"Would complete: '{title}' in {lst.name}")
else:
try:
reminder.completed = True
completed_count += 1
print(f"Completed: '{title}' in {lst.name}")
except Exception as e:
print(f"Error completing '{title}': {e}")
if dry_run:
print(f"\nDry run: Found {found_count} matching incomplete reminders")
else:
print(f"\nCompleted {completed_count} reminders matching '{search_pattern}'")
return completed_count if not dry_run else found_count
except Exception as e:
print(f"Error completing reminders: {e}")
return 0
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python complete_reminders.py 'search pattern' [--list 'List Name'] [--dry-run]")
sys.exit(1)
search_pattern = sys.argv[1]
list_name = None
dry_run = False
# Parse optional arguments
for arg in sys.argv[2:]:
if arg.startswith('--list='):
list_name = arg.split('=', 1)[1]
elif arg == '--list' and len(sys.argv) > sys.argv.index(arg) + 1:
list_name = sys.argv[sys.argv.index(arg) + 1]
elif arg == '--dry-run':
dry_run = True
count = complete_reminders(search_pattern, list_name, dry_run)
sys.exit(0 if count > 0 else 1)#!/usr/bin/env osascript -l JavaScript
/**
* create_reminder.js - Create a reminder in Apple Reminders via JXA
*
* Usage:
* osascript -l JavaScript create_reminder.js
*
* This script creates a reminder with a timed alert. It uses a fallback
* approach to find an available list since list names vary by system
* (e.g., "Reminders", "Inbox", or localized names).
*/
function getList(app, preferredName) {
// Try to get list by preferred name first
try {
const list = app.lists.byName(preferredName);
list.name(); // Verify it exists
return list;
} catch (e) {
// Fall back to first available list
const lists = app.lists();
if (lists.length === 0) {
throw new Error("No reminder lists found");
}
return lists[0];
}
}
function createReminder(options) {
const app = Application("Reminders");
const defaults = {
listName: "Reminders",
name: "New Reminder",
body: "",
minutesFromNow: 5,
priority: 0 // 0=none, 1=high, 5=medium, 9=low
};
const opts = Object.assign({}, defaults, options);
try {
const list = getList(app, opts.listName);
// Calculate reminder time
const reminderTime = new Date(Date.now() + opts.minutesFromNow * 60 * 1000);
const reminderProps = {
name: opts.name,
remindMeDate: reminderTime
};
if (opts.body) {
reminderProps.body = opts.body;
}
if (opts.priority > 0) {
reminderProps.priority = opts.priority;
}
if (opts.dueDate) {
reminderProps.dueDate = opts.dueDate;
}
const reminder = app.Reminder(reminderProps);
list.reminders.push(reminder);
return {
success: true,
list: list.name(),
reminderTime: reminderTime.toLocaleString(),
name: opts.name
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Example usage - create a reminder for 5 minutes from now
function run() {
const result = createReminder({
name: "Call back 555-555-5555",
body: "Return phone call",
minutesFromNow: 5,
priority: 1 // High priority
});
if (result.success) {
return `Reminder "${result.name}" created in '${result.list}' for ${result.reminderTime}`;
} else {
return `Error: ${result.error}`;
}
}
#!/usr/bin/env python3
"""
Create Reminder Script - PyXA Implementation
Creates a new reminder in Reminders app
Usage: python create_reminder.py "Reminder Title" ["due date"] ["list name"]
"""
import sys
from datetime import datetime, timedelta
import PyXA
def create_reminder(title, due_date_str=None, list_name="Reminders"):
"""Create a new reminder"""
try:
reminders = PyXA.Application("Reminders")
# Parse due date if provided
due_date = None
if due_date_str:
try:
due_date = datetime.fromisoformat(due_date_str)
except:
print(f"Invalid date format: {due_date_str}. Use YYYY-MM-DD or YYYY-MM-DD HH:MM")
return False
# Find or create list
target_list = None
lists = reminders.lists()
for lst in lists:
if lst.name == list_name:
target_list = lst
break
if not target_list:
# Create new list
target_list = reminders.new_list(list_name)
# Create reminder
reminder_data = {"name": title}
if due_date:
reminder_data["due_date"] = due_date
reminder = target_list.reminders().push(reminder_data)
print(f"Created reminder: '{title}'")
if due_date:
print(f"Due: {due_date.strftime('%Y-%m-%d %H:%M')}")
print(f"List: {list_name}")
return True
except Exception as e:
print(f"Error creating reminder: {e}")
return False
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python create_reminder.py 'Reminder Title' ['YYYY-MM-DD'] ['List Name']")
sys.exit(1)
title = sys.argv[1]
due_date = sys.argv[2] if len(sys.argv) > 2 else None
list_name = sys.argv[3] if len(sys.argv) > 3 else "Reminders"
success = create_reminder(title, due_date, list_name)
sys.exit(0 if success else 1)#!/usr/bin/env python3
"""
List Reminders Script - PyXA Implementation
Lists reminders from Reminders app with filtering options
Usage: python list_reminders.py [--list "List Name"] [--completed] [--overdue]
"""
import sys
import PyXA
from datetime import datetime
def list_reminders(list_name=None, show_completed=False, show_overdue_only=False):
"""List reminders with optional filtering"""
try:
reminders_app = PyXA.Application("Reminders")
all_lists = reminders_app.lists()
total_reminders = 0
for lst in all_lists:
# Skip if specific list requested and this isn't it
if list_name and lst.name != list_name:
continue
list_reminders = lst.reminders()
filtered_reminders = []
for reminder in list_reminders:
# Filter by completion status
if not show_completed and reminder.completed():
continue
# Filter by overdue status
if show_overdue_only:
due_date = reminder.due_date()
if not due_date or due_date > datetime.now():
continue
filtered_reminders.append(reminder)
if filtered_reminders:
print(f"\n📝 {lst.name} ({len(filtered_reminders)} reminders):")
print("-" * 50)
for reminder in sorted(filtered_reminders,
key=lambda r: r.due_date() or datetime.max):
title = reminder.name()
completed = "✅" if reminder.completed() else "⏳"
due_date = reminder.due_date()
print(f" {completed} {title}")
if due_date:
if due_date < datetime.now() and not reminder.completed():
print(f" 🚨 Overdue: {due_date.strftime('%Y-%m-%d %H:%M')}")
else:
print(f" 📅 Due: {due_date.strftime('%Y-%m-%d %H:%M')}")
total_reminders += 1
if total_reminders == 0:
filters = []
if list_name:
filters.append(f"list '{list_name}'")
if not show_completed:
filters.append("incomplete only")
if show_overdue_only:
filters.append("overdue only")
filter_desc = f" ({', '.join(filters)})" if filters else ""
print(f"No reminders found{filter_desc}")
else:
print(f"\n📊 Total: {total_reminders} reminders")
return total_reminders
except Exception as e:
print(f"Error listing reminders: {e}")
return 0
if __name__ == "__main__":
list_name = None
show_completed = False
show_overdue = False
# Parse arguments
for arg in sys.argv[1:]:
if arg.startswith('--list='):
list_name = arg.split('=', 1)[1]
elif arg == '--list' and len(sys.argv) > sys.argv.index(arg) + 1:
list_name = sys.argv[sys.argv.index(arg) + 1]
elif arg == '--completed':
show_completed = True
elif arg == '--overdue':
show_overdue = True
count = list_reminders(list_name, show_completed, show_overdue)
sys.exit(0 if count >= 0 else 1)#!/usr/bin/env python3
"""Trigger Reminders Automation prompt via a read-only AppleScript call."""
import subprocess
import sys
from textwrap import dedent
APPLESCRIPT = dedent(
"""
tell application "Reminders"
activate
set listNames to name of every list
return "Lists: " & (listNames as text)
end tell
"""
)
def main() -> int:
print("Requesting Automation permission for Reminders...")
result = subprocess.run(
["osascript", "-e", APPLESCRIPT],
capture_output=True,
text=True,
)
if result.stdout.strip():
print(result.stdout.strip())
if result.returncode != 0:
print(result.stderr.strip() or "Reminders check failed without error output.")
return result.returncode
if __name__ == "__main__":
sys.exit(main())
#!/usr/bin/env bash
# Trigger Reminders Automation prompt via a read-only AppleScript call.
set -euo pipefail
echo "Requesting Automation permission for Reminders..."
osascript -e 'tell application "Reminders"
activate
set listNames to name of every list
return "Lists: " & (listNames as text)
end tell'
echo "Reminders responded. If prompted, grant Terminal/Python permission."