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

Unable to find AppShortcutProvider
Hello, I'm evaluating if it's worth to expose shortcuts from our app, it seems to be working fine on my machine - Apple Silicon, latest Tahoe beta, Xcode 26 beta. But if I compile the same code on our intel build agents which are running latest macOS 15 and Xcode 26 beta, once I install the bundle to /Applications on Tahoe I don't see any shortcuts. Only other difference is that CI build is signed with distribution DeveloperID certificate - I re-signed the build with my dev certificate and it has no effect. I found out that linkd is somehow involved in the discovery process and most relevant logs look like this: default (...) linkd Registry com.**** is not link enabled com.apple.appintents debug (...) linkd ApplicationService Created AppShortcutClient with bundleId: com.**** com.apple.appintents error (...) linkd AppService Unable to find AppShortcutProvider for com.**** com.apple.appintents Could you please advice where to look for the problem?
0
0
129
Jul ’25
AudioPlaybackIntent usage requesting a screen unlock
Hello, I have an AppIntent that uses the AudioPlaybackIntent to trigger my app to open and initiate an AVPlayer that plays back a media stream I control. When the phone is unlocked, everything works as I expect. The app opens and plays the audio. However, when the phone is locked, any attempt to invoke the intent causes a "Request Code" dialog to be displayed. This seems counter to what I would expect with the AudioPlaybackIntent usage. Am I able to accomplish what I'm after here with AppIntents? Does the fact that I'm using openAppWhenRun require me to have the phone unlocked somehow? import AppIntents import Foundation struct PlayStationAppIntent: AudioPlaybackIntent { static var title: LocalizedStringResource = "Play radio station" static var description: IntentDescription = .init("Play radio station") static var notification: Notification.Name = .init("playStation") static var openAppWhenRun: Bool = true init() {} func perform() async throws -> some IntentResult { AudioPlayerService.shared.play() return .result() } }
0
0
120
Jul ’25
Array of AppEnum in a Parameter will always be empty
Consider the following in an AppIntent: struct TestIntent: AppIntent { static let title: LocalizedStringResource = "Test Intent" static var parameterSummary: some ParameterSummary { Summary("Test") { \.$options } } enum Option: Int, CaseIterable, AppEnum { case one case two case three case four case five case six static let typeDisplayRepresentation: TypeDisplayRepresentation = TypeDisplayRepresentation( name: "Options" ) static let caseDisplayRepresentations: [Option: DisplayRepresentation] = [ .one: DisplayRepresentation(title: "One"), .two: DisplayRepresentation(title: "Two"), .three: DisplayRepresentation(title: "Three"), .four: DisplayRepresentation(title: "Four"), .five: DisplayRepresentation(title: "Five"), .six: DisplayRepresentation(title: "Six"), ] } @Parameter(title: "Options", default: []) var options: [Option] @MainActor func perform() async throws -> some IntentResult { print(options) return .result() } } In Shortcuts, this will turn into a dropdown where you can check multiple Option values. However, when perform() is called, options will be an empty array regardless of what the user selects. This is observed on both iOS 18.5 and macOS 15.5. However, on iOS 26.0 beta and macOS 26.0 beta, the issue seems to be resolved and options contains all the checked options. However, we do back deploy to current/previous iOS/macOS versions. How can we provide a multiple choice selection of fixed values on these older versions?
3
0
178
Aug ’25
Terminal Command or AppleScript to Set Audio Balance to Perfect Center?
Hi everyone, I'm looking for a way to programmatically set the left/right audio balance to perfect center (50/50) using either a Terminal command or AppleScript. Background: The audio balance slider in System Settings > Sound > Output & Input works functionally, but I have difficulty determining when it's positioned at the exact center point. The visual nature of the slider makes it challenging for me to achieve the precision I need, and I end up adjusting it repeatedly trying to get it perfectly centered. What I'm looking for: A Terminal command that can set the audio balance to exact center An AppleScript that accomplishes the same thing Any other programmatic method to ensure perfect 50/50 balance I've tried searching through the defaults command documentation and Core Audio frameworks but haven't found the right approach yet. Has anyone successfully automated this setting before? Any help would be greatly appreciated! Thanks in advance, Dylan
0
0
80
Jul ’25
Shortcuts: Expense Tracker Header Lines
Issue: CSV Headings Not Appearing in Shortcut-Generated File I'm using an iPhone 16 Pro with iOS 18.5 and the latest Shortcuts app to log expenses into a CSV file. The shortcut works fine, except the resulting file doesn't include the column headings. Here’s what I’ve done: Created a file called Expenses.csv with this single header line: Date,Price,Category,Store,Notes,Location Saved it to both /iCloud Drive and /iCloud Drive/Shortcuts (via iCloud on my Windows PC). My Shortcut builds the CSV line from inputs (date, price, category, etc.) and appends it to the file. I renamed the variables only in the final “Text” block, since renaming in earlier blocks seems no longer possible in this Shortcuts version. Despite this setup, the file doesn’t preserve the header row—it either doesn’t show up, or gets overwritten. Goal: Have a persistent CSV file with the correct headers once, and each new entry appended below the correct columns. Can anyone help me figure out what I’m doing wrong?
0
0
262
Jul ’25
Siri not prompting to enable for AppIntent
We're trying to add an AppIntent to our very complex and large app that works with Siri. What we've found through numerous different configuration attempts is that when the Siri toggle is turned off on in the Shortcuts app for our app, when we speak our phrase to Siri we get this prompt: " hasn't added support for that with Siri." with an "Open " button. When we speak the phrase while the app is open, we get the prompt that says "Turn on "" shortcuts with Siri?" with a "Turn On" button. When the Siri toggle is turned on for our app in the Shortcuts app, all of our phrases work as expected. Is there some kind of configuration we're missing? There doesn't seem to be a lot of documentation. We've tried to match an example app's approach (AcceleratingAppInteractionsWithAppIntents) to no avail. Our app intents live in an xcframework if that makes a difference, but we've also tried moving it out of xcframework without success. This is a blocker to us shipping this feature. Thanks!
2
0
179
Jul ’25
how to use a 3D short cut with the totally closed application
I'm soliciting you because I'm having a problem using the 3D short cut for my ios application in uikit in the AppDelegate file but it's impossible to redirect the route when the user has completely killed the application. It works as a background application. I'd like it to redirect to the searchPage search page when the application is fully closed and the user clicks on search with 3D touch. final class AppDelegate: UIResponder, UIApplicationDelegate { lazy var window: UIWindow? = { return UIWindow(frame: UIScreen.main.bounds) }() private let appDependencyContainer = Container() private let disposeBag = DisposeBag() var pendingDeeplink: String? private lazy var onboardingNavigationController: UINavigationController = { let navigationController = UINavigationController(nibName: nil, bundle: nil) navigationController.setNavigationBarHidden(true, animated: false) return navigationController }() private func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first(where: { $0.isKeyWindow }), let rootVC = window.rootViewController else { DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in self?.handleShortcutItem(shortcutItem) } return } if let presentedVC = rootVC.presentedViewController { presentedVC.dismiss(animated: !UIAccessibility.isReduceMotionEnabled) { [weak self] in self?.executeShortcutNavigation(shortcutItem) } } else { executeShortcutNavigation(shortcutItem) } } private func executeShortcutNavigation(_ shortcutItem: UIApplicationShortcutItem) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in guard let self = self else { return } switch shortcutItem.type { case ShortcutType.searchAction.rawValue: self.mainRouter.drive(to: .searchPage(.show), origin: AppRoutingOrigin()) case ShortcutType.playAction.rawValue: self.mainRouter.drive(to: .live(channel: Channel(), appTabOrigin: AppTabOrigin.navigation.rawValue), origin: AppRoutingOrigin()) case ShortcutType.myListHistoryAction.rawValue: self.mainRouter.drive(to: .myList(.history), origin: AppRoutingOrigin()) default: break } } } What I've tried: Adding delays with DispatchQueue.main.asyncAfter Checking for window availability and rootViewController Dismissing presented view controllers before navigation Environment: iOS 15+ Swift 6 Using custom router system (mainRouter) App supports both SwiftUI and UIKit Questions: What's the best practice for handling shortcuts on cold launch vs warm launch? How can I ensure the router is properly initialized before navigation?
0
0
107
Jul ’25
Siri complains AppIntent is not registered
My question is similar to https://developer.apple.com/forums/thread/757298?answerId=791343022#791343022 but the solution from there did not help me. My app sends messages. I need it to do so when a user says to Siri: "Send message with ". When a user says so, Siri shows "Open button and says " hasn't added support for that with Siri". The code is pretty short and must work, but it doesn't. Could you please help and explain how to add the support mentioned above? How else I can use AppIntent and register the app as one capable to send messages when asked by Siri? import AppIntents @main struct MyAppNameApp: App { var body: some Scene { WindowGroup { ContentView() } } init() { MyAppNameShortcuts.updateAppShortcutParameters() Task { await MyAppNameShortcuts.updateAppShortcutParameters() } } } struct SendMessageWithMyAppName: AppIntent { static var title: LocalizedStringResource = "Send message" static let description = IntentDescription( "Dictate a message and have MyAppName print it to the Xcode console.") @Parameter(title: "Message", requestValueDialog: "What should I send?") var content: String static var openAppWhenRun = false func perform() async throws -> some IntentResult { print("MyAppName message: \(content)") await MainActor.run { NotificationCenter.default.post(name: .newMessageReceived, object: content) } return .result(dialog: "Message sent: \(content)") } } struct MyAppNameShortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: SendMessageWithMyAppName(), phrases: [ "Send message with \(.applicationName)" ], shortTitle: "Send Message", systemImageName: "message" ) } }
1
0
92
Aug ’25
Transaction Shortcuts + AppIntent is flaky occasionally
Hello, I made myself an app to track my expenses. The most important event is when I make a purchase via apple wallet. What happens is sometimes the values from Merchant and Amount are; Merchant = " " Amount = 0.0 Has anyone experienced this, is there something I can do about it ? I was thinking that sometimes maybe speed connection and service is something that might make an impact Does anyone here know something about the topic ?
6
0
231
Oct ’25
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
66
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
95
Sep ’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
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
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
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