home-assistant-plugin/skills/ha-validate/SKILL.md
Validate Home Assistant YAML for syntax errors, undefined secrets, and duplicate keys. Use when validating HA config, diagnosing YAML errors, or running hass check_config.
npx skillsauth add laurigates/claude-plugins ha-validateInstall 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.
Validate Home Assistant configuration files for YAML syntax errors and common issues.
| Use this skill when... | Use ha-configuration instead when... |
|---|---|
| Checking YAML syntax in configuration.yaml or automations.yaml | Editing configuration.yaml to add or change integrations |
| Detecting undefined !secret references against secrets.yaml | Adding new entries to secrets.yaml |
| Finding duplicate keys in scripts.yaml or scenes.yaml | Reorganizing configuration into packages |
| Running hass --script check_config via Docker or HA OS | Authoring template sensors and recorder/logger config |
{{ path or '.' }}find {{ path or '.' }} -name "*.yaml" -type fValidate all YAML files for proper syntax:
find {{ path or '.' }} -name "*.yaml" -type f -exec python3 -c "
import yaml
import sys
try:
with open('{}', 'r') as f:
yaml.safe_load(f)
print('OK: {}')
except yaml.YAMLError as e:
print('ERROR: {}')
print(str(e)[:200])
sys.exit(1)
" \; 2>&1 | head -50
Check for undefined secrets:
# Find secret references
grep -rh "!secret [a-z_]*" {{ path or '.' }} --include="*.yaml" 2>/dev/null | \
sed 's/.*!secret //' | sort -u > /tmp/used_secrets.txt
# Check if secrets.yaml exists
if [ -f "{{ path or '.' }}/secrets.yaml" ]; then
echo "secrets.yaml found"
# List defined secrets
grep "^[a-z_]*:" {{ path or '.' }}/secrets.yaml | sed 's/:.*//' | sort -u > /tmp/defined_secrets.txt
echo "Undefined secrets:"
comm -23 /tmp/used_secrets.txt /tmp/defined_secrets.txt
else
echo "WARNING: secrets.yaml not found"
fi
Check for duplicate keys:
python3 -c "
import yaml
import sys
from collections import Counter
class DuplicateKeyChecker(yaml.SafeLoader):
def construct_mapping(self, node, deep=False):
keys = [k.value for k, v in node.value if isinstance(k, yaml.ScalarNode)]
duplicates = [k for k, count in Counter(keys).items() if count > 1]
if duplicates:
print(f'Duplicate keys in {node.start_mark}: {duplicates}')
return super().construct_mapping(node, deep)
for f in ['configuration.yaml', 'automations.yaml', 'scripts.yaml', 'scenes.yaml']:
path = '{{ path or '.' }}/' + f
try:
with open(path) as file:
yaml.load(file, Loader=DuplicateKeyChecker)
print(f'OK: {f}')
except FileNotFoundError:
pass
except yaml.YAMLError as e:
print(f'ERROR in {f}: {e}')
" 2>&1
If Home Assistant is running in Docker:
docker exec homeassistant hass --script check_config 2>&1 | head -100 || echo "Docker validation not available"
ha core check 2>&1 || echo "HA OS validation not available"
Report validation results:
| Issue | Fix |
|-------|-----|
| found undefined alias | Add missing entry to secrets.yaml |
| could not determine a constructor | Check YAML indentation |
| duplicate key | Remove or rename duplicate key |
| expected <block end> | Fix indentation alignment |
| mapping values are not allowed | Add space after colon |
testing
Verify accumulated bug claims at upstream HEAD and dedup against trackers before filing issues. Use when filing upstream reports from backlogs, audit docs, or git-history findings.
documentation
Gate outward-bound text (upstream issues, docs, PR bodies) through isolated haiku fresh-reader critique before publishing. Use when an artifact must survive a reader with zero project context.
tools
Suggest improvements to SKILL.md content, descriptions, or tool config from eval results. Use when raising pass rates, fixing triggering, or iterating on a skill after evaluation.
tools
deadbranch CLI for stale-branch cleanup — dry-run preview, TUI or non-interactive delete, protects main/develop/WIP. Use when asked to clean up branches, prune branches, or remove stale branches.