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.
- package/.env.example +7 -0
- package/CLAUDE.md +220 -0
- package/README.md +206 -0
- package/SKILL.md +60 -0
- package/dist/cli/dashboard.d.ts +3 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +206 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/import.d.ts +3 -0
- package/dist/cli/import.d.ts.map +1 -0
- package/dist/cli/import.js +78 -0
- package/dist/cli/import.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +31 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/info.d.ts +5 -0
- package/dist/cli/info.d.ts.map +1 -0
- package/dist/cli/info.js +34 -0
- package/dist/cli/info.js.map +1 -0
- package/dist/cli/metrics.d.ts +3 -0
- package/dist/cli/metrics.d.ts.map +1 -0
- package/dist/cli/metrics.js +20 -0
- package/dist/cli/metrics.js.map +1 -0
- package/dist/cli/query.d.ts +3 -0
- package/dist/cli/query.d.ts.map +1 -0
- package/dist/cli/query.js +18 -0
- package/dist/cli/query.js.map +1 -0
- package/dist/cli/serve.d.ts +3 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +19 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/sleep.d.ts +3 -0
- package/dist/cli/sleep.d.ts.map +1 -0
- package/dist/cli/sleep.js +19 -0
- package/dist/cli/sleep.js.map +1 -0
- package/dist/cli/summary.d.ts +3 -0
- package/dist/cli/summary.d.ts.map +1 -0
- package/dist/cli/summary.js +53 -0
- package/dist/cli/summary.js.map +1 -0
- package/dist/cli/trends.d.ts +3 -0
- package/dist/cli/trends.d.ts.map +1 -0
- package/dist/cli/trends.js +77 -0
- package/dist/cli/trends.js.map +1 -0
- package/dist/cli/watch.d.ts +12 -0
- package/dist/cli/watch.d.ts.map +1 -0
- package/dist/cli/watch.js +89 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/cli/workouts.d.ts +3 -0
- package/dist/cli/workouts.d.ts.map +1 -0
- package/dist/cli/workouts.js +19 -0
- package/dist/cli/workouts.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +25 -0
- package/dist/config.js.map +1 -0
- package/dist/db/importLog.d.ts +5 -0
- package/dist/db/importLog.d.ts.map +1 -0
- package/dist/db/importLog.js +10 -0
- package/dist/db/importLog.js.map +1 -0
- package/dist/db/metrics.d.ts +4 -0
- package/dist/db/metrics.d.ts.map +1 -0
- package/dist/db/metrics.js +14 -0
- package/dist/db/metrics.js.map +1 -0
- package/dist/db/schema.d.ts +5 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +100 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/sleep.d.ts +4 -0
- package/dist/db/sleep.d.ts.map +1 -0
- package/dist/db/sleep.js +13 -0
- package/dist/db/sleep.js.map +1 -0
- package/dist/db/workouts.d.ts +4 -0
- package/dist/db/workouts.d.ts.map +1 -0
- package/dist/db/workouts.js +11 -0
- package/dist/db/workouts.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/parse/metrics.d.ts +17 -0
- package/dist/parse/metrics.d.ts.map +1 -0
- package/dist/parse/metrics.js +33 -0
- package/dist/parse/metrics.js.map +1 -0
- package/dist/parse/sleep.d.ts +23 -0
- package/dist/parse/sleep.d.ts.map +1 -0
- package/dist/parse/sleep.js +58 -0
- package/dist/parse/sleep.js.map +1 -0
- package/dist/parse/time.d.ts +4 -0
- package/dist/parse/time.d.ts.map +1 -0
- package/dist/parse/time.js +41 -0
- package/dist/parse/time.js.map +1 -0
- package/dist/parse/workouts.d.ts +17 -0
- package/dist/parse/workouts.d.ts.map +1 -0
- package/dist/parse/workouts.js +24 -0
- package/dist/parse/workouts.js.map +1 -0
- package/dist/server/app.d.ts +5 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +39 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/ingest.d.ts +15 -0
- package/dist/server/ingest.d.ts.map +1 -0
- package/dist/server/ingest.js +41 -0
- package/dist/server/ingest.js.map +1 -0
- package/dist/types/hae.d.ts +103 -0
- package/dist/types/hae.d.ts.map +1 -0
- package/dist/types/hae.js +2 -0
- package/dist/types/hae.js.map +1 -0
- package/dist/util/zip.d.ts +3 -0
- package/dist/util/zip.d.ts.map +1 -0
- package/dist/util/zip.js +24 -0
- package/dist/util/zip.js.map +1 -0
- package/docs/COMMANDS.md +315 -0
- package/docs/plans/2026-02-18-hae-vault-initial-implementation.md +2015 -0
- package/docs/plans/2026-02-18-readme-dashboard-design.md +213 -0
- package/docs/plans/2026-02-18-readme-dashboard-plan.md +1306 -0
- package/docs/plans/2026-02-18-zip-env-watch-design.md +213 -0
- package/docs/plans/2026-02-18-zip-env-watch.md +966 -0
- package/package.json +57 -0
- package/src/cli/dashboard.ts +242 -0
- package/src/cli/import.ts +85 -0
- package/src/cli/index.ts +32 -0
- package/src/cli/info.ts +36 -0
- package/src/cli/metrics.ts +20 -0
- package/src/cli/query.ts +17 -0
- package/src/cli/serve.ts +18 -0
- package/src/cli/sleep.ts +19 -0
- package/src/cli/summary.ts +58 -0
- package/src/cli/trends.ts +103 -0
- package/src/cli/watch.ts +111 -0
- package/src/cli/workouts.ts +19 -0
- package/src/config.ts +28 -0
- package/src/db/importLog.ts +18 -0
- package/src/db/metrics.ts +15 -0
- package/src/db/schema.ts +105 -0
- package/src/db/sleep.ts +15 -0
- package/src/db/workouts.ts +13 -0
- package/src/index.ts +4 -0
- package/src/parse/metrics.ts +50 -0
- package/src/parse/sleep.ts +82 -0
- package/src/parse/time.ts +43 -0
- package/src/parse/workouts.ts +42 -0
- package/src/server/app.ts +46 -0
- package/src/server/ingest.ts +68 -0
- package/src/types/hae.ts +94 -0
- package/src/util/zip.ts +24 -0
- package/tests/cli-watch.test.ts +64 -0
- package/tests/db-import-log.test.ts +40 -0
- package/tests/db-metrics.test.ts +44 -0
- package/tests/db-schema.test.ts +55 -0
- package/tests/db-sleep.test.ts +36 -0
- package/tests/db-workouts.test.ts +34 -0
- package/tests/ingest.test.ts +99 -0
- package/tests/parse-metrics.test.ts +55 -0
- package/tests/parse-sleep.test.ts +65 -0
- package/tests/parse-time.test.ts +48 -0
- package/tests/parse-workouts.test.ts +43 -0
- package/tests/types.test.ts +27 -0
- package/tests/util-zip.test.ts +46 -0
- package/tsconfig.json +19 -0
package/.env.example
ADDED
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
|
+
[](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 @@
|
|
|
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"}
|