mcpField
A
app-intents

app-intents

github.com/n0an开发39523 次安装5 周前更新
代码仓库

关于 app-intents

app-intents 是用于编写和审查 Swift 代码的技能,可通过 Apple 的 App Intents 框架公开应用功能。它按任务提供指导,并检查 Intent、实体、Siri、Spotlight、测试及相关集成。

主要功能

  1. 01审查 Intent 协议、参数和结果
  2. 02验证实体、查询与 Spotlight 索引
  3. 03指导 Siri 和 Apple Intelligence 集成
  4. 04检查快捷指令、导航和片段行为
  5. 05涵盖依赖模式、执行与测试

适用场景

  1. 01创建 App Intent 并注册以便发现
  2. 02让 Siri 或 Spotlight 搜索应用数据
  3. 03通过 Siri 或快捷指令打开特定应用实体
  4. 04测试 Intent 或排查实现错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/n0an/app-intents-agent-skill --skill app-intents

安装后在 Claude Code 中输入/app-intents确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
anti-patterns.md
assistant-schemas.md
dependencies.md
entities.md
fundamentals.md
long-running-and-execution.md
onscreen-awareness.md
open-and-snippet-intents.md
parameters.md
shortcuts-and-siri.md
siri-intelligence.md
spotlight.md
testing-intents.md

详细介绍

编写和审查 Swift 代码,通过 App Intents 框架公开应用功能,确保符合协议要求、数据流安全,并采用符合惯例且便于发现的接入方式。

审查流程:

  1. 使用 references/fundamentals.md 检查意图基础知识(协议、perform()、返回类型、对话)。
  2. 使用 references/parameters.md 验证参数和参数选项。
  3. 使用 references/entities.md 验证实体类型、显示形式和查询。
  4. 使用 references/shortcuts-and-siri.md 检查 AppShortcutsProvider 注册和发现界面。
  5. 使用 references/open-and-snippet-intents.md 验证 OpenIntent 导航和片段视图返回类型。
  6. 使用 references/dependencies.md 检查依赖项注入和数据控制器模式。
  7. 使用 references/spotlight.md 验证通过 IndexedEntity、IndexedEntityQuery 和属性集进行的 Spotlight 索引。
  8. 使用 references/assistant-schemas.md 检查 @AssistantEntity / @AssistantIntent 架构的采用情况。
  9. 使用 references/siri-intelligence.md 验证 Siri / Apple Intelligence 集成(查找内容、自定义响应、捐赠、确认、所有权)。
  10. 使用 references/onscreen-awareness.md 检查屏幕内容感知和内容传输(视图注释、IntentValueRepresentation、系统集成注释)。
  11. 对于运行时间超过 30 秒、需要处理取消操作或针对特定进程的意图,请使用 references/long-running-and-execution.md。
  12. 如果要编写或审查意图测试,请使用 references/testing-intents.md(涵盖新的 AppIntentsTesting 框架)。
  13. 使用 references/anti-patterns.md 发现常见错误。

如果只处理部分内容,请仅加载相关参考文件。

按任务路由

根据用户目标匹配阅读顺序。只加载所需内容。

“创建我的第一个 App Intent”
  1. references/fundamentals.md - 协议、perform()、返回类型
  2. references/shortcuts-and-siri.md - 注册意图,使其显示出来
“添加一个由用户在快捷指令中选择的参数”
  1. references/parameters.md - @Parameter、提示词、消歧
  2. references/entities.md - 如果参数是领域实体
“让 Siri / Spotlight 能搜索我的应用数据”
  1. references/entities.md - AppEntity、IndexedEntity、@Property
  2. references/spotlight.md - 索引策略、属性集
  3. references/shortcuts-and-siri.md - 灵活匹配、短语规则
“Siri 运行我的意图时显示摘要 / 交互视图”
  1. references/open-and-snippet-intents.md - 内联与间接片段、SnippetIntent、Button(intent:)
  2. references/fundamentals.md - 返回类型和片段设计规则
“通过 Siri / 快捷指令在我的应用中打开特定内容”
  1. references/open-and-snippet-intents.md - OpenIntent、URLRepresentableIntent、TargetContentProvidingIntent
  2. references/dependencies.md - 导航器 / 场景路由
“将我的应用内容和操作引入 Siri / Apple Intelligence”
  1. references/siri-intelligence.md - 集成模式、查找内容(语义索引 / 结构化搜索 / 应用内搜索)、自定义响应、捐赠、确认 / 所有权
  2. references/assistant-schemas.md - 架构宏、领域、多架构要求、Xcode 代码片段
  3. references/onscreen-awareness.md - 视图注释、内容传输、系统集成注释
“集成 Apple Intelligence”
  1. references/assistant-schemas.md - 架构宏、领域、“使用模型”操作、屏幕内容
  2. references/entities.md - @Property、Transferable(多个架构所必需)
“让 Siri 理解屏幕上的内容”
  1. references/onscreen-awareness.md - 4 种注释 API、内容传输、displayRepresentations 快捷路径、通知 /“正在播放”/ AlarmKit 中的注释
  2. references/siri-intelligence.md - 屏幕上下文如何融入更广泛的 Siri 体系
“让我的意图运行超过 30 秒或面向某个进程”
  1. references/long-running-and-execution.md - LongRunningIntent、CancellableIntent、allowedExecutionTargets、后台 GPU
  2. references/fundamentals.md - ProgressReportingIntent、supportedModes
“高效处理大量实体/跨设备同步”
  1. references/parameters.md - EntityCollection(仅标识符参数)
  2. references/entities.md - 用于跨设备标识的 SyncableEntity、用于主动建议的 RelevantEntities
“支持 Visual Intelligence/图像搜索”
  1. references/assistant-schemas.md - IntentValueQuery、SemanticContentDescriptor、@UnionValue
  2. references/entities.md - Transferable + OpenIntent 配对
“构建交互式小组件或控制中心控件”
  1. references/open-and-snippet-intents.md - Button(intent:)、WidgetConfigurationIntent、ControlConfigurationIntent、ControlWidgetButton
  2. references/dependencies.md - App Group 共享存储、进程边界
“围绕 App Intents 组织我的应用”
  1. references/fundamentals.md - 将意图作为规范的操作层
  2. references/dependencies.md - @Dependency、跨模块 AppIntentsPackage
  3. references/entities.md - 实体桥接模式
“测试我的 App Intents”
  1. references/testing-intents.md - AppIntentsTesting 框架(进程外集成)、直接对结构体进行单元测试、模拟 @Dependency、仅用于测试的意图,以及无法测试的内容
“我遇到了构建错误或运行时问题”
  1. references/anti-patterns.md - 35+ 项检查及修复前后对照

决策树

已知任务但不确定该使用哪个 API 时,可快速参考。

我应该遵循哪个意图协议?
Generic action?
  → AppIntent

Opens the app to a specific entity?
  → OpenIntent (+ TargetContentProvidingIntent on iOS)
  → on iOS 27+, @AppIntent(schema: .system.open) on the OpenIntent, with a legacy sibling intent for older OS

Renders an interactive view only, no business logic?
  → SnippetIntent

Needs to bring the app forward conditionally?
  → AppIntent with supportedModes (iOS 26+)
  → or ForegroundContinuableIntent (iOS 17-18)

Runs longer than 30 seconds (upload, sync, inference)?
  → LongRunningIntent + performBackgroundTask (iOS 27+)

Needs to clean up gracefully when cancelled (with the reason)?
  → CancellableIntent + withIntentCancellationHandler (iOS 26.4+)

Deletes entities with standard confirmation?
  → DeleteIntent

Routes a search query into the app?
  → ShowInAppSearchResultsIntent

Backs widget configuration?
  → WidgetConfigurationIntent (empty conformance, no perform)

Backs a Control Center control?
  → ControlConfigurationIntent

Has a universal-link URL representation?
  → URLRepresentableIntent + OpenIntent (no perform needed)

Matches an Apple Intelligence domain?
  → AppIntent + @AppIntent(schema: .domain.action)
我应该使用哪种实体类型?
Fixed set known at compile time?
  → AppEnum

Dynamic data with a persistent id?
  → AppEntity

Entity must appear in Spotlight?
  → AppEntity + IndexedEntity

Entity IS a file (scan, voice memo, exported image)?
  → FileEntity

Computed / aggregated data with no stable id?
  → TransientAppEntity

Needs Apple Intelligence schema awareness?
  → AppEntity + @AppEntity(schema: .domain.type)

Supports cross-app sharing?
  → AppEntity + Transferable
我的实体应该使用哪种查询?
Small fixed set, enumerable?
  → EnumerableEntityQuery (also gets a basic Find intent)

Large dataset, searchable by name?
  → EntityQuery + EntityStringQuery

Many queryable properties, user should build predicates?
  → EntityPropertyQuery (auto-generates Find intent with comparators + sort)

Simple id-only lookup, no search?
  → UniqueIDEntityQuery

Indexed in Spotlight and want reindexing support?
  → IndexedEntityQuery (iOS 27+)

Structured Siri search you can't index ahead of time?
  → IntentValueQuery (structured input, returns 1+ entity types via @UnionValue)

Visual intelligence / image search?
  → IntentValueQuery + SemanticContentDescriptor
Siri 应该如何找到我的内容?
Content is local and indexable?
  → IndexedEntity + indexAppEntities (semantic index) - the primary path
  → add IndexedEntityQuery for reindexing support (iOS 27+)

Too large / server-side / too volatile to index?
  → IntentValueQuery (structured search input)

User wants to search inside your own UI?
  → @AppIntent(schema: .system.searchInApp) + ShowInAppSearchResultsIntent

Content nobody has found or used yet, but relevant right now?
  → RelevantEntities.updateEntities(_:for:) (iOS 27+)

Teach the system how people use the app (patterns)?
  → IntentDonationManager (donate UI interactions)
实体字段应该使用哪个属性包装器?
Stored on the entity struct, should appear in Shortcuts/Find/summary?
  → @Property

Derived from an underlying model object (cheap to compute)?
  → @ComputedProperty (preferred over @Property for wrappers around models)

Derived AND should be indexed in Spotlight?
  → @ComputedProperty(indexingKey: \.keyName)

Expensive to compute (network, ML inference, heavy query)?
  → @DeferredProperty (async getter, only runs when system asks)

Internal to the entity, not shown anywhere?
  → plain stored property (no wrapper)

核心说明

  • App Intents 的最低目标版本为 iOS 16+ / macOS 13+。IndexedEntity、OpenIntent、焦点筛选器和控制小组件需要 iOS 16+;@AssistantEntity / @AssistantIntent 架构需要 iOS 18.2+;锚定相对日期样式和许多助手架构需要 iOS 18.4+。27 系列版本(WWDC 2026、iOS 27 / macOS 27)新增了 LongRunningIntent、EntityCollection、SyncableEntity、RelevantEntities、IndexedEntityQuery、OwnershipProvidingEntity、allowedExecutionTargets、AppIntentsTesting 框架,以及原生 Duration / PersonNameComponents 参数;CancellableIntent 和 IntentValueRepresentation 需要 iOS 26.4+;supportedModes 需要 iOS 26+。Apple 对 WWDC 2026 这一批版本的官方称呼是“27 系列版本”——请使用这个称呼,而不是“iOS 19”。
  • 绝不要让 SwiftData @Model 类或其他引用类型数据模型遵循 AppEntity。AppEntity 要求遵循 Sendable;@Model 类无法遵循 Sendable。请创建一个单独的 struct 实体,仅映射你想公开的字段。
  • 绝不要跨 actor 边界传递 ModelContext。ModelContext 无法遵循 Sendable。请传递可遵循 Sendable 的 ModelContainer,并在需要它的 actor 内创建本地 context。
  • 绝不要只通过编写 intent 类型来向 Siri / Spotlight 公开 intent;始终通过 AppShortcutsProvider 注册。未在其中注册的类型不会出现在快捷指令、Siri 建议或操作按钮选择器中。
  • 绝不要编写未插入 \(.applicationName) 的 Siri 激活短语。App Intents 宏会在编译时拒绝缺少该内容的短语,因为不带应用名称的短语会与其他应用的命令冲突。
  • 绝不要在 intent 中访问 SwiftUI @Query。@Query 只能在 View 内使用。请通过 ModelContext 执行一次性的 FetchDescriptor,或通过集中式数据控制器进行路由。
  • 绝不要在 perform() 中实例化服务、数据存储或身份验证管理器。请通过 @Dependency 注入,并在 App.init() 中使用 AppDependencyManager.shared.add(dependency:) 注册一次。
  • 绝不要使用 String(format:) 或手动拼接来生成本地化的 intent 对话文本。请使用 LocalizedStringResource,并在 AttributedString 中使用 Foundation 的语法一致性 Markdown(^[\(count) item](inflect: true))处理复数形式。
  • 当 intent 可能在应用的存储区 / 导航界面尚未创建时触发(冷启动、启动画面、存储区在根视图中创建),请通过主 actor 路由器分发操作,在 UI 接入前先将操作排队;并通过同一个操作发送 Spotlight CSSearchableItemActionType 用户活动。请参阅 references/open-and-snippet-intents.md。
  • 对于“带我去这个内容”之类的操作,优先使用 OpenIntent;对于独立的一次性摘要,使用 AppIntent & ShowsSnippetView;如果片段中包含 Button(intent:) 且需要在按钮触发后重新渲染,则使用 AppIntent & ShowsSnippetIntent 并配对一个 SnippetIntent。
  • 对于仅用于支持小组件按钮、片段按钮或其他 intent 的辅助 intent,始终设置 static let isDiscoverable: Bool = false;否则它们会污染用户的快捷指令库。
  • 当 intent 修改了小组件或控制小组件所显示的数据时,请在返回前于 perform() 中调用 WidgetCenter.shared.reloadAllTimelines()。
  • 当 Button(intent:) 位于小组件视图中时,应通过 App Group UserDefaults(suiteName:) 或共享的 ModelContainer URL,在 intent(运行于应用进程)和小组件时间线提供器(运行于扩展进程)之间共享状态;绝不要使用 UserDefaults.standard 或内存中的 @Dependency 状态。
  • 当快捷指令短语的键路径中所引用的实体数据发生变化(创建、重命名、删除)时,请调用 YourShortcutsProvider.updateAppShortcutParameters(),使缓存的候选项列表失效。
  • 当整个集合规模较小且加载成本低时,优先使用 EnumerableEntityQuery;当数据集规模较大或需要搜索时,实现 EntityQuery + EntityStringQuery;添加 EntityPropertyQuery,即可免费获得系统生成的查找 intent。每个查询都必须实现 entities(for identifiers:);如果缺少它,参数解析就会出错。
  • 对于用户可能用于筛选、排序或在参数摘要中引用的实体字段,请使用 @Property(存储属性)或 @ComputedProperty(派生属性)进行标记。App Intents 框架无法识别普通存储属性。
  • 对于动态计算的返回数据(摘要、聚合结果),请使用 TransientAppEntity。不要用虚构 ID 强行将其塞进 AppEntity。
  • 如果实体已有通用链接 URL,请让它遵循 URLRepresentableEntity,并让打开 intent 遵循 URLRepresentableIntent——系统会通过现有链接处理器路由打开操作,无需实现 perform()。
  • 对于屏幕上可见且 Siri 应能理解的实体,请在视图上使用 .userActivity(_:element:),并让实体遵循 Transferable。仅有标识信息还不够;Siri 需要可导出的内容。
  • 每次用户交互都会多次调用 SnippetIntent.perform()(初次显示、每次点击按钮后、外观变化时、调用 reload() 时)。请保持其纯粹:读取状态、组装视图并返回。绝不要在片段 intent 的 perform() 中修改应用状态或启动耗时任务。
  • 遵守硬性限制:每个应用最多 10 个 AppShortcut,触发短语总数最多 1000 个(包括参数展开)。每个快捷指令数组中的第一个短语是主要短语——它会显示在快捷指令首页磁贴上,也会作为 Siri 对“我可以用 X 做什么?”的回答。
  • 每个 App Shortcut 至少包含一个不带参数的短语,以便在首次启动前也能被发现;在应用运行一次并填充参数缓存之前,带参数的短语不会出现在 Spotlight 中。
  • 对于有条件切换到前台的新代码,优先使用 supportedModes + continueInForeground(iOS 26+),而不是 ForegroundContinuableIntent / needsToContinueInForegroundError。较新的形式允许一个 intent 根据运行时状态声明其可以在后台或前台运行。
  • 片段视图的高度上限为 340 点;超过此高度会破坏快速浏览覆盖层的交互模式。较深的内容应链接到完整应用,并确保片段文本大于系统默认字号,以便在阅读距离下清晰可辨。
  • 对于可能接收来自 Apple Intelligence“使用模型”操作输入的文本参数,请声明类型为 AttributedString 而不是 String,以无损保留富文本格式(粗体、斜体、列表、表格)。
  • 即使 UI 从未显示,只要 intent 运行,应用的 App 结构体初始化器就会执行。所有与 intent 相关的设置(创建 ModelContainer、调用 AppDependencyManager.shared.add(...)、配置日志)都应放在 init() 中,而不是放在 .task 或 .onAppear 等视图修饰符中。
  • LocalizedStringResource 是 App Intents 中各处(标题、对话文本、参数提示)的标准字符串类型。它与 SwiftUI 共用字符串目录,因此无需额外配置即可实现本地化。
  • 语法一致性(inflect: true)适用于英语、法语、德语、意大利语、西班牙语和葡萄牙语(两种变体)。其他语言环境会回退到未修改的形式。
  • 从系统界面触发的 intent 可运行约 30 秒(macOS 没有硬性时限)。对于上传、同步、大型文件操作或设备端推理,请遵循 LongRunningIntent,并在 performBackgroundTask { ... } 中执行工作——还要定期报告 progress,因为如果长时间没有进度更新,系统会撤销运行时扩展。可搭配 CancellableIntent,根据取消原因执行清理。不要尝试通过分离的 Task 绕过时限;非托管任务不受扩展机制保护。
  • 对于可能包含多个实体、且 perform() 主要需要 ID 的参数,请使用 EntityCollection<Entity> 而不是 [Entity]——它会在参数处理期间跳过完整实体解析。仅在需要完整对象时才调用 resolvedEntities()。
  • 在基于架构的更新 intent 中,请通过 $parameter.valueState(.set(value) / .set(nil) / .unset)区分“不修改”和“清除”,而不是仅检查 nil;否则语音命令无法清除字段。
  • 如果 Siri 可能在跨设备对话中引用某个实体,请让它遵循 SyncableEntity。如果 ID 在所有设备上都一致(服务器 UUID、CloudKit 记录 ID),直接采用该协议即可;否则,请通过 SyncableEntityIdentifier 配对本地 ID 和稳定 ID。
  • 请让可共享实体遵循 OwnershipProvidingEntity,并保持其 ownership(.shared / .public)为最新状态,以便 Siri 在用户对其共享或发布的内容执行操作时请求确认。默认情况下,Siri 会假定实体为私有内容,因此可能跳过确认。
  • 要传递其他应用可理解的结构化类型(坐标、联系人、姓名),请通过 ValueRepresentation 构建器将 IntentValueRepresentation 添加到实体的 transferRepresentation 中——FileRepresentation / DataRepresentation 仅支持文件格式。如果实体已存储系统类型,请使用键路径形式(ValueRepresentation(exporting: \.place))。
  • 对于屏幕内容感知,请根据对象形态选择注解:对一个主要项目使用 .userActivity,对少量项目中的某一个使用 .appEntityIdentifier(_:),对 List / 集合中的多个项目(惰性加载)使用 .appEntityIdentifier(forSelectionType:),对自定义 Canvas / CALayer 绘图使用 .appEntityUIElements(_:)。通知、“正在播放”和 AlarmKit 中的注解需要真正的 AppEntity——TransientAppEntity 没有持久 ID,无法在这些场景中使用。请添加 displayRepresentations 查询方法,使 Siri 无需完整数据库读取即可解析屏幕上的实体。
  • 使用 IntentDonationManager 捐赠 UI 交互(系统已自动捐赠 Siri / 快捷指令运行记录);请在操作完成后再捐赠,不要过度捐赠(系统会开始忽略你的捐赠),并删除过时的捐赠记录。
  • 使用 AppIntentsTesting 框架进行测试(在 XCUITest bundle 中进程外运行),以覆盖集成界面——intents、查询、spotlightQuery()、viewAnnotations();使用仅用于测试的 intents(isDiscoverable = false + #if DEBUG)来填充数据并访问内部状态。对于纯逻辑,请保留直接测试 perform() 结构体的做法。

输出格式

如果用户要求进行审查,请按文件整理问题。对于每个问题:

  1. 说明文件和相关行号。
  2. 指明要替换的反模式。
  3. 展示简短的修复前后代码。

跳过没有问题的文件。最后按优先级总结最值得优先处理的改动。

示例输出:

RecentItemsIntent.swift

第 18 行:SwiftData @Model 无法遵循 AppEntity(不符合 Sendable)。

// Before
extension Article: AppEntity { ... }

// After
struct ArticleEntity: AppEntity {
    var id: UUID
    var title: String
    static let typeDisplayRepresentation: TypeDisplayRepresentation = "Article"
    static let defaultQuery = ArticleEntityQuery()
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(title)")
    }
}

第 42 行:Siri 短语缺少 \(.applicationName),将导致构建失败。

// Before
AppShortcut(intent: OpenArticleIntent(), phrases: ["Open an article"], ...)

// After
AppShortcut(intent: OpenArticleIntent(), phrases: ["Open an article in \(.applicationName)"], ...)
总结
  1. 可发送性(高): Article 作为 AppEntity 将无法通过 Swift 6 编译;请创建一个影子结构体。
  2. Siri 短语(高): 每个短语都必须包含 \(.applicationName)。

示例结束。

参考资料

  • references/fundamentals.md - AppIntent 协议、perform()、返回类型(IntentResult、ProvidesDialog、ReturnsValue、ShowsSnippetView、OpensIntent)、意图对话、语法一致性。
  • references/parameters.md - @Parameter、基本类型与实体参数、@AppEnum、对话选项、参数提示词。
  • references/entities.md - AppEntity、IndexedEntity、影子结构体模式、显示表示形式、实体查询(EnumerableEntityQuery、EntityQuery、EntityStringQuery、UniqueIDEntityQuery)。
  • references/shortcuts-and-siri.md - AppShortcutsProvider、短语(\(.applicationName) 规则)、shortcutTileColor、SiriTipView、ShortcutsLink、参数呈现方式。
  • references/open-and-snippet-intents.md - OpenIntent、片段视图(ShowsSnippetView)、通过数据控制器导航、各自适用的场景。
  • references/dependencies.md - @Dependency、AppDependencyManager、数据控制器模式、ModelContainer 与 ModelContext 的可发送性、主线程隔离与本地上下文的权衡。
  • references/spotlight.md - IndexedEntity、IndexedEntityQuery(重新索引)、CSSearchableIndex、attributeSet、语义索引、启动时索引与变更时索引、去抖重新索引。
  • references/assistant-schemas.md - @AssistantEntity、@AssistantIntent、采用架构、多架构要求、.system.searchInApp、视觉智能(iPad/macOS、系统存储)、Xcode 代码片段、注意事项。
  • references/siri-intelligence.md - Siri / Apple Intelligence 集成模型:查找内容(语义索引 / 结构化搜索 / 应用内搜索)、自定义响应、交互捐赠、确认 + OwnershipProvidingEntity、验证流程。
  • references/onscreen-awareness.md - 4 种屏幕内容标注 API、内容传输(IntentValueRepresentation、解析与导入)、displayRepresentations 快速路径、通知 / 现在播放 / AlarmKit 中的实体标注。
  • references/long-running-and-execution.md - 30 秒时限、LongRunningIntent + performBackgroundTask、CancellableIntent、后台 GPU、allowedExecutionTargets。
  • references/testing-intents.md - AppIntentsTesting 框架(进程外集成)、直接进行 perform() 单元测试、通过 AppDependencyManager 模拟 @Dependency、仅用于测试的意图、无法进行单元测试的内容。
  • references/anti-patterns.md - LLM 生成 App Intents 代码时常犯的错误。

评论

支持 Markdown