HomeClaw
Integrates with Apple HomeKit to control HomeKit accessories, rooms, scenes, automations, and events via MCP tools.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@HomeClawturn off all the lights"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
HomeClaw exposes your HomeKit accessories through a command-line tool, a stdio MCP server, and plugins for Claude Code and OpenClaw. It runs as a lightweight macOS menu bar app.
Screenshots
Why HomeClaw?
Apple HomeKit has no public API, no CLI, and no way to integrate with AI assistants or automation pipelines. HomeClaw bridges that gap with a Mac Catalyst app that talks to HomeKit on your behalf and exposes a clean API surface.
Ask Claude or OpenClaw to "turn off all the lights" or "set the thermostat to 72"
Script your smart home from the terminal
Build automations that go beyond what the Home app offers
Search and control devices by name, room, category, or semantic type
Architecture
Claude Code --> Plugin (.claude-plugin/) --> stdio MCP server (Node.js) --+
Claude Desktop --> stdio MCP server (Node.js) ----------------------------+
OpenClaw --> Plugin (openclaw/) --> homeclaw-cli --------------------------+
v
Unix socket (JSON newline-delimited)
|
HomeClaw (Mac Catalyst app)
+-- HomeKitManager (direct, in-process)
+-- SocketServer (for CLI/MCP clients)
+-- macOSBridge.bundle (NSStatusItem menu bar)Single-process design. Apple's HMHomeManager requires a UIKit/Catalyst app with the HomeKit entitlement. By making the entire app Catalyst, HomeKit access is direct (no IPC), signing is unified (single archive), and App Store submission is clean. The macOSBridge plugin bundle provides the native macOS menu bar via NSStatusItem.
Install
Marketing site with screenshots and full pitch: homeclaw.omarknows.app.
Mac App Store (Recommended)
HomeClaw is live on the Mac App Store:
Open in the Mac App Store and install
Launch HomeClaw -- grant HomeKit access when prompted
The menu bar icon appears. Click it to see your connected homes.
App Store builds are fully signed and notarized, so HomeKit works without any developer account setup.
TestFlight Beta
Want early access to in-flight builds before they ship to the App Store?
Install HomeClaw from TestFlight
Launch the app -- grant HomeKit access when prompted
TestFlight builds are signed the same way as App Store builds, so HomeKit works out of the box. You'll get new features (like the automations work in v1.0.1) before they hit the App Store.
After installing
Set up your AI integrations:
Claude Desktop -- one-click install from Settings > Integrations, or add the MCP server config manually
Claude Code -- install the plugin from GitHub
OpenClaw -- one-click install from Settings > Integrations, or set up manually
Build from Source
Prerequisites
macOS 26 (Tahoe) or later
Xcode 26+ with Swift 6.2
XcodeGen:
brew install xcodegenNode.js 20+ (for the MCP server wrapper)
Apple Developer account with HomeKit capability enabled
Why is a developer account required? Apple does not provide a public HomeKit API for macOS. The only way to access HomeKit is through
HMHomeManager, which requires thecom.apple.developer.homekitentitlement and a provisioning profile that covers your Mac's hardware UDID. Apple restricts this entitlement to development signing and App Store distribution -- it cannot be included in Developer ID (notarized) builds. This means every Mac that runs HomeClaw must be registered as a development device in your Apple Developer portal, and the app must be built with your team's signing identity. There is no way around this; it's an Apple platform restriction, not a HomeClaw limitation.
Setup
git clone https://github.com/omarshahine/HomeClaw.git
cd HomeClaw
# Configure your Apple Developer Team ID (one-time setup)
echo "HOMEKIT_TEAM_ID=YOUR_TEAM_ID" > .env.local
# Install Node.js dependencies
npm install
# Build everything and install
scripts/build.sh --release --installFind your Team ID at developer.apple.com/account under Membership Details.
Launch from /Applications or: open "/Applications/HomeClaw.app"
On first launch, grant HomeKit access when prompted. The menu bar icon appears -- click it to see your connected homes.
Note: Apple restricts the HomeKit entitlement to development signing and App Store distribution. Developer ID builds cannot access HomeKit. See Why Development Signing? for details.
MCP Tools
The stdio MCP server wraps homeclaw-cli and exposes these tools:
Tool | Description |
| Check bridge connectivity and accessory count |
| List, get details, search, or control accessories |
| List rooms and their accessories |
| List, get details, trigger, import, or delete scenes |
| LLM-optimized device map with semantic types and aliases |
| Manage home structure: rename accessories/rooms, create/remove rooms and zones, manage zone membership |
| Manage automations: list, create button-press triggers (single/double/long), link to scenes, enable/disable |
| Query recent HomeKit events (characteristic changes, scene triggers, control actions) |
| Manage webhook configuration: setup (configure + auto-test), test, reset circuit breaker, status |
| View or update configuration (set active home, filtering) |
Connecting an MCP Client
Any MCP-compatible client can connect via the stdio server, which wraps homeclaw-cli and requires no authentication (the HomeClaw app must be running for the socket). Add this to your MCP client config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"homeclaw": {
"command": "node",
"args": ["/Applications/HomeClaw.app/Contents/Resources/mcp-server.js"]
}
}
}The mcp-server.js is bundled inside the app. You can also use the Integrations tab in Settings to install this automatically.
CLI
The homeclaw-cli command-line tool communicates directly over the Unix domain socket. All read commands support --json for machine-readable output.
# List accessories
homeclaw-cli list
homeclaw-cli list --room "Kitchen"
homeclaw-cli list --category thermostat
# Control devices
homeclaw-cli set "Living Room Light" brightness 75
homeclaw-cli set "Front Door Lock" lock_target_state locked
homeclaw-cli set "Thermostat" target_temperature 72
# Disambiguate when a characteristic exists on multiple services (e.g. bridged TVs)
homeclaw-cli set "TV" active 0 --service-type 000000D8-0000-1000-8000-0026BB765291
# Get detailed device info
homeclaw-cli get "Kitchen Light" --json
# Search across all homes
homeclaw-cli search "bedroom" --category lightbulb
# Scenes
homeclaw-cli scenes
homeclaw-cli get-scene "Good Night" --json # Full detail: all actions
homeclaw-cli trigger "Good Night"
# Scene management
homeclaw-cli delete-scene "Old Scene"
homeclaw-cli import-scene scene.json --dry-run # Preview before creating
homeclaw-cli import-scene scene.json # Create scene from JSON
homeclaw-cli assign-rooms rooms.json --dry-run # Preview room assignments
homeclaw-cli assign-rooms rooms.json # Bulk-assign accessories to rooms
# Home management
homeclaw-cli rename "Front Door" "Front Door Lock" # Rename accessory
homeclaw-cli rename-room "Bedroom" "Primary Bedroom" # Rename room
homeclaw-cli create-room "Nursery" # Create room
homeclaw-cli remove-room "Old Room" # Remove room
homeclaw-cli remove-accessory "Broken Sensor" # Remove accessory
homeclaw-cli create-zone "Upstairs" # Create zone
homeclaw-cli remove-zone "Old Zone" # Remove zone
homeclaw-cli add-room-to-zone "Bedroom" "Upstairs" # Add room to zone
homeclaw-cli remove-room-from-zone "Bedroom" "Upstairs" # Remove room from zone
homeclaw-cli rename "Front Door" "New Name" --dry-run # Preview any mutation
# Automations (button programming)
homeclaw-cli automations # List all automations
homeclaw-cli automations get "<name-or-uuid>" # Detail view
# Scene-based: trigger an existing scene
homeclaw-cli automations create --name "Gym Lights" \
--accessory "Gym Button" --scene "Gym On" --press single
# Inline actions: use UUIDs for target accessories to avoid name collisions
homeclaw-cli automations create --name "Sarah's Room Open" \
--accessory "Office Button" \
--action "BE21C139-413A-50F9-B97F-B9BDA06302A8:power:true" \
--action "52195C6F-6FAA-5E52-AA56-840A6605EEAA:target_position:100" \
--press single --service-index 1
# Multi-button preview
homeclaw-cli automations create --name "Open Blinds" \
--accessory "Blinds Button" --scene "Open" \
--service-index 1 --dry-run
homeclaw-cli automations delete "<name-or-uuid>" # Delete automation
homeclaw-cli automations enable "<name-or-uuid>" # Enable
homeclaw-cli automations disable "<name-or-uuid>" # Disable
# LLM-optimized device map
homeclaw-cli device-map
# Status and configuration
homeclaw-cli status
homeclaw-cli config --default-home "Main House"
homeclaw-cli config --filter-mode allowlist
homeclaw-cli config --list-devices
# Event log
homeclaw-cli events # Recent events (last 50)
homeclaw-cli events --since 1h # Events from the last hour
homeclaw-cli events --since 2d --json # Last 2 days, JSON output
homeclaw-cli events --type scene_triggered # Filter by event type
# Webhook configuration
homeclaw-cli config --webhook-url "http://127.0.0.1:18789"
homeclaw-cli config --webhook-token "your-secret-token"
homeclaw-cli config --webhook-enabled true
homeclaw-cli config --webhook-test # Send test event, show HTTP response
homeclaw-cli config --webhook-reset # Reset circuit breaker without toggling
# Webhook triggers
homeclaw-cli triggers # List all triggers
homeclaw-cli triggers add --label "Front Door" --accessory-id "<uuid>"
homeclaw-cli triggers add --label "Mailbox Open" --accessory-id "<uuid>" --characteristic contact_state
homeclaw-cli triggers update "<trigger-id>" --wake-mode now
homeclaw-cli triggers remove "<trigger-id>"
# Dry-run mutations (validate without actuating)
homeclaw-cli set "Front Door" lock_target_state locked --dry-run
homeclaw-cli delete-scene "Movie Night" --dry-run
# Auto-JSON: all commands output JSON when piped or when env var is set
homeclaw-cli status | jq . # Auto-detects non-TTY
OUTPUT_FORMAT=json homeclaw-cli list # Force JSON via env varButton Programming Notes
Inline vs scene: Use --action for simple button-to-device mappings. This creates a scene named after the automation. Use --scene to trigger an existing scene instead. Note: Apple's Home app uses a private API for hidden automation-only action sets; inline actions created via HomeClaw will appear as visible scenes in the Home app.
Button modes: Some buttons (like Aqara AR009) support fast mode (2 buttons, single press each, instant response) or multi-event mode (1 button, single/double/long press, ~300ms delay). Use --service-index to target a specific button in fast mode.
Interactive TUI
homeclaw-cli uiLaunches a full-screen, keyboard-driven view of your home. Browse rooms and accessories, see live state at a glance, and toggle anything that has a binary state (lights, switches, fans, outlets, locks, blinds).
π¦ HomeClaw 21 rooms Β· 112 accessories
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β βΎ Living Room (4) β
β ββ β Floor Lamp On β
β ββ β TV Light Strip On β
β ββ β Thermostat 70.5Β°F β
β ββ β Window Blinds 100% β
β β
β βΎ Kitchen (3) β
β ββ β Counter Light Off β
β ... β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
^D quit ββ navigate Enter toggleKey | Action |
| Navigate between accessories |
| Toggle the focused accessory (lights/switches/outlets/fans flip onβoff, locks flip lockedβunlocked, blinds flip 0%β100%) |
| Quit |
State color coding: lights on are yellow, outlets/switches cyan, fans blue, locks green when locked / red when unlocked, motion red, sensors cyan, off/idle dim.
The TUI works over SSH (no AppKit assumptions), runs against the same Unix socket as the rest of the CLI, and respects demo mode β launch HomeClaw with --ui-test-demo to render a synthetic home for screenshots or demos. Built on SwiftTUI. Scene picker, search, and help overlay are tracked in #53 β they need a different framework's key handling and will land when SwiftTUI gains app-level key bindings (or we switch).
Using with Claude Code
HomeClaw integrates with Claude Code as a plugin that provides MCP tools and a HomeKit skill for richer natural language understanding.
Installing the Plugin
Install from a local clone or directly from GitHub.
From a local clone:
# Clone if you haven't already
git clone https://github.com/omarshahine/HomeClaw.git ~/GitHub/HomeClaw
# Inside Claude Code, register the marketplace and install
/plugin marketplace add ~/GitHub/HomeClaw
/plugin install homeclaw@homeclawFrom GitHub (no local clone needed):
# Inside Claude Code, add the GitHub repo as a marketplace
/plugin marketplace add https://github.com/omarshahine/HomeClaw
# Install the plugin
/plugin install homeclaw@homeclawAfter installing, restart Claude Code. Then just ask:
"Turn on the kitchen lights and set them to 50% brightness" "Lock all the doors" "What's the thermostat set to?" "Run the movie time scene" "Which lights are on in the living room?"
Verifying the Connection
After installing, verify Claude can reach HomeKit:
# Check MCP server status inside Claude Code
/mcpUsing with OpenClaw
HomeClaw includes an OpenClaw plugin that registers a HomeKit skill on the gateway. The skill calls homeclaw-cli by name, so it must be in your PATH.
Same-Mac Install (Recommended)
If HomeClaw and OpenClaw run on the same Mac, use the one-click installer:
Open Settings > Integrations and click Install in the OpenClaw section.
This handles all four steps automatically: installs the plugin, enables it, symlinks homeclaw-cli into your PATH, and restarts the gateway.
Or from the terminal:
# 1. Install the plugin from the bundled files
openclaw plugins install "/Applications/HomeClaw.app/Contents/Resources/openclaw/"
openclaw plugins enable homeclaw
# 2. Symlink the CLI into PATH (the skill calls homeclaw-cli by name)
# Apple Silicon (M1/M2/M3/M4):
ln -sf '/Applications/HomeClaw.app/Contents/MacOS/homeclaw-cli' /opt/homebrew/bin/homeclaw-cli
# Intel:
ln -sf '/Applications/HomeClaw.app/Contents/MacOS/homeclaw-cli' /usr/local/bin/homeclaw-cli
# 3. Restart the gateway to load the plugin
openclaw gateway restartRemote Gateway
If OpenClaw runs on a different machine:
# Clone the repo on the gateway
git clone https://github.com/omarshahine/HomeClaw.git ~/GitHub/HomeClaw
# Install the plugin
openclaw plugins install ~/GitHub/HomeClaw/openclaw
openclaw plugins enable homeclaw
# Symlink the CLI into PATH
ln -sf /path/to/homeclaw-cli /opt/homebrew/bin/homeclaw-cli
# Restart the gateway
openclaw gateway restartNote: The
homeclaw-clibinary must be accessible from the gateway (in PATH), and the HomeClaw app must be running on the same Mac (connected via Unix socket).
Supported Accessories
HomeClaw supports the full range of HomeKit accessory categories:
Category | Controllable Characteristics |
Lights | power, brightness (0-100), hue (0-360), saturation (0-100), color temperature (140-500 mireds) |
Thermostats | target temperature, HVAC mode (off/heat/cool/auto), target humidity |
Locks | lock/unlock (accepts |
Doors & Garage Doors | open/close, obstruction detection (read-only) |
Fans | active, rotation speed, rotation direction, swing mode |
Window Coverings | target position (0-100%) |
Switches & Outlets | power on/off |
Sensors | motion, contact, temperature, humidity, light level, battery (all read-only) |
Doorbells | ring detection via input_event (single/double/long press), motion (read-only) |
Programmable Switches | button press detection (single/double/long press) (read-only) |
Scenes | trigger by name or UUID, inspect actions, import from JSON, delete by name |
Scene Import Format
The import-scene command accepts a JSON file defining a scene and its actions:
{
"name": "Movie Night",
"actions": [
{"accessory": "Living Room Light", "room": "Living Room", "property": "brightness", "value": "30%"},
{"accessory": "TV Backlight", "room": "Living Room", "property": "power_state", "value": "ON"},
{"accessory": "Overhead", "room": "Living Room", "property": "power_state", "value": "OFF"}
]
}The assign-rooms command accepts a JSON file mapping accessories to rooms. Use uuid for precise matching when multiple accessories share the same name (e.g., fan + light from a ceiling fan):
{
"assignments": [
{"accessory": "Kitchen Light", "room": "Kitchen"},
{"uuid": "790A359D-27A6-5738-A92E-F4380CC6BA07", "room": "Front Door"},
{"accessory": "Desk Lamp", "room": "Office"}
]
}Both commands support --dry-run to preview changes without modifying HomeKit.
Menu Bar App
The menu bar provides at-a-glance status and quick actions:
HomeKit connection status -- shows home names when connected, or error states with reasons
Launch at Login toggle
Settings link and Quit
Settings
Five configuration tabs accessible from the menu bar:
Tab | Features |
HomeKit | Connection status, home list with accessory and room counts, active home selector |
Devices | Filter mode (all/allowlist), per-device toggles with category icons and state badges, grouped by room, search, bulk select/deselect |
Event Log | Enable/disable event logging, configure file rotation (size limit + backup count), view storage stats, purge logs, reveal in Finder |
Webhook | Configure webhook base URL + bearer token, select which scenes and accessories trigger webhooks with category icons and state badges. Accessories with multiple characteristics (e.g., a sensor with both contact and motion) show individual toggles per characteristic; battery characteristics are excluded. Per-trigger delivery mode (Batched/Immediate). Circuit breaker banners with Reset button, delivery stats, and last HTTP status. Test webhook connectivity from CLI or manage triggers via |
Integrations | One-click install for Claude Desktop, Claude Code plugin detection, OpenClaw gateway setup |
HomeKit
View connection status, browse your homes, and select which home is active for all MCP and CLI commands.
Devices
Control which accessories are exposed to MCP clients and the CLI. Switch between All Accessories (everything visible) and Selected Only (allowlist mode). Accessories are grouped by room with a search filter and room-level toggles for quick bulk selection.
Integrations
Install and manage connections to AI assistants. The app detects existing configurations and guides you through setup:
Claude Desktop -- one-click install of the bundled stdio MCP server (requires Node.js)
Claude Code -- detects the installed plugin (
homeclaw@homeclaw)OpenClaw -- detects plugin configuration on the remote gateway and provides setup instructions
Event Log
HomeClaw records all HomeKit events to a JSONL file in ~/Library/Application Support/HomeClaw/events.jsonl. Events include characteristic changes (a light turned on), scene triggers, and control actions from the CLI or MCP.
Configuration
Open Settings > Event Log to configure:
Enable/disable event logging
Max file size (10-500 MB) -- when the log reaches this size, it's rotated
Rotated backups (0-10) -- how many old log files to keep before deleting the oldest
Purge -- delete all event log files
Show in Finder -- reveal the log directory
Or configure via CLI:
homeclaw-cli events # Show recent events
homeclaw-cli events --since 1h # Last hour
homeclaw-cli events --type characteristic_change # Filter by type
homeclaw-cli events --limit 200 --json # JSON outputEvent types: characteristic_change, scene_triggered, accessory_controlled, homes_updated
The --since flag accepts ISO 8601 timestamps or duration shorthand: 1h, 30m, 2d.
Webhook
HomeClaw pushes HomeKit events to OpenClaw via mapped webhooks. Only accessories and scenes with configured triggers fire webhooks -- untriggered events are logged to disk but not pushed. A dedicated HomeClaw agent receives all events, classifies them by severity, and escalates noteworthy ones to the main agent.
Note: OpenClaw 2026.3.x has a known bug where
/hooks/wakesilently drops events (#33271). HomeClaw uses mapped webhooks (/hooks/homeclaw) which route throughhooks.mappingsand are not affected.
How It Works
HomeClaw POSTs all triggered events to a single mapped endpoint: /hooks/homeclaw. OpenClaw's hooks.mappings config resolves the "homeclaw" key and routes each event to a dedicated HomeClaw agent that classifies and triages events.
HomeKit event --> HomeClaw event logger --> POST /hooks/homeclaw
--> OpenClaw hooks.mappings --> HomeClaw Agent (dedicated)
--> Classifies: CRITICAL / NOTABLE / AMBIENT
--> If notable/critical: a2a to main agent
--> If ambient: log to agent memory onlyHomeClaw doesn't need to know about agentId, channel, or sessionKey -- all routing intelligence lives in the OpenClaw config.
Trigger Delivery Modes
Each trigger has a delivery mode that controls timing:
Mode | Behavior | Set via |
Batched (default) | Event queued until next heartbeat cycle | Settings UI segmented control |
Immediate | Event delivered right away | Settings UI segmented control |
In Settings > Webhook, each enabled trigger shows a Batched / Immediate picker. Use Immediate for events you want to react to right away (leak sensors, door locks, scene triggers). Use Batched for ambient events (light toggles, temperature changes) to avoid noise.
Setup with AI Assistant
Paste this prompt into OpenClaw or Claude Code to configure webhooks end-to-end. The prompt is idempotent -- it verifies each step and skips anything already configured:
Prerequisites: HomeClaw must be installed and running (menu bar icon visible). If using Claude Code, the
homeclawplugin must be registered (/plugin install homeclaw@homeclaw). Thehomeclaw-clibinary must be in your PATH.Set up HomeClaw mapped webhooks with a dedicated HomeClaw agent. Verify each step first -- skip any that are already configured.
1. HomeClaw agent workspace:
Check if
homeclawagent exists:openclaw agents listIf missing, install from the bundled app:
openclaw agents install homeclaw /Applications/HomeClaw.app/Contents/Resources/openclaw/agents/homeclawCopy agent docs (IDENTITY/SOUL/AGENTS/TOOLS.md) from the app bundle to the local agent dir if newer
Configure agent: model
claude-sonnet-4, restricted tools (memory, sessions/a2a, read/write only -- no exec, no browser, no external services)2. OpenClaw gateway hooks config:
Check
~/.openclaw/openclaw.jsonfor ahooks.mappings.homeclawentryIf missing, add:
"hooks": { "enabled": true, "token": "${HOMECLAW_WEBHOOK_TOKEN}", "mappings": { "homeclaw": { "agentId": "homeclaw", "sessionKey": "hook:homeclaw", "deliver": true, "channel": "last", "allowUnsafeExternalContent": true } } }
Create a transform at
~/.openclaw/hooks/transforms/homeclaw-transform.jsto convert HomeClaw state-change payloads into agent messagesCheck
~/.openclaw/.envforHOMECLAW_WEBHOOK_TOKEN. If missing, generate one:openssl rand -base64 24 | tr '+/' '-_' | tr -d '='and add itRemove any legacy
defaultSessionKeyentries that are no longer needed with dedicated mappingRestart gateway only if config changed:
openclaw gateway restart3. HomeClaw webhook config:
Check current config:
homeclaw-cli config --jsonVerify:
webhook.enabledis true,webhook.urlishttp://127.0.0.1:18789,webhook.tokenmatches theHOMECLAW_WEBHOOK_TOKENfrom step 2, andwebhook_endpointis/hooks/homeclawFix any mismatches via HomeClaw Settings UI or CLI
If circuit breaker shows old failures, reset it
4. End-to-end test:
Run
homeclaw-cli config --webhook-test-- expect HTTP 200Verify circuit state is
closedandlast_successis recentReport what was already configured, what was changed, and the test result.
Manual Setup
1. Create the Agent Workspace
The agent docs are bundled inside the HomeClaw app. Because the app bundle is read-only, you need a local copy for OpenClaw to use as the agent directory:
# Create local agent dir with workspace
mkdir -p ~/.openclaw/agents/homeclaw/{agent,workspace}
# Copy agent docs from app bundle
cp /Applications/HomeClaw.app/Contents/Resources/openclaw/agents/homeclaw/*.md \
~/.openclaw/agents/homeclaw/agent/
# Register the agent
openclaw agents add homeclaw \
--agent-dir ~/.openclaw/agents/homeclaw/agent \
--workspace ~/.openclaw/agents/homeclaw/workspace
openclaw agents list # verify it appearsNote:
openclaw agents add(notinstall) is the correct CLI command. The--workspaceflag is required in non-interactive mode.
2. Configure OpenClaw
Add the hooks block with mappings to ~/.openclaw/openclaw.json:
"hooks": {
"enabled": true,
"token": "${HOMECLAW_WEBHOOK_TOKEN}",
"mappings": {
"homeclaw": {
"agentId": "homeclaw",
"sessionKey": "hook:homeclaw",
"deliver": true,
"channel": "last",
"allowUnsafeExternalContent": true
}
}
}The mappings entry routes all /hooks/homeclaw POSTs to the dedicated HomeClaw agent in a persistent hook:homeclaw session.
Create a transform to convert HomeClaw payloads into agent messages. The hook mapping requires a message field in the payload -- without a transform, payloads with only text + mode will get a 400 error:
mkdir -p ~/.openclaw/hooks/transforms
cat > ~/.openclaw/hooks/transforms/homeclaw-transform.js << 'TRANSFORM'
// Convert HomeClaw webhook payload {text, mode} into agent message format
module.exports = function(payload) {
return {
message: payload.text || JSON.stringify(payload),
mode: payload.mode || "next-heartbeat"
};
};
TRANSFORMThen reference the transform in the mapping:
"homeclaw": {
"agentId": "homeclaw",
"sessionKey": "hook:homeclaw",
"deliver": true,
"channel": "last",
"allowUnsafeExternalContent": true,
"transform": "homeclaw-transform"
}Generate a token and add it to ~/.openclaw/.env:
# Generate a secure token
openssl rand -base64 24 | tr '+/' '-_' | tr -d '='
# Add to .env
echo 'HOMECLAW_WEBHOOK_TOKEN=<your-generated-token>' >> ~/.openclaw/.envRestart the gateway: openclaw gateway restart
Warning: The gateway rewrites
openclaw.jsonon restart. Verify your mapping and transform entries survived by checking the file after restart. If a newly-added mapping is stripped, restart a second time -- there may be a race condition with first-time mappings.
3. Configure HomeClaw
Option A -- GUI: Open Settings > Webhook. Toggle Enable, enter http://127.0.0.1:18789 as the base URL, paste the same token from step 2.
Option B -- CLI (note: the CLI updates the running daemon only -- it does not persist to config.json. Use the Settings UI or edit the config file directly for persistent changes):
homeclaw-cli config --webhook-url "http://127.0.0.1:18789" \
--webhook-token "your-token" \
--webhook-enabled true4. Test the Pipe
homeclaw-cli config --webhook-testYou should see an HTTP 200 response. If it fails, check the token matches and the OpenClaw gateway is running.
Note: Test events update
total_deliveredandlast_http_statusin the circuit breaker stats. After running--webhook-test, checkhomeclaw-cli config --jsonto confirm the values were updated.
5. Create Triggers
In Settings > Webhook, check the accessories and scenes you want to fire webhooks. Only checked items generate events. Accessories with multiple characteristics (e.g., a sensor with both contact state and motion) show individual toggles so you can choose exactly which state changes fire webhooks. Battery-related characteristics are automatically excluded.
Note: Trigger creation is GUI-only. The CLI can list and manage existing triggers (
homeclaw-cli triggers list,triggers remove), but new triggers must be created in the HomeClaw app's Settings > Webhook tab.
6. Test End-to-End
# Verify HomeClaw is connected and webhook is healthy
homeclaw-cli status
# Toggle a light from the Home app, then check events
homeclaw-cli events --since 5m
# Check webhook delivery log
homeclaw-cli webhook-log
# Check HomeClaw delivery logs
log show --predicate 'process == "HomeClaw" AND category == "webhook"' --last 5m --style compactCircuit Breaker
The webhook system includes a tiered circuit breaker that prevents runaway delivery failures from hammering a down endpoint, while ensuring critical events are never silently dropped.
State | Trigger | Behavior | Recovery |
Normal | -- | All webhooks delivered | -- |
Soft Open | 5 consecutive failures | Non-critical paused | Auto-resumes after 5 minutes |
Hard Open | 3 soft trips without any success | All non-critical stopped | Reset button in Settings, |
Critical triggers (critical: true) always attempt delivery regardless of circuit state.
The circuit state is visible in:
Menu bar -- warning icon when paused or disabled
Settings > Webhook -- orange (paused) or red (disabled) banner with countdown
CLI --
homeclaw-cli statusshows circuit state, dropped count, and recovery hint
How Events Flow
Home app / physical device / Siri
|
v
HomeKit (HMAccessoryDelegate callback)
|
+-- Cache warmup? --> Update cache only (no logging, no webhooks)
|
+-- Battery event? --> Update cache only (silently dropped)
|
v
HomeClaw event logger (writes to events.jsonl)
|
+-- Trigger matches? --> POST /hooks/homeclaw
|
+-- No trigger --> Logged to disk only (no webhook sent)
v (trigger matched)
OpenClaw gateway validates Bearer token
|
v
hooks.mappings resolves "homeclaw"
|
v
HomeClaw Agent (dedicated)
+-- Classifies: CRITICAL / NOTABLE / AMBIENT
+-- If notable/critical: a2a to main agent
+-- If ambient: log to agent memory onlyAuthentication
Uses Authorization: Bearer <token> with idempotency headers (X-Request-ID, X-Event-Timestamp). See SKILL.md for the full trigger fields reference, scenario cookbook, and troubleshooting.
Device Filtering
Use the Devices tab in Settings or the CLI to control which accessories are exposed:
homeclaw-cli config --filter-mode allowlist
homeclaw-cli config --allow-accessories "uuid1,uuid2,uuid3"
homeclaw-cli config --list-devices # shows allowed/filtered statusBuilding
The build script uses XcodeGen to generate the Xcode project and xcodebuild to compile all targets (HomeClaw Catalyst app, macOSBridge bundle, homeclaw-cli tool):
# Full release build + install to /Applications
scripts/build.sh --release --install
# Override team ID on the command line
scripts/build.sh --release --install --team-id ABCDE12345
# Debug build (faster)
scripts/build.sh --debug
# Clean build artifacts first
scripts/build.sh --cleanYour Apple Developer Team ID is required, provided via .env.local, --team-id, or the HOMEKIT_TEAM_ID environment variable.
Archiving for App Store / TestFlight
The release pipeline is driven by fastlane. Lanes:
fastlane archive # Build a release .xcarchive (no upload)
fastlane upload # Archive + upload to App Store Connect (no external submission)
fastlane beta # Archive + upload + submit to external TestFlight (full release loop)
fastlane status # Show TestFlight processing/external state for the latest build
fastlane submit_only build:NNN # Recovery: submit an already-uploaded build
fastlane auth_check # Validate ASC API key setup
# Pass tester notes (used by `beta` and `submit_only`):
fastlane beta notes_file:/tmp/notes.txt
fastlane beta notes:"Bug fixes and improvements"
# App Store screenshot pipeline (XCUITest-driven, demo mode, zero personal data):
fastlane screenshots # Run HomeClawUITests in demo mode, extract PNGs to fastlane/screenshots/en-US/
fastlane upload_screenshots # Push screenshots to App Store ConnectThe screenshot pipeline uses demo mode β HomeKitManager.isDemoMode (gated on --ui-test-demo launch arg or HOMECLAW_DEMO=1) bypasses HomeKit and serves synthetic data from Sources/homeclaw/HomeKit/DemoFixtures.swift. Real HomeKit data is never read or shown. Requires xcparse (brew install chargepoint/xcparse/xcparse).
Known follow-up: the menu-bar dropdown is NSMenu (AppKit), so it can't be auto-rendered via SwiftUI ImageRenderer. Capture it manually with screencapture -x of the running demo-mode app, or build a SwiftUI mockup of the dropdown.
Auth uses an App Store Connect API key from ~/.secrets.env (ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_PATH). Team ID comes from .env.local (HOMEKIT_TEAM_ID).
To open the archive in Xcode Organizer instead of uploading:
fastlane archive
open '.build/archives/HomeClaw.xcarchive'Version Bumping
Version is derived from git tags at build time. To release a new version:
scripts/bump-version.sh 0.2.0 # Updates source files + prints tag commands
npm run build:mcp # Rebuild MCP server with new version
git add -A && git commit -m "Bump version to 0.2.0"
git tag -a v0.2.0 -m "HomeClaw v0.2.0"
git push && git push origin v0.2.0Installing on Additional Macs
Development-signed builds are tied to registered devices. To run HomeClaw on another Mac:
Get the target Mac's Provisioning UDID -- on that Mac, run:
system_profiler SPHardwareDataType | grep "Provisioning UDID"Register the device at developer.apple.com/account/resources/devices/add:
Platform: macOS
Device Name: a descriptive name (e.g. "Living Room MacBook Air")
Device ID: the Provisioning UDID from step 1
Rebuild on your development machine (Xcode regenerates the provisioning profile to include the new device):
scripts/build.sh --release --install --cleanCopy
/Applications/HomeClaw.appto the target Mac (AirDrop, USB, network share, etc.)Grant HomeKit access on first launch when prompted.
Note: The target Mac must be signed into iCloud with an account that has HomeKit home data. HomeKit homes are tied to iCloud accounts, not to the app.
Why Development Signing?
Apple restricts the com.apple.developer.homekit entitlement to development signing and Mac App Store distribution. It cannot be included in Developer ID provisioning profiles. A Developer ID build would pass Gatekeeper but have no HomeKit access (HMHomeManager returns zero homes). This is an Apple platform restriction, not a bug.
Project Structure
Sources/
homeclaw/ Unified Catalyst app (Xcode target via XcodeGen)
App/ UIApplicationDelegate entry point, scene delegates
Bridge/ BridgeProtocols.swift (Mac2iOS, iOS2Mac)
HomeKit/ HomeKitManager, SocketServer, CharacteristicMapper,
AccessoryModel, DeviceMap, CharacteristicCache,
HomeEventLogger, WebhookCircuitBreaker
Views/ SettingsView, IntegrationsSettingsView
Shared/ AppConfig, AppLogger, HomeClawConfig
macOSBridge/ AppKit bundle (NSStatusItem menu bar)
MacOSController.swift NSStatusItem + NSMenu via iOS2Mac protocol
Info.plist NSPrincipalClass: MacOSController
homeclaw-cli/ CLI tool (SPM executable + Xcode target)
Commands/ list, get, set, search, scenes, get-scene, status, config, device-map,
events, triggers, delete-scene, import-scene, assign-rooms
SocketClient.swift Direct socket communication
Resources/ Info.plist, entitlements, app icons
scripts/
build.sh Build, sign, and install
bump-version.sh Update version across source files
fastlane/
Fastfile Release pipeline: archive, upload, beta (TestFlight)
Appfile Bundle ID + team ID
Gymfile Mac Catalyst archive defaults
mcp-server/ Node.js stdio MCP server (wraps homeclaw-cli)
openclaw/ OpenClaw plugin (HomeClaw)
skills/homekit/ HomeKit skill with full characteristic reference
App bundle layout (after build):
Contents/MacOS/HomeClaw Catalyst app executable
Contents/MacOS/homeclaw-cli Bundled CLI binary
Contents/Resources/macOSBridge.bundle AppKit menu bar plugin
Contents/Resources/mcp-server.js Node.js stdio MCP server
Contents/Resources/openclaw/ Bundled OpenClaw plugin filesDebugging
# Check if HomeClaw is running and HomeKit is ready
echo '{"command":"status"}' | nc -U ~/Library/Group\ Containers/group.com.shahine.homeclaw/homeclaw.sock
# Or via the CLI
homeclaw-cli status
# Verify HomeKit entitlement on installed app
codesign -d --entitlements :- "/Applications/HomeClaw.app"
# View HomeClaw logs
log show --predicate 'process == "HomeClaw"' --last 10m --style compact
# Check TCC (privacy) permissions
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db \
"SELECT client, auth_value FROM access WHERE service = 'kTCCServiceWillow'"Symptom | Cause | Fix |
0 homes, | Missing HomeKit entitlement | Verify with |
All characteristic values | Accessory unreachable | Check device power and network |
"HomeKit Unavailable" in menu | iCloud not signed in | Sign into iCloud with HomeKit data |
CLI crashes with SIGTRAP | Missing bundle ID in sandbox | Rebuild with |
Tech Stack
Swift 6 with strict concurrency (
@MainActor,actorisolation)Mac Catalyst (UIKit) for HomeKit framework access
AppKit (via macOSBridge bundle) for native menu bar
Swift Argument Parser for CLI
Node.js + @modelcontextprotocol/sdk for stdio MCP server
XcodeGen for Xcode project generation
GCD + Unix domain sockets for CLI/MCP communication
FAQ
spctl --assess says "rejected" -- is that a problem?
No. spctl checks Gatekeeper, which only trusts Developer ID and App Store signing. HomeClaw uses development signing (required for HomeKit on macOS), so Gatekeeper will always reject it. This is expected and doesn't prevent the app from running -- AMFI handles development-signed apps separately via the embedded provisioning profile.
Can I use a different Apple ID for HomeKit than my developer account?
Yes. The two accounts serve completely different purposes:
Apple Developer account -- only matters at build time. Xcode uses it to create the provisioning profile and sign the code.
iCloud account (on the Mac running HomeClaw) -- determines which HomeKit homes appear. This is the account linked to your Home app data.
These are independent. You can build HomeClaw with your developer account and run it on a Mac signed into a completely different iCloud account that has HomeKit homes. The HomeKit data follows the iCloud account, not the signing identity.
When should I use --clean?
Use scripts/build.sh --clean when:
Switching Apple Developer Team IDs
After major Xcode version updates
Build fails with signing or entitlement errors
You see code signature errors after rebuilding
The --clean flag removes all build artifacts before building fresh.
HomeKit shows 0 homes
The app is running but can't see any HomeKit data. Check in order:
iCloud signed in? HomeKit data lives in iCloud. Open System Settings > Apple Account and verify.
HomeKit entitlement present? Run:
codesign -d --entitlements :- "/Applications/HomeClaw.app"You should see
com.apple.developer.homekit->true.TCC permission granted? On first launch, macOS asks for HomeKit access. If you denied it, re-grant in System Settings > Privacy & Security > HomeKit.
Using Developer ID signing? Only development signing supports the HomeKit entitlement. See Why Development Signing?.
How do I install on another Mac?
Development-signed apps are tied to registered devices. See Installing on Additional Macs for the full walkthrough.
How do I see what's happening?
# HomeClaw app logs
log show --predicate 'process == "HomeClaw"' --last 10m --style compact
# Check HomeKit status directly over the socket
homeclaw-cli status
# Verify code signature and entitlements
codesign -d --entitlements :- "/Applications/HomeClaw.app"License
MIT -- Copyright (c) 2025 Omar Shahine
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/omarshahine/HomeClaw'
If you have feedback or need assistance with the MCP directory API, please join our Discord server