A native macOS SwiftUI prototype for "Datadog for Humans". This build focuses on UI parity with the provided frames, live input telemetry, BLE heart rate ingestion, and local SQLite storage.
- SwiftUI + AppKit UI with dark neon styling and chart bands
- Hover tooltip, crosshair, and time range/bin selectors
- Input monitoring via event taps (keystroke count, clicks, pointer distance)
- Frontmost app/context via Accessibility
- ScreenCaptureKit stream (no images stored)
- BLE heart rate via CoreBluetooth (standard HR service)
- SQLite persistence (local file in iCloud container if available)
- Wispr Flow dictation stats integration (words dictated, WPM, streaks)
This is a prototype that captures sensitive data to power the UI. It counts keystrokes via Input Monitoring event taps (no keycodes or text are captured or stored), collects frontmost app/window context via Accessibility, and streams screen frames via ScreenCaptureKit (frames are processed in-memory; no images are stored). Avoid entering sensitive information while running the app, and contact the maintainers for privacy questions before deploying in any shared or production environment.
swift build
swift run./scripts/build_app.sh
open dist/Datahuman.appNote: macOS privacy permissions (Screen Recording, Input Monitoring, Accessibility, etc.) are tied to an app's
code signature. If you rebuild an unsigned app, macOS can treat each build as a new app and re-prompt on launch.
build_app.sh produces an unsigned app bundle by default. If you have a signing identity, you can codesign:
codesign --force --deep --sign "Apple Development: Your Name (TEAMID)" \
--entitlements Entitlements/Datahuman.entitlements dist/Datahuman.appIcon packaging knobs (trade size vs fidelity):
# Include the 1024x1024 rendition in Assets.car (bigger; best quality at very large icon sizes).
APP_ASSETS_CAR_INCLUDE_1024=1 ./scripts/build_app.sh
# Omit Assets.car entirely (smallest build; macOS may fall back to AppIcon.icns).
APP_INCLUDE_ASSETS_CAR=0 ./scripts/build_app.shOptional versioning:
./scripts/build_app.sh --version=0.1.0Build and run immediately:
./scripts/build_app.sh --runCIruns on pull requests and pushes tomainto build, test, and package the app bundle.Releaseruns on tags matchingv*or manual dispatch to builddist/Datahuman-<version>.zip.
GitHub Releases include a zipped .app bundle (Datahuman-<version>.zip).
Note: Release builds are currently not code-signed or notarized, so macOS may block first launch. If that happens, either right-click Datahuman.app and choose Open, or remove the quarantine attribute:
xattr -dr com.apple.quarantine /path/to/Datahuman.appIf you'd rather not run an unsigned prebuilt app, compile from source using SwiftPM (swift run) or ./scripts/build_app.sh.
- Pair the WHOOP device in macOS Bluetooth settings if needed.
- Run the app (
swift run) and wait for the BLE scan to connect. - Inspect the log file:
~/Library/Application Support/Datahuman/ble-debug.jsonl- It logs discovered services, characteristics (with properties), and raw value notifications.
- This file can include sensitive health/biometric data. Treat it as sensitive: restrict file permissions, avoid sending it unencrypted, and delete or redact it when debugging is done. For production builds, disable or limit logging so heart-rate and other biometric values are not retained.
- If no HR is shown, the app will still log custom notify characteristics so we can identify the right UUIDs.
The app will request:
- Input Monitoring
- Accessibility
- Screen Recording
- Bluetooth
For iCloud sync, add the entitlements in Entitlements/Datahuman.entitlements and configure the container identifier in Xcode.
The repo ships with a placeholder container (iCloud.com.example.datahuman) so you must replace it with your own iCloud container identifier.
If Wispr Flow is installed, Datahuman automatically displays your dictation stats in the "Dictated" stat slot:
- Words dictated - matches the selected time range (1H, TODAY, WEEK, etc.)
- Dictation count - number of dictation sessions in the time range
- WPM avg - your average words per minute
- Day streak - consecutive days of dictation
Stats are read directly from Wispr Flow's SQLite database (~/Library/Application Support/Wispr Flow/flow.sqlite) and update when you change time ranges. Polled every 30 seconds for new dictations. If Wispr Flow is not installed, the stat shows "--" with "Wispr Flow not detected".
