# hass-dashboard-agent-skill > Creates and modifies Home Assistant Lovelace dashboards using the websocket API via Chrome DevTools. Use when the user wants to create, update, or delete Home Assistant dashboards, add cards or views, or query entities for dashboard building. - Author: Josh Pearce - Repository: joshpearce/hass-dashboard-agent-skill - Version: 20260106084841 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/joshpearce/hass-dashboard-agent-skill - Web: https://mule.run/skillshub/@@joshpearce/hass-dashboard-agent-skill~hass-dashboard-agent-skill:20260106084841 --- --- name: hass-dashboard-agent-skill description: Creates and modifies Home Assistant Lovelace dashboards using the websocket API via Chrome DevTools. Use when the user wants to create, update, or delete Home Assistant dashboards, add cards or views, or query entities for dashboard building. allowed-tools: Read, Glob, Grep, mcp__chrome-devtools__* --- # Home Assistant Dashboard Creation Skill Creates and modifies Home Assistant Lovelace dashboards using the websocket API via Chrome DevTools. ## Quick Reference - [STYLE.md](STYLE.md) - **User preferences and layout recommendations** - [CARDS.md](CARDS.md) - Card types reference (tile, entities, gauge, etc.) - [VIEWS.md](VIEWS.md) - View types and layout options - [EXAMPLES.md](EXAMPLES.md) - Complete dashboard examples - [CUSTOM-CARDS.md](CUSTOM-CARDS.md) - Custom JavaScript cards for advanced layouts - [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Common errors and solutions ## Workflow ### Step 1: Get Home Assistant URL **Before doing anything else**, prompt the user for their Home Assistant URL. Do not assume or guess the URL. Example prompt: "What is your Home Assistant URL? (e.g., https://homeassistant.local:8123 or https://ha.example.com)" ### Step 2: Connect via Chrome DevTools ```javascript // Open the page mcp__chrome-devtools__new_page({ url: "" }) // Verify login mcp__chrome-devtools__take_snapshot() // Access the hass object const hass = document.querySelector('home-assistant')?.hass; ``` ### Step 3: Query Entities (if needed) ```javascript async () => { const hass = document.querySelector('home-assistant')?.hass; const entities = await hass.callWS({ type: 'config/entity_registry/list' }); const devices = await hass.callWS({ type: 'config/device_registry/list' }); const areas = await hass.callWS({ type: 'config/area_registry/list' }); // Create lookups const areaLookup = Object.fromEntries(areas.map(a => [a.area_id, a.name])); const deviceLookup = Object.fromEntries(devices.map(d => [d.id, { name: d.name_by_user || d.name, area_id: d.area_id }])); // Example: Find all lights with area info const lights = entities .filter(e => e.entity_id.startsWith('light.') && !e.disabled_by) .map(e => { const state = hass.states[e.entity_id]; let areaName = 'Unassigned'; if (e.area_id) { areaName = areaLookup[e.area_id] || 'Unassigned'; } else if (e.device_id && deviceLookup[e.device_id]) { areaName = areaLookup[deviceLookup[e.device_id].area_id] || 'Unassigned'; } return { entity_id: e.entity_id, name: state?.attributes?.friendly_name || e.entity_id, area: areaName, state: state?.state }; }); return lights; } ``` ### Step 4: Create Dashboard **CRITICAL**: The `url_path` MUST contain a hyphen (`-`). Single words like `lights` will fail. ```javascript async () => { const hass = document.querySelector('home-assistant')?.hass; // Step 1: Create dashboard in registry await hass.callWS({ type: 'lovelace/dashboards/create', url_path: 'my-dashboard', // MUST contain hyphen title: 'My Dashboard', icon: 'mdi:view-dashboard', show_in_sidebar: true, require_admin: false }); // Step 2: Save configuration await hass.callWS({ type: 'lovelace/config/save', url_path: 'my-dashboard', config: { views: [{ title: 'Home', type: 'sections', // or 'panel' for dense layouts sections: [{ type: 'grid', cards: [ { type: 'heading', heading: 'My Section' }, { type: 'tile', entity: 'light.example' } ] }] }] } }); return { success: true }; } ``` ### Step 5: Update Existing Dashboard For existing dashboards, use `lovelace/config/save` directly - no need to recreate: ```javascript await hass.callWS({ type: 'lovelace/config/save', url_path: 'existing-dashboard', config: { /* new configuration */ } }); ``` ### Step 6: Delete Dashboard ```javascript async () => { const hass = document.querySelector('home-assistant')?.hass; // List dashboards to find the ID const dashboards = await hass.callWS({ type: 'lovelace/dashboards/list' }); // Delete by ID (not url_path) await hass.callWS({ type: 'lovelace/dashboards/delete', dashboard_id: 'the_dashboard_id' }); } ``` ## Layout Strategy See [STYLE.md](STYLE.md) for detailed layout recommendations. **Quick summary:** Use `masonry` view with `entities` cards (with titles) for clear hierarchy and compact layout. ## Common Card Types | Card | Use For | |------|---------| | `tile` | Individual entities with optional controls | | `entities` | Dense lists of related items | | `heading` | Section labels | | `gauge` | Numeric sensors with visual range | | `history-graph` | Time series data | | `button` | Triggering actions/scripts | See [CARDS.md](CARDS.md) for complete reference. ## Entity Domains | Domain | Description | |--------|-------------| | `light` | Lighting devices | | `switch` | On/off devices | | `sensor` | Measurements (temp, power, etc.) | | `binary_sensor` | Two-state (motion, door, etc.) | | `climate` | Thermostats, HVAC | | `cover` | Garage doors, blinds | | `media_player` | TVs, speakers | ## Best Practices - **URL paths**: Must use kebab-case with hyphen (`all-lights`, not `lights`) - **Grouped entities**: Use `entities` card with `title` for visual hierarchy (see [STYLE.md](STYLE.md)) - **Performance**: Limit `hours_to_show` on history graphs - **Always query first**: Use entity/device/area registries before building dashboards dynamically