A daily food and symptom diary for iPhone, built for people trying to work out what is triggering histamine and digestive reactions — and built so that months of entries can be handed to an AI model in one file and actually analysed.
Public domain, no account, no server, no analytics.
Most food diaries are built for calorie counting. Histamine intolerance needs something different:
- Reactions are delayed and cumulative. A symptom on Thursday might come from Tuesday's leftovers, or from four moderate days stacking up. A diary that only shows you one day at a time will never surface that.
- The trigger is often a category, not a food. "Aged things" or "anything fermented" is a more useful finding than "cheddar".
- Hormones move the baseline. Oestrogen peaks around ovulation and is associated with higher histamine and reduced DAO activity; progesterone in the luteal phase tends the other way. The same meal can land differently depending on the week.
- The analysis is the point. Logging is only worth the effort if something reads it afterwards.
So Food Mood logs in plain language, tags what it recognises, tracks the cycle alongside it, and exports the lot as a document written for a language model to read.
Food — Type what you ate in ordinary words. A curated library of ~140 foods and preparation keywords is matched as you type, tagging entries as high histamine, histamine liberator, DAO blocker, high tyramine, fermented, leftovers/aged, high FODMAP or low histamine. Every tag is editable and your raw text is always preserved. Slots for breakfast, lunch, dinner, snack, dessert, naughty treat and drink.
Symptoms — 30 built-in symptoms across skin, respiratory, digestive, systemic and neuro, each rated 0–4. Add your own. Logging an explicit "none" is supported and encouraged: negative data is what separates a pattern from a coincidence.
Fasting — Didn't fast (< 8 h), 12, 16, 20 or 24 hours.
Cycle — Bleeding, follicular, ovulation and luteal. The whole app recolours to the current phase (pushka pink → light pink → light purple → indigo). Phases can be set by hand, or predicted from your last period start and average cycle length — predictions are clearly marked as such, in the UI and in the export. Fully optional.
Body — Sleep, exercise, stress and water. Sleep and exercise auto-fill from Oura when it's connected, with a manual override on each. Stress is kept as two separate fields — felt (self-rated 1–5) and body (Oura's physiological reading) — because they measure different things and the gap between them is often the interesting part.
Supplements — A register you build once by photographing labels. The name and dose are read off the photo on device with Vision; an ingredients shot is worth taking too, since fillers and excipients are a common trigger. Logging is then one tap per day. Each supplement can carry its own daily reminder times.
Food score — Every day gets a 0–10 score on a green-to-red bar, shown on the day and down the History list so a trend is visible at a glance. It's scaled to the person rather than to an absolute threshold: once there are enough days that recorded both food and symptoms and came out clear, the 75th percentile of their tagged-item load becomes the working estimate of what this person tolerates, and that lands at 5/10. Until then it uses a stated default and is labelled provisional. It is a heuristic over self-reported data, and the export says so.
Oura Ring — Optional. Connect with a Personal Access Token to pull readiness, sleep score, sleep duration, HRV, resting heart rate, steps and active calories onto each day. Oura data never overwrites anything you typed.
Insights — In-app trend chart, symptom frequency, per-tag burden comparison and a cycle-phase breakdown, all with sample-size guards so a three-day coincidence isn't dressed up as a finding.
Export — Markdown, JSON or CSV, over 30 days to everything. The Markdown export is the main event: it contains a written brief for the analysing model, a legend explaining every tag, pre-computed summary tables (symptom frequency, burden with vs without each tag, load vs same-day and next-day symptoms, phase and fasting breakdowns), then the full daily log with your original wording intact.
- iOS 17 or later, iPhone only
- Xcode 16 or later to build
- XcodeGen (
brew install xcodegen)
git clone <your-fork-url> foodmood
cd foodmood
xcodegen generate
open FoodMood.xcodeprojFoodMood.xcodeproj is generated and git-ignored — project.yml is the source of
truth. Change the bundle identifier and DEVELOPMENT_TEAM there before running on
a device.
To regenerate the app icon after changing its colours:
python3 Tools/make_icon.pySources/
App/ FoodMoodApp.swift, Navigator.swift
Models/ SwiftData models, enums, symptom catalog, histamine library
Services/ Histamine matcher, export, Oura client, Keychain, settings
Theme/ Cycle-phase palettes and shared chrome
Views/ One file per screen
Tools/ Icon generator
Everything is stored in a SwiftData database inside the app container on your phone. There is no account, no backend, no analytics and no crash reporting.
The only network request the app can make is to api.ouraring.com, and only if
you connect Oura. Your Oura token is stored in the iOS Keychain with
ThisDeviceOnly accessibility, which also keeps it out of device backups.
Exports leave the device only when you share them. Note that pasting an export into a hosted AI service puts that data on their servers under their retention and training policies — worth checking those settings first.
The tags come from published low-histamine food lists, which disagree with each
other more than you would hope. Histamine content varies with freshness, storage,
ripeness and preparation, and individual tolerance varies more still. The library
in Sources/Models/HistamineLibrary.swift is a starting point, deliberately kept
as plain readable data so it can be argued with.
Corrections are welcome — please include a source in the pull request.
Food Mood is a diary, not a diagnosis. Histamine intolerance overlaps with mast cell activation disorders, SIBO, coeliac disease, IBS and true IgE food allergy, several of which need proper medical testing to distinguish. Nothing produced by this app, or by any model analysing its output, is medical advice.
Take the export to a doctor or dietitian rather than starting a restrictive elimination diet on the strength of an app and a chatbot.
If you get swelling of the lips, tongue or throat, difficulty breathing, or feel faint after eating, seek emergency care.
The Unlicense — this software is released into the public domain. See LICENSE.
Copy it, fork it, sell it, ship your own version, strip the credits. No attribution required, no conditions attached. If you improve the food library, a pull request would be welcome, but nothing obliges you to send one back.