{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ha-ultimate",
    "name": "Home Assistant",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/Titunito/ha-ultimate",
    "canonicalUrl": "https://clawhub.ai/Titunito/ha-ultimate",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ha-ultimate",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ha-ultimate",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "ha-skills-comparison-v2.html",
      "README.md",
      "SKILL.md",
      "scripts/ha.sh",
      "scripts/inventory.js",
      "references/api.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/ha-ultimate"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/ha-ultimate",
    "agentPageUrl": "https://openagent3.xyz/skills/ha-ultimate/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ha-ultimate/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ha-ultimate/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "ha-ultimate — Definitive Home Assistant Skill",
        "body": "Control your smart home via the Home Assistant REST API with safety enforcement, inventory\nawareness, and full domain coverage."
      },
      {
        "title": "1. Environment Variables",
        "body": "export HA_URL=\"http://your-ha-instance:8123\"\nexport HA_TOKEN=\"your-long-lived-access-token\"\n\nOr create a .env file in the skill directory (auto-loaded by ha.sh):\n\nHA_URL=http://192.168.1.100:8123\nHA_TOKEN=eyJ...your-token...\n\nThe CLI wrapper also checks $HOME/.config/homeassistant/config.json as a fallback\n(JSON with url and token keys). Protect this file with restrictive permissions\n(chmod 600) since it may contain your token."
      },
      {
        "title": "2. Getting a Long-Lived Access Token",
        "body": "Open Home Assistant → Profile (bottom left)\nScroll to \"Long-Lived Access Tokens\"\nClick \"Create Token\", name it (e.g., \"OpenClaw\")\nCopy the token immediately (shown only once)"
      },
      {
        "title": "3. Test Connection",
        "body": "curl -s -H \"Authorization: Bearer $HA_TOKEN\" \"$HA_URL/api/\" | jq\n\nOr with the CLI wrapper:\n\nscripts/ha.sh info"
      },
      {
        "title": "4. Generate Entity Inventory (Recommended, requires Node.js)",
        "body": "Note: Node.js is an optional dependency, only needed for inventory.js.\nIf Node.js is not available, ha.sh inventory falls back to a curl+jq listing.\n\nnode scripts/inventory.js\n\nThis generates ENTITIES.md with all entities organized by domain, including name, area,\nand current state. Read ENTITIES.md before acting on devices to know what is available."
      },
      {
        "title": "5. Docker / Container Networking",
        "body": "If running inside Docker:\n\nUse IP address (recommended): http://192.168.1.100:8123\nTailscale: http://homeassistant.ts.net:8123\nAvoid mDNS in Docker: homeassistant.local often doesn't resolve\nNabu Casa: https://xxxxx.ui.nabu.casa (requires subscription)"
      },
      {
        "title": "Safety Rules",
        "body": "This skill implements a layered safety system to prevent accidental actions on\nsecurity-critical devices."
      },
      {
        "title": "Layer 1: Mandatory Confirmation (Agent Behavior)",
        "body": "Always confirm with the user before performing these actions:\n\nLocks — locking or unlocking any lock\nAlarm panels — arming or disarming\nGarage doors — opening or closing (cover.* with device_class: garage)\nSecurity automations — disabling automations related to security or safety\nCovers — opening or closing covers that control physical access (gates, barriers)\n\nNever act on security-sensitive devices without explicit user confirmation."
      },
      {
        "title": "Layer 2: Critical Action Workflow",
        "body": "For critical domains (locks, alarm panels, garage doors, covers controlling physical\naccess), follow this workflow before executing any command:\n\nIdentify the action as critical — check if the entity domain is lock, alarm_control_panel, or cover with device_class garage/gate\nInform the user and ask for confirmation — \"⚠️ Opening the garage door is a critical action. Do you want to proceed?\"\nWait for explicit confirmation — \"Yes\", \"OK\", \"Sure\", \"Do it\", or any affirmative response\nOnly then execute the command — never execute first\n\nImportant: The agent (not the script) is responsible for enforcing this confirmation\nflow. The CLI wrapper (scripts/ha.sh) checks blocked_entities.json as a hard block,\nbut interactive confirmation must be handled at the agent conversation level before\ninvoking any command on critical domains."
      },
      {
        "title": "Layer 3: Blocked Entities (Optional Configuration)",
        "body": "Users can permanently block entities by listing them in a blocked_entities.json file:\n\n{\n  \"blocked\": [\"switch.main_breaker\", \"lock.front_door\"],\n  \"notes\": \"Main breaker should never be automated. Front door is manual-only.\"\n}\n\nBlocked entities cannot be controlled under any circumstance, even with user confirmation.\nCheck this file before executing any action if it exists."
      },
      {
        "title": "CLI Wrapper",
        "body": "The scripts/ha.sh CLI provides easy access to all HA functions:\n\n# Test connection\nscripts/ha.sh info\n\n# List entities\nscripts/ha.sh list all          # all entities\nscripts/ha.sh list light        # just lights\nscripts/ha.sh list switch       # just switches\n\n# Search entities\nscripts/ha.sh search kitchen    # find entities by name\n\n# Get/set state\nscripts/ha.sh state light.living_room\nscripts/ha.sh full light.living_room    # full details with attributes\nscripts/ha.sh on light.living_room\nscripts/ha.sh on light.living_room 200  # with brightness (0-255)\nscripts/ha.sh off light.living_room\nscripts/ha.sh toggle switch.fan\n\n# Scenes & scripts\nscripts/ha.sh scene movie_night\nscripts/ha.sh script goodnight\n\n# Climate\nscripts/ha.sh climate climate.thermostat 22\n\n# Dashboard (quick status of everything)\nscripts/ha.sh dashboard\n\n# Call any service\nscripts/ha.sh call light turn_on '{\"entity_id\":\"light.room\",\"brightness\":200}'\n\n# Areas\nscripts/ha.sh areas"
      },
      {
        "title": "List all entities",
        "body": "curl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[].entity_id' | sort"
      },
      {
        "title": "List entities by domain",
        "body": "# Lights\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"light.\")) | \"\\(.entity_id): \\(.state)\"'\n\n# Sensors (with units)\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"sensor.\")) | \"\\(.entity_id): \\(.state) \\(.attributes.unit_of_measurement // \"\")\"'\n\nReplace the domain prefix (switch., light., sensor., etc.) to discover entities\nin any domain."
      },
      {
        "title": "Get single entity state",
        "body": "curl -s \"$HA_URL/api/states/ENTITY_ID\" -H \"Authorization: Bearer $HA_TOKEN\""
      },
      {
        "title": "Area & Floor Discovery",
        "body": "Use the template API to query areas, floors, and labels.\n\n# List all areas\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ areas() }}\"}'\n\n# Entities in a specific area\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ area_entities(\\\"kitchen\\\") }}\"}'\n\n# Find which area an entity belongs to\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ area_name(\\\"light.kitchen\\\") }}\"}'\n\n# List all floors and their areas\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% for floor in floors() %}{{ floor }}: {{ floor_areas(floor) }}\\n{% endfor %}\"}'"
      },
      {
        "title": "Switches",
        "body": "# Turn on\ncurl -s -X POST \"$HA_URL/api/services/switch/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"switch.office_lamp\"}'\n\n# Turn off\ncurl -s -X POST \"$HA_URL/api/services/switch/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"switch.office_lamp\"}'\n\n# Toggle\ncurl -s -X POST \"$HA_URL/api/services/switch/toggle\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"switch.office_lamp\"}'"
      },
      {
        "title": "Lights",
        "body": "# Turn on with brightness (percentage)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"brightness_pct\": 80}'\n\n# Turn on with color (RGB)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"rgb_color\": [255, 150, 50]}'\n\n# Turn on with color temperature (mireds, 153-500)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"color_temp\": 300}'\n\n# Turn on with transition (seconds)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"brightness_pct\": 100, \"transition\": 3}'\n\n# Turn off\ncurl -s -X POST \"$HA_URL/api/services/light/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\"}'"
      },
      {
        "title": "Scenes",
        "body": "curl -s -X POST \"$HA_URL/api/services/scene/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"scene.movie_time\"}'"
      },
      {
        "title": "Scripts",
        "body": "# List all scripts\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"script.\")) | \"\\(.entity_id): \\(.state)\"'\n\n# Run a script\ncurl -s -X POST \"$HA_URL/api/services/script/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"script.bedtime_routine\"}'\n\n# Run a script with variables\ncurl -s -X POST \"$HA_URL/api/services/script/bedtime_routine\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"variables\": {\"brightness\": 20, \"delay_minutes\": 5}}'"
      },
      {
        "title": "Automations",
        "body": "# List all automations\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"automation.\")) | \"\\(.entity_id): \\(.state)\"'\n\n# Trigger an automation\ncurl -s -X POST \"$HA_URL/api/services/automation/trigger\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"automation.morning_routine\"}'\n\n# Enable / Disable automation\ncurl -s -X POST \"$HA_URL/api/services/automation/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"automation.morning_routine\"}'\n\ncurl -s -X POST \"$HA_URL/api/services/automation/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"automation.morning_routine\"}'"
      },
      {
        "title": "Climate Control",
        "body": "# Get thermostat state\ncurl -s \"$HA_URL/api/states/climate.thermostat\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '{state: .state, current_temp: .attributes.current_temperature, target_temp: .attributes.temperature}'\n\n# Set temperature\ncurl -s -X POST \"$HA_URL/api/services/climate/set_temperature\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"climate.thermostat\", \"temperature\": 22}'\n\n# Set HVAC mode (heat, cool, auto, off)\ncurl -s -X POST \"$HA_URL/api/services/climate/set_hvac_mode\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"climate.thermostat\", \"hvac_mode\": \"auto\"}'\n\n# Set preset mode (away, home, sleep, etc.)\ncurl -s -X POST \"$HA_URL/api/services/climate/set_preset_mode\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"climate.thermostat\", \"preset_mode\": \"away\"}'"
      },
      {
        "title": "Covers (Blinds, Garage Doors)",
        "body": "Safety: Confirm with the user before opening/closing garage doors or gates.\n\n# Open\ncurl -s -X POST \"$HA_URL/api/services/cover/open_cover\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.garage_door\"}'\n\n# Close\ncurl -s -X POST \"$HA_URL/api/services/cover/close_cover\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.garage_door\"}'\n\n# Set position (0 = closed, 100 = open)\ncurl -s -X POST \"$HA_URL/api/services/cover/set_cover_position\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.blinds\", \"position\": 50}'\n\n# Stop\ncurl -s -X POST \"$HA_URL/api/services/cover/stop_cover\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.blinds\"}'"
      },
      {
        "title": "Locks",
        "body": "Safety: Always confirm with the user before locking/unlocking.\n\n# Lock\ncurl -s -X POST \"$HA_URL/api/services/lock/lock\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"lock.front_door\"}'\n\n# Unlock\ncurl -s -X POST \"$HA_URL/api/services/lock/unlock\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"lock.front_door\"}'"
      },
      {
        "title": "Fans",
        "body": "# Turn on with speed percentage\ncurl -s -X POST \"$HA_URL/api/services/fan/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"fan.bedroom\", \"percentage\": 50}'\n\n# Turn off\ncurl -s -X POST \"$HA_URL/api/services/fan/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"fan.bedroom\"}'"
      },
      {
        "title": "Media Players",
        "body": "# Play/pause\ncurl -s -X POST \"$HA_URL/api/services/media_player/media_play_pause\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"media_player.living_room_tv\"}'\n\n# Set volume (0.0 to 1.0)\ncurl -s -X POST \"$HA_URL/api/services/media_player/volume_set\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"media_player.living_room_tv\", \"volume_level\": 0.5}'\n\n# Play media\ncurl -s -X POST \"$HA_URL/api/services/media_player/play_media\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"media_player.tv\", \"media_content_id\": \"https://example.com/stream\", \"media_content_type\": \"music\"}'"
      },
      {
        "title": "Vacuum",
        "body": "# Start cleaning\ncurl -s -X POST \"$HA_URL/api/services/vacuum/start\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"vacuum.robot\"}'\n\n# Return to dock\ncurl -s -X POST \"$HA_URL/api/services/vacuum/return_to_base\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"vacuum.robot\"}'"
      },
      {
        "title": "Alarm Control Panel",
        "body": "Safety: Always confirm with the user before arming/disarming.\n\n# Arm (home mode)\ncurl -s -X POST \"$HA_URL/api/services/alarm_control_panel/alarm_arm_home\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"alarm_control_panel.home\"}'\n\n# Arm (away mode)\ncurl -s -X POST \"$HA_URL/api/services/alarm_control_panel/alarm_arm_away\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"alarm_control_panel.home\"}'\n\n# Disarm (requires code if configured)\ncurl -s -X POST \"$HA_URL/api/services/alarm_control_panel/alarm_disarm\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"alarm_control_panel.home\", \"code\": \"1234\"}'"
      },
      {
        "title": "Notifications",
        "body": "# List available notification targets\ncurl -s \"$HA_URL/api/services\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.domain == \"notify\") | .services | keys[]' | sort\n\n# Send a notification to a mobile device\ncurl -s -X POST \"$HA_URL/api/services/notify/mobile_app_phone\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"Front door opened\", \"title\": \"Home Alert\"}'\n\n# Send to all devices (default notify service)\ncurl -s -X POST \"$HA_URL/api/services/notify/notify\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"System alert\", \"title\": \"Home Assistant\"}'\n\nReplace mobile_app_phone with the actual service name from the list command."
      },
      {
        "title": "Person & Presence",
        "body": "# Who is home?\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"person.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\"'\n\n# Device tracker locations\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"device_tracker.\")) | \"\\(.entity_id): \\(.state)\"'\n\nStates: home, not_home, or a zone name."
      },
      {
        "title": "Weather",
        "body": "# Current weather\ncurl -s \"$HA_URL/api/states/weather.home\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '{state: .state, temperature: .attributes.temperature, humidity: .attributes.humidity, wind_speed: .attributes.wind_speed}'\n\n# Get forecast (daily)\ncurl -s -X POST \"$HA_URL/api/services/weather/get_forecasts\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"weather.home\", \"type\": \"daily\"}'\n\n# Get forecast (hourly)\ncurl -s -X POST \"$HA_URL/api/services/weather/get_forecasts\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"weather.home\", \"type\": \"hourly\"}'"
      },
      {
        "title": "Input Helpers",
        "body": "# Toggle an input boolean\ncurl -s -X POST \"$HA_URL/api/services/input_boolean/toggle\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_boolean.guest_mode\"}'\n\n# Set input number\ncurl -s -X POST \"$HA_URL/api/services/input_number/set_value\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_number.target_temperature\", \"value\": 72}'\n\n# Set input select\ncurl -s -X POST \"$HA_URL/api/services/input_select/select_option\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_select.house_mode\", \"option\": \"Away\"}'\n\n# Set input text\ncurl -s -X POST \"$HA_URL/api/services/input_text/set_value\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_text.welcome_message\", \"value\": \"Welcome home!\"}'\n\n# Set input datetime\ncurl -s -X POST \"$HA_URL/api/services/input_datetime/set_datetime\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_datetime.alarm_time\", \"time\": \"07:30:00\"}'"
      },
      {
        "title": "Calendar",
        "body": "# List all calendars\ncurl -s \"$HA_URL/api/calendars\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[].entity_id'\n\n# Get upcoming events (next 7 days)\nSTART=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\nEND=$(date -u -d \"+7 days\" +%Y-%m-%dT%H:%M:%S.000Z 2>/dev/null || date -u -v+7d +%Y-%m-%dT%H:%M:%S.000Z)\ncurl -s \"$HA_URL/api/calendars/calendar.personal?start=$START&end=$END\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '[.[] | {summary: .summary, start: .start.dateTime, end: .end.dateTime}]'"
      },
      {
        "title": "Text-to-Speech",
        "body": "curl -s -X POST \"$HA_URL/api/services/tts/speak\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"tts.google_en\", \"media_player_entity_id\": \"media_player.living_room_speaker\", \"message\": \"Dinner is ready\"}'\n\nReplace tts.google_en with your TTS entity and the media player with the target speaker."
      },
      {
        "title": "Call Any Service",
        "body": "The general pattern for any HA service:\n\ncurl -s -X POST \"$HA_URL/api/services/{domain}/{service}\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"domain.entity_name\", ...}'"
      },
      {
        "title": "Batch operations",
        "body": "Control multiple entities in one call by passing an array of entity IDs:\n\ncurl -s -X POST \"$HA_URL/api/services/light/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": [\"light.living_room\", \"light.kitchen\", \"light.bedroom\"]}'"
      },
      {
        "title": "Template Evaluation",
        "body": "The /api/template endpoint evaluates Jinja2 templates server-side. Useful for computed\nqueries that go beyond simple state reads.\n\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"TEMPLATE_STRING\"}'"
      },
      {
        "title": "Examples",
        "body": "# Count entities by domain\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ states.light | list | count }} lights\"}'\n\n# List all entities that are \"on\"\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ states | selectattr(\\\"state\\\", \\\"eq\\\", \\\"on\\\") | map(attribute=\\\"entity_id\\\") | list }}\"}'\n\n# Entities in an area filtered by domain\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ area_entities(\\\"kitchen\\\") | select(\\\"match\\\", \\\"light.\\\") | list }}\"}'\n\nAvailable template functions: states(), is_state(), state_attr(), areas(),\narea_entities(), area_name(), floors(), floor_areas(), labels(),\nlabel_entities(), devices(), device_entities(), now(), relative_time()."
      },
      {
        "title": "Entity state history",
        "body": "# Last 24 hours for a specific entity\ncurl -s \"$HA_URL/api/history/period?filter_entity_id=sensor.temperature\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[0] | [.[] | {state: .state, last_changed: .last_changed}]'\n\n# Specific time range (ISO 8601)\ncurl -s \"$HA_URL/api/history/period/2025-01-15T00:00:00Z?end_time=2025-01-15T23:59:59Z&filter_entity_id=sensor.temperature\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[0]'"
      },
      {
        "title": "Logbook",
        "body": "# Recent logbook entries\ncurl -s \"$HA_URL/api/logbook\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[:10]'\n\n# Logbook for a specific entity\ncurl -s \"$HA_URL/api/logbook?entity=light.living_room\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[:10] | [.[] | {name: .name, message: .message, when: .when}]'"
      },
      {
        "title": "Dashboard Overview",
        "body": "Quick status of all active devices:\n\n# All lights that are on\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"light.\")) | select(.state == \"on\") | .entity_id'\n\n# All open doors/windows (binary sensors)\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"binary_sensor.\")) | select(.state == \"on\") | select(.attributes.device_class == \"door\" or .attributes.device_class == \"window\") | .entity_id'\n\n# Temperature sensors\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"sensor.\")) | select(.attributes.device_class == \"temperature\") | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\\(.attributes.unit_of_measurement // \"\")\"'\n\n# Climate summary\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"climate.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state), current: \\(.attributes.current_temperature)°, target: \\(.attributes.temperature)°\"'\n\n# Lock status\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"lock.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\"'\n\n# Who is home\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"person.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\"'"
      },
      {
        "title": "Inbound Webhooks (HA → Agent)",
        "body": "To receive events from Home Assistant automations:"
      },
      {
        "title": "1. Define REST Command in HA",
        "body": "# configuration.yaml\nrest_command:\n  notify_agent:\n    url: \"https://your-agent-url/webhook/home-assistant\"\n    method: POST\n    headers:\n      Authorization: \"Bearer {{ webhook_secret }}\"\n      Content-Type: \"application/json\"\n    payload: '{\"event\": \"{{ event }}\", \"area\": \"{{ area }}\", \"entity\": \"{{ entity }}\"}'"
      },
      {
        "title": "2. Create HA Automation with Webhook Action",
        "body": "# automations.yaml\n- alias: \"Notify agent on motion\"\n  trigger:\n    - platform: state\n      entity_id: binary_sensor.motion_hallway\n      to: \"on\"\n  action:\n    - service: rest_command.notify_agent\n      data:\n        event: motion_detected\n        area: hallway\n        entity: binary_sensor.motion_hallway"
      },
      {
        "title": "3. Handle in Agent",
        "body": "The agent receives the webhook POST and can notify the user or take action based on\nthe event type and data.\n\nFor complete webhook setup, see references/webhooks.md."
      },
      {
        "title": "Check API connectivity",
        "body": "curl -s -o /dev/null -w \"%{http_code}\" \"$HA_URL/api/\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\"\n# Expect: 200"
      },
      {
        "title": "Verify entity exists before acting",
        "body": "HTTP_CODE=$(curl -s -o /dev/null -w \"%{http_code}\" \\\n  \"$HA_URL/api/states/light.nonexistent\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\")\n# 200 = exists, 404 = not found"
      },
      {
        "title": "HTTP status codes",
        "body": "CodeMeaning200Success400Bad request (malformed JSON or invalid service data)401Unauthorized (bad or missing token)404Entity or endpoint not found405Method not allowed (wrong HTTP method)503Home Assistant is starting up or unavailable"
      },
      {
        "title": "Response Format",
        "body": "Service calls return an array of state objects for affected entities:\n\n[{\"entity_id\": \"light.living_room\", \"state\": \"on\", \"attributes\": {...}, \"last_changed\": \"...\"}]\n\nSuccessful call with no state change: returns [] (empty array)\nState read (/api/states/...): returns a single state object\nErrors: returns {\"message\": \"...\"} with an HTTP error code\n\nFor more troubleshooting, see references/troubleshooting.md."
      },
      {
        "title": "Entity Domains",
        "body": "DomainExamplesswitch.*Smart plugs, generic switcheslight.*Lights (Hue, LIFX, etc.)scene.*Pre-configured scenesscript.*Reusable action sequencesautomation.*Automationsclimate.*Thermostats, AC unitscover.*Blinds, garage doors, gateslock.*Smart locksfan.*Fans, ventilationmedia_player.*TVs, speakers, streaming devicesvacuum.*Robot vacuumsalarm_control_panel.*Security systemsnotify.*Notification targetsperson.*People / presence trackingdevice_tracker.*Device locationsweather.*Weather conditions and forecastscalendar.*Calendar eventstts.*Text-to-speech enginessensor.*Temperature, humidity, power, etc.binary_sensor.*Motion, door/window, presenceinput_boolean.*Virtual togglesinput_number.*Numeric slidersinput_select.*Dropdown selectorsinput_text.*Text inputsinput_datetime.*Date/time inputs"
      },
      {
        "title": "Notes",
        "body": "API returns JSON by default\nLong-lived tokens don't expire — store securely\nTest entity IDs with the list command first\nFor locks, alarms, and garage doors — always confirm actions with the user\nUse scripts/inventory.js to generate a full entity map before first use\nCheck blocked_entities.json if it exists before acting on any entity\nFor complete API reference, see references/api.md"
      }
    ],
    "body": "ha-ultimate — Definitive Home Assistant Skill\n\nControl your smart home via the Home Assistant REST API with safety enforcement, inventory awareness, and full domain coverage.\n\nSetup\n1. Environment Variables\nexport HA_URL=\"http://your-ha-instance:8123\"\nexport HA_TOKEN=\"your-long-lived-access-token\"\n\n\nOr create a .env file in the skill directory (auto-loaded by ha.sh):\n\nHA_URL=http://192.168.1.100:8123\nHA_TOKEN=eyJ...your-token...\n\n\nThe CLI wrapper also checks $HOME/.config/homeassistant/config.json as a fallback (JSON with url and token keys). Protect this file with restrictive permissions (chmod 600) since it may contain your token.\n\n2. Getting a Long-Lived Access Token\nOpen Home Assistant → Profile (bottom left)\nScroll to \"Long-Lived Access Tokens\"\nClick \"Create Token\", name it (e.g., \"OpenClaw\")\nCopy the token immediately (shown only once)\n3. Test Connection\ncurl -s -H \"Authorization: Bearer $HA_TOKEN\" \"$HA_URL/api/\" | jq\n\n\nOr with the CLI wrapper:\n\nscripts/ha.sh info\n\n4. Generate Entity Inventory (Recommended, requires Node.js)\n\nNote: Node.js is an optional dependency, only needed for inventory.js. If Node.js is not available, ha.sh inventory falls back to a curl+jq listing.\n\nnode scripts/inventory.js\n\n\nThis generates ENTITIES.md with all entities organized by domain, including name, area, and current state. Read ENTITIES.md before acting on devices to know what is available.\n\n5. Docker / Container Networking\n\nIf running inside Docker:\n\nUse IP address (recommended): http://192.168.1.100:8123\nTailscale: http://homeassistant.ts.net:8123\nAvoid mDNS in Docker: homeassistant.local often doesn't resolve\nNabu Casa: https://xxxxx.ui.nabu.casa (requires subscription)\nSafety Rules\n\nThis skill implements a layered safety system to prevent accidental actions on security-critical devices.\n\nLayer 1: Mandatory Confirmation (Agent Behavior)\n\nAlways confirm with the user before performing these actions:\n\nLocks — locking or unlocking any lock\nAlarm panels — arming or disarming\nGarage doors — opening or closing (cover.* with device_class: garage)\nSecurity automations — disabling automations related to security or safety\nCovers — opening or closing covers that control physical access (gates, barriers)\n\nNever act on security-sensitive devices without explicit user confirmation.\n\nLayer 2: Critical Action Workflow\n\nFor critical domains (locks, alarm panels, garage doors, covers controlling physical access), follow this workflow before executing any command:\n\nIdentify the action as critical — check if the entity domain is lock, alarm_control_panel, or cover with device_class garage/gate\nInform the user and ask for confirmation — \"⚠️ Opening the garage door is a critical action. Do you want to proceed?\"\nWait for explicit confirmation — \"Yes\", \"OK\", \"Sure\", \"Do it\", or any affirmative response\nOnly then execute the command — never execute first\n\nImportant: The agent (not the script) is responsible for enforcing this confirmation flow. The CLI wrapper (scripts/ha.sh) checks blocked_entities.json as a hard block, but interactive confirmation must be handled at the agent conversation level before invoking any command on critical domains.\n\nLayer 3: Blocked Entities (Optional Configuration)\n\nUsers can permanently block entities by listing them in a blocked_entities.json file:\n\n{\n  \"blocked\": [\"switch.main_breaker\", \"lock.front_door\"],\n  \"notes\": \"Main breaker should never be automated. Front door is manual-only.\"\n}\n\n\nBlocked entities cannot be controlled under any circumstance, even with user confirmation. Check this file before executing any action if it exists.\n\nCLI Wrapper\n\nThe scripts/ha.sh CLI provides easy access to all HA functions:\n\n# Test connection\nscripts/ha.sh info\n\n# List entities\nscripts/ha.sh list all          # all entities\nscripts/ha.sh list light        # just lights\nscripts/ha.sh list switch       # just switches\n\n# Search entities\nscripts/ha.sh search kitchen    # find entities by name\n\n# Get/set state\nscripts/ha.sh state light.living_room\nscripts/ha.sh full light.living_room    # full details with attributes\nscripts/ha.sh on light.living_room\nscripts/ha.sh on light.living_room 200  # with brightness (0-255)\nscripts/ha.sh off light.living_room\nscripts/ha.sh toggle switch.fan\n\n# Scenes & scripts\nscripts/ha.sh scene movie_night\nscripts/ha.sh script goodnight\n\n# Climate\nscripts/ha.sh climate climate.thermostat 22\n\n# Dashboard (quick status of everything)\nscripts/ha.sh dashboard\n\n# Call any service\nscripts/ha.sh call light turn_on '{\"entity_id\":\"light.room\",\"brightness\":200}'\n\n# Areas\nscripts/ha.sh areas\n\nEntity Discovery\nList all entities\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[].entity_id' | sort\n\nList entities by domain\n# Lights\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"light.\")) | \"\\(.entity_id): \\(.state)\"'\n\n# Sensors (with units)\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"sensor.\")) | \"\\(.entity_id): \\(.state) \\(.attributes.unit_of_measurement // \"\")\"'\n\n\nReplace the domain prefix (switch., light., sensor., etc.) to discover entities in any domain.\n\nGet single entity state\ncurl -s \"$HA_URL/api/states/ENTITY_ID\" -H \"Authorization: Bearer $HA_TOKEN\"\n\nArea & Floor Discovery\n\nUse the template API to query areas, floors, and labels.\n\n# List all areas\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ areas() }}\"}'\n\n# Entities in a specific area\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ area_entities(\\\"kitchen\\\") }}\"}'\n\n# Find which area an entity belongs to\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ area_name(\\\"light.kitchen\\\") }}\"}'\n\n# List all floors and their areas\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% for floor in floors() %}{{ floor }}: {{ floor_areas(floor) }}\\n{% endfor %}\"}'\n\nSwitches\n# Turn on\ncurl -s -X POST \"$HA_URL/api/services/switch/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"switch.office_lamp\"}'\n\n# Turn off\ncurl -s -X POST \"$HA_URL/api/services/switch/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"switch.office_lamp\"}'\n\n# Toggle\ncurl -s -X POST \"$HA_URL/api/services/switch/toggle\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"switch.office_lamp\"}'\n\nLights\n# Turn on with brightness (percentage)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"brightness_pct\": 80}'\n\n# Turn on with color (RGB)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"rgb_color\": [255, 150, 50]}'\n\n# Turn on with color temperature (mireds, 153-500)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"color_temp\": 300}'\n\n# Turn on with transition (seconds)\ncurl -s -X POST \"$HA_URL/api/services/light/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\", \"brightness_pct\": 100, \"transition\": 3}'\n\n# Turn off\ncurl -s -X POST \"$HA_URL/api/services/light/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"light.living_room\"}'\n\nScenes\ncurl -s -X POST \"$HA_URL/api/services/scene/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"scene.movie_time\"}'\n\nScripts\n# List all scripts\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"script.\")) | \"\\(.entity_id): \\(.state)\"'\n\n# Run a script\ncurl -s -X POST \"$HA_URL/api/services/script/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"script.bedtime_routine\"}'\n\n# Run a script with variables\ncurl -s -X POST \"$HA_URL/api/services/script/bedtime_routine\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"variables\": {\"brightness\": 20, \"delay_minutes\": 5}}'\n\nAutomations\n# List all automations\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"automation.\")) | \"\\(.entity_id): \\(.state)\"'\n\n# Trigger an automation\ncurl -s -X POST \"$HA_URL/api/services/automation/trigger\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"automation.morning_routine\"}'\n\n# Enable / Disable automation\ncurl -s -X POST \"$HA_URL/api/services/automation/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"automation.morning_routine\"}'\n\ncurl -s -X POST \"$HA_URL/api/services/automation/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"automation.morning_routine\"}'\n\nClimate Control\n# Get thermostat state\ncurl -s \"$HA_URL/api/states/climate.thermostat\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '{state: .state, current_temp: .attributes.current_temperature, target_temp: .attributes.temperature}'\n\n# Set temperature\ncurl -s -X POST \"$HA_URL/api/services/climate/set_temperature\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"climate.thermostat\", \"temperature\": 22}'\n\n# Set HVAC mode (heat, cool, auto, off)\ncurl -s -X POST \"$HA_URL/api/services/climate/set_hvac_mode\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"climate.thermostat\", \"hvac_mode\": \"auto\"}'\n\n# Set preset mode (away, home, sleep, etc.)\ncurl -s -X POST \"$HA_URL/api/services/climate/set_preset_mode\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"climate.thermostat\", \"preset_mode\": \"away\"}'\n\nCovers (Blinds, Garage Doors)\n\nSafety: Confirm with the user before opening/closing garage doors or gates.\n\n# Open\ncurl -s -X POST \"$HA_URL/api/services/cover/open_cover\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.garage_door\"}'\n\n# Close\ncurl -s -X POST \"$HA_URL/api/services/cover/close_cover\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.garage_door\"}'\n\n# Set position (0 = closed, 100 = open)\ncurl -s -X POST \"$HA_URL/api/services/cover/set_cover_position\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.blinds\", \"position\": 50}'\n\n# Stop\ncurl -s -X POST \"$HA_URL/api/services/cover/stop_cover\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"cover.blinds\"}'\n\nLocks\n\nSafety: Always confirm with the user before locking/unlocking.\n\n# Lock\ncurl -s -X POST \"$HA_URL/api/services/lock/lock\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"lock.front_door\"}'\n\n# Unlock\ncurl -s -X POST \"$HA_URL/api/services/lock/unlock\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"lock.front_door\"}'\n\nFans\n# Turn on with speed percentage\ncurl -s -X POST \"$HA_URL/api/services/fan/turn_on\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"fan.bedroom\", \"percentage\": 50}'\n\n# Turn off\ncurl -s -X POST \"$HA_URL/api/services/fan/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"fan.bedroom\"}'\n\nMedia Players\n# Play/pause\ncurl -s -X POST \"$HA_URL/api/services/media_player/media_play_pause\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"media_player.living_room_tv\"}'\n\n# Set volume (0.0 to 1.0)\ncurl -s -X POST \"$HA_URL/api/services/media_player/volume_set\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"media_player.living_room_tv\", \"volume_level\": 0.5}'\n\n# Play media\ncurl -s -X POST \"$HA_URL/api/services/media_player/play_media\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"media_player.tv\", \"media_content_id\": \"https://example.com/stream\", \"media_content_type\": \"music\"}'\n\nVacuum\n# Start cleaning\ncurl -s -X POST \"$HA_URL/api/services/vacuum/start\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"vacuum.robot\"}'\n\n# Return to dock\ncurl -s -X POST \"$HA_URL/api/services/vacuum/return_to_base\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"vacuum.robot\"}'\n\nAlarm Control Panel\n\nSafety: Always confirm with the user before arming/disarming.\n\n# Arm (home mode)\ncurl -s -X POST \"$HA_URL/api/services/alarm_control_panel/alarm_arm_home\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"alarm_control_panel.home\"}'\n\n# Arm (away mode)\ncurl -s -X POST \"$HA_URL/api/services/alarm_control_panel/alarm_arm_away\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"alarm_control_panel.home\"}'\n\n# Disarm (requires code if configured)\ncurl -s -X POST \"$HA_URL/api/services/alarm_control_panel/alarm_disarm\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"alarm_control_panel.home\", \"code\": \"1234\"}'\n\nNotifications\n# List available notification targets\ncurl -s \"$HA_URL/api/services\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.domain == \"notify\") | .services | keys[]' | sort\n\n# Send a notification to a mobile device\ncurl -s -X POST \"$HA_URL/api/services/notify/mobile_app_phone\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"Front door opened\", \"title\": \"Home Alert\"}'\n\n# Send to all devices (default notify service)\ncurl -s -X POST \"$HA_URL/api/services/notify/notify\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"System alert\", \"title\": \"Home Assistant\"}'\n\n\nReplace mobile_app_phone with the actual service name from the list command.\n\nPerson & Presence\n# Who is home?\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"person.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\"'\n\n# Device tracker locations\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"device_tracker.\")) | \"\\(.entity_id): \\(.state)\"'\n\n\nStates: home, not_home, or a zone name.\n\nWeather\n# Current weather\ncurl -s \"$HA_URL/api/states/weather.home\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '{state: .state, temperature: .attributes.temperature, humidity: .attributes.humidity, wind_speed: .attributes.wind_speed}'\n\n# Get forecast (daily)\ncurl -s -X POST \"$HA_URL/api/services/weather/get_forecasts\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"weather.home\", \"type\": \"daily\"}'\n\n# Get forecast (hourly)\ncurl -s -X POST \"$HA_URL/api/services/weather/get_forecasts\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"weather.home\", \"type\": \"hourly\"}'\n\nInput Helpers\n# Toggle an input boolean\ncurl -s -X POST \"$HA_URL/api/services/input_boolean/toggle\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_boolean.guest_mode\"}'\n\n# Set input number\ncurl -s -X POST \"$HA_URL/api/services/input_number/set_value\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_number.target_temperature\", \"value\": 72}'\n\n# Set input select\ncurl -s -X POST \"$HA_URL/api/services/input_select/select_option\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_select.house_mode\", \"option\": \"Away\"}'\n\n# Set input text\ncurl -s -X POST \"$HA_URL/api/services/input_text/set_value\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_text.welcome_message\", \"value\": \"Welcome home!\"}'\n\n# Set input datetime\ncurl -s -X POST \"$HA_URL/api/services/input_datetime/set_datetime\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"input_datetime.alarm_time\", \"time\": \"07:30:00\"}'\n\nCalendar\n# List all calendars\ncurl -s \"$HA_URL/api/calendars\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[].entity_id'\n\n# Get upcoming events (next 7 days)\nSTART=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\nEND=$(date -u -d \"+7 days\" +%Y-%m-%dT%H:%M:%S.000Z 2>/dev/null || date -u -v+7d +%Y-%m-%dT%H:%M:%S.000Z)\ncurl -s \"$HA_URL/api/calendars/calendar.personal?start=$START&end=$END\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '[.[] | {summary: .summary, start: .start.dateTime, end: .end.dateTime}]'\n\nText-to-Speech\ncurl -s -X POST \"$HA_URL/api/services/tts/speak\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"tts.google_en\", \"media_player_entity_id\": \"media_player.living_room_speaker\", \"message\": \"Dinner is ready\"}'\n\n\nReplace tts.google_en with your TTS entity and the media player with the target speaker.\n\nCall Any Service\n\nThe general pattern for any HA service:\n\ncurl -s -X POST \"$HA_URL/api/services/{domain}/{service}\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": \"domain.entity_name\", ...}'\n\nBatch operations\n\nControl multiple entities in one call by passing an array of entity IDs:\n\ncurl -s -X POST \"$HA_URL/api/services/light/turn_off\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"entity_id\": [\"light.living_room\", \"light.kitchen\", \"light.bedroom\"]}'\n\nTemplate Evaluation\n\nThe /api/template endpoint evaluates Jinja2 templates server-side. Useful for computed queries that go beyond simple state reads.\n\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"TEMPLATE_STRING\"}'\n\nExamples\n# Count entities by domain\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ states.light | list | count }} lights\"}'\n\n# List all entities that are \"on\"\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ states | selectattr(\\\"state\\\", \\\"eq\\\", \\\"on\\\") | map(attribute=\\\"entity_id\\\") | list }}\"}'\n\n# Entities in an area filtered by domain\ncurl -s -X POST \"$HA_URL/api/template\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{{ area_entities(\\\"kitchen\\\") | select(\\\"match\\\", \\\"light.\\\") | list }}\"}'\n\n\nAvailable template functions: states(), is_state(), state_attr(), areas(), area_entities(), area_name(), floors(), floor_areas(), labels(), label_entities(), devices(), device_entities(), now(), relative_time().\n\nHistory & Logbook\nEntity state history\n# Last 24 hours for a specific entity\ncurl -s \"$HA_URL/api/history/period?filter_entity_id=sensor.temperature\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[0] | [.[] | {state: .state, last_changed: .last_changed}]'\n\n# Specific time range (ISO 8601)\ncurl -s \"$HA_URL/api/history/period/2025-01-15T00:00:00Z?end_time=2025-01-15T23:59:59Z&filter_entity_id=sensor.temperature\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[0]'\n\nLogbook\n# Recent logbook entries\ncurl -s \"$HA_URL/api/logbook\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[:10]'\n\n# Logbook for a specific entity\ncurl -s \"$HA_URL/api/logbook?entity=light.living_room\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq '.[:10] | [.[] | {name: .name, message: .message, when: .when}]'\n\nDashboard Overview\n\nQuick status of all active devices:\n\n# All lights that are on\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"light.\")) | select(.state == \"on\") | .entity_id'\n\n# All open doors/windows (binary sensors)\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"binary_sensor.\")) | select(.state == \"on\") | select(.attributes.device_class == \"door\" or .attributes.device_class == \"window\") | .entity_id'\n\n# Temperature sensors\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"sensor.\")) | select(.attributes.device_class == \"temperature\") | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\\(.attributes.unit_of_measurement // \"\")\"'\n\n# Climate summary\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"climate.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state), current: \\(.attributes.current_temperature)°, target: \\(.attributes.temperature)°\"'\n\n# Lock status\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"lock.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\"'\n\n# Who is home\ncurl -s \"$HA_URL/api/states\" -H \"Authorization: Bearer $HA_TOKEN\" \\\n  | jq -r '.[] | select(.entity_id | startswith(\"person.\")) | \"\\(.attributes.friendly_name // .entity_id): \\(.state)\"'\n\nInbound Webhooks (HA → Agent)\n\nTo receive events from Home Assistant automations:\n\n1. Define REST Command in HA\n# configuration.yaml\nrest_command:\n  notify_agent:\n    url: \"https://your-agent-url/webhook/home-assistant\"\n    method: POST\n    headers:\n      Authorization: \"Bearer {{ webhook_secret }}\"\n      Content-Type: \"application/json\"\n    payload: '{\"event\": \"{{ event }}\", \"area\": \"{{ area }}\", \"entity\": \"{{ entity }}\"}'\n\n2. Create HA Automation with Webhook Action\n# automations.yaml\n- alias: \"Notify agent on motion\"\n  trigger:\n    - platform: state\n      entity_id: binary_sensor.motion_hallway\n      to: \"on\"\n  action:\n    - service: rest_command.notify_agent\n      data:\n        event: motion_detected\n        area: hallway\n        entity: binary_sensor.motion_hallway\n\n3. Handle in Agent\n\nThe agent receives the webhook POST and can notify the user or take action based on the event type and data.\n\nFor complete webhook setup, see references/webhooks.md.\n\nError Handling\nCheck API connectivity\ncurl -s -o /dev/null -w \"%{http_code}\" \"$HA_URL/api/\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\"\n# Expect: 200\n\nVerify entity exists before acting\nHTTP_CODE=$(curl -s -o /dev/null -w \"%{http_code}\" \\\n  \"$HA_URL/api/states/light.nonexistent\" \\\n  -H \"Authorization: Bearer $HA_TOKEN\")\n# 200 = exists, 404 = not found\n\nHTTP status codes\nCode\tMeaning\n200\tSuccess\n400\tBad request (malformed JSON or invalid service data)\n401\tUnauthorized (bad or missing token)\n404\tEntity or endpoint not found\n405\tMethod not allowed (wrong HTTP method)\n503\tHome Assistant is starting up or unavailable\nResponse Format\n\nService calls return an array of state objects for affected entities:\n\n[{\"entity_id\": \"light.living_room\", \"state\": \"on\", \"attributes\": {...}, \"last_changed\": \"...\"}]\n\nSuccessful call with no state change: returns [] (empty array)\nState read (/api/states/...): returns a single state object\nErrors: returns {\"message\": \"...\"} with an HTTP error code\n\nFor more troubleshooting, see references/troubleshooting.md.\n\nEntity Domains\nDomain\tExamples\nswitch.*\tSmart plugs, generic switches\nlight.*\tLights (Hue, LIFX, etc.)\nscene.*\tPre-configured scenes\nscript.*\tReusable action sequences\nautomation.*\tAutomations\nclimate.*\tThermostats, AC units\ncover.*\tBlinds, garage doors, gates\nlock.*\tSmart locks\nfan.*\tFans, ventilation\nmedia_player.*\tTVs, speakers, streaming devices\nvacuum.*\tRobot vacuums\nalarm_control_panel.*\tSecurity systems\nnotify.*\tNotification targets\nperson.*\tPeople / presence tracking\ndevice_tracker.*\tDevice locations\nweather.*\tWeather conditions and forecasts\ncalendar.*\tCalendar events\ntts.*\tText-to-speech engines\nsensor.*\tTemperature, humidity, power, etc.\nbinary_sensor.*\tMotion, door/window, presence\ninput_boolean.*\tVirtual toggles\ninput_number.*\tNumeric sliders\ninput_select.*\tDropdown selectors\ninput_text.*\tText inputs\ninput_datetime.*\tDate/time inputs\nNotes\nAPI returns JSON by default\nLong-lived tokens don't expire — store securely\nTest entity IDs with the list command first\nFor locks, alarms, and garage doors — always confirm actions with the user\nUse scripts/inventory.js to generate a full entity map before first use\nCheck blocked_entities.json if it exists before acting on any entity\nFor complete API reference, see references/api.md"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Titunito/ha-ultimate",
    "publisherUrl": "https://clawhub.ai/Titunito/ha-ultimate",
    "owner": "Titunito",
    "version": "1.0.2",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ha-ultimate",
    "downloadUrl": "https://openagent3.xyz/downloads/ha-ultimate",
    "agentUrl": "https://openagent3.xyz/skills/ha-ultimate/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ha-ultimate/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ha-ultimate/agent.md"
  }
}