Skill: iahmadzain/home-assistant (version 1.0.0)

--- name: home-assistant description: Control Home Assistant smart home devices, run automations, and receive webhook events. Use when controlling lights, switches, climate, scenes, scripts, or any HA entity. Supports bidirectional communication via REST API (outbound) and webhooks (inbound triggers from HA automations). metadata: {"clawdbot":{"emoji":"🏠","requires":{"bins":["jq","curl"]}}} --- # Home Assistant Control your smart home via Home Assistant's REST API and webhooks. ## Setup ### Option 1: Config File (Recommended) Create `~/.config/home-assistant/config.json`: ```json { "url": "https://your-ha-instance.duckdns.org", "token": "your-long-lived-access-token" } ``` ### Option 2: Environment Variables ```bash export HA_URL="http://homeassistant.local:8123" export HA_TOKEN="your-long-lived-access-token" ``` ### Getting a Long-Lived Access Token 1. Open Home Assistant → Profile (bottom left) 2. Scroll to "Long-Lived Access Tokens" 3. Click "Create Token", name it (e.g., "Clawdbot") 4. Copy the token immediately (shown only once) ## Quick Reference ### List Entities ```bash curl -s -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/states" | jq '.[].entity_id' ``` ### Get Entity State ```bash curl -s -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/states/light.living_room" ``` ### Control Devices ```bash # Turn on curl -X POST -H "Authorization: Bearer $HA_TOKEN" -H "Content-Type: application/json" \ "$HA_URL/api/services/light/turn_on" -d '{"entity_id": "light.living_room"}' # Turn off curl -X POST -H "Authorization: Bearer $HA_TOKEN" -H "Content-Type: application/json" \ "$HA_URL/api/services/light/turn_off" -d '{"entity_id": "light.living_room"}' # Set brightness (0-255) curl -X POST -H "Authorization: Bearer $HA_TOKEN" -H "Content-Type: application/json" \ "$HA_URL/api/services/light/turn_on" -d '{"entity_id": "light.living_room", "brightness": 128}' ``` ### Run Scripts & Automations ```bash # Trigger script curl -X POST -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/services/script/turn_on" \ -H "Content-Type: application/json" -d '{"entity_id": "script.goodnight"}' # Trigger automation curl -X POST -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/services/automation/trigger" \ -H "Content-Type: application/json" -d '{"entity_id": "automation.motion_lights"}' ``` ### Activate Scenes ```bash curl -X POST -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/services/scene/turn_on" \ -H "Content-Type: application/json" -d '{"entity_id": "scene.movie_night"}' ``` ## Common Services | Domain | Service | Example entity_id | |--------|---------|-------------------| | `light` | `turn_on`, `turn_off`, `toggle` | `light.kitchen` | | `switch` | `turn_on`, `turn_off`, `toggle` | `switch.fan` | | `climate` | `set_temperature`, `set_hvac_mode` | `climate.thermostat` | | `cover` | `open_cover`, `close_cover`, `stop_cover` | `cover.garage` | | `media_player` | `play_media`, `media_pause`, `volume_set` | `media_player.tv` | | `scene` | `turn_on` | `scene.relax` | | `script` | `turn_on` | `script.welcome_home` | | `automation` | `trigger`, `turn_on`, `turn_off` | `automation.sunrise` | ## Inbound Webhooks (HA → Clawdbot) To receive events from Home Assistant automations: ### 1. Create HA Automation with Webhook Action ```yaml # In HA automation action: - service: rest_command.notify_clawdbot data: event: motion_detected area: living_room ``` ### 2. Define REST Command in HA ```yaml # configuration.yaml rest_command: notify_clawdbot: url: "https://your-clawdbot-url/webhook/home-assistant" method: POST headers: Authorization: "Bearer {{ webhook_secret }}" Content-Type: "application/json" payload: '{"event": "{{ event }}", "area": "{{ area }}"}' ``` ### 3. Handle in Clawdbot Clawdbot receives the webhook and can notify you or take action based on the event. ## CLI Wrapper The `scripts/ha.sh` CLI provides easy access to all HA functions: ```bash # Test connection ha.sh info # List entities ha.sh list all # all entities ha.sh list lights # just lights ha.sh list switch # just switches # Search entities ha.sh search kitchen # find entities by name # Get/set state ha.sh state light.living_room ha.sh states light.living_room # full details with attributes ha.sh on light.living_room ha.sh on light.living_room 200 # with brightness (0-255) ha.sh off light.living_room ha.sh toggle switch.fan # Scenes & scripts ha.sh scene movie_night ha.sh script goodnight # Climate ha.sh climate climate.thermostat 22 # Call any service ha.sh call light turn_on '{"entity_id":"light.room","brightness":200}' ``` ## Troubleshooting - **401 Unauthorized**: Token expired or invalid. Generate a new one. - **Connection refused**: Check HA_URL, ensure HA is running and accessible. - **Entity not found**: List entities to find the correct entity_id. ## API Reference For advanced usage, see [references/api.md](references/api.md).

path: references/api.md
content: # Home Assistant REST API Reference

## Authentication

All requests require the `Authorization` header:

```
Authorization: Bearer <long-lived-access-token>
```

## Base Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/` | GET | API status and HA version |
| `/api/config` | GET | Current configuration |
| `/api/states` | GET | All entity states |
| `/api/states/<entity_id>` | GET | Single entity state |
| `/api/states/<entity_id>` | POST | Set entity state |
| `/api/services` | GET | Available services |
| `/api/services/<domain>/<service>` | POST | Call a service |
| `/api/events` | GET | Available events |
| `/api/events/<event_type>` | POST | Fire an event |
| `/api/history/period/<timestamp>` | GET | State history |
| `/api/logbook/<timestamp>` | GET | Logbook entries |

## Common Services

### Lights

```bash
# Turn on with options
POST /api/services/light/turn_on
{
  "entity_id": "light.living_room",
  "brightness": 255,           # 0-255
  "color_temp": 370,           # Mireds (153-500 typically)
  "rgb_color": [255, 0, 0],    # RGB array
  "transition": 2              # Seconds
}

# Turn off
POST /api/services/light/turn_off
{"entity_id": "light.living_room"}
```

### Climate

```bash
# Set temperature
POST /api/services/climate/set_temperature
{
  "entity_id": "climate.thermostat",
  "temperature": 22,
  "hvac_mode": "heat"  # heat, cool, auto, off
}

# Set preset
POST /api/services/climate/set_preset_mode
{
  "entity_id": "climate.thermostat",
  "preset_mode": "away"
}
```

### Media Player

```bash
# Play/pause
POST /api/services/media_player/media_play_pause
{"entity_id": "media_player.tv"}

# Set volume (0.0-1.0)
POST /api/services/media_player/volume_set
{"entity_id": "media_player.tv", "volume_level": 0.5}

# Play media
POST /api/services/media_player/play_media
{
  "entity_id": "media_player.tv",
  "media_content_type": "music",
  "media_content_id": "spotify:playlist:xyz"
}
```

### Cover (Blinds/Garage)

```bash
POST /api/services/cover/open_cover
{"entity_id": "cover.garage"}

POST /api/services/cover/close_cover
{"entity_id": "cover.garage"}

POST /api/services/cover/set_cover_position
{"entity_id": "cover.blinds", "position": 50}  # 0=closed, 100=open
```

### Notifications

```bash
POST /api/services/notify/mobile_app_phone
{
  "message": "Motion detected!",
  "title": "Security Alert",
  "data": {
    "image": "/local/camera_snapshot.jpg"
  }
}
```

## Entity State Object

```json
{
  "entity_id": "light.living_room",
  "state": "on",
  "attributes": {
    "brightness": 255,
    "color_temp": 370,
    "friendly_name": "Living Room Light",
    "supported_features": 63
  },
  "last_changed": "2024-01-15T10:30:00+00:00",
  "last_updated": "2024-01-15T10:30:00+00:00"
}
```

## Webhooks (Inbound to HA)

Trigger automations via webhook:

```bash
POST /api/webhook/<webhook_id>
{"custom": "data"}
```

Create webhook trigger in automation:

```yaml
automation:
  trigger:
    - platform: webhook
      webhook_id: my_webhook_id
      allowed_methods:
        - POST
```

## WebSocket API

For real-time updates, use the WebSocket API at `ws://ha-url/api/websocket`.

Connection flow:
1. Connect to WebSocket
2. Receive `auth_required`
3. Send `{"type": "auth", "access_token": "TOKEN"}`
4. Receive `auth_ok`
5. Subscribe to events: `{"id": 1, "type": "subscribe_events", "event_type": "state_changed"}`

## Error Responses

| Code | Meaning |
|------|---------|
| 400 | Bad request (invalid JSON or missing fields) |
| 401 | Unauthorized (invalid/missing token) |
| 404 | Entity or service not found |
| 405 | Method not allowed |

## Rate Limits

Home Assistant doesn't enforce strict rate limits, but avoid:
- Polling faster than every 1 second
- Bulk updates without batching

Use WebSocket for real-time state tracking instead of polling.


path: scripts/ha.sh
content: #!/usr/bin/env bash
# Home Assistant CLI wrapper
# Usage: ha.sh <command> [args...]

set -euo pipefail

CONFIG_FILE="${HA_CONFIG:-$HOME/.config/home-assistant/config.json}"

# Load config
if [[ -f "$CONFIG_FILE" ]]; then
  HA_URL="${HA_URL:-$(jq -r '.url // empty' "$CONFIG_FILE")}"
  HA_TOKEN="${HA_TOKEN:-$(jq -r '.token // empty' "$CONFIG_FILE")}"
fi

: "${HA_URL:?Set HA_URL or configure $CONFIG_FILE}"
: "${HA_TOKEN:?Set HA_TOKEN or configure $CONFIG_FILE}"

cmd="${1:-help}"
shift || true

api() {
  curl -s -H "Authorization: Bearer $HA_TOKEN" -H "Content-Type: application/json" "$@"
}

case "$cmd" in
  state|get)
    # Get entity state: ha.sh state light.living_room
    entity="${1:?Usage: ha.sh state <entity_id>}"
    api "$HA_URL/api/states/$entity" | jq -r '.state // "unknown"'
    ;;
    
  states)
    # Get full entity state with attributes
    entity="${1:?Usage: ha.sh states <entity_id>}"
    api "$HA_URL/api/states/$entity" | jq
    ;;

  on|turn_on)
    # Turn on entity: ha.sh on light.living_room [brightness]
    entity="${1:?Usage: ha.sh on <entity_id> [brightness]}"
    domain="${entity%%.*}"
    brightness="${2:-}"
    if [[ -n "$brightness" ]]; then
      api -X POST "$HA_URL/api/services/$domain/turn_on" \
        -d "{\"entity_id\": \"$entity\", \"brightness\": $brightness}"
    else
      api -X POST "$HA_URL/api/services/$domain/turn_on" \
        -d "{\"entity_id\": \"$entity\"}"
    fi
    echo "✓ $entity turned on"
    ;;

  off|turn_off)
    # Turn off entity: ha.sh off light.living_room
    entity="${1:?Usage: ha.sh off <entity_id>}"
    domain="${entity%%.*}"
    api -X POST "$HA_URL/api/services/$domain/turn_off" \
      -d "{\"entity_id\": \"$entity\"}" >/dev/null
    echo "✓ $entity turned off"
    ;;

  toggle)
    # Toggle entity: ha.sh toggle switch.fan
    entity="${1:?Usage: ha.sh toggle <entity_id>}"
    domain="${entity%%.*}"
    api -X POST "$HA_URL/api/services/$domain/toggle" \
      -d "{\"entity_id\": \"$entity\"}" >/dev/null
    echo "✓ $entity toggled"
    ;;

  scene)
    # Activate scene: ha.sh scene movie_night
    scene="${1:?Usage: ha.sh scene <scene_name>}"
    [[ "$scene" == scene.* ]] || scene="scene.$scene"
    api -X POST "$HA_URL/api/services/scene/turn_on" \
      -d "{\"entity_id\": \"$scene\"}" >/dev/null
    echo "✓ Scene $scene activated"
    ;;

  script)
    # Run script: ha.sh script goodnight
    script="${1:?Usage: ha.sh script <script_name>}"
    [[ "$script" == script.* ]] || script="script.$script"
    api -X POST "$HA_URL/api/services/script/turn_on" \
      -d "{\"entity_id\": \"$script\"}" >/dev/null
    echo "✓ Script $script executed"
    ;;

  automation|trigger)
    # Trigger automation: ha.sh automation motion_lights
    auto="${1:?Usage: ha.sh automation <automation_name>}"
    [[ "$auto" == automation.* ]] || auto="automation.$auto"
    api -X POST "$HA_URL/api/services/automation/trigger" \
      -d "{\"entity_id\": \"$auto\"}" >/dev/null
    echo "✓ Automation $auto triggered"
    ;;

  climate|temp)
    # Set temperature: ha.sh climate climate.thermostat 22
    entity="${1:?Usage: ha.sh climate <entity_id> <temperature>}"
    temp="${2:?Usage: ha.sh climate <entity_id> <temperature>}"
    api -X POST "$HA_URL/api/services/climate/set_temperature" \
      -d "{\"entity_id\": \"$entity\", \"temperature\": $temp}" >/dev/null
    echo "✓ $entity set to ${temp}°"
    ;;

  list)
    # List entities by domain: ha.sh list lights / ha.sh list all
    filter="${1:-all}"
    if [[ "$filter" == "all" ]]; then
      api "$HA_URL/api/states" | jq -r '.[].entity_id' | sort
    else
      # Normalize: "lights" -> "light", "switches" -> "switch"
      filter="${filter%s}"
      api "$HA_URL/api/states" | jq -r --arg d "$filter" \
        '.[] | select(.entity_id | startswith($d + ".")) | .entity_id' | sort
    fi
    ;;

  search)
    # Search entities: ha.sh search kitchen
    pattern="${1:?Usage: ha.sh search <pattern>}"
    api "$HA_URL/api/states" | jq -r --arg p "$pattern" \
      '.[] | select(.entity_id | test($p; "i")) | "\(.entity_id): \(.state)"'
    ;;

  call)
    # Call any service: ha.sh call light turn_on '{"entity_id":"light.room","brightness":200}'
    domain="${1:?Usage: ha.sh call <domain> <service> [json_data]}"
    service="${2:?Usage: ha.sh call <domain> <service> [json_data]}"
    data="${3:-{}}"
    api -X POST "$HA_URL/api/services/$domain/$service" -d "$data"
    ;;

  info)
    # Get HA instance info
    api "$HA_URL/api/" | jq
    ;;

  help|*)
    cat <<EOF
Home Assistant CLI

Usage: ha.sh <command> [args...]

Commands:
  state <entity>              Get entity state
  states <entity>             Get full entity state with attributes
  on <entity> [brightness]    Turn on (optional brightness 0-255)
  off <entity>                Turn off
  toggle <entity>             Toggle on/off
  scene <name>                Activate scene
  script <name>               Run script
  automation <name>           Trigger automation
  climate <entity> <temp>     Set temperature
  list [domain]               List entities (lights, switches, all)
  search <pattern>            Search entities by name
  call <domain> <svc> [json]  Call any service
  info                        Get HA instance info

Environment:
  HA_URL    Home Assistant URL (required)
  HA_TOKEN  Long-lived access token (required)

Examples:
  ha.sh on light.living_room 200
  ha.sh scene movie_night
  ha.sh list lights
  ha.sh search kitchen
EOF
    ;;
esac


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)