CLI for Cronometer automation via Kernel.sh.
Cronometer has no public API, so crono automates the web UI through Kernel.sh browser automation. Log macros from your terminal in seconds.
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.
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.
npm install -g @milldr/cronocrono loginYou'll be prompted for three things:
- Kernel API key — get one at kernel.sh
- Cronometer email — your Cronometer account email
- Cronometer password — stored securely in your system keychain
┌ crono login
│
◇ Kernel API key
│ sk-abc...
│
◒ Validating API key...
◇ API key valid.
│
◇ Cronometer email
│ you@example.com
│
◇ Cronometer password
│ ****
│
└ Credentials saved.
crono quick-add -p 30 -c 100 -f 20 -a 14 -m Dinner -d yesterday┌ crono quick-add
│
◒ Logging into Cronometer...
◇ Done.
│
└ Added: 30g protein, 100g carbs, 20g fat, 14g alcohol → Dinner on 2026-02-15
Set up or update your Kernel API key and Cronometer credentials. If credentials already exist, pressing Enter keeps the current value.
crono loginHeadless / container deployments: all credentials can be provided via environment variables instead of crono login. Env vars take precedence over stored credentials.
| Variable | Credential |
|---|---|
KERNEL_API_KEY |
Kernel.sh API key |
CRONO_CRONOMETER_USERNAME |
Cronometer email |
CRONO_CRONOMETER_PASSWORD |
Cronometer password |
Add a quick macro entry to your Cronometer diary.
crono quick-add [options]Options:
| Flag | Long | Description |
|---|---|---|
-p |
--protein <g> |
Grams of protein |
-c |
--carbs <g> |
Grams of carbohydrates |
-f |
--fat <g> |
Grams of fat |
-a |
--alcohol <g> |
Grams of alcohol |
-m |
--meal <name> |
Meal category (Breakfast, Lunch, Dinner, Snacks) |
-d |
--date <date> |
Date (YYYY-MM-DD, yesterday, -1d) |
At least one macro flag (-p, -c, -f, or -a) is required.
Safe execution and verification: Quick-add is not idempotent and saves each
macro separately (Quick Add, Protein, Quick Add, Carbohydrate, Quick Add, Fat,
and Quick Add, Alcohol). Wait for the original CLI process to exit; if your
execution tool returns a session ID, retain it and poll that same session.
Progress output or a tool's wait deadline is not a completed failure. Never
launch a second write while the first may still be running.
Take an unfiltered crono export servings -d YYYY-MM-DD --json snapshot before
writing, then compare another snapshot after the process completes. Check each
requested macro's amount and meal, not the restaurant or sandwich name. Empty
servings exports produce []; invalid exports fail instead of implying absence.
Check the exit status and keep stderr visible. A missing row while a write is
pending does not prove failure. A failed write may have saved only some macros;
never replay the whole meal after a partial save. If the operation's completion
or diary state is uncertain, stop and report an unconfirmed outcome rather than
retrying. The browser SDK's automatic transport retries are disabled to avoid
replaying non-idempotent operations after a lost response.
Examples:
# Log 30g protein
crono quick-add -p 30
# Log full meal macros
crono quick-add -p 30 -c 100 -f 20
# Log to Dinner category
crono quick-add -p 30 -c 50 -f 15 --meal Dinner
# Log to yesterday
crono quick-add -p 30 -d yesterday -m Dinner
# Log alcohol
crono quick-add -a 14 -m Dinner
# Combine everything
crono quick-add -p 30 -c 50 -f 10 -a 14 -d -3d -m DinnerCreate a custom food in Cronometer with specified macros.
crono add custom-food <name> [options]Options:
| Flag | Long | Description |
|---|---|---|
-p |
--protein <g> |
Grams of protein |
-c |
--carbs <g> |
Grams of carbohydrates |
-f |
--fat <g> |
Grams of fat |
--log [meal] |
Also log to diary (optionally specify meal) |
At least one macro flag (-p, -c, or -f) is required.
Examples:
# Create a custom food with all macros
crono add custom-food "Wendy's Chicken Sandwich" -p 50 -c 100 -f 50
# Just protein and carbs
crono add custom-food "Post-Workout Shake" -p 40 -c 60
# Create and immediately log to Uncategorized
crono add custom-food "Wendy's Chicken Sandwich" -p 50 -c 100 -f 50 --log
# Create and immediately log to Dinner
crono add custom-food "Wendy's Chicken Sandwich" -p 50 -c 100 -f 50 --log DinnerLog a saved food to your diary by name. Works with custom foods, custom recipes, and database items.
crono log <name> [options]Options:
| Flag | Long | Description |
|---|---|---|
-m |
--meal <name> |
Meal category (Breakfast, Lunch, Dinner, Snacks) |
-s |
--servings <count> |
Number of servings (default: 1) |
Examples:
# Log a custom food
crono log "Wendy's Chicken Sandwich"
# Log to a specific meal
crono log "Wendy's Chicken Sandwich" -m Dinner
# Log multiple servings
crono log "Post-Workout Shake" -s 2 -m SnacksCheck your weight from Cronometer. Defaults to today if no date or range is specified.
crono weight [options]Options:
| Flag | Long | Description |
|---|---|---|
-d |
--date <date> |
Date (YYYY-MM-DD) |
-r |
--range <range> |
Range (7d, 30d, or YYYY-MM-DD:YYYY-MM-DD) |
--json |
Output as JSON |
-d and -r are mutually exclusive.
Examples:
# Today's weight
crono weight
# → 212.5 lbs
# Specific date
crono weight -d 2026-02-05
# Last 7 days
crono weight -r 7d
# → 2026-02-11: 212.5
# → 2026-02-10: 212.7
# → 2026-02-09: 215.5
# → ...
# JSON output for scripting
crono weight --json
# → {"date":"2026-02-11","weight":212.5,"unit":"lbs"}
# Range as JSON
crono weight -r 7d --json
# → [{"date":"2026-02-11","weight":212.5,"unit":"lbs"}, ...]View daily nutrition totals (calories, protein, carbs, fat) from Cronometer. Defaults to today if no date or range is specified.
crono diary [options]Options:
| Flag | Long | Description |
|---|---|---|
-d |
--date <date> |
Date (YYYY-MM-DD) |
-r |
--range <range> |
Range (7d, 30d, or YYYY-MM-DD:YYYY-MM-DD) |
-t |
--targets |
Show macro targets and progress |
--json |
Output as JSON |
-d and -r are mutually exclusive.
Examples:
# Today's nutrition
crono diary
# → 1847 kcal | P: 168g | C: 142g | F: 58g
# Specific date
crono diary -d 2026-02-05
# Last 7 days
crono diary -r 7d
# → 2026-02-11: 1847 kcal | P: 168g | C: 142g | F: 58g
# → 2026-02-10: 2103 kcal | P: 155g | C: 200g | F: 72g
# → ...
# Show targets and progress
crono diary --targets
# → 2994 kcal (109% of 2746) | P: 239g | C: 311g | F: 95g
# Targets with range (includes averages)
crono diary --targets -r 3d
# → 2026-03-12: 2994 kcal (109% of 2746) | P: 239g | C: 311g | F: 95g
# → 2026-03-11: 2770 kcal (100% of 2759) | P: 238g | C: 273g | F: 88g
# → 2026-03-10: 2678 kcal (97% of 2750) | P: 248g | C: 279g | F: 87g
# → ───
# → Average: 2814 kcal (102% of 2752) | P: 242g | C: 288g | F: 90g
# JSON output for scripting
crono diary --json
# → {"date":"2026-02-11","calories":1847,"protein":168,"carbs":142,"fat":58}
# Range as JSON
crono diary -r 7d --json
# → [{"date":"2026-02-11","calories":1847,"protein":168,"carbs":142,"fat":58}, ...]Log biometrics to Cronometer (weight, body fat percentage, blood pressure). Defaults to today if no date is specified.
crono biometrics [options]Options:
| Flag | Long | Description |
|---|---|---|
-w |
--weight <value> |
Weight value |
-b |
--body-fat <value> |
Body fat percentage |
-s |
--systolic <value> |
Systolic blood pressure (mmHg) |
-d |
--diastolic <value> |
Diastolic blood pressure (mmHg) |
--date <date> |
Date (YYYY-MM-DD, yesterday, -1d) | |
-u |
--unit <unit> |
Weight unit (kg or lbs), default: kg |
At least one biometric value is required. Blood pressure requires both systolic and diastolic values.
Examples:
# Log weight in kg (default)
crono biometrics --weight 90
# Log weight in lbs
crono biometrics --weight 198 --unit lbs
# Log body fat percentage
crono biometrics --body-fat 19
# Log blood pressure
crono biometrics --systolic 130 --diastolic 76
# Log weight for yesterday
crono biometrics --weight 90 --date yesterday
# Log multiple biometrics (requires multiple commands)
crono biometrics --weight 90
crono biometrics --body-fat 19List your custom recipes from Cronometer.
crono recipes [options]Options:
| Flag | Long | Description |
|---|---|---|
--json |
Output as JSON |
Examples:
# List all custom recipes
crono recipes
# → Chicken Stir Fry
# → Overnight Oats
# → 2 recipes
# JSON output for scripting
crono recipes --jsonExport data directly from Cronometer's API — no browser automation, much faster than diary or weight.
crono export <type> [options]Types:
| Type | Granularity | Description |
|---|---|---|
nutrition |
Daily totals | Aggregated calories + 60+ nutrient columns (vitamins, minerals, amino acids, omega 3/6, etc.) |
servings |
Per food entry | Time, meal, food name, amount, and nutrient columns when supplied by Cronometer |
exercises |
Per exercise entry | Time, exercise name, duration, calories burned, group |
biometrics |
Per measurement | Weight, BP, plus anything Apple Health pushes in (heart rate, HRV, sleep) |
Options:
| Flag | Long | Description |
|---|---|---|
-d |
--date <date> |
Date (YYYY-MM-DD) |
-r |
--range <range> |
Range (7d, 30d, or YYYY-MM-DD:YYYY-MM-DD) |
-m |
--meal <name> |
servings only: filter to a meal (Breakfast / Lunch / Dinner / Snacks) |
--csv |
Output as raw CSV | |
--json |
Output as JSON |
-d and -r are mutually exclusive. --csv and --json are mutually exclusive.
Cronometer may return a servings CSV with no nutrient columns. In that case,
JSON nutrient fields are null, not zero, and text output reports unknown
values without inventing totals. Blank or invalid nutrient values are also
unknown. Use the live food details and diary to verify nutrition when the
export omits it; do not treat null as a zero-calorie food.
Examples:
# Today's nutrition (daily totals)
crono export nutrition
# → 1847 kcal | P: 168g | C: 142g | F: 58g
# Last 7 days of nutrition as JSON
crono export nutrition -r 7d --json
# What did I have for dinner today? (per-food breakdown)
crono export servings -m Dinner
# → 7:30 PM | Dinner | Beef Steak | 150g | 306 kcal | P: 46g C: 0g F: 13.5g
# → ...
# → Total: 672 kcal | P: 70.1g C: 43.5g F: 34.3g
# Yesterday's full food log
crono export servings -d yesterday
# Last 7 days of food entries as JSON (includes nutrient columns when available)
crono export servings -r 7d --json
# Today's exercises
crono export exercises
# → Running: 30 min, 350 kcal
# Biometrics for last 30 days
crono export biometrics -r 30d
# → 2026-02-11: Weight: 212.5 lbs
# → 2026-02-09: Blood Pressure: 120/80 mmHg
# Raw CSV export
crono export nutrition -r 30d --csvConfig: crono login writes backend preference to ~/.config/crono/config.json. Kernel remains the default; set useKernel to false to use a local Playwright browser profile instead:
{
"useKernel": false,
"playwrightHeadless": true
}Local Playwright session data is stored in ~/.config/crono/playwright-profile.
When using the local Playwright backend, install the browser binaries once:
npx playwright installGWT overrides: If Cronometer updates break the export, override GWT values in ~/.config/crono/config.json or via environment variables:
export CRONO_GWT_PERMUTATION=<new-value>
export CRONO_GWT_HEADER=<new-value>- Node.js 18+
- Kernel.sh account (for Kernel browser automation)
- Cronometer account
Food writes are non-idempotent. If add custom-food --log times out, the
custom food may already exist even when no diary entry is visible. Treat the
outcome as unconfirmed: wait for the original operation to stop, check the
food catalog, and compare a fresh unfiltered servings export for the exact diary
date with your pre-write baseline before considering any retry. Never recreate
the food based only on a missing diary row.
Food-dialog actions skip hidden controls and use bounded waits. Standalone logging has a 180-second operation budget; custom-food creation has 120 seconds, or 300 seconds when combined with logging. These budgets exclude login time; increasing them does not make retries safe.
git clone https://github.com/milldr/crono.git
cd crono
npm install
# Run in dev mode
npm run dev -- login
npm run dev -- quick-add -p 30
npm run dev -- weight -r 7d
npm run dev -- diary
# Run tests
npm test
# Build
npm run buildFor the unit suite in an authenticated shell, exclude credential overrides so the credential-store tests remain isolated:
env -u KERNEL_API_KEY -u CRONO_CRONOMETER_USERNAME -u CRONO_CRONOMETER_PASSWORD npm testI build and maintain projects like crono in my free time as personal hobbies. They're completely free and always will be. If you find this useful and want to show some support, feel free to buy me a coffee:
MIT
