How I manage my shopping lists with Org Mode
And on the terminal these words appear:
"My name is Orgzlymandias, King of Kings:
Look on my notes, ye Mighty, and despair!"Why I went into this rabbit hole
Shopping lists are a nightmare. They are a necessary evil you must deal with every week in order to survive. They are required for the daunting task of shopping that repeats itself every few days. Supermarkets are a mess by design, as they'd rather you get lost and find more items so you consider buying them than finish your shopping tasks quickly. In fact, they are a space so detached from the production process that it feels alien to see all the products arranged on shelves, decontextualised. Local shops have better products and an ethical argument for preferring them, but less variety.
What I mean to say is that I'm not a fan of shopping by any means, so I'm not a fan of shopping lists either. Add to that the fact that my ADHD brain will work overtime to prevent me from sitting down and filling the list and then will do its best to forget what kind of yoghurt I've been buying the last five years. When I say that I have found a system that works, I mean that it works for a person who finds this task most excruciating, so it will probably work for you as well.
My requirements
In order to satisfy my shopping list needs, my system MUST be able to handle the following scenarios with a consistent interface:
- Multiple items are available in multiple shops.
- Once an item is bought at a shop there's no need to buy it at others.
- There are items I don't need to buy some days and don't want to know about.
- Supermarkets tend to retire, add, and change the packaging of products.
- I want to optimise my route around supermarkets, as I don't want to spend a single second more than is necessary inside.
- Still, I'll refuse to go through self-checkout, as I won't optimise the wages out of my fellow proletarians.
- I tend to forget what exactly I'm looking for, so I need clues to find some items.
- Unless I note that I need to buy an item once I find the need, I'll forget it.
These requirements are perfectly reasonable, but they're hard to find together in a single system.
I've tried using a notebook, which is great for single-use lists, but descriptions are unsorted, insert-only, and separate from the actual list. Obsidian worked kind of well for some time, but I never found a good plugin to sort the lists by status (bought or not), sections usually had lots of repeated items, and descriptions were still separate from the items. I think that Obsidian's Bases may be up to the task nowadays, but when I tried it the closest I found was Dataview and, as great as it is, it wasn't enough for my needs. On top of that, it's a proprietary system even though the underlying Markdown file system does broadly respect your user freedoms.
As for fully proprietary solutions, Google Keep was too simple and Notion requires that I be connected to the internet to read a glorified plain-text file, so that's a no go. I've considered (and actually tried) writing my own Android app to do this, but damn does Google make it miserable to write and maintain something for their system. I have the biggest admiration for the force of will Android developers have to write their programs!
All this exposed, let's look at how I write my shopping lists.
It all starts with a notebook
If you don't want to use a text editor on your computer for this task, skim through this section for some basics and I'll introduce an Android app right after.
First of all, I don't use Emacs. Surprise!
Instead, I use Neovim's orgmode plugin, which is more than enough for my current needs.
Check out my Org config at the time of writing if you want to replicate my setup.
Still, everything should be 1:1 translatable to an Emacs-based environment.
In my Org workspace, I have a file called Shopping.org which contains an unsorted list of all items I want to buy or have ever bought.
This file is unsorted because it acts as my database for all items.
Every item is a note with a heading level of 1, a TODO or DONE status and a list of tags for the shops I can find the item in.
For example:
* TODO Cheese for breakfast :aldi:auchan:
* DONE Avocado :aldi:auchan:grocer:
CLOSED: [2025-12-29 Mon 18:53]
Nice!
We've just started a simple database with a couple of items and we can see movement!
First of all, I know I have to buy cheese and that I can buy it at aldi and auchan.
I also know that I bought avocados almost at the end of last year and that I can buy it at aldi, auchan and grocer.
By using tags as names for the shops we can buy an item at, we're effectively creating a database with an M:N relationship between items and shops.
We can also name our tags however we want, so we adding shops doesn't require extra steps.
Note: Be careful to avoid typos when adding existing shops. Prefer using tools with an autocomplete feature.
Now, Avocado is a clear item name, but Cheese for breakfast, not so much. It turns out that reality is often ambiguous and that we may want to try different types of cheese, beer or cereals. That's not an issue, however, as Org allows us to add a body to each note containing any information we deem important about an item:
* TODO Cheese for breakfast :aldi:auchan:
*Auchan:* We've tried classic and semi-mature goat cheese from Brand XZYZZY
on 2025-10-28. We didn't like them.
* DONE Avocado :aldi:auchan:grocer:
CLOSED: [2025-12-29 Mon 18:53]
Now, every time I'm looking for some Cheese for breakfast, I'll be sure to avoid the ones we tried and didn't like.
We can also use checklists to select what exact item we want to buy:
* TODO Beer :auchan:
*Auchan:* Beers we like:
- [ ] Free Dam
- [X] Heineken 0.0
- [ ] Mahou Toasted
I'll be sure to re-stock on Heineken next time I visit the supermarket!
Making it portable
If I had Neovim in my phone's terminal emulator, I would just open it and query Org with something like like auchan/TODO.
Alas, the interface is not so great on mobile and I need to share the lists with Ari, my partner, who would kill me if I tried to force a terminal on them.
Instead, we went with Orgzly as we both have Android phones and it works on mine, which doesn't have any Google crap.
In order to sync the files, we use Syncthing and a ~/Sync/ directory we both share.
To use the notes we're syncing, we'll first need to configure our Org directory as a repository in Orgzly, which we can easily do in Settings/Repositories at the time of writing.

Once our notes are synced, we will find a Shopping notebook in Orgzly's main screen (or we can create one from the main screen if we didn't write any Org files in the first step).
Clicking on it, we'll find the items we added earlier.
We can add more items here with the floating + button and edit their tags, status and body.
Also, we can see if a note has a body of text before opening it if there's a number after the list of tags, which represents the number of lines in the note's body.
Saved searches as database views
In order to turn a random list of notes into a shopping database system, we need different ways of viewing the data.
In Orgzly, we can search all our notes and save those searches for quick use, and that's exactly what we're going to use as database views.
Sliding from the left of the screen or pressing the hamburger menu at the top left, we'll find the left drawer and go to the Searches page, which should be at the top of the menu.
There, add a new search with the floating + icon, name it Shopping and add the following search query:
b.Shopping o.t

This first simple query does two things:
b.Shopping: Restrict the search to notes in theShoppingnotebook (b).o.t: Order (o) the found notes, which are the shopping items, by title (t).
Cool!
Saving this query gives us a sorted view into the Shopping notebook we're now treating as a database.
This allows us to quickly navigate the items we have in our system in alphabetical order, which can be useful for general maintenance.
Another good query is one that displays which items we need to buy at a particular shop.
For example, save this one with the name Shopping/grocer:
b.Shopping t.grocer it.todo o.t
This query has two new parts:
t.grocer: Restrict the search to items to which we added thegrocertag (t).it.todo: Restrict the search to items whose state (it) is interpretable asTODO.
As you can see, all parts of the query combine together with an implicit AND operator, so every part we add will constrain the search further.
Even though this search displays the items we have to buy, marking one as bought (DONE) will remove it from the view and send it to the void of all items we can buy at that particular shop, which can be in the hundreds for a big supermarket.
To solve this, we want our view to also display the items we have bought during this visit to the shop, which we can do like so:
b.Shopping t.grocer AND (it.todo OR (it.done AND c.eq.today)) o.t
Here, instead of just filtering by it.todo, we have a more complex filter, which requires explicit AND operators:
it.todo: Same as before.ORit.done: Restrict the search to items whose state is interpretable asDONE.ANDc.eq.today: Restrict the search to items whose close time (c) is equal to (eq) today (today).
So now, instead of only displaying the items we need to buy, we also display the ones we marked as bought today.
It's not exactly a query for the items we bought during our latest visit to the shop, but it's flexible enough to allow us to review the list at a later point in the day.
This works because Orgzly automatically adds a CLOSED date when we mark a TODO note as DONE, which c.eq.today compares against with our device's current date.
If we want to hide bought item, we can just remove the closing date or edit it to the day before!
Finally, we'd like to display TODO items at the top of the list and DONE ones at the bottom, as Google Keep does too.
This requires a small addition to the query:
b.Shopping t.grocer AND (it.todo OR (it.done AND c.eq.today)) o.st o.t
Here, we added o.st to order (o) the results by they their TODO/DONE state (st) before ordering them by title.
The order of the query parts is important here, as each order specifier divides the results in different sections that the following specifier applies for each section.
For example, your results could look like this:
TODO Almonds
TODO Beef
TODO Cornflakes
DONE Anchovies
DONE Biscuits
DONE Curry
That's because Orgzly applies the o.st order to the whole list and then the o.t order to both the TODO and DONE sections of the lists.
Quick side rant: if a small plaintext notes app can do this, million-dollar proprietary music players should be able to sort albums by artist and year in the same way.
I'm still hurt that this is an issue in 2026 >:(
Anyway! This should be enough for us to be happy with our plaintext shopping lists, but there's one last trick that makes this system shine above all others.
Using priorities as categories
Org Mode lets us assign priorities to notes, which is a single letter from A to Z.
The intended use of priorities is to let us know which TODO notes have precedence over others in our life, but the system doesn't impose any semantics on the priorities.
As such, we can hack priorities to act as categories and group items by them.
As an example, here are some priority semantics you can use:
[#D]: Drinks.[#H]: Home items.[#M]: Meat and charcuterie.[#P]: Pantry.[#V]: Vegetables and fruit.[#X]: Frozen (theXlooks like a snowflake).
We can define our categories as strictly or loosely as we like, as it's us who're defining their meaning. Then, to unleash their power, we make one final change to our query:
b.Shopping t.grocer AND (it.todo OR (it.done AND c.eq.today)) o.p o.st o.t
By adding the order specifier o.p before o.st and o.t, we're first of all ordering our items by priority (p).
By doing this, every time we mark an item as DONE, it will move to the bottom of the sub-list of items of the same category, effectively transforming our shopping list into a compact set of smaller lists for items we can find close together in a shop.
How cool is that?
TODO [#D] Beer TODO [#D] Soda
TODO [#D] Soda --> DONE [#D] Beer
TODO [#V] Lettuce TODO [#V] LettuceIn conclusion
After testing this system for a few months now, I can confidently say that this is the best shopping lists system I've ever used. I don't think it's perfect, as it has some rough edges like categories being shared between shops or the search syntax, but these issues are minor compared to the flexibility Org Mode offers. Being able to track the shopping lists both in the computer and the phone, using the notes as a database and making everything work with a few plaintext files in our local file system are the kinds of advantages that I expect (and demand!) from the general purpose computing machines we carry every day.
What I find most beautiful about this system is that it doesn't need a domain specific program to work with its particular data representation that maintainers may decide to abandon one day. Rather, it's all built on top of the battle-tested Org Mode notebook system, which tons of people use around the world. Sure, Orgzly may die one day, but the file format is still a well-known standard and we have multiplatform support from many different programs, so it's not like we'll wake up one day without a trace of our old shopping lists.
So go forth my friend and enjoy your shopping lists! Open your lists to add missing items in less than fifteen seconds when you find them. Make your visits to the supermarket less miserable by optimising your path with categories. And, on top of all, use your computers to do what they were designed for: to improve your life with good, libre software.