axiom-app-shortcuts-ref by charleswiltgen/axiom
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-app-shortcuts-ref关于 App Shortcuts 框架的全面指南,用于让您的应用操作在 Siri、Spotlight、操作按钮、控制中心和其他系统体验中立即可用。App Shortcuts 是预配置的 App Intents,在应用安装后立即生效——无需用户设置。
关键区别 App Intents 是操作本身;App Shortcuts 是预配置的“呈现层”,使这些操作在整个系统范围内立即可被发现。
在以下情况使用此技能:
不要将此技能用于:
| 方面 | App Intent |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| App Shortcut |
|---|
| 发现性 | 必须在快捷指令应用中查找 | 安装后立即可用 |
| 配置 | 用户在快捷指令中配置 | 由开发者预配置 |
| Siri 激活 | 需要自定义短语设置 | 使用提供的短语立即生效 |
| Spotlight | 需要捐赠或 IndexedEntity | 自动出现 |
| 操作按钮 | 无法直接访问 | 可立即分配 |
| 设置时间 | 每个用户数分钟 | 零 |
何时使用 App Shortcuts 每个应用都应为核心功能提供 App Shortcuts。它们以零用户努力显著提高可发现性。
必需遵循 您的应用必须恰好有一个类型遵循 AppShortcutsProvider。
struct MyAppShortcuts: AppShortcutsProvider {
// 必需:定义您的快捷指令
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] { get }
// 可选:品牌颜色
static var shortcutTileColor: ShortcutTileColor { get }
// 可选:动态更新
static func updateAppShortcutParameters()
// 可选:否定短语(iOS 17+)
static var negativePhrases: [NegativeAppShortcutPhrase] { get }
}
平台支持 iOS 16+, iPadOS 16+, macOS 13+, tvOS 16+, watchOS 9+
将 AppIntent 与口语短语和元数据关联。
AppShortcut(
intent: StartMeditationIntent(),
phrases: [
"在 \(.applicationName) 中开始冥想",
"使用 \(.applicationName) 开始正念练习"
],
shortTitle: "冥想",
systemImageName: "figure.mind.and.body"
)
组件:
intent — 要执行的 App Intentphrases — 用于 Siri/Spotlight 的口语/输入短语shortTitle — 快捷指令应用图块的简短标签systemImageName — 用于视觉表示的 SF Symbol字符串插值 短语使用 \(.applicationName) 动态包含您的应用名称。
phrases: [
"在 \(.applicationName) 中开始冥想",
"使用 \(.applicationName) 冥想"
]
用户在 Siri/Spotlight 中看到:
重要性 系统使用这些确切短语通过 Siri 触发您的意图并在 Spotlight 中显示建议。
用于定义快捷指令数组的结果构建器。
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
AppShortcut(intent: OrderIntent(), /* ... */)
AppShortcut(intent: ReorderIntent(), /* ... */)
if UserDefaults.standard.bool(forKey: "premiumUser") {
AppShortcut(intent: CustomizeIntent(), /* ... */)
}
}
结果构建器特性:
AppShortcut(
intent: StartWorkoutIntent(),
phrases: [
"在 \(.applicationName) 中开始锻炼",
"使用 \(.applicationName) 开始运动",
"在 \(.applicationName) 中锻炼"
],
shortTitle: "开始锻炼",
systemImageName: "figure.run"
)
优点:
使用时机 意图没有必需参数或参数有默认值时。
使用特定参数值预配置意图,以跳过 Siri 的澄清步骤。
// 带参数的意图
struct StartMeditationIntent: AppIntent {
static var title: LocalizedStringResource = "开始冥想"
@Parameter(title: "类型")
var meditationType: MeditationType?
@Parameter(title: "时长")
var duration: Int?
}
// 具有不同参数组合的快捷指令
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// 通用版本(将询问参数)
AppShortcut(
intent: StartMeditationIntent(),
phrases: ["在 \(.applicationName) 中开始冥想"],
shortTitle: "冥想",
systemImageName: "figure.mind.and.body"
)
// 特定版本(跳过参数步骤)
AppShortcut(
intent: StartMeditationIntent(
meditationType: .mindfulness,
duration: 10
),
phrases: [
"在 \(.applicationName) 中开始快速正念",
"在 \(.applicationName) 中进行 10 分钟正念"
],
shortTitle: "快速正念",
systemImageName: "brain.head.profile"
)
AppShortcut(
intent: StartMeditationIntent(
meditationType: .sleep,
duration: 20
),
phrases: [
"在 \(.applicationName) 中开始睡眠冥想"
],
shortTitle: "睡眠冥想",
systemImageName: "moon.stars.fill"
)
}
优点:
权衡 更多快捷指令 = 快捷指令应用中更多视觉混乱。平衡常见情况(3-5 个快捷指令)与灵活性(带参数的通用快捷指令)。
训练系统不要为某些短语调用您的应用。
struct MeditationAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: StartMeditationIntent(),
phrases: ["在 \(.applicationName) 中开始冥想"],
shortTitle: "冥想",
systemImageName: "figure.mind.and.body"
)
}
// 防止误触发
static var negativePhrases: [NegativeAppShortcutPhrase] {
NegativeAppShortcutPhrases {
"停止冥想"
"取消冥想"
"结束会话"
}
}
}
使用时机:
平台 iOS 17.0+, iPadOS 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+
直接在您的应用 UI 中显示快捷指令的口语短语。
import AppIntents
import SwiftUI
struct OrderConfirmationView: View {
@State private var showSiriTip = true
var body: some View {
VStack {
Text("订单已确认!")
// 在成功下单后显示 Siri 提示
SiriTipView(intent: ReorderIntent(), isVisible: $showSiriTip)
.siriTipViewStyle(.dark)
}
}
}
要求:
样式:
.automatic — 适应环境.light — 浅色背景.dark — 深色背景最佳实践 在用户完成操作后显示,建议下次更简单的方法。
在快捷指令应用中打开您的应用页面,列出所有可用快捷指令。
import AppIntents
import SwiftUI
struct SettingsView: View {
var body: some View {
List {
Section("Siri 与快捷指令") {
ShortcutsLink()
// 显示带有标准链接样式的"快捷指令"
}
}
}
}
使用时机:
优点 单次点击即可让用户查看您应用的所有快捷指令,并显示建议短语。
在快捷指令应用中设置您的快捷指令颜色。
struct CoffeeAppShortcuts: AppShortcutsProvider {
static var shortcutTileColor: ShortcutTileColor = .tangerine
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// ...
}
}
可用颜色:
| 颜色 | 用例 |
|---|---|
.blue | 默认,专业 |
.tangerine | 能量,食品/饮料 |
.purple | 创意,冥想 |
.teal | 健康,保健 |
.red | 紧急,重要 |
.pink | 生活方式,社交 |
.navy | 商业,金融 |
.yellow | 生产力,笔记 |
.lime | 健身,户外 |
完整列表:.blue, .grape, .grayBlue, .grayBrown, .grayGreen, .lightBlue, .lime, .navy, .orange, .pink, .purple, .red, .tangerine, .teal, .yellow
选择颜色 匹配您的应用图标或品牌标识。
当参数选项更改时调用以刷新存储的快捷指令。
struct MeditationAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// 快捷指令可以引用动态数据
for session in MeditationData.favoriteSessions {
AppShortcut(
intent: StartSessionIntent(session: session),
phrases: ["在 \(.applicationName) 中开始 \(session.name)"],
shortTitle: session.name,
systemImageName: session.iconName
)
}
}
static func updateAppShortcutParameters() {
// 在需要时自动调用
// 仅在需要自定义行为时重写
}
}
// 在您的应用中,当数据更改时
extension MeditationData {
func markAsFavorite(_ session: Session) {
favoriteSessions.append(session)
// 更新 App Shortcuts 以反映新数据
MeditationAppShortcuts.updateAppShortcutParameters()
}
}
调用时机:
自动调用 系统会定期调用此方法,但当您知道数据已更改时可以强制更新。
import AppIntents
struct OrderCoffeeIntent: AppIntent {
static var title: LocalizedStringResource = "订购咖啡"
static var description = IntentDescription("订购咖啡以便取货")
@Parameter(title: "咖啡类型")
var coffeeType: CoffeeType
@Parameter(title: "尺寸")
var size: CoffeeSize
@Parameter(title: "定制选项")
var customizations: String?
static var parameterSummary: some ParameterSummary {
Summary("订购 \(\.$size) \(\.$coffeeType)") {
\.$customizations
}
}
func perform() async throws -> some IntentResult {
let order = try await CoffeeService.shared.order(
type: coffeeType,
size: size,
customizations: customizations
)
return .result(
value: order,
dialog: "您的 \(size) \(coffeeType) 已订购,等待取货"
)
}
}
struct ReorderLastIntent: AppIntent {
static var title: LocalizedStringResource = "重新订购上次咖啡"
static var description = IntentDescription("重新订购您最近的咖啡")
static var openAppWhenRun: Bool = false
func perform() async throws -> some IntentResult {
guard let lastOrder = try await CoffeeService.shared.lastOrder() else {
throw CoffeeError.noRecentOrders
}
try await CoffeeService.shared.reorder(lastOrder)
return .result(
dialog: "正在重新订购您的 \(lastOrder.coffeeName)"
)
}
}
enum CoffeeType: String, AppEnum {
case latte, cappuccino, americano, espresso
static var typeDisplayRepresentation: TypeDisplayRepresentation = "咖啡类型"
static var caseDisplayRepresentations: [CoffeeType: DisplayRepresentation] = [
.latte: "拿铁",
.cappuccino: "卡布奇诺",
.americano: "美式咖啡",
.espresso: "浓缩咖啡"
]
}
enum CoffeeSize: String, AppEnum {
case small, medium, large
static var typeDisplayRepresentation: TypeDisplayRepresentation = "尺寸"
static var caseDisplayRepresentations: [CoffeeSize: DisplayRepresentation] = [
.small: "小杯",
.medium: "中杯",
.large: "大杯"
]
}
import AppIntents
struct CoffeeAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// 通用订单(将询问参数)
AppShortcut(
intent: OrderCoffeeIntent(),
phrases: [
"在 \(.applicationName) 中订购咖啡",
"从 \(.applicationName) 获取咖啡"
],
shortTitle: "订购",
systemImageName: "cup.and.saucer.fill"
)
// 常见特定订单(跳过参数步骤)
AppShortcut(
intent: OrderCoffeeIntent(
coffeeType: .latte,
size: .medium
),
phrases: [
"从 \(.applicationName) 订购我常喝的",
"从 \(.applicationName) 获取我常喝的咖啡"
],
shortTitle: "常规订单",
systemImageName: "star.fill"
)
// 重新订购上次
AppShortcut(
intent: ReorderLastIntent(),
phrases: [
"从 \(.applicationName) 重新订购咖啡",
"从 \(.applicationName) 再次订购"
],
shortTitle: "重新订购",
systemImageName: "arrow.clockwise"
)
}
// 品牌标识
static var shortcutTileColor: ShortcutTileColor = .tangerine
// 防止误触发(iOS 17+)
static var negativePhrases: [NegativeAppShortcutPhrase] {
NegativeAppShortcutPhrases {
"取消咖啡订单"
"停止咖啡"
}
}
}
import SwiftUI
import AppIntents
struct OrderConfirmationView: View {
@State private var showReorderTip = true
var body: some View {
VStack(spacing: 20) {
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 60))
.foregroundColor(.green)
Text("订单已提交!")
.font(.title)
Text("您的咖啡将在 10 分钟内准备好")
.foregroundColor(.secondary)
// 推广重新订购快捷指令
if showReorderTip {
SiriTipView(intent: ReorderLastIntent(), isVisible: $showReorderTip)
.siriTipViewStyle(.dark)
.padding(.top)
}
// 链接查看所有快捷指令
Section {
ShortcutsLink()
} header: {
Text("查看所有可用快捷指令")
.font(.caption)
}
}
.padding()
}
}
实现后,您的 App Shortcuts 在以下位置可用:
| 位置 | 用户体验 |
|---|---|
| Siri | 使用提供的短语进行语音激活 |
| Spotlight | 搜索操作或短语 → 立即执行 |
| 快捷指令应用 | 预填充的快捷指令,零配置 |
| 操作按钮 (iPhone 15 Pro) | 可分配给硬件按钮 |
| Apple Watch Ultra | 操作按钮分配 |
| 控制中心 | 添加快捷指令作为控件 |
| 锁屏小组件 | 无需解锁的快速操作 |
| Apple Pencil Pro | 挤压手势分配 |
| 专注模式过滤器 | 上下文过滤 |
即时可用性 所有位置在应用安装后立即生效。无需用户设置。
如果快捷指令未出现:
isDiscoverable 为 true(默认)示例:
如果 Siri 无法识别短语:
\(.applicationName)如果快捷指令未出现在 Spotlight 中:
#if DEBUG
struct CoffeeAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
let shortcuts = [
AppShortcut(/* ... */),
// ...
]
print("📱 注册了 \(shortcuts.count) 个 App Shortcuts")
shortcuts.forEach { shortcut in
print(" - \(shortcut.shortTitle)")
}
return shortcuts
}
}
#endif
检查 Xcode 控制台 应用启动后验证快捷指令是否已注册。
phrases: [
"我想从 \(.applicationName) 订购一杯咖啡,请"
]
phrases: [
"在 \(.applicationName) 中订购咖啡",
"从 \(.applicationName) 获取咖啡"
]
指南:
\(.applicationName) 以消除歧义// 不好:令人不知所措
为每个可能的组合提供 AppShortcut
// 好:专注于常见任务
AppShortcut(intent: OrderIntent(), /* ... */)
AppShortcut(intent: ReorderIntent(), /* ... */)
AppShortcut(intent: ViewOrdersIntent(), /* ... */)
原因 太多快捷指令会造成混乱。专注于高价值、频繁使用的操作。
// 不好:创建 12 个快捷指令(3 种尺寸 × 4 种类型)
for size in CoffeeSize.allCases {
for type in CoffeeType.allCases {
AppShortcut(intent: OrderIntent(type: type, size: size), /* ... */)
}
}
// 好:通用 + 常见特定案例
AppShortcut(intent: OrderIntent(), /* ... */) // 通用
AppShortcut(intent: OrderIntent(type: .latte, size: .medium), /* ... */) // 常规
AppShortcut(intent: OrderIntent(type: .espresso, size: .small), /* ... */) // 快速
shortTitle: "从咖啡应用订购咖啡"
shortTitle: "订购"
上下文 应用名称已出现在快捷指令应用中,无需重复。
// 不支持
shortImage: UIImage(named: "custom")
systemImageName: "cup.and.saucer.fill"
原因 SF Symbols 能正确缩放,支持深色模式,并与系统 UI 集成。
WWDC : 2022-10170, 2022-10169, 260
文档 : /appintents/appshortcutsprovider, /appintents/appshortcut, /appintents/app-shortcuts
技能 : axiom-app-intents-ref, axiom-app-discoverability, axiom-core-spotlight-ref
记住 App Shortcuts 让您的应用功能在 iOS 中立即可用。定义 3-5 个带有自然短语的核心快捷指令,使用 SiriTipView 在您的 UI 中推广它们,用户可以通过 Siri、Spotlight、操作按钮等立即调用它们。
每周安装数
96
代码仓库
GitHub 星标数
610
首次出现
2026年1月21日
安全审计
安装在
opencode80
claude-code77
codex74
gemini-cli72
cursor71
github-copilot67
Comprehensive guide to App Shortcuts framework for making your app's actions instantly available in Siri, Spotlight, Action Button, Control Center, and other system experiences. App Shortcuts are pre-configured App Intents that work immediately after app install—no user setup required.
Key distinction App Intents are the actions; App Shortcuts are the pre-configured "surface" that makes those actions instantly discoverable system-wide.
Use this skill when:
Do NOT use this skill for:
| Aspect | App Intent | App Shortcut |
|---|---|---|
| Discovery | Must be found in Shortcuts app | Instantly available after install |
| Configuration | User configures in Shortcuts | Pre-configured by developer |
| Siri activation | Requires custom phrase setup | Works immediately with provided phrases |
| Spotlight | Requires donation or IndexedEntity | Appears automatically |
| Action button | Not directly accessible | Can be assigned immediately |
| Setup time | Minutes per user | Zero |
When to use App Shortcuts Every app should provide App Shortcuts for core functionality. They dramatically improve discoverability with zero user effort.
Required conformance Your app must have exactly one type conforming to AppShortcutsProvider.
struct MyAppShortcuts: AppShortcutsProvider {
// Required: Define your shortcuts
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] { get }
// Optional: Branding color
static var shortcutTileColor: ShortcutTileColor { get }
// Optional: Dynamic updates
static func updateAppShortcutParameters()
// Optional: Negative phrases (iOS 17+)
static var negativePhrases: [NegativeAppShortcutPhrase] { get }
}
Platform support iOS 16+, iPadOS 16+, macOS 13+, tvOS 16+, watchOS 9+
Associates an AppIntent with spoken phrases and metadata.
AppShortcut(
intent: StartMeditationIntent(),
phrases: [
"Start meditation in \(.applicationName)",
"Begin mindfulness with \(.applicationName)"
],
shortTitle: "Meditate",
systemImageName: "figure.mind.and.body"
)
Components:
intent — The App Intent to executephrases — Spoken/typed phrases for Siri/SpotlightshortTitle — Short label for Shortcuts app tilessystemImageName — SF Symbol for visual representationString interpolation Phrases use \(.applicationName) to dynamically include your app's name.
phrases: [
"Start meditation in \(.applicationName)",
"Meditate with \(.applicationName)"
]
User sees in Siri/Spotlight:
Why this matters The system uses these exact phrases to trigger your intent via Siri and show suggestions in Spotlight.
Result builder for defining shortcuts array.
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
AppShortcut(intent: OrderIntent(), /* ... */)
AppShortcut(intent: ReorderIntent(), /* ... */)
if UserDefaults.standard.bool(forKey: "premiumUser") {
AppShortcut(intent: CustomizeIntent(), /* ... */)
}
}
Result builder features:
AppShortcut(
intent: StartWorkoutIntent(),
phrases: [
"Start workout in \(.applicationName)",
"Begin exercise with \(.applicationName)",
"Work out in \(.applicationName)"
],
shortTitle: "Start Workout",
systemImageName: "figure.run"
)
Benefits:
Use when Intent has no required parameters or parameters have defaults.
Pre-configure intents with specific parameter values to skip Siri's clarification step.
// Intent with parameters
struct StartMeditationIntent: AppIntent {
static var title: LocalizedStringResource = "Start Meditation"
@Parameter(title: "Type")
var meditationType: MeditationType?
@Parameter(title: "Duration")
var duration: Int?
}
// Shortcuts with different parameter combinations
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// Generic version (will ask for parameters)
AppShortcut(
intent: StartMeditationIntent(),
phrases: ["Start meditation in \(.applicationName)"],
shortTitle: "Meditate",
systemImageName: "figure.mind.and.body"
)
// Specific versions (skip parameter step)
AppShortcut(
intent: StartMeditationIntent(
meditationType: .mindfulness,
duration: 10
),
phrases: [
"Start quick mindfulness in \(.applicationName)",
"10 minute mindfulness in \(.applicationName)"
],
shortTitle: "Quick Mindfulness",
systemImageName: "brain.head.profile"
)
AppShortcut(
intent: StartMeditationIntent(
meditationType: .sleep,
duration: 20
),
phrases: [
"Start sleep meditation in \(.applicationName)"
],
shortTitle: "Sleep Meditation",
systemImageName: "moon.stars.fill"
)
}
Benefits:
Trade-off More shortcuts = more visual clutter in Shortcuts app. Balance common cases (3-5 shortcuts) vs flexibility (generic shortcut with parameters).
Train the system to NOT invoke your app for certain phrases.
struct MeditationAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: StartMeditationIntent(),
phrases: ["Start meditation in \(.applicationName)"],
shortTitle: "Meditate",
systemImageName: "figure.mind.and.body"
)
}
// Prevent false positives
static var negativePhrases: [NegativeAppShortcutPhrase] {
NegativeAppShortcutPhrases {
"Stop meditation"
"Cancel meditation"
"End session"
}
}
}
When to use:
Platform iOS 17.0+, iPadOS 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+
Display the spoken phrase for a shortcut directly in your app's UI.
import AppIntents
import SwiftUI
struct OrderConfirmationView: View {
@State private var showSiriTip = true
var body: some View {
VStack {
Text("Order confirmed!")
// Show Siri tip after successful order
SiriTipView(intent: ReorderIntent(), isVisible: $showSiriTip)
.siriTipViewStyle(.dark)
}
}
}
Requirements:
Styles:
.automatic — Adapts to environment.light — Light background.dark — Dark backgroundBest practice Show after users complete actions, suggesting easier ways next time.
Opens your app's page in the Shortcuts app, listing all available shortcuts.
import AppIntents
import SwiftUI
struct SettingsView: View {
var body: some View {
List {
Section("Siri & Shortcuts") {
ShortcutsLink()
// Displays "Shortcuts" with standard link styling
}
}
}
}
When to use:
Benefits Single tap takes users to see all your app's shortcuts, with suggested phrases visible.
Set the color for your shortcuts in the Shortcuts app.
struct CoffeeAppShortcuts: AppShortcutsProvider {
static var shortcutTileColor: ShortcutTileColor = .tangerine
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// ...
}
}
Available colors:
| Color | Use Case |
|---|---|
.blue | Default, professional |
.tangerine | Energy, food/beverage |
.purple | Creative, meditation |
.teal | Health, wellness |
.red | Urgent, important |
.pink | Lifestyle, social |
Full list: .blue, .grape, .grayBlue, .grayBrown, .grayGreen, .lightBlue, .lime, .navy, .orange, .pink, .purple, .red, , ,
Choose color that matches your app icon or brand identity.
Call when parameter options change to refresh stored shortcuts.
struct MeditationAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// Shortcuts can reference dynamic data
for session in MeditationData.favoriteSessions {
AppShortcut(
intent: StartSessionIntent(session: session),
phrases: ["Start \(session.name) in \(.applicationName)"],
shortTitle: session.name,
systemImageName: session.iconName
)
}
}
static func updateAppShortcutParameters() {
// Called automatically when needed
// Override only if you need custom behavior
}
}
// In your app, when data changes
extension MeditationData {
func markAsFavorite(_ session: Session) {
favoriteSessions.append(session)
// Update App Shortcuts to reflect new data
MeditationAppShortcuts.updateAppShortcutParameters()
}
}
When to call:
Automatic invocation The system calls this periodically, but you can force updates when you know data changed.
import AppIntents
struct OrderCoffeeIntent: AppIntent {
static var title: LocalizedStringResource = "Order Coffee"
static var description = IntentDescription("Orders coffee for pickup")
@Parameter(title: "Coffee Type")
var coffeeType: CoffeeType
@Parameter(title: "Size")
var size: CoffeeSize
@Parameter(title: "Customizations")
var customizations: String?
static var parameterSummary: some ParameterSummary {
Summary("Order \(\.$size) \(\.$coffeeType)") {
\.$customizations
}
}
func perform() async throws -> some IntentResult {
let order = try await CoffeeService.shared.order(
type: coffeeType,
size: size,
customizations: customizations
)
return .result(
value: order,
dialog: "Your \(size) \(coffeeType) is ordered for pickup"
)
}
}
struct ReorderLastIntent: AppIntent {
static var title: LocalizedStringResource = "Reorder Last Coffee"
static var description = IntentDescription("Reorders your most recent coffee")
static var openAppWhenRun: Bool = false
func perform() async throws -> some IntentResult {
guard let lastOrder = try await CoffeeService.shared.lastOrder() else {
throw CoffeeError.noRecentOrders
}
try await CoffeeService.shared.reorder(lastOrder)
return .result(
dialog: "Reordering your \(lastOrder.coffeeName)"
)
}
}
enum CoffeeType: String, AppEnum {
case latte, cappuccino, americano, espresso
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Coffee"
static var caseDisplayRepresentations: [CoffeeType: DisplayRepresentation] = [
.latte: "Latte",
.cappuccino: "Cappuccino",
.americano: "Americano",
.espresso: "Espresso"
]
}
enum CoffeeSize: String, AppEnum {
case small, medium, large
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Size"
static var caseDisplayRepresentations: [CoffeeSize: DisplayRepresentation] = [
.small: "Small",
.medium: "Medium",
.large: "Large"
]
}
import AppIntents
struct CoffeeAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
// Generic order (will ask for parameters)
AppShortcut(
intent: OrderCoffeeIntent(),
phrases: [
"Order coffee in \(.applicationName)",
"Get coffee from \(.applicationName)"
],
shortTitle: "Order",
systemImageName: "cup.and.saucer.fill"
)
// Common specific orders (skip parameter step)
AppShortcut(
intent: OrderCoffeeIntent(
coffeeType: .latte,
size: .medium
),
phrases: [
"Order my usual from \(.applicationName)",
"Get my regular coffee from \(.applicationName)"
],
shortTitle: "Usual Order",
systemImageName: "star.fill"
)
// Reorder last
AppShortcut(
intent: ReorderLastIntent(),
phrases: [
"Reorder coffee from \(.applicationName)",
"Order again from \(.applicationName)"
],
shortTitle: "Reorder",
systemImageName: "arrow.clockwise"
)
}
// Branding
static var shortcutTileColor: ShortcutTileColor = .tangerine
// Prevent false positives (iOS 17+)
static var negativePhrases: [NegativeAppShortcutPhrase] {
NegativeAppShortcutPhrases {
"Cancel coffee order"
"Stop coffee"
}
}
}
import SwiftUI
import AppIntents
struct OrderConfirmationView: View {
@State private var showReorderTip = true
var body: some View {
VStack(spacing: 20) {
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 60))
.foregroundColor(.green)
Text("Order Placed!")
.font(.title)
Text("Your coffee will be ready in 10 minutes")
.foregroundColor(.secondary)
// Promote reorder shortcut
if showReorderTip {
SiriTipView(intent: ReorderLastIntent(), isVisible: $showReorderTip)
.siriTipViewStyle(.dark)
.padding(.top)
}
// Link to see all shortcuts
Section {
ShortcutsLink()
} header: {
Text("See all available shortcuts")
.font(.caption)
}
}
.padding()
}
}
Once implemented, your App Shortcuts are available in:
| Location | User Experience |
|---|---|
| Siri | Voice activation with provided phrases |
| Spotlight | Search for action or phrase → Instant execution |
| Shortcuts app | Pre-populated shortcuts, zero configuration |
| Action Button (iPhone 15 Pro) | Assignable to hardware button |
| Apple Watch Ultra | Action Button assignment |
| Control Center | Add shortcuts as controls |
| Lock Screen widgets | Quick actions without unlocking |
| Apple Pencil Pro | Squeeze gesture assignment |
| Focus Filters | Contextual filtering |
Instant availability All locations work immediately after app install. No user setup required.
If shortcuts don't appear:
isDiscoverable is true for the AppIntents (default)Example :
If Siri doesn't recognize phrase:
\(.applicationName)If shortcut doesn't appear in Spotlight:
#if DEBUG
struct CoffeeAppShortcuts: AppShortcutsProvider {
@AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
let shortcuts = [
AppShortcut(/* ... */),
// ...
]
print("📱 Registered \(shortcuts.count) App Shortcuts")
shortcuts.forEach { shortcut in
print(" - \(shortcut.shortTitle)")
}
return shortcuts
}
}
#endif
Check Xcode console after app launch to verify shortcuts are registered.
phrases: [
"I would like to order a coffee from \(.applicationName) please"
]
phrases: [
"Order coffee in \(.applicationName)",
"Get coffee from \(.applicationName)"
]
Guidelines:
\(.applicationName) for disambiguation// Bad: Overwhelming
AppShortcut for every possible combination
// Good: Focused on common tasks
AppShortcut(intent: OrderIntent(), /* ... */)
AppShortcut(intent: ReorderIntent(), /* ... */)
AppShortcut(intent: ViewOrdersIntent(), /* ... */)
Why Too many shortcuts creates clutter. Focus on high-value, frequently-used actions.
// Bad: Creates 12 shortcuts (3 sizes × 4 types)
for size in CoffeeSize.allCases {
for type in CoffeeType.allCases {
AppShortcut(intent: OrderIntent(type: type, size: size), /* ... */)
}
}
// Good: Generic + common specific cases
AppShortcut(intent: OrderIntent(), /* ... */) // Generic
AppShortcut(intent: OrderIntent(type: .latte, size: .medium), /* ... */) // Usual
AppShortcut(intent: OrderIntent(type: .espresso, size: .small), /* ... */) // Quick
shortTitle: "Order Coffee from Coffee App"
shortTitle: "Order"
Context App name already appears in Shortcuts app, so no need to repeat.
// Not supported
shortImage: UIImage(named: "custom")
systemImageName: "cup.and.saucer.fill"
Why SF Symbols scale properly, support dark mode, and integrate with system UI.
WWDC : 2022-10170, 2022-10169, 260
Docs : /appintents/appshortcutsprovider, /appintents/appshortcut, /appintents/app-shortcuts
Skills : axiom-app-intents-ref, axiom-app-discoverability, axiom-core-spotlight-ref
Remember App Shortcuts make your app's functionality instantly available across iOS. Define 3-5 core shortcuts with natural phrases, promote them in your UI with SiriTipView, and users can invoke them immediately via Siri, Spotlight, Action Button, and more.
Weekly Installs
96
Repository
GitHub Stars
610
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode80
claude-code77
codex74
gemini-cli72
cursor71
github-copilot67
Intercom自动化指南:通过Rube MCP与Composio实现客户支持对话管理
69 周安装
二进制初步分析指南:使用ReVa工具快速识别恶意软件与逆向工程
69 周安装
PrivateInvestigator 道德人员查找工具 | 公开数据调查、反向搜索与背景研究
69 周安装
TorchTitan:PyTorch原生分布式大语言模型预训练平台,支持4D并行与H100 GPU加速
69 周安装
screenshot 截图技能:跨平台桌面截图工具,支持macOS/Linux权限管理与多模式捕获
69 周安装
tmux进程管理最佳实践:交互式Shell初始化、会话命名与生命周期管理
69 周安装
.navy| Business, finance |
.yellow | Productivity, notes |
.lime | Fitness, outdoor |
.tangerine.teal.yellow