Skip to content

Pull iPhone Screen Time from Biome store on macOS 14+#6

Open
natewill wants to merge 1 commit into
FelixKohlhas:mainfrom
natewill:feat/biome-iphone-screentime
Open

Pull iPhone Screen Time from Biome store on macOS 14+#6
natewill wants to merge 1 commit into
FelixKohlhas:mainfrom
natewill:feat/biome-iphone-screentime

Conversation

@natewill
Copy link
Copy Markdown

Summary

  • Adds a second data source to screentime2csv.py so one script produces a unified CSV covering both Mac and iPhone (plus any other synced Screen Time peers) on macOS 14+.
  • No new dependencies — the Biome SEGB pages are parsed directly with the stdlib.
  • Output schema is unchanged (app, usage, start_time, end_time, created_at, tz, device_id, device_model), so existing downstream analysis keeps working.

Why

On macOS 14 (Sonoma) and later, Apple stopped writing synced iPhone /app/usage events into knowledgeC.db and moved them to the Biome telemetry store at ~/Library/Biome/streams/restricted/App.InFocus/remote/<peer-uuid>/ — binary SEGB pages containing protobuf records.

Before this change, screentime2csv.py returned only Mac-local rows even when Screen Time → Share Across Devices was enabled, because the ZSOURCE / ZSYNCPEER join it relies on no longer contains iPhone events. The /app/usage rows in knowledgeC.db all have ZSOURCE = NULL on modern macOS.

What's in it

  • SEGB parser (stdlib only): walks App.InFocus/{local,remote}/<peer-uuid>/ pages and extracts (timestamp, bundle_id) events by pattern-matching the protobuf wire format (field 4 fixed64 start + field 6 length-delimited bundle). No external protobuf schema or dependency required.
  • Peer resolution: reads ~/Library/Biome/sync/sync.db DevicePeer table so iPhone rows are labeled e.g. iPhone (23D8133) and Macs as Mac (...). Falls back to platform-N / bundle model if unknown.
  • Session merging: consecutive same-app events per peer are merged into sessions. Each closed session's end is extended toward the next event in the stream, capped at --biome-max-gap seconds (default 300), so short foreground bursts followed by a gap still register as active use. The last event in the stream just spans its observed range.
  • New flags (defaults preserve prior behavior — knowledgeC is still read; Biome is read in addition):
    • --since7d / 24h / 30m / unix epoch
    • --no-knowledge — skip the knowledgeC source (Mac-only runs)
    • --no-biome — skip the Biome source
    • --biome-stream — alternate stream name (default App.InFocus; ScreenTime.AppUsage is the fallback on some installs)
    • --biome-max-gap — seconds between events to still count as one session (default 300)
    • --include-biome-local — also include this Mac's local Biome stream (usually redundant with knowledgeC)
    • --summary — per-device top-apps summary to stderr
  • README updated with the new flags, examples, and a short explanation of the knowledgeC → Biome migration.

The existing knowledgeC.db SQL query is untouched; Mac-local behavior is unchanged for users who pass --no-biome.

Test plan

  • python3 screentime2csv.py -o output.csv --since 7d --summary on a Mac + iPhone signed into the same iCloud account with Share Across Devices on:
    • Mac section reports Mac-local apps (Brave, kitty, Obsidian, etc.) from knowledgeC.db
    • iPhone section reports mobile bundle IDs (com.atebits.Tweetie2, com.burbn.instagram, com.google.ios.youtube, com.apple.mobilesafari, com.hammerandchisel.discord, com.spotify.client, …) attributed to iPhone (…)
    • Per-app totals are in the same ballpark as Settings → Screen Time for the same window
  • --no-biome produces the original behavior (Mac-only rows from knowledgeC.db)
  • --no-knowledge produces only Biome rows
  • Runs with no third-party dependencies (stdlib + sqlite3 only)
  • Full Disk Access is still the only TCC requirement

Notes / caveats

  • Requires Full Disk Access for your terminal / Python interpreter (same as before, plus now for ~/Library/Biome/).
  • SEGB retention is local to the Mac — historical iPhone data older than what Biome still has on disk isn't recoverable through this path.
  • If a future macOS moves Screen Time again, --biome-stream lets you point at an alternate stream without a code change.

🤖 Generated with Claude Code

On macOS 14 (Sonoma) and later, Apple stopped writing synced iPhone
/app/usage events into knowledgeC.db and moved them to the Biome
telemetry store at ~/Library/Biome/streams/restricted/App.InFocus/
(binary SEGB pages containing protobuf records). As a result,
screentime2csv.py only returned Mac-local rows even with Screen Time
"Share Across Devices" enabled.

This change adds a second source to screentime2csv.py so one script
produces a unified CSV covering both Mac and iPhone:

- Walks App.InFocus/{local,remote}/<peer-uuid>/ SEGB pages and extracts
  (timestamp, bundle_id) events by pattern-matching the protobuf wire
  format (field 4 fixed64 + field 6 length-delimited) — no external
  protobuf schema or dependency required.
- Resolves peer UUIDs to device models via ~/Library/Biome/sync/sync.db
  (DevicePeer table) so iPhone rows are labeled e.g. "iPhone (23D8133)".
- Merges consecutive same-app events per peer into sessions, extending
  each closed session's end toward the next event in the stream (capped
  at --biome-max-gap, default 300s) so short foreground bursts followed
  by a gap still register as active use.
- New flags: --since, --no-knowledge, --no-biome, --biome-stream,
  --biome-max-gap, --include-biome-local, --summary. Defaults keep the
  previous behavior of reading knowledgeC, and additionally read Biome.
- The knowledgeC SQL query is unchanged; output schema is unchanged
  (app, usage, start_time, end_time, created_at, tz, device_id,
  device_model).

README updated with the new usage, flags, and a short explanation of
why Biome is needed on macOS 14+.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant