Skip to main content

Pantry

Pantry finds and stores food-product nutrition. The local store is permanent; shop prices and availability are live search results and are never cached or written to a product record.

pantry --json search "greek yoghurt"
pantry --json search tofu --source umall
pantry --json search "bega high protein cheese" --source coles
pantry add barcode:9323536800014
pantry add coles:https://www.coles.com.au/product/bega-cheese-tasty-protein-grated-250g-7699284
pantry add woolworths:769526
pantry add usda:2476857
pantry --json lookup coles 7699284
pantry delete manual sourdough

Local search reads the shipped shards and everything previously added. If it does not identify the product, --source makes a live request to one shop and returns current offers with price, currency, pack_grams, price_per_100g, available, url, and a ref.

No shop's search carries a nutrition panel, so live results have null macros and a ref naming where the panel would be. Adding that ref fetches and stores a separate nutrition record; price and availability stay live-result fields and are never copied into it.

A ref is a lead, not a guarantee. coles: and woolworths: refs address the shop's own page and resolve as reliably as the shop is reachable. A barcode:<barcode> ref names a code the retailer printed, which Open Food Facts may or may not hold: of the ten external GTINs one Umall search produced on 2026-08-30, nine were unknown there. pantry add says so and stops.

  • --source coles is a plain request, about 0.5s. The results page is server-rendered, so nothing here needs a browser. It spends one of the four or five page loads Coles serves in a burst, so one query is one request. The result's ref is coles:<url>.
  • --source umall is a plain request, about 0.6s. Where a product publishes an external barcode the result's ref is barcode:<barcode>.
  • --source woolworths needs a browser and opens a visible window: the results page carries no products, and the request behind it is refused for anything that is not a browser, headless included. Install it with uv tool install 'mealtime-pantry[browser]'. About 4s to start, then 2-6s a query in the same run. The result's ref is woolworths:<stockcode>, and its barcode is the GTIN the page prints.

Coles and Woolworths results keep the shop's own order and carry no match. Their relevance engines know their catalogues and their shoppers' words — asked for "shredded cheese" they answer with the grated ones — and rescoring that on shared words dropped right answers and marked others weak.

Umall is the exception, and it is ranked here. Its endpoint is a suggest index, not a relevance engine: measured, "shredded cheese" returns one cheese followed by taro strips, lychees and scallops. So those results are ranked and filtered like the store's, and they do carry a match.

Records and matching

Every nutrient describes the record's grams, always present and 100 unless --grams N on search or lookup asks for another weight. pack_grams is a live offer's package size and never changes that nutrition basis. A per-100 mL panel is read as per 100 g and says so in basis_note.

An item is a flat record in the shared item format. Reading follows that format's rule and ignores a key it does not define, so a store written by a newer Pantry still opens here; writing drops what this version cannot express. What a record may contain on the way in stays closed, because sodum would store cleanly and hide the sodium forever. Energy is kcal; every other nutrient is grams. Kilojoules are converted when a panel is read, so no stored record has a kj field. Unknown nutrients are null; zero is returned only when the source explicitly reported zero.

A ranked result carries match — every store result, and every Umall result:

  • score is 0 to 1 and states how much of the query the name accounted for.
  • tier is the source kind: verified, composition, crowdsourced, retail, or unknown for a price-only shop result.

Below 0.7 the human output marks a result ~weak. That is the cue to try a live shop rather than silently accepting the local answer. A cooked or water-diluted panel never outranks a dry record. Regional spellings are one food, not two: shredded/grated, prawn/shrimp, yoghurt/yogurt.

--sort protein-per-kcal can reorder nutrient-bearing results. A result that lacks a required figure sorts last rather than being treated as zero.

Adding and maintaining records

pantry add REF accepts these forms:

  • coles:<product-url>
  • woolworths:<stockcode>
  • barcode:<barcode>
  • usda:<fdcId>

A GTIN is printed on the pack rather than owned by any one database, so the prefix names the code. Open Food Facts is currently the only provider that can resolve one.

Bare Coles and Woolworths product URLs remain accepted. A held record is not fetched again unless --refresh is explicit. Retailer requests are limited and paced; a block stops the run, with no retry, proxy rotation, or CAPTCHA handling.

Manual input is one flat JSON object. Its figures are restated to 100 g before storage, and the record carries entered: true, shown as ~entered. That flag exists because a panel typed in under a retailer's id and url is otherwise indistinguishable from one the tool fetched, and a blocked shop is exactly when someone is tempted to type one:

printf '%s\n' '{"grams":90,"kcal":335,"protein":45.6,"fat":7.9,"carbs":4.9}' |
  pantry add --input - --id sourdough --name Sourdough

pantry lookup SOURCE ID reads one exact local record without a network request. pantry delete SOURCE ID removes only a record from the user's own store. Shipped shard rows cannot be deleted; removing a user correction makes the shipped row it shadowed visible again.

No command writes package data. Acquired records go to $XDG_CONFIG_HOME/pantry or ~/.config/pantry.

Development

uv run pytest -q
uv run --project importers/afcd pytest -q importers/afcd/tests
readability check src --fix

Release files for mealtime-pantry 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mealtime-pantry 0.5.1
File Size Uploaded
mealtime_pantry-0.5.1.tar.gz 154.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mealtime-pantry 0.5.1
File Interpreter ABI Platform
mealtime_pantry-0.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 312.3 kB

Release files / mealtime_pantry-0.5.1.tar.gz

Download URL mealtime_pantry-0.5.1.tar.gz
Size 154.7 kB
Tags Source
SHA-256 checksum
How to use checksums
75356add19c112c36b98b3c3edc4c9e7ef093b7081d0896c303d7a9310cf7a1a
BLAKE2b-256 checksum
How to use checksums
025aefb9ee7d6d842c51f3d8c1ae0ae85a192c34aa2d78b9789f11214aa293c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release files / mealtime_pantry-0.5.1-py3-none-any.whl

Download URL mealtime_pantry-0.5.1-py3-none-any.whl
Size 157.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f17cef43addbc5d57a3c34dde5ca72f05038657bfd508b8d2ac074589ae0f882
BLAKE2b-256 checksum
How to use checksums
21c6e8d48daf1d6bf96bf6103c97c5ad3e642218408d3aee6e0d8377f1510812
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page