Skip to content

Repository files navigation

Trophe

A local nutrition journal for people and their agents.

Trophe comes from Ancient Greek τροφή (trophē): nourishment or food. Dictionary source.

Tell your agent what you ate, show it a label or meal photo, or ask how your week looks. The agent interprets the request. Trophe stores the evidence, checks the records, and does the arithmetic.

Design

your agent ── CLI or MCP ── validated actions ── Markdown files
     │
     └── its own vision and web tools, when needed
  • Markdown with YAML front matter is the source of truth: profile, saved foods, meal logs, assumptions, and notes.
  • One TypeScript core handles validation, serving calculations, and date totals.
  • No account, application server, built-in model, API key, or database service.
  • The CLI and MCP server expose the same operations and input schemas.
  • Food edits do not alter past meals. Each logged item stores a nutrition snapshot.
  • Estimates stay marked as estimates. Missing nutrients stay null.

There is no SQLite layer in this first version. A personal journal is small enough to read directly. If indexing becomes useful, it can be rebuilt from the files.

Start

Requires Bun 1.3.13 or newer.

bun install

# Default data location: ~/.trophe
bun run trophe init --timezone America/Toronto
bun run trophe food put --input examples/food.json
bun run trophe meal log --input examples/meal.json
bun run trophe day 2026-09-21
bun run trophe validate

The examples are fictional. They are added only when you run these commands. To use a separate example journal, add --data ./data to every command. TROPHE_HOME can also set a fixed data directory. An absolute path is best in agent configuration. Opening a missing journal fails; only init creates one.

The executable is bun /absolute/path/to/trophe/src/cli.ts. bun run trophe is a repository shortcut. Command results are JSON, or raw NDJSON for NDJSON exports. Errors go to stderr.

Commands

CLI MCP tool Purpose
init --timezone <zone> init_journal Create an empty journal
profile get get_profile Read timezone, targets, and notes
profile set --input <file> set_profile Update the profile with its revision
food list --query <text> search_foods Find reusable foods
food get <id> get_food Read a food and its revision
food put --input <file> put_food Create or update a food
meal log --input <file> log_meal Record portions and evidence
meal get <id> get_meal Read a meal and its revision
meal update --input <file> update_meal Correct or void a meal
meal list --from <date> --to <date> list_meals Read a date range, including void records
day <date> / summary --from <date> --to <date> summarize Calculate active meal totals
export ndjson export_ndjson Export all native records, one JSON object per line
export fhir5 --patient-id <id> export_fhir Export meal history as a FHIR R5 Bundle or NDJSON
validate validate_journal Check all records

Use tools to print all tool argument schemas. schema prints the stored record schemas. call <tool> --json '{...}' invokes any shared action directly. --input - reads JSON from stdin. JSON input files contain the full tool arguments: for example, { "meal": { ... } }.

Native NDJSON export

bun run trophe export ndjson > journal.ndjson

This exports the profile, all saved foods, and all meals, including void records. Each line is one complete native record with schema_version, kind, and notes. Targets, evidence, unknown values (null), and known zero values are preserved. There is no outer array or revision envelope. The MCP tool export_ndjson takes no arguments and returns the same raw text.

The export reads the whole journal; it has no date filter. Attachment references in notes are included, but attachment files are not. See SCHEMA.md for ordering and format details. Markdown remains the source of truth.

FHIR export

# Export all logged meals. Supply the ID for the journal's subject.
bun run trophe export fhir5 --patient-id example-person > nutrition.fhir.json

# Optional inclusive dates use the journal's configured timezone.
bun run trophe export fhir5 --patient-id example-person \
  --from 2026-09-01 --to 2026-09-30 > september.fhir.json

# FHIR NDJSON uses one resource type per file.
bun run trophe export fhir5 --patient-id example-person \
  --format ndjson --resource-type Patient > Patient.ndjson
bun run trophe export fhir5 --patient-id example-person \
  --format ndjson --resource-type NutritionIntake > NutritionIntake.ndjson

The default output is a native FHIR R5 Bundle of type collection: a minimal Patient and one NutritionIntake per logged meal. Each intake contains NutritionProduct snapshots with the consumed portions, nutrition values, sources, and assumptions. Voided meals are included with status: entered-in-error. Export only reads local records; it does not upload data or require a FHIR server.

With --format ndjson, the output is one FHIR resource per line. Select Patient or NutritionIntake with --resource-type. The same MCP tool accepts "format": "ndjson" and "resource_type": "Patient" or "NutritionIntake".

Use a stable patient ID that you choose for this journal. Trophe does not infer demographics or match the subject to an external patient record. The export covers meal history; unused saved foods and profile targets are not included. See FHIR.md for mappings, units, identity, and export limits, and examples/fhir-bundle.json for a fictional example.

Agent setup

Give your agent SKILL.md and the absolute command and data paths. Agents with shell access can use the CLI. Agents with MCP support can use:

{
  "mcpServers": {
    "trophe": {
      "command": "bun",
      "args": [
        "/absolute/path/to/trophe/src/cli.ts",
        "mcp",
        "--data",
        "/absolute/path/to/your/nutrition-journal"
      ]
    }
  }
}

The server uses stdio. It opens no network port. It exposes the guide as trophe://guide, the schema explanation as trophe://schema-guide, and generated JSON Schemas as trophe://schemas. The FHIR export guide is trophe://fhir-guide.

Photo interpretation and online food lookup use the host agent's capabilities. Trophe itself does not call a model or nutrition provider. An agent can save photo references and source links in the Markdown notes, with files in attachments/. Using an external agent or web tool can share the information you give it; local storage does not make those external services local.

Data you can read

~/.trophe/
├── profile.md
├── foods/
│   └── example-yogurt.md
├── journal/
│   └── 2026-09-21-breakfast.md
└── attachments/

Read SCHEMA.md for the record format and examples/meal.md for a full meal record. You can edit Markdown directly; run validate afterward. Stop concurrent tools before manual edits. Back up the whole data directory with your preferred file backup tool. Personal data is separate from the code and is not pushed by this repository.

Tool writes use an exclusive directory lock and an atomic file replacement. Updates require the SHA-256 revision returned by a read. This prevents one tool from overwriting another tool's edits. Repeating an identical write is safe. A changed payload with an existing ID fails until an explicit update is made.

If a process crashes while holding .write-lock, stop all Trophe writers and remove that empty lock directory before retrying. The lock protects cooperating Trophe processes; external editors must not write concurrently. Records are current state, not a full revision archive. Backups preserve older versions.

Totals and targets

The profile timezone determines the day for a timestamp, including daylight saving time. Targets have effective dates. A report uses the target in effect on each day. Changing the profile timezone regroups historical timestamps into that timezone.

Each nutrient reports a known subtotal, unknown_items, and whether the value is complete for the logged items. This does not mean every meal was logged. remaining is null if a nutrient is unknown or no target exists. An empty day has logged: false; it is not treated as a confirmed fast. Estimates are counted separately. Voided meals remain readable but are excluded from totals.

Development

bun run check
bun test

The tests cover persisted records, duplicate retries, serving calculations, corrections, unknown values, local dates, malformed files, CLI behavior, and real MCP client/server calls. See AGENTS.md for development conventions.

This initial version covers saved foods, meal logging, dated targets, and daily or period summaries. Recipes can be saved as foods with known per-serving values. Automatic recipe calculation, barcode lookup, body measurements, synchronization, and a graphical interface are outside the initial scope.

License

MIT. Copyright (c) 2026 Flexpa.

About

A local nutrition journal for people and their agents. Markdown records, shared CLI and MCP tools.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages