Feature: Manage Shopping List with Your Voice
Want to quickly add, remove, or hear what's on your shopping list - just by asking your Home Assistant? This guide shows you exactly how to do it, step by step, with both advanced AI (ExtendedOpenAI/LLM) and fully local options.
1. Enable the Shopping List Integration
Home Assistant's shopping list is available by default in most installs, but if you don't see "Shopping List" or "To-Do List" in your sidebar:
- Go to Settings > Devices & Services.
- Click Add Integration, search for Shopping List or To-Do List, and follow the prompts to add it.
- Once set up, you can add the shopping list as a card to any dashboard by editing your dashboard and clicking Add Card > To-Do List.
2. Voice Shopping List with ExtendedOpenAI
With ExtendedOpenAI, you can add functions that let your Home Assistant understand and respond to natural shopping list requests.
- Go to Settings > Devices & Services → ExtendedOpenAI and click the cog wheel to edit.
- Find the Functions section. Paste the code below to add shopping list actions (add, remove, read, and clear).
- name: add_item_to_shopping_list
description: Add an item to your shopping list.
parameters:
type: object
properties:
name:
type: string
description: The item to add.
required: [name]
function:
type: script
sequence:
- action: todo.add_item
target:
entity_id: todo.shopping_list
data:
summary: '{{ name }}'
- name: remove_item_from_shopping_list
description: Remove an item from your shopping list.
parameters:
type: object
properties:
name:
type: string
description: The item to remove.
required: [name]
function:
type: script
sequence:
- action: todo.remove_item
target:
entity_id: todo.shopping_list
data:
item: '{{ name }}'
- name: read_shopping_list
description: Read out all items currently needing action on your shopping list.
parameters:
type: object
properties: {}
function:
type: script
sequence:
- action: todo.get_items
target:
entity_id: todo.shopping_list
data:
status: needs_action
value_template: |
{% set items = (results[0].items if results else []) %}
{% if items %}
{{ items | map(attribute='summary') | join(', ') }}
{% else %}
Your shopping list is empty.
{% endif %}
- name: clear_shopping_list
description: Remove all completed items from your shopping list.
parameters:
type: object
properties: {}
function:
type: script
sequence:
- action: todo.get_items
target:
entity_id: todo.shopping_list
data:
status: completed
response_variable: completed_items
- repeat:
for_each: '{{ completed_items[0].items }}'
sequence:
- action: todo.remove_item
target:
entity_id: todo.shopping_list
data:
item: '{{ repeat.item.summary }}'
How it works:
- Add: Just say "Add milk to my shopping list" and it will appear instantly.
- Remove: "Remove milk from my shopping list" deletes the first matching item.
- Read: "What's on my shopping list?" reads out all your current items.
- Clear: "Clear my shopping list" removes all completed items.
3. Local Option: Shopping List Automations Using Assist (No Cloud Needed)
Want to keep everything local? Home Assistant's Assist lets you create voice commands with sentence triggers - no cloud or LLM required. Here are ready-to-use automations for adding, removing, and reading your list. You can add these by going to Settings > Automations & Scenes, click Add Automation, and then switch to YAML mode before pasting.
Add Item by Voice (local, with duplicate prevention)
alias: Assist Shopping List – Add Item
description: ""
triggers:
- command:
- "[please] add {item} to [my] shopping list"
- "[please] put {item} on [my] shopping list"
- "{item} to [my] shopping list [please]"
trigger: conversation
conditions: []
actions:
- action: todo.get_items
target:
entity_id: todo.shopping_list
response_variable: shopping_items
- choose:
- conditions: >
{% set target = trigger.slots.item | lower %}
{% set existing = shopping_items['todo.shopping_list']['items']
| selectattr('status', 'equalto', 'needs_action')
| map(attribute='summary')
| map('lower') | list %}
{{ target in existing }}
sequence:
- set_conversation_response: "{{ trigger.slots.item }} is already on your shopping list."
default:
- action: shopping_list.add_item
data:
name: "{{ trigger.slots.item }}"
- set_conversation_response: "Added {{ trigger.slots.item }} to your shopping list."
mode: single
Remove Item by Voice (local)
alias: Assist Shopping List – Remove Item
description: ""
triggers:
- command:
- "[please] remove {item} from [my] shopping list"
- "(remove|delete|take off) {item} (from|off) [my] shopping list"
- "{item} (from|off) [my] shopping list [please]"
trigger: conversation
conditions: []
actions:
- action: shopping_list.remove_item
data:
name: "{{ trigger.slots.item }}"
- set_conversation_response: "Removed {{ trigger.slots.item }} from your shopping list."
mode: single
Read Shopping List by Voice (local)
alias: Assist Shopping List – Read Items
description: ""
triggers:
- command:
- "[please] (what's|what is|read|list|tell me|show me) (on|in) [my|the] shopping list [please]"
- "shopping list [please]"
- "[please] (what's|what is) my shopping list [please]"
trigger: conversation
conditions: []
actions:
- action: todo.get_items
target:
entity_id: todo.shopping_list
response_variable: shopping_items
- set_conversation_response: >
{% set items = shopping_items['todo.shopping_list']['items']
| selectattr('status', 'equalto', 'needs_action')
| map(attribute='summary') | list %}
{% if items %}
Your shopping list contains: {{ items | join(', ') }}.
{% else %}
Your shopping list is empty.
{% endif %}
mode: single
How Sentence Triggers Work
These automations use sentence triggers with special syntax to match the way people speak:
- [word] = Optional. The word inside square brackets can be omitted. Example:
[please]means you can say "please" or not. - (a|b) = Required choice. The options inside parentheses separated by
|mean you must say one of those words. Example:(remove|delete)means either word will match.
This means you can say things like "Can you add bananas to my shopping list?" or just "Bananas on my shopping list," and Home Assistant will understand and respond.
Local vs LLM: What Are the Differences?
Home Assistant's built-in voice (Assist) can process some basic shopping list commands locally, with no internet or cloud required. This is great for privacy and reliability, but it has some limitations:
- If you say, "Add milk, bread and eggs to my shopping list," Assist will add a single item called "milk bread and eggs" - it doesn't know how to separate multiple items.
- It does not understand questions like "What's on my shopping list?" - it only supports actions you've built as automations.
In contrast, an LLM-based setup (using ExtendedOpenAI or similar) can understand much more natural language, handle lists, and answer questions about your shopping list.
The best of both worlds: You can use both local and LLM processing at the same time! Just enable LLM for advanced commands, but set Home Assistant to "Prefer handling commands locally" for speed and privacy with supported actions.
To enable this: Go to Settings → Voice Assistants, click on your assistant, and toggle "Prefer handling commands locally" on.
Can Local Voice Handle Multiple Items?
If you want to process multiple items locally, you could try using a template to split input by commas or the word "and". For example, if a user says "add milk, bread and eggs", you could split the input string by commas and then by "and". However, when speaking, users don't always say "comma" - so unless the input is typed or dictated with clear pauses, this method is limited. Also, many shopping list items have more than one word (like "almond milk" or "green apples"), so splitting by spaces won't work reliably.
Summary: For most users, local Assist is ideal for quick, simple commands ("add bananas"), but for complex, natural-language commands (adding multiple items, or asking for a list), an LLM-powered solution is much more capable.
What's Next?
- Try adding, removing, or hearing your shopping list with your voice!
- Combine these with dashboard cards for quick tap access too.
- Want to add more advanced options (like batch adds or due dates)? Let me know and I'll show you how!