Skip to content

Tips & Tricks: Bulk Updating Chores via Scripts

ccpk1 edited this page Jun 3, 2026 · 2 revisions

Bulk Updating Chores via Scripts: Examples and Warnings

While ChoreOps does not provide a dedicated bulk-update service, you can use Home Assistant scripts with repeat.for_each to loop through a list of chores and update them one at a time.

This is an advanced pattern. It can be very effective, but it also makes it easy to apply the same change to a large number of chores very quickly.

Warning

Use extreme caution with bulk update scripts.

  • Test with one chore first. Use Developer Tools -> Actions to manually run choreops.update_chore for a single chore until the payload is exactly what you want.
  • Create a backup before your first bulk run. See Backup & Restore.
  • choreops.update_chore updates only the fields you provide, but any field you do provide is applied exactly as sent. For example, assigned_user_names with assignment_action: "replace" (the default) replaces the list entirely. Use assignment_action: "add" or "remove" to merge with existing assignees instead.
  • Validation still applies. If a bulk run does not produce the results you expect, check your Home Assistant logs for service call failures.
  • For large or long-lived automations, id is a safer identifier than name. The examples below use name because it is easier to read, but id is less fragile if names ever change.

If you are comfortable with those rules, here are two ways to build the script.


Example 1: Manual target list

In this example, target_chores is a hardcoded list.

alias: "ChoreOps: Manual Bulk Update Reminder Offset"
description: "Iterates through a hardcoded list of chore names to update their due reminder offset."
mode: single
variables:
  entry_title: "ChoreOps"
  new_offset: "37m"
  target_chores:
    - "Clean the gutters"
    - "Sweep the garage"
    - "Organize workbench"
sequence:
  - repeat:
      for_each: "{{ target_chores }}"
      sequence:
        - action: choreops.update_chore
          data:
            config_entry_title: "{{ entry_title }}"
            name: "{{ repeat.item }}"
            due_reminder_offset: "{{ new_offset }}"

Example 2: Dynamic helper loop

In this example, the update sequence is the same. The difference is that target_chores is built dynamically from one user's dashboard helper.

This is useful when you want to update all chores currently exposed through that helper instead of maintaining a manual list.

alias: "ChoreOps: Dynamic Bulk Update via Dashboard Helper"
description: "Dynamically fetches all chores from a UI dashboard helper and updates them."
mode: single
variables:
  entry_title: "ChoreOps"
  helper_entity: "sensor.zoe_choreops_ui_dashboard_helper"
  new_offset: "37m"
  target_chores: >
    {% set helper = helper_entity %}
    {% set dashboard_helpers = state_attr(helper, 'dashboard_helpers') or {} %}
    {% set chore_helper_eids = dashboard_helpers.get('chore_helper_eids', []) %}
    {% if chore_helper_eids is not iterable or chore_helper_eids is string %}
      {% set chore_helper_eids = [] %}
    {% else %}
      {% set chore_helper_eids = chore_helper_eids | list %}
    {% endif %}

    {% set ns = namespace(chores=state_attr(helper, 'chores') or []) %}
    {% if chore_helper_eids | count > 0 %}
      {% set ns.chores = [] %}
      {% for helper_eid in chore_helper_eids %}
        {% if helper_eid not in ['', none, 'None'] and states(helper_eid) not in ['unknown', 'unavailable'] %}
          {% set helper_rows = state_attr(helper_eid, 'chores') or [] %}
          {% if helper_rows is iterable and helper_rows is not string %}
            {% set ns.chores = ns.chores + (helper_rows | list) %}
          {% endif %}
        {% endif %}
      {% endfor %}
    {% endif %}

    {{ ns.chores | map(attribute='name') | list }}
sequence:
  - repeat:
      for_each: "{{ target_chores }}"
      sequence:
        - action: choreops.update_chore
          data:
            config_entry_title: "{{ entry_title }}"
            name: "{{ repeat.item }}"
            due_reminder_offset: "{{ new_offset }}"

Notes on adapting these examples

  • Change due_reminder_offset to the specific field you want to update.
  • If you are updating list-style fields such as assigned_user_names, send the complete intended value for that field.
  • If your goal is to rename or reassign many chores, consider exporting the target list first and testing with only one item in target_chores before expanding the loop.

See also

Clone this wiki locally