Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/tomevault-io/skills-registry --skill setup-customize명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | setup-customize |
| description | > Use when this capability is needed. |
This skill maps your Home Assistant instance to the dashboard and automation templates through a guided interview. It is resumable — if the conversation ends mid-way, re-invoke this skill and it will pick up from the last checkpoint.
See references/question-patterns.md for detailed question wording and example answers
for each domain.
Verify setup-state.json exists and infrastructure is complete:
import json, sys, os
if not os.path.exists('setup-state.json'):
print('NOT_READY'); sys.exit(0)
with open('setup-state.json') as f:
state = json.load(f)
schema = state.get('schema_version', 0)
if schema > 1:
print('SCHEMA_WARNING')
phase = state.get('session', {}).get('current_phase', '')
infra = state.get('infrastructure', {}).get('steps_completed', [])
if 'infrastructure_complete' in phase or 'pull' in infra:
answers = state.get('answers', {})
if answers.get('rooms') or phase.startswith('customize:'):
print('RESUME')
print(f'PHASE:{phase}')
print(f'ROOMS_DONE:{",".join(answers.get("rooms", {}).keys())}')
else:
print('FRESH')
else:
print('NOT_READY')
Run via python3 -c "..." and check the output:
NOT_READY: Tell user to run setup-infrastructure first.SCHEMA_WARNING: State file from newer version — proceed with caution.RESUME: Load checkpoint. Tell user: "Welcome back! You were at [phase]. Rooms done: [list]. Continuing."FRESH: Begin from Phase 1.After EVERY user answer, update setup-state.json with granular progress:
import json
def save_checkpoint(phase, answers_update=None, files_written=None):
with open('setup-state.json') as f:
state = json.load(f)
state['session']['current_phase'] = phase
if answers_update:
state.setdefault('answers', {}).update(answers_update)
if files_written:
state.setdefault('files_written', []).extend(files_written)
with open('setup-state.json', 'w') as f:
json.dump(state, f, indent=2)
Example calls:
save_checkpoint('customize:room_mapping', {'rooms': {'living_room': {'light': '...', 'motion': '...'}}})save_checkpoint('customize:domain_selection', {'domains_selected': ['lighting', 'climate']})save_checkpoint('customize:notifications', {'notify_targets': {'primary': 'notify.mobile_app_x'}})save_checkpoint('customize:files', files_written=['config/automations/lighting.yaml'])Primary method: Use registry data. Entity-to-room assignment should come from the
device/entity registries (via area_id) whenever possible. This is the authoritative source.
Fallback: Name inference + user confirmation. If the registries have sparse area
assignments (common in setups where the user hasn't organized areas in HA), you may infer
room assignments from entity ID naming patterns (e.g., bedroom_motion → bedroom).
However, when using name inference, you MUST:
Get the authoritative room and floor structure:
source .env && ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH:=/config/}.env; ha-ws raw config/floor_registry/list" 2>/dev/null
source .env && ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH}.env; ha-ws raw config/area_registry/list" 2>/dev/null
This gives you:
floor_id assignmentsGet the authoritative entity-to-area mappings:
source .env && ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH}.env; ha-ws raw config/device_registry/list" 2>/dev/null
source .env && ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH}.env; ha-ws raw config/entity_registry/list" 2>/dev/null
Entity-to-area resolution chain:
entity_registry → if the entity has a direct area_id, use itdevice_id → look up that device in device_registry → use the device's area_idarea_id, the entity is unassigned — note it but do NOT guessFor each relevant domain, query the live entity list:
source .env
for domain in light binary_sensor sensor climate media_player camera cover vacuum remote switch; do
ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH}.env; ha-ws entity list $domain" 2>/dev/null
done
Cross-reference the entity list with the device/entity registry area assignments to build a verified mapping. For each room, list:
binary_sensor.* with device_class: motion or occupancy)Before presenting any mapping to the user: mark each assignment's source:
area_id — present as fact? mark, ask user to confirmIf SSH/ha-ws is unavailable, parse the local .storage/ files (pulled by make pull):
source venv/bin/activate && python tools/entity_explorer.py --full 2>/dev/null | head -100
Or use the REST API as a last resort:
source .env && set -a && source .env && set +a && python3 -c "
import urllib.request, json, os
url = os.environ['HA_URL'] + '/api/states'
req = urllib.request.Request(url, headers={'Authorization': 'Bearer ' + os.environ['HA_TOKEN']})
with urllib.request.urlopen(req) as r:
states = json.load(r)
domains = {}
for s in states:
d = s['entity_id'].split('.')[0]
domains[d] = domains.get(d, 0) + 1
for d, c in sorted(domains.items()):
print(f'{d}: {c} entities')
"
Summarize what was found: "Found X floors, Y areas, Z lights, W climate entities, ..."
See references/question-patterns.md → Phase 1 for question wording.
Goal: Build a RoomConfig[] array for dashboard/src/lib/areas.ts.
setup-state.json after each room confirmation.Generate areas.ts once all rooms are confirmed:
// dashboard/src/lib/areas.ts — generated by setup-customize
export interface RoomConfig {
id: string;
name: string;
floor: number;
icon: string;
light?: string; // primary light entity
motionSensor?: string;
temperatureSensor?: string;
mediaPlayer?: string;
climate?: string;
}
export const ROOMS: RoomConfig[] = [
// REPLACE: Add your rooms here (generated from interview)
// { id: "living_room", name: "Living Room", floor: 0, icon: "sofa", light: "light.living_room" },
];
// Maps HA person entity → display name
export const USER_ROOM_MAP: Record<string, string> = {};
For each room, ask domain-specific questions:
Lights:
Climate:
Media:
Save answers to setup-state.json as you go.
Present automation domains as a checklist. Ask the user which apply to their setup:
Which automation domains do you want to set up?
□ Motion lights (auto on/off with motion sensors)
□ Activity modes (night mode, movie mode, work mode)
□ Climate scheduling (morning/night temperature changes)
□ Away mode (setback when nobody home)
□ Appliance tracking (washer/dishwasher state machine)
□ Health monitoring (integration watchdogs, battery alerts)
□ EV/Solar charging (if you have solar + EV)
□ AC solar heating (if you have solar + AC units)
□ None — I'll write my own automations
For each selected domain, note which automation template to use from
docs/templates/config/automations/.
Ask about preferences that drive automation behavior. See references/question-patterns.md
→ Phase 4 for full question bank.
Key questions:
work_mode auto-trigger)Save all answers to setup-state.json.
Discover available notification targets:
set -a && source .env && set +a && python3 -c "
import urllib.request, json, os
url = os.environ['HA_URL'] + '/api/services'
req = urllib.request.Request(url, headers={'Authorization': 'Bearer ' + os.environ['HA_TOKEN']})
with urllib.request.urlopen(req) as r:
services = json.load(r)
notify = [s for s in services if s.get('domain') == 'notify']
for n in notify:
for svc in n.get('services', {}).keys():
print(f'notify.{svc}')
" 2>/dev/null
Alternatively, use SSH + ha-api (more reliable):
source .env && ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH:=/config/}.env; ha-api search notify"
Ask the user which targets to use for:
Read existing configuration.yaml and check if it already has input_* helpers:
grep -l "input_boolean:\|input_select:\|input_number:" config/configuration.yaml 2>/dev/null && echo "has_helpers" || echo "no_helpers"
If existing helpers found: Show them and ask:
"Your
configuration.yamlalready has input helpers. I can: (A) Keep them where they are and add only missing ones from the templates (B) Consolidate all helpers intoconfig/helpers.yamland use!include helpers.yamlWhich do you prefer?"
Never silently move or overwrite existing helpers.
Based on all interview answers, generate:
dashboard/src/lib/entities.ts// dashboard/src/lib/entities.ts — generated by setup-customize
// Edit this file to update entity mappings. Re-run setup-customize to regenerate.
// ── Modes ──────────────────────────────────────────────────────────────────
export const NIGHT_MODE = "input_boolean.night_mode";
export const MOVIE_MODE = "input_boolean.movie_mode";
export const WORK_MODE = "input_boolean.work_mode";
export const AWAY_MODE = "input_boolean.away_mode";
export const CLIMATE_MODE = "input_select.your_climate_mode"; // # REPLACE: or remove
// ── People ─────────────────────────────────────────────────────────────────
// Add your person entity IDs here
export const PERSONS: string[] = [];
// ── Add your entities below ────────────────────────────────────────────────
// (Generated from interview answers — each room's entities added here)
For each selected domain, copy the template and substitute placeholder IDs:
your_room_motion_sensor → actual entity ID from interviewyour_notify_target → chosen notification targetyour_morning_work_day (input_datetime) → keep as-is (user sets value in HA UI)Copy template files to config/automations/:
# Example for lighting:
cp docs/templates/config/automations/lighting.yaml config/automations/lighting.yaml
# Then perform substitutions based on interview answers
docs/system-overview.md and docs/house-rules.mdPopulate the template sections with interview answers. Leave blank sections with the original guidance comments for sections not covered.
Install dashboard dependencies (if not already installed):
cd dashboard && npm install && cd ..
Verify TypeScript compiles cleanly before deploying:
cd dashboard && npx tsc -b --noEmit && cd ..
If this fails, fix the errors before proceeding. Common issues:
"" as EntityId need actual entity IDs or removal@types/* packages → run npm install firstRun backup:
make backup
Push configuration:
make push
Deploy dashboard:
make deploy-dashboard
Verify by asking the user to open HA and confirm the dashboard panel appears.
Provide the URL: http://[HA_URL]/custom-dashboard
After the dashboard deploys successfully, ask the user:
"Would you like to make this dashboard your default view when opening Home Assistant? This requires installing the Custom Sidebar plugin via HACS. If you don't have HACS, you can skip this — your dashboard is still accessible from the sidebar."
If the user wants this:
Verify HACS is installed:
source .env && ssh "$SSH_USER@$HA_HOST" "source /etc/profile.d/claude-ha.sh; source ${HA_REMOTE_PATH:=/config/}.env; ha-api state sensor.hacs" 2>/dev/null
If HACS is not installed, tell the user to install it first from hacs.xyz and skip this step.
Tell the user to install Custom Sidebar via HACS:
Once confirmed installed, add the plugin to configuration.yaml under frontend:
frontend:
extra_module_url:
- /hacsfiles/custom-sidebar/custom-sidebar-plugin.js
Merge with existing frontend: block — do not duplicate the key.
Create config/custom-sidebar-config.yaml:
default_path: /custom-dashboard
Push the config and tell the user to restart HA (this change requires a restart, not just a reload):
make push
python3 -c "
import json, datetime
with open('setup-state.json') as f:
state = json.load(f)
state['session']['current_step'] = 'customize_complete'
state['session']['steps_completed'].append('customize')
state['session']['completed_at'] = datetime.datetime.now().isoformat()
with open('setup-state.json', 'w') as f:
json.dump(state, f, indent=2)
print('Setup complete. setup-state.json updated.')
"
"Setup complete! Your dashboard is deployed.
What's configured:
- [N] rooms mapped
- [N] automation domains active
- Dashboard entities wired
Next steps:
- Open HA companion app and navigate to your custom dashboard panel
- Review
docs/house-rules.mdand fill in any sections that are still blank- If something's wrong, just tell me what to fix — all entity IDs are now in
dashboard/src/lib/entities.tsandconfig/automations/*.yaml"
Source: dcb/homeassistant-claude-kit — distributed by TomeVault.