Track recurring home maintenance tasks with a beautiful sidebar panel built right into your Home Assistant instance.
- Template library & CSV import/export — 90+ pre-built tasks covering HVAC, plumbing, electrical, exterior, and more; bulk-import or export your own via CSV
- Search, filter & labels — filter tasks by title/description or by Home Assistant labels with clickable chips
- Overdue notifications — optional per-task persistent notification when a task becomes overdue
- Seasonal tasks — restrict a task to specific active months (e.g. spring/summer lawn care) instead of flagging it overdue year-round
- Completion history — opt-in per-task log of every completion, with an optional cap on how many entries to keep
- NFC tag support — scan a tag to mark a task complete instantly
- Automation-friendly — a binary sensor and complete-button per task, a global "any overdue" sensor, and
create_task/complete_task/mark_overdueservices - Localized, configurable panel — sidebar UI follows your Home Assistant profile language (English/German, falling back to English), with a configurable title and optional admin-only access
- Open HACS in your Home Assistant instance.
- Go to Integrations.
- Click the three-dot menu in the top-right corner and select Custom repositories.
- Add
https://github.com/TomSelander/ha-home-maintenanceas an Integration. - Search for Home Maintenance Pro and click Download.
- Restart Home Assistant.
- Download the latest release from the GitHub releases page.
- Copy the
custom_components/ha_home_maintenancedirectory into your Home Assistantconfig/custom_components/directory. - Restart Home Assistant.
- Go to Settings > Devices & Services.
- Click Add Integration.
- Search for and select Home Maintenance Pro.
- Follow the setup wizard.
After the integration is set up, you can adjust its options at any time via Settings > Devices & Services > Home Maintenance Pro > Configure:
| Option | Default | Description |
|---|---|---|
admin_only |
true |
Restrict the sidebar panel to admin users only |
sidebar_title |
"Maintenance" |
The title displayed in the sidebar navigation |
max_completion_history |
0 (unlimited) |
Oldest completion-history entries are dropped once a task exceeds this count |
create_aggregate_sensor |
true |
Create binary_sensor.home_maintenance_any_overdue, which is on when any task is overdue |
- Open the Home Maintenance Pro panel from the sidebar.
- Click Add Task.
- Fill in the task name, interval (value and type: days/weeks/months), and an optional description.
- Optionally set the Last Performed date if the task has been done before.
- Click Save.
- Click Browse Templates from the task list.
- Browse or search the 90+ pre-built tasks.
- Click a template to pre-fill the form, then adjust as needed and click Save.
- Click Browse Templates from the task list.
- Click the Import CSV button.
- Select a
.csvfile. The required column istitle; optional columns aredescription,interval_value,interval_type,last_performed, andicon. - Review the preview table and click Import to create all tasks.
Example CSV:
title,description,interval_value,interval_type,last_performed,icon
Replace HVAC Filter,Change the air filter,90,days,2026-01-15,mdi:air-filter
Clean Gutters,Remove debris from gutters,180,days,,mdi:home-roofIf you were using the original "home_maintenance" integration (or a fork of it), you can migrate all your existing tasks using the CSV import feature.
-
Export your legacy data
- Locate your legacy integration's storage file at
config/.storage/home_maintenance - Open it in a text editor and review your task data
- Locate your legacy integration's storage file at
-
Create a CSV file
- Create a new
.csvfile with the following columns:title,description,interval_value,interval_type,last_performed,icon
- Create a new
-
Map legacy fields to CSV columns
name→titlefrequencyorfrequency_value→interval_valuefrequency_typeorfrequency_unit→interval_type(usedays,weeks, ormonths)last_doneorlast_completed→last_performed(format:YYYY-MM-DD)icon→icon(e.g.,mdi:air-filter)- Any other notes →
description
-
Import via the UI
- Go to Browse Templates → Import CSV
- Upload your CSV file
- Review the preview to ensure all fields are correct
- Click Import to create all tasks
title,description,interval_value,interval_type,last_performed,icon
Replace HVAC Filter,Change the air filter,90,days,2026-01-15,mdi:air-filter
Clean Gutters,Remove debris from gutters,180,days,2026-02-10,mdi:home-roof
Drain Furnace Trap,Annual drainage of condensation trap,365,days,2025-01-20,mdi:water-pump-off- Additive import — The import will not delete your existing tasks. Review and clean up duplicates if needed.
- Interval format — The
interval_valueshould be a number (e.g., 90, 180, 365) andinterval_typemust bedays,weeks, ormonths. - Date format — Use
YYYY-MM-DDformat forlast_performeddates. Leave blank if the date is unknown.
- From the task list, click Export CSV.
- A
home_maintenance_tasks.csvfile will be downloaded containing all tasks with their title, description, interval, last performed date, icon, labels, and notification setting.
- Use the search box at the top of the task list to filter by title or description.
- Click label chips below the search box to filter by one or more Home Assistant labels. Tasks matching any selected label are shown (OR logic). Click a selected chip again to deselect it, or use the Clear button to reset all label filters.
- Click the pencil icon on any row in the task table.
- Modify any fields and click Save.
- Click the checkmark icon on a task row to mark it complete. The last performed date is set to today and the next due date advances by the task's interval.
- Alternatively, scan the NFC tag associated with the task (see NFC setup below).
Each task has a Notify when overdue toggle on the create/edit form. When enabled, a persistent notification is created in Home Assistant as soon as the task transitions to overdue status. The notification is automatically deduplicated per task so you only see one at a time.
Each task has a Track completion history toggle on the create/edit form (off by default). When enabled, every completion is timestamped and shown in a scrollable Completion History section (newest first) on the edit form. History is unbounded by default — cap it per the max_completion_history option above if you'd rather trim old entries.
Every task binary sensor exposes the following attributes for use in automations and dashboards:
| Attribute | Type | Description |
|---|---|---|
title |
string | Task title |
description |
string | Task description |
last_performed |
string | null | ISO date of the last completion (null if never performed) |
next_due |
string | ISO date when the task is next due |
days_until_due |
integer | null | Days until next due (0 = due today, negative = overdue, null if never performed) |
interval |
string | Repeat interval, e.g. 12 months |
icon |
string | MDI icon name, e.g. mdi:wrench |
tag_id |
string | null | NFC tag ID linked to the task (null if none) |
track_history |
boolean | Whether completion history tracking is enabled |
completion_count |
integer | null | Total number of recorded completions (null when track_history is off) |
last_completed |
string | null | ISO timestamp of the most recent completion (null when track_history is off or no completions yet) |
labels |
list | HA labels assigned to the task (empty list if none) |
Example — notify a specific person when their tasks are overdue:
condition:
- condition: template
value_template: "{{ 'Mike' in state_attr('binary_sensor.my_task', 'labels') }}"Example — skip notification if the task was performed recently:
condition:
- condition: template
value_template: "{{ state_attr('binary_sensor.my_task', 'last_performed') < (now().date() - timedelta(days=7)).isoformat() }}"-
Edit a task and note its Task ID displayed in the form.
-
Write the following URL to an NFC tag using any NFC writing app:
https://your-ha-instance.local/api/ha_home_maintenance/complete/<task_id> -
Scanning the tag will mark the task complete immediately.
Each task exposes a button entity named "<Task Title> Complete". Pressing the button marks the task as completed (sets last performed to today), identical to clicking the checkmark in the sidebar panel.
Button entities are automatically created when tasks are added and become unavailable when tasks are deleted. They can be placed on any Home Assistant dashboard using the standard Button card.
type: button
entity: button.replace_hvac_filter_complete
name: Mark HVAC Filter Done
icon: mdi:check-circleBecause it's a standard button entity, button.press can also be called from an automation — so any switch, NFC tag, or sensor state change can mark a task complete without touching the panel.
Each task exposes a binary_sensor entity with a name derived from the task. The sensor is on when the task is overdue and off when it is current.
A global sensor binary_sensor.home_maintenance_any_overdue is on whenever at least one task is overdue.
automation:
alias: "Notify when maintenance is overdue"
trigger:
- platform: state
entity_id: binary_sensor.home_maintenance_any_overdue
to: "on"
action:
- service: notify.mobile_app_your_phone
data:
title: "Home Maintenance Pro Overdue"
message: "One or more home maintenance tasks need attention."Call button.press against the task's button.<task>_complete entity from any automation, triggered by a physical button, a switch, or a sensor state:
automation:
alias: "Mark driveway shoveled from a smart button"
trigger:
- platform: device
device_id: your_smart_button_device_id
domain: button
type: press
action:
- service: button.press
target:
entity_id: button.shovel_driveway_completeThe integration also exposes services for automations that need more than button.press:
| Service | Purpose |
|---|---|
ha_home_maintenance.reset_last_performed |
Set a task's last-performed date to a specific date (defaults to today). Targets the task's binary_sensor entity. |
ha_home_maintenance.mark_overdue |
Force a task to become overdue immediately, e.g. when a sensor reports a fault. Targets the task's binary_sensor entity. |
ha_home_maintenance.create_task |
Create a new task from an automation. Takes a title plus the same optional fields as the create form (description, interval_value, interval_type, icon, labels, notify_when_overdue, track_history, tag_id). If a task with the same title already exists, this is a no-op — safe to call repeatedly from a flapping sensor. |
ha_home_maintenance.complete_task |
Mark a task complete. Accepts either an entity target or a title field — the title form is useful for a task created dynamically via create_task, since its entity id isn't known ahead of time. |
Example — create a task when a sensor reports a fault, complete it when the sensor recovers:
automation:
- alias: "Create filter-replacement task when purifier filter is empty"
trigger:
- platform: numeric_state
entity_id: sensor.air_purifier_filter_life
below: 1
action:
- service: ha_home_maintenance.create_task
data:
title: "Replace air purifier filter"
icon: "mdi:air-filter"
notify_when_overdue: true
- alias: "Complete filter-replacement task when purifier filter is refilled"
trigger:
- platform: numeric_state
entity_id: sensor.air_purifier_filter_life
above: 99
action:
- service: ha_home_maintenance.complete_task
data:
title: "Replace air purifier filter"Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository.
- Run
scripts/setupto install all dependencies. - Make your changes.
- Run
scripts/lintto check Python code style. - Run
scripts/developto build the frontend bundle. - Submit a pull request.
