skip to content
stevengates.io
back to home
case study·secondary·since 2026

LoseIt CLI

Nutrition data out of Lose It!, no official API.

visit live publicGoCLIReverse EngineeringAgent Tooling

the project

LoseIt CLI pulls your nutrition data out of Lose It! and emits standardized per-day nutrition JSON — calories and macros, ready for an agent or script to reason over. It does one thing and stays dumb on purpose: extraction only, no storage, no interpretation. What the numbers meanis the consumer's job.

The catch: Lose It! has no public API. This is the tool that gets the data out anyway — shipped as a static Go binary and an OpenClaw / ClawHub skill.

the hard problem: no official API

There is no documented endpoint to call. So the work was reverse-engineering the real ones: the OAuth password-grant login (api.loseit.com/account/login) and the private data-export endpoint (loseit.com/export/data) — and discovering that the web form's reCAPTCHA isn't actually enforced on the API itself, so a clean authenticated POST works.

That makes the integration inherently fragile — a Lose It! change can break it overnight. The repo treats that as a known operating condition: endpoints are compiled-in constants (not overridable at runtime), and a “When auth breaks” playbook is written down in advance — check for a new captcha, renamed cookies, moved endpoints — so recovery is a known procedure, not a forensic dig.

the engineering

  • Self-healing session cache. Tokens expire roughly every 14 days. Rather than make you re-login, the tool detects the expiry, re-authenticates from stored credentials, and retries — no human in the loop. The cached token is written owner-only (0600).
  • Credential safety as a hard rule.Login and export requests assert they're going to a first-party host (*.loseit.com, HTTPS) so a hostile env var or config file can't redirect credentials elsewhere. Secrets are gitignored and never printed.
  • Data minimization by design. The Lose It! export ZIP also contains bodyweight, exercise, steps, and photos. The tool reads onlythe two nutrition CSVs and discards the rest in memory — enforced as a regression test. Widening that scope would require a separate, security-reviewed, opt-in change; it's never on by default.
  • Go 1.24 + cobra, single static binary, cross-compiled to GitHub Releases and auto-published to ClawHub on skill-doc changes.

lessons learned

Mocks lie; the live endpoint is the source of truth.Because the API is undocumented and reverse-engineered, the repo mandates a real end-to-end test against the actual Lose It! service — with real credentials — before any PR is opened. A green mock proves nothing when the thing you're integrating with can change its login form without telling you. The other rule is restraint: the tool deliberately owns no business logic, which keeps its attack surface and its maintenance burden small.

what this demonstrates

  • Pragmatic integration against a hostile surface— getting useful data out of a closed system, cleanly, without pretending it's stable.
  • Security and privacy treated as invariants — first-party assertions, minimization-as-a-test, secrets handled correctly.
  • Honest operations. The failure modes are documented before they happen, because fragile dependencies are a fact, not a surprise.