cadence
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
A local-first health-context engine. Pulls WHOOP and Apple Health into one local store, and gives Claude real, current knowledge of how you're actually doing -- sleep, recovery, strain, workouts -- instead of working blind.
The honest privacy story
Unlike the rest of this portfolio (lantern, stacks, orchard), cadence can't claim "nothing leaves the machine" -- WHOOP data necessarily comes from WHOOP's own cloud API over OAuth, there's no way around that. What's real and true instead: **once pulled, your health data lives only on this machine** (a local SQLite file at ~/.cadence/cadence.db, permissioned 0600, owner-only), your OAuth tokens live in the macOS Keychain (never on disk in plaintext, never in this repo), and cadence never re-uploads or re-shares anything to a third party. Apple Health data never leaves the machine at all -- it's a local file import, no network call involved. Claude reads your data locally via MCP; nothing about that transmits it anywhere else either.
Install
**Apple Health (no setup, fully local):**
(Export from iPhone: Health app -> profile icon -> Export All Health Data.)
**WHOOP (one-time OAuth setup, see below):**
**MCP server** (so Claude can query this live instead of just reading the brief):
Point your Claude client at it (claude mcp add cadence -- cadence mcp, or the equivalent stdio-server config for your client).
WHOOP setup (one-time)
1. Register a personal app at developer.whoop.com (sign in with your normal WHOOP account, create a Team if prompted, then create an App). Fill in:
- **Privacy Policy**: a real link is required -- https://github.com/ /cadence#the-honest-privacy-story (this section) is a reasonable choice for a personal-use app.
- **Redirect URL**: must exactly match cadence.auth.REDIRECT_URI (https://github.com/rajanshxrma/cadence by default). WHOOP's own form only accepts https:// or a custom URL scheme -- a plain http://localhost redirect is rejected, which is why cadence auth uses a copy-paste flow instead of a local callback server (see auth.py's module docstring).
- **Scopes**: check all six data scopes (read:recovery, read:cycles, read:sleep, read:workout, read:profile, read:body_measurement). There's no offline checkbox on the form -- that scope is requested dynamically in the actual authorization request, not a per-app setting.
- **Webhooks**: leave empty -- cadence is pull-based (cadence sync), no webhook receiver.
- Apps work immediately for up to 10 WHOOP accounts in dev status -- no approval needed for personal use.
2. Export your credentials (shown once on the app's page after creation -- copy both immediately):
3. Run cadence auth. It opens your browser; after you approve, WHOOP redirects there with a code in the URL -- copy the full address-bar URL and paste it back into the terminal when prompted. Tokens land in Keychain. cadence sync after that just works -- refresh happens automatically (WHOOP rotates refresh tokens on every use; cadence persists the new one each time, per their API's requirement).
Client id/secret are read from environment variables only -- never written to disk, never committed. keyring (the library used for token storage) needs an OS credential store; on macOS that's Keychain, no extra setup.
Health-aware AI sessions (v0.2.0)
The piece that makes this more than a data viewer: cadence hook emits a Claude Code SessionStart hook payload, so the **first Claude session of each day opens already knowing your physiological state** -- last night's sleep, today's recovery, recent strain -- plus a one-line adaptive hint when the numbers warrant one (low recovery: "favor lighter work over marathon builds"; short sleep: flagged; data gone stale: a re-sync nudge instead of silent death). Second session of the day: silent, by design -- a hook that talks every session is noise.
Wire-up: a 15-line shim script in your hooks config calls cadence hook; a launchd job runs cadence sync --quiet twice daily. The hook never blocks a session -- no network calls (local SQLite reads only), and every failure path chooses silence over a broken session startup.