plugins/home-assistant-dev/skills/ha-deprecation-fixes/SKILL.md
Fix Home Assistant deprecation warnings and upgrade integrations to newer HA versions. Use when encountering deprecated imports, type annotations, or patterns that need updating for HA 2024.x/2025.x compatibility.
npx skillsauth add l3digitalnet/claude-code-plugins ha-deprecation-fixesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Home Assistant deprecations follow a consistent pattern:
# OLD (deprecated)
from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.components.ssdp import SsdpServiceInfo
from homeassistant.components.dhcp import DhcpServiceInfo
from homeassistant.components.usb import UsbServiceInfo
from homeassistant.components.bluetooth import BluetoothServiceInfo
# NEW (use these)
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
from homeassistant.helpers.service_info.ssdp import SsdpServiceInfo
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
from homeassistant.helpers.service_info.usb import UsbServiceInfo
from homeassistant.helpers.service_info.bluetooth import BluetoothServiceInfo
# OLD pattern
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
coordinator = MyCoordinator(hass, entry)
await coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
# NEW pattern
type MyConfigEntry = ConfigEntry[MyCoordinator]
async def async_setup_entry(hass: HomeAssistant, entry: MyConfigEntry) -> bool:
coordinator = MyCoordinator(hass, entry)
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator # Just assign directly
async def async_unload_entry(hass: HomeAssistant, entry: MyConfigEntry) -> bool:
# No cleanup needed - runtime_data is automatically cleared
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
# OLD (deprecated)
class MyOptionsFlow(OptionsFlow):
def __init__(self, config_entry: ConfigEntry) -> None:
self.config_entry = config_entry
# NEW (use this)
class MyOptionsFlow(OptionsFlow):
# No __init__ needed - self.config_entry is automatically available
async def async_step_init(self, user_input=None):
current_value = self.config_entry.options.get("key", "default")
class MyCoordinator(DataUpdateCoordinator[dict[str, Any]]):
async def _async_setup(self) -> None:
"""Set up the coordinator (runs once before first update)."""
self.device_info = await self.client.async_get_device_info()
async def _async_update_data(self) -> dict[str, Any]:
"""Fetch data (runs on every update)."""
return await self.client.async_get_data()
# OLD (deprecated)
from homeassistant.components.vacuum import STATE_CLEANING, STATE_DOCKED
class MyVacuum(StateVacuumEntity):
@property
def state(self) -> str:
return STATE_CLEANING
# NEW
from homeassistant.components.vacuum import VacuumActivity
class MyVacuum(StateVacuumEntity):
@property
def activity(self) -> VacuumActivity | None:
return VacuumActivity.CLEANING
# OLD (deprecated)
class MyCamera(Camera):
@property
def frontend_stream_type(self) -> StreamType:
return StreamType.WEB_RTC
async def async_handle_web_rtc_offer(self, offer_sdp: str) -> str:
pass
# NEW
class MyCamera(Camera):
async def async_handle_async_webrtc_offer(
self, offer_sdp: str, session_id: str, send_message: Callable
) -> None:
pass
# OLD (pre-Python 3.9)
from typing import List, Dict, Optional, Union
def my_func(items: List[str]) -> Dict[str, int]: ...
def optional_param(value: Optional[str] = None) -> None: ...
# NEW
from __future__ import annotations
def my_func(items: list[str]) -> dict[str, int]: ...
def optional_param(value: str | None = None) -> None: ...
from __future__ import annotations to all filesList[], Dict[], Optional[X], Union[X, Y] with modern syntaxhelpers.service_info.*hass.data[DOMAIN] with entry.runtime_data__init__ if only storing config_entryVacuumActivity enum instead of STATE_* constants# Detect common deprecations
python3 scripts/check-patterns.py custom_components/my_integration/
# Detects: old imports, deprecated type hints, blocking I/O, hass.data usage
ha-config-migrationha-coordinatortools
Configures Python projects to the Python Tooling SSOT Standard (uv, Ruff, BasedPyright strict, pytest+coverage, pip-audit). Use when creating projects, writing standalone scripts, configuring pyproject.toml, migrating from pip/Poetry/mypy/black/flake8, or auditing a project for conformance to the standard.
development
Use when you're stuck or missing current information mid-task - the same command/API/approach failed twice, an error looks like a changed or deprecated API, or you need the current version of something, a fact from after your training cutoff, or to verify something you cannot confirm from the code in context. Starts with a cheap inline lookup and only escalates to a full research sweep if that fails. Do not use for routine pre-emptive checks before ordinary library work - for deliberate research, use /qdev:research.
documentation
Update the llm-wiki knowledge base (remote LXC CT 103, /srv/workspaces/llm-wiki, over SSH) with implementation-level details from the current session by dispatching the up-docs-propagate-wiki sub-agent. This skill should be used when the user runs /up-docs:wiki.
documentation
Update repository documentation (README.md, docs/, CLAUDE.md) based on session changes by dispatching the up-docs-propagate-repo sub-agent. This skill should be used when the user runs /up-docs:repo.