Skip to main content

nemlai

CLI and Python SDK for automated grocery replenishment on Nemlig.com — Denmark's largest online grocery delivery service.

NemlAI predicts what groceries you'll need next based on your order history, then builds ready-to-checkout basket links. Especially useful for OpenClaw and other AI agents that interact with the NemlAI platform.

Platform: nemlai.milops.org

Install

pip install nemlai

On Arch Linux:

yay -S nemlai

On Ubuntu:

sudo add-apt-repository ppa:milops/nemlai
sudo apt install nemlai

Quick start

# Log in to your NemlAI instance
nemlai login

# Interactive mode
nemlai

# Run a single command
nemlai predict
nemlai search "mælk"
nemlai basket

Python SDK

from nemlai import NemlAI

client = NemlAI.login("you@example.com", "password")  # or NemlAI(token="...")

basket = client.basket.generate(size="medium")       # predicts, polls, returns JSON
for item in client.basket.items()["items"]:
    print(item["name"], item["quantity"], item["explanation"])
client.basket.adjust("5001234", 2)                    # by product_number
client.basket.compare()                               # price the basket at every enabled shop
client.basket.send()                                  # returns basket_url

Basket methods return JSON by default since 0.10.0 (remove/adjust take a product_number). Pass structured=False for the old text replies.

Resource Methods
client.basket generate, items, add, add_batch, remove, adjust, send, search, categories, why, dish, status; other shops: shops, shop_prices, alternatives, choose, unchoose, choices, send_to_shop, compare
client.exclusions list, items(order_id), exclude_order, include_order, hide_lines(order_id, product), unhide_lines, set
client.shops status, link(email, password, shops=["bilka", "foetex"]), refresh(shop_id)
client.settings show, update(order_cutoff_date=..., auto_learn_from_purchases=...)
client.preferences get, update(prefer_eco=True, exclude_products=[...]), recalculate
client.orders refresh(password), fetch_status
client.household info, members
client.analytics see below
client whoami, export_data, feedback, command(text)

The basket at other shops

The same basket priced at Bilka, Netto, Føtex and REMA 1000 (the shop tabs on /kurv). Where a shop has no validated match you get a suggestion (status: "suggestion", with differs), and you can pick another product for this basket only:

prices = client.basket.shop_prices()                 # every shop tab, current basket
for shop in prices["shops"]:
    print(shop["name"], shop["total"], shop["counts"])

milk = client.basket.items()["items"][0]
alts = client.basket.alternatives("netto", canonical_id=milk["canonical_id"], quantity=milk["quantity"])
client.basket.choose(milk["product_number"], "netto", alts["items"][0]["product_number"])
client.basket.shop_prices(shops=["netto"])           # the pick comes back as status "chosen"

client.basket.send_to_shop("bilkatogo")              # your own BilkaToGo cart; never checks out

Picks are never stored on the server and are dropped by generate(). send_to_shop only works for shops whose send_mode is basket_push in client.basket.shops() (today BilkaToGo, after nemlai shops link).

nemlai basket prices                              # totals per shop
nemlai basket prices --shop netto                 # every line at Netto
nemlai basket alternatives 3 --shop netto         # or --search "rugbrød"
nemlai basket choose 3 --shop netto --product 123456
nemlai basket send-shop bilkatogo

Picks made in the CLI are kept in ~/.config/nemlai/basket_picks.json until the next basket generate.

Exclusions and other shops

Leave orders or single products out of predictions and analytics, and link Bilka/Føtex so their receipts count too:

nemlai exclusions list
nemlai exclusions items 4211
nemlai exclusions exclude 4211          # whole order
nemlai exclusions hide 4211 5001234     # one product in that order
nemlai shops status
nemlai shops link --email you@example.com --shops bilka,foetex   # prompts for the password
nemlai shops refresh bilka
nemlai settings update --cutoff 2026-01-01 --auto-learn true

Spending analytics

Ask where the grocery money went: from the CLI (nemlai analytics guide for the full reference) or from Python.

nemlai analytics overview --last this-month
nemlai analytics spend --product mælk --category Mejeri --last 12m --compare previous-period
nemlai analytics top categories --level sub --from 2026-01-01 --to 2026-03-31
nemlai analytics trend --bucket month --last 12m
nemlai analytics drill --order 0042
nemlai analytics receipts --product jordbær --last 3m --detail full --save
nemlai analytics categories-tree --last 12m

Tables are rendered by the SDK (canonical product variants, comparison changes, saved amounts, truncation notices); --format json|csv|markdown returns the server's own output.

from nemlai import NemlAI, AnalyticsError

client = NemlAI(token="your-token")
overview = client.analytics.overview(last="3m")
print(overview.spend.total, overview.spend.saved, overview.spend.comparison)

milk = client.analytics.spend(product="mælk", compare="previous-period")
for match in milk.matches:
    print(match.name, match.total, match.product_numbers)

try:
    client.analytics.trend("fortnight")
except AnalyticsError as err:
    print(err.status_code, err.message, err.hint)

Methods: overview, spend, top, trend, drill, receipts, categories_tree (typed dataclass results), plus text(endpoint, payload, format="csv") for server-rendered output.

What it does

  • Fetches order history from Nemlig.com
  • Uses a cloud ML model trained on your purchase patterns
  • Predicts quantities for your next basket
  • Builds Nemlig basket URLs you can review and checkout
  • Supports manual item search and hybrid baskets (manual + ML)

For agents

NemlAI has an MCP server for AI agents (Claude, ChatGPT, Codex, Grok, Hermes, OpenClaw and others) at https://nemlai.milops.org/mcp, and a nemlai skill that teaches them the workflows. Sign in with OAuth where the client supports it, or with the token from nemlai login (stored in ~/.config/nemlai/token).

Connect in one minute

export NEMLAI_TOKEN=$(cat ~/.config/nemlai/token)   # the configs read the token from here
nemlai mcp install claude-code    # or: codex, hermes, openclaw
nemlai mcp doctor                 # checks the URL, the token (whoami) and the tool list
  • nemlai mcp install <client> writes the client's MCP config and installs the skill. It backs up the file first, never changes other entries, and replaces an existing nemlai entry only with --force. --dry-run shows the diff; --embed-token writes the token itself instead of ${NEMLAI_TOKEN}.
  • nemlai mcp config <client> prints the config instead (claude-code, codex, hermes, openclaw, claude-desktop, generic).
  • claude.ai, Claude Desktop, ChatGPT and Grok: add a custom connector with the URL and sign in (OAuth, Giv adgang).

The server explains itself: its instructions and the nemlai_guide tool cover the data model, the rules (show the basket and total before sending, send only on the user's go-ahead, NemlAI never checks out, never put a password in chat) and the workflows.

When MCP fails, this CLI is the fallback. Every MCP tool has a CLI command, and --json prints one JSON object per command:

nemlai --json whoami
nemlai --json basket items
nemlai --json analytics spend --last 30d

If the CLI fails too, the web app at https://nemlai.milops.org has every feature. The full map (every tool's CLI command and web page), the rules and the workflows: https://nemlai.milops.org/agents.

License

MIT

Metadata

Release files for nemlai 0.11.0

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

Source distribution (sdist)

Source distribution for nemlai 0.11.0
File Size Uploaded Provenance Actions
nemlai-0.11.0.tar.gz 92.7 kB Without provenance Details for nemlai-0.11.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for nemlai 0.11.0
File Interpreter ABI Platform Actions
nemlai-0.11.0-py3-none-any.whl Python 3 none any Details for nemlai-0.11.0-py3-none-any.whl

Total release size: 206.5 kB

Release files / nemlai-0.11.0.tar.gz

Download URL nemlai-0.11.0.tar.gz
Size 92.7 kB
Tags Source
SHA-256 checksum
How to use checksums
8553077a8e53c611e0bfeb09b231886d5218d898357d1b90e16f2b9ce211b5a8
BLAKE2b-256 checksum
How to use checksums
30b499295d52e07ecf4be88a2097379cb47ea42ffb0bcb671896b25f884b104b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.18

Release files / nemlai-0.11.0-py3-none-any.whl

Download URL nemlai-0.11.0-py3-none-any.whl
Size 113.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2cd4a23b5f77118763d27298825c263e92087a51a2d744707ee36519c65fc3bc
BLAKE2b-256 checksum
How to use checksums
a54db0a3558e0f53e671f3a65fd7947039f0a05797bcd578f2564d47629b7a6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.18

Security for nemlai 0.11.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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