name: Echo options: bundleIdPrefix: com.goosehouse deploymentTarget: iOS: "26.0" watchOS: "26.0" xcodeVersion: "27.0" createIntermediateGroups: true developmentLanguage: en generateEmptyDirectories: true # Code from outside Apple and this repository: the terminal's (Echo/Services/Terminal). Pinned: # SwiftTerm 1.12 onwards compiles a Metal shader (Xcode's separately downloaded Metal toolchain) and # 1.20 onwards runs a build-tool plugin Xcode wants trusted before every build and archive; 1.11.2 # needs neither. swift-nio-ssh is Apple's, on Apple's CryptoKit. The packages after swift-nio are # what these need, pinned here too: Package.resolved is inside Echo.xcodeproj, which isn't kept, so # without them every fresh checkout would take whatever is newest. packages: SwiftTerm: url: https://github.com/migueldeicaza/SwiftTerm exactVersion: 1.11.2 swift-nio-ssh: url: https://github.com/apple/swift-nio-ssh exactVersion: 0.15.0 swift-nio: url: https://github.com/apple/swift-nio exactVersion: 2.104.0 swift-crypto: url: https://github.com/apple/swift-crypto.git exactVersion: 4.5.2 swift-asn1: url: https://github.com/apple/swift-asn1.git exactVersion: 1.7.3 swift-atomics: url: https://github.com/apple/swift-atomics.git exactVersion: 1.3.1 swift-collections: url: https://github.com/apple/swift-collections.git exactVersion: 1.7.3 swift-system: url: https://github.com/apple/swift-system.git exactVersion: 1.8.1 swift-argument-parser: url: https://github.com/apple/swift-argument-parser exactVersion: 1.8.2 settings: base: DEVELOPMENT_TEAM: 579BSQT6J4 SWIFT_VERSION: "6.2" SWIFT_STRICT_CONCURRENCY: complete SWIFT_TREAT_WARNINGS_AS_ERRORS: true CODE_SIGN_STYLE: Automatic MARKETING_VERSION: "2.4" CURRENT_PROJECT_VERSION: "293" ENABLE_USER_SCRIPT_SANDBOXING: true # Translations: every target's text is pulled into the String Catalog beside its code # (Localizable.xcstrings in each target's folder), which the build fills with the English. SWIFT_EMIT_LOC_STRINGS: true targets: Echo: type: application platform: iOS sources: - path: Echo excludes: - Resources/Web - Resources/Redde.storekit # the scheme's local test store only; not shipped # Folder reference: keeps Web/fonts/ intact so katex.min.css can find its fonts. - path: Echo/Resources/Web type: folder buildPhase: resources - path: Shared dependencies: - target: EchoControls - target: EchoShare - target: EchoPush - target: EchoWatch - package: SwiftTerm - package: swift-nio-ssh product: NIOSSH - package: swift-nio product: NIOCore - package: swift-nio product: NIOPosix entitlements: path: Echo/Echo.entitlements properties: com.apple.security.application-groups: - group.com.goosehouse.echo # CarPlay: voice-based conversational apps (iOS 26.4+), enabled on the App ID. com.apple.developer.carplay-voice-based-conversation: true # Time-sensitive notifications, so Siri can announce Redde's alerts on AirPods. com.apple.developer.usernotifications.time-sensitive: true # Setup links, https://redde.goosehouse.org/connect#…, open in the app (universal links). # The site names this app in .well-known/apple-app-site-association (companion/website). com.apple.developer.associated-domains: - applinks:redde.goosehouse.org # Remote notifications from the push relay (Push Notifications is enabled on the App ID). # "development" is what the source carries; the App Store export rewrites it to production. aps-environment: development # Sync with iCloud (CloudSync): settings and servers in iCloud's key-value store. Their # secrets go in iCloud Keychain, which needs nothing more. com.apple.developer.ubiquity-kvstore-identifier: $(TeamIdentifierPrefix)$(CFBundleIdentifier) # Health-Aware Days (HealthDays): reads sleep, steps and workouts, off until turned on; # Health wakes Redde when new sleep or a workout is saved. com.apple.developer.healthkit: true com.apple.developer.healthkit.access: [] com.apple.developer.healthkit.background-delivery: true # Phone tools › Apple Home (DeviceHome): the agent sees and controls HomeKit accessories, # off until turned on. HomeKit is enabled on the App ID for this. com.apple.developer.homekit: true info: path: Echo/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) UILaunchScreen: {} # CarPlay scene. Multiple-scene support once stopped echo:// opens from widgets reaching the # app; the WindowGroup now routes every external event to the existing window (EchoApp). UIApplicationSceneManifest: UIApplicationSupportsMultipleScenes: true UISceneConfigurations: CPTemplateApplicationSceneSessionRoleApplication: - UISceneClassName: CPTemplateApplicationScene UISceneConfigurationName: CarPlay UISceneDelegateClassName: $(PRODUCT_MODULE_NAME).CarPlaySceneDelegate NSSupportsLiveActivities: true # Bundled fonts (Terminal theme). OFL license alongside in Resources/Fonts. UIAppFonts: - SourceCodePro-Medium.ttf - SourceCodePro-Bold.ttf - Inter-Regular.ttf - Inter-SemiBold.ttf - Inter-Bold.ttf CFBundleURLTypes: - CFBundleURLName: com.goosehouse.echo # echo: the app's own links (controls, share extension). redde: setup links, # redde://connect, which people see and type. CFBundleURLSchemes: [echo, redde] # Landscape too, for an iPhone Duo's outer screen standing like a tent: every other iPhone # is kept in portrait at run time (`Foldable.orientations`, from the app delegate). UISupportedInterfaceOrientations: - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad: - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight ITSAppUsesNonExemptEncryption: false # A reply the person started keeps streaming after the phone locks (BackgroundTurn): an # iOS 26 continued-processing task, one identifier per turn under this wildcard. Leave-By # Alerts (LeaveByAlerts): a background refresh shortly before the next alert, to move it with the traffic. BGTaskSchedulerPermittedIdentifiers: - com.goosehouse.echo.turn.* - com.goosehouse.echo.leaveby # `audio`: a voice conversation goes on when Redde isn't in front — the car screen switched # to navigation, the phone locked in a pocket — so listening and the spoken reply aren't # cut off with the foreground. Without it iOS stops the microphone and silences playback. UIBackgroundModes: - audio - processing # Calls from agents (AgentCalls): a VoIP push wakes Redde to ring with CallKit. - voip # Leave-By Alerts (LeaveByAlerts): the background refresh above. - fetch NSRemindersFullAccessUsageDescription: With Phone tools turned on, Redde reads and adds reminders when your assistant asks it to. They go only to the server you connect to. NSAlarmKitUsageDescription: With Phone tools turned on, Redde sets an alarm or a timer when your assistant asks it to, once you have said yes to it. NSContactsUsageDescription: With Phone tools turned on, Redde looks up a contact when your assistant asks it to. What it finds goes only to the server you connect to. NSPhotoLibraryUsageDescription: With Phone tools turned on, Redde finds photos, shows one to your assistant, or deletes the ones you confirm, when your assistant asks it to. A photo goes only to the server you connect to. # Places (Settings → Agent → Places): arriving at or leaving a place the person set tells the bot they chose. # Current Location (Settings → Agent → Current Location): roughly where the person is, for the agent. NSLocationWhenInUseUsageDescription: With Places on, Redde uses where you are to set a place and to notice when you arrive or leave; only "arrived at Home" goes to your server. With Current Location on, your own agent hears roughly where you are when you ask about places, directions or the weather. With Leave-By Alerts on, Redde works out from where you are when to leave for an event; where you are goes only to Apple Maps, for the way there. NSLocationAlwaysAndWhenInUseUsageDescription: With Places turned on, Redde notices when you arrive at or leave a place you set, even when Redde is closed, and tells the bot you chose. Where you are stays on your iPhone; only "arrived at Home" goes to your server. # Redde's folder in the Files app ("On My iPhone › Redde"): what Phone tools' files read and write. UIFileSharingEnabled: true LSSupportsOpeningDocumentsInPlace: true NSMotionUsageDescription: Redde reads head movement from your AirPods so you can nod to approve, or shake your head to deny, a request from your assistant. It is read on this device and never stored or sent. NSMicrophoneUsageDescription: Redde listens so you can talk to your assistant. Speech is transcribed on this device and only your own server receives the text, unless you start a live voice call, which goes to the voice service you chose. NSCalendarsFullAccessUsageDescription: Redde can show your next event when you start a conversation, and attach a day's events to a message for your assistant. With Phone tools turned on, your assistant can also look up events and add them. Events go only to your own server. With Leave-By Alerts on, Redde also reads your next events on this device and asks Apple Maps how long the way to their address takes, to tell you when to leave. NSCameraUsageDescription: Redde uses the camera when you take a photo to attach to a message, when you show your assistant something in voice mode, and to scan a setup code. A photo goes only to the server you connect to. NSFaceIDUsageDescription: Redde uses Face ID to unlock the app, which holds your Hermes credentials. NSLocalNetworkUsageDescription: Redde connects to the Hermes gateway or model server you configure, which is often on your local network. # Health-Aware Days (Settings → Agent → Health), off until turned on. NSHealthShareUsageDescription: Redde reads only the Health data you turn on. With Health-Aware Days, last night's sleep, your steps and your workouts shape your agent's morning ideas and evening wrap-up. With Phone Tools › Health, your agent can read the kinds you choose when it asks. It goes only to your own server. # Phone tools › Apple Home, off until turned on. NSHomeKitUsageDescription: With Phone Tools › Apple Home on, your agent can see your accessories and scenes and control them when you ask. Locks, garage doors, doors, windows and the alarm always ask you first. What it reads goes only to your own server. NSHealthUpdateUsageDescription: Redde doesn't save anything to Health. It only reads the Health data you turn on, for Health-Aware Days and Phone Tools. # Lets Siri accept "Hey Siri, ask Hermes" in addition to "ask Echo". INAlternativeAppNames: - INAlternativeAppName: Hermes INAlternativeAppNamePronunciationHint: her-meez - INAlternativeAppName: Sol INAlternativeAppNamePronunciationHint: sole # Echo talks only to servers the user configures (self-hosted Hermes, llama.cpp, Kokoro), # frequently on private networks without public certificates. Arbitrary loads are # allowed for that reason; HTTPS is used whenever the configured URL provides it. NSAppTransportSecurity: NSAllowsArbitraryLoads: true settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo TARGETED_DEVICE_FAMILY: "1,2" SUPPORTS_MACCATALYST: false SWIFT_EMIT_LOC_STRINGS: true # Redde Face (the bot face on Matte Mist) is the default; Matte Graphite, the glass Graphite # (AppIcon) and the rest are alternates. ASSETCATALOG_COMPILER_APPICON_NAME: AppIconFaceMist ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES: "AppIconBubbleGreen AppIconBubblePurple AppIconBubbleOrange AppIconBubblePink AppIconBubbleGraphite AppIconBubbleYellow AppIconBubbleGold AppIconStarMist AppIconStarGreen AppIconStarPurple AppIconStarOrange AppIconStarPink AppIconStarGraphite AppIconStarYellow AppIconStarGold AppIconGhostBlue AppIconGhostGreen AppIconGhostPurple AppIconGhostOrange AppIconGhostPink AppIconGhostGraphite AppIconGhostYellow AppIconGhostGold AppIcon AppIconGraphiteBlock AppIconSteelBlock AppIconMist AppIconGraphiteFlat AppIconGraphiteBlockFlat AppIconSteelFlat AppIconMistFlat AppIconNavyBlock AppIconInk AppIconPaperNavy AppIconGold AppIconClassic" ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor SWIFT_APPROACHABLE_CONCURRENCY: true SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SWIFT_OBJC_BRIDGING_HEADER: Echo/App/Echo-Bridging-Header.h configs: # The personal prefill never rides along in a Release / App Store build. Release: EXCLUDED_SOURCE_FILE_NAMES: LocalDefaults.json # The Apple Watch app. It talks to Hermes itself, with the connection the phone hands over # (Shared/WatchSync.swift), through the same transport code as the phone: those files are # listed one by one, since the rest of the app assumes iOS. EchoWatch: type: application platform: watchOS sources: - path: Watch - path: Shared/WatchSync.swift - path: Shared/WatchRelay.swift - path: Shared/Attachment.swift - path: Shared/PlainText.swift - path: Shared/ReplyMedia.swift - path: Echo/Services/Keychain.swift - path: Echo/Models/Message.swift - path: Echo/Models/ReplyCards.swift - path: Echo/Models/ReplyCardsMore.swift - path: Echo/Models/MailModels.swift - path: Echo/Models/WatchChats.swift # The complication's look and its link, shared with the extension that draws it. - path: WatchWidgets/AskComplication.swift - path: Echo/Models/ReplyLanguage.swift - path: Echo/Models/TurnNotes.swift - path: Echo/Models/MeasureUnits.swift - path: Echo/Models/CalendarChoice.swift - path: Echo/Models/CurrentLocation.swift - path: Echo/Models/AsideNote.swift - path: Echo/Models/Reactions.swift - path: Echo/Services/Transport/HermesTransport.swift - path: Echo/Services/Transport/HermesSessionsTransport.swift - path: Echo/Services/Transport/ChatCompletionsTransport.swift - path: Echo/Services/Transport/SSEParser.swift - path: Echo/Services/Transport/JSONValue.swift info: path: Watch/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) WKApplication: true WKCompanionAppBundleIdentifier: com.goosehouse.echo # Setup comes from the phone once; after that the watch asks Hermes on its own. WKRunsIndependentlyOfCompanionApp: true # A spoken reply keeps playing after the wrist goes down (Speaker). UIBackgroundModes, as # on iOS: WKBackgroundModes is for workout and extended runtime sessions, and App Store # Connect rejects a bundle that lists `audio` there. UIBackgroundModes: - audio NSAppTransportSecurity: NSAllowsArbitraryLoads: true dependencies: - target: EchoWatchWidgets settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.watchkitapp SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SWIFT_APPROACHABLE_CONCURRENCY: true ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor SKIP_INSTALL: true # The watch app's complications (WidgetKit). They share no data with the app, only a link it # opens, so the extension needs no app group. EchoWatchWidgets: type: app-extension platform: watchOS sources: - path: WatchWidgets info: path: WatchWidgets/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) NSExtension: NSExtensionPointIdentifier: com.apple.widgetkit-extension settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.watchkitapp.widgets SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SKIP_INSTALL: true EchoControls: type: app-extension platform: iOS sources: - path: EchoControls - path: Shared entitlements: path: EchoControls/EchoControls.entitlements properties: com.apple.security.application-groups: - group.com.goosehouse.echo info: path: EchoControls/Info.plist properties: CFBundleDisplayName: Redde Controls CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) NSSupportsLiveActivities: true NSExtension: NSExtensionPointIdentifier: com.apple.widgetkit-extension settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.controls SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SKIP_INSTALL: true ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor EchoShare: type: app-extension platform: iOS sources: - path: EchoShare - path: Shared entitlements: path: EchoShare/EchoShare.entitlements properties: com.apple.security.application-groups: - group.com.goosehouse.echo info: path: EchoShare/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) NSExtension: NSExtensionPointIdentifier: com.apple.share-services NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).ShareViewController NSExtensionAttributes: NSExtensionActivationRule: NSExtensionActivationSupportsText: true NSExtensionActivationSupportsWebURLWithMaxCount: 1 NSExtensionActivationSupportsImageWithMaxCount: 4 NSExtensionActivationSupportsFileWithMaxCount: 4 settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.share SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SKIP_INSTALL: true # Opens the sealed notifications a paired Hermes sends through the push relay (Shared/PushSeal). # Only what that takes is compiled in: an extension that runs for every notification stays small. EchoPush: type: app-extension platform: iOS sources: - path: EchoPush - path: Shared/PushSeal.swift # What a note says is waiting on the person goes on the "Needs you" widget. - path: Shared/NeedsYou.swift # And what the agent sent for its own widget while the phone wasn't following the turn. - path: Shared/AgentBoard.swift - path: Shared/DeviceDates.swift - path: Shared/PlainText.swift - path: Shared/ReplyMedia.swift - path: Shared/Attachment.swift # A muted chat's notification is delivered quietly. - path: Shared/MutedChats.swift # The agent's ideas, and what its watches saw, kept as they arrive with Redde closed. - path: Shared/AgentIdeas.swift - path: Shared/AgentWatches.swift - path: Shared/AgentGoals.swift - path: Shared/AgentBriefings.swift - path: Shared/DayBrief.swift - path: Shared/WeekPlan.swift - path: Shared/AgentActivityLog.swift - path: Shared/QuietHours.swift - path: Shared/LeaveTime.swift # Leave-By Alerts' traffic re-check, woken by the paired Hermes. - path: Shared/LeaveCheck.swift entitlements: path: EchoPush/EchoPush.entitlements properties: # The pairings' Keychain item is shared through the app group. com.apple.security.application-groups: - group.com.goosehouse.echo info: path: EchoPush/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) NSExtension: NSExtensionPointIdentifier: com.apple.usernotifications.service NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).NotificationService settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.push SKIP_INSTALL: true # The same for the Mac (asked 2026-10-30, "pair the mac and ipad for push"): EchoPush's code and # the same shared files, so a paired Hermes's notes open with Redde closed there too. Sandboxed, # as a Mac App Store extension must be; the pairings are in a Keychain group it shares with the # app (`PushVault.keychainGroup`): its own id's, which the app lists second. EchoPushMac: type: app-extension platform: macOS deploymentTarget: "26.0" sources: - path: EchoPush excludes: # The iPhone's: this one's own are in EchoPushMac/. - EchoPush.entitlements - Info.plist - path: Shared/PushSeal.swift - path: Shared/NeedsYou.swift - path: Shared/AgentBoard.swift - path: Shared/DeviceDates.swift - path: Shared/PlainText.swift - path: Shared/ReplyMedia.swift - path: Shared/Attachment.swift - path: Shared/MutedChats.swift - path: Shared/AgentIdeas.swift - path: Shared/AgentWatches.swift - path: Shared/AgentGoals.swift - path: Shared/AgentBriefings.swift - path: Shared/DayBrief.swift - path: Shared/WeekPlan.swift - path: Shared/AgentActivityLog.swift - path: Shared/QuietHours.swift - path: Shared/LeaveTime.swift - path: Shared/LeaveCheck.swift entitlements: path: EchoPushMac/EchoPushMac.entitlements properties: com.apple.security.app-sandbox: true # Ideas, briefings, what waits on the person: kept in the app group for the app to show. com.apple.security.application-groups: - group.com.goosehouse.echo # The pairings: this extension's own Keychain group, which the app shares (Mac/Redde.entitlements). keychain-access-groups: - $(AppIdentifierPrefix)$(PRODUCT_BUNDLE_IDENTIFIER) # A heads-up's leaving time asks Apple Maps the way (`LeaveTime.work`), from where the Mac # last was (the app keeps it in the app group): the extension never asks for a fix of its own. com.apple.security.network.client: true info: path: EchoPushMac/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) NSExtension: NSExtensionPointIdentifier: com.apple.usernotifications.service NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).NotificationService settings: base: # The iPhone extension's id, as the app is the iPhone's (one App ID for both); the Debug # app's own id has its own (below), the prefix an extension's id must start with. PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.push # No version of its own (UAT 2.3.1, 2026-10-31: a pinned 2.3 (279) sat inside the 2.3.1 (280) # app, which App Store Connect refuses): it takes the project's, as every other target does. SKIP_INSTALL: true ENABLE_HARDENED_RUNTIME: true SWIFT_TREAT_WARNINGS_AS_ERRORS: false configs: Debug: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.mac.push # Redde for the Mac (started 2026-10-27): a native SwiftUI app on the iPhone app's models, # services and views (Mac/ReddeMacApp.swift), in the iPad's layout, sandboxed (Mac/Redde.entitlements). ReddeMac: type: application platform: macOS deploymentTarget: "26.0" sources: - path: Mac - path: Echo/Models - path: Echo/Services excludes: # Frameworks the Mac doesn't have: CallKit and PushKit (calls), WatchConnectivity, # AlarmKit, MessageUI, CarPlay. - AgentCalls.swift - WatchLink.swift - WatchRelayHost.swift - DeviceTools/DeviceAlarms.swift - DeviceTools/DevicePeople.swift - Voice/WakeListener.swift - path: Echo/App/DevHooks.swift - path: Echo/App/FrameMonitor.swift # The app's resources as the iPhone's: pictures and colours, the translations, the fonts, # the sounds, the voice words, and the diagram and maths scripts (a folder, kept whole). - path: Echo/Resources excludes: - Web - Redde.storekit # The iPhone's permission texts in translation: the Mac has its own (Mac/InfoPlist.xcstrings). # With the iPhone's, a Mac in German asked for the camera "to scan a setup code" and # said things stay "on this iPhone". - InfoPlist.xcstrings - path: Echo/Resources/Web type: folder buildPhase: resources - path: Echo/Intents - path: Echo/Views excludes: # The iPhone's own: CarPlay's settings, alternate app icons, calls. - CarPlayVoiceSettings.swift - CarPlayBotSettings.swift - CarPlayCardSettings.swift - AppIconSettings.swift - AgentCallsSettingsView.swift # The SSH terminal is SwiftTerm's iPhone view; its Mac view comes later. - TerminalScreen.swift # The iPhone's side panel and its edge swipe. - SwipeToOpen.swift - path: Shared excludes: - AgentAlarm.swift - EchoTurnAttributes.swift - ApprovalIntents.swift dependencies: # Opens a paired Hermes's notes with Redde closed (Contents/PlugIns). - target: EchoPushMac - package: SwiftTerm - package: swift-nio-ssh product: NIOSSH - package: swift-nio product: NIOCore - package: swift-nio product: NIOPosix info: path: Mac/Info.plist properties: CFBundleDisplayName: Redde CFBundleShortVersionString: $(MARKETING_VERSION) CFBundleVersion: $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType: public.app-category.productivity # As the iPhone's: only Apple's encryption (HTTPS, CryptoKit), no export documents. ITSAppUsesNonExemptEncryption: false # The bundled fonts (the Terminal theme's), from the app's resources. ATSApplicationFontsPath: . # The permission texts the Mac can ask with, as the iPhone's say them. NSMicrophoneUsageDescription: Redde listens so you can talk to your assistant. Speech is transcribed on this device and only your own server receives the text, unless you start a live voice call, which goes to the voice service you chose. NSSpeechRecognitionUsageDescription: Redde turns what you say into text on this Mac, so you can talk to your assistant. NSCameraUsageDescription: Redde uses the camera when you show your assistant something in voice mode. A picture goes only to the server you connect to. # The AirPods' nod and shake (HeadGestures) is compiled in: App Store processing refused the # first upload (278, ITMS-90683) without it. NSMotionUsageDescription: Redde reads head movement from your AirPods so you can nod to approve, or shake your head to deny, a request from your assistant. It is read on this Mac and never stored or sent. NSCalendarsFullAccessUsageDescription: Redde can show your next event when you start a conversation, and attach a day's events to a message for your assistant. Events go only to your own server. With Leave-By Alerts on, Redde also reads your next events on this device and asks Apple Maps how long the way to their address takes, to tell you when to leave. NSRemindersFullAccessUsageDescription: With Phone tools turned on, Redde reads and adds reminders when your assistant asks it to. They go only to the server you connect to. NSContactsUsageDescription: With Phone tools turned on, Redde looks up a contact when your assistant asks it to. What it finds goes only to the server you connect to. NSPhotoLibraryUsageDescription: With Phone tools turned on, Redde finds photos, shows one to your assistant, or deletes the ones you confirm, when your assistant asks it to. A photo goes only to the server you connect to. # Places (Settings → Agent → Places): arriving at or leaving a place the person set tells the bot they chose. # Current Location (Settings → Agent → Current Location): roughly where the person is, for the agent. NSLocationWhenInUseUsageDescription: With Places on, Redde uses where you are to set a place and to notice when you arrive or leave; only "arrived at Home" goes to your server. With Current Location on, your own agent hears roughly where you are when you ask about places, directions or the weather. With Leave-By Alerts on, Redde works out from where you are when to leave for an event; where you are goes only to Apple Maps, for the way there. NSLocationAlwaysAndWhenInUseUsageDescription: With Places turned on, Redde notices when you arrive at or leave a place you set, even when Redde is closed, and tells the bot you chose. Where you are stays on this Mac; only "arrived at Home" goes to your server. # Current Location (Settings → Agent → Current Location): what the Mac asks with. NSLocationUsageDescription: With Current Location on, your own agent hears roughly where you are when you ask about places, directions or the weather. It goes to your own server and nowhere else. With Leave-By Alerts on, Redde works out from where you are when to leave for an event; where you are goes only to Apple Maps, for the way there. NSLocalNetworkUsageDescription: Redde connects to the Hermes gateway or model server you configure, which is often on your local network. # Hermes servers are often on a home network, without public certificates. NSAppTransportSecurity: NSAllowsArbitraryLoads: true settings: base: # Shipped under the iPhone's id: one purchase, one App Store record, and the container of the # iPad app a Mac may already run. Debug keeps an id of its own (below), so a build made here # never opens that iPad app's data. PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo PRODUCT_NAME: Redde # Redde Face on the Mac's icon grid (Mac/Assets.xcassets), made from the iPhone's default. ASSETCATALOG_COMPILER_APPICON_NAME: AppIconMac ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor SWIFT_EMIT_LOC_STRINGS: true SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SWIFT_APPROACHABLE_CONCURRENCY: true SWIFT_TREAT_WARNINGS_AS_ERRORS: false SWIFT_OBJC_BRIDGING_HEADER: Echo/App/Echo-Bridging-Header.h CODE_SIGN_ENTITLEMENTS: Mac/Redde.entitlements ENABLE_HARDENED_RUNTIME: true configs: Debug: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.mac Release: EXCLUDED_SOURCE_FILE_NAMES: LocalDefaults.json EchoTests: type: bundle.unit-test platform: iOS sources: - path: EchoTests # The status widgets' views and timelines, compiled in so the tests can draw them # (the file imports the app when WIDGET_VIEWS_IN_TESTS is set). - path: EchoControls/StatusWidgets.swift - path: EchoControls/BoardWidget.swift - path: EchoControls/UpNextWidget.swift dependencies: - target: Echo settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.tests GENERATE_INFOPLIST_FILE: true SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor SWIFT_ACTIVE_COMPILATION_CONDITIONS: $(inherited) WIDGET_VIEWS_IN_TESTS EchoUITests: type: bundle.ui-testing platform: iOS sources: - path: EchoUITests dependencies: - target: Echo settings: base: PRODUCT_BUNDLE_IDENTIFIER: com.goosehouse.echo.uitests GENERATE_INFOPLIST_FILE: true TEST_TARGET_NAME: Echo schemes: Echo: build: targets: Echo: all EchoTests: [test] run: config: Debug # Tips work in the simulator and debug builds before the products exist in App Store Connect. storeKitConfiguration: Echo/Resources/Redde.storekit test: config: Debug targets: - EchoTests EchoUITests: build: targets: Echo: all EchoUITests: [test] test: config: Debug targets: - EchoUITests archive: config: Release