OpenClaw↗ runs its gateway on loopback only, on port 18789, so nothing outside the machine can reach it. That is the right default, but it means the hooks that wake your Claw (/hooks/wake and /hooks/agent) have no public URL. OtterKit solves this in two ways: a capture-and-relay setup that never exposes the gateway, or a direct tunnel for callers that need the gateway itself.
Install the skill#
Teach your Claw to manage its own tunnels and webhook endpoints:
clawhub install otterkit-tunnelThe skill is published on ClawHub↗. It includes the command reference, the recipes below, and pricing, so after a one-time npx otterkit login the agent can set everything up on its own.
Wake your Claw from public webhooks (recommended)#
An OtterKit webhook endpoint takes the public traffic, and --deliver-exec relays each capture to the gateway on loopback. The gateway port is never public. First, a small relay script wraps each body in the {text, mode} payload that /hooks/wake expects:
#!/bin/sh
jq -Rs '{text: ("Webhook " + env.OTTERKIT_METHOD + " " + env.OTTERKIT_PATH + "\n" + .), mode: "now"}' \
| curl -s -X POST http://127.0.0.1:18789/hooks/wake \
-H "Authorization: Bearer $OPENCLAW_HOOKS_TOKEN" \
-H "Content-Type: application/json" -d @-Then start a background endpoint that runs it for every capture:
chmod +x wake-relay.sh
npx otterkit webhook --subdomain my-claw-hooks --daemon --ttl never \
--deliver-exec "$PWD/wake-relay.sh"Point Stripe, GitHub, your CI, or anything else at https://my-claw-hooks.otterkit.app. Each capture's body arrives on the command's stdin, and the request method, path, and signature verdict arrive in OTTERKIT_* environment variables. External events wake your Claw within seconds.
OtterKit's servers answer the endpoint, so providers keep getting a 200 even while your laptop is asleep. Deliveries are buffered and relayed when the machine comes back. Every event also lands in the capture log, ready for inspect and replay.
OpenClaw plugin#
The OtterKit plugin for OpenClaw runs the same relay for you and ties it to the gateway lifecycle. Configure a wake URL and any tunnels in openclaw.json, restart the gateway, and the plugin logs the live URLs. It also bundles the otterkit-tunnel skill.
{
"plugins": {
"entries": {
"otterkit": {
"enabled": true,
"config": {
"wake": { "subdomain": "my-claw-hooks" },
"tunnels": [{ "port": 3000, "subdomain": "myapp" }]
}
}
}
},
"hooks": { "enabled": true, "token": "use-a-dedicated-hooks-token" }
}Tunnel the gateway directly#
Some callers need the gateway itself, for example a provider that reads responses from /hooks/agent, or remote access. Give the gateway a stable public URL:
npx otterkit tunnel 18789 --subdomain my-claw --daemon --ttl 3d