@drakulavich/oura-cli 0.5.0 → 0.5.2
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/CHANGELOG.md +37 -0
- package/README.md +11 -9
- package/dist/index.js +924 -734
- package/docs/schemas/doctor.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,40 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.5.2] - 2026-09-06
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- `db trends N` covers N calendar days ending today; it used to include one day more than the heading claimed. (#52)
|
|
13
|
+
- `report` no longer averages a day whose activity is still accumulating as if it were complete. A day counts as complete once it is over in the report timezone and the ring has uploaded past its end (the newest heart-rate sample in the cache is the proxy); activity and steps averages, the high-activity pattern and the steps recommendation stop at the last complete day, while sleep and readiness — final once they exist — still use the whole window. The partial day stays in the daily table, marked `*`, with one line explaining it. (#57)
|
|
14
|
+
- A 401/403 from the Oura API carries a hint (`oura-cli login` with a fresh token), like a missing token already did. (#54)
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- `manifest`: `healthcheck.expects` lists the `error` field that `healthcheck` emits when `ok` is false. (#54)
|
|
18
|
+
- `report` JSON: `days[].partial`, `completeThrough`, `lastUpload` and `averages[].count` are added; nothing is removed or renamed. (#57)
|
|
19
|
+
- README's automation section no longer claims JSON Schemas for every output shape (they cover `fetch` and `doctor`), explains that `doctor` and `healthcheck` exit 0 with `ok: false` when the probe itself ran, and records two quirks kept for compatibility: `report --period month` returns `weekStart`/`weekEnd`, and `heartrate.day` is the date written in Oura's timestamp, UTC in practice. (#54)
|
|
20
|
+
|
|
21
|
+
## [0.5.1] - 2026-09-05
|
|
22
|
+
|
|
23
|
+
Fixes from the 0.5.0 exploratory testing sessions: the seam between citty and the command runner, and the sync window.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- `sync` JSON: `import.counts` is replaced by `import.fetched` (rows the API returned per table) and `import.added` (net growth: days or samples the table did not hold before; a revised row for a day already stored counts as fetched, not new). The text summary prints `sleep 28 (+0)` in the same spirit, so a repeat run no longer looks like it imported 28 days. (#51)
|
|
27
|
+
- `sync --from YYYY-MM-DD [--to YYYY-MM-DD]` re-fetches an explicit window for every collection, for recovery after an interrupted run or a deliberate backfill. `--to` defaults to today and requires `--from`. (#53)
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- `sync` resumes every collection from its own last stored day instead of a single watermark taken from the three daily tables. A run interrupted after those tables (Ctrl-C, a crash) used to advance the watermark and leave the other six collections with a permanent gap that no later sync could fill. (#53)
|
|
31
|
+
- First sync fetches exactly 30 inclusive days, as documented, not 31. (#46)
|
|
32
|
+
- `fetch sleep-periods --day D` and `sync` no longer miss the requested day's sleep periods, and `fetch workout --from A --to B` no longer drops workouts on day B: Oura treats `start_date` as exclusive for `sleep` and `end_date` as exclusive for `workout`, and the request bounds are now shifted accordingly. (#58)
|
|
33
|
+
- Two `oura-cli` processes on the same cache no longer fail with `database is locked`: connections wait up to 5 s for a lock, `PRAGMA journal_mode = WAL` is only issued when the file is not already in WAL mode (that statement itself needs an exclusive lock), and a lock that does outlast the wait reports a hint naming the cause. (#56)
|
|
34
|
+
- `~/.oura-cli/` and a newly created cache file are created with `0700` / `0600` permissions, matching the token file; existing files are left alone. (#60)
|
|
35
|
+
- `doctor --offline` reports the token check as `skip` rather than `ok`. The new status keeps `ok: true` and produces no next step, but an agent gating on the JSON can now tell "not checked" from "passed"; `docs/schemas/doctor.json` lists the value. (#59)
|
|
36
|
+
- README: bundle size, the sync wording above, the token-missing message shape, and the `fetch sleep` pipe example, which read a readiness contributor (`hrv_balance`) off the sleep collection and printed `null` for every row. (#62)
|
|
37
|
+
- A token containing whitespace or a line break (for example a token file with a second line) is rejected as `TOKEN_INVALID` (exit 2) naming the source; previously it reached the API layer and came back as `UNKNOWN` with the token quoted in the message. Every error message and hint is now passed through the secret redactor. (#47)
|
|
38
|
+
- `DB_ERROR` (exit 4) is reachable: a corrupt cache file, an unusable `--db` path or a failing query in `db *`, `sync` and `report` now report `DB_ERROR` with a hint instead of `UNKNOWN` / exit 1. (#48)
|
|
39
|
+
- Errors raised before a command runs — unknown command, missing positional, no command on a pipe — use the same envelope as every other error: JSON on stderr when piped, text on a TTY, nothing on stdout, `--no-color` honoured. The commands removed in 0.5.0 (`db reset`, `db import`, `sleep|readiness|activity|hr|spo2|stress|workout …`) point at `fetch`/`sync`. `--help` and a bare `oura-cli` on a TTY still show usage, and `--version` now answers even when other flags are present (it used to exit 1 with usage unless it was the only argument), but not when it sits in another flag's value position. (#49)
|
|
40
|
+
- Undeclared flags and extra positionals are `BAD_ARGS` instead of being ignored, for every command including `describe`, `manifest`, `healthcheck` and `login`: `fetch sleep --dayz 7` no longer returns today's data with exit 0, and `db trends -5` no longer falls back to the 30-day default. (#50, part of #52)
|
|
41
|
+
- Global flags placed before the subcommand are no longer moved past a `--` separator, and `oura-cli constructor` (any `Object.prototype` name) is an unknown command instead of a silent exit 0.
|
|
42
|
+
|
|
9
43
|
## [0.5.0] - 2026-09-05
|
|
10
44
|
|
|
11
45
|
### Breaking
|
|
@@ -307,6 +341,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
307
341
|
- Local SQLite cache at `~/.oura-cli/oura.db`.
|
|
308
342
|
- Auth via `oura-cli login`, `OURA_TOKEN`, `OURA_TOKEN_PATH`, or `~/.oura-token`.
|
|
309
343
|
|
|
344
|
+
[0.5.2]: https://github.com/drakulavich/oura-cli/releases/tag/v0.5.2
|
|
345
|
+
[0.5.1]: https://github.com/drakulavich/oura-cli/releases/tag/v0.5.1
|
|
346
|
+
[0.5.0]: https://github.com/drakulavich/oura-cli/releases/tag/v0.5.0
|
|
310
347
|
[0.4.4]: https://github.com/drakulavich/oura-cli/releases/tag/v0.4.4
|
|
311
348
|
[0.4.3]: https://github.com/drakulavich/oura-cli/releases/tag/v0.4.3
|
|
312
349
|
[0.4.2]: https://github.com/drakulavich/oura-cli/releases/tag/v0.4.2
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- **Offline-first.** Everything caches into `~/.oura-cli/oura.db` after one `oura-cli sync`. Reports keep working when your internet doesn't.
|
|
18
18
|
- **Real terminal reports.** `oura-cli report` writes a weekly or monthly digest with averages, trend deltas, and "you slept poorly Tuesday" callouts. No dashboards, no logging in.
|
|
19
19
|
- **Pipe-friendly.** Output auto-switches to stable JSON when stdout isn't a terminal. Analyse with `jq`, plot with `gnuplot`, or feed it into your own scripts.
|
|
20
|
-
- **Single
|
|
20
|
+
- **Single ~110 kB binary, MIT, no telemetry.** Built on Bun; zero native dependencies.
|
|
21
21
|
|
|
22
22
|
## Install
|
|
23
23
|
|
|
@@ -50,18 +50,18 @@ Four commands get you there:
|
|
|
50
50
|
```bash
|
|
51
51
|
oura-cli login # paste your PAT — input is hidden, nothing echoes to the terminal
|
|
52
52
|
oura-cli doctor # confirm the token works and the local database is ready
|
|
53
|
-
oura-cli sync # first sync
|
|
53
|
+
oura-cli sync # first sync fetches the last 30 days; later syncs resume from the last stored day
|
|
54
54
|
oura-cli report # weekly digest in the terminal
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
Subsequent `oura-cli sync`
|
|
57
|
+
Subsequent `oura-cli sync` re-fetches each collection from its own last stored day (Oura revises recent days, so the overlap is deliberate) and reports rows fetched (+new). `oura-cli sync --from 2026-08-01 [--to 2026-08-07]` re-fetches an explicit window for every collection instead — for example after an interrupted sync. `oura-cli db today` / `oura-cli db week` read the local cache instantly, no API call.
|
|
58
58
|
|
|
59
59
|
### If something looks wrong
|
|
60
60
|
|
|
61
61
|
| What you see | What to run |
|
|
62
62
|
|---|---|
|
|
63
63
|
| `No Oura data is available for this report yet.` | `oura-cli sync` |
|
|
64
|
-
| `No Oura access token at
|
|
64
|
+
| `No Oura access token at /…/.oura-token` | `oura-cli login` |
|
|
65
65
|
| `Oura API 401` | `oura-cli login` with a fresh PAT |
|
|
66
66
|
| `db today` empty right after a sync | Normal — Oura publishes a day's summary after that night's sleep syncs from the ring. |
|
|
67
67
|
| Anything else | `oura-cli doctor` |
|
|
@@ -96,7 +96,7 @@ oura-cli report # weekly (default)
|
|
|
96
96
|
oura-cli report --period month # 30-day window with weekly buckets
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
Reports cover daily scores, averages, deltas vs the previous window, sleep details, and a short recommendation block.
|
|
99
|
+
Reports cover daily scores, averages, deltas vs the previous window, sleep details, and a short recommendation block. A day whose activity is still accumulating (today, or the last day before the ring stopped syncing) is shown with a `*` and kept out of the activity averages and recommendations; the JSON says so via `days[].partial` and `completeThrough`.
|
|
100
100
|
|
|
101
101
|
### Trends and stats
|
|
102
102
|
|
|
@@ -123,7 +123,7 @@ Collections: `sleep readiness activity hr spo2 stress workout sleep-periods cv-a
|
|
|
123
123
|
Output auto-switches to JSON the moment you pipe it:
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
oura-cli fetch sleep --days 7 | jq '.[] | {day, score,
|
|
126
|
+
oura-cli fetch sleep --days 7 | jq '.[] | {day, score, deep: .contributors.deep_sleep}'
|
|
127
127
|
oura-cli db trends 90 > trends.json
|
|
128
128
|
```
|
|
129
129
|
|
|
@@ -163,17 +163,19 @@ This tool reads your personal health data — handle the token with care.
|
|
|
163
163
|
| Sleep model | Oura V2 `sleep` | `sleep_model` |
|
|
164
164
|
| Cardiovascular age | Oura V2 `cardiovascular_age` | `cardiovascular_age` |
|
|
165
165
|
|
|
166
|
-
Runtime: [Bun](https://bun.sh). Storage: built-in `bun:sqlite`. CLI parsing: [citty](https://github.com/unjs/citty). Output styling: [chalk](https://github.com/chalk/chalk). One
|
|
166
|
+
Runtime: [Bun](https://bun.sh). Storage: built-in `bun:sqlite`. CLI parsing: [citty](https://github.com/unjs/citty). Output styling: [chalk](https://github.com/chalk/chalk). One ~110 kB `dist/index.js`, no native deps.
|
|
167
167
|
|
|
168
168
|
## Automation (LLM agents, scripts, MCP)
|
|
169
169
|
|
|
170
170
|
If you're driving the CLI from a script or LLM harness:
|
|
171
171
|
|
|
172
172
|
- `oura-cli describe` — JSON manifest of every command, argument, and output schema. Agents discover capabilities without scraping `--help`.
|
|
173
|
-
- `oura-cli healthcheck` — `{ok, version, latencyMs}` JSON for liveness probes.
|
|
173
|
+
- `oura-cli healthcheck` — `{ok, version, latencyMs}` JSON for liveness probes, plus `error` when `ok` is false.
|
|
174
|
+
- Gate on `.ok`, not on the exit code: `doctor` exits 0 with `ok: false` for any warning-level check (no data yet, stale data, Oura API unreachable), and `healthcheck` exits 0 with `ok: false` for an unusable database (the probe itself ran). `doctor --offline` skips the token-validation call, and a skipped check still counts towards `ok`.
|
|
174
175
|
- Errors emit a stable JSON envelope on stderr: `{"error":{"code":"…","message":"…","hint":"…"}}`.
|
|
175
176
|
- Documented exit codes: `0` success, `1` user error, `2` auth, `3` API, `4` storage.
|
|
176
|
-
- JSON Schemas under [`docs/schemas/`](docs/schemas/) describe
|
|
177
|
+
- JSON Schemas under [`docs/schemas/`](docs/schemas/) cover `fetch <collection>`, `doctor` and the `describe` manifest itself, semver-stable; `describe` names the schema next to each command. Per-collection schemas pin the identity fields (`id`, `day`, `timestamp`) and allow the rest of the Oura record through unchanged, so new upstream fields never break validation. The local-data commands (`sync`, `db *`, `report`) have no schema files yet; their shapes are versioned through the CHANGELOG.
|
|
178
|
+
- Two contract quirks, kept for compatibility: `report --period month` returns its window as `weekStart`/`weekEnd`, and `heartrate.day` in the cache is the date written in Oura's timestamp (UTC in practice) while every `--day`/`--tz` argument is local.
|
|
177
179
|
|
|
178
180
|
Plays cleanly with [OpenClaw](https://github.com/openclaw/openclaw) — `oura-cli manifest` returns the tool-registry shape. A first-party `oura-mcp` companion is on the roadmap.
|
|
179
181
|
|