Automation & Scripting

RSS for tag

Learn about scripting languages and automation frameworks available on the platform to automate repetitive tasks.

Automation & Scripting Documentation

Posts under Automation & Scripting subtopic

Post

Replies

Boosts

Views

Activity

Can my users get siri to use my app without specifying the app name?
I have a food logging app. I want my users to be able to say something like: "Hey siri, log chicken and rice for lunch" But appshortcuts provider is forcing me to add the name of the app to the phrase so it becomes: "Hey siri, log chicken and rice for lunch in FoodLogApp". After running a quick survey, I've found that many users dislike having to say the name of the app, it makes it too cumbersome. My question is: Is there a plan from apple 2026 so the users can converse with Siri and apps more naturally without having to say the name of the app? If so, is it already in Beta and can you point me towards it? @available(iOS 17.0, *) struct LogMealIntent: AppIntent { static var title: LocalizedStringResource = "Log Meal" static var description: LocalizedStringResource = "Log a meal" func perform() async throws -> some IntentResult { return .result() } } @available(iOS 17.0, *) struct LogMealShortcutsProvider: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: LogMealIntent(), phrases: [ "Log chicken and rice for lunch in \(.applicationName)", ], shortTitle: "Log meal", systemImageName: "mic.fill" ) } }
1
0
32
1w
Siri Shortcut Passes NSUserActivity Object Twice
In my app, when invoking a Shortcut via Siri, the application(_:continueUserActivity:restorationHandler:) method in AppDelegate is called twice. When I debug, both NSUserActivity objects are identical. However, when I run the same Shortcut by tapping it manually, the method is only called once as expected. Has anyone experienced this issue? How can I prevent Siri Shortcuts from delivering the same NSUserActivity twice?
3
0
54
1w
Can an app be seen as a trigger device on Homekit?
Suppose I want to create a dummy switch for HomeKit using an app. I run the app for the first time, the app registers itself as a dummy switch and all accessories see the app as an OFF switch. The following day, I run the app again and turn the dummy switch ON. All accessories that were monitoring the status of that switch, adjusted themselves accordingly, run their automations and so on. Can an app do that in iOS, macOS, iPadOS, watchOS, etc.? If so, can you point me in the right direction?
1
0
706
Oct ’24
Shortcuts app in macOS has no logic
I'm trying to study music theory and I need a simple series of tasks to be automated to avoid wasting time on repetitive actions. That's what the Shortcuts app is for, but the actions it comes with are either severely mislabeled, or just don't work. I tried to ask for this in some regular forums and nobody could give me a simple answer, so I figured this is something that developers probably know. I just need four PDFs to open in Preview, their windows moved to one of my monitors, and then be tiled in four equal sizes, with the order determined by me. Sounds easy, doesn't it? But I've been trying to accomplish this for over a year in Shortcuts and even Automator, but at best I can get halfway there. I've also noticed that the Shortcuts I had prepared are running awfully slow. I'm on a Mac Studio M1 Ultra, and these PDFs are less than 10 MB each, three of them are less than 5 MB. These used to open almost instantly, but now the first one opens, then 3-5 seconds later the next one opens and so on. As for the window tiling, at best it's tiling three of the windows correctly, but the other one that should tile on the top left, doesn't resize to the quarter of the screen. But worst of all, they are supposed to move to one of the monitors and do the tiling there, but they all open and tile on the main monitor. So this is one I started today from scratch: Logically speaking, this should work. But either I'm not following the logic with which Shortcuts was designed, or Shortcuts just doesn't work very well. I'm hoping it's just that I don't follow the logic, but the help is not very helpful. It's rather scant, and other than that, I can't find something that will give me more information about how it works. I'm on the current version of Sonoma, but this was the same in the previous macOS. I doubt it changed at all in Sequoia. Sorry if I'm asking this in a developer forum, but I figured it's the place where I can finally get some answers after over a year of trial and error and online searching and getting nowhere.
3
0
713
Oct ’24
Correctly using NSAppleScript for Mail.app plugin
Context I'm working on a Mail.app plugin. I would like to disseminate plugin via AppStore. I'm interested in exposing a functionality to user enabling user to choose if plugin should apply to all or selected email account. My intention is to use AppleScript to get a list of available email accounts and expose the list to the end-user via SwiftUI Sourcing account information Apple Script I'm using the following AppleScript tell application "Mail" set accountDict to {} repeat with acc in accounts set accName to name of acc set accEmails to email addresses of acc set accountDict's end to {accName:accEmails} end repeat return accountDict end tell The above generates expected results when executed using Script Editor. Swift Implementation This is still incomplete but shows the overall plan. // // EmailAccounts.swift import Foundation enum EmailScriptError: Error { case scriptExecutionError(String) } struct EmailAccounts { func getAccountNames() -> [String]? { let appleScriptSource = """ tell application "Mail" set accountDict to {} repeat with acc in accounts set accName to name of acc set accEmails to email addresses of acc set accountDict's end to {accName:accEmails} end repeat return accountDict end tell """ var error: NSDictionary? var accountNames: [String] = [] // Create script object, exit if fails guard let scriptObject = NSAppleScript(source: appleScriptSource) else { return nil } // Execute script and store results, nil on error let scriptResult = scriptObject.executeAndReturnError(&error) if error != nil { return nil } // Iterate over results for index in 0...scriptResult.numberOfItems { if let resultEntry = scriptResult.atIndex(index) { if let resultString = resultEntry.stringValue { // Process result handling // accountNames.append(resultString) } } } return accountNames } } Questions Most important one, can I deploy the App on the App Store and use NSAppleScript as shown above? If yes can I use the script in the manner shown above or will I need to store the script in User > Library > Application Scripts location and source it from there. This is outlined in the Scripting from a Sandbox article by Craig Hockenberry, which I cannot link due to being hosted within a not-permitted domain. If yes what entitlements I need to give to the target. I understand that I wouldn't be able to use ScriptingBridge, which feels more robust but wouldn't permit me to deploy the app on the AppStore. My key objective is to programatically identify mail accounts available to Mail.app, if there is a wiser / easier way of doing that I would be more than receptive.
2
0
810
Oct ’24
Getting path of deleted item from Scripting Bridge SBObject in Swift
In the Swift function at the end of this post, I use Scripting Bridge to have Finder delete a path. The variable result is a SBObject returned by the delete() function. I know that result somehow contains the new path of the deleted item in the trash folder, but I don't know how to nicely extract it as a single String. If I print(String(describing: result)), I get output like: <SBObject @0x0123456789ab: <class 'appf'> "AppName.app" of <class 'cfol'> ".Trash" of <class 'cfol'> "user" of <class 'cfol'> "Users" of startupDisk of application "Finder" (822)> Is there any way to obtain the String "/Users/user/.Trash/AppName.app" from result without having to perform string parsing on the above output? The Finder* types in the code below are from https://github.com/tingraldi/SwiftScripting/blob/master/Frameworks/FinderScripting/FinderScripting/Finder.swift func trash(path: String) throws { guard let finder: FinderApplication = SBApplication(bundleIdentifier: "com.apple.finder") else { throw runtimeError("Failed to obtain Finder access: com.apple.finder does not exist") } guard let items = finder.items else { throw runtimeError("Failed to obtain Finder access: finder.items does not exist") } let object = items().object(atLocation: URL(fileURLWithPath: path)) guard let item = object as? FinderItem else { throw runtimeError( """ Failed to obtain Finder access: finder.items().object(atLocation: URL(fileURLWithPath: \ \"\(path)\") is a '\(type(of: object))' that does not conform to 'FinderItem' """ ) } guard let delete = item.delete else { throw runtimeError("Failed to obtain Finder access: FinderItem.delete does not exist") } let result = delete() }
2
0
673
Oct ’24
Missing "add transaction" shortcut
I keep seeing that there's a shortcut called "Add transaction" where whenever a card was tapped from apple wallet, you can add some automation. https://support.apple.com/en-au/guide/shortcuts/apd65c67538a/7.0/ios/17.0 However, I cannot for the life of me find this option on my iphone 13 ios 17.6.1 All I can find when I go to the shortcuts app and search for transactions or apple wallet, I get 2 options to send/receive payments which isn't what I'm looking for. Did apple remove this shortcut??
1
0
661
Oct ’24
Writing an app to help install DMGs/PKGs
Hi all I work in music production, the way the tools are set up is we use many tools (plugins) inside one larger app (a DAW), as such the process of setting up a machine to do work involves running 50-100+ different installers to get all tools installed. I'd like to write a small app that will automate the install process. I have a working approach for this where all steps work when run individually in terminal or via AppleScript, but as I create one unifying app I am running into an issue where any app I create in Xcode is not allowed to mount DMGs or give commands to terminal (even if I make a build app package and move it out of the Xcode directory, and even if I give explicit permission via settings) and if I try to have the app try to do the works via terminal it also can't seem to access terminal. I think there are some limitations I'm missing here. Any tips?
2
0
564
Nov ’24
Help with app automation permissions
Hi, I am trying to make an app that uses Spotify's web API to play songs. For the web API to work, Spotify needs to be running, and my Mac has to be recognized as an active device. For my Mac to be recognized as an active device, I have to play a song for a very short amount of time (under a second). I want to make my app automatically do that on launch. I already wrote the AppleScript in Automator, and it worked. It successfully launched Spotify, played a song for 0.5 seconds, then hid itself. After writing the code, I tried to implement it into my app to run on startup, but I ran into a problem. The app only started the Spotify app on my mac, and gave me an error that told me it wasn't running. What do I do? Is this an issue with the permissions of the app, or something else? I have given the app the "Apple Events" entitlement. This is the error I am getting. Note that the app opens Spotify, after which it gives me this. Error: { NSAppleScriptErrorAppName = Spotify; NSAppleScriptErrorBriefMessage = "Application isn\U2019t running."; NSAppleScriptErrorMessage = "Spotify got an error: Application isn\U2019t running."; NSAppleScriptErrorNumber = "-600"; NSAppleScriptErrorRange = "NSRange: {31, 8}"; } This is the function I am trying to use to do the actions with Spotify: func runAppleScript() { let appleScript = """ tell application "Spotify" activate if player state is not playing then play track "spotify:track:5XSKC4d0y0DfcGbvDOiL93" delay 1 pause end if end tell tell application "System Events" tell process "Spotify" set frontmost to true delay 1 keystroke "h" using {command down} end tell end tell """ var error: NSDictionary? if let scriptObject = NSAppleScript(source: appleScript) { scriptObject.executeAndReturnError(&error) } if let error = error { print("Error: \(error)") } } Any help is appreciated. Thank you in advance.
1
0
404
Jan ’25
EntityStringQuery does not show variable menu in Shortcuts app
(Public dupe of FB16477656) The Shortcuts app allows you to parameterise the input for an action using variables or allowing "Ask every time". This option DOES NOT show when conforming my AppEntity.defaultQuery Struct to EntityStringQuery: But it DOES shows when confirming to EntityQuery: As discussed on this forum post (or FB13253161) my AppEntity.defaultQuery HAS TO confirm to EntityStringQuery to allow for searching by String from Siri Voice input. To summarise: With EntityQuery: My Intent looks like it supports variables via the Shortcuts app. But will end up in an endless loop because there is no entities(matching string: String) function. This will allow me to choose an item via the Shorcuts.app UI With EntityStringQuery: My Intent does not support variables via the Shortcuts app. I am not allows to choose an item via the Shorcuts.app UI. Even weirder, if i set up the shortcut with using a build with EntityQuery and then do another build with EntityStringQuery it works as expected. Code: /* Works with Siri to find a match, doesn't show "Ask every time" */ public struct WidgetStationQuery: EntityStringQuery { public init() { } public func entities(matching string: String) async throws -> [Station] { let stations = [Station(id: "car", name: "car"), Station(id: "bike", name: "bike")] return stations.filter { $0.id.lowercased() == string.lowercased() } } public func entities(for identifiers: [Station.ID]) async throws -> [Station] { let stations = [Station(id: "car", name: "car"), Station(id: "bike", name: "bike")] return stations.filter { identifiers.contains($0.id.lowercased()) } } public func suggestedEntities() async throws -> [Station] { return [Station(id: "car", name: "car"), Station(id: "bike", name: "bike")] } public func defaultResult() async -> Station? { try? await suggestedEntities().first } } /* DOES NOT work with Siri to find a match, but Shortcuts shows "Ask every time" */ public struct WidgetBrokenStationQuery: EntityQuery { public init() { } public func entities(matching string: String) async throws -> [Station] { let stations = [Station(id: "car", name: "car"), Station(id: "bike", name: "bike")] return stations.filter { $0.id.lowercased() == string.lowercased() } } public func entities(for identifiers: [Station.ID]) async throws -> [Station] { let stations = [Station(id: "car", name: "car"), Station(id: "bike", name: "bike")] return stations.filter { identifiers.contains($0.id.lowercased()) } } public func suggestedEntities() async throws -> [Station] { return [Station(id: "car", name: "car"), Station(id: "bike", name: "bike")] } public func defaultResult() async -> Station? { try? await suggestedEntities().first } }```
2
0
364
Jun ’25
"Not authorized to send Apple events to Terminal
We are trying to open an application "xyz.app" It worked fine until 15.1.1 versions. But facing issues with 15.2 and 15.3 The application is working fine when we navigate to xyz.app/Contents/MacOS/ and run applet in this directory. But the error "Not authorized to send Apple events to Terminal" occurs when we are trying to open the app directly. We have tried with all the available solutions like giving full disk access to terminal and application, adding my application to automation in privacy and security tabs in settings. Any help would be appreciated. Thanks!
1
0
412
Feb ’25
Automator error when running Watch Me Do-created script
Hi everyone, I'm trying to use Automator to batch process PDF files. I have hundreds of academic journal article PDFs whose page sizes vary from 5x7 inches to A4 format (8.27 x 11.69 inches). I want to scale all the PDFs to US Letter size (8.5 x 11.0 inches) such that smaller originals remain 100% scale but are centered on the larger page and larger originals are scaled down to fit the page. Manually opening a PDF in Preview.app, scaling it to US Letter paper, and using the Save as PDF option is producing the desired output for me. I captured my workflow using the Watch Me Do action in Automator, then adjusted it into the following AppleScript. -- a Get Specified Finder Items action to specify the input PDFs precedes this script on run {input, parameters} repeat with filePath in input -- Open the file in Preview tell application "Preview" open filePath activate end tell -- Give Preview some time to open the file delay 2.0 -- Press ⌘P set timeoutSeconds to 0.25 set uiScript to "keystroke \"p\" using command down" my doWithTimeout(uiScript, timeoutSeconds) -- Click the “Scale to Fit:” radio button. delay 2.0 set timeoutSeconds to 2.0 set uiScript to "click radio button \"Scale to Fit:\" of radio group 1 of group 1 of group 2 of scroll area 2 of splitter group 1 of sheet 1 of window 1 of application process \"Preview\"" my doWithTimeout(uiScript, timeoutSeconds) -- Click the “&lt;fill in title&gt;” menu button. delay 4.0 set timeoutSeconds to 2.000000 set uiScript to "click menu button 1 of group 2 of splitter group 1 of sheet 1 of window 1 of application process \"Preview\"" my doWithTimeout( uiScript, timeoutSeconds ) -- Save as PDF… delay 2.0 set timeoutSeconds to 2.0 set uiScript to "click menu item 2 of menu 1 of splitter group 1 of sheet 1 of window 1 of application process \"Preview\"" my doWithTimeout(uiScript, timeoutSeconds) -- Click the “Save” button. delay 8.0 set timeoutSeconds to 2.0 set uiScript to "click UI Element \"Save\" of sheet 1 of sheet 1 of window 1 of application process \"Preview\"" my doWithTimeout(uiScript, timeoutSeconds) -- Press ⌘W to close the file delay 0.25 set timeoutSeconds to 2.0 set uiScript to "keystroke \"w\" using command down" my doWithTimeout(uiScript, timeoutSeconds) end repeat return input end run on doWithTimeout(uiScript, timeoutSeconds) set endDate to (current date) + timeoutSeconds repeat try run script "tell application \"System Events\" " &amp; uiScript &amp; " end tell" exit repeat on error errorMessage if ((current date) &gt; endDate) then error "Can not " &amp; uiScript end if end try end repeat end doWithTimeout My problem arises at the Save as PDF step. When this action runs, I see the PDF menu pop open: but the Save as PDF... menu item doesn't get clicked. Instead, I get an error: Can anyone advise on how to overcome this error?
1
0
363
Feb ’25
Add the ability to remove/delete chats in the ChatGPT app using shortcuts
So Recently I’ve been making shortcuts and I noticed that I can prompt chatgpt with shortcuts to add extra functionality, I like this idea but there is 1 flaw with it and that is there is no ability to remove chats automatically, I suppose this would be fine except every time the shortcut is run it creates a new chat, usually I would have made it to remove the chat after the shortcut is finished, but since I can’t the chats would pile up as there is no way of getting rid of them automatically and it would be tedious to manually delete all the chats. also sorry if I chose the wrong topic and subtopic, I couldn’t find a topic about shortcuts
1
0
437
Feb ’25
Language choice sometimes pops up during Recovery
Sometimes, during Recovery, when choosing "Options" I'm presented with the Language chooser before going into the Recovery options. Other times the process moves directly into Recovery options, without any language choice. I'm running in recovery mode, after completing a fresh installation of macOS (including setting a language) and fully shutting down the OS via the menu. This happens seemingly randomly, which affects the ability to automate the process. So far I've only seen it on macOS 15. Is there some logic to why this language chooser pops up, and any way I can make it consistent (in either direction)?
3
0
365
Feb ’25