Privacy and architecture
Follow data through Electron, FastAPI, Gemini, ChromaDB, Photos, local paths, logs, and current API-key storage.
Memsearch keeps its vector index and thumbnail cache on the Mac. It is not an offline-only system: supported content and every search query are sent to Google Gemini to create embeddings.
Component data flow
Electron desktop ─┐
Raycast extension ├── HTTP ──> FastAPI on 127.0.0.1:7242
CLI / curl ───────┘ │
├── local files and PDF/image processors
├── PhotoKit + read-only Photos.sqlite
├── Google Gemini embedding API
└── local ChromaDB + thumbnail cacheThe Electron app manages a backend child process after onboarding. Raycast and other clients use the same HTTP API. The CLI can either access storage directly for its commands or start the HTTP server.
Indexing flow
- The backend scans an allowed folder or enumerates image assets through PhotoKit.
- A local processor extracts text or prepares JPEG image content.
- The prepared content is sent to Gemini with the
RETRIEVAL_DOCUMENTtask. - Gemini returns a vector with the configured dimensions.
- ChromaDB stores the vector plus local metadata such as path/asset ID, filename, modality, summary, size, time, thumbnail filename, and optional people names.
- Derived 256 × 256 JPEG thumbnails are saved to the local thumbnail directory.
Search flow
- FastAPI removes
@personmentions and retains them for local filtering. - The remaining query—or
photofor a people-only query—is sent to Gemini withRETRIEVAL_QUERY. - ChromaDB performs cosine nearest-neighbor search, optionally filtering by modality.
- Person filters are applied locally against stored names.
- The client receives result metadata and fetches local thumbnails as needed.
What is sent to Gemini
| Operation | Sent |
|---|---|
| Text file indexing | Up to the first 8,000 decoded characters |
| Image file indexing | A JPEG representation, resized when the prepared JPEG exceeds 4 MB |
| PDF indexing | Up to 8,000 extracted characters plus a JPEG rendering of the first page |
| Photos indexing | A JPEG representation of image data obtained through PhotoKit |
| Search | Query text after @person mentions are removed |
The embedding calls do not intentionally include the filesystem path or filename as a separate argument. Result summaries and metadata stay in ChromaDB. For Photos, person names are appended to local metadata after the image embedding is returned.
Review Google’s data terms
Your Gemini API key controls requests to Google. Treat document text, PDF content, images, Photos assets, and queries as data disclosed to that API for embedding. Review the current Google AI terms that apply to your key and account.
Data locations
| Data | Default location |
|---|---|
| ChromaDB vector index | ~/Library/Application Support/MacMemorySearch/chroma |
| Cached thumbnails | ~/Library/Application Support/MacMemorySearch/thumbnails |
| Backend persistent settings | ~/Library/Application Support/MacMemorySearch/config.json |
| Electron Store | ~/Library/Application Support/MemSearch/config.json |
| Electron-managed Python environment | ~/Library/Application Support/MemSearch/venv |
| Desktop-managed backend log | ~/Library/Application Support/MemSearch/logs/backend.log |
| Default Photos library | ~/Pictures/Photos Library.photoslibrary |
All ~ paths resolve under the current macOS user account. Storage locations can be overridden with the corresponding MEMSEARCH_* environment settings.
ChromaDB contents
Each record uses a SHA-256 hash of the file path or photos:// identifier as its Chroma ID. Stored metadata can include:
file_path / photos:// identifier
modality
filename or generated photo display name
text_summary (up to 1,000 characters in storage)
file_size
indexed_at
thumbnail_filename
person_namesText passed as the Chroma document field is the same stored summary or filename fallback—not the entire original file. The embedding itself can nevertheless encode information from the larger prepared payload sent to Gemini.
Photos access
PhotoKit permission gates asset enumeration and image requests. Network access is enabled so iCloud-only assets can be downloaded. The people feature opens Photos.sqlite in read-only/query-only mode and does not modify the Photos library database.
Opening a result runs AppleScript against Photos using the local asset identifier. Memsearch does not export the photo to a separate permanent source-file location.
API-key handling
The desktop app currently stores the Gemini key in Electron Store under apiKey as plaintext. On backend launch it copies the key into the child process environment as MEMSEARCH_GEMINI_API_KEY.
Legacy builds may have stored a safeStorage-encrypted base64 value. Current code attempts to decrypt such a value once, validates that it resembles a Gemini key, and rewrites it as plaintext. An undecryptable legacy value is discarded.
Protect the Electron Store file
Anyone or any process that can read the macOS user-data file may be able to read the Gemini key. Current code does not use Keychain as the persistent store.
The backend GET /config response does not expose the key.
Logs
When the desktop app manages the backend, stdout and stderr are appended to:
~/Library/Application Support/MemSearch/logs/backend.logThe log records backend starts, dependency/install progress, process exits, file/photo progress, and error messages. Indexing output can contain filenames, file paths, photo labels/dates, and service errors. Review or redact the file before sharing it.
The backend does not implement log rotation in the current source; the Electron process opens the file in append mode.
Network surfaces
| Destination | Why |
|---|---|
| Google Gemini | Document/image and query embeddings |
| Apple iCloud through PhotoKit | Download Photos assets not present locally |
astral.sh | Automatic uv installation when the desktop app cannot find it |
| Python package indexes | First-run uv dependency environment setup |
| GitHub | Electron release/update checks and downloads when used |
The FastAPI service itself defaults to loopback, but it has no authentication and enables wildcard CORS. See Local API before changing its host.
Clearing and retention
DELETE /index, the desktop Clear Index action, and CLI clear remove the Chroma collection and cached thumbnails. They do not remove:
- original files or Photos assets;
- backend/Electron settings;
- the stored Gemini key;
- the Python environment; or
- backend logs.
Use the reset procedures in Troubleshooting when you need to remove more than search data.