Plug-In: Events from Clipboard

REQUIRES: macOS 26, iOS 26, iPados 26, visionOS 26 • OmniFocus 4.8+

This plug-in uses the on-device Apple Foundation Models (AFM) frameworks to create new tasks in the OmniFocus Inbox for each of the event descriptions found in text copied to the clipboard.

Related Links: AFM and Omni Automation documentationAFM Plug-In Collection

Event Schema


{ arrayOf: { name: "event-schema", properties: [ { name: "title", isOptional: false }, { name: "description", isOptional: true }, { name: "date", isOptional: false }, { name: "time", isOptional: false }, { name: "location", isOptional: false }, { name: "phone", isOptional: true } ] } }
Party Invite


Greetings Otto, We’re planning a party for Shelia Bradley on 2PM Wednesday, October 15, 2025 at City Hall, 2180 Milvia St, Berkeley, CA 94704. You can call Bill Jacobs at 510-555-1212 for more information. Thank you, Susan Blake
Clipboard Events
  

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.of.events-from-clipboard", "version": "1.0", "description": "Uses the on-device Apple Foundation Models to scan the text on the clipboard for events, and creates new tasks in the Inbox for each.", "label": "AFM • Events from Clipboard", "shortLabel": "Clipboard Events", "paletteLabel": "Clipboard Events", "image": "apple.intelligence" }*/ (() => { const action = new PlugIn.Action(async function(selection, sender){ try { clipboardText = Pasteboard.general.string resultSchema = {arrayOf:{name:"event-schema",properties:[{name:"title",isOptional:false},{name:"description",isOptional:true},{name:"date",isOptional:false},{name:"time",isOptional:false},{name:"location",isOptional:false},{name:"phone",isOptional:true}]}} schema = LanguageModel.Schema.fromJSON(resultSchema) prompt = "Read the provided text and if one or more events are found, return their information as an array of JSON objects, detailing event title, event description, event date, event time, event location, and event phone number, for each found event. The following is the text to scan for events:\n\n" + clipboardText console.log("PROMPT:", prompt) session = new LanguageModel.Session() responseStr = await session.respondWithSchema(prompt, schema) if(responseStr === null){ throw { name: "No Events", message: "No events were found in the clipboard text." } } response = JSON.parse(responseStr) console.log(JSON.stringify(response, null, 2)) fmtr = Formatter.Date.withStyle(Formatter.Date.Style.Short) for (event of response){ console.log(JSON.stringify(event, null, 2)) task = new Task(event.title) task.note = event.description if (event.time !== "Unspecified"){ var dateObjStr = event.date + " at " + event.time } else { var dateObjStr = event.date } task.dueDate = fmtr.dateFromString(dateObjStr) if(event.location !== "Unspecified"){ task.appendStringToNote("\n\n" + "LOCATION: " + event.location) } if(event.phone.length > 0){ task.appendStringToNote("\n\n" + "PHONE: " + event.phone) } } document.windows[0].perspective = Perspective.BuiltIn.Inbox } catch(err){ if(!err.causedByUserCancelling){ console.error(err.name, err.message) new Alert(err.name, err.message).show() } } }); action.validate = function(selection, sender){ compatibility = Device.current.operatingSystemVersion.atLeast(new Version("26")) if (compatibility === false){return false} return (Pasteboard.general.hasStrings) }; return action; })();