We build custom applications 5x faster and cheaper 🚀
Book a Free Consultation
Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.
Integrating Apple Reminders with OpenClaw requires a bridge because Apple does not expose a public server-side Reminders API; the reliable, supported approach is to run client-side code (an iOS or macOS helper app or a Shortcuts flow) that uses EventKit to read/write Reminders with the user’s permission and then forward those events securely to a backend that your OpenClaw skill can consume. Configure authentication explicitly (OAuth or API keys), register and configure the skill in ClawHub to use that backend endpoint (and store secrets as environment variables or service credentials), keep persistent state and queues outside the agent runtime, and instrument logging and retries so you can debug failures by inspecting logs, API responses, and token/scopes.
import EventKit
import Foundation
let store = EKEventStore()
<b>// Request access to reminders</b>
store.requestAccess(to: .reminder) { granted, error in
guard granted, error == nil else {
print("Reminders access denied or error:", error ?? "unknown")
return
}
<b>// Create a predicate for incomplete reminders (example)</b>
let calendars = store.calendars(for: .reminder)
let predicate = store.predicateForReminders(in: calendars)
store.fetchReminders(matching: predicate) { reminders in
guard let reminders = reminders else { return }
let jsonArray: [[String: Any]] = reminders.compactMap { r in
return [
"id": r.calendarItemIdentifier,
"title": r.title ?? "",
"notes": r.notes ?? "",
"completed": r.isCompleted,
"dueDate": r.dueDateComponents?.date?.iso8601String ?? NSNull()
]
}
guard let url = URL(string: "https://api.your-backend.example.com/v1/reminders") else { return }
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
<b>// Use a secure auth scheme (Bearer token / short-lived JWT)</b>
req.setValue("Bearer YOUR_DEVICE_TOKEN", forHTTPHeaderField: "Authorization")
do {
req.httpBody = try JSONSerialization.data(withJSONObject: ["reminders": jsonArray], options: [])
} catch {
print("JSON encoding error:", error)
return
}
let task = URLSession.shared.dataTask(with: req) { data, resp, err in
if let err = err { print("Network error:", err); return }
if let http = resp as? HTTPURLResponse, http.statusCode >= 400 {
print("Server error:", http.statusCode)
} else {
print("Forwarded reminders successfully")
}
}
task.resume()
}
}
const express = require('express')
const bodyParser = require('body-parser')
const crypto = require('crypto')
const app = express()
app.use(bodyParser.json())
<b>// Shared secret to validate device requests (or validate JWT)</b>
const SHARED_SECRET = process.env.DEVICE_SHARED_SECRET
function validateSignature(req) {
<b>// Example: HMAC over payload with shared secret</b>
const sig = req.get('X-Signature') || ''
const body = JSON.stringify(req.body)
const expected = crypto.createHmac('sha256', SHARED_SECRET).update(body).digest('hex')
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
}
app.post('/v1/reminders', (req, res) => {
if (!validateSignature(req)) return res.status(401).send('invalid signature')
const reminders = req.body.reminders || []
<b>// Persist reminders into a database or push into a queue for processing</b>
// db.saveReminders(reminders)
<b>// Option A: Notify OpenClaw by making an explicit API call that your skill expects</b>
<b>// Option B: The OpenClaw skill can poll this backend or consume a message queue (preferred for scale)</b>
res.status(200).json({ received: reminders.length })
})
app.listen(3000, () => console.log('webhook running on :3000'))
Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.
1
Because the OpenClaw ClawConnector typically runs inside the OpenClaw agent/runtime (a non‑UI or extension host) iOS cannot present the Reminders permission prompt. Adding NSRemindersUsageDescription to your project’s Info.plist is necessary but not sufficient—the key must be in the Info.plist of the actual running target (the host app or extension) and the request must be made from a UI‑capable process.
Verify these points before retrying:
let store = EKEventStore()
store.requestAccess(to: .reminder) { granted, error in
<b>//</b> update UI or handle denial on main queue
}
2
Direct answer: Duplicate ClawTask entries appear because the EKReminder's identifier isn't being used as the stable key when creating/updating ClawTask records. If each sync creates a new ClawTask.id (or doesn't persist the EKReminder.identifier into a consistent external key), the SyncEngine can't match existing tasks and inserts duplicates.
3
Direct answer: Map an EKRecurrenceRule’s core components into OpenClaw’s RecurrenceModel fields: frequency (daily/weekly/monthly/yearly), interval, weekday set (byWeekday), month-day or month-position rules (byMonthDay / bySetPosition), and the end condition (count or until/date). Convert Apple alarms into RecurrenceModel.reminders as either absolute timestamps or relative offsets (seconds before/after occurrence). Keep original RRULE/EK metadata in a raw field for fidelity.
Practical mapping:
4
Changes in Apple Reminders don’t reliably trigger ClawSyncDaemon background sync or ClawWebhook because iOS/macOS restricts background execution, Reminders data is managed by Apple (EventKit/iCloud/CloudKit) without a public push hook, and OpenClaw agents run only when explicitly scheduled or authorized. In short: the system doesn’t deliver an immediate, third-party-consumable change event by default, and ClawSyncDaemon/Webhook need explicit configuration and a reachable notification path.
Common causes to verify:
This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â