nutrilog 0.1.0__tar.gz

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.
@@ -0,0 +1,31 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ branches: ["main"]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test on Python ${{ matrix.python-version }}
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+ with:
24
+ version: "latest"
25
+ enable-cache: true
26
+
27
+ - name: Set up Python ${{ matrix.python-version }}
28
+ run: uv python install ${{ matrix.python-version }}
29
+
30
+ - name: Run test suite
31
+ run: uv run --python ${{ matrix.python-version }} --extra dev pytest --cov=nutrilog
@@ -0,0 +1,58 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ test:
10
+ name: Test & Verify Suite
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v5
17
+ with:
18
+ version: "latest"
19
+ enable-cache: true
20
+
21
+ - name: Set up Python
22
+ run: uv python install 3.12
23
+
24
+ - name: Run test suite
25
+ run: uv run --extra dev pytest --cov=nutrilog
26
+
27
+ build-and-publish:
28
+ name: Build & Publish to PyPI
29
+ needs: test
30
+ runs-on: ubuntu-latest
31
+ environment:
32
+ name: pypi
33
+ url: https://pypi.org/p/nutrilog
34
+ permissions:
35
+ id-token: write # Required for PyPI Trusted Publishing (OIDC)
36
+ contents: write # Required for GitHub Release creation
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ with:
41
+ fetch-depth: 0
42
+
43
+ - name: Install uv
44
+ uses: astral-sh/setup-uv@v5
45
+ with:
46
+ version: "latest"
47
+
48
+ - name: Build distributions (sdist & wheel)
49
+ run: uv build
50
+
51
+ - name: Publish package distributions to PyPI
52
+ uses: pypa/gh-action-pypi-publish@release/v1
53
+
54
+ - name: Create GitHub Release
55
+ uses: softprops/action-gh-release@v2
56
+ with:
57
+ files: dist/*
58
+ generate_release_notes: true
@@ -0,0 +1,38 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+
8
+ # Distribution / packaging
9
+ build/
10
+ dist/
11
+ *.egg-info/
12
+ .eggs/
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ env/
17
+ venv/
18
+ ENV/
19
+
20
+ # Testing & Coverage
21
+ .pytest_cache/
22
+ .coverage
23
+ .coverage.*
24
+ htmlcov/
25
+
26
+ # Local credentials & secrets
27
+ tokens.json
28
+ credentials.json
29
+ client_secrets*.json
30
+ client_secret*.json
31
+ *.token
32
+
33
+ # IDE & OS
34
+ .idea/
35
+ .vscode/
36
+ *.swp
37
+ *.swo
38
+ .DS_Store
nutrilog-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nutrilog Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,282 @@
1
+ Metadata-Version: 2.5
2
+ Name: nutrilog
3
+ Version: 0.1.0
4
+ Summary: A standalone, privacy-first CLI tool for logging meals, macronutrients, and calories directly to Google Health.
5
+ Author: Nutrilog Contributors
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: calories,cli,fitbit,google-health,health,macros,nutrition
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: End Users/Desktop
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: System :: Monitoring
20
+ Classifier: Topic :: Utilities
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: google-auth-oauthlib>=1.2.0
23
+ Requires-Dist: google-auth>=2.28.0
24
+ Requires-Dist: httpx>=0.27.0
25
+ Requires-Dist: pydantic>=2.6.0
26
+ Requires-Dist: python-dateutil>=2.9.0
27
+ Requires-Dist: rich>=13.7.0
28
+ Requires-Dist: typer>=0.12.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
32
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # Nutrilog
36
+
37
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
+ [![Built with Typer & Rich](https://img.shields.io/badge/CLI-Typer%20%26%20Rich-green.svg)](https://typer.tiangolo.com)
40
+ [![uvx ready](https://img.shields.io/badge/uvx-ready-purple.svg)](https://github.com/astral-sh/uv)
41
+
42
+ A fast, privacy-first CLI tool for logging meals, macronutrients, and calories directly to the **Google Health API (`health.googleapis.com/v4`)** from any terminal. Syncs live with your **Google Health app**, **Fitbit**, and **Pixel Watch**.
43
+
44
+ ---
45
+
46
+ ```
47
+ Today's Nutrition Summary (Mon, Aug 17)
48
+ ┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┓
49
+ ┃ Time ┃ Meal Type ┃ Food ┃ Protein ┃ Calories ┃ Carbs ┃ Fat ┃
50
+ ┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━┩
51
+ │ 12:30 PM │ Lunch │ Tofu Edamame Soba Bowl │ 38.5g │ 580 kcal │ 54.0g │ 18.0g │
52
+ │ 04:00 PM │ Snack │ Protein Shake │ 25.0g │ 180 kcal │ 4.0g │ 2.0g │
53
+ └━━━━━━━━━━━━┴━━━━━━━━━━━━━━┴━━━━━━━━━━━━━━━━━━━━━━━━━━┴━━━━━━━━━┴━━━━━━━━━━┴━━━━━━━━━┴━━━━━━━━┘
54
+ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮
55
+ │ Daily Total: 63.5g / 120g Protein (53%) | 760 / 2,000 kcal (38%) │
56
+ │ Remaining: 56.5g Protein | 1,240 kcal │
57
+ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
58
+ ```
59
+
60
+ ---
61
+
62
+ ## ⚡ Quickstart
63
+
64
+ ### 1. Run Instantly with `uvx` (No Installation Required)
65
+
66
+ ```bash
67
+ # Log a meal using intuitive shorthand syntax (in dry-run preview)
68
+ uvx --from . nutrilog "38p 18f 54c 580k Tofu Edamame Soba Bowl" --dry-run
69
+
70
+ # View today's summary & daily target progress
71
+ uvx --from . nutrilog today
72
+
73
+ # View command help
74
+ uvx --from . nutrilog --help
75
+ ```
76
+
77
+ ### 2. Install Globally with `uv` or `pip`
78
+
79
+ ```bash
80
+ # Install globally via uv
81
+ uv tool install .
82
+
83
+ # Or via standard pip
84
+ pip install .
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 🏗️ Architecture & Cloud Sync
90
+
91
+ ```mermaid
92
+ graph LR
93
+ User["User Terminal"] --> CLI["nutrilog CLI<br/>(Typer + Rich)"]
94
+ CLI --> Parser["Macro & Shorthand<br/>Regex Parser"]
95
+ CLI --> Auth["OAuth 2.0 Auth Manager<br/>(PKCE / Loopback)"]
96
+ Auth --> Keyring["Local Token Store<br/>(~/.config/nutrilog/tokens.json)"]
97
+ CLI --> Client["Google Health Client<br/>(health.googleapis.com/v4)"]
98
+ Client --> GoogleHealth["Google Health Platform<br/>(Pixel Watch / Fitbit / Mobile App)"]
99
+ ```
100
+
101
+ - **Zero-Friction Logging:** Log any meal in $<2$ seconds directly from your command line.
102
+ - **Hardware & Cloud Sync:** Data writes directly to Google Health API and syncs to your Pixel Watch, Fitbit, and phone dashboard.
103
+ - **Local & Private:** Auth tokens are stored locally on your machine with strict `0600` permissions.
104
+
105
+ ---
106
+
107
+ ## 🚀 Usage & Commands
108
+
109
+ ### 1. Shorthand Meal Logging
110
+
111
+ Macros and calorie tokens can appear anywhere in the string in any order:
112
+
113
+ ```bash
114
+ # Shorthand notation (protein 'p', fat 'f', carbs 'c', calories 'k' or 'cal')
115
+ nutrilog "38p 18f 54c 580k Tofu Edamame Soba Bowl"
116
+
117
+ # Explicit units and labels
118
+ nutrilog "Grilled Salmon protein: 35g, fat: 12g, carbs: 5g, calories: 280, fiber: 2g"
119
+
120
+ # Prefix notation
121
+ nutrilog "p30 f10 c45 390cal Chicken Burrito Bowl"
122
+
123
+ # Automatic calorie calculation if calories are omitted (4*P + 4*C + 9*F)
124
+ nutrilog "30p 40c 10f Oatmeal"
125
+ ```
126
+
127
+ #### Shorthand Syntax Cheat-Sheet
128
+
129
+ | Nutrient | Recognized Formats |
130
+ | :--- | :--- |
131
+ | **Protein** | `38p`, `p38`, `38g protein`, `protein: 38g`, `pro: 38` |
132
+ | **Fat** | `18f`, `f18`, `18g fat`, `fat: 18g`, `total_fat: 18` |
133
+ | **Carbohydrates** | `54c`, `c54`, `54g carbs`, `carbs: 54g`, `carb: 54` |
134
+ | **Calories / Energy**| `580k`, `580cal`, `580kcal`, `cal: 580`, `calories: 580` |
135
+ | **Fiber** | `9fib`, `9g fiber`, `fiber: 9g` |
136
+ | **Sugar** | `5sug`, `5g sugar`, `sugar: 5g` |
137
+ | **Sodium** | `500mg sod`, `sodium: 0.5g` |
138
+
139
+ ---
140
+
141
+ ### 2. Flag-Based Logging
142
+
143
+ ```bash
144
+ # Explicit flags
145
+ nutrilog log "Grilled Barramundi & Veggies" \
146
+ --protein 36 \
147
+ --calories 480 \
148
+ --fat 14 \
149
+ --carbs 12 \
150
+ --meal lunch
151
+
152
+ # Quick macro top-up (e.g. protein shake, snack)
153
+ nutrilog quick --protein 25 --calories 180 --name "Post-Workout Protein Shake"
154
+
155
+ # Dry run (preview payload without sending)
156
+ nutrilog "35p 450k Protein Shake" --dry-run
157
+
158
+ # Output raw JSON payload
159
+ nutrilog "35p 450k Protein Shake" --json
160
+ ```
161
+
162
+ ---
163
+
164
+ ### 3. Reviewing Today's Totals, History & Listing Meals
165
+
166
+ ```bash
167
+ # View today's rollup vs daily targets
168
+ nutrilog today
169
+
170
+ # List recent meals with their Data Point IDs
171
+ nutrilog list --days 3
172
+
173
+ # View past week's meal history
174
+ nutrilog history --days 7 --ids
175
+ ```
176
+
177
+ ---
178
+
179
+ ### 4. Deleting Meals
180
+
181
+ Delete mistakenly logged or duplicate meals using their Data Point ID:
182
+
183
+ ```bash
184
+ # Delete with confirmation prompt
185
+ nutrilog delete <DATA_POINT_ID>
186
+
187
+ # Delete immediately (skip prompt)
188
+ nutrilog delete <DATA_POINT_ID> --yes
189
+ # Or alias
190
+ nutrilog rm <DATA_POINT_ID> -y
191
+ ```
192
+
193
+ ---
194
+
195
+ ### 5. Configuring Daily Nutrition Targets
196
+
197
+ ```bash
198
+ # Display active daily targets
199
+ nutrilog config show
200
+
201
+ # Set custom daily macro and calorie targets
202
+ nutrilog config set --calories 2200 --protein 140 --carbs 220 --fat 65
203
+ ```
204
+
205
+ ---
206
+
207
+ ## 🤖 AI Agent Skill Integration
208
+
209
+ Nutrilog includes a packaged **Agent Skill** (`SKILL.md`) that allows AI coding assistants (Gemini, Claude Code, Cursor, Antigravity) to discover and run Nutrilog commands autonomously.
210
+
211
+ ```bash
212
+ # Check skill status across detected AI tools
213
+ nutrilog skill status
214
+
215
+ # Install into default shared location (~/.agents/skills)
216
+ nutrilog skill install
217
+
218
+ # Install into all detected agent tool directories
219
+ nutrilog skill install --all
220
+
221
+ # Symlink instead of copying (for live package updates)
222
+ nutrilog skill install --all --link
223
+ ```
224
+
225
+ ---
226
+
227
+ ## 🔑 Google Cloud Authentication (`nutrilog auth`)
228
+
229
+ Nutrilog connects directly to the Google Health API using OAuth 2.0.
230
+
231
+ ### Step 1: GCP Project Setup (Free, 1-time)
232
+
233
+ 1. Create or select a project in [Google Cloud Console](https://console.cloud.google.com).
234
+ 2. Enable the **Google Health API** (*APIs & Services $\rightarrow$ Library $\rightarrow$ Google Health API $\rightarrow$ Enable*).
235
+ 3. Under **OAuth consent screen**, select **External**, and add your email to **Test Users**.
236
+ 4. Under **Credentials**, create an **OAuth client ID** of type **Desktop App**, and download the JSON credentials.
237
+
238
+ ### Step 2: Configure & Log In
239
+
240
+ ```bash
241
+ # Option A: Import client_secrets.json file
242
+ nutrilog auth setup --file path/to/client_secrets.json
243
+
244
+ # Option B: Pass credentials via CLI flags
245
+ nutrilog auth setup --client-id "<YOUR_CLIENT_ID>" --client-secret "<YOUR_CLIENT_SECRET>"
246
+
247
+ # Option C: Use environment variables
248
+ export NUTRILOG_CLIENT_ID="<YOUR_CLIENT_ID>"
249
+ export NUTRILOG_CLIENT_SECRET="<YOUR_CLIENT_SECRET>"
250
+
251
+ # Complete browser OAuth login
252
+ nutrilog auth login
253
+
254
+ # Check authentication status & token expiry
255
+ nutrilog auth status
256
+
257
+ # Sign out & clear local tokens
258
+ nutrilog auth logout
259
+ ```
260
+
261
+ ---
262
+
263
+ ## 🧪 Development & Testing
264
+
265
+ Each Python module has a corresponding `_test.py` unit test suite alongside it:
266
+
267
+ ```bash
268
+ # Set up virtual environment and install dependencies
269
+ uv venv
270
+ uv pip install -e ".[dev]"
271
+
272
+ # Run full test suite (57 tests)
273
+ uv run pytest
274
+
275
+ # Run tests with coverage report
276
+ uv run pytest --cov=nutrilog
277
+ ```
278
+
279
+ ---
280
+
281
+ ## 📄 License
282
+ MIT License. See [LICENSE](LICENSE) for details.
nutrilog-0.1.0/PLAN.md ADDED
@@ -0,0 +1,241 @@
1
+ # Nutrilog: End-to-End Implementation & Publishing Plan
2
+
3
+ A standalone, privacy-first CLI tool for logging meals, macronutrients, and calories directly to the **Google Health API (`health.googleapis.com/v4`)** from any terminal, usable with any standard `@gmail.com` or Google Workspace account.
4
+
5
+ ---
6
+
7
+ ## 1. Executive Architecture Overview
8
+
9
+ ```mermaid
10
+ graph LR
11
+ User["User Terminal"] --> CLI["nutrilog CLI<br/>(Click / Typer)"]
12
+ CLI --> Parser["Macro & Timestamp<br/>Parser"]
13
+ CLI --> Auth["OAuth 2.0 Auth Manager<br/>(PKCE / Local Loopback)"]
14
+ Auth --> Keyring["Local Token Store<br/>(~/.config/nutrilog/tokens.json)"]
15
+ CLI --> Client["Google Health Client<br/>(health.googleapis.com/v4)"]
16
+ Client --> GoogleHealth["Google Health Platform<br/>(Google Health App / Pixel Watch / Fitbit)"]
17
+ ```
18
+
19
+ ### Core Goals:
20
+ 1. **Zero-Friction Logging:** Log any meal (cafe, restaurant, home-cooked) in $<2$ seconds via shorthand or natural flags.
21
+ 2. **True Cloud Sync:** Syncs natively with the user's Pixel Watch, Fitbit, and Google Health mobile app.
22
+ 3. **Works Anywhere:** Completely decoupled from internal corporate tooling (`google3`), packaged as a clean open-source Python tool (`pip` / `pipx`).
23
+ 4. **Google Cloud Publishing Path:** Clear roadmap from personal developer mode ("Testing" state) to verified published OAuth app.
24
+
25
+ ---
26
+
27
+ ## 2. Google Cloud & OAuth 2.0 Setup (Prerequisites & Publishing)
28
+
29
+ Because health and nutrition data is categorized under Google's **Sensitive / Restricted Scopes**, Google applies specific verification tiers for OAuth applications.
30
+
31
+ ### Phase 2.1: Google Cloud Project Creation
32
+ 1. Create a project in [Google Cloud Console](https://console.cloud.google.com): `nutrilog-cli-app`.
33
+ 2. Enable the **Google Health API**:
34
+ * Navigate to *APIs & Services > Library*.
35
+ * Search for **Google Health API** and click **Enable**.
36
+
37
+ ### Phase 2.2: OAuth 2.0 Consent Screen Configuration
38
+ 1. **User Type:** Select **External** (allows any `@gmail.com` account to sign in).
39
+ 2. **App Information:**
40
+ * App Name: `Nutrilog CLI`
41
+ * User support email: Developer email.
42
+ * App logo (optional, 120x120px).
43
+ 3. **Scopes Requested:**
44
+ * `https://www.googleapis.com/auth/health.nutrition.writeonly` (Required: write meals, calories, macros)
45
+ * `https://www.googleapis.com/auth/health.nutrition.readonly` (Optional: view meal history)
46
+ 4. **OAuth Client Credentials:**
47
+ * Create Credentials > **OAuth Client ID**.
48
+ * Application Type: **Desktop App**.
49
+ * Name: `Nutrilog Desktop Client`.
50
+ * Download `client_secrets.json`.
51
+
52
+ ---
53
+
54
+ ### Phase 2.3: The Verification & Publishing Roadmap
55
+
56
+ Google enforces specific trust states for OAuth applications accessing Health APIs:
57
+
58
+ ```
59
+ [ State A: Local Developer Mode ]
60
+ │ (Self-use & Test Users)
61
+
62
+ [ State B: Pre-Launch / Test Track ] ──► Up to 100 explicit test Gmail accounts
63
+ │ (Instant access, zero review required)
64
+
65
+ [ State C: Public Production App ] ──► Cloud Verification + CASA Assessment
66
+ (Publicly usable by anyone on the internet)
67
+ ```
68
+
69
+ | Deployment Tier | Who Can Sign In | Requirements | Best For |
70
+ | :--- | :--- | :--- | :--- |
71
+ | **Tier 1: Developer / Testing** *(Fastest)* | You + up to 100 explicitly added test Gmail accounts. | • Add test emails in GCP Console.<br/>• Users see a one-time *"Google hasn't verified this app"* warning screen. | **Immediate personal use, pair programming, beta testers.** |
72
+ | **Tier 2: Publicly Verified App** | Any Google account worldwide without warning dialogs. | • Public domain with verified ownership.<br/>• Privacy Policy & Terms of Service URLs.<br/>• YouTube demo video showing OAuth flow.<br/>• Cloud Application Security Assessment (CASA Tier 2). | **Public PyPI release for widespread distribution.** |
73
+
74
+ > [!TIP]
75
+ > **Recommended Strategy:** Start in **Tier 1 (Testing Mode)** with your personal Gmail added to the Test Users list. This allows full, unrestricted API access within 5 minutes while working towards Tier 2 verification for public PyPI distribution.
76
+
77
+ ---
78
+
79
+ ## 3. Google Health API (v4) Technical Specification
80
+
81
+ ### 3.1 Endpoint Schema
82
+ * **URL:** `POST https://health.googleapis.com/v4/users/me/dataTypes/nutrition-log/dataPoints`
83
+ * **HTTP Method:** `POST`
84
+ * **Headers:**
85
+ ```http
86
+ Authorization: Bearer <ACCESS_TOKEN>
87
+ Content-Type: application/json
88
+ ```
89
+
90
+ ### 3.2 Canonical JSON Request Payload
91
+ ```json
92
+ {
93
+ "nutritionLog": {
94
+ "foodDisplayName": "Tofu & Edamame Soba Bowl",
95
+ "mealType": "LUNCH",
96
+ "interval": {
97
+ "startTime": "2026-08-17T12:30:00Z",
98
+ "endTime": "2026-08-17T13:00:00Z"
99
+ },
100
+ "energy": {
101
+ "kcal": 580
102
+ },
103
+ "totalCarbohydrate": {
104
+ "grams": 54.0
105
+ },
106
+ "totalFat": {
107
+ "grams": 18.0
108
+ },
109
+ "nutrients": [
110
+ {
111
+ "nutrient": "PROTEIN",
112
+ "quantity": {
113
+ "grams": 38.5
114
+ }
115
+ },
116
+ {
117
+ "nutrient": "FIBER",
118
+ "quantity": {
119
+ "grams": 9.0
120
+ }
121
+ },
122
+ {
123
+ "nutrient": "SODIUM",
124
+ "quantity": {
125
+ "grams": 0.650
126
+ }
127
+ }
128
+ ],
129
+ "serving": {
130
+ "amount": 1.0,
131
+ "unit": "bowl"
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### 3.3 Supported Nutrients & Enums
138
+ * **Meal Types:** `MEAL_TYPE_UNSPECIFIED`, `BREAKFAST`, `LUNCH`, `DINNER`, `SNACK`.
139
+ * **Nutrient Enums:** `PROTEIN`, `TOTAL_FAT`, `TOTAL_CARBOHYDRATE`, `FIBER`, `SUGAR`, `SODIUM`, `POTASSIUM`, `CALCIUM`, `IRON`, `SATURATED_FAT`, `CHOLESTEROL`.
140
+
141
+ ---
142
+
143
+ ## 4. Local CLI Implementation Architecture
144
+
145
+ ```
146
+ ~/Sandbox/nutrilog/
147
+ ├── pyproject.toml # Build & dependency metadata (Hatchling / Flit)
148
+ ├── README.md # Quickstart, setup guide & documentation
149
+ ├── nutrilog/
150
+ │ ├── __init__.py
151
+ │ ├── cli.py # CLI command dispatch & argument parsing (Typer/Click)
152
+ │ ├── auth.py # OAuth 2.0 PKCE local loopback flow & token refresh
153
+ │ ├── client.py # Google Health API v4 HTTP client
154
+ │ ├── parser.py # Shorthand & natural language macro parser
155
+ │ ├── storage.py # Local secure token & cache management
156
+ │ └── models.py # Pydantic data schemas for meals & nutrients
157
+ └── tests/
158
+ ├── test_parser.py # Unit tests for shorthand macro syntax
159
+ ├── test_client.py # Mocked HTTP tests for API payloads
160
+ └── test_auth.py # Token refresh & keyring tests
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 5. User Experience & CLI Command Design
166
+
167
+ ### 5.1 Initial Setup (`nutrilog auth`)
168
+ ```bash
169
+ # Authenticate with Google OAuth via browser loopback
170
+ nutrilog auth login
171
+
172
+ # Check authentication status & token expiry
173
+ nutrilog auth status
174
+
175
+ # Discard tokens & sign out
176
+ nutrilog auth logout
177
+ ```
178
+
179
+ ### 5.2 Fast Shorthand Logging (`nutrilog log` / `nutrilog quick`)
180
+ ```bash
181
+ # 1. Shorthand notation (macros + name)
182
+ nutrilog "38p 18f 54c 580k Tofu Edamame Soba Bowl"
183
+
184
+ # 2. Flag-based explicit logging
185
+ nutrilog log "Grilled Barramundi & Veggies" \
186
+ --protein 36 \
187
+ --calories 480 \
188
+ --fat 14 \
189
+ --carbs 12 \
190
+ --meal lunch
191
+
192
+ # 3. Quick calorie/protein top-up
193
+ nutrilog quick --protein 25 --calories 180 --name "Post-workout Protein Shake"
194
+ ```
195
+
196
+ ### 5.3 Meal History & Daily Targets (`nutrilog today` / `nutrilog history`)
197
+ ```bash
198
+ # View today's total logged macros vs daily targets
199
+ nutrilog today
200
+
201
+ # Output:
202
+ # ━━━━━━━━━━━━━━━━ Today's Nutrition Summary (Mon, Aug 17) ━━━━━━━━━━━━━━━━
203
+ # Meals Logged: 2
204
+ # • 12:30 PM [Lunch] Tofu & Edamame Bowl 38.5g P | 580 kcal | 54g C | 18g F
205
+ # • 04:00 PM [Snack] Protein Shake 25.0g P | 180 kcal | 4g C | 2g F
206
+ # ──────────────────────────────────────────────────────────────────────────
207
+ # Daily Total: 63.5g / 120g Protein (53%) | 760 / 2,000 kcal (38%)
208
+ # Remaining: 56.5g Protein | 1,240 kcal
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 6. Detailed Step-by-Step Implementation Roadmap
214
+
215
+ ### Step 1: GCP Project & OAuth Setup
216
+ * [ ] Create GCP Project: `nutrilog-prod`.
217
+ * [ ] Enable `Google Health API` in API Library.
218
+ * [ ] Configure OAuth Consent Screen (External, Test mode).
219
+ * [ ] Add personal Gmail to **Test Users**.
220
+ * [ ] Download Desktop OAuth Client JSON to `~/.config/nutrilog/credentials.json`.
221
+
222
+ ### Step 2: Core Python Engine (`nutrilog/`)
223
+ * [ ] **`auth.py`**: Implement `InstalledAppFlow.run_local_server(port=0)` with automatic token refresh via `google.auth.transport.requests.Request`.
224
+ * [ ] **`storage.py`**: Secure token persistence in `~/.config/nutrilog/tokens.json` with strict `0600` permissions.
225
+ * [ ] **`models.py`**: Define `MealLog`, `NutrientEntry`, and `MacroSummary` dataclasses.
226
+ * [ ] **`parser.py`**: Implement regex parser for shorthand macro strings (e.g. `35p 600k 20f 40c`).
227
+ * [ ] **`client.py`**: Build resilient `GoogleHealthClient` handling retry logic, ISO timestamp formatting, and payload serialization.
228
+
229
+ ### Step 3: CLI Interface & Rich Terminal UI
230
+ * [ ] Build Typer CLI commands in `cli.py` (`login`, `log`, `today`, `history`, `config`).
231
+ * [ ] Format terminal tables and progress bars using `rich`.
232
+
233
+ ### Step 4: Verification & Integration Testing
234
+ * [ ] Run end-to-end integration test: log a test meal from terminal.
235
+ * [ ] Open **Google Health App on phone / Pixel Watch / Fitbit** and confirm live synchronization.
236
+ * [ ] Verify accurate calorie rollup and macronutrient calculation on mobile dashboard.
237
+
238
+ ### Step 5: Packaging & Open-Source Distribution
239
+ * [ ] Configure `pyproject.toml` with entry point `nutrilog = "nutrilog.cli:app"`.
240
+ * [ ] Author comprehensive `README.md` with GCP setup walkthrough and visual examples.
241
+ * [ ] Publish package to PyPI (`pip install nutrilog`).