hae-vault 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/.env.example +7 -0
  2. package/CLAUDE.md +220 -0
  3. package/README.md +206 -0
  4. package/SKILL.md +60 -0
  5. package/dist/cli/dashboard.d.ts +3 -0
  6. package/dist/cli/dashboard.d.ts.map +1 -0
  7. package/dist/cli/dashboard.js +206 -0
  8. package/dist/cli/dashboard.js.map +1 -0
  9. package/dist/cli/import.d.ts +3 -0
  10. package/dist/cli/import.d.ts.map +1 -0
  11. package/dist/cli/import.js +78 -0
  12. package/dist/cli/import.js.map +1 -0
  13. package/dist/cli/index.d.ts +3 -0
  14. package/dist/cli/index.d.ts.map +1 -0
  15. package/dist/cli/index.js +31 -0
  16. package/dist/cli/index.js.map +1 -0
  17. package/dist/cli/info.d.ts +5 -0
  18. package/dist/cli/info.d.ts.map +1 -0
  19. package/dist/cli/info.js +34 -0
  20. package/dist/cli/info.js.map +1 -0
  21. package/dist/cli/metrics.d.ts +3 -0
  22. package/dist/cli/metrics.d.ts.map +1 -0
  23. package/dist/cli/metrics.js +20 -0
  24. package/dist/cli/metrics.js.map +1 -0
  25. package/dist/cli/query.d.ts +3 -0
  26. package/dist/cli/query.d.ts.map +1 -0
  27. package/dist/cli/query.js +18 -0
  28. package/dist/cli/query.js.map +1 -0
  29. package/dist/cli/serve.d.ts +3 -0
  30. package/dist/cli/serve.d.ts.map +1 -0
  31. package/dist/cli/serve.js +19 -0
  32. package/dist/cli/serve.js.map +1 -0
  33. package/dist/cli/sleep.d.ts +3 -0
  34. package/dist/cli/sleep.d.ts.map +1 -0
  35. package/dist/cli/sleep.js +19 -0
  36. package/dist/cli/sleep.js.map +1 -0
  37. package/dist/cli/summary.d.ts +3 -0
  38. package/dist/cli/summary.d.ts.map +1 -0
  39. package/dist/cli/summary.js +53 -0
  40. package/dist/cli/summary.js.map +1 -0
  41. package/dist/cli/trends.d.ts +3 -0
  42. package/dist/cli/trends.d.ts.map +1 -0
  43. package/dist/cli/trends.js +77 -0
  44. package/dist/cli/trends.js.map +1 -0
  45. package/dist/cli/watch.d.ts +12 -0
  46. package/dist/cli/watch.d.ts.map +1 -0
  47. package/dist/cli/watch.js +89 -0
  48. package/dist/cli/watch.js.map +1 -0
  49. package/dist/cli/workouts.d.ts +3 -0
  50. package/dist/cli/workouts.d.ts.map +1 -0
  51. package/dist/cli/workouts.js +19 -0
  52. package/dist/cli/workouts.js.map +1 -0
  53. package/dist/config.d.ts +9 -0
  54. package/dist/config.d.ts.map +1 -0
  55. package/dist/config.js +25 -0
  56. package/dist/config.js.map +1 -0
  57. package/dist/db/importLog.d.ts +5 -0
  58. package/dist/db/importLog.d.ts.map +1 -0
  59. package/dist/db/importLog.js +10 -0
  60. package/dist/db/importLog.js.map +1 -0
  61. package/dist/db/metrics.d.ts +4 -0
  62. package/dist/db/metrics.d.ts.map +1 -0
  63. package/dist/db/metrics.js +14 -0
  64. package/dist/db/metrics.js.map +1 -0
  65. package/dist/db/schema.d.ts +5 -0
  66. package/dist/db/schema.d.ts.map +1 -0
  67. package/dist/db/schema.js +100 -0
  68. package/dist/db/schema.js.map +1 -0
  69. package/dist/db/sleep.d.ts +4 -0
  70. package/dist/db/sleep.d.ts.map +1 -0
  71. package/dist/db/sleep.js +13 -0
  72. package/dist/db/sleep.js.map +1 -0
  73. package/dist/db/workouts.d.ts +4 -0
  74. package/dist/db/workouts.d.ts.map +1 -0
  75. package/dist/db/workouts.js +11 -0
  76. package/dist/db/workouts.js.map +1 -0
  77. package/dist/index.d.ts +3 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +5 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/parse/metrics.d.ts +17 -0
  82. package/dist/parse/metrics.d.ts.map +1 -0
  83. package/dist/parse/metrics.js +33 -0
  84. package/dist/parse/metrics.js.map +1 -0
  85. package/dist/parse/sleep.d.ts +23 -0
  86. package/dist/parse/sleep.d.ts.map +1 -0
  87. package/dist/parse/sleep.js +58 -0
  88. package/dist/parse/sleep.js.map +1 -0
  89. package/dist/parse/time.d.ts +4 -0
  90. package/dist/parse/time.d.ts.map +1 -0
  91. package/dist/parse/time.js +41 -0
  92. package/dist/parse/time.js.map +1 -0
  93. package/dist/parse/workouts.d.ts +17 -0
  94. package/dist/parse/workouts.d.ts.map +1 -0
  95. package/dist/parse/workouts.js +24 -0
  96. package/dist/parse/workouts.js.map +1 -0
  97. package/dist/server/app.d.ts +5 -0
  98. package/dist/server/app.d.ts.map +1 -0
  99. package/dist/server/app.js +39 -0
  100. package/dist/server/app.js.map +1 -0
  101. package/dist/server/ingest.d.ts +15 -0
  102. package/dist/server/ingest.d.ts.map +1 -0
  103. package/dist/server/ingest.js +41 -0
  104. package/dist/server/ingest.js.map +1 -0
  105. package/dist/types/hae.d.ts +103 -0
  106. package/dist/types/hae.d.ts.map +1 -0
  107. package/dist/types/hae.js +2 -0
  108. package/dist/types/hae.js.map +1 -0
  109. package/dist/util/zip.d.ts +3 -0
  110. package/dist/util/zip.d.ts.map +1 -0
  111. package/dist/util/zip.js +24 -0
  112. package/dist/util/zip.js.map +1 -0
  113. package/docs/COMMANDS.md +315 -0
  114. package/docs/plans/2026-02-18-hae-vault-initial-implementation.md +2015 -0
  115. package/docs/plans/2026-02-18-readme-dashboard-design.md +213 -0
  116. package/docs/plans/2026-02-18-readme-dashboard-plan.md +1306 -0
  117. package/docs/plans/2026-02-18-zip-env-watch-design.md +213 -0
  118. package/docs/plans/2026-02-18-zip-env-watch.md +966 -0
  119. package/package.json +57 -0
  120. package/src/cli/dashboard.ts +242 -0
  121. package/src/cli/import.ts +85 -0
  122. package/src/cli/index.ts +32 -0
  123. package/src/cli/info.ts +36 -0
  124. package/src/cli/metrics.ts +20 -0
  125. package/src/cli/query.ts +17 -0
  126. package/src/cli/serve.ts +18 -0
  127. package/src/cli/sleep.ts +19 -0
  128. package/src/cli/summary.ts +58 -0
  129. package/src/cli/trends.ts +103 -0
  130. package/src/cli/watch.ts +111 -0
  131. package/src/cli/workouts.ts +19 -0
  132. package/src/config.ts +28 -0
  133. package/src/db/importLog.ts +18 -0
  134. package/src/db/metrics.ts +15 -0
  135. package/src/db/schema.ts +105 -0
  136. package/src/db/sleep.ts +15 -0
  137. package/src/db/workouts.ts +13 -0
  138. package/src/index.ts +4 -0
  139. package/src/parse/metrics.ts +50 -0
  140. package/src/parse/sleep.ts +82 -0
  141. package/src/parse/time.ts +43 -0
  142. package/src/parse/workouts.ts +42 -0
  143. package/src/server/app.ts +46 -0
  144. package/src/server/ingest.ts +68 -0
  145. package/src/types/hae.ts +94 -0
  146. package/src/util/zip.ts +24 -0
  147. package/tests/cli-watch.test.ts +64 -0
  148. package/tests/db-import-log.test.ts +40 -0
  149. package/tests/db-metrics.test.ts +44 -0
  150. package/tests/db-schema.test.ts +55 -0
  151. package/tests/db-sleep.test.ts +36 -0
  152. package/tests/db-workouts.test.ts +34 -0
  153. package/tests/ingest.test.ts +99 -0
  154. package/tests/parse-metrics.test.ts +55 -0
  155. package/tests/parse-sleep.test.ts +65 -0
  156. package/tests/parse-time.test.ts +48 -0
  157. package/tests/parse-workouts.test.ts +43 -0
  158. package/tests/types.test.ts +27 -0
  159. package/tests/util-zip.test.ts +46 -0
  160. package/tsconfig.json +19 -0
package/.env.example ADDED
@@ -0,0 +1,7 @@
1
+ HVAULT_DB_PATH=~/.hae-vault/health.db
2
+ HVAULT_PORT=4242
3
+ HVAULT_TOKEN=
4
+ HVAULT_WATCH_DIR=~/Downloads
5
+ HVAULT_WATCH_INTERVAL=60
6
+ HVAULT_TARGET=default
7
+ HVAULT_ENV_FILE=
package/CLAUDE.md ADDED
@@ -0,0 +1,220 @@
1
+ # hae-vault — Claude Code Guide
2
+
3
+ ## Project Identity
4
+
5
+ - **npm package name:** `hae-vault`
6
+ - **CLI command:** `hvault`
7
+ - **Install:** `npm install -g hae-vault`
8
+ - **Language:** TypeScript (Node.js 22+, ESM, NodeNext)
9
+ - **Status:** Implemented and working — 570k+ rows ingested from real Apple Health data
10
+
11
+ ---
12
+
13
+ ## What This Project Does
14
+
15
+ `hae-vault` is an npm package with three responsibilities:
16
+
17
+ 1. **Server** (`hvault serve`): HTTP server that receives health data pushed from the **Health Auto Export** iOS app. POST to `/api/ingest`, writes to local SQLite.
18
+
19
+ 2. **Import** (`hvault import <file>`): Bulk import from a HAE JSON or ZIP export file. Idempotent via SHA-256 hash tracking — skips already-imported files.
20
+
21
+ 3. **Watch** (`hvault watch`): Polls a directory for new HAE export files, auto-imports on schedule. Configurable via env vars.
22
+
23
+ 4. **CLI** (`hvault <command>`): Query interface for AI agents (OpenClaw). Returns JSON.
24
+
25
+ ---
26
+
27
+ ## Ecosystem Context
28
+
29
+ ```
30
+ OpenClaw (AI agent platform, remote server)
31
+ ├── skill: whoop-up ← existing, WHOOP wearable, live API calls
32
+ ├── skill: hae-vault ← Apple Health archive, queries SQLite
33
+
34
+ ├── whoop-up CLI ← npm install -g whoop-up (already published)
35
+ └── hvault CLI ← npm install -g hae-vault (local install)
36
+ └── reads ~/.hae-vault/health.db (SQLite)
37
+
38
+ iPhone (Health Auto Export app)
39
+ └── REST API automation → POST http://server:4242/api/ingest
40
+ └── writes to health.db via hvault serve
41
+
42
+ OR
43
+
44
+ HAE Manual Export → .zip file → hvault import export.zip
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Source Structure
50
+
51
+ ```
52
+ hae-vault/
53
+ ├── src/
54
+ │ ├── index.ts ← entry point, Commander CLI
55
+ │ ├── config.ts ← env config singleton (dotenv + HVAULT_* vars)
56
+ │ ├── server/
57
+ │ │ ├── app.ts ← Express HTTP server
58
+ │ │ └── ingest.ts ← parse payload → write to DB, returns IngestResult
59
+ │ ├── db/
60
+ │ │ ├── schema.ts ← SQLite schema + openDb() + closeDb()
61
+ │ │ ├── metrics.ts ← upsertMetrics()
62
+ │ │ ├── sleep.ts ← upsertSleep()
63
+ │ │ ├── workouts.ts ← upsertWorkout()
64
+ │ │ └── importLog.ts ← hasBeenImported() + logImport() (SHA-256 dedup)
65
+ │ ├── parse/
66
+ │ │ ├── time.ts ← 5-format date parser
67
+ │ │ ├── metrics.ts ← MetricData[] → NormalizedMetric[]
68
+ │ │ ├── sleep.ts ← detect 3 variants, normalizeSleep()
69
+ │ │ └── workouts.ts ← WorkoutData[] → NormalizedWorkout
70
+ │ ├── util/
71
+ │ │ └── zip.ts ← extractPayloadFromZip() — adm-zip, finds HealthAutoExport-*.json
72
+ │ ├── cli/
73
+ │ │ ├── index.ts ← program + all command registrations
74
+ │ │ ├── serve.ts ← hvault serve
75
+ │ │ ├── import.ts ← hvault import <file> (JSON or ZIP, dedup via import_log)
76
+ │ │ ├── watch.ts ← hvault watch (polls dir, auto-imports, exports tick())
77
+ │ │ ├── metrics.ts ← hvault metrics --metric <name> --days N
78
+ │ │ ├── sleep.ts ← hvault sleep --days N
79
+ │ │ ├── workouts.ts ← hvault workouts --days N
80
+ │ │ ├── summary.ts ← hvault summary --days N
81
+ │ │ ├── query.ts ← hvault query "<sql>"
82
+ │ │ └── info.ts ← hvault sources | last-sync | stats
83
+ │ └── types/
84
+ │ └── hae.ts ← TypeScript interfaces for HAE payload
85
+ ├── tests/
86
+ │ ├── types.test.ts
87
+ │ ├── parse-time.test.ts
88
+ │ ├── parse-sleep.test.ts
89
+ │ ├── parse-metrics.test.ts
90
+ │ ├── parse-workouts.test.ts
91
+ │ ├── db-schema.test.ts
92
+ │ ├── db-metrics.test.ts
93
+ │ ├── db-sleep.test.ts
94
+ │ ├── db-workouts.test.ts
95
+ │ ├── db-import-log.test.ts
96
+ │ ├── ingest.test.ts
97
+ │ ├── util-zip.test.ts
98
+ │ └── cli-watch.test.ts
99
+ ├── docs/plans/ ← design + implementation plan docs
100
+ ├── CLAUDE.md
101
+ ├── SKILL.md ← OpenClaw skill definition
102
+ ├── package.json ← bin: { "hvault": "dist/index.js" }
103
+ └── tsconfig.json
104
+ ```
105
+
106
+ ---
107
+
108
+ ## CLI Commands
109
+
110
+ ```bash
111
+ # Server
112
+ hvault serve # start HTTP ingest server (default port 4242)
113
+ hvault serve --port 4242 # custom port
114
+ hvault serve --token <secret> # require Authorization: Bearer <secret>
115
+
116
+ # Import from file (JSON or ZIP)
117
+ hvault import export.json # import HAE JSON export
118
+ hvault import export.zip # import HAE zip (extracts HealthAutoExport-*.json)
119
+ hvault import export.zip --target me # tag with device/person name
120
+
121
+ # Watch directory for new exports
122
+ hvault watch # uses HVAULT_WATCH_DIR env var
123
+ hvault watch --dir ~/Downloads # watch specific directory
124
+ hvault watch --interval 60 # check every 60 seconds
125
+
126
+ # Query (all return JSON, --pretty for formatted)
127
+ hvault metrics --metric step_count --days 30
128
+ hvault metrics --metric heart_rate --days 7
129
+ hvault sleep --days 14
130
+ hvault workouts --days 30
131
+ hvault summary --days 90
132
+ hvault query "<sql>" # raw SQL → JSON
133
+ hvault sources # metric coverage in DB
134
+ hvault last-sync # last REST API push received
135
+ hvault stats # row counts per table
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Environment Variables
141
+
142
+ Load order: CLI flag > env var > `.env` file > hardcoded default.
143
+
144
+ In Docker: set env vars directly — no `.env` file needed.
145
+
146
+ ```bash
147
+ HVAULT_ENV_FILE=/path/to/.env # override .env file location (default: CWD/.env)
148
+ HVAULT_DB_PATH=~/.hae-vault/health.db # SQLite DB location (tilde expanded)
149
+ HVAULT_PORT=4242 # serve port
150
+ HVAULT_TOKEN=secret # bearer token for serve
151
+ HVAULT_WATCH_DIR=~/Downloads # directory to watch for exports (tilde expanded)
152
+ HVAULT_WATCH_INTERVAL=60 # watch poll interval (seconds)
153
+ HVAULT_TARGET=default # default target name
154
+ ```
155
+
156
+ ---
157
+
158
+ ## SQLite Schema
159
+
160
+ Database: `~/.hae-vault/health.db`
161
+
162
+ ### Tables
163
+ - `metrics` — all health metrics (steps, HR, HRV, etc.) `UNIQUE(ts, metric, source, target)`
164
+ - `sleep` — nightly sleep records (3 schema variants handled) `UNIQUE(date, source, target)`
165
+ - `workouts` — workout sessions `UNIQUE(ts, name, target)`
166
+ - `sync_log` — REST API push history
167
+ - `import_log` — file import history with SHA-256 hash for deduplication `UNIQUE(file_hash)`
168
+
169
+ ### Key implementation notes
170
+ - **WAL mode** — concurrent reads while server writes
171
+ - **`INSERT OR REPLACE`** — idempotent upserts throughout
172
+ - **`import_log` hash check** — skip re-importing identical files
173
+ - **DB path** from `HVAULT_DB_PATH` env or `~/.hae-vault/health.db`
174
+
175
+ ---
176
+
177
+ ## Payload Format (HAE REST API)
178
+
179
+ Top-level:
180
+ ```json
181
+ { "data": { "metrics": [], "workouts": [], "stateOfMind": [], ... } }
182
+ ```
183
+
184
+ ### Date format — 5 variants (all handled by `src/parse/time.ts`)
185
+ ```
186
+ "2026-01-15 14:30:00 +0000" ← 24-hour
187
+ "2026-01-15 2:30:00 PM +0000" ← 12-hour uppercase
188
+ "2026-01-15 2:30:00 pm +0000" ← 12-hour lowercase
189
+ "2026-01-15 2:30:00\u202fPM +0000" ← narrow non-breaking space before PM
190
+ "2026-01-15 2:30:00\u202fpm +0000" ← narrow non-breaking space before pm
191
+ ```
192
+
193
+ ### Sleep — 3 schema variants (detected by `src/parse/sleep.ts`)
194
+ - `detailed` — has `startDate`/`endDate` (non-aggregated phases)
195
+ - `aggregated_v2` — has `core`/`deep`/`rem` + `source` (HAE >= 6.6.2)
196
+ - `aggregated_v1` — has `sleepSource`/`inBedSource` (HAE < 6.6.2)
197
+
198
+ Detection: `'startDate' in dp` → detailed | `'core' in dp` → v2 | else → v1
199
+
200
+ ---
201
+
202
+ ## Development
203
+
204
+ ```bash
205
+ npm install
206
+ npm run dev -- serve # run server without building
207
+ npm run build # compile TypeScript → dist/
208
+ npm test # run all tests (59 passing)
209
+ npm install -g . # install globally as hvault
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Reference Projects
215
+
216
+ Located at `/Volumes/storage/01_Projects/whoop/healthy/`:
217
+
218
+ - `health-auto-export-server/` — TypeScript/MongoDB reference. Useful: `MetricName.ts`, `Metric.ts`
219
+ - `apple-health-ingester/` — Go reference. Useful: `types.go` (canonical type defs + time parser)
220
+ - `restapi.md` — Official HAE REST API documentation
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # hae-vault
2
+
3
+ [![npm version](https://img.shields.io/npm/v/hae-vault.svg)](https://www.npmjs.com/package/hae-vault)
4
+
5
+ CLI + HTTP server for Apple Health data from the [Health Auto Export](https://www.healthexportapp.com) iOS app. Ingests via REST API or ZIP file, stores in local SQLite.
6
+
7
+ ```bash
8
+ npm install -g hae-vault
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```bash
14
+ hvault serve # start ingest server (port 4242)
15
+ hvault import export.zip # bulk import from HAE export file
16
+ hvault dashboard # full terminal dashboard
17
+ hvault summary --color # N-day averages with emoji indicators
18
+ ```
19
+
20
+ ## Setup
21
+
22
+ 1. Install the [Health Auto Export](https://www.healthexportapp.com) iOS app
23
+ 2. In HAE: Settings → REST API → set server URL to `http://your-server:4242/api/ingest`
24
+ 3. Or: export a ZIP from HAE and run `hvault import export.zip`
25
+
26
+ **Optional:** create `.env` in your working directory to override defaults:
27
+
28
+ ```env
29
+ HVAULT_DB_PATH=~/.hae-vault/health.db # SQLite DB location
30
+ HVAULT_PORT=4242 # ingest server port
31
+ HVAULT_TOKEN=secret # bearer token for serve (optional)
32
+ HVAULT_WATCH_DIR=~/Downloads # directory to watch for exports
33
+ ```
34
+
35
+ ## Commands
36
+
37
+ ### Ingest
38
+
39
+ | Command | Description |
40
+ | --- | --- |
41
+ | `hvault serve` | Start HTTP server, receive HAE REST API pushes |
42
+ | `hvault import <file>` | Import HAE JSON or ZIP export (idempotent) |
43
+ | `hvault watch` | Watch directory and auto-import new HAE exports |
44
+
45
+ ### Query
46
+
47
+ Output is JSON by default. Add `--pretty` for formatted JSON.
48
+
49
+ | Command | Description |
50
+ | --- | --- |
51
+ | `hvault metrics --metric <name>` | Time series for a specific metric |
52
+ | `hvault sleep` | Sleep records with stage breakdown |
53
+ | `hvault workouts` | Workout sessions |
54
+ | `hvault summary` | Per-metric averages over N days (JSON) |
55
+ | `hvault query "<sql>"` | Raw SQL query |
56
+
57
+ ### Analysis
58
+
59
+ Output is pretty-printed by default. Add `--json` for raw JSON.
60
+
61
+ | Command | Description |
62
+ | --- | --- |
63
+ | `hvault summary --color` | N-day averages with emoji indicators |
64
+ | `hvault dashboard` | Full terminal dashboard with trends |
65
+ | `hvault trends` | Multi-metric trend analysis with direction arrows |
66
+
67
+ ### Info
68
+
69
+ | Command | Description |
70
+ | --- | --- |
71
+ | `hvault sources` | Metric coverage in DB (name, count, date range) |
72
+ | `hvault last-sync` | Last HAE REST API push received |
73
+ | `hvault stats` | Row counts per table |
74
+
75
+ ## Example output
76
+
77
+ `hvault dashboard`:
78
+ ```
79
+ 📅 2026-02-18 | Apple Health Vault
80
+
81
+ ── Sleep (last night) ────────────────
82
+ 😴 7.2h | Efficiency: 94%
83
+ Deep: 1.5h (21%) | REM: 2.1h (29%) | Light: 3.6h (50%)
84
+ Awake: 0.3h | Source: Apple Watch
85
+
86
+ ── Activity (recent) ─────────────────
87
+ 👟 8,432 steps | 🔥 420 kcal active
88
+ Stand hours: 10
89
+
90
+ ── Heart Health ──────────────────────
91
+ 💓 Resting HR: 58bpm | HRV: 44ms
92
+
93
+ ── Recent Workouts ───────────────────
94
+ 🚶 2026-02-17 Walking 45min 280 kcal
95
+ 🚴 2026-02-15 Cycling 62min 420 kcal
96
+
97
+ ── 7-Day Trends ──────────────────────
98
+ Steps: 7,200 → 8,432 ↑ (avg 7,840)
99
+ Sleep: 6.8h → 7.2h ↑ (avg 7.1h)
100
+ Resting HR: 60 → 58bpm ↓ (avg 59)
101
+ HRV: 42 → 44ms ↑ (avg 43)
102
+
103
+ ── Vault Stats ───────────────────────
104
+ Metrics: 570,432 | Sleep: 365 | Workouts: 248
105
+ Last sync: 2026-02-18 09:23 UTC
106
+ ```
107
+
108
+ `hvault summary --color --days 30`:
109
+ ```
110
+ 📊 30-Day Summary
111
+
112
+ 👟 Avg Steps: 8,432
113
+ 💓 Avg Resting HR: 58bpm
114
+ 🧠 Avg HRV: 44ms
115
+ 😴 Avg Sleep: 7.2h
116
+ 🔥 Avg Active Cal: 420 kcal
117
+ ```
118
+
119
+ `hvault trends --days 7`:
120
+ ```
121
+ 📊 7-Day Trends
122
+
123
+ 👟 Steps: 8,432 avg (6,100–11,200) ↑
124
+ 💓 Resting HR: 58bpm avg (55–62) ↓
125
+ 🧠 HRV: 44ms avg (38–52) ↑
126
+ 😴 Sleep: 7.2h avg (5.5–8.9h) ↑
127
+ 🔥 Active Cal: 420 kcal avg (280–620) →
128
+ ```
129
+
130
+ `hvault stats`:
131
+ ```json
132
+ {"metrics":570432,"sleep":365,"workouts":248,"syncs":12}
133
+ ```
134
+
135
+ ## Flags
136
+
137
+ ### Ingest flags
138
+
139
+ | Flag | Applies to | Description |
140
+ | --- | --- | --- |
141
+ | `--port <n>` | serve | HTTP port (default: 4242) |
142
+ | `--token <secret>` | serve | Require `Authorization: Bearer` header |
143
+ | `--target <name>` | import, watch | Tag data with device/person name |
144
+ | `--dir <path>` | watch | Directory to watch |
145
+ | `--interval <s>` | watch | Poll interval in seconds (default: 60) |
146
+
147
+ ### Query flags
148
+
149
+ | Flag | Description |
150
+ | --- | --- |
151
+ | `--days <n>` | Days of history (default varies per command) |
152
+ | `--metric <name>` | Metric name, e.g. `step_count`, `resting_heart_rate` |
153
+ | `--pretty` | Pretty-print JSON output |
154
+
155
+ ### Analysis flags
156
+
157
+ | Flag | Applies to | Description |
158
+ | --- | --- | --- |
159
+ | `--days <n>` | all analysis | Days of history (default: 7 or 90) |
160
+ | `-c, --color` | summary | Pretty terminal output |
161
+ | `--json` | dashboard, trends | Raw JSON output |
162
+
163
+ ## Environment variables
164
+
165
+ Load order: CLI flag > env var > `.env` file > default.
166
+
167
+ ```bash
168
+ HVAULT_DB_PATH=~/.hae-vault/health.db # SQLite DB location
169
+ HVAULT_PORT=4242 # serve port
170
+ HVAULT_TOKEN=secret # bearer token for serve
171
+ HVAULT_WATCH_DIR=~/Downloads # directory to watch
172
+ HVAULT_WATCH_INTERVAL=60 # watch poll interval (seconds)
173
+ HVAULT_TARGET=default # default target name
174
+ HVAULT_ENV_FILE=/path/to/.env # override .env file location
175
+ ```
176
+
177
+ ## Exit codes
178
+
179
+ | Code | Meaning |
180
+ | --- | --- |
181
+ | 0 | Success |
182
+ | 1 | General error |
183
+
184
+ ## Development
185
+
186
+ ```bash
187
+ git clone https://github.com/mrkhachaturov/hae-vault.git
188
+ cd hae-vault
189
+ npm install
190
+
191
+ npm run dev -- serve # run server without building
192
+ npm run dev -- dashboard # run dashboard without building
193
+ npm run build # compile TypeScript → dist/
194
+ npm test # run test suite
195
+ npm install -g . # install globally as hvault
196
+ ```
197
+
198
+ Node.js 22+ required.
199
+
200
+ ## Full command reference
201
+
202
+ → [docs/COMMANDS.md](docs/COMMANDS.md)
203
+
204
+ ## License
205
+
206
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: hae-vault
3
+ description: >
4
+ Apple Health archive database. Use for: historical Apple Health data (steps,
5
+ heart rate, HRV, sleep, workouts, mindfulness, respiratory rate, blood oxygen
6
+ from iPhone/Apple Watch), multi-day trends, long-term patterns. Data comes
7
+ from Health Auto Export iOS app synced to local SQLite. NOT for WHOOP data —
8
+ use whoop-up skill for that. NOT for live/real-time data.
9
+ metadata:
10
+ openclaw:
11
+ emoji: "🍎"
12
+ requires:
13
+ bins:
14
+ - hvault
15
+ install:
16
+ - id: node
17
+ kind: node
18
+ package: hae-vault
19
+ bins:
20
+ - hvault
21
+ label: "Install hae-vault (node)"
22
+ ---
23
+
24
+ # hae-vault
25
+
26
+ Query Apple Health data stored locally by `hvault serve` from the Health Auto Export iOS app.
27
+
28
+ ## Commands
29
+
30
+ ```bash
31
+ # Query last 30 days of steps
32
+ hvault metrics --metric step_count --days 30
33
+
34
+ # Query HRV
35
+ hvault metrics --metric heart_rate_variability --days 30
36
+
37
+ # Query sleep (last 14 nights)
38
+ hvault sleep --days 14
39
+
40
+ # Query workouts (last 30 days)
41
+ hvault workouts --days 30
42
+
43
+ # Summary averages across all metrics (90 days)
44
+ hvault summary --days 90
45
+
46
+ # Raw SQL for custom queries
47
+ hvault query "SELECT date, qty FROM metrics WHERE metric='step_count' ORDER BY date DESC LIMIT 7"
48
+
49
+ # What's in the DB?
50
+ hvault sources
51
+ hvault last-sync
52
+ hvault stats
53
+ ```
54
+
55
+ ## Available Metrics (common)
56
+
57
+ step_count, heart_rate, heart_rate_variability, resting_heart_rate,
58
+ active_energy, basal_energy_burned, respiratory_rate, blood_oxygen_saturation,
59
+ weight_body_mass, body_fat_percentage, sleep_analysis (via hvault sleep),
60
+ mindful_minutes, vo2max, walking_running_distance, flights_climbed
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const dashboardCommand: Command;
3
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/cli/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6GpC,eAAO,MAAM,gBAAgB,SAoIzB,CAAC"}