Morpheus — Product Spec

A diet companion in iMessage that remembers what you eat, tells you what to order, and watches you change. The ideal product.

7 min

2026-06-17 · updated 2026-06-18 · companion to DESIGN.md · v0 = single-user dogfood

Status — v0 is built and dogfooding. Conversation, onboarding, the mirror, food + nutrition lookup, the memory graph, suggestions, and continuous Find My location are all implemented and tested. The Apple-Shortcut geofence was dropped — Morpheus now reads the phone's shared location directly off the Mac mini. The pills below reflect current state.

Thesis

Dieting fails on accountability and what goes unspoken, not on tracking. Tracking is a solved commodity that leaves you alone with a passive log. Morpheus is the relationship: it remembers what you eat, tells you what to order when you ask, and watches how you look week-to-week — and that alone bends the curve.

Onboarding built

A short, casual Q&A — one question at a time — then it wires up tracking and confirms it can see you. No forms.

morpheuslast thing, share your location with me in find my (share indefinitely) so i can keep an eye on you. lmk when
youdone
morpheusok yeah, i can see you're in fremont. good, we're set

What Coach does built

One job, done well — and nothing else.

The daily ritual

The whole product is one small, repeatable habit — it survives because it takes ten seconds and someone's waiting for it.

you[photo] morning check-in
morpheusleaner than monday fr 🔥 shoulders popping more — keep doing whatever u did this week
you[photo] lunch
morpheusdouble-double + fries… that's like 1100 my guy 😭 logged it. lets keep dinner light yeah

The mirror — visual progress hero · built

Send Morpheus a photo of yourself; it judges this one against last time and tells you whether you progressed. The scale becomes optional — the camera is the instrument.

you[photo] week 3 check-in
morpheuscomparing to 2 weeks ago… midsection is noticeably down 📉 this is real, not water
morpheusfunny thing — ur weight barely moved. see why we don't trust the scale 💀

How it works: the inbound photo is classified (body / food / other); a body shot is sent to the model alongside your last couple of check-in photos so it reads the delta, then writes the verdict to the timeline. Photos stay on the self-hosted Mac mini as local file refs (HEIC→JPEG via sips) — sent to the model for the read, never to a third-party app.

Ask it what to eat main value prop · built

The core loop: Morpheus remembers what you actually like, so when you're hungry it doesn't hand you a meal plan — it suggests something you'd genuinely eat that still fits your goal.

youim hungry, what should i eat
morpheusur ~600 under for the day and light on protein
morpheusdo the chicken bowl u liked sunday — quick, ~500, 45g protein 🔥
youeh im feeling korean
morpheussay less — bibimbap, extra veggies, lean beef, easy on the sauce. high protein + ~550, fits clean

Location callouts & restaurant memory built · Find My

Morpheus watches where you are and texts first when you've parked somewhere you shouldn't — and because it has learned your spots, it names your usual order. No app, no Apple Shortcut: it reads the location you share over Find My, continuously.

morpheuswhy are we at mcdonald's. we were doing good
youlol busted
morpheusif you're eating, grilled chicken sandwich, skip the fries

Mechanism: the phone shares location over Find My; findmylocateagent's encrypted SQLite is decrypted on the Mac mini (Apple's AES-256 page codec, 32-byte key grabbed once via lldb), the live coordinate read from the WAL, dwell-checked, then matched to a saved restaurant or reverse-geocoded (OpenStreetMap). The old Apple-Shortcut geofence + HTTP endpoint were removed.

Nutrition lookup built

You never count. Morpheus figures out the numbers — from the web, the photo, or what it already knows.

PathHow it works
Search lookupNamed items ("Big Mac", a restaurant entrée) → server-side web search for published nutrition facts → use real numbers, cache onto the dish record.
Portion estimateFrom a meal photo, estimate serving size and flag outliers ("easily two servings"). A rough baseline beats no log.
RememberedUsual orders are cached — no lookup, no describing. "Same as usual?" → "yes" → logged with your number.
Calories are a fuzzy input, not the truth. Morpheus keeps them consistent so trends mean something, then calibrates against the real ground truth: how your body changes.

Memory model built

The store grew from a thin profile keyed by handle into a lightweight graph — records that reference each other by id (no database until it earns one). It now holds restaurants, usual orders, dishes, the daily meal log, and the body-photo timeline, plus the linked Find My sharer id per user.

EntityHolds
usergoal, restrictions, baseline, tone, cal/protein targets, linked findMyId
restaurantsgeo / radius, visit count, usual orders, danger level
disheslearned cal/macro estimate, source (search vs. estimate), confidence
mealsdaily log entries — photo ref, estimate, portion note, restaurant link
checkinsbody-photo timeline — observations + verdict
weightoptional — one signal, not required
user {
  profile:  { goal, restrictions, baseline, tone }
  patterns: [ "late-night burritos on weekends", ... ]
  restaurants: { "chipotle-mission": {
    geo:{lat,lng}, dangerLevel:"high", visits:14,
    usualOrders:[ { dish:"carnitas-bowl", freq:11, calEst:900 } ] } }
  dishes: { "carnitas-bowl": {
    calEst:900, macros:{p,c,f}, source:"search→photos", confidence:0.8 } }
  meals: { "2026-06-17": [ { time, slot, dish, calEst, photo,
    portion:"large", restaurant:"chipotle-mission" } ] }
  checkins: [ { date, photo, observations:["waist tighter"],
    verdict:"progress", comparedTo:"2026-06-03" } ]
  weight?: { "2026-06-17": 174 }   // optional
}

Photos stored as local file refs on the Mac mini, not blobs in the JSON.

A day

TimeWhat happens
8:10Mirror pic → compared to last week → "leaner, keep going" → observation filed.
9:00Breakfast nudge (scheduled) → you snap a plate → logged rough.
12:51Lunch photo → search the numbers → flag the portion → keep dinner light.
16:30"what should I eat?" → suggests a meal you like that fits the day's remaining calories + protein.
19:38Find My shows you parked at Chipotle → names your usual → "yes" logs it → offers the swap.
21:30Evening recap → connects the look to the eating → "proud of u 🤝".

Architecture

Forked from a self-hosted iMessage agent stack. Transport and the agent loop were already proven; the net-new work — vision, the memory graph, nutrition lookup, and continuous location — is now built.

ComponentStatusNotes
iMessage transportdonehelper dylib (send/typing/read) + chat.db poller (now surfaces photo attachments)
Agent loopdoneagent.mjs — tool loop, human cadence, multi-bubble, inbound photo routing
Persona + boundarydoneprompt.mjs — gen-z tough-love, calibrate-on-body, strict in-character domain refusal
Toolsdonesave_profile · log_meal · log_weight · log_checkin · lookup_nutrition · remember_restaurant · remember_order · confirm_order · claim_location
Store (graph)doneper-handle JSON graph: restaurants / dishes / meals / checkins + geo helpers
Schedulerdonemeal + weigh-in nudges; mirror folded into the weigh-in; suggestion-aware
Vision: bodydonevision.mjs classify → compare vs. recent check-ins → log_checkin
Vision: fooddoneportion + nutrition lookup → log_meal w/ photo ref (HEIC→JPEG via sips)
Find My locationdonedecrypt findmylocateagent DB → live coord → dwell → callout (replaces the Shortcut)
Venue detectiondonegeocode.mjs — OSM reverse-geocode; fast-food / brand danger detection + city for onboarding
Nutrition lookupdonenutrition.mjs — server-side web search, cached on the dish record
Suggestion enginedonein-persona reasoning over remaining cal/protein + learned preferences

The inbound photo router

inbound msg text or photo classify text only agent turn body compare vs. last → log_checkin food portion + search → log_meal react + store file ref on record
Built: the chat-poller now surfaces attachments; the agent classifies (body / food) and routes — HEIC→JPEG via sips.

Build order

Ship the relationship first — if the conversation isn't good, no camera or location trick saves it. All five v0 steps are now in.

#StepStatus
1Talk like a person. Onboarding + one real back-and-forth that genuinely feels good. Make-or-break.done
2The mirror. Body photo → vision compare vs. last → observation + verdict → react. The headline.done
3Meal photos + search. Food photo → portion + web lookup → log w/ photo. The "huge portion 💀" callout.done
4Memory + suggestions. Store grown into restaurants / dishes / meals / checkins + learned preferences, so it answers "what should I eat?" with meals you like that fit the goal.done
5Location. Continuous Find My location → dwell + venue detection → callout that names the remembered order. (Replaced the Apple Shortcut.)done

Open questions