From 6440ce21f6d0d38a5c519b3a7a18cb9f7762efba Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 19 Jun 2026 08:27:36 -0400 Subject: [PATCH 1/2] feat: add Photos crawler integration --- CHANGELOG.md | 4 ++ README.md | 1 + .../BuiltInCrawlApps+Photoscrawl.swift | 47 +++++++++++++++++++ .../BuiltInApps/BuiltInCrawlApps.swift | 2 + Sources/CrawlBarSelfTest/SelfTestConfig.swift | 4 ++ 5 files changed, 58 insertions(+) create mode 100644 Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index c536d89..825a8cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Changes + +- Add Apple Photos as a built-in crawler with read-only status, refresh, search, platform-native storage paths, and configurable library selection. + ### Fixes - Install OpenClaw crawler apps from the current Homebrew tap instead of legacy formulas that lag released versions. diff --git a/README.md b/README.md index 2a70b64..d383cf0 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Built-in manifests ship for: - `discrawl` - `telecrawl` - `imsgcrawl` +- `photoscrawl` - `notcrawl` - `gogcli` through the `gog` executable - `wacli` diff --git a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift new file mode 100644 index 0000000..68f417c --- /dev/null +++ b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift @@ -0,0 +1,47 @@ +import Foundation + +public extension BuiltInCrawlApps { + static let photoscrawl = CrawlAppManifest( + id: Self.photoscrawlID, + displayName: "Apple Photos", + description: "Local-first, read-only Apple Photos archive crawler", + binary: .init(name: "photoscrawl"), + branding: .init( + symbolName: "photo.on.rectangle.angled", + accentColor: "#FF2D55", + bundleIdentifier: "com.apple.Photos"), + paths: .init( + defaultConfig: "~/Library/Application Support/photoscrawl/config.toml", + defaultDatabase: "~/Library/Application Support/photoscrawl/photos.sqlite", + defaultCache: "~/Library/Caches/photoscrawl", + defaultLogs: "~/Library/Application Support/photoscrawl/logs", + defaultShare: "~/Library/Application Support/photoscrawl/share"), + commands: [ + "metadata": ["metadata", "--json"], + "status": ["status", "--json"], + "refresh": ["crawl", "--library", "{config:library_path}", "--json"], + "query": ["search", "--json", "--query"], + ], + capabilities: [.status, .refresh, .search], + statusRequiresSecrets: false, + privacy: .init( + exportsSecrets: false, + localOnlyScopes: [ + "apple-photos", + "sqlite", + "media-metadata", + "location-observations", + "local-model-observations", + ]), + configOptions: [ + .init( + id: "library_path", + label: "Photos library", + help: "Photos Library package read by refresh; photoscrawl expands a leading ~/ path.", + defaultValue: "~/Pictures/Photos Library.photoslibrary"), + ], + configSections: [ + .init(id: "photos", title: "Photos Library", optionIDs: ["library_path"]), + ]) + .withSuggestion(Self.appSuggest("Photos", ["com.apple.Photos"])) +} diff --git a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift index d92e410..ce16f50 100644 --- a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift +++ b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift @@ -6,6 +6,7 @@ public enum BuiltInCrawlApps { public static let discrawlID = CrawlAppID(rawValue: "discrawl") public static let telecrawlID = CrawlAppID(rawValue: "telecrawl") public static let imsgcrawlID = CrawlAppID(rawValue: "imsgcrawl") + public static let photoscrawlID = CrawlAppID(rawValue: "photoscrawl") public static let notcrawlID = CrawlAppID(rawValue: "notcrawl") public static let gogcliID = CrawlAppID(rawValue: "gogcli") public static let wacliID = CrawlAppID(rawValue: "wacli") @@ -18,6 +19,7 @@ public enum BuiltInCrawlApps { Self.discrawl, Self.telecrawl, Self.imsgcrawl, + Self.photoscrawl, Self.notcrawl, Self.gogcli, Self.wacli, diff --git a/Sources/CrawlBarSelfTest/SelfTestConfig.swift b/Sources/CrawlBarSelfTest/SelfTestConfig.swift index f9b1b6e..52dbf1a 100644 --- a/Sources/CrawlBarSelfTest/SelfTestConfig.swift +++ b/Sources/CrawlBarSelfTest/SelfTestConfig.swift @@ -14,6 +14,10 @@ extension CrawlBarSelfTest { try Self.expect(config.apps.map(\.id) == BuiltInCrawlApps.all.map(\.id), "built-in apps are present") try Self.expect(config.appConfig(for: BuiltInCrawlApps.gogcliID)?.enabled == true, "new Google app normalizes enabled") try Self.expect(config.appConfig(for: BuiltInCrawlApps.gogcliID)?.showInMenuBar == true, "new Google app appears in menu bar") + try Self.expect(config.appConfig(for: BuiltInCrawlApps.photoscrawlID)?.enabled == true, "Photos crawler normalizes enabled") + try Self.expect( + BuiltInCrawlApps.photoscrawl.commands["refresh"] == ["crawl", "--library", "{config:library_path}", "--json"], + "Photos refresh uses the configured library path") let oldConfig = CrawlBarConfig( version: 1, apps: [CrawlBarAppConfig(id: BuiltInCrawlApps.wacliID, enabled: false, showInMenuBar: false)]).normalized() From d92a80b9452ff60b165bcad58910c9ef82eff4e6 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 19 Jun 2026 08:31:20 -0400 Subject: [PATCH 2/2] fix: mark Photos crawler coming soon --- CHANGELOG.md | 2 +- README.md | 2 +- .../BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift | 1 + Sources/CrawlBarSelfTest/SelfTestConfig.swift | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 825a8cd..e07063f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Changes -- Add Apple Photos as a built-in crawler with read-only status, refresh, search, platform-native storage paths, and configurable library selection. +- Add Apple Photos as a coming-soon built-in crawler with read-only status, refresh, search, platform-native storage paths, and configurable library selection. ### Fixes diff --git a/README.md b/README.md index d383cf0..2a576ef 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Built-in manifests ship for: - `discrawl` - `telecrawl` - `imsgcrawl` -- `photoscrawl` +- `photoscrawl` (coming soon) - `notcrawl` - `gogcli` through the `gog` executable - `wacli` diff --git a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift index 68f417c..3cbff62 100644 --- a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift +++ b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift @@ -5,6 +5,7 @@ public extension BuiltInCrawlApps { id: Self.photoscrawlID, displayName: "Apple Photos", description: "Local-first, read-only Apple Photos archive crawler", + availability: .comingSoon, binary: .init(name: "photoscrawl"), branding: .init( symbolName: "photo.on.rectangle.angled", diff --git a/Sources/CrawlBarSelfTest/SelfTestConfig.swift b/Sources/CrawlBarSelfTest/SelfTestConfig.swift index 52dbf1a..5ae6a1a 100644 --- a/Sources/CrawlBarSelfTest/SelfTestConfig.swift +++ b/Sources/CrawlBarSelfTest/SelfTestConfig.swift @@ -14,7 +14,8 @@ extension CrawlBarSelfTest { try Self.expect(config.apps.map(\.id) == BuiltInCrawlApps.all.map(\.id), "built-in apps are present") try Self.expect(config.appConfig(for: BuiltInCrawlApps.gogcliID)?.enabled == true, "new Google app normalizes enabled") try Self.expect(config.appConfig(for: BuiltInCrawlApps.gogcliID)?.showInMenuBar == true, "new Google app appears in menu bar") - try Self.expect(config.appConfig(for: BuiltInCrawlApps.photoscrawlID)?.enabled == true, "Photos crawler normalizes enabled") + try Self.expect(config.appConfig(for: BuiltInCrawlApps.photoscrawlID)?.enabled == false, "coming-soon Photos crawler normalizes disabled") + try Self.expect(BuiltInCrawlApps.photoscrawl.availability == .comingSoon, "Photos crawler remains coming soon without an installer") try Self.expect( BuiltInCrawlApps.photoscrawl.commands["refresh"] == ["crawl", "--library", "{config:library_path}", "--json"], "Photos refresh uses the configured library path")