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

Created

Best Approach for Monitoring Music Playback State Across Multiple Apps?
Hey Swift community! I'm exploring building a macOS app that needs to monitor what's currently playing in music apps like Spotify and Apple Music (track info, playback position, play/pause state). I'm trying to figure out the most efficient architecture before diving in. The Goal: Monitor playback state across multiple music players to react to changes in real-time, ideally with minimal CPU overhead since this would run continuously in the background. Approaches I'm Considering AppleScript / ScriptingBridge Distributed Notifications Native Frameworks (Apple Music only) What's the recommended way to do this on macOS? Are distributed notifications reliable enough to avoid polling entirely? Is there a performance difference between AppleScript and ScriptingBridge for IPC? For Apple Music specifically, should I use MusicKit, MediaPlayer, or stick with AppleScript? Are there other approaches I'm missing?
0
0
25
1d
Activating application from Terminal occasionally fails on macOS 26
On macOS Tahoe 26 activating GUI apps from command-line often fails. It launches the app but not brings to the foreground as expected. For example, running the following commands in Terminal is expected to launch Pages and bring it to the foreground. open /Applications/Pages.app or osascript -e `tell application "Pages" to activate` Moreover, they sometimes not return in Terminal. These commands worked as expected until macOS 15 but no more in macOS 26. The tricky part is that this failure doesn't happen 100% of the time; it occurs randomly. However, since multiple users of my app have reported the same symptoms, and I can reproduce it not only with my app but also with apps bundled to macOS, I don't believe this is an issue specific to my environment alone. I’ve already filed this issue: FB21087054 Open version: https://github.com/1024jp/AppleFeedback/issues/87 However, I’d like to know if any workaround exists or my understanding is wrong, especially for case with osascript.
3
1
80
6d
Press return
Here is the appleScript part of my script: tell application "Finder" activate open application file "Messages.app" of folder "Applications" of folder "System" of startup disk end tell What I need is a step to send the message already inside the Mesage.app. The message is ready to send. I just would like a step that will act as "Return" to send the message. Again I have already prepared message to send but just need a step to send the message. Is there a possible step to perform the" Return" command to iMessage?
1
0
41
1w
AppleScript scripts return -600 error in STP 231 for Tahoe
The AppleScript script below returns a -600 error (application not running) under STP Tahoe version 231 and macOS 26.1. It functioned flawlessly under previous STP versions under macOS 15.x and 14.x. tell application "Safari Technology Preview" tell front window set _old_tab to current tab set _new_tab to make new tab at after _old_tab set current tab to _new_tab end tell end tell The following version returns a syntax error. Tell application "System Events" Tell process "Safari Technology Preview" tell front window set _old_tab to current tab set _new_tab to make new tab at after _old_tab set current tab to _new_tab end tell end tell end tell How would these scripts need to be fixed for STP 231 for Tahoe?
2
0
111
1w
UI Testing and 'Allow Paste'
I am developing an app that allows the user to ask it to process the clipboard contents and do something with it. In developing a XC UI Test, I find the app stops while it waits for the user to give permission. That breaks the automation. I tried: let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let allowButton = springboard.buttons["Allow Paste"] But that does not work. Is there a way to tell the framework to automatically give the test permission to access the Paste clipboard (or to allow me to write tests to grant this)?
0
0
33
2w
Visual Intelligence: App Intent Not Found?
I'm making a PoC for Visual Intelligence integration in iOS. It's a very simple setup... the extension will always reply with a couple of static "results" just so I can verify that it's working and figure out how to handle receiving app activation from the Intents framework. The app seems to be registering the VI intent correctly, because I see my app's name in the tab list of providers for search results, but when I select my app, I always get no results. I looked at the console for the moment I'm selecting my app and seeing this error: error 16:37:09.433057-0600 duetexpertd [com.hairlessape.VisualIntelligenceProvider.VIAppIntent] Unable to get connection interface: Error Domain=LNConnectionErrorDomain Code=1100 "Unable to locate `com.hairlessape.VisualIntelligenceProvider.VIAppIntent` for the `com.apple.appintents-extension` extension point" No amount of web searching or AI interrogation has produced any headwind here. I've checked the build product and I can see the VIAppIntent.appex file in the Extensions\ folder of my app bundle. I've triple checked the bundle identifiers, code file membership, installed the app from an IPA, restarted my phone, etc. I cannot get my intent to be queried and it's very frustrating. I've put the PoC project on Github: https://github.com/JoshuaSullivan/VisualSearchForVI
5
0
100
2w
AppleScript
Here's my AppleScript: tell application "Finder" activate open application file "Messages.app" of folder "Applications" of folder "System" of startup disk end tell I just need the step to send the message making the script automatically send the message which has already been created. This step opens the completed iMessage ready to send . I want to send it without and keyboard usage. All that is needed is the step to send
0
0
16
2w
AppIntents crashes in prod
We implemented AppIntents using EnumerableEntityQuery and @Dependency and we are receiving these crash reports: AppIntents/AppDependencyManager.swift:120: Fatal error: AppDependency of type MyDependency.Type was not initialized prior to access. Dependency values can only be accessed inside of the intent perform flow and within types conforming to _SupportsAppDependencies unless the value of the dependency is manually set prior to access. I can't post the stack because of the Developer Forums sensitive language filter :( but basically it's just a call to suggestedEntities of MyEntityQuery that calls the dependency getter and then it crashes. My understanding was that when using @Dependency, the execution of the intent, or query of suggestedEntities in this case, would be delayed by the AppIntents framework until the dependency was added to the AppDependencyManager by me. At least that's what's happening in my tests. But in prod I'm having these crashes which I haven't been able to reproduce in dev yet. Does anyone know if this is a bug or how can this be fixed? As a workaround, I can avoid using @Dependency and AppDependencyManager completely and make sure that all operations are async and delay the execution myself until the dependency is set. But I'd like to know if there's a better solution. Thanks!
1
0
122
4w
Siri AppIntent phrasing
When my AppShortcut phrase is: "Go (.$direction) with (.applicationName)" Then everything works correctly, the AppIntent correctly receives the parameter. But when my phrase is: "What is my game (.$direction) with (.applicationName)" The an alert dialog pops up saying: "Hey siri what is my game tomorrow with {app name} Do you want me to use ChatGPT to answer that?" The phrase is obviously heard correctly, and it's exactly what I've specified in the AppShortcut. Why isn't it being sent to my AppIntent? import Foundation import AppIntents @available(iOS 17.0, *) enum Direction: String, CaseIterable, AppEnum { case today, yesterday, tomorrow, next static var typeDisplayRepresentation: TypeDisplayRepresentation { TypeDisplayRepresentation(name: "Direction") } static var caseDisplayRepresentations: [Direction: DisplayRepresentation] = [ .today: DisplayRepresentation(title: "today", synonyms: []), .yesterday: DisplayRepresentation(title: "yesterday", synonyms: []), .tomorrow: DisplayRepresentation(title: "tomorrow", synonyms: []), .next: DisplayRepresentation(title: "next", synonyms: []) ] } @available(iOS 17.0, *) struct MoveItemIntent: AppIntent { static var title: LocalizedStringResource = "Move Item" @Parameter(title: "Direction") var direction: Direction func perform() async throws -> some IntentResult { // Logic to move item in the specified direction print("Moving item \(direction)") return .result() } } @available(iOS 17.0, *) final class MyShortcuts: AppShortcutsProvider { static let shortcutTileColor = ShortcutTileColor.navy static var appShortcuts: [AppShortcut] { AppShortcut( intent: MoveItemIntent() , phrases: [ "Go \(\.$direction) with \(.applicationName)" // "What is my game \(\.$direction) with \(.applicationName)" ] , shortTitle: "Test of direction parameter" , systemImageName: "soccerball" ) } }
3
0
244
Oct ’25
Copying files using Finder and Apple Events
I need my application to copy some files, but using Finder. Now, I know all different methods and options to programmatically copy files using various APIs, but that's not the point here. I specifically need to use Finder for the purpose, so please, let's avoid eventual suggestions mentioning other ways to copy files. My first thought was to use the most simple approach, execute an AppleScript script using NSUserAppleScriptTask, but that turned out not to be ideal. It works fine, unless there already are files with same names at the copying destination. In such case, either the script execution ends with an error, reporting already existing files at the destination, or the existing files can be simply overridden by adding with overwrite option to duplicate command in the script. What I need is behaviour just like when Finder is used from the UI (drag'n'drop, copy/paste…); if there are existing files with same names at the destination, Finder should offer a "resolution panel", asking the user to "stop", "replace", "don't replace", "keep both" or "merge" (the latter in case of conflicting folders). So, I came to suspect that I could achieve such bahaviour by using Apple Events directly and passing kAEAlwaysInteract | kAECanSwitchLayer options to AESendMessage(). However, I can't figure out how to construct appropriate NSAppleEventDescriptor (nor old-style Carbon AppleEvent) objects and instruct Finder to copy files. This is where I came so far, providing srcFiles are source files (to be copied) URLs and dstFolder destination folder (to be copied into) URL: NSRunningApplication *finder = [[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"] firstObject]; if (!finder) { NSLog(@"Finder is not running."); return; } NSAppleEventDescriptor *finderDescriptor = [NSAppleEventDescriptor descriptorWithBundleIdentifier:[finder bundleIdentifier]]; NSAppleEventDescriptor *dstDescriptor = [NSAppleEventDescriptor descriptorWithString:[dstFolder path]]; NSAppleEventDescriptor *srcDescriptor = [NSAppleEventDescriptor listDescriptor]; for (NSURL *url in srcFiles) { NSAppleEventDescriptor *fileDescriptor = [NSAppleEventDescriptor descriptorWithString:[url path]]; [srcDescriptor insertDescriptor:fileDescriptor atIndex:([srcDescriptor numberOfItems] + 1)]; } NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kAECoreSuite eventID:kAEClone targetDescriptor:finderDescriptor returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [event setParamDescriptor:srcDescriptor forKeyword:keyDirectObject]; [event setParamDescriptor:dstDescriptor forKeyword:keyAETarget]; NSError *error; NSAppleEventDescriptor *result = [event sendEventWithOptions:(NSAppleEventSendAlwaysInteract | NSAppleEventSendCanSwitchLayer) timeout:10.0 error:&error]; The code above executes without any error. The final result descriptor is a NULL descriptor ([NSAppleEventDescriptor nullDescriptor]) and there's no error returned (by reference). However, nothing happens, Finder remains silent and the application doesn't make macOS/TCC prompt for a permission to "automate Finder". I wonder if the approach above is correct and if I use correct parameters as arguments for all calling method/messages. I'm specially interested if passing keyAETarget is the right value in [event setParamDescriptor:dstDescriptor forKeyword:keyAETarget], since that one looks most suspicious to me. I'd really appreciate if anyone can help me with this. I'd also like to point out that I tried the same approach outlined above with old-style Carbon AppleEvent API, using AECreateDesc(), AECreateAppleEvent(), AEPutParamDesc() and AESendMessage()… All API calls succeeded, returning noErr, but again, nothing happened, Finder remained silent and no macOS/TCC prompt for a permission to "automate Finder". Any help is highly appreciated, thanks! -- Dragan
9
0
162
Oct ’25
Siri Shortcut extension build cycle
I developed a XCode project using Flutter (v. 3.35.6). The application basically has a IntentExtension to handle intents donation and the related business logic. We decided to go with ShortcutExtension in place of AppIntents because it fits with our app's use case (where basically we need to dynamically donate/remove intents). We have an issue building the project, and it is due to the presence of the IntentExtension .appex file in the Build Phases --> Embed Foundation Extensions. If we remove it , the project builds however the IntentHandling is not invoked in the Shortcuts app. Build issue: Generated error in the console: Cycle inside Runner; building could produce unreliable results. Cycle details: → Target 'Runner' has copy command from '/Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/ShortcutsExtension.appex' to '/Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/PlugIns/ShortcutsExtension.appex' ○ That command depends on command in Target 'Runner': script phase “[CP] Copy Pods Resources” ○ That command depends on command in Target 'Runner': script phase “[CP] Embed Pods Frameworks” ○ That command depends on command in Target 'Runner': script phase “FlutterFire: "flutterfire upload-crashlytics-symbols"” ○ That command depends on command in Target 'Runner': script phase “FlutterFire: "flutterfire bundle-service-file"” ○ That command depends on command in Target 'Runner': script phase “Thin Binary” ○ Target 'Runner' has process command with output '/Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/Info.plist' ○ Target 'Runner' has copy command from '/Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/ShortcutsExtension.appex' to '/Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/PlugIns/ShortcutsExtension.appex' Raw dependency cycle trace: target: -> node: -> command: -> node: /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Intermediates.noindex/Runner.build/Release-quality-iphoneos/Runner.build/Objects-normal/arm64/ExtractedAppShortcutsMetadata.stringsdata -> command: P0:target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49-:Release-quality:ExtractAppIntentsMetadata -> node: -> command: P0:::Gate target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49--fused-phase10-copy-files -> node: <Copy /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/PlugIns/ShortcutsExtension.appex> -> CYCLE POINT -> command: P0:target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49-:Release-quality:Copy /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/PlugIns/ShortcutsExtension.appex /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/ShortcutsExtension.appex -> node: -> command: P0:::Gate target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49--fused-phase9--cp--copy-pods-resources -> node: /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/GoogleMapsResources.bundle -> command: P2:target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49-:Release-quality:PhaseScriptExecution [CP] Copy Pods Resources /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Intermediates.noindex/Runner.build/Release-quality-iphoneos/Runner.build/Script-B728693F1F2684724A065652.sh -> node: -> command: P0:::Gate target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49--fused-phase8--cp--embed-pods-frameworks -> node: /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Products/Release-quality-iphoneos/Runner.app/Frameworks/Alamofire.framework -> command: P2:target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49-:Release-quality:PhaseScriptExecution [CP] Embed Pods Frameworks /Users/federico.gatti/Documents/comfort-mobile-app/apps/comfort/ios/DerivedData/Runner/Build/Intermediates.noindex/Runner.build/Release-quality-iphoneos/Runner.build/Script-1A1449CD6436E619E61D3E0D.sh -> node: -> command: P0:::Gate target-Runner-18c1723432283e0cc55f10a6dcfd9e0288a783a885d8b0b3beb2e9f90bde3f49--fused-phase7-flutterfire---flutterfire-upload-crashlytics-symbols- -> node: <execute-shell-script-18c1723432283e0cc55f10a6dcfd9e024008e7f13be1da4979f78de280354094-target-Runner-18c1723432283e
1
0
53
Oct ’25
openAppWhenRun = true is wrong
import AppIntents struct MGIntents: AppIntent { static var title = LocalizedStringResource("open app") static var openAppWhenRun: Bool = true func perform() async throws -> some IntentResult & ProvidesDialog { return .result(dialog: "app open") } } struct AppItentsShortcuts:AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut(intent: MGIntents(), phrases: ["\(.applicationName) Open app"], shortTitle: "Open app", systemImageName: "fan.desk.fill") } } when use ,error more error。 when i delet openAppWhenRun ,is ok。why? how I can do it? thank you!
3
0
276
Oct ’25
Macos Tahoe issue launching apps through SSH
On a CI infrastructure we connect nodes through SSH, and launch automated apps testing. Since Macos Tahoe: When launching an App through SSH with full executable binary path App doesn't show up in apps bar and top menu No keyboard events are received (mouse work well) How to reproduce: ssh <YOUR_MAC_TAHOE> /Applications/Pages.app/Contents/MacOS/Pages # ==> Navigate until you can enter text, no keyboard input are working # ==> App do not show up on app bar # ==> Work as expected if launched from a local terminal open /Applications/Pages.app # ==> work well Do I miss a system configuration to restore ability to launch apps from SSH ? Note: We use full executable binary path (not bundle path/.app folder) because our test application require this full path (Qt Squish)
1
1
101
Oct ’25
How to properly localise AppShortcutPhrase?
Hi, I have AppShortcutsProvider in my app target(not as a separate extension) to support Siri command. It is working perfectly in English, but I would also like to add a localisation on it as my app supports multiple languages. struct MyShortcuts: AppShortcutsProvider { static let shortcutTileColor: ShortcutTileColor = .grape static var appShortcuts: [AppShortcut] { AppShortcut( intent: NextClassAppIntents(), phrases: [ "What is my next class in \(.applicationName)?", "What's the next class in \(.applicationName)?", "Next class in \(.applicationName)." ], shortTitle: "Next Class", systemImageName: "calendar.badge.clock" ) } } Xcode String Catalog was doing great jobs, It also detected shortTitle automatically and added that to the Catalog. However, I don't see localisation for those phrases anywhere in the String Catalog and when I try to use String(localized: ), compiler gives me an error. How can I properly localise AppShortcutPhrase?
1
0
90
Oct ’25
Apple Music ScriptingBridge Broken in macOS Tahoe 26
l’m trying to automate Apple Music on macOS Tahoe 26 using ScriptingBridge. Scripts that previously worked for controlling playback, fetching track info, or manipulating playlists no longer function. For example, code like this used to work: `import ScriptingBridge let music = SBApplication(bundleIdentifier: "com.apple.Music") as! MusicApplication print(music.currentTrack?.name ?? "No track playing")` But now it fails, returning nil for track info and failing to send playback commands. Questions: Has ScriptingBridge been deprecated or broken in Tahoe 26 for Apple Music? Any guidance or example code would be appreciated.
2
2
262
Sep ’25
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
94
Sep ’25