CoreAIKit

SpotlightApp — ask your own files, with your own local model

A SwiftUI app (iPhone + Mac) that answers questions about your real files using Apple’s WWDC26 SpotlightSearchTool for retrieval — driven by your own converted model, not the system one. Fully on device, works in airplane mode.

You point the app at a folder (or a set of files) with the picker; it searches them in place and grounds every answer in the real text. The retrieval chain is the centerpiece of the UI: you watch the model search your files → read the ones that matter → answer, and every answer carries the source files it used (tap to open).

This is the file-backed evolution of Examples/SpotlightChat (the verified CLI): the same 2-tool RAG, now over your own documents, as an app you can run on a phone.

What it shows

There is never an empty first screen: a few sample documents are seeded into the app’s own Application Support folder on first launch and used as the default scope, so you can ask a question immediately, then switch to your own files.

Run it

The project is generated with XcodeGen:

cd Examples/SpotlightApp
xcodegen generate
open SpotlightApp.xcodeproj

On first launch the app downloads the default model (Qwen3 4B, ~2.5 GB) once, then it is cached — every later launch, including the whole RAG round trip, runs with no network. Turn on airplane mode and ask away.

Headless self-test (the gate)

# from a built product dir, or via `xcodebuild ... build` then run the binary:
SPOTLIGHT_SELFTEST=1 /path/to/SpotlightApp.app/Contents/MacOS/SpotlightApp
SPOTLIGHT_SELFTEST=1 SPOTLIGHT_SELFTEST_ASK="Which file mentions a waterfall?" .../SpotlightApp

Seeds the sample documents, points the .files source at that folder, and runs the exact RagEngine path the UI uses (search → fetch → grounded answer). It prints the retrieval chain and the answer, and exits 0 only if the model actually read a file and produced an answer (i.e. it grounded, not hallucinated).

How it works

Things that matter (carried from the CLI verification)

Files

File Role
FileLibrary.swift The user’s real files: scopes, recursive walk, text extraction, sample seeding
Tools.swift FetchFileTool (hydration) + live SearchReply → UI mapping
RagEngine.swift The verified 2-tool RAG, headless — loads the model, answers one question over a library
ChatModel.swift @Observable view model: library selection, loading, live callbacks → UI state
ContentView.swift The chat UI: identity + badges, library bar, the visible RAG trace, tappable sources
SelfTest.swift SPOTLIGHT_SELFTEST=1 headless gate (over the sample folder)

A real app’s bundle identity makes the Foundation Models tool path work out of the box — unlike the CLI, no embedded Info.plist hack is needed.