Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

890 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NOOP

A personal, offline WHOOP companion app for macOS, iOS and the Apple Watch. It pairs directly with a WHOOP strap over Bluetooth, stores everything on-device in SQLite, and computes recovery, strain, HRV, and sleep locally — no cloud, no account, nothing leaves the device.

Not affiliated with WHOOP, Inc. "WHOOP" is used only to identify the hardware this interoperates with. Not a medical device — every metric is an approximation, not clinically validated.


Why

You bought the strap. The biometric stream it produces is yours.

  • Own your data. NOOP reads heart rate, R-R intervals, SpO₂, skin temperature, respiration, accelerometer/gravity, battery, and event data straight off the strap over Bluetooth and writes it to a local SQLite database.
  • Account-free and local. NOOP never logs into a WHOOP account and never hits a WHOOP server.
  • Bring your history. Import a WHOOP CSV export and/or an Apple Health export.xml once, and it's permanently on the machine.
  • Transparent math. Recovery, strain, HRV, and sleep are recomputed on-device from documented, citable methods (Task Force 1996 HRV, Karvonen %HRR, Edwards/Banister TRIMP, Tanaka HRmax).

Features

Everything lives behind a single sidebar (Strand/App/RootView.swift). Each row below is a real screen in Strand/Screens/.

Screen What it does
Today Home dashboard: recovery ring, a "today's synthesis" insight, stat tiles with 14-day sparklines, live strap battery % and HR trend, recent workouts, data-sources footer.
Readiness An on-device "should you push today?" read synthesizing HRV vs baseline, resting-HR drift, sleeping respiratory-rate drift, training-load balance, and training monotony into one headline.
Live Real-time view of the connected strap — heart rate and frame stream as they arrive (~1 Hz).
Breathe HRV haptic breathing biofeedback: the strap paces your breath with buzzes and shows live HR + rolling RMSSD. Presets: Relax 4-6, Coherence 5.5, Box 4-4.
Intervals Silent haptic HIIT timer — the strap buzzes every transition.
Explore Interrogate any single metric over time.
Compare Plot two metrics together / against each other over a shared timeline.
Insights Behavioral and correlational insights derived from your own series, including Activity Cost.
Sleep Sleep sessions with a hypnogram, stage breakdown, efficiency, resting HR, and HRV.
Trends Long-range trends and a shareable one-page PDF report, rendered entirely on-device.
Workouts Detected and manual exercise sessions with strain and heart-rate detail.
Health Biometric overview (HR, HRV, SpO₂, skin temperature, respiratory rate).
Stress Day-level stress / autonomic load visualization.
Mind A daily mood check-in correlated against recovery, sleep and HRV. Non-clinical.
Apple Health Browse and reconcile data imported from an Apple Health export.
Data Sources One-tap import of a WHOOP CSV export, an Apple Health export, a workout file (GPX/TCX/FIT), or a nutrition CSV.
Notifications Configure local notifications and thresholds.
Automations Turn the strap's physical inputs and live biometrics into Mac actions (see below).
Coach An optional AI Coach, off until a key is added (Anthropic, OpenAI, or any OpenAI-compatible endpoint including a local model). Sends only a short text summary, never raw streams.
Settings Profile, preferences, step calibration, unit choices, an opt-in Experimental section.
Support Contact + attribution to the reverse-engineering work this is built on.

There is also a menu-bar extra (Strand/MenuBar/MenuBarContent.swift) with a glanceable live HR readout, and a first-run onboarding wizard.

Automations (on-device)

Strand/Screens/AutomationsView.swift + Strand/System/MacActions.swift:

  • Double-tap → Mac action. Double-tap the strap to lock the Mac, buzz back to confirm, mark a moment, do nothing, or run any macOS Shortcut by name.
  • Wear & presence. Lock the Mac (or run a Shortcut) the moment the strap leaves the wrist; run a Shortcut when it goes back on.
  • Haptic coaching. HR-zone coaching and an experimental resting-stress nudge.
  • Inactivity reminder. An optional gentle wrist buzz after sitting still too long — off by default.
  • Smart alarm. Arms the strap's own firmware alarm to buzz at a set wake time.

Platforms

Platform Status
macOS Full app (Strand/, SwiftUI, macOS 13+). Pairs over BLE, offloads the strap's history, and scores recovery/strain/sleep on-device.
iOS Build-from-source in Xcode (StrandiOS/), no App Store. Shares the cross-platform Swift packages, so scoring matches macOS.
watchOS Companion app (NOOPWatch/, NOOPWatchComplications/) via HealthKit.

Strap support

Strap Status
WHOOP 4.0 The tested, supported path. Live HR, recovery, strain, sleep, history offload — the full experience.
WHOOP 5.0 / MG Live heart rate works. Deeper metrics (recovery, strain, sleep) are still being mapped; there's an opt-in Settings → Experimental toggle.

Pairing a WHOOP 5.0 / MG — read this first

A WHOOP strap holds an encrypted Bluetooth bond with only one device at a time, normally the official WHOOP app. You can't just scan for it — if the strap is still bonded elsewhere, pairing is refused ("Encryption is insufficient" / "bond refused" in the strap log). Live heart rate is the exception — it rides the standard Bluetooth heart-rate profile, so it streams without a bond, but the deeper features need one.

To pair:

  1. Close the official WHOOP app on the phone (or turn that phone's Bluetooth off).
  2. Put the strap in pairing mode — on a 5.0/MG, tap the band repeatedly until the LEDs flash blue.
  3. In NOOP: Live → choose "WHOOP 5.0 / MG" → Scan & Connect. Success looks like "CLIENT_HELLO acked — link established" in the strap log.

Only one device at a time. Don't leave the strap connected to a phone and a Mac at once — HR streams on all of them, but only one holds the real encrypted bond. If HR works but buzz, alarm, double-tap and history don't, that's the tell.

What to expect when you start

  • Live heart rate shows the moment the strap connects.
  • Strain and sleep appear after wearing it and syncing — the strap's last ~14 days offload automatically.
  • Recovery needs a few nights to learn a personal baseline, then sharpens each night.
  • In a hurry? Import a WHOOP export in Data Sources and history fills in about a minute.

Architecture

The repository is split into platform-pure Swift packages plus the macOS and iOS app targets. All packages declare both .iOS(.v16) and .macOS(.v13); framework-specific UI is guarded with #if canImport(UIKit) / #if canImport(AppKit).

Strand/                  macOS SwiftUI app
StrandiOS/                iOS app (shares most of Strand/)
NOOPWatch/                watchOS companion app
Packages/
  WhoopProtocol/         BLE frame parsing, CRC, command/event/packet decode
  WhoopStore/            GRDB/SQLite persistence (migrations, streams, caches)
  StrandAnalytics/       HRV / recovery / strain / sleep / correlation math
  StrandImport/          WHOOP CSV + Apple Health importers
  StrandDesign/          SwiftUI design system (palette, components, charts)
Tools/Backfill/          CLI tool for backfilling decoded data

WhoopProtocol — the protocol-support core

Platform-pure (no CoreBluetooth import) so it runs in tests and CLI tools unchanged. It implements the on-wire frame format for both strap generations:

public enum DeviceFamily: String, Sendable, CaseIterable {
    case whoop4   // CRC8 (poly 0x07) header check; service 61080001-…
    case whoop5   // CRC16-Modbus header check, "puffin" packet types; service fd4b0001-…
}

Decoding is schema-driven (Resources/whoop_protocol.json) and includes CRC8, CRC16-Modbus, and zlib CRC-32 implementations, frame framing, value interpretation, and historical-stream reassembly. The app layer (Strand/BLE/, Strand/Collect/) wraps these UUID strings in CBUUID and handles bonding, offload, and live notifications.

WhoopStore — local SQLite via GRDB

Everything is stored on-device in SQLite via GRDB.swift. The schema is a versioned migrator (Database.swift).

StrandAnalytics — transparent, on-device math

Pure, database-free analyzers, each grounded in published methods:

File Computes
HRVAnalyzer.swift RMSSD + SDNN from R-R intervals (Task Force 1996), with range + Malik ectopic filtering.
RecoveryScorer.swift A 0–100 recovery score: HRV-dominant z-score + logistic composite vs personal baselines.
StrainScorer.swift A 0–21 logarithmic strain scale from %HRR (Karvonen) and Edwards/Banister TRIMP.
SleepStager.swift Sleep/wake detection + approximate 4-class staging from cardiorespiratory + gravity features.
CorrelationEngine.swift Pearson r, OLS regression, day-aligned and lagged correlations between two series.

StrandImport — bring your own history

  • WHOOP CSV export (WhoopExportImporter.swift): tolerant parser for physiological_cycles.csv, sleeps.csv, workouts.csv, journal_entries.csv, from a folder or .zip.
  • Apple Health export (AppleHealthImporter.swift): a streaming SAX parser for export.xml (which can exceed 1 GB).
  • Nutrition CSV — a tolerant importer for daily-nutrition exports from Cronometer and MacroFactor.

StrandDesign — the SwiftUI design system

Palette, typography, motion, and reusable components/charts — no external UI dependencies.


Quickstart (macOS)

Requirements: macOS 13+, Xcode 15+ (Swift 5.9), and a Mac with Bluetooth. To pair live, a WHOOP strap; to just explore, import a CSV / Apple Health export instead.

The Xcode project is generated from project.yml with XcodeGen.

# 1. Clone
git clone <this-repo-url> NOOP
cd NOOP

# 2. (Re)generate the Xcode project from project.yml
brew install xcodegen   # if you don't have it
xcodegen generate

# 3. Open and run
open Strand.xcodeproj
# Select the "Strand" scheme → Run (⌘R). The built app is named NOOP.

Notes:

  • Bundle id com.noopapp.noop, product name NOOP, sandboxed with the Bluetooth and user-selected-files entitlements.
  • Swift Package Manager resolves the only third-party dependencies automatically: GRDB.swift (SQLite) and ZIPFoundation (export unzip).
  • Run the tests from Xcode (the StrandTests target + each package's test target), or per-package with swift test inside Packages/<Name>/.

To build and run the iPhone app instead, see docs/BUILD.md for the NOOPiOS scheme (needs a real device — BLE doesn't work in the simulator).


How data flows

WHOOP strap ──BLE──▶ Strand/BLE + Strand/Collect ──▶ WhoopProtocol (decode)
                                                          │
WHOOP CSV   ─┐                                            ▼
Apple Health ├─▶ StrandImport (parse) ──────────▶ WhoopStore (local SQLite)
Nutrition CSV┘                                            │
                                                          ▼
                                            StrandAnalytics (recovery/strain/
                                            HRV/sleep, on-device)
                                                          │
                                                          ▼
                                          Strand (SwiftUI) + StrandDesign

Every arrow stays on the device.


Privacy

Offline by design. No server, no telemetry, no account. Strap data, imports, and computed metrics live in a local SQLite database and never leave the device.


Attribution

Built on community interoperability and protocol-documentation work. With thanks:

  • johnmiddleton12/my-whoop — the WHOOP 4.0 BLE protocol; the WhoopProtocol and WhoopStore packages and the collection logic are adapted from this work.
  • b-nnett/goose — the WHOOP 5.0 / MG BLE protocol documentation.
  • groue/GRDB.swift — SQLite persistence.
  • weichsel/ZIPFoundation — export unzipping.

Contains no WHOOP proprietary code, firmware, logos, or assets, and performs no DRM circumvention. Full detail in ATTRIBUTION.md.


Disclaimer

Independent, unofficial, non-commercial interoperability project. Not affiliated with, endorsed by, or connected to WHOOP, Inc. "WHOOP" is used nominatively, only to identify the hardware this interoperates with.

Not a medical device. Heart rate, HRV, recovery, strain, sleep stages, SpO₂, respiratory rate, and skin temperature are approximations computed from published methods — not clinically validated and not medical advice.

Provided as-is, with no warranty, for personal use. Use it at your own risk.


License

Source-available under the PolyForm Noncommercial License 1.0.0. The license covers NOOP's own original code and docs. Protocol facts (frame layouts, command numbers, byte offsets) are uncopyrightable; bundled dependencies keep their own licenses (GRDB.swift and ZIPFoundation are MIT — see NOTICE).


Docs

About

Offline WHOOP companion — pair your strap over Bluetooth, keep all data on your own device. No cloud, no account, no subscription.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages