@milldr/crono 0.3.0 → 0.3.1

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/README.md CHANGED
@@ -8,6 +8,12 @@ Cronometer has no public API, so crono automates the web UI through Kernel.sh br
8
8
 
9
9
  ![crono quick-add demo](demo.gif)
10
10
 
11
+ ## Motivation
12
+
13
+ Cronometer is great for logging food — barcode scanning and manual search cover most meals at home. But when you're eating out or don't have a barcode, the workflow gets clunky: take a photo, ask an AI to estimate the macros, then manually punch those numbers into the app as a quick add.
14
+
15
+ crono closes that loop. Give your AI agent a skill that knows how to call crono, and it goes from estimating macros to actually logging them — no manual step in between. On top of that, your agent can query your diary, pull export data, and answer questions about your nutrition without you ever opening the app.
16
+
11
17
  ## Quickstart
12
18
 
13
19
  ### 1. Install
@@ -49,7 +55,7 @@ You'll be prompted for three things:
49
55
  ### 3. Log a meal
50
56
 
51
57
  ```bash
52
- crono quick-add -p 30 -c 100 -f 20 -m Dinner
58
+ crono quick-add -p 30 -c 100 -f 20 -a 14 -m Dinner -d yesterday
53
59
  ```
54
60
 
55
61
  ```
@@ -58,7 +64,7 @@ crono quick-add -p 30 -c 100 -f 20 -m Dinner
58
64
  ◒ Logging into Cronometer...
59
65
  ◇ Done.
60
66
 
61
- └ Added: 30g protein, 100g carbs, 20g fat → Dinner
67
+ └ Added: 30g protein, 100g carbs, 20g fat, 14g alcohol → Dinner on 2026-02-15
62
68
  ```
63
69
 
64
70
  ## Commands
@@ -86,9 +92,11 @@ crono quick-add [options]
86
92
  | `-p` | `--protein <g>` | Grams of protein |
87
93
  | `-c` | `--carbs <g>` | Grams of carbohydrates |
88
94
  | `-f` | `--fat <g>` | Grams of fat |
95
+ | `-a` | `--alcohol <g>` | Grams of alcohol |
89
96
  | `-m` | `--meal <name>` | Meal category (Breakfast, Lunch, Dinner, Snacks) |
97
+ | `-d` | `--date <date>` | Date (YYYY-MM-DD, yesterday, -1d) |
90
98
 
91
- At least one macro flag (`-p`, `-c`, or `-f`) is required.
99
+ At least one macro flag (`-p`, `-c`, `-f`, or `-a`) is required.
92
100
 
93
101
  **Examples:**
94
102
 
@@ -101,6 +109,15 @@ crono quick-add -p 30 -c 100 -f 20
101
109
 
102
110
  # Log to Dinner category
103
111
  crono quick-add -p 30 -c 50 -f 15 --meal Dinner
112
+
113
+ # Log to yesterday
114
+ crono quick-add -p 30 -d yesterday -m Dinner
115
+
116
+ # Log alcohol
117
+ crono quick-add -a 14 -m Dinner
118
+
119
+ # Combine everything
120
+ crono quick-add -p 30 -c 50 -f 10 -a 14 -d -3d -m Dinner
104
121
  ```
105
122
 
106
123
  ### `crono add custom-food`
@@ -1 +1 @@
1
- {"version":3,"file":"quick-add.d.ts","sourceRoot":"","sources":["../../src/kernel/quick-add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKrD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAwQ3D"}
1
+ {"version":3,"file":"quick-add.d.ts","sourceRoot":"","sources":["../../src/kernel/quick-add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKrD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAmR3D"}
@@ -93,7 +93,7 @@ export function buildQuickAddCode(entry) {
93
93
  try {
94
94
  const el = page.locator(sel);
95
95
  if (await el.count() > 0) {
96
- await el.first().click();
96
+ await el.first().click({ timeout: 5000 });
97
97
  return true;
98
98
  }
99
99
  } catch {}
@@ -107,7 +107,7 @@ export function buildQuickAddCode(entry) {
107
107
  try {
108
108
  const el = page.locator(sel);
109
109
  if (await el.count() > 0) {
110
- await el.first().click({ button: 'right' });
110
+ await el.first().click({ button: 'right', timeout: 5000 });
111
111
  return true;
112
112
  }
113
113
  } catch {}
@@ -125,9 +125,12 @@ export function buildQuickAddCode(entry) {
125
125
  if (!clicked) {
126
126
  return { success: false, error: 'Could not find meal category "' + mealLabel + '" in diary' };
127
127
  }
128
- await page.waitForSelector('text="Add Food..."', { timeout: 3000 }).catch(() =>
129
- page.waitForSelector('text="Add Food"', { timeout: 2000 }).catch(() => {})
130
- );
128
+ const menuVisible = await page.waitForSelector('text="Add Food..."', { timeout: 3000 })
129
+ .then(() => true)
130
+ .catch(() => page.waitForSelector('text="Add Food"', { timeout: 2000 }).then(() => true).catch(() => false));
131
+ if (!menuVisible) {
132
+ return { success: false, error: 'Context menu did not appear after right-clicking "' + mealLabel + '"' };
133
+ }
131
134
 
132
135
  // Click "Add Food..." in context menu
133
136
  const addFoodClicked = await clickFirst([
@@ -185,7 +188,11 @@ export function buildQuickAddCode(entry) {
185
188
  'button:has-text("SEARCH")',
186
189
  'button:has-text("Search")',
187
190
  ]);
188
- await page.waitForSelector('td:has-text("' + macro.searchName + '")', { timeout: 8000 }).catch(() => {});
191
+ const resultsAppeared = await page.waitForSelector('td:has-text("' + macro.searchName + '")', { timeout: 8000 })
192
+ .then(() => true).catch(() => false);
193
+ if (!resultsAppeared) {
194
+ return { success: false, error: 'Search results did not appear for "' + macro.searchName + '"' };
195
+ }
189
196
 
190
197
  // Select the search result row (not the search input)
191
198
  // Target table rows/cells containing the macro name
@@ -276,8 +283,12 @@ export function buildQuickAddCode(entry) {
276
283
  if (!addClicked) {
277
284
  return { success: false, error: 'Could not find "Add to Diary" button for "' + macro.name + '"' };
278
285
  }
279
- await page.waitForSelector('text="Add Food to Diary"', { state: 'hidden', timeout: 8000 }).catch(() => {});
280
- await page.waitForTimeout(300);
286
+ const dialogDismissed = await page.waitForSelector('text="Add Food to Diary"', { state: 'hidden', timeout: 8000 })
287
+ .then(() => true).catch(() => false);
288
+ if (!dialogDismissed) {
289
+ return { success: false, error: '"Add Food to Diary" dialog did not close after adding "' + macro.name + '"' };
290
+ }
291
+ await page.waitForTimeout(500);
281
292
  }
282
293
 
283
294
  return { success: true };
@@ -1 +1 @@
1
- {"version":3,"file":"quick-add.js","sourceRoot":"","sources":["../../src/kernel/quick-add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,OAAO,EAAE,oBAAoB;IAC7B,KAAK,EAAE,yBAAyB;IAChC,GAAG,EAAE,gBAAgB;IACrB,OAAO,EAAE,oBAAoB;CAC9B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IACjD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAE3D,MAAM,SAAS,GAAG,IAAI;QACpB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAC5D,CAAC,CAAC,eAAe,CAAC;IAEpB,8BAA8B;IAC9B,MAAM,MAAM,GAA0D,EAAE,CAAC;IACzE,IAAI,OAAO,KAAK,SAAS;QACvB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,kBAAkB,CAAC,OAAO;YACtC,KAAK,EAAE,OAAO;SACf,CAAC,CAAC;IACL,IAAI,KAAK,KAAK,SAAS;QACrB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,kBAAkB,CAAC,KAAK;YACpC,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,IAAI,GAAG,KAAK,SAAS;QACnB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,KAAK;YACX,UAAU,EAAE,kBAAkB,CAAC,GAAG;YAClC,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;IACL,IAAI,OAAO,KAAK,SAAS;QACvB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,kBAAkB,CAAC,OAAO;YACtC,KAAK,EAAE,OAAO;SACf,CAAC,CAAC;IAEL,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO;qBACY,UAAU;wBACP,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;yBACxB,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgOlD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"quick-add.js","sourceRoot":"","sources":["../../src/kernel/quick-add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,OAAO,EAAE,oBAAoB;IAC7B,KAAK,EAAE,yBAAyB;IAChC,GAAG,EAAE,gBAAgB;IACrB,OAAO,EAAE,oBAAoB;CAC9B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IACjD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAE3D,MAAM,SAAS,GAAG,IAAI;QACpB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAC5D,CAAC,CAAC,eAAe,CAAC;IAEpB,8BAA8B;IAC9B,MAAM,MAAM,GAA0D,EAAE,CAAC;IACzE,IAAI,OAAO,KAAK,SAAS;QACvB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,kBAAkB,CAAC,OAAO;YACtC,KAAK,EAAE,OAAO;SACf,CAAC,CAAC;IACL,IAAI,KAAK,KAAK,SAAS;QACrB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,kBAAkB,CAAC,KAAK;YACpC,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,IAAI,GAAG,KAAK,SAAS;QACnB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,KAAK;YACX,UAAU,EAAE,kBAAkB,CAAC,GAAG;YAClC,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;IACL,IAAI,OAAO,KAAK,SAAS;QACvB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,kBAAkB,CAAC,OAAO;YACtC,KAAK,EAAE,OAAO;SACf,CAAC,CAAC;IAEL,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO;qBACY,UAAU;wBACP,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;yBACxB,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2OlD,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milldr/crono",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "CLI for Cronometer automation via Kernel.sh",
5
5
  "type": "module",
6
6
  "bin": {