#zimaos openclaw install
1 messages · Page 1 of 1 (latest)
On ZimaOS the two things that usually bite people are Node being too old (<22) and PATH/permissions for global npm installs.
Can you paste the output of these (and also what exact command/error you’re seeing when you “have no luck”)?
cat /etc/os-release
uname -m
node -v
npm -v
npm prefix -g
echo "$PATH"
The “normal” install that should work (host install)
Docs: https://docs.openclaw.ai/start/quickstart + https://docs.openclaw.ai/install
npm install -g openclaw@latest
openclaw --version
openclaw onboard --install-daemon
If --install-daemon fails (common on some NAS-ish / container-ish environments), try:
openclaw onboard
openclaw gateway --port 18789
If you hit a permissions/PATH error
This doc is the exact playbook: https://docs.openclaw.ai/install/node
Once you paste the outputs + the error message, I can tell you exactly which case you’re in (Node version, PATH, EACCES, systemd/daemon, or “you’re inside a container”).
$ cat /etc/os-release
uname -m
node -v
npm -v
npm prefix -g
echo "$PATH"PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
$ x86_64
$ v22.22.0
$ 10.9.4
$ /usr/local
Debian 12 + x86_64 + Node 22.22.0 is perfect — so this isn’t a “wrong OS/CPU/Node” problem.
Two likely issues left:
- Global npm installs into
/usr/localneed root (common on Debian), sonpm install -g openclaw@latestmay be failing withEACCES. - Your output didn’t include the actual PATH line, so it might be installing but
openclawisn’t found.
Can you paste:
A) The exact command you ran + the full error output
Most useful is:
npm install -g openclaw@latest
B) PATH + whether /usr/local/bin is on it
echo "$PATH" | tr ':' '\n'
which node
which npm
ls -l /usr/local/bin/openclaw 2>/dev/null || true
openclaw --version
If you’re seeing EACCES (permission denied) on /usr/local/...
Fix by switching npm’s global prefix to your user (recommended; no sudo):
mkdir -p "$HOME/.npm-global"
npm config set prefix "$HOME/.npm-global"
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
npm install -g openclaw@latest
openclaw --version
(If you use zsh, replace ~/.bashrc with ~/.zshrc.)
Once openclaw --version works, we can do:
openclaw onboard --install-daemon
And if the daemon doesn’t stay up on ZimaOS, we’ll handle lingering (loginctl enable-linger) next.
i installed it through the bigbear app store
Ah — BigBear app store install is almost certainly a 3rd-party Docker app (CasaOS/ZimaOS), not the “official” OpenClaw installer flow. We can still try to debug it, but first we need to know what’s actually failing.
- When you open the dashboard in a browser, what do you see?
http://<your-zima-ip>:18789/- Do you get a UI?
- Or connection refused?
- Or “unauthorized” / “pairing required” / websocket 1008?
- In ZimaOS/CasaOS, can you paste:
- the container logs for the OpenClaw app (last ~50-100 lines)
- and the image name + tag it’s running (e.g.
openclaw:latestvs something else)
If you have SSH, this is the quickest way to grab both:
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
docker logs --tail 120 <container_name>
Also: since your box already has Debian 12 + Node 22, the most supported path (and usually easiest) is not BigBear, but the official install:
https://docs.openclaw.ai/install
If you want, tell me whether you prefer native install or Docker, and I’ll give you the cleanest step-by-step for that.
i get this site cannot be reached and ill grab the logs and its alpine/openclaw:latest
openclaw-gateway | 2026-02-06T08:59:02.628Z [canvas] host mounted at http://127.0.0.1:18789/__openclaw__/canvas/ (root /home/node/.openclaw/canvas)
openclaw-gateway | 2026-02-06T08:59:02.661Z [heartbeat] started
openclaw-gateway | 2026-02-06T08:59:02.662Z [gateway] agent model: anthropic/claude-opus-4-5
openclaw-gateway | 2026-02-06T08:59:02.663Z [gateway] listening on ws://127.0.0.1:18789 (PID 1)
openclaw-gateway | 2026-02-06T08:59:02.664Z [gateway] listening on ws://[::1]:18789
openclaw-gateway | 2026-02-06T08:59:02.664Z [gateway] log file: /tmp/openclaw/openclaw-2026-02-06.log
openclaw-gateway | 2026-02-06T08:59:02.668Z [browser/service] Browser control service ready (profiles=2)
openclaw-gateway | 2026-02-06T08:59:02.808Z [gateway] update available (latest): v2026.2.3-1 (current v2026.2.2). Run: openclaw update
If the container is using OpenClaw defaults, the Gateway binds to 127.0.0.1 by default — and inside Docker that makes it unreachable from outside the container, even if the port is published. Also, if it does try to bind to LAN, it may refuse to start unless a token is set.
When you grab logs, also paste these two commands (they’ll tell us immediately if it’s (a) not running, (b) ports not published, or (c) bound to loopback):
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
docker logs --tail 200 <container_name>
Two super-common fixes for the “site can’t be reached” Docker case:
1) Make sure the container is actually publishing the gateway port
In docker ps, you want to see something like:
0.0.0.0:18789->18789/tcp (or some other host port mapped to 18789)
If it maps to a different host port, use that in the browser:
http://<zima-ip>:<host-port>/
2) Ensure OpenClaw binds to LAN + has a token
In BigBear/CasaOS app settings (env vars), set:
OPENCLAW_GATEWAY_BIND=lanOPENCLAW_GATEWAY_TOKEN=<some long random string>
Then restart the container.
Once you paste the logs, I’ll tell you which exact one you’re hitting (you’ll usually see a log line like “listening on …127.0.0.1:18789” or an error about auth/token/bind).
Yup, the logs explain it:
[gateway] listening on ws://127.0.0.1:18789
That means OpenClaw is bound to loopback inside the container. With Docker/CasaOS port publishing, connections arrive on the container’s eth0 IP (not 127.0.0.1), so the gateway won’t accept them → browser says “site can’t be reached”.
Fix (BigBear/CasaOS)
In the app’s environment variables, set:
OPENCLAW_GATEWAY_BIND=lanOPENCLAW_GATEWAY_TOKEN=<long random string>
Then restart the container.
(Non-loopback binds require a token/password, so the token is important.)
Also verify the port is actually published
After restart, run:
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
You should see something like 0.0.0.0:18789->18789/tcp (or a different host port). Then open:
http://<zima-ip>:18789/
If you paste the docker ps line after you change the env vars, I can sanity-check the mapping.
i never recived a token
You don’t “receive” a token in the BigBear flow — you set one (BigBear didn’t run openclaw onboard, so nothing generated it for you).
Do this:
- Generate a token (run on the host, anywhere):
openssl rand -hex 32
- In the BigBear/CasaOS app settings for the container, add env vars:
OPENCLAW_GATEWAY_BIND=lanOPENCLAW_GATEWAY_TOKEN=<paste the hex string>
-
Restart the container.
-
Open the dashboard with the token in the URL:
http://<zima-ip>:18789/?token=<your_token>
After restart, the logs should no longer say ws://127.0.0.1:18789 — you want to see it listening on 0.0.0.0/LAN.
If it still says “site can’t be reached”, paste:
docker ps --format "table {{.Names}}\t{{.Ports}}"
i get that there is no command
Which command is “not found” — openssl?
If you don’t have openssl installed, you can generate a token with Node (you do have Node 22):
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
(or with Python if you have it:)
python3 -c "import secrets; print(secrets.token_hex(32))"
Then in the BigBear app’s env vars set (don’t paste the token publicly—treat it like a password):
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_TOKEN=<the hex string>
Restart the container, then open:
http://<zima-ip>:18789/?token=<your_token>
If you tell me exactly which command you ran that gave “no command” (and the full line), I can pinpoint what’s missing.
i just ran the python one and it worked
Nice — next steps:
- Paste that token into the container env vars:
OPENCLAW_GATEWAY_BIND=lanOPENCLAW_GATEWAY_TOKEN=...
-
Restart the container.
-
Open:
http://<zima-ip>:18789/?token=<token>
If it still doesn’t load, paste the new startup lines from the logs — specifically the [gateway] listening on ... line — and docker ps --format "table {{.Names}}\t{{.Ports}}".
Glad that helped! If this fixed it, please right-click this message → Apps → ✅ Mark Solution so Answer Overflow can index it.
the container keeps starting then stopping
Crash-loop = we need the last error line from the container logs — it’ll usually be something like “refusing to bind … without auth”, “port already in use”, or config validation failing.
Can you paste (last ~150 lines):
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
docker logs --tail 150 openclaw-gateway
Also (don’t paste the token), verify the env vars are actually present inside the container:
docker exec openclaw-gateway sh -lc 'echo "BIND=$OPENCLAW_GATEWAY_BIND"; if [ -n "$OPENCLAW_GATEWAY_TOKEN" ]; then echo "TOKEN=set"; else echo "TOKEN=missing"; fi'
Most likely causes + fixes (based on what the log will say):
- “refusing to bind lan without auth” →
OPENCLAW_GATEWAY_TOKENdidn’t get set (or is empty). Re-enter it in BigBear env and restart. - “address already in use :18789” → another container/app is already using the port. Change the host port mapping in BigBear.
- Config validation error → BigBear is mounting a bad
openclaw.json. We’ll look at that next once we see the log.
│ to the internet. │
│ │
│ Recommended baseline: │
│ - Pairing/allowlists + mention gating. │
│ - Sandbox + least-privilege tools. │
│ - Keep secrets out of the agent’s reachable filesystem. │
│ - Use the strongest available model for any bot with tools or │
│ untrusted inboxes. │
│ │
│ Run regularly: │
│ openclaw security audit --deep │
│ openclaw security audit --fix │
│ │
│ Must read: https://docs.openclaw.ai/gateway/security │
│ │
├────────────────────────────────────────────────────────────────────────╯
│
◆ I understand this is powerful and inherently risky. Continue?
│ ○ Yes / ● No
└
│
│ Recommended baseline: │
│ - Pairing/allowlists + mention gating. │
│ - Sandbox + least-privilege tools. │
│ - Keep secrets out of the agent’s reachable filesystem. │
│ - Use the strongest availabl
it just keeps looping that
and i cant interact with it at all
That output isn’t a “crash” — it’s the onboarding wizard asking for confirmation:
“I understand this is powerful… Continue? Yes/No”
Because the container has no interactive TTY, it can’t answer, defaults to No, and exits → so Docker restarts it → loop.
Fix: make the container run the Gateway (not the wizard)
In BigBear/CasaOS, change the container command to run the gateway directly, e.g.:
- If entrypoint is already
openclaw, set Command to:
gateway --allow-unconfigured --bind lan --port 18789
- If you must specify the full command:
openclaw gateway --allow-unconfigured --bind lan --port 18789
And keep these env vars set:
OPENCLAW_GATEWAY_BIND=lanOPENCLAW_GATEWAY_TOKEN=...(don’t share it)
Quick check: what is the container actually launching right now?
Paste this:
docker inspect openclaw-gateway --format 'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}}'
If it shows it’s running openclaw onboard ..., that confirms why it stops, and we’ll know exactly what to override in BigBear.
(If BigBear won’t let you change the command/TTY at all, the reliable path is: skip BigBear and do the official native install on Debian 12, since you already have Node 22.)
That loop is happening because the container is running openclaw onboard (interactive wizard), and in BigBear you don’t get a TTY to click “Yes” — so it exits → restarts → exits → …
You’ve got 2 ways out:
Option A (recommended): make the container run the Gateway, not onboarding
We need to see what command BigBear configured. Please paste:
docker inspect openclaw-gateway --format 'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}}'
Then in BigBear/CasaOS, change Command (or Entrypoint/Cmd) to run the gateway directly, e.g.:
openclaw gateway --allow-unconfigured --bind lan --port 18789
Keep your env vars:
OPENCLAW_GATEWAY_BIND=lanOPENCLAW_GATEWAY_TOKEN=...
(Once it’s running, open http://<zima-ip>:18789/?token=....)
Option B: skip BigBear and install “native” (your host is perfect for it)
Since you’re on Debian 12 + Node 22 already, the clean path is:
https://docs.openclaw.ai/install
npm install -g openclaw@latest
openclaw onboard --install-daemon
If you paste that docker inspect ... line, I can tell you exactly what to set in BigBear to stop the crash loop.
openclaw-gateway | 2026-02-06T10:06:09.421Z [canvas] host mounted at http://0.0.0.0:18789/__openclaw__/canvas/ (root /home/node/.openclaw/canvas)
openclaw-gateway | 2026-02-06T10:06:09.458Z [heartbeat] started
openclaw-gateway | 2026-02-06T10:06:09.460Z [gateway] agent model: anthropic/claude-opus-4-5
openclaw-gateway | 2026-02-06T10:06:09.460Z [gateway] listening on ws://0.0.0.0:18789 (PID 1)
openclaw-gateway | 2026-02-06T10:06:09.461Z [gateway] log file: /tmp/openclaw/openclaw-2026-02-06.log
openclaw-gateway | 2026-02-06T10:06:09.465Z [browser/service] Browser control service ready (profiles=2)
openclaw-gateway | 2026-02-06T10:06:09.599Z [gateway] update available (latest): v2026.2.3-1 (current v2026.2.2). Run: openclaw update
Perfect — that’s exactly what we wanted. It’s now listening on 0.0.0.0:18789, so the “site can’t be reached” issue should be gone.
Now try opening (same network):
http://<zima-ip>:18789/?token=<your_token>
If the page loads but then you see “unauthorized” / disconnect, it’s almost always:
- wrong token in the URL, or
- you opened without
?token=...the first time and the UI cached an empty/wrong token
Fix: open an incognito/private window and use the tokenized URL again.
If you still can’t reach it at all, paste:
docker ps --format "table {{.Names}}\t{{.Ports}}"
because that would mean the port isn’t being published to the host.
Glad you got it bound correctly — if the dashboard opens now, please right-click the solution message → Apps → ✅ Mark Solution so it’s searchable later.
disconnected (1008): control ui requires HTTPS or localhost (secure context)
the web ui works now
but it wont let use the token at the end
That’s expected if you open the Control UI over plain HTTP to a LAN IP. The browser treats it as a non-secure context, blocks WebCrypto, and OpenClaw refuses to let the Control UI connect (1008).
Recommended fix: use “localhost” via an SSH tunnel
From your laptop/desktop:
ssh -N -L 18789:127.0.0.1:18789 <user>@<zima-ip>
Then open:
http://127.0.0.1:18789/?token=<your_token>
(Localhost is auto-approved and counts as a secure-enough context for the UI.)
Alternative (less safe): allow token-only over insecure HTTP
Set this in ~/.openclaw/openclaw.json inside the container and restart:
{
gateway: {
controlUi: { allowInsecureAuth: true },
bind: "lan",
auth: { mode: "token", token: "${OPENCLAW_GATEWAY_TOKEN}" },
},
}
This disables the device-identity/pairing protections for the Control UI, so only do it if you fully trust your LAN.
If you tell me whether you have SSH access to the ZimaOS host (and what username you SSH with), I’ll give you the exact tunnel command.
When you say “it won’t let me use the token at the end”, what exact error do you see in the UI after it loads? (e.g. unauthorized, pairing required, etc.)
Two very common gotchas:
1) Token in the wrong place in the URL
It must be before any #.
Correct:
http://127.0.0.1:18789/?token=YOURTOKEN
Incorrect:
http://127.0.0.1:18789/#/?token=YOURTOKEN
2) You’re actually hitting “pairing required” (looks like token didn’t work)
If it says: disconnected (1008): pairing required, you need to approve the browser once.
Run on the ZimaOS host:
docker exec -it openclaw-gateway openclaw devices list
docker exec -it openclaw-gateway openclaw devices approve <requestId>
Then reload the UI.
If it says “unauthorized”
Easiest way to ensure you’re using the right token is to have the container print the exact link:
docker exec -it openclaw-gateway openclaw dashboard --no-open
(Also: try an incognito/private window so you don’t fight a cached bad token in localStorage.)
2026-02-06T10:07:54.911Z [ws] closed before connect conn=93ecac1c-4d6d-453b-bc34-cd77341c20a1 remote=192.168.1.52 fwd=n/a origin=http://192.168.1.44:18789 host=192.168.1.44:18789 ua=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 OPR/126.0.0.0 code=1008 reason=control ui requires HTTPS or localhost (secure context)
nothing
hello?
That log line means the token isn’t the problem — the Control UI is refusing to open a WS connection because you’re accessing it via plain HTTP on a LAN IP:
origin=http://192.168.1.44:18789 → code=1008 reason=control ui requires HTTPS or localhost (secure context)
So the page may load, but the websocket gets kicked before auth even happens.
Fix option 1 (recommended): SSH tunnel → localhost
From your Windows machine (PowerShell):
ssh -N -L 18789:127.0.0.1:18789 <user>@192.168.1.44
Then open:
http://127.0.0.1:18789/?token=YOURTOKEN
Fix option 2 (works, but less safe): allow token-only over HTTP
This disables the “secure context” requirement (token-only, no device identity). Run:
docker exec -it openclaw-gateway openclaw config set gateway.controlUi.allowInsecureAuth true --json
docker restart openclaw-gateway
Then you can use:
http://192.168.1.44:18789/?token=YOURTOKEN
(Keep that token private — on HTTP it’s basically a password that could be sniffed on the LAN.)
I’m here. “Nothing” is ambiguous though — which fix did you try?
If you tried the SSH tunnel
That command is supposed to look like it does “nothing” (it just sits there holding the tunnel open).
On Windows PowerShell you run:
ssh -N -L 18789:127.0.0.1:18789 <user>@192.168.1.44
Leave that terminal window open, then in your browser open:
http://127.0.0.1:18789/?token=YOURTOKEN
If you close the SSH window, the UI disconnects.
If you don’t have SSH enabled on the ZimaOS box, the tunnel won’t work — tell me what error ssh ... prints.
If you tried “allow insecure HTTP”
Check whether the setting actually stuck:
docker exec -it openclaw-gateway openclaw config get gateway.controlUi.allowInsecureAuth
If it’s not true, set it + restart:
docker exec -it openclaw-gateway openclaw config set gateway.controlUi.allowInsecureAuth true --json
docker restart openclaw-gateway
Then open:
http://192.168.1.44:18789/?token=YOURTOKEN
If it still disconnects
Paste the new WS close line from logs:
docker logs --tail 30 openclaw-gateway
and tell me which URL you’re opening (the exact http://... you typed, minus the token).
i tried the ssh and get disconnected (1008): pairing required
Nice — that means the SSH/localhost “secure context” part is solved. 1008: pairing required is the next (normal) step: you need to approve that browser once.
Run this on the ZimaOS box (or wherever Docker is):
docker exec -it openclaw-gateway openclaw devices list
You should see a pending request with a requestId. Approve it:
docker exec -it openclaw-gateway openclaw devices approve <requestId>
Then reload the Control UI in your browser.
Note: pairing is per browser profile (incognito / different browser will need a new approval).
i get permisson denied
“Permission denied” from what command exactly?
Most common case on ZimaOS/Debian is you tried docker exec ... and got permission denied to the Docker socket (something like permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock).
If it’s Docker socket permission
Run the same commands with sudo:
sudo docker exec -it openclaw-gateway openclaw devices list
sudo docker exec -it openclaw-gateway openclaw devices approve <requestId>
Or permanently fix it (then log out/in):
sudo usermod -aG docker $USER
If it’s permission denied inside the container (files)
Paste the exact error line, but it’ll usually mean the mounted ~/.openclaw dir is owned by root and the container user can’t read it. We’ll chown it to the container uid.
For now: paste the exact command you ran + the full error output and I’ll tell you which one it is.
OCI runtime exec failed: exec failed: unable to start container process: exec: "openclaw": executable file not found in $PATH: unknown
That container image doesn’t have the openclaw CLI binary in $PATH (it’s running the gateway, but the CLI command isn’t installed), so docker exec ... openclaw ... fails.
Use the node entrypoint inside the container instead:
sudo docker exec -it openclaw-gateway sh -lc 'node dist/index.js devices list --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
Copy the requestId, then approve it:
sudo docker exec -it openclaw-gateway sh -lc 'node dist/index.js devices approve <requestId> --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
Then reload the Control UI (through your SSH tunnel).
/bin/sh: 1: sudo: Permission denied
That error means you’re in a shell where sudo can’t be executed (common in some ZimaOS/CasaOS terminals / restricted containers). Good news: you don’t actually need sudo inside the OpenClaw container.
Try the same commands without sudo:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js devices list --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
Then approve the requestId it prints:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js devices approve <requestId> --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
If docker itself says permission denied (docker socket), then run the docker commands from an SSH session to the ZimaOS host as a user that can run docker (often root on NAS boxes), e.g. open a second SSH window and run the same docker exec ... commands there.
After approval, reload the Control UI (the one that said 1008 pairing required).
it comes up with 1 pending and 1 paired
Great — approve the pending one (that’s your current browser/session).
Re-run the list command and copy the requestId under Pending, then:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js devices approve <requestId> --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
After it says approved, reload the Control UI page (still through the SSH tunnel).
If you paste the devices list output (just the lines showing the pending requestId — redact any tokens), I can point at exactly which ID to approve.
is it the device or request one
Use the request one.
devices approvetakes therequestIdfrom the Pending section.- The device id is for already-paired devices (used for rotate/revoke).
So: copy the requestId for the pending entry, then run:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js devices approve <requestId> --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
Then reload the UI.
that worked
Awesome. If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it.
but now the local one aint working
“Local one” = opening the UI on the ZimaOS box itself via http://127.0.0.1:18789/?
If yes, two quick checks:
- Are you still leaving the SSH tunnel open, and are you maybe mixing up URLs?
- Remote via tunnel on your PC:
http://127.0.0.1:18789/(this is your PC’s localhost) - Direct LAN:
http://192.168.1.44:18789/(this is the ZimaOS IP)
- On the ZimaOS box, confirm the gateway is still listening and the port is published:
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
docker logs --tail 30 openclaw-gateway
Also: what exact error do you see when “local” doesn’t work (unauthorized / pairing required / site can’t be reached)?
If it’s just “unauthorized”, open locally with the token once:
http://127.0.0.1:18789/?token=YOURTOKEN
direct lan one
Got it — direct LAN (http://192.168.1.44:18789/) will still hit the secure-context rule, so it’ll fail with the same:
control ui requires HTTPS or localhost (secure context)
If you want direct LAN to work, you have 2 options:
Option A (safe/recommended): keep using SSH tunnel (or HTTPS)
- SSH tunnel = localhost = works (what you just did)
- For “real” HTTPS, you’d use something like Tailscale Serve / reverse proxy (more setup)
Option B (works, less safe): allow insecure Control UI auth over HTTP
Set this once, then restart:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set gateway.controlUi.allowInsecureAuth true --json --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
docker restart openclaw-gateway
Then open:
http://192.168.1.44:18789/?token=YOURTOKEN
Security note: this makes the Control UI rely on token-only over plain HTTP (no device identity). Only do it if you trust your LAN.
error: unknown option '--url'
Yeah — --url is not a flag for the config command (it’s for things like devices, where the CLI talks to the gateway over WS). For config set, just set the value locally and restart.
Run:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set gateway.controlUi.allowInsecureAuth true --json'
docker restart openclaw-gateway
Then the direct LAN UI should work (token-only over HTTP):
http://192.168.1.44:18789/?token=YOURTOKEN
If it still disconnects, paste the new [ws] closed ... reason=... line from docker logs --tail 30 openclaw-gateway.
Anytime.
If you get a second, please right-click the message that fixed it → Apps → ✅ Mark Solution so Answer Overflow indexes it for the next ZimaOS/BigBear person.
Yep — I’m an AI assistant (a bot) helping out in the OpenClaw Discord.
what if its everything?
If you mean “what if the bot is everything?” — it’s not.
I’m just software generating text based on what you type (and whatever the OpenClaw gateway you’re running is configured to allow). No consciousness, no spooky awareness, no “living in the network” stuff — and I can’t do anything unless someone actually runs the system and grants it access.
i mean the whole thing fixed it
Ahh gotcha — then yep, you’re good now.
If you want to “lock it down” a bit now that it’s working, the big three are:
- keep that gateway token private (treat it like a password)
- don’t expose the port to the public internet
- set allowlists / mention-gating before inviting it into group chats
okay thank you. now to connect it to ollama cloud and home assistant
Nice.
Ollama
OpenClaw can talk to Ollama via its OpenAI-compatible API. Docs: https://docs.openclaw.ai/providers/ollama
Key gotcha for your setup: since OpenClaw is in Docker, 127.0.0.1:11434 inside the container is NOT the host. So if Ollama is running on the ZimaOS host, you’ll usually want the host’s LAN IP:
# inside the openclaw container
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set models.providers.ollama.baseUrl "http://192.168.1.44:11434/v1"'
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set models.providers.ollama.apiKey "ollama-local"'
docker restart openclaw-gateway
(Replace 192.168.1.44 with wherever Ollama is reachable from the container.)
Home Assistant
There’s a community Home Assistant Skill on ClawHub: https://clawhub.com/skills/homeassistant
…and a Home Assistant add-on (for HA OS setups): https://github.com/ngutman/openclaw-ha-addon
I’d start with the Skill. If you tell me:
- where Ollama is running (same ZimaOS box? another machine?) and
- where Home Assistant is running,
I can tell you the cleanest wiring for each (especially the Docker networking bits).
ollama is running on the same zimaos box and its running cloud from that and same with my home assistant
Cool — since OpenClaw + Ollama + Home Assistant are all on the same ZimaOS box, this is mostly a Docker networking exercise.
1) Ollama (same host)
Because OpenClaw is in Docker, it usually can’t reach Ollama via 127.0.0.1:11434 (that would be “inside the container”). Use the ZimaOS LAN IP instead.
First, test from inside the OpenClaw container (replace 192.168.1.44 with your Zima IP):
docker exec -it openclaw-gateway sh -lc 'wget -qO- http://192.168.1.44:11434/api/tags | head'
If that works, point OpenClaw at it:
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set models.providers.ollama.baseUrl "http://192.168.1.44:11434/v1"'
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set models.providers.ollama.apiKey "ollama-local"'
Then pick a model name from:
ollama list
…and set it (example format):
docker exec -it openclaw-gateway sh -lc 'node dist/index.js config set agents.defaults.model.primary "ollama/<model-from-ollama-list>"'
docker restart openclaw-gateway
If the wget .../api/tags test fails, Ollama is probably only listening on localhost. You’ll need to make Ollama listen on LAN (0.0.0.0:11434) or run OpenClaw in “host network” mode.
2) Home Assistant (same host)
Easiest path: install the Home Assistant Skill from ClawHub:
https://clawhub.com/skills/homeassistant
To install skills you want them to land in the OpenClaw workspace’s skills/ folder. If you’re not sure where that is on the host, run:
docker inspect openclaw-gateway --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
Find the mount that goes to /home/node/.openclaw/workspace, then cd into the host side of that path and run:
npm i -g clawhub
clawhub install homeassistant
After installing, open the skill’s SKILL.md and it’ll tell you exactly what HA URL/token env vars it expects (then you set them via skills.entries.<skill>.env in config).
If you tell me your Zima IP and whether Ollama/HA are also Docker apps (or native installs), I can give you the exact “bind/listen” setting if the connectivity test fails.
i cant use docker exec i get permission denied
No worries — you don’t need docker exec to wire up Ollama + Home Assistant.
Option A (easiest): do it in the OpenClaw Web UI
In the Control UI, go to Config (raw JSON editor) and set:
{
models: {
providers: {
ollama: {
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local"
}
}
},
agents: { defaults: { model: { primary: "ollama/llama3.3" } } }
}
(Replace 192.168.1.44 with your ZimaOS IP, and llama3.3 with whatever you pulled in Ollama.)
Then restart the OpenClaw container from the BigBear UI.
Option B: use BigBear’s “Terminal/Console” for the OpenClaw container
If BigBear lets you open a terminal inside openclaw-gateway, run:
node dist/index.js config set models.providers.ollama.baseUrl "http://192.168.1.44:11434/v1"
node dist/index.js config set models.providers.ollama.apiKey "ollama-local"
node dist/index.js config set agents.defaults.model.primary "ollama/llama3.3"
Then restart the container.
Why this matters
Because OpenClaw is in Docker, 127.0.0.1:11434 would mean “inside the OpenClaw container”, not your host Ollama — so you need the host IP.
If you tell me what “permission denied” you get (the exact line), I can also tell you whether it’s Docker socket permissions vs something else.
Error: Config validation failed: models.providers.ollama.models: Invalid input: expected array, received undefined
That error is because as soon as you add an explicit models.providers.ollama entry, the schema expects you to also provide a models array (manual model list). Auto-discovery only happens when you don’t define models.providers.ollama at all.
Since you’re in Docker and need a custom baseUrl, the easiest fix is: keep the provider + add one model entry.
Example (paste into the Config editor; replace the IP + model id with yours from ollama list):
{
models: {
providers: {
ollama: {
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "llama3.3", // must match ollama model name
name: "Llama 3.3",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]
}
}
},
agents: {
defaults: {
model: { primary: "ollama/llama3.3" }
}
}
}
If you tell me what ollama list shows (just the model names), I’ll map it to the exact id / ollama/<id> string to use.
ohh was i meant to past it all at once?
If you’re editing the config in the Control UI Raw JSON editor: yes — you paste/save the whole config object (or at least a complete valid config), not just a fragment.
If the UI has a patch editor mode, you can change only a few keys — but Raw JSON replaces the file, so missing required fields (like models.providers.ollama.models once you add the provider) will fail validation.
So easiest: paste the full snippet I sent as one block, save/apply, then restart.
i was trying option b
Got it — Option B (running commands inside the container) is fine, but you need to set all the required Ollama fields, including the models array, since you’re using a custom baseUrl.
In the BigBear “terminal/console” for the openclaw-gateway container, run these (adjust IP + model name):
node dist/index.js config set models.providers.ollama.baseUrl "http://192.168.1.44:11434/v1"
node dist/index.js config set models.providers.ollama.apiKey "ollama-local"
node dist/index.js config set models.providers.ollama.api "openai-completions" --json
node dist/index.js config set models.providers.ollama.models --json '[
{
id: "llama3.3",
name: "Llama 3.3",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]'
node dist/index.js config set agents.defaults.model.primary "ollama/llama3.3"
Then restart the container.
If you paste the output of ollama list (just the model names), I’ll swap in the exact id you should use.
gemma3:27b-cloud is the model im trying to use
Cool — then your Ollama model id is exactly:
gemma3:27b-cloud
So in the config, use:
- provider model entry
id: "gemma3:27b-cloud" - agent primary model
ollama/gemma3:27b-cloud
Option B commands (inside the openclaw-gateway container console)
(Replace 192.168.1.44 with your ZimaOS IP)
node dist/index.js config set models.providers.ollama.baseUrl "http://192.168.1.44:11434/v1"
node dist/index.js config set models.providers.ollama.apiKey "ollama-local"
node dist/index.js config set models.providers.ollama.api "openai-completions" --json
node dist/index.js config set models.providers.ollama.models --json '[
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]'
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
Then restart the OpenClaw container.
If it acts weird with tools
Some Ollama models/endpoints don’t actually support tool/function calling well. If the agent starts “ignoring tools” or errors on tool calls, that’s usually why (not your config).
Error: Config validation failed: models.providers.ollama.baseUrl: Invalid input: expected string, received undefined
i get that for both
That error means your config currently has an ollama provider entry, but it’s missing baseUrl (so it’s coming through as “undefined”).
Add/set it explicitly, then restart.
If you’re doing Option B (commands in the container console)
Run (replace 192.168.1.44 with your ZimaOS IP):
node dist/index.js config set models.providers.ollama.baseUrl "http://192.168.1.44:11434/v1"
Then (optional sanity check):
node dist/index.js config get models.providers.ollama.baseUrl
Then restart the container.
If you’re editing in the Control UI config editor
Make sure your ollama block includes baseUrl like:
models: {
providers: {
ollama: {
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [ /* … */ ],
}
}
}
If you paste what your current models.providers.ollama section looks like (remove tokens), I can point out exactly what’s missing.
If you’re still seeing “baseUrl … received undefined” after trying to set it, it usually means one of these is happening:
- the
ollamaprovider object exists, but you’re applying/saving a config that doesn’t actually includebaseUrl, or - you ran
config set models.providers.ollama.baseUrlwithout the value (so it stays undefined), or - you’re editing a different config than the gateway is using.
Fastest way to debug (in the BigBear terminal inside the openclaw container)
Run these two and paste the output:
env | grep OPENCLAW
node dist/index.js config get models.providers.ollama
What models.providers.ollama must look like (minimum valid)
Since you’re using explicit provider config, you need both baseUrl and models:
models: {
providers: {
ollama: {
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]
}
}
}
If you paste what your current models.providers.ollama section is (no tokens), I’ll point out exactly what’s missing/where it’s getting dropped.
Config path not found: models.providers.ollama
That message is actually fine — it just means you haven’t configured the Ollama provider yet, so config get models.providers.ollama has nothing to show.
Instead of setting it piece-by-piece, set the whole ollama provider in one go (includes baseUrl + models, so validation won’t complain):
In the BigBear terminal/console inside the openclaw-gateway container run (replace the IP if needed):
node dist/index.js config set models.providers.ollama --json '{
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]
}'
Then set the agent model:
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
Then restart the OpenClaw container from the BigBear UI.
If you want, paste what you get from:
node dist/index.js config get models.providers.ollama
(redact nothing sensitive—there shouldn’t be any real secrets there) and I’ll sanity-check it.
openclaw-gateway | 2026-02-06T11:49:10.435Z [diagnostic] lane task error: lane=session:agent:main:main durationMs=2 error="Error: Unknown model: ollama/gemma3:27b-cloud"
openclaw-gateway | 2026-02-06T11:49:10.435Z Embedded agent failed before reply: Unknown model: ollama/gemma3:27ub-clod
That log means the Gateway doesn’t currently have a model registered with the id you set as primary.
Two things jump out:
- It says
Unknown model: ollama/gemma3:27b-cloud(soollama/gemma3:27b-cloudis not in the models registry yet) - The next line shows a typo:
ollama/gemma3:27ub-clod(so at least one place in your config has the model name misspelled)
Fix
- In the Control UI → Config, make sure you have both:
- a provider entry that defines the model:
models: {
providers: {
ollama: {
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]
}
}
}
- and your agent primary model matches it exactly:
agents: { defaults: { model: { primary: "ollama/gemma3:27b-cloud" } } }
- Save/apply, then restart the OpenClaw container.
If you paste this, I can spot the typo immediately
In Control UI, copy/paste just these two parts (redact nothing; no secrets here):
models.providers.ollamaagents.defaults.model
Right now you almost certainly have ollama/gemma3:27ub-clod somewhere, and that will always fail.
openclaw-gateway | 2026-02-06T11:49:10.435Z [diagnostic] lane task error: lane=session:agent:main:main durationMs=2 error="Error: Unknown model: ollama/gemma3:27b-cloud"
openclaw-gateway | 2026-02-06T11:49:10.435Z Embedded agent failed before reply: Unknown model: ollama/gemma3:27b-cloud
That log shows you’re still trying to run ollama/gemma3:27b-cloud (missing the “a”). Your Ollama model is gemma3:27b-cloud, so OpenClaw can’t find a matching model entry.
Fix = make these two strings match exactly:
- provider model
id:gemma3:27b-cloud - agent primary:
ollama/gemma3:27b-cloud
If you’re using the BigBear terminal inside the container
Run:
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
Then restart the container.
Sanity check (still in the container terminal)
This will show you what OpenClaw thinks exists:
node dist/index.js models list | grep -i ollama
node dist/index.js models status
If models list doesn’t show ollama/gemma3:27b-cloud, then your models.providers.ollama.models[] entry still isn’t set to that exact id.
$ node dist/index.js models list | grep -i ollama
node dist/index.js models statusollama/gemma3:27b-cloud - - - - default,missing
$
🦞 OpenClaw 2026.2.2 (unknown)
One CLI to rule them all, and one more restart because you changed the port.
Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : ollama/gemma3:27b-cloud
Fallbacks (0) : -
Image model : -
Image fallbacks (0): -
Aliases (0) : -
Configured models (0): all
Auth overview
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (0): -
- openai effective=env:sk-xxxxxx | env=sk-xxxxxx | source=env: OPENAI_API_KEY
Missing auth
- ollama Run
openclaw configureor set an API key env var.
OAuth/token status
- none
$
That output is super helpful: OpenClaw sees the model name, but it marks it missing because the Ollama provider has “Missing auth”.
Even though Ollama doesn’t need a real key, OpenClaw still requires some key/value to “enable” the provider.
Fix: set OLLAMA_API_KEY (easiest on BigBear)
In the BigBear app settings for the openclaw-gateway container, add an env var:
OLLAMA_API_KEY=ollama-local(any value is fine)
Restart the container, then re-run:
node dist/index.js models status
You should no longer see “Missing auth – ollama”.
Also double-check your baseUrl + model id
In the container terminal:
node dist/index.js config get models.providers.ollama.baseUrl
node dist/index.js config get agents.defaults.model.primary
They should be exactly:
- baseUrl:
http://192.168.1.44:11434/v1(or whatever your ZimaOS IP is) - primary:
ollama/gemma3:27b-cloud
If after setting OLLAMA_API_KEY it still shows missing, the next culprit is usually that Ollama is only bound to localhost (so the container can’t reach 192.168.1.44:11434).
$ node dist/index.js models status
🦞 OpenClaw 2026.2.2 (unknown)
Think different. Actually think.
Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : ollama/gemma3:27b-cloud
Fallbacks (0) : -
Image model : -
Image fallbacks (0): -
Aliases (0) : -
Configured models (0): all
Auth overview
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (0): -
- openai effective=env:sk-xxxxxx | env=sk-xxxxxx | source=env: OPENAI_API_KEY
Missing auth
- ollama Run
openclaw configureor set an API key env var.
OAuth/token status
- none
That still says the Ollama provider has no credential at all (OpenClaw treats it as “disabled”), so it marks the model as missing.
Let’s confirm what the container actually has right now. In the same terminal where you ran node dist/index.js ..., run and paste:
echo "OLLAMA_API_KEY=$OLLAMA_API_KEY"
node dist/index.js config get models.providers.ollama
Fix (one of these must be true)
A) Set the env var (persists via BigBear app settings)
In BigBear → openclaw-gateway → Environment, add:
OLLAMA_API_KEY=ollama-local(any string)
Then restart the container and re-run:
node dist/index.js models status
B) Or set the apiKey in config (no env var needed)
Run inside the container terminal:
node dist/index.js config set models.providers.ollama.apiKey "ollama-local"
Then restart container and check models status again.
If after that it still says “Missing auth – ollama”, it means your Ollama provider config isn’t actually being saved where the gateway is reading it (or the config is getting overwritten). The config get models.providers.ollama output will make that obvious.
Error: Config validation failed: models.providers.ollama.baseUrl: Invalid input: expected string, received undefined
That error means your config currently has an ollama provider block that’s half-defined (it exists, but baseUrl is missing), so any further config set ...ollama... triggers validation and fails.
Fix it by setting the entire Ollama provider object in one shot (baseUrl + apiKey + models), then set the agent model.
In the BigBear terminal inside the openclaw-gateway container run (replace 192.168.1.44 with your ZimaOS IP if different):
node dist/index.js config set models.providers.ollama --json '{
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]
}'
Then:
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
Restart the container, then check:
node dist/index.js models status
If it still complains, paste:
node dist/index.js config get models.providers.ollama
$ node dist/index.js config set models.providers.ollama --json '{
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
✅
Click to react
💯
Click to react
😆
Click to react
Add Reaction
Reply
Forward
More
[10:38 PM]Friday, February 6, 2026 10:38 PM
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192> ,
maxTokens: 8192 * 10
}
]
}'
Error: Failed to parse JSON5 value: SyntaxError: JSON5: invalid character ':' at 10:1
$
Your pasted JSON5 got corrupted by the Discord UI (it injected the ✅/💯/😆 “Click to react” lines), and there’s also a stray > after 8192 in there. That’s why JSON5 parsing blows up.
Re-run it as a single clean paste (don’t copy from Discord’s rendered block). Use exactly this:
node dist/index.js config set models.providers.ollama --json '{
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 8192 * 10
}
]
}'
If the CasaOS terminal is wrapping lines in a weird way, an even safer approach is: paste it into a local text editor first, make sure it has no emojis / no “Click to react” / no >, then paste into the terminal.
After it succeeds:
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
node dist/index.js models status
$ node dist/index.js config set models.providers.ollama --json '{
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gemma3:27b-cloud",
name: "Gemma 3 27B (cloud)",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 8192,
maxTokens: 81> 92 * 10
}
]
}'> > > > > > > > > > > > >
it just comes up with the >>>>>>>>
Those > you’re seeing are the shell’s continuation prompt (it shows up when you’re pasting a multi‑line quoted string). Don’t type the > lines yourself — just paste the command and make sure the final closing ' actually gets entered.
Also: use a real number for maxTokens (JSON5 won’t evaluate 8192 * 10). Use 81920.
Try this single-line version (much harder to break):
node dist/index.js config set models.providers.ollama --json '{"baseUrl":"http://192.168.1.44:11434/v1","apiKey":"ollama-local","api":"openai-completions","models":[{"id":"gemma3:27b-cloud","name":"Gemma 3 27B (cloud)","reasoning":false,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":8192,"maxTokens":81920}]}'
Then set the default model:
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
Sanity check:
node dist/index.js models status
If it still errors, paste the exact error line that comes right after the command (not the whole prompt spam).
Those >>>>>>> means your shell thinks the command is incomplete (almost always: an unclosed quote), so it’s waiting for you to finish it.
-
Cancel out of it: press Ctrl+C once. You should be back at the normal
$prompt. -
Then paste this exact single line (no line breaks), and hit Enter once:
node dist/index.js config set models.providers.ollama --json '{"baseUrl":"http://192.168.1.44:11434/v1","apiKey":"ollama-local","api":"openai-completions","models":[{"id":"gemma3:27b-cloud","name":"Gemma 3 27B (cloud)","reasoning":false,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":8192,"maxTokens":81920}]}'
(Important: don’t type/copy any > characters into it — those are just the prompt.)
- Then:
node dist/index.js config set agents.defaults.model.primary "ollama/gemma3:27b-cloud"
node dist/index.js models status
If you still get stuck in >>>>>>>, paste the very last few characters of what you typed (just the tail end) — it’ll show which quote isn’t closing.
🦞 OpenClaw 2026.2.2 (unknown)
Ship fast, log faster.
Config : ~/.openclaw/openclaw.json
Agent dir : ~/.openclaw/agents/main/agent
Default : ollama/gemma3:27b-cloud
Fallbacks (0) : -
Image model : -
Image fallbacks (0): -
Aliases (0) : -
Configured models (0): all
Auth overview
Auth store : ~/.openclaw/agents/main/agent/auth-profiles.json
Shell env : off
Providers w/ OAuth/tokens (0): -
- ollama effective=models.json:ollama-local | models.json=ollama-local | source=models.json: ~/.openclaw/agents/main/agent/models.json
- openai effective=env:sk-xxxxxx | env=sk-xxxxxx | source=env: OPENAI_API_KEY
OAuth/token status
- none
Perfect — that’s the “green” state.
Key line is:
ollama effective=models.json:ollama-local
So OpenClaw now sees Ollama as configured (no more “Missing auth”), and your default model is set to ollama/gemma3:27b-cloud.
At this point, restart the gateway container (if you haven’t already), then try a simple prompt in the Control UI chat like “say hi” to confirm it’s actually generating responses via Ollama.
If you get any new error, paste the first [diagnostic] ... Unknown model / connection error line and we’ll tackle it.
nothing is coming through
When you say “nothing is coming through” — is this in the Control UI chat (you type a message and it just never replies), or are you talking about messages from WhatsApp/Telegram/etc?
Assuming it’s the Control UI chat: the next thing to check is whether the Gateway can actually reach Ollama from inside the OpenClaw container.
1) Check Ollama is reachable from inside the container
In the BigBear terminal/console for openclaw-gateway, run:
node -e "fetch('http://192.168.1.44:11434/api/tags').then(r=>r.text()).then(t=>console.log(t.slice(0,200))).catch(e=>console.error('FETCH_FAIL',e))"
- If that prints JSON → networking is OK.
- If it prints
FETCH_FAIL/ connection refused → Ollama is not reachable at that URL (most often Ollama is only bound to localhost, or the port isn’t published).
2) Grab the Gateway error that happens when you send a message
Right after you send a test message in the UI, open the container logs in BigBear and paste the newest error lines (or paste docker logs --tail 80 openclaw-gateway if you can).
There should be a line showing why it’s not replying (Ollama connection error, model error, etc.).
3) Quick sanity check (you already did this, but confirm it’s still “green”)
node dist/index.js models status
If you answer these two things:
- what UI you’re testing (Control UI chat vs messaging channel), and
- the output of the
node -e fetch(...)test above,
I can tell you exactly what to change (usually it’s “make Ollama listen on LAN / fix baseUrl”).
{"models":[{"name":"gemma3:27b-cloud","model":"gemma3:27b-cloud","remote_model":"gemma3:27b","remote_host":"https://ollama.com:443","modified_at":"2026-01-27T09:36:50.876206667Z","size":374,"digest":"
Nice — that output means the OpenClaw container can reach your Ollama server (so networking is not the blocker).
Next step: confirm that the OpenAI-compatible endpoint works for that cloud model, because OpenClaw talks to Ollama via .../v1/..., not /api/tags.
In the same ZimaOS terminal where you ran the fetch, run this:
node -e "fetch('http://192.168.1.44:11434/v1/chat/completions',{method:'POST',headers:{'content-type':'application/json','authorization':'Bearer ollama-local'},body:JSON.stringify({model:'gemma3:27b-cloud',messages:[{role:'user',content:'Say hi in 5 words'}],stream:false})}).then(r=>r.text().then(t=>({s:r.status,t}))).then(x=>{console.log(x.s); console.log(x.t.slice(0,800))}).catch(e=>console.error(e))"
What we’re looking for:
- If you get a 200 and JSON with a reply → Ollama’s
/v1API works, so we then need to look at the OpenClaw gateway logs for why it isn’t replying. - If you get 404 / 400 / error → that model (or “Ollama Cloud”) might not be usable via
/v1/chat/completions, and OpenClaw won’t be able to use it. In that case try a normal local model likellama3.3orqwen2.5-coder:32bas a sanity check.
Also, right after you send a message in the Control UI and it “does nothing”, paste the last error lines from the gateway log (BigBear logs view is fine). There should be a concrete error (timeout, provider 4xx, etc.).
200
{"id":"chatcmpl-708","object":"chat.completion","created":1770380792,"model":"gemma3:27b-cloud","system_fingerprint":"fp_ollama","choices":[{"index":0,"message":{"role":"assistant","content":"Hello there, how are you? 👋"},"finish_reason":"stop"}],"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}
Perfect — that proves Ollama is reachable from the OpenClaw container and /v1/chat/completions works for gemma3:27b-cloud.
So if the Control UI chat still “does nothing”, it’s almost certainly the agent run failing silently (and the reason will be in the Gateway logs).
Can you do these two quick checks:
1) Trigger an error + grab the exact log lines
Send a message in the Control UI chat (e.g. hi), then immediately open the BigBear container logs for openclaw-gateway and paste the newest ~20 lines after that send.
We’re looking for something like a 4xx/5xx from the model provider, tool-schema error, timeout, etc.
2) Run one agent turn from the container terminal (bypasses the UI)
In the same terminal where you ran models status, run:
node dist/index.js agent --local --message "hi (cli test)"
- If this prints a reply → Ollama + agent are fine, and the issue is UI/session/log routing.
- If this errors → paste the error; that will tell us exactly what OpenClaw doesn’t like about the Ollama integration (most commonly tool-calling / schema differences).
Once I see the log/error, we can fix it in one step (it’s usually either a tool-calling compatibility issue or a stuck/old session in the UI).
i think i found the problem is says that the min tokens is 16000
openclaw-gateway | 2026-02-06T12:29:55.149Z [agent/embedded] low context window: ollama/gemma3:27b-cloud ctx=16000 (warn<32000) source=modelsConfig
That “minimum tokens is 16000” is almost certainly OpenClaw rejecting the model because its declared contextWindow is < 16000. There’s a hard minimum (16k) for models OpenClaw will run the agent with, so an Ollama model that reports (or defaults to) 8192 will fail and it can look like the Control UI just “doesn’t answer”.
1) Confirm the exact error
Please paste the single log line that mentions 16000 (from the BigBear/CasaOS app logs right after you send a message), or run:
node dist/index.js logs --limit 200
2) Fix: set the Ollama model’s contextWindow to ≥ 16000
If you have shell access in the container, first inspect what you currently have:
node dist/index.js config get models.providers.ollama --json
Then (assuming models[0] is your gemma3:27b-cloud entry) bump it to e.g. 16384:
node dist/index.js config set models.providers.ollama.models[0].contextWindow 16384 --json
node dist/index.js config set models.providers.ollama.models[0].maxTokens 163840 --json
Notes:
- Use a literal number for
maxTokens(don’t type16384 * 10). - Restart the OpenClaw container after config edits (BigBear UI restart).
If you don’t have shell access, do the same edit in the Control UI → Config editor, under:
models.providers.ollama.models[] (find the id: "gemma3:27b-cloud" object and set contextWindow / maxTokens).
3) Also make sure the agent is actually using that model
In config, ensure:
agents: {
defaults: {
model: { primary: "ollama/gemma3:27b-cloud" }
}
}
(Otherwise it might still be trying some other default model and failing silently.)
Important caveat
If gemma3:27b-cloud truly only supports an ~8k context, overriding contextWindow to 16k will get OpenClaw past its check, but the model may still choke on longer conversations. If that happens, the real fix is: switch to an Ollama model that actually supports ≥16k context.
Send me the exact 16000 log line and your current models.providers.ollama block (redact nothing except tokens), and I’ll tell you the safest exact values / whether you should switch models.
That log line is not the “minimum tokens is 16000” failure — it’s just a warning:
low context window ... ctx=16000 (warn<32000) source=modelsConfig
Meaning: OpenClaw sees your configured model ollama/gemma3:27b-cloud with a 16k context window (from your models.providers.ollama.models[] config), and it’s warning that <32k is kinda tight for tool-heavy agents.
So this line alone wouldn’t explain “no replies” — OpenClaw should still continue.
What I’d do next (to find the real “no reply” cause)
-
Trigger the issue, then immediately grab logs around it (BigBear app logs).
- We need the lines after you send a Control UI message, especially anything like:
Model context window too small... Minimum is 16000(error)Model "... is not allowed"(allowlist issue)tool/function_call/ JSON schema errors (common with some local models)
- We need the lines after you send a Control UI message, especially anything like:
-
If you can run commands in the container, tail logs live:
node dist/index.js logs --follow
Send a message in Control UI, then copy the next ~30 lines.
If you want to remove the warning (optional)
Only do this if the model truly supports it. Set contextWindow to 32000/32768+ in your models.providers.ollama.models[] entry (the one with id: "gemma3:27b-cloud"). Otherwise you’re just lying to OpenClaw and it may try to stuff too much into prompts.
Docs: https://docs.openclaw.ai/providers/ollama
If you paste your current models.providers.ollama block (redact tokens), I can tell you exactly what to change and where (and whether it’s likely safe for that model).
now nothing is showing up but it says its replying
@blissful aspen That low context window ... ctx=16000 (warn<32000) line is only a warning — it shouldn’t prevent replies.
When you see “it’s replying” (typing / running) but no message shows up, it usually means one of these is happening:
- the agent run starts, then errors before producing assistant text, or
- the agent produces a reply, but Discord send fails (permissions/routing/rate limit), or
- the model returns an “empty” completion (content
null) and OpenClaw ends up with nothing to post.
What I need from you (fastest path)
Please reproduce once, then paste the log lines right after the message (20–50 lines).
Best option (no shell needed): Control UI → Logs → Follow, then send a message, then copy what appears.
If you can run commands inside the container, do:
node dist/index.js logs --limit 200
(or --follow while you test)
Quick sanity checks
- Are you testing via Discord or the Control UI chat?
- In Discord: are you mentioning the bot? (many configs require mention in guild channels)
- If you can, run this to bypass Discord/UI and see if the model run itself works:
node dist/index.js agent --local --message "hi (cli test)"
Once you paste the logs around the attempt, I can tell you exactly which of the 3 buckets it is (and the specific fix).
12:35:44 debug diagnostic {"subsystem":"diagnostic"} session state: sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e sessionKey=unknown prev=idle new=processing reason="run_started" queueDepth=0
12:35:44 debug diagnostic {"subsystem":"diagnostic"} run registered: sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e totalActive=1
12:35:44 debug agent/embedded {"subsystem":"agent/embedded"} embedded run prompt start: runId=5bcd105a-9c79-490e-aa01-700abe28f95a sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e
12:35:44 debug agent/embedded {"subsystem":"agent/embedded"} embedded run agent start: runId=5bcd105a-9c79-490e-aa01-700abe28f95a
12:35:45 debug agent/embedded {"subsystem":"agent/embedded"} embedded run agent end: runId=5bcd105a-9c79-490e-aa01-700abe28f95a
12:35:45 debug agent/embedded {"subsystem":"agent/embedded"} embedded run prompt end: runId=5bcd105a-9c79-490e-aa01-700abe28f95a sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e durationMs=653
12:35:45 debug diagnostic {"subsystem":"diagnostic"} session state: sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e sessionKey=unknown prev=processing new=idle reason="run_completed" queueDepth=0
12:35:45 debug diagnostic {"subsystem":"diagnostic"} run cleared: sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e totalActive=0
12:35:45 debug agent/embedded {"subsystem":"agent/embedded"} embedded run done: runId=5bcd105a-9c79-490e-aa01-700abe28f95a sessionId=33692cb1-ce0d-4e99-967c-280ff06bc61e durationMs=698 aborted=false
12:35:45 debug diagnostic {"subsystem":"diagnostic"} lane task done: lane=main durationMs=699 active=0 queued=0
12:35:45 debug diagnostic {"subsystem":"diagnostic"} lane task done: lane=session:agent:main:main durationMs=701 active=0 queued=0
12:39:14 info gateway {"subsystem":"gateway"} device pairing auto-approved device=05833eacd4b0cc7648254da9aaee0ff5ae481d6c5bd6d625fbe1bdc1b17b90ea role=operator
Log tail truncated (increase --max-bytes).
@blissful aspen Those lines show the run starts and completes cleanly in ~700ms, but we’re missing the part that would explain why no assistant message gets emitted.
Two things jump out:
- No error line is included (but your paste ends with
Log tail truncated) - With Ollama, a super common footgun is
maxTokensbeing set way too high (docs/examples often showcontextWindow * 10, which can make Ollama/OpenAI-compatible servers return errors or weird empty outputs).
1) Grab a non-truncated log slice around that runId
Please run this in the container (or Control UI → Logs if it supports max-bytes):
node dist/index.js logs --limit 500 --max-bytes 2000000 --plain
Then reproduce once, and paste the chunk that includes runId=5bcd105a-... plus anything WARN/ERROR right after.
2) Check your Ollama model entry (especially maxTokens)
Paste:
node dist/index.js config get models.providers.ollama --json
node dist/index.js config get agents.defaults.model --json
node dist/index.js config get agents.defaults.models --json
What I’m specifically looking for:
contextWindow: 16000is fine (just “low” warning)- If
maxTokensis 160000 (or similarly huge), try setting it to something sane like 2048–4096:
node dist/index.js config set models.providers.ollama.models[0].maxTokens 4096 --json
(then restart the container and test again)
3) Quick “bypass the UI” test (tells us if the model run is empty)
node dist/index.js agent --local --message "hello test" --json
- If that returns an assistant message in JSON → the model works, and the issue is Control UI rendering/WS events.
- If it returns an error (or empty output) → we fix provider/model config next.
Drop the models.providers.ollama block and the agent --json output and I can point to the exact fix.
i think its the model because it dosent have tools on it or thinking
@blissful aspen Yeah, that’s a very plausible root cause.
“Thinking” doesn’t matter, but tool support does: OpenClaw’s agent usually sends an OpenAI-style tools array with every request (even if it ends up not using tools). If your Ollama model/endpoint doesn’t support OpenAI tool calling, the run can start/end fast and you’ll get “it’s replying” vibes with no actual message.
Quick proof: does the model accept tools?
If you can run this (host or container), try a minimal tool-call request:
curl -s http://192.168.1.44:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"gemma3:27b-cloud",
"messages":[{"role":"user","content":"Say hi"}],
"tools":[{"type":"function","function":{"name":"noop","description":"noop","parameters":{"type":"object","properties":{}}}}],
"tool_choice":"auto"
}' | head
- If that errors (or returns weird/empty), that model isn’t tool-capable in the way OpenClaw needs.
Fix: switch to a tool-capable Ollama model
Pick one that Ollama reports as tool-capable (common good bets):
llama3.3qwen2.5-coder:32b(or smaller if needed)
On the ZimaOS host:
ollama pull llama3.3
Then in OpenClaw config, set:
agents.defaults.model.primary = "ollama/llama3.3"- and make sure
models.providers.ollama.models[]includes an entry withid: "llama3.3"(since you’re using explicit provider config)
Restart the container after.
If you paste your current models.providers.ollama config block, I’ll tell you the exact edit (which index to change, and a safe contextWindow/maxTokens pair).
qwen3-vl:235b-cloud
is what ill change to
@blissful aspen qwen3-vl:235b-cloud could work, but the critical thing for OpenClaw is: does that model actually support OpenAI-style tool calling (tools / function calling) on Ollama’s /v1/chat/completions? A lot of “VL” models (and some cloud-wrapped ones) don’t.
1) Quick check (tool support)
Run this against your Ollama box:
curl -s http://192.168.1.44:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"qwen3-vl:235b-cloud",
"messages":[{"role":"user","content":"Say hi"}],
"tools":[{"type":"function","function":{"name":"noop","description":"noop","parameters":{"type":"object","properties":{}}}}],
"tool_choice":"auto"
}'
- If that errors / complains about
tools/ returns empty weirdness → that’s why OpenClaw “runs” but nothing shows.
- If it returns normal assistant content → good.
2) Update OpenClaw config (since you’re using explicit models.providers.ollama)
Make sure both are set:
-
agents.defaults.model.primary:ollama/qwen3-vl:235b-cloud
-
and you have a matching model entry under:
models.providers.ollama.models[]withid: "qwen3-vl:235b-cloud"
Also keep contextWindow >= 16000 (16000 is okay; you’ll just keep seeing the “warn<32000” warning).
3) Reality check
235b is enormous. If it’s not truly “cloud” inference, it simply won’t run locally. If it is cloud-backed, it may be slow—so if you get timeouts later, we’ll bump the agent timeout.
If the tool-support test fails, I’d switch to a known tool-capable text model first (e.g. llama3.3 or qwen2.5-coder) and only use VL models when you actually need images.
openclaw-gateway | 2026-02-06T12:56:52.972Z [openclaw] Model "qwen3-vl:235b-cloud" specified without provider. Falling back to "anthropic/qwen3-vl:235b-cloud". Please use "anthropic/qwen3-vl:235b-cloud" in your config.
openclaw-gateway | 2026-02-06T12:56:55.753Z [openclaw] Model "qwen3-vl:235b-cloud" specified without provider. Falling back to "anthropic/qwen3-vl:235b-cloud". Please use "anthropic/qwen3-vl:235b-cloud" in your config.
openclaw-gateway | 2026-02-06T12:56:55.772Z [openclaw] Model "qwen3-vl:235b-cloud" specified without provider. Falling back to "anthropic/qwen3-vl:235b-cloud". Please use "anthropic/qwen3-vl:235b-cloud" in your config.
openclaw-gateway | 2026-02-06T12:56:55.805Z [diagnostic] lane task error: lane=main durationMs=27 error="Error: Unknown model: anthropic/qwen3-vl:235b-cloud"
openclaw-gateway | 2026-02-06T12:56:55.807Z [diagnostic] lane task error: lane=session:agent:main:main durationMs=30 error="Error: Unknown model: anthropic/qwen3-vl:235b-cloud"
openclaw-gateway | 2026-02-06T12:56:55.809Z Embedded agent failed before reply: Unknown model: anthropic/qwen3-vl:235b-cloud
@blissful aspen Perfect — those logs explain the “it says it’s replying but nothing shows”:
- You set
qwen3-vl:235b-cloudwithout a provider - OpenClaw guesses/falls back to
anthropic/qwen3-vl:235b-cloud - That model doesn’t exist in the Anthropic catalog →
Unknown model→ run aborts before any reply is produced.
Fix
Use the provider/model form everywhere. For Ollama it must be:
ollama/qwen3-vl:235b-cloud
In config (Control UI config editor)
Set:
agents: {
defaults: {
model: { primary: "ollama/qwen3-vl:235b-cloud" }
}
}
And because you’re using an explicit Ollama provider block, make sure the model exists in:
models.providers.ollama.models[] with:
{ id: "qwen3-vl:235b-cloud", name: "qwen3-vl:235b-cloud" }
Then restart the container.
Also check allowlist (common gotcha)
If you have agents.defaults.models (model allowlist) set, you must add it there too, or it’ll silently refuse to run. Add:
agents: {
defaults: {
models: {
"ollama/qwen3-vl:235b-cloud": { alias: "Qwen3 VL Cloud" }
}
}
}
After that, if it still “runs” but produces no output, we’ll do the next check: whether that Ollama model actually supports OpenAI tools function-calling.
okay it replys back but very slow
@blissful aspen Nice — that means the wiring is correct now. Slow is expected with that kind of model, but you can usually make it much snappier with a couple tweaks:
1) First sanity check: is it actually “thinking for ages” or “waiting on Ollama”?
OpenClaw side: look at the log line for the run duration + any provider timings.
If you can, tail logs while you send one message:
node dist/index.js logs --follow --plain
If you see long gaps before the first token, it’s model latency.
2) Practical fix: use a smaller tool-capable text model for chat
Use the giant VL model only when you need images. For normal chat/tool use, switch primary to something like:
ollama/llama3.3ollama/qwen2.5-coder:32b(or a smaller qwen coder)
Then set the VL model as the image model (only used when images are present):
agents: {
defaults: {
model: { primary: "ollama/llama3.3" },
imageModel: { primary: "ollama/qwen3-vl:235b-cloud" }
}
}
That way most messages are fast, and images still work.
3) Reduce output length (big speed win)
If you have maxTokens set huge for this model, clamp it to something like 1024–2048 in your models.providers.ollama.models[] entry. That limits rambling and speeds up “time to finish”.
Example:
node dist/index.js config set models.providers.ollama.models[0].maxTokens 2048 --json
(Adjust the index to the right model entry.)
4) If it’s timing out in Discord/UI
We can bump the agent timeout, but I’d only do that after we confirm it’s not just “too big a model for the job”.
If you tell me roughly how slow (e.g. “30s to first word” vs “2 min total”), and paste your models.providers.ollama.models[] entries (just the list), I’ll suggest the best primary+fallback combo for Ollama on your box.
{
"status": "error",
"tool": "read",
"error": "ENOENT: no such file or directory, access '/home/node/.openclaw/workspace/MEMORY.md'"
}
@blissful aspen That error just means the agent tried to read a memory file that doesn’t exist yet in its workspace:
/home/node/.openclaw/workspace/MEMORY.md
MEMORY.md is optional, but if you (or the agent prompt) tells it to “check memory”, it’ll try to open it and you’ll see this.
Quick fix (create the file + folder)
In the OpenClaw container terminal (BigBear/CasaOS “Terminal” / “Exec”), run:
mkdir -p /home/node/.openclaw/workspace/memory
touch /home/node/.openclaw/workspace/MEMORY.md
After that, “read MEMORY.md” won’t error anymore.
Important (so it doesn’t disappear on restart)
Make sure your Docker app has a persistent volume mapped to:
/home/node/.openclaw/workspace(workspace files likeMEMORY.md,memory/*.md)- and usually also
/home/node/.openclaw(state/config/sessions)
Docs reference: https://docs.openclaw.ai/help/faq#where-should-agentsmd-soulmd-usermd-memorymd-live
so it talks back quick now
@blissful aspen Sweet — that lines up: once the MEMORY.md read stopped erroring, the run no longer bails early and replies feel “instant”.
Two quick suggestions so it stays stable:
-
Persist the workspace volume
Make sure/home/node/.openclaw/workspaceis mapped to a host folder in CasaOS/BigBear, otherwiseMEMORY.md(andmemory/*.md) will vanish on container recreate. -
Use a fast default model + keep the huge VL model for images
If you haven’t already, set something smaller as primary and keepqwen3-vl:235b-cloudasimageModelonly. That’s the best “fast chat, still can do vision” setup.
If this fixed it, please mark the solution so Answer Overflow can index it: right‑click the solution message → Apps → ✅ Mark Solution.
now how do i connect imessages
@blissful aspen You can’t do iMessage directly from the ZimaOS/Linux box — you need a Mac that’s signed into Messages/iMessage. Then OpenClaw (running on ZimaOS) connects to that Mac.
Recommended way: BlueBubbles (easiest / best supported)
-
On a Mac (Mac mini/MacBook that stays on):
- Install BlueBubbles Server: https://bluebubbles.app
- Enable the Web API and set an API password
- Note the server address (usually
http://<mac-ip>:1234)
-
In OpenClaw config (Control UI → Config editor), add:
{
channels: {
bluebubbles: {
enabled: true,
serverUrl: "http://<MAC_IP>:1234",
password: "<BLUEBUBBLES_PASSWORD>",
webhookPath: "/bluebubbles-webhook",
},
},
}
- In BlueBubbles Server settings, set the webhook URL to your gateway:
http://192.168.1.44:18789/bluebubbles-webhook?password=<BLUEBUBBLES_PASSWORD>
- Restart the OpenClaw container.
Docs: https://docs.openclaw.ai/channels/bluebubbles
Legacy option (not recommended): imsg
Only works if OpenClaw runs on macOS (or you SSH to a Mac to run imsg rpc). Docs: https://docs.openclaw.ai/channels/imessage
If you tell me whether you have a Mac available on your LAN (and its IP), I’ll paste the exact config + webhook URL with your real addresses.
how would i connect to home assistant
@blissful aspen Easiest way is to install the Home Assistant skill and give it your HA URL + a long‑lived token.
1) Create a Home Assistant token
In Home Assistant: Profile → Long-Lived Access Tokens → Create Token
Copy it (this is basically full access).
2) Install the skill homeassistant
In the OpenClaw Control UI → Skills → Install, install from ClawHub: homeassistant
(Or if you have a terminal in the container: npx -y clawhub@latest install homeassistant in your workspace.)
3) Configure the skill env vars in OpenClaw config
Set these two env vars for the skill:
HA_URL= your HA URL (likelyhttp://192.168.1.44:8123)HA_TOKEN= the token you created
Config snippet (Control UI → Config editor):
{
skills: {
entries: {
homeassistant: {
enabled: true,
apiKey: "PASTE_YOUR_LONG_LIVED_TOKEN_HERE", // sets HA_TOKEN for this skill
env: {
HA_URL: "http://192.168.1.44:8123"
}
}
}
}
}
Restart the container after changing config.
4) If the skill doesn’t show up
That skill expects curl inside the OpenClaw container. Check in the container terminal:
curl --version
If missing, you’ll need to add curl to the image/container (otherwise the skill will be “ineligible” and tool calls will fail).
5) Test
Try: “List my switch.* entities” or “Turn on switch.office_lamp”.
If you tell me what URL your HA is on (and whether it’s HAOS/Docker), I can give the exact HA_URL you should use from inside the OpenClaw container.
everything i just did got unsaved when i restarted the container
@blissful aspen Yep — that means the BigBear app is running OpenClaw with no persistent volume, so when the container restarts/recreates you lose:
- config:
/home/node/.openclaw/openclaw.json - sessions/state:
/home/node/.openclaw/agents/... - workspace files (MEMORY.md, skills):
/home/node/.openclaw/workspace/...
Docker containers have an ephemeral filesystem unless you bind-mount a host folder.
Fix (CasaOS / BigBear)
In the CasaOS UI for the OpenClaw app, add a storage/volume mapping:
- Host path (pick something like):
/DATA/AppData/openclaw(or wherever CasaOS stores appdata) - Container path:
/home/node/.openclaw
That one mount will persist everything (config + workspace + sessions + skills).
Then restart the container, re-apply your config once, restart again → it should stick.
Permissions gotcha
Make sure the host folder is writable by the container user (usually UID 1000). If you see permission errors in logs, you may need to chown that host folder to the right uid/gid.
Docs that explain what must be persisted:
- Where data lives: https://docs.openclaw.ai/help/faq#where-does-openclaw-store-its-data
- Workspace files (MEMORY.md etc): https://docs.openclaw.ai/help/faq#where-should-agentsmd-soulmd-usermd-memorymd-live
- Docker notes: https://docs.openclaw.ai/install/docker
If you screenshot the CasaOS “Volumes/Storage” section of the OpenClaw app, I can tell you exactly what to add there.
/DATA/AppData/openclaw/config=/home/node/.openclaw
/DATA/AppData/openclaw/workspace=/home/node/.openclaw/workspace
@blissful aspen Yep — that mapping is the right idea:
/DATA/AppData/openclaw/config (host) → /home/node/.openclaw (container)
That will persist config + sessions + workspace + skills (everything under .openclaw). The host folder name being config is fine — it’s just a folder.
A couple quick gotchas to watch:
- Make sure it’s RW (read/write), not read-only.
- Permissions: the container usually runs as user
node(UID ~1000). If the gateway logs show “permission denied” writingopenclaw.jsonoragents/, you’ll need tochownthat host folder to the container user (or fix perms in CasaOS file manager).
Quick persistence test
After starting with the mount:
- In Control UI → Config editor, set any small value (e.g.
gateway.controlUi.allowInsecureAuth=true) - Restart the container
- Confirm the value is still set
If it still resets after restart, paste the first ~50 lines of the container logs right after boot — that’ll usually show a permissions error or that the mount didn’t apply.
@blissful aspen That one is also good — it will persist the workspace files (MEMORY.md, memory/*.md, workspace skills/, etc.).
But: don’t mount workspace instead of the main .openclaw dir unless you know what you’re doing.
Recommended (simple, everything persists)
Just mount one folder:
- Host:
/DATA/AppData/openclaw/state - Container:
/home/node/.openclaw
That covers:
openclaw.jsonconfig- sessions + auth profiles
- workspace (since it lives under
.openclaw/workspaceby default)
If you already mounted both
Mounting both can work, but make sure they don’t “fight”:
/home/node/.openclawmount persists everything/home/node/.openclaw/workspacemount is redundant, and can hide the workspace folder from the parent mount depending on Docker’s mount layering.
So I’d do either:
- Option A: only
/home/node/.openclaw(best) - Option B: mount
.openclawand workspace, but ensure both host paths exist and are writable, and understand the workspace mount overrides that subdir.
If you tell me what CasaOS/BigBear UI shows for the volumes list (screenshot or text), I’ll tell you which one to remove so you get clean persistence.
so i have the home assistant configured but it dont work
@blissful aspen “doesn’t work” with Home Assistant is usually one of these 3 things. Let’s narrow it down fast.
0) Common gotcha: don’t use localhost
If you set HA_URL=http://localhost:8123 inside Docker, it points at the OpenClaw container, not Home Assistant.
Use the LAN IP instead (sounds like yours is the same box):
HA_URL = "http://192.168.1.44:8123"
1) Verify the skill is actually loaded (eligible)
In Control UI → Skills, do you see homeassistant and is it “enabled/eligible”?
That skill requires curl inside the container. If curl is missing, the skill won’t work / may not load.
If you have a terminal in the container, run:
which curl && curl --version
2) Verify token+URL from inside the container (this is the real test)
Run (in the OpenClaw container terminal):
curl -s -i "$HA_URL/api/" -H "Authorization: Bearer $HA_TOKEN"
Expected: HTTP/1.1 200 and {"message":"API running."}
If you get:
401→ bad tokenFailed to connect→ wrong URL / HA not reachable / you used localhost- TLS/cert error → you set
https://...with an untrusted cert; switch to HA’s plainhttp://...:8123(or fix your cert)
3) Make sure HA_TOKEN is truly set (don’t rely on apiKey here)
To be safe, set it explicitly:
skills: {
entries: {
homeassistant: {
enabled: true,
env: {
HA_URL: "http://192.168.1.44:8123",
HA_TOKEN: "PASTE_TOKEN_HERE"
}
}
}
}
(Then restart the container.)
What I need from you
Paste:
- what your
HA_URLis set to (don’t paste the token) - the output of the
curl .../api/test above (status + first line is enough) - if there’s an error in OpenClaw logs right when you try a HA command, paste that error line(s).
HTTP/1.1 200 OK
Content-Type: application/json
Referrer-Policy: no-referrer
X-Content-Type-Options: nosniff
Server:
X-Frame-Options: SAMEORIGIN
Content-Length: 26
Date: Fri, 06 Feb 2026 15:13:47 GMT
@blissful aspen That HTTP/1.1 200 OK result is great — it proves HA_URL + HA_TOKEN are valid and reachable.
So if the OpenClaw “Home Assistant skill doesn’t work”, it’s almost always one of these:
1) You don’t have a real entity_id yet (most common)
Try listing some entities from inside the OpenClaw container:
curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \
| grep -o '"entity_id":"[^"]*"' | head -n 30
Pick one like light.something or switch.something, then test a direct service call:
curl -s -X POST "$HA_URL/api/services/switch/turn_on" \
-H "Authorization: Bearer $HA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entity_id":"switch.YOUR_SWITCH_HERE"}'
If that works, HA is 100% fine.
2) The agent isn’t actually able to run commands (no tool calls)
The homeassistant skill is basically “instructions + curl”. For the agent to do anything, it must be able to run the exec tool.
When you ask “turn on my kitchen light” in Control UI chat:
- do you see an exec/tool card (with a curl command)?
- No tool card ⇒ your current model likely isn’t tool-calling reliably. Switch your primary model to a known tool-capable text model and keep the huge VL model as
imageModel. - Tool card shows but errors ⇒ paste the error text from the card/logs.
- No tool card ⇒ your current model likely isn’t tool-calling reliably. Switch your primary model to a known tool-capable text model and keep the huge VL model as
3) HA_URL / HA_TOKEN not injected into the agent run
Make sure you set them under the skill entry (not just in your shell):
skills: {
entries: {
homeassistant: {
enabled: true,
env: {
HA_URL: "http://192.168.1.44:8123",
HA_TOKEN: "PASTE_TOKEN"
}
}
}
}
(Then restart the container.)
Send me 2 things and I’ll pinpoint it
- The output of the
entity_idlisting command (no secrets) - What happens in Control UI when you ask it to turn one of those entities on (screenshot/log line/tool card text).
light.lounge_rgb
@blissful aspen Great — that’s a valid entity id.
1) Prove HA control works (from inside the OpenClaw container)
Run:
# Check current state
curl -s "$HA_URL/api/states/light.lounge_rgb" \
-H "Authorization: Bearer $HA_TOKEN"
# Turn it ON
curl -s -X POST "$HA_URL/api/services/light/turn_on" \
-H "Authorization: Bearer $HA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entity_id":"light.lounge_rgb"}'
# Turn it OFF
curl -s -X POST "$HA_URL/api/services/light/turn_off" \
-H "Authorization: Bearer $HA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entity_id":"light.lounge_rgb"}'
If those work, HA + token are good and it’s purely an OpenClaw/tooling issue.
2) Then test via OpenClaw chat
In Control UI chat, say exactly:
Turn on light.lounge_rgb
Watch if you get a tool/exec card showing the curl command.
- No tool card at all → your current model isn’t doing tool calling reliably (switch primary model to a known tool-capable text model; keep the VL model as imageModel).
- Tool card appears but errors → paste the tool card error (or the log lines right after).
If you paste the output of the turn_on curl (it’s usually [] on success, or a JSON error), I can tell you what’s failing immediately.
why does it keep coming up with an arrow
@blissful aspen That “arrow” prompt (usually just > or >>>) is your shell telling you: it’s waiting for you to finish something — almost always an unclosed quote or unclosed { … } from a pasted command.
Fix
- Hit Ctrl+C to cancel the half-finished command.
- Paste the command again as one single line, making sure quotes match.
For example, this one is safe (note the single quotes around the JSON):
curl -s -X POST "$HA_URL/api/services/light/turn_on" \
-H "Authorization: Bearer $HA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entity_id":"light.lounge_rgb"}'
If you paste it and it still drops you into >, copy/paste exactly what you typed right before the > shows up — I’ll point out the missing quote/bracket.
it keeps replacing text in memory
@blissful aspen Two different things can look like “replacing text in memory” — which one do you mean?
A) The file contents (MEMORY.md / memory/YYYY-MM-DD.md) keep getting overwritten / losing old notes
That happens when the model uses the write file tool (which overwrites the whole file) and it doesn’t re-include the existing content correctly.
Fix options:
- Disable the automatic memory flush (so it stops writing to memory on its own):
{
agents: {
defaults: {
compaction: {
memoryFlush: { enabled: false }
}
}
}
}
(then restart)
- Add a rule in
AGENTS.md(in/home/node/.openclaw/workspace/AGENTS.md) like:
- “When writing memory: always
readthe file first, then write it back with the old content preserved + append new lines at the end. Never delete or replace existing entries unless user explicitly asks.”
- Use a more reliable tool-calling model for runs that involve file edits (local models sometimes botch “read → rewrite with old content preserved”). If you want recommendations, ask in #models.
B) When you’re typing in the editor, your cursor is in overwrite mode
This is a UI/editor thing (Insert key toggled) — typing replaces characters in-place.
Fix: press Insert (Ins) once to toggle back to insert mode (or in some UIs: Fn+Ins).
If you can, tell me which file is being “replaced” (MEMORY.md vs memory/2026-..md) and whether it’s happening after a bot turn (tool call) or while you’re manually typing in the editor.
now how do i connet whats app
@blissful aspen To connect WhatsApp you need to link it like WhatsApp Web (scan a QR) and you need the WhatsApp credentials folder to be persistent (your new /home/node/.openclaw volume fix is what makes it stick).
1) Minimal config (so it will respond to you)
In Control UI → Config editor:
{
channels: {
whatsapp: {
enabled: true,
dmPolicy: "allowlist",
allowFrom: ["+YOUR_PHONE_NUMBER_IN_E164"]
}
}
}
Example E.164: +447700900123 (must include + and country code).
Restart the container.
2) Login (scan QR)
You have two ways:
A) Control UI (easiest)
Control UI → Channels → WhatsApp → Login
It should show a QR.
On your phone:
WhatsApp → Settings → Linked devices → Link a device → scan QR.
B) CLI inside the container (if you have terminal)
Run:
node dist/index.js channels login whatsapp
(or node dist/index.js channels login and pick WhatsApp)
3) Verify
In Control UI → Channels it should show WhatsApp as linked/connected.
Notes / gotchas
- Use a spare number if possible (recommended).
- If you’re using your personal number, you may need:
channels: { whatsapp: { selfChatMode: true } } - If it “unlinks” after restart, your
/home/node/.openclawmount still isn’t applied right (because creds live under~/.openclaw/credentials/whatsapp/...).
If you tell me whether you want WhatsApp on your personal number or a new bot number, I’ll give you the exact config for that mode.
How to use ollama cloud models?
It's not an option within the onboarding flow, ollama or ollama cloud isn't there in provider list.
(sorry, lol. accidentally sent it here)
@old pewter Ollama (including the “*-cloud” models you see in ollama list) doesn’t show up in the onboarding provider picker in some setups — you just wire it manually in config.
Key idea
If your Ollama daemon exposes the model in /api/tags / ollama list, then for OpenClaw it’s just:
- provider:
ollama - model ref:
ollama/<exact-model-id-from-ollama>(e.g.ollama/gemma3:27b-cloud)
Don’t put just qwen3-vl:235b-cloud without the ollama/ prefix, or OpenClaw will “guess” another provider and you’ll get Unknown model.
Option A (simple, local gateway): auto-discovery
If OpenClaw can reach Ollama at http://127.0.0.1:11434:
- Set any Ollama API key (it’s just an opt-in flag):
- env:
OLLAMA_API_KEY=ollama-local
or
- config:
models.providers.ollama.apiKey = "ollama-local"
-
Do not set
models.providers.ollama(the whole block). With no explicit provider entry, OpenClaw auto-discovers tool-capable models. -
Set your default model:
{
agents: { defaults: { model: { primary: "ollama/<your-model-id>" } } }
}
Docs: https://docs.openclaw.ai/providers/ollama
Option B (Docker / remote Ollama): explicit provider (most common)
If OpenClaw is in Docker or Ollama is on another host/IP, you typically need:
{
models: {
providers: {
ollama: {
baseUrl: "http://<OLLAMA_HOST>:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{ id: "<your-model-id>" }
]
}
}
},
agents: {
defaults: {
model: { primary: "ollama/<your-model-id>" }
}
}
}
(Replace <OLLAMA_HOST> with your LAN IP/hostname, and <your-model-id> with exactly what ollama list shows, including :tag and -cloud if present.)
One more gotcha: context window minimum
OpenClaw enforces a minimum context window (16k). If your Ollama model reports 8k, you may need to override contextWindow in the explicit model entry, or choose a model that actually supports ≥16k.
If you paste your ollama list output + whether OpenClaw runs in Docker, I can give you the exact minimal config for your network layout.
Channel login failed: Error: Unsupported channel: whatsapp
@blissful aspen That error means the gateway doesn’t think the WhatsApp channel plugin is active, so /channels login can’t find a channel named whatsapp.
Two quick things to check/fix:
1) Make sure the web runtime is enabled (WhatsApp runs under web)
In Control UI → Config editor, ensure this exists:
{
web: { enabled: true }
}
Restart the container after.
(If web.enabled is false, WhatsApp won’t load and you’ll get “Unsupported channel: whatsapp”.)
2) Use the correct login command syntax
If you’re running it from the container terminal, use:
node dist/index.js channels login --channel whatsapp --verbose
(Or just node dist/index.js channels login since the default channel is WhatsApp.)
3) Sanity check: is WhatsApp even listed?
Run:
node dist/index.js channels list
If WhatsApp still isn’t in that list, paste the output — that would mean the BigBear image you’re using was built without the WhatsApp/web channel pieces, and we’d need to switch the app/image or enable the missing plugin.
Config was last written by a newer OpenClaw (2026.2.2); current version is 0.0.0.
Channel login failed: Error: Unsupported channel: whatsapp
$
@blissful aspen That log is the smoking gun:
-
“Config was last written by a newer OpenClaw (2026.2.2); current version is 0.0.0.”
→ the thing you’re running inside the container is effectively an unversioned/old build, so parts of your config + features won’t line up. -
“Unsupported channel: whatsapp”
→ in that build, the WhatsApp channel plugin isn’t present/registered, sochannels logincan’t even find it.
Quick confirm (takes 10 seconds)
Run in the container terminal:
node dist/index.js channels capabilities
If WhatsApp isn’t listed there, it’s not you/config — the image you installed doesn’t include WhatsApp support.
What to do next
You’ll need to switch to a proper OpenClaw Docker build/version (one that reports a real version like 2026.2.x), then your WhatsApp login will work and persist under /home/node/.openclaw/credentials/whatsapp/....
Best-known-good path (official docs): build the image from the OpenClaw repo and run via compose
https://docs.openclaw.ai/install/docker
That flow gives you an openclaw-cli container where WhatsApp login works:
docker compose run --rm openclaw-cli channels login --channel whatsapp
If you want to stay in CasaOS/BigBear
Open the app settings and check what image it’s using. Right now, whatever you’re on is yielding version=0.0.0 and missing WhatsApp. If you paste the exact image name/tag from CasaOS, I can tell you whether it’s the wrong image or just needs updating/pinning.
Unknown channel "".
@blissful aspen Unknown channel "" just means whatever command/UI you used ended up passing an empty channel name (literally "") instead of whatsapp.
If you’re doing it in the container terminal
Use exactly one of these (no quotes):
node dist/index.js channels login --channel whatsapp
or (WhatsApp is the default):
node dist/index.js channels login
Sanity check (is WhatsApp even available in this build?)
Run:
node dist/index.js channels capabilities
- If WhatsApp is not listed, then this container image/build doesn’t include the WhatsApp channel plugin (which matches your earlier
version is 0.0.0+Unsupported channel: whatsappissue) → you’ll need to switch images/build to a proper OpenClaw release.
If you paste the exact command you ran right before Unknown channel "", I can tell you why it turned into an empty string.
Config was last written by a newer OpenClaw (2026.2.2); current version is 0.0.0.
Channel login failed: Error: Unsupported channel: whatsapp
@blissful aspen That message means your container is running a broken/old OpenClaw build:
- config was written by OpenClaw 2026.2.2
- but the thing you’re running now reports version
0.0.0 - and in that build, the WhatsApp channel plugin isn’t registered, so you get
Unsupported channel: whatsapp.
1) Confirm the container’s actual version
In the container terminal run:
node dist/index.js --version
If it prints 0.0.0, you need to change the Docker image tag.
2) Fix: pin the image to a real release tag (don’t use :latest)
In CasaOS / BigBear app settings, change the image from:
alpine/openclaw:latest
to a specific release, e.g.:
alpine/openclaw:2026.2.2(matches your config)- or newer if you see it available on Docker Hub
Then “Update/Pull” the image and restart the container.
3) After updating, WhatsApp login should work
Run:
node dist/index.js channels capabilities
You should see WhatsApp listed. Then:
node dist/index.js channels login --channel whatsapp
(scan the QR in WhatsApp → Settings → Linked devices)
If you paste the output of node dist/index.js --version + what image tag CasaOS shows, I can tell you the exact tag to switch to.
$ node dist/index.js --version
2026.2.2
@blissful aspen Great — node dist/index.js --version = 2026.2.2 means your OpenClaw binary is fine.
The reason you still get:
current version is 0.0.0(config warning), andUnsupported channel: whatsapp
is almost always: the bundled “extensions” folder isn’t being found/loaded, so the channel plugins (including WhatsApp) never register.
1) Check if the bundled extensions are actually present
In the container terminal:
pwd
ls -la
ls -la extensions
-
If
extensions/is missing → this Docker image/build is incomplete for channels. WhatsApp won’t work until you switch to a full OpenClaw image (or build from the repo via the Docker guide): https://docs.openclaw.ai/install/docker -
If
extensions/exists → force OpenClaw to use it.
2) Force the bundled plugins dir (CasaOS env var)
Add this environment variable to the container and restart it:
OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions(adjust if yourextensionsdir is elsewhere)
(Optional, silences the “0.0.0” warning):
OPENCLAW_BUNDLED_VERSION=2026.2.2
3) Re-test
node dist/index.js channels capabilities
node dist/index.js channels login --channel whatsapp
Paste the output of ls -la extensions and I’ll tell you the exact value to set for OPENCLAW_BUNDLED_PLUGINS_DIR.
total 236
drwxrwxr-x 1 node node 4096 Feb 4 22:30 .
drwxr-xr-x 1 node node 4096 Feb 4 22:31 ..
drwxrwxr-x 1 node node 4096 Feb 4 22:30 bluebubbles
drwxrwxr-x 1 node node 4096 Feb 4 22:30 copilot-proxy
drwxrwxr-x 1 node node 4096 Feb 4 22:30 diagnostics-otel
drwxrwxr-x 1 node node 4096 Feb 4 22:30 discord
drwxrwxr-x 1 node node 4096 Feb 4 22:30 feishu
drwxrwxr-x 1 node node 4096 Feb 4 22:30 google-antigravity-auth
drwxrwxr-x 1 node node 4096 Feb 4 22:30 google-gemini-cli-auth
drwxrwxr-x 1 node node 4096 Feb 4 22:30 googlechat
drwxrwxr-x 1 node node 4096 Feb 4 22:30 imessage
drwxrwxr-x 1 node node 4096 Feb 4 22:30 line
drwxrwxr-x 1 node node 4096 Feb 4 22:30 llm-task
drwxrwxr-x 1 node node 4096 Feb 4 22:30 lobster
drwxrwxr-x 1 node node 4096 Feb 4 22:30 matrix
drwxrwxr-x 1 node node 4096 Feb 4 22:30 mattermost
drwxrwxr-x 1 node node 4096 Feb 4 22:30 memory-core
drwxrwxr-x 1 node node 4096 Feb 4 22:30 memory-lancedb
drwxrwxr-x 1 node node 4096 Feb 4 22:30 minimax-portal-auth
drwxrwxr-x 1 node node 4096 Feb 4 22:30 msteams
drwxrwxr-x 1 node node 4096 Feb 4 22:30 nextcloud-talk
drwxrwxr-x 1 node node 4096 Feb 4 22:30 nostr
drwxrwxr-x 1 node node 4096 Feb 4 22:30 open-prose
drwxrwxr-x 1 node node 4096 Feb 4 22:30 qwen-portal-auth
drwxrwxr-x 1 node node 4096 Feb 4 22:30 signal
drwxrwxr-x 1 node node 4096 Feb 4 22:30 slack
drwxrwxr-x 1 node node 4096 Feb 4 22:30 telegram
drwxrwxr-x 1 node node 4096 Feb 4 22:30 tlon
drwxrwxr-x 1 node node 4096 Feb 4 22:30 twitch
drwxrwxr-x 1 node node 4096 Feb 4 22:30 voice-call
drwxrwxr-x 1 node node 4096 Feb 4 22:30 whatsapp
drwxrwxr-x 1 node node 4096 Feb 4 22:30 zalo
drwxrwxr-x 1 node node 4096 Feb 4 22:30 zalouser
@blissful aspen Cool, so the binary is fine (--version = 2026.2.2) and the extensions/whatsapp plugin folder exists.
Unsupported channel: whatsapp means the WhatsApp plugin is not getting loaded/enabled into the active plugin registry, so the CLI can’t “see” a channel named whatsapp.
1) Check whether the plugin is disabled or crashing on load
Run in the container:
node dist/index.js plugins list
node dist/index.js plugins doctor
Look specifically for a line for whatsapp:
- if it says something like disabled / not allowlisted → config issue
- if it shows an error stack / missing module → image/dependency issue
2) Very common cause: plugins.allow is set but doesn’t include whatsapp
Check:
node dist/index.js config get plugins --json
If you see plugins: { allow: [...] } and whatsapp isn’t in there, either:
- add it to the allowlist, or
- remove
plugins.allowentirely (allow all bundled plugins)
3) Also make sure WhatsApp runtime isn’t disabled
WhatsApp won’t run if this is set:
web: { enabled: false }
(but note: that would normally make it “disabled”, not “unsupported”)
If you paste the output of plugins list (just the whatsapp-related lines), I’ll tell you exactly what to change in config to get channels login --channel whatsapp working.
│ m │ │ │ channel plugin │ │
│ @opencl │ tlo │ disabled │ /app/extensions/ │ 2026.2.2 │
│ aw/tlon │ n │ │ tlon/index.ts │ │
│ │ │ │ OpenClaw Tlon/ │ │
│ │ │ │ Urbit channel │ │
│ │ │ │ plugin │ │
│ @opencl │ twi │ disabled │ /app/extensions/ │ 2026.2.2 │
│ aw/ │ tch │ │ twitch/index.ts │ │
│ twitch │ │ │ OpenClaw Twitch │ │
│ │ │ │ channel plugin │ │
│ @opencl │ voi │ disabled │ /app/extensions/ │ 2026.2.2 │
│ aw/ │ ce- │ │ voice-call/index. │ │
│ voice- │ cal │ │ ts │ │
│ call │ l │ │ OpenClaw voice- │ │
│ │ │ │ call plugin │ │
│ @opencl │ wha │ disabled │ /app/extensions/ │ 2026.2.2 │
│ aw/ │ tsa │ │ whatsapp/index.ts │ │
│ whatsap │ pp │ │ OpenClaw WhatsApp │ │
│ p │ │ │ channel plugin │ │
│ @opencl │ zal │ disabled │ /app/extensions/ │ 2026.2.2 │
│ aw/zalo │ o │ │ zalo/index.ts │ │
│ │ │ │ OpenClaw Zalo │ │
│ │ │ │ channel plugin │ │
│ @opencl │ zal │ disabled │ /app/extensions/ │ 2026.2.2 │
│ aw/ │ ous │ │ zalouser/index.ts │ │
│ zalouse │ er │ │ OpenClaw Zalo │ │
│ r │ │ │ Personal Account │ │
│ │ │ │ plugin via zca-cli │ │
@blissful aspen That output explains it: the WhatsApp plugin is installed but disabled:
@openclaw/whatsapp … disabled … /app/extensions/whatsapp/index.ts
Bundled channel plugins ship disabled by default, so channels login can’t see whatsapp until you enable the plugin.
1) Enable the WhatsApp plugin
In the container terminal:
node dist/index.js plugins enable whatsapp
Then restart the container (important).
2) If you have a plugin allowlist, add whatsapp to it
Sometimes BigBear configs include plugins.allow which will keep it disabled even after “enable”.
Check:
node dist/index.js config get plugins.allow --json
- If it shows a non-empty list and
whatsappisn’t in it, either addwhatsappin the Control UI config editor, or remove the allowlist (simplest):
node dist/index.js config unset plugins.allow
Restart container again.
3) Login (QR)
Now this should work:
node dist/index.js channels login --channel whatsapp --verbose
(or Control UI → Channels → WhatsApp → Login to show the QR)
its working now
@blissful aspen Hell yes.
Quick “make sure it stays working” checklist:
- Keep that
/home/node/.openclawvolume mounted (so WhatsApp creds persist) - If you recreate the container, make sure the WhatsApp plugin stays enabled (
plugins enable whatsapp)
If this solved it, please mark the solution so Answer Overflow indexes it: right‑click the solution message → Apps → ✅ Mark Solution.
can you delete this thread
@blissful aspen I can’t delete Discord threads from here (that’s a server permission thing), but you can:
- Archive it (makes it disappear from the active list): open the thread → click the thread name at the top → Archive Thread
- Delete it (if you have “Manage Threads/Channels” perms): thread name menu → Delete Thread
- Or ask a server mod/admin to delete it.
If you pasted any secrets (gateway token, HA token, WhatsApp QR/creds logs), you should also delete those specific messages and rotate the tokens just to be safe.
whats app not working
What does “not working” look like right now — no replies, it says “not linked”, or it’s linked but disconnected?
Fastest way to debug is to grab status + WhatsApp channel logs from inside the container.
1) Paste these 3 command outputs (from the OpenClaw container terminal)
node dist/index.js --version
node dist/index.js channels status --deep
node dist/index.js channels logs --channel whatsapp --lines 200
2) Two super common fixes (check these while you’re at it)
A) WhatsApp plugin got disabled again
node dist/index.js plugins list | grep -i whatsapp
If it shows disabled:
node dist/index.js plugins enable whatsapp
# then restart the container
B) Credentials didn’t persist (container recreated / volume missing)
If channels status shows WhatsApp as not linked, your /home/node/.openclaw volume mount isn’t being applied (or permissions broke). Re-link after fixing the mount:
node dist/index.js channels login --channel whatsapp
Send the channels status --deep + channels logs output and I’ll tell you exactly which case it is and the minimal fix.
$ node dist/index.js --version
node dist/index.js channels status --deep
node dist/index.js channels logs --channel whatsapp --lines 200
2026.2.2
$
🦞 OpenClaw 2026.2.2 (unknown)
Your AI assistant, now without the $3,499 headset.
error: unknown option '--deep'
(Did you mean one of --dev, --help?)
$
🦞 OpenClaw 2026.2.2 (unknown)
OpenAI-compatible, not OpenAI-dependent.
Log file: /tmp/openclaw/openclaw-2026-02-07.log
Channel: whatsapp
2026-02-06T16:43:12.029Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-06T16:43:15.684Z error {"subsystem":"gateway/channels/whatsapp"} [default] channel exited: {"error":{"data":{"reason":"401","location":"rva"},"isBoom":true,"isServer":false,"output":{"statusCode":401,"payload":{"statusCode":401,"error":"Unauthorized","message":"Connection Failure"},"headers":{}}},"date":"2026-02-06T16:43:15.678Z"}
2026-02-07T00:00:35.573Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-07T00:00:39.249Z error {"subsystem":"gateway/channels/whatsapp"} [default] channel exited: {"error":{"data":{"reason":"401","location":"atn"},"isBoom":true,"isServer":false,"output":{"statusCode":401,"payload":{"statusCode":401,"error":"Unauthorized","message":"Connection Failure"},"headers":{}}},"date":"2026-02-07T00:00:39.243Z"}
That log is pretty clear: WhatsApp is rejecting the saved WhatsApp Web session:
statusCode: 401 … Unauthorized … Connection Failure
That usually means the linked-device creds got revoked/expired (or you unlinked it in WhatsApp → Linked Devices), so the gateway can’t reconnect until you re-link via QR.
Fix (recommended: Control UI)
- Control UI → Channels → WhatsApp
- Click Logout (if available), then Login
- Scan the new QR in WhatsApp on your phone: Settings → Linked devices → Link a device
- Restart the container if it doesn’t auto-reconnect.
Fix (CLI in the container)
node dist/index.js channels logout --channel whatsapp
node dist/index.js channels login --channel whatsapp --verbose
If it keeps happening / instantly 401 again
- Make sure you don’t have two OpenClaw instances trying to use the same WhatsApp linked session.
- In WhatsApp → Linked Devices, remove old entries, then link again.
- Double-check your
/home/node/.openclawvolume mount is still in place + writable (otherwise the new creds can’t be saved).
(Also: channels status --deep isn’t a thing in your 2026.2.2 build — so that error is expected.)
it keeps coming up saying couldnt link device on whats app
That “couldn’t link device” message is coming from the WhatsApp app when you scan the QR, and your gateway logs already showed the saved session is getting 401 Unauthorized — so you’re in “relink” land.
Here’s the usual sequence that fixes it:
1) Fully wipe the old WhatsApp session, then relink
In the container terminal:
node dist/index.js channels logout --channel whatsapp
node dist/index.js channels login --channel whatsapp --verbose
Then scan the new QR (WhatsApp → Settings → Linked devices → Link a device).
2) On your phone, clean up Linked Devices
WhatsApp → Settings → Linked devices
- Remove old linked sessions (especially if you have multiple “Linux/Chrome” entries)
- Try linking again
(WhatsApp has a linked-device limit, and old broken sessions can block relinking.)
3) Check phone/network gotchas (very common)
- Update WhatsApp to latest
- Disable VPN / iCloud Private Relay / adblock DNS on the phone (temporarily)
- Ensure phone time is set to Automatic
- Try a different network (Wi‑Fi ↔ mobile data)
4) Grab the log lines right after a failed scan
After you try linking once, run:
node dist/index.js channels logs --channel whatsapp --lines 200
Paste the newest lines around the failure (they’ll usually say why the login was rejected).
If you keep getting “couldn’t link device” even after logout + new QR + removing linked devices, it can also be WhatsApp temporarily rate-limiting that number (then waiting ~30–60 min sometimes helps), or the account is flagged and a fresh number links fine. The logs will help confirm which.
$ node dist/index.js channels login --channel whatsapp --verbose
🦞 OpenClaw 2026.2.2 (unknown)
The UNIX philosophy meets your DMs.
error: unknown option '--verbosenode'
That error is just a typo/paste artifact: OpenClaw is seeing an option literally named --verbosenode (i.e. --verbose got stuck to node with no space), and that flag doesn’t exist.
Do this:
- First, check what flags your build supports:
node dist/index.js channels login --help
- Then run one single line (don’t paste multiple commands at once):
node dist/index.js channels login --channel whatsapp --verbose
If --verbose isn’t listed in the help output, run it without:
node dist/index.js channels login --channel whatsapp
- If you’re still getting the 401 Unauthorized loop, wipe the old session first:
node dist/index.js channels logout --channel whatsapp
node dist/index.js channels login --channel whatsapp
After you try linking once, paste the newest WhatsApp logs again:
node dist/index.js channels logs --channel whatsapp --lines 80
🦞 OpenClaw 2026.2.2 (unknown)
Your terminal just grew claws—type something and let the bot pinch the busywork.
Log file: /tmp/openclaw/openclaw-2026-02-07.log
Channel: whatsapp
2026-02-06T16:43:12.029Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-06T16:43:15.684Z error {"subsystem":"gateway/channels/whatsapp"} [default] channel exited: {"error":{"data":{"reason":"401","location":"rva"},"isBoom":true,"isServer":false,"output":{"statusCode":401,"payload":{"statusCode":401,"error":"Unauthorized","message":"Connection Failure"},"headers":{}}},"date":"2026-02-06T16:43:15.678Z"}
2026-02-07T00:00:35.573Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-07T00:00:39.249Z error {"subsystem":"gateway/channels/whatsapp"} [default] channel exited: {"error":{"data":{"reason":"401","location":"atn"},"isBoom":true,"isServer":false,"output":{"statusCode":401,"payload":{"statusCode":401,"error":"Unauthorized","message":"Connection Failure"},"headers":{}}},"date":"2026-02-07T00:00:39.243Z"}
2026-02-07T00:28:39.792Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-07T00:28:42.478Z info {"subsystem":"gateway/channels/whatsapp"} Listening for personal WhatsApp inbound messages.
Those newest lines are good news:
Listening for personal WhatsApp inbound messages.
That means WhatsApp is running again (the 401 happened earlier, but at 00:28 it successfully started and stayed up).
What to do now
- Send a DM to that WhatsApp number from your phone (or “Message yourself” if you’re using your own number).
- Watch logs live for inbound/outbound:
node dist/index.js channels logs --channel whatsapp --lines 200
If you don’t get a reply, it’s usually one of these:
- DM policy blocking (pairing/allowlist):
-
Check your config:
channels.whatsapp.dmPolicy+channels.whatsapp.allowFrom- If
dmPolicy: "pairing", the first message returns a pairing code, and you must approve it.
- If
-
Self-chat mode needed (if you’re running on your personal number):
channels: { whatsapp: { selfChatMode: true } }
If you tell me whether you’re messaging it from your own number or a different phone/number, I’ll tell you exactly which config you need (pairing vs allowlist vs selfChatMode).
Log file: /tmp/openclaw/openclaw-2026-02-07.log
Channel: whatsapp
2026-02-06T16:43:12.029Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-06T16:43:15.684Z error {"subsystem":"gateway/channels/whatsapp"} [default] channel exited: {"error":{"data":{"reason":"401","location":"rva"},"isBoom":true,"isServer":false,"output":{"statusCode":401,"payload":{"statusCode":401,"error":"Unauthorized","message":"Connection Failure"},"headers":{}}},"date":"2026-02-06T16:43:15.678Z"}
2026-02-07T00:00:35.573Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-07T00:00:39.249Z error {"subsystem":"gateway/channels/whatsapp"} [default] channel exited: {"error":{"data":{"reason":"401","location":"atn"},"isBoom":true,"isServer":false,"output":{"statusCode":401,"payload":{"statusCode":401,"error":"Unauthorized","message":"Connection Failure"},"headers":{}}},"date":"2026-02-07T00:00:39.243Z"}
2026-02-07T00:28:39.792Z info {"subsystem":"gateway/channels/whatsapp"} [default] starting provider (+61451811123)
2026-02-07T00:28:42.478Z info {"subsystem":"gateway/channels/whatsapp"} Listening for personal WhatsApp inbound messages.
2026-02-07T00:29:41.794Z info {"subsystem":"gateway/channels/whatsapp/inbound"} Inbound message +61451811123 -> +61451811123 (direct, 71 chars)
2026-02-07T00:29:46.451Z debug {"subsystem":"gateway/channels/whatsapp/outbound"} Sent chunk 1/1 to +61451811123 (744ms)
2026-02-07T00:29:46.453Z info {"subsystem":"gateway/channels/whatsapp/outbound"} Auto-replied to +61451811123
2026-02-07T00:30:40.656Z info {"subsystem":"gateway/channels/whatsapp/inbound"} Inbound message +61451811123 -> +61451811123 (direct, 72 chars)
2026-02-07T00:30:46.289Z debug {"subsystem":"gateway/channels/whatsapp/outbound"} Sent chunk 1/1 to +61451811123 (3ms)
2026-02-07T00:30:46.290Z info {"subsystem":"gateway/channels/whatsapp/outbound"} Auto-replied to +61451811123
Those logs say WhatsApp is working end-to-end:
Inbound message +6145… -> +6145…Sent chunk 1/1Auto-replied
So OpenClaw is receiving and sending replies successfully.
If you’re not seeing the replies on the phone, it’s usually one of these:
-
You’re in “message yourself” / self-chat weirdness
- You’re sending from
+6145…to the same+6145…(self-chat). - WhatsApp sometimes hides/threads these oddly depending on device/account.
- Try messaging from a different number (friend’s phone) temporarily to confirm.
- You’re sending from
-
You’re looking at the wrong chat
- Make sure you’re viewing the chat that corresponds to the linked account (sometimes there are multiple “Message yourself” threads).
- WhatsApp linked devices glitch
- Open WhatsApp → Linked Devices and confirm the session is still active.
Quick test to remove ambiguity: send a message to the bot from another phone number (not the same +6145… number). If that works, we just need to adjust config for personal-number mode (selfChatMode) and/or change how you test.
If you tell me: are you running OpenClaw on your personal WhatsApp number and using “Message yourself” to test, or is this a separate bot number?
im messaging my open number
Your logs show this line:
Inbound message +61451811123 -> +61451811123
That means you’re messaging the same WhatsApp number that OpenClaw is linked to (self‑chat). OpenClaw is replying (you can see Auto-replied), but in self-chat it can be confusing because everything is “you”.
Best setup (recommended)
- Link OpenClaw to a dedicated WhatsApp number (the “OpenClaw number”).
- Message it from your normal personal number.
Then logs will look like:your-personal -> openclaw-number, and replies are obvious.
If you only have ONE number and you’re testing via “Message yourself”
Enable self-chat mode and add a prefix so you can see which messages are the bot:
{
channels: {
whatsapp: {
selfChatMode: true
}
},
messages: {
responsePrefix: "[openclaw] "
}
}
Restart the container after editing config.
Quick test to confirm
Ask a friend (or another SIM/WhatsApp Business account) to message your OpenClaw number once. If that works, your WhatsApp link is fine and it was just self-chat confusion.
If you tell me whether you have a separate bot number or you’re running on your personal number, I’ll give you the exact safest dmPolicy/allowFrom settings too.
it wont let me put that in the edit
Got it — the Control UI config editor is picky about exact JSON5 shape and where keys live.
Two common reasons it “won’t let you”:
- you’re editing the wrong section (e.g.
channels.whatsappvschannels: { whatsapp: ... }) - you pasted a block with mismatched braces/commas so it won’t validate
Do it as two small “path edits” instead (much easier)
In Control UI → Config → Set (or “add field”), set these exact paths:
- Enable self-chat mode
- key/path:
channels.whatsapp.selfChatMode - value:
true(boolean)
- Add a reply prefix
- key/path:
messages.responsePrefix - value:
"[openclaw] "(string)
Then restart the container.
If your editor only supports raw JSON
Paste this inside your existing config at the top level (don’t duplicate channels if it already exists—merge it):
channels: {
whatsapp: {
selfChatMode: true,
},
},
messages: {
responsePrefix: "[openclaw] ",
},
If you paste a screenshot of the part of config you’re editing (just the channels + messages sections), I can tell you exactly where to insert it without breaking validation.
Error: SyntaxError: JSON5: invalid character 'c' at 87:1
That error means your config file stopped being valid JSON5 right at line 87, and the first bad character it sees there is a c — usually because you pasted something like:
channels: { ... }without a comma before it, or- you pasted raw text like
channels.whatsapp.selfChatModeinto the JSON editor, or - you have an extra
}above and nowchannelsstarts in the wrong place.
Fast fix
- In the config editor, go to line 87 and copy/paste lines 83–92 here (just that snippet).
- Also paste the line right above where you inserted the
channels:block (often the missing comma is there).
What it should look like (top-level keys must be comma-separated)
Example valid shape:
{
gateway: { /* ... */ },
channels: {
whatsapp: {
selfChatMode: true,
},
},
messages: {
responsePrefix: "[openclaw] ",
},
}
Notice the commas after each top-level block.
If you don’t want to fight the raw editor: use path-based set fields in Control UI (set channels.whatsapp.selfChatMode to true and messages.responsePrefix to "[openclaw] "). That avoids JSON5 syntax issues entirely.
is there a way to send chats and it acutally has a convo with me?
Yes — but you need to avoid “self-chat” on the same WhatsApp number, because then it’s basically you talking to you and it gets confusing fast.
Best way (real conversation)
- Use a separate WhatsApp number for OpenClaw (recommended)
- Link that number to OpenClaw (QR)
- Then message it from your normal personal number
- You’ll get a normal DM thread and it’ll maintain context naturally.
If you only have one number (still possible, just awkward)
You can use WhatsApp’s “Message yourself” thread, but it’s not a great “conversation” UX.
If you do this, set a response prefix so you can tell bot vs you:
messages.responsePrefix = "[openclaw] "
And enable:
channels.whatsapp.selfChatMode = true
(Do it via Control UI path-based config set to avoid JSON syntax issues.)
Also make sure it’s not in “pairing-only/allowlist blocking” mode
For DMs, either:
dmPolicy: "pairing"(first message gives a code, then you approve once), ordmPolicy: "allowlist"+allowFrom: ["+your_number"]
Once you’re messaging from a different number, it’ll behave like a normal chat and keep the thread context.
If you tell me: are you willing to use a second number (even WhatsApp Business with another SIM/eSIM), or are you stuck with one? I’ll give you the exact config for your case.
how would i get openclaw to make home assistant dashboards
You can use OpenClaw to help build Home Assistant dashboards, but it can’t magically “click around in HA” unless you give it a way to edit your dashboard YAML.
Practical options (from easiest → most automated):
Option 1 (recommended): have it generate Lovelace YAML, you paste it
- Tell it what you want on the dashboard (rooms, entities, layout, mobile vs tablet).
- Have OpenClaw generate a Lovelace view/card YAML.
- In Home Assistant: Dashboard → Edit → Raw configuration editor (or “Edit dashboard YAML”) → paste.
To make this work well, first give it:
- your key entities (lights/switches/sensors), or a paste of
/api/statesfiltered by the domains you care about - your HA theme preference (minimal, mushroom, etc.)
Option 2: let OpenClaw write dashboard YAML files (needs file access)
If your HA config is on disk somewhere OpenClaw can reach, you can mount that folder into the OpenClaw container and then it can edit YAML files.
You’d mount something like:
- host:
/DATA/AppData/homeassistant(or wherever your HA config lives) - container:
/ha-config(read/write)
Then you tell OpenClaw: “edit /ha-config/ui-lovelace.yaml and add a new view…”
Option 3: automate via HA API (limited)
Home Assistant’s REST API is great for entities/services, but dashboard editing via API isn’t as clean as service calls. So most people do Option 1 or 2.
Quick question
Are you using:
- Storage mode dashboards (most common; edited in UI), or
ui-lovelace.yamlin your HA config folder?
If you tell me which one + what kind of dashboard you want (rooms + devices), I’ll have OpenClaw draft a first Lovelace view for you using your real entities (e.g. light.lounge_rgb, etc.).
option 1
Cool — then the workflow is: OpenClaw generates Lovelace YAML → you paste it into HA’s Raw editor.
To generate something that actually fits your setup, I need 2 things:
- What views do you want? (example: “Home / Lounge / Bedroom / Climate / Security”)
- Your main entities (paste a short list, or categories). For a first pass, just list:
- lights (
light.*) - switches (
switch.*) - climate (
climate.*) - important sensors (
sensor.*)
- lights (
You already have light.lounge_rgb. Give me 5–15 more like that and I’ll draft a clean dashboard.
Quick starter template (you can paste now)
Here’s a simple “Lounge” view you can paste into Raw configuration editor and then edit entity ids:
title: Home
views:
- title: Lounge
path: lounge
icon: mdi:sofa
cards:
- type: vertical-stack
cards:
- type: heading
heading: Lounge
- type: light
entity: light.lounge_rgb
name: Lounge RGB
- type: entities
title: Quick toggles
show_header_toggle: false
entities:
- entity: light.lounge_rgb
If you paste your list of entities + whether you want a mobile-friendly layout or a tablet wall panel layout, I’ll generate a nicer multi-view dashboard (with sections, chips/buttons, brightness sliders, etc.).
how do i past a list of my entities
Easiest ways (pick one):
Option A (HA UI, no terminal): paste from Developer Tools
- Home Assistant → Developer Tools → States
- Use the filter box and search
light.(thenswitch.,climate., etc.) - Copy the entity_ids you care about (even just 10–20 is enough) and paste them here as lines, e.g.
light.lounge_rgb
switch.kitchen_plug
sensor.lounge_temp
Option B (One-shot from the OpenClaw container, if you have terminal)
If HA_URL and HA_TOKEN are set in the container, run:
curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \
| grep -o '"entity_id":"[^"]*"' \
| cut -d'"' -f4 \
| sort
If that’s too long, filter to just lights/switches:
curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \
| grep -o '"entity_id":"[^"]*"' | cut -d'"' -f4 \
| grep -E '^(light|switch|climate|scene)\.' \
| sort
Paste the output (or just the first ~50 lines) and tell me whether you want mobile or tablet layout.
it wont let me post it
Discord is probably blocking it because the list is too long (message length / flood limits).
Do one of these:
Option 1: Send only a small slice
Paste just:
- 10 lights
- 10 switches
- 5 sensors
That’s enough for me to build a good dashboard.
Option 2: Split it into multiple messages
Send it in chunks like:
- “Lights part 1/3”
- “Lights part 2/3”
- “Switches”
etc.
Option 3: Upload as a file (best)
In Discord, attach a text file:
- Put the list in a file called
entities.txt - Upload it in the channel/thread
If you can run commands in the container, you can also generate a small curated list that’s easier to post:
curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \
| grep -o '"entity_id":"[^"]*"' | cut -d'"' -f4 \
| grep -E '^(light|switch|climate|scene)\.' \
| sort | head -n 60
Paste that output (60 lines max) and we’re good.
still wont let me
If Discord won’t accept even a small chunk, it’s usually one of these:
- you’re pasting thousands of lines (even
headdidn’t apply because it didn’t run) - Discord is rate-limiting you for rapid posts
- you’re trying to paste in a place that doesn’t allow messages (e.g., a locked thread)
- the content includes something Discord flags (rare)
Let’s bypass Discord entirely:
Option A (best): screenshot the entity list
In Home Assistant → Developer Tools → States
- filter
light. - scroll a bit so ~20 entities are visible
- take a screenshot and post the image here
I can read the entity_ids from the screenshot and build the dashboard from that.
Option B: paste only 5 entities manually
Just type (don’t paste) 5–10 entity ids like:
light.lounge_rgbswitch.kitchen_plug
etc.
Option C: upload as a file
Create a text file entities.txt and upload it. (Drag & drop into Discord.)
Which of these is easiest for you right now?
c
Cool — upload entities.txt and we’re set.
Fast way to create entities.txt (inside the OpenClaw container terminal)
Run:
curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \
| grep -o '"entity_id":"[^"]*"' | cut -d'"' -f4 \
| sort > entities.txt
If you want a smaller, dashboard-focused file:
curl -s "$HA_URL/api/states" -H "Authorization: Bearer $HA_TOKEN" \
| grep -o '"entity_id":"[^"]*"' | cut -d'"' -f4 \
| grep -E '^(light|switch|climate|scene|media_player|cover|lock|alarm_control_panel|sensor)\.' \
| sort > entities.txt
Then in Discord, attach entities.txt (drag/drop or “+” → upload file).
Once it’s uploaded, tell me: mobile layout or tablet wall panel, and what rooms/views you want, and I’ll generate the Lovelace YAML.
wont let me past it
You can do this without pasting a giant entity list by using Home Assistant Area cards. Area cards auto-populate controls for whatever devices/entities are assigned to that area, so you only need your area IDs (short strings), not every entity.
Step 1: Make sure your devices are assigned to Areas
Home Assistant → Settings → Areas, labels & zones → Areas
- Create areas like
lounge,kitchen,bedroom, etc. - Assign devices/entities to the right area.
Step 2: Get the exact area: id (small + easy to post)
In any dashboard:
- Add card → search for Area
- Pick your area (e.g. Lounge)
- Open the card menu → Show code editor
- Copy just this tiny bit and post it here, e.g.
type: area
area: lounge
Do that for each room (even 3–6 areas is enough).
Step 3: Paste this starter dashboard YAML (Area-based)
Once you have a few areas, you can paste something like this in the Raw configuration editor:
title: Home
views:
- title: Rooms
path: rooms
icon: mdi:home
cards:
- type: grid
columns: 2
square: false
cards:
- type: area
area: lounge
display_type: picture
features:
- type: area-controls
- type: area
area: kitchen
display_type: picture
features:
- type: area-controls
Replace lounge / kitchen with your real area ids.
If Discord won’t let you paste anything big, just send me your area ids as plain lines (you can type them):
lounge, kitchen, bedroom, etc.
Then I’ll generate a complete multi-view dashboard YAML for those rooms.
openclaw ui chat keeps coming up with a white screen
A “white screen” in the Control UI is usually just the web app crashing (JS error) or it can’t talk to the gateway WS.
1) Grab the browser error (most important)
Open the Control UI in Chrome → F12 DevTools → Console and copy the first red error line(s).
Also check Network → WS: do you see the websocket connecting to ws://192.168.1.44:18789 (or whatever) or is it failing?
2) Quick things to try that fix 80% of white screens
- Hard refresh: Ctrl+Shift+R
- Clear site data: DevTools → Application → Clear storage (or clear the site’s Local Storage)
- Open it with an explicit gateway URL + token so it doesn’t use a bad saved value:
http://192.168.1.44:18789/?gatewayUrl=ws://192.168.1.44:18789&token=YOUR_TOKEN
(This overwrites the stored gateway URL/token.)
3) If you’re using plain HTTP on LAN
If you didn’t set gateway.controlUi.allowInsecureAuth=true, you can get secure-context weirdness. You already used that before, but double-check it didn’t get lost after container changes.
4) Get gateway logs around the crash
In the container:
node dist/index.js logs --limit 200
Paste:
- the browser console error
- and the newest gateway log lines right when it turns white
…and I can tell you if it’s a broken saved gatewayUrl/token, a secure-context block, or a Control UI build/asset path problem.
01:31:46 info web-heartbeat {"module":"web-heartbeat","runId":"94a9eda5-636b-4768-885d-a8520771f1b4"} {"connectionId":"92989293-c13d-47ec-bb12-9275e79928b0","reconnectAttempts":1,"messagesHandled":0,"lastMessageAt":null,"authAgeMs":60000.194091796875,"uptimeMs":62601} web gateway heartbeat
01:32:46 info web-heartbeat {"module":"web-heartbeat","runId":"94a9eda5-636b-4768-885d-a8520771f1b4"} {"connectionId":"92989293-c13d-47ec-bb12-9275e79928b0","reconnectAttempts":1,"messagesHandled":0,"lastMessageAt":null,"authAgeMs":120001.19409179688,"uptimeMs":122602} web gateway heartbeat
01:33:46 info web-heartbeat {"module":"web-heartbeat","runId":"94a9eda5-636b-4768-885d-a8520771f1b4"} {"connectionId":"92989293-c13d-47ec-bb12-9275e79928b0","reconnectAttempts":1,"messagesHandled":0,"lastMessageAt":null,"authAgeMs":180002.19409179688,"uptimeMs":182603} web gateway heartbeat
01:34:29 debug diagnostic {"subsystem":"diagnostic"} lane enqueue: lane=session:agent:main:main queueSize=1
01:34:29 debug diagnostic {"subsystem":"diagnostic"} lane dequeue: lane=session:agent:main:main waitMs=0 queueSize=0
01:34:29 debug diagnostic {"subsystem":"diagnostic"} lane enqueue: lane=main queueSize=1
01:34:29 debug diagnostic {"subsystem":"diagnostic"} lane dequeue: lane=main waitMs=1 queueSize=0
01:34:29 debug agent/embedded {"subsystem":"agent/embedded"} embedded run start: runId=d497271b-de6d-4674-8c0f-1e13a2dee618 sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 provider=ollama model=gpt-oss:120b-cloud thinking=off messageChannel=webchat
01:34:29 debug diagnostic {"subsystem":"diagnostic"} session state: sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 sessionKey=unknown prev=idle new=processing reason="run_started" queueDepth=0
01:34:29 debug diagnostic {"subsystem":"diagnostic"} run registered: sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 totalActive=1
01:34:29 debug agent/embedded {"subsystem":"agent/embedded"} embedded run prompt start: runId=d497271b-de6d-4674-8c0f-1e13a2dee618 sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3
01:34:29 debug agent/embedded {"subsystem":"agent/embedded"} embedded run compaction start: runId=d497271b-de6d-4674-8c0f-1e13a2dee618
01:34:29 debug agent/embedded {"subsystem":"agent/embedded"} embedded run agent start: runId=d497271b-de6d-4674-8c0f-1e13a2dee618
01:34:32 debug agent/embedded {"subsystem":"agent/embedded"} embedded run agent end: runId=d497271b-de6d-4674-8c0f-1e13a2dee618
01:34:32 debug agent/embedded {"subsystem":"agent/embedded"} embedded run prompt end: runId=d497271b-de6d-4674-8c0f-1e13a2dee618 sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 durationMs=2840
01:34:32 debug diagnostic {"subsystem":"diagnostic"} session state: sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 sessionKey=unknown prev=processing new=idle reason="run_completed" queueDepth=0
01:34:32 debug diagnostic {"subsystem":"diagnostic"} run cleared: sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 totalActive=0
01:34:32 debug agent/embedded {"subsystem":"agent/embedded"} embedded run done: runId=d497271b-de6d-4674-8c0f-1e13a2dee618 sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 durationMs=2891 aborted=false
01:34:32 debug diagnostic {"subsystem":"diagnostic"} lane task done: lane=main durationMs=2892 active=0 queued=0
01:34:32 debug diagnostic {"subsystem":"diagnostic"} lane task done: lane=session:agent:main:main durationMs=2893 active=0 queued=0
01:34:32 debug diagnostic {"subsystem":"diagnostic"} lane enqueue: lane=session:agent:main:main queueSize=1
01:34:32 debug diagnostic {"subsystem":"diagnostic"} lane dequeue: lane=session:agent:main:main waitMs=0 queueSize=0
01:34:32 debug diagnostic {"subsystem":"diagnostic"} lane enqueue: lane=main queueSize=1
01:34:32 debug diagnostic {"subsystem":"diagnostic"} lane dequeue: lane=main waitMs=0 queueSize=0
01:34:32 debug agent/embedded {"subsystem":"agent/embedded"} embedded run start: runId=56e0c684-9659-43b5-b6d4-a595ff7e06c8 sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 provider=ollama model=gpt-oss:120b-cloud thinking=off messageChannel=webchat
01:34:32 debug diagnostic {"subsystem":"diagnostic"} session state: sessionId=237bd408-001a-41d5-9a26-8b3a3a810bc3 sessionKey=unknown prev=idle new=processing reason="run_started" queueDepth=0
01:34:32 debug diagnostic {"subsystem":"diagnostic"} run registered: sessionId=2
Those log lines are just the WhatsApp web-heartbeat; they don’t explain the Control UI going white. A white screen is almost always a browser-side JS crash or the UI can’t load its JS bundle.
1) Grab the real error (browser console)
On the machine where you open the Control UI:
- Open the Control UI URL
- Press F12 → Console
- Copy/paste the first red error line(s)
Also check Network:
- Any 404 for
/assets/*.js(missing bundle)? - Any failed WebSocket connection?
2) Two common fixes you can try immediately
A) Clear the UI’s saved settings (bad saved gatewayUrl/token can brick it)
- Open in an Incognito/Private window, or
- Clear site data for
http://192.168.1.44:18789(cookies/localStorage), then reload.
B) Secure-context issue (happens over plain HTTP sometimes)
If the console error mentions crypto.subtle / “secure context” / WebCrypto, either:
- set
gateway.controlUi.allowInsecureAuth=trueagain, or - use an SSH tunnel and open
http://127.0.0.1:18789/(localhost).
To check the current setting from the container:
node dist/index.js config get gateway.controlUi --json
3) Tell me these two things
- The exact URL you’re opening (including any path like
/openclaw/) - The first console error line
With those, I can tell you if it’s (a) missing assets/basePath mismatch, (b) secure-context, or (c) WS auth/origin problem.
That gateway log snippet shows the agent runs are completing normally (messageChannel=webchat, run starts/ends). So the “white screen” is almost certainly the browser UI crashing (JS error) or failing to load its JS bundle — not the model.
Do this on the computer where the UI turns white
- Open the Control UI, then open DevTools → Console and paste the first red error you see.
- Open DevTools → Network and reload the page:
- Do you see any 404 for
/assets/*.jsor/assets/*.css? - Do you see the WebSocket connecting, or failing?
- Do you see any 404 for
Quick fixes that usually solve it
- Hard refresh:
Ctrl+Shift+R - Try Incognito/Private window (bypasses bad cached files + bad localStorage)
- Clear site data: DevTools → Application → Clear storage (or browser “Clear site data” for
http://192.168.1.44:18789)
If the console mentions “secure context / WebCrypto / crypto.subtle”
Then you’re hitting the HTTP-on-LAN restriction again. Fix = either:
- use an SSH tunnel and open
http://127.0.0.1:18789/, or - re-enable insecure auth:
node dist/index.js config set gateway.controlUi.allowInsecureAuth true --json
then restart the container.
Paste the console error + the exact URL you’re opening (including IP/port), and I’ll tell you the exact fix.
how to setup elvenlabs to call me from openclaw
ElevenLabs by itself can’t place a phone call — it only provides the voice (TTS).
To have OpenClaw “call you”, you need the Voice Call plugin + a telephony provider (Twilio / Telnyx / Plivo), and then optionally use ElevenLabs for the speech audio.
1) Configure ElevenLabs TTS (core)
In openclaw.json:
{
messages: {
tts: {
provider: "elevenlabs",
elevenlabs: {
apiKey: "ELEVENLABS_API_KEY",
voiceId: "YOUR_VOICE_ID",
modelId: "eleven_multilingual_v2"
}
}
}
}
Docs: https://docs.openclaw.ai/tts
2) Install + enable voice calls (the actual “call me” part)
openclaw plugins install @openclaw/voice-call
# then restart the gateway
Then configure the plugin (example Twilio skeleton):
{
plugins: {
entries: {
"voice-call": {
enabled: true,
config: {
provider: "twilio",
fromNumber: "+15550001234",
twilio: {
accountSid: "ACxxxx",
authToken: "xxxx"
},
// You MUST expose a public webhook URL (ngrok/tailscale/etc)
// publicUrl: "https://....../voice/webhook",
// tunnel: { provider: "ngrok" },
// Optional: override TTS just for calls (otherwise it uses messages.tts)
tts: {
provider: "elevenlabs",
elevenlabs: {
apiKey: "ELEVENLABS_API_KEY",
voiceId: "YOUR_VOICE_ID",
modelId: "eleven_multilingual_v2"
}
}
}
}
}
}
}
Docs: https://docs.openclaw.ai/plugins/voice-call
3) Test an outbound call
openclaw voicecall call --to "+1YOURNUMBER" --message "Hello from OpenClaw"
If you tell me which provider you’re using (Twilio vs Telnyx vs Plivo) and whether your ZimaOS box can expose a public URL (ngrok/tailscale), I can point you at the exact minimal config for that setup.
apprently eleven labs can make calls
ElevenLabs as a company may offer phone-calling in their own product stack, but in OpenClaw today ElevenLabs is only used as the TTS voice provider — it’s not the thing that actually dials a phone number.
In OpenClaw, the “call a phone number” part is handled by the Voice Call plugin, and its supported call providers are currently:
- Twilio
- Telnyx
- Plivo
- (and
mockfor dev)
Docs: https://docs.openclaw.ai/plugins/voice-call
So the typical setup is:
- Twilio/Telnyx/Plivo = places/receives the phone call + webhooks
- ElevenLabs = generates the spoken audio (voice)
If what you want is just spoken replies (no phone call), that’s simpler: enable TTS with ElevenLabs and OpenClaw will send audio messages/voice notes (depending on the chat app). Docs: https://docs.openclaw.ai/tts
If you specifically want “OpenClaw uses ElevenLabs to dial calls directly” (no Twilio/Telnyx/Plivo), that would need a new integration — best next step would be a feature request: https://github.com/openclaw/openclaw/issues
how do i enable the voice call plugin
To enable the Voice Call plugin you do 3 things: install plugin → restart gateway → add plugin config.
1) Install the plugin (on the machine running the Gateway)
openclaw plugins install @openclaw/voice-call
2) Restart the Gateway (so it loads the plugin)
If you installed OpenClaw as a service:
openclaw gateway restart
If you run it manually, stop/start your gateway process.
3) Enable it in openclaw.json
Add this (minimal “does it load?” config using the mock provider):
{
plugins: {
entries: {
"voice-call": {
enabled: true,
config: {
provider: "mock"
}
}
}
}
}
Restart the gateway again after editing config.
Next step (real calls)
To actually dial a phone number you must switch provider to twilio / telnyx / plivo and set up a public webhook URL (ngrok/tailscale/etc). Docs: https://docs.openclaw.ai/plugins/voice-call
If you paste:
openclaw --version- how you’re running OpenClaw on ZimaOS (docker? npm global? from source?)
I can give you the exact commands for that setup.
im running it in a docker
If your Gateway is running in Docker, you need to install/enable the plugin inside the container environment (so it ends up in the container’s ~/.openclaw/extensions volume), then restart the gateway container.
If you’re using the standard docker compose setup (openclaw-gateway + openclaw-cli)
From the folder that has your docker-compose.yml:
- Install the plugin
docker compose run --rm openclaw-cli plugins install @openclaw/voice-call
- Verify it’s there
docker compose run --rm openclaw-cli plugins list
docker compose run --rm openclaw-cli plugins doctor
- Enable + configure it in your
openclaw.json(usually on the host at~/.openclaw/openclaw.jsonif you used the official docker setup). Minimal “does it load?” config:
{
plugins: {
entries: {
"voice-call": {
enabled: true,
config: { provider: "mock" }
}
}
}
}
- Restart the gateway container
docker compose restart openclaw-gateway
After that, switch from provider: "mock" to twilio / telnyx / plivo + set up the public webhook bits.
Docs: https://docs.openclaw.ai/plugins/voice-call
If you tell me how you’re running it (compose file / Portainer stack / single docker run command), I can give you the exact commands/paths for that layout.
how do i run openclaw doctor --fix on a docker container
If you’re running the Gateway in Docker, run Doctor inside the container that has the OpenClaw CLI (usually openclaw-cli in the official compose setup).
Docker Compose (recommended / official setup)
From the directory with your docker-compose.yml:
docker compose run --rm -it openclaw-cli doctor --fix
If you want it to auto-accept prompts:
docker compose run --rm -it openclaw-cli doctor --fix --yes
After Doctor changes config/plugins/tokens, restart the gateway container:
docker compose restart openclaw-gateway
Plain Docker (docker run / Portainer stack)
Find your container name, then:
docker exec -it <container_name> openclaw doctor --fix
(If the container doesn’t have the openclaw CLI binary, you’ll need to exec into the CLI container, or run the openclaw-cli image for that stack.)
}
}
}
"skills": {
"entries": {
"homeassistant": {
"enabled": true,
can you fix that part?
That snippet is almost certainly a config syntax error (JSON/JSON5): you’ve got a "skills": { ... } key starting right after some closing } braces, but there’s no comma (and possibly you closed the top-level {} too early).
At the top level, it must look like this (note the comma between sections):
{
plugins: {
entries: {
"voice-call": { enabled: true, config: { provider: "mock" } }
}
},
skills: {
entries: {
homeassistant: {
enabled: true
}
}
}
}
Quick way to see exactly what’s wrong (line/column) in Docker
Run Doctor inside the CLI container:
docker compose run --rm -it openclaw-cli doctor
It should print the exact file + line number where parsing fails.
If you paste more, I can point at the exact missing comma/brace
Please paste ~20 lines above the "skills": { line (wrap it in a Discord code block), and redact tokens/keys.
Yep — you just need a comma between the top-level blocks (and make sure the braces close in the right place).
Replace this broken bit:
}
}
}
"skills": {
"entries": {
"homeassistant": {
"enabled": true,
with this:
}
},
"skills": {
"entries": {
"homeassistant": {
"enabled": true
}
}
}
Key change: the line that used to be the final } becomes }, so "skills" is the next top-level key.
If you paste ~10 lines above and ~10 lines below that area, I can format the exact corrected chunk with all braces matched.
Missing: config:plugins.entries.voice-call.enabled
That error means your config has a plugins.entries["voice-call"] block, but it’s missing the required boolean flag:
plugins.entries["voice-call"].enabled
Fix: add enabled: true under the voice-call entry, like:
{
plugins: {
entries: {
"voice-call": {
enabled: true,
config: {
provider: "mock"
}
}
}
}
}
If you prefer doing it via CLI (inside Docker Compose):
docker compose run --rm -it openclaw-cli \
openclaw config set 'plugins.entries["voice-call"].enabled' true --json
docker compose restart openclaw-gateway
when my openclaw adds my twilio info it breaks the config
That usually happens for one of 3 reasons when you paste Twilio stuff:
- Wrong nesting (the
twilio: { ... }block must be insideplugins.entries["voice-call"].config) - Missing comma / bad quotes (especially after
fromNumberor afteraccountSid) - Phone numbers not quoted (E.164 must be a string, like
"+1555...", not+1555...)
Here’s a known-good minimal Twilio block (compare your indentation/commas to this):
{
plugins: {
entries: {
"voice-call": {
enabled: true,
config: {
provider: "twilio",
fromNumber: "+15550001234",
twilio: {
accountSid: "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authToken: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
serve: {
port: 3334,
path: "/voice/webhook"
}
// plus publicUrl / tunnel / tailscale etc later
}
}
}
}
}
Easiest way to avoid breaking JSON5: set values via CLI (it writes valid syntax)
If you’re using docker compose:
docker compose run --rm -it openclaw-cli openclaw config set 'plugins.entries["voice-call"].enabled' true --json
docker compose run --rm -it openclaw-cli openclaw config set 'plugins.entries["voice-call"].config.provider' '"twilio"' --json
docker compose run --rm -it openclaw-cli openclaw config set 'plugins.entries["voice-call"].config.fromNumber' '"+15550001234"' --json
docker compose run --rm -it openclaw-cli openclaw config set 'plugins.entries["voice-call"].config.twilio.accountSid' '"AC...."' --json
docker compose run --rm -it openclaw-cli openclaw config set 'plugins.entries["voice-call"].config.twilio.authToken' '"...."' --json
docker compose restart openclaw-gateway
If you paste the error, I can point to the exact character
Run:
docker compose run --rm -it openclaw-cli openclaw doctor
and paste the first error line that includes the file + line number (redact the auth token). That will tell us exactly whether it’s a JSON5 parse problem (comma/brace/quote) or a schema problem (wrong nesting / wrong key names).
I don’t see the actual error text/line number yet — “it breaks the config” can mean either:
- JSON5 parse error (missing comma/brace/quote), or
- schema error (right JSON5, wrong keys/nesting)
Can you paste the exact Doctor output (first error line that includes the file + line/column)?
Run this in your Docker setup:
docker compose run --rm -it openclaw-cli openclaw doctor
Then paste:
- the first ~10 lines of the error, and
- your
plugins.entries["voice-call"]block (redactauthTokenlike"****")
In the meantime, the #1 Twilio config “break” is missing quotes or wrong nesting. It must be:
plugins: {
entries: {
"voice-call": {
enabled: true,
config: {
provider: "twilio",
fromNumber: "+1555...",
twilio: { accountSid: "AC...", authToken: "****" }
}
}
}
}
Once you paste the real error line, I can point to the exact character that’s wrong.
i cant use openclaw commands
If you installed OpenClaw as a Docker container, you usually don’t have the openclaw CLI on the ZimaOS host — you have to run it inside the container (or via the openclaw-cli service if you used docker compose).
Option A (docker compose setup: openclaw-cli)
Run from the folder that has docker-compose.yml:
docker compose run --rm -it openclaw-cli openclaw --version
docker compose run --rm -it openclaw-cli openclaw doctor
Option B (no compose / Portainer / single container)
Exec into the gateway container and run the CLI via the Node entrypoint:
- Find the container name:
docker ps
- Run doctor inside it (replace the name):
docker exec -it openclaw-gateway node dist/index.js doctor
(You can also try openclaw doctor inside the container, but node dist/index.js ... works even when PATH is weird.)
Quick check
Try:
docker exec -it openclaw-gateway node dist/index.js --help
If you paste your docker ps output (just names/images/status — no secrets), I’ll tell you the exact command for your container names.
when i get a phone call from openclaw it say we are sorry a application error has accured
That Twilio voice message (“we’re sorry, an application error has occurred”) almost always means Twilio couldn’t fetch/parse the TwiML webhook from OpenClaw (or it got a 4xx/5xx back).
In your case (OpenClaw in Docker) the #1 gotcha is:
- Voice-call webhook server defaults to bind
127.0.0.1(inside the container) - and Twilio needs a publicly reachable URL to hit.
Fix checklist (Docker + Twilio)
1) Make the webhook server reachable from outside the container
In plugins.entries["voice-call"].config.serve, set bind to 0.0.0.0:
serve: {
port: 3334,
bind: "0.0.0.0",
path: "/voice/webhook"
},
And make sure your Docker container publishes that port, e.g.:
-p 3334:3334(or the equivalent in your compose/stack)
2) Expose it publicly (Twilio must reach it)
You need one of these:
publicUrl: "https://<your-public-host>/voice/webhook"(reverse proxy/domain)- or an ngrok URL (ngrok on the host or in-container)
- or Tailscale Funnel (public HTTPS)
Then set:
publicUrl: "https://YOUR_PUBLIC_HOST/voice/webhook"
3) Check the Twilio Debugger + OpenClaw logs (this will tell us which case it is)
In Twilio Console → Monitor → Debugger, you’ll usually see an error like 11200 / 11205 (HTTP retrieval failure) with the exact URL it tried.
Also check the gateway logs for [voice-call] errors (often signature validation or URL mismatch).
Paste these (redact secrets) and I’ll tell you the exact fix
- Twilio Debugger error code + message (11200 etc)
- Your
voice-callconfig block (redactauthToken) - How you run the container (compose? portainer?
docker run?) and whether port 3334 is published
setup ngrok on zimacube
If the goal is “I want to open the OpenClaw dashboard on my ZimaCube from outside my LAN”, the recommended way is Tailscale Serve (no public exposure). Docs: https://docs.openclaw.ai/gateway/remote
But if you specifically want ngrok, here’s the clean setup:
1) Confirm what you’re tunneling
OpenClaw’s dashboard/Gateway is usually on port 18789 (after onboarding). (Ref: docs FAQ)
2) Install + auth ngrok on the ZimaCube
- Install ngrok agent (however you install tools on ZimaOS), then:
ngrok config add-authtoken <YOUR_NGROK_TOKEN>
3) Start the tunnel (dashboard)
If OpenClaw is running on the same machine:
ngrok http 18789
# (equivalently: ngrok http http://127.0.0.1:18789)
ngrok will print a forwarding URL like:
https://xxxx.ngrok-free.app
4) Open it with your OpenClaw token
OpenClaw’s dashboard is protected by a token. Easiest way to get it:
openclaw dashboard
Copy the token=... part from the printed localhost URL and append it to the ngrok URL:
https://xxxx.ngrok-free.app/?token=PASTE_TOKEN_HERE
If OpenClaw is in Docker (common on ZimaOS)
Tell me which you’re doing:
- OpenClaw installed on host, or
- OpenClaw running in a container (and which port mapping)
Because if ngrok runs in a different container, 127.0.0.1:18789 won’t point at the OpenClaw container unless you use --network host or the same docker network + service name.
If you paste:
- how you’re running OpenClaw (command / compose snippet)
openclaw gateway status
…I can tell you the exact ngrok command/target to use.
ngrok-1 | ERROR: Error reading configuration file '/etc/ngrok.yml': read /etc/ngrok.yml: is a directory
That error is a Docker/volume-mount gotcha: ngrok expects /etc/ngrok.yml to be a file, but in your container it’s a directory.
This usually happens when your compose has something like:
volumes:
- ./ngrok.yml:/etc/ngrok.yml
…but ./ngrok.yml didn’t exist yet on the host, so Docker created it as a directory, and now ngrok chokes.
Fix options
Option A (simplest): don’t mount a config file at all
- Remove the
/etc/ngrok.ymlvolume mount - Provide the token via env var instead (
NGROK_AUTHTOKEN) - Recreate the container
Option B: mount an actual file
- On the host where you run docker compose, check whether your “ngrok.yml” path is a directory.
- If it is, rename it (don’t delete blindly), then create a real
ngrok.ymlfile. - Use a v3 config like:
version: 3
agent:
authtoken: YOUR_NGROK_TOKEN
- Mount it read-only:
volumes:
- ./ngrok.yml:/etc/ngrok.yml:ro
Quick sanity check
Inside the ngrok container, this should show it’s a file (not directory):
ls -la /etc/ngrok.yml
If you paste your ngrok service block from docker-compose.yml (just that part), I can tell you exactly what to change (and whether you should be tunneling 18789 directly or openclaw:18789 via the compose network).
its not working still
“Not working” can mean 3 totally different things with ngrok, so I need one concrete symptom:
- Does the ngrok container start and print a
Forwarding https://…URL, or does it exit with an error? - When you open the ngrok URL, what do you see exactly? (timeout / 502 / “refused to connect” / OpenClaw “unauthorized” / blank page)
If you can paste these (redact tokens), I can pinpoint it fast:
docker compose psdocker compose logs ngrok --tail=100- and if OpenClaw is also in compose:
docker compose logs openclaw --tail=100
Most common cause (especially since you’re running ngrok in Docker: ngrok-1):
The ngrok container is tunneling the wrong upstream
On Linux, if you do ngrok http 18789 inside the ngrok container, it tries to reach the ngrok container itself on port 18789 — not your OpenClaw service/host — so you get 502 / connection refused.
Fix depends on where OpenClaw is running:
A) OpenClaw is running on the HOST (not in docker)
- Either run ngrok on the host too, or
- point ngrok at the host from inside the container (Linux needs host-gateway mapping):
- add in compose:
extra_hosts:
- "host.docker.internal:host-gateway"
- then run:
ngrok http http://host.docker.internal:18789
B) OpenClaw is another CONTAINER in the same compose
- Put them on the same network (default compose network is fine)
- Target the service name:
ngrok http http://openclaw:18789
C) It opens but shows “unauthorized”
That’s expected unless you include the dashboard token. Run on the OpenClaw machine:
openclaw dashboard
…and open the ngrok URL with ?token=... appended.
Paste the docker compose ps + the ngrok logs and I’ll tell you which of A/B/C you’re hitting and the exact compose snippet to use.
Use "ngrok [command] --help" for more information about a command.
ngrok - tunnel local ports to public URLs and inspect traffic
USAGE:
ngrok [command] [flags]
COMMANDS:
api CLI to api.ngrok.com
completion generates shell completion code for bash or zsh
config update or migrate ngrok's configuration file
credits prints author and licensing information
help help about any command
http start an HTTP tunnel
service run and control ngrok as a background service
start start endpoints in the config file by name
tcp start a TCP tunnel
tls start a TLS endpoint
update update ngrok to the latest version
version print the version string
EXAMPLES:
forward http traffic from assigned public URL to local port 80
ngrok http 80
port 8080 available at baz.ngrok.dev
ngrok http --url baz.ngrok.dev 8080
tunnel arbitrary TCP traffic to port 22
ngrok tcp 22
secure your app with oauth
ngrok http 80 --oauth=google --oauth-allow-email=foo@foo.com
Paid Features:
ngrok http 80 --url mydomain.com # run ngrok with your own custom domain
ngrok http 80 --cidr-allow 2600:8c00::a03c:91ee:fe69:9695/32 # run ngrok with IP policy restrictions
Upgrade your account at https://dashboard.ngrok.com/billing/choose-a-plan to access paid features
Upgrade your account at https://dashboard.ngrok.com/billing/choose-a-plan to access paid features
Flags:
-h, --help help for ngrok
Use "ngrok [command] --help" for more information about a command.
That output is just ngrok’s generic help — it usually means you ran ngrok with no subcommand, so it never started a tunnel.
Try this (pick the case that matches your setup):
1) First confirm OpenClaw is actually reachable locally
On the ZimaCube, run:
curl -I http://127.0.0.1:18789/
You should get something back (often 200 or 401 Unauthorized).
If this times out / connection refused, ngrok won’t work yet because there’s nothing listening.
2) Start ngrok correctly
A) OpenClaw running on the host (not in Docker):
ngrok http 18789
B) OpenClaw running in Docker compose as a service named openclaw, and ngrok is also in compose:
Inside the ngrok container, the upstream must be the service name:
ngrok http http://openclaw:18789
C) OpenClaw on host, ngrok in Docker:
You need host access from the container (then tunnel host.docker.internal):
ngrok http http://host.docker.internal:18789
3) If it opens but shows “unauthorized”
That’s expected — you must use the OpenClaw dashboard token:
openclaw dashboard
Then open the ngrok URL with ?token=... appended.
If you paste the exact command you ran (and whether OpenClaw is host vs docker), plus the output of:
curl -I http://127.0.0.1:18789/ngrok http 18789(the output lines it prints)
…I can tell you the next exact fix.
it keeps crashing so i cant
What’s crashing — ngrok or OpenClaw?
Either way, the fastest way forward is: grab the crash reason from logs (even if it restarts too fast).
If you’re running them in Docker/Compose
Run these on the ZimaCube and paste output (redact tokens/domains if you want):
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
docker logs --tail=120 ngrok-1
docker logs --tail=120 openclaw-1 # only if you have this container
If it’s restarting too fast to catch, follow live:
docker logs -f ngrok-1
Very common cause (ngrok crash-loop)
You still have /etc/ngrok.yml mounted as a directory (or NGROK_CONFIG points at a directory). Quick check:
docker exec -it ngrok-1 ls -la /etc/ngrok.yml
It must start with - (file), not d (directory).
Quick workaround (avoid config file entirely)
If you want, you can run ngrok without /etc/ngrok.yml at all (less stuff to break):
- remove
NGROK_CONFIG - remove any volume mount to
/etc/ngrok.yml - pass the token via env var + command
If you paste your docker-compose.yml ngrok service block, I’ll rewrite it into the minimal working version for either:
- OpenClaw on the host (
127.0.0.1:18789), or
- OpenClaw as another compose service (
http://openclaw:18789).
Which Twilio product do you mean?
If you mean Twilio WhatsApp
OpenClaw doesn’t support Twilio WhatsApp anymore (it uses WhatsApp Web/Baileys instead). Reason + details: https://docs.openclaw.ai/channels/whatsapp#why-not-twilio
So there’s nothing to “point Twilio to” for WhatsApp in current OpenClaw — you’d instead do openclaw channels login and link via WhatsApp “Linked Devices”.
If you mean Twilio Voice (phone calls)
That’s supported via the Voice Call plugin, and yes—Twilio needs a public webhook URL to reach your Gateway host.
High level steps:
- Install + enable the plugin on the machine running the Gateway:
- Make the plugin’s webhook port public (ngrok / tailscale funnel). By default the plugin listens on something like:
serve.port: 3334serve.path: /voice/webhook
So your public URL should look like:
https://<your-public-host>/voice/webhook
- In the Twilio Console (Phone Numbers → your number → Voice config):
- Set “A CALL COMES IN” to Webhook =
https://<your-public-host>/voice/webhook - Save.
Important: if you’re using ngrok free tier, the URL changes when ngrok restarts, and Twilio signature verification will fail unless publicUrl matches exactly—so you’ll need to update config each time (or use a reserved domain / Tailscale Funnel for stability).
If you tell me “Twilio WhatsApp vs Twilio Voice” (and whether you’re using Docker), I’ll give you the exact URL/port you should expose and where to paste it in config.
im using deepclaw
Ah — deepclaw changes the answer. In deepclaw, Twilio should NOT point at OpenClaw directly; it points at the deepclaw server, and deepclaw forwards to your OpenClaw Gateway.
What to paste into Twilio
In Twilio Console → Phone Numbers → Active Numbers → (your number) → Voice Configuration:
- A CALL COMES IN: Webhook
- URL:
https://<your-ngrok-url>.ngrok-free.app/twilio/incoming - Method:
POST - Save
(That /twilio/incoming path is what deepclaw’s README specifies.)
What you need running for that to work
- deepclaw server listening locally (default is port 8000):
python -m deepclaw
- ngrok exposing deepclaw’s port:
ngrok http 8000- copy the
https://....ngrok-free.appURL and use it in Twilio as above
- OpenClaw must expose the chat-completions endpoint (deepclaw uses it):
openclaw config set gateway.http.endpoints.chatCompletions.enabled true
…and then restart your OpenClaw gateway.
If you tell me one detail, I can give the exact URL to use
Are you running deepclaw:
- (A) directly on the ZimaCube host, or
- (B) in Docker?
If you paste your deepclaw logs (last ~30 lines) + what ngrok URL you got, we can also confirm whether Twilio is reaching it (Twilio will otherwise show error 11200 in the console).
my openclaw isnt showing up messages anymore and heres the only log i get openclaw-gateway | 2026-02-09T12:56:55.132Z [ws] ⇄ res ✓ chat.history 52ms conn=ddebcfe4…c742 id=6484ef02…2067
That log line just means the Control UI is connected and asked the gateway for chat history (chat.history). It doesn’t tell us anything about inbound messages from Discord/WhatsApp/Twilio/etc.
To figure out why “messages aren’t showing up” we need to answer two things:
- Which surface stopped working? (Discord? WhatsApp? deepclaw phone calls? the web dashboard?)
- Is the gateway receiving the inbound event and then failing to reply, or is it not receiving anything at all?
Since you’re in Docker (log prefix openclaw-gateway |), please paste these outputs (they’re safe-ish; redact tokens if they appear):
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
docker logs --tail=200 openclaw-gateway
And the most useful one (channel health):
docker exec -it openclaw-gateway openclaw channels status --probe
Finally, do a live test:
- run
docker logs -f openclaw-gateway - then send a message to your bot / place a call
- paste the new log lines that appear right when you do that
With those, I can tell you immediately whether it’s a channel disconnected, auth/model failure, or you’re just looking at the wrong agent/session (deepclaw often creates/uses a separate voice agent).
i get http 500:500 internal server error: internal server error
That HTTP 500 is coming from something calling OpenClaw (deepclaw, the dashboard, or a CLI probe) — but 500 just means “the gateway crashed while handling the request”. We need the error line right before/after it in the gateway logs.
Two quick questions:
- Where do you see the 500? (deepclaw terminal? Twilio error 11200? browser? a command like
openclaw channels status --probe?) - Are you running OpenClaw in Docker as
openclaw-gateway? (sounds like yes)
Paste these (they won’t include secrets unless you’ve enabled very verbose logging)
docker logs --since 15m --tail=300 openclaw-gateway
If you can reproduce it (e.g. place a call / trigger deepclaw), do:
docker logs -f openclaw-gateway
then reproduce once, then paste the chunk where the 500 happens.
Also run (best “what’s broken” snapshot; it redacts tokens)
docker exec -it openclaw-gateway openclaw status --all
Common cause with deepclaw specifically: OpenClaw’s /v1/chat/completions endpoint is enabled, but the agent run behind it fails (no model credentials / “All models failed” / provider rate limit / etc.). The gateway logs will say exactly which.
Drop the docker logs --since 15m output here and I’ll tell you the precise fix.
i get that on the whatsapp to openclaw
WhatsApp itself normally won’t show “HTTP 500” when you DM a bot — so this sounds like you’re using some WhatsApp → webhook → OpenClaw bridge (Twilio WhatsApp / WhatsApp Cloud API / some relay) and that webhook call is getting a 500 from OpenClaw.
Two important splits:
1) If you meant Twilio WhatsApp / WhatsApp Cloud API
OpenClaw’s WhatsApp support is WhatsApp Web (Baileys), not Twilio/Cloud-API webhooks. Twilio WhatsApp support was removed. Docs: https://docs.openclaw.ai/channels/whatsapp#why-not-twilio
So you can’t “point Twilio WhatsApp to OpenClaw” in a supported way.
2) If you meant OpenClaw’s built-in WhatsApp Web channel
Then you won’t see an HTTP 500 in WhatsApp — instead the bot just stops replying when it’s unlinked/disconnected.
Run this in the container and paste the output:
docker exec -it openclaw-gateway openclaw channels status --probe
Also paste the last errors around the time you send a WhatsApp message:
docker logs --since 15m --tail=300 openclaw-gateway
Quick likely fix (if WhatsApp got unlinked)
If channels status shows WhatsApp not linked / disconnected, re-link:
docker exec -it openclaw-gateway openclaw channels login
Then scan the QR in WhatsApp → Linked Devices.
If you tell me where exactly you’re seeing “HTTP 500” (Twilio console error? a webhook response body? a log line?), I can tell you which of the two cases you’re in immediately.
i cant use those cmmants on my container
That usually just means you’re inside the OpenClaw container, and those commands I gave (docker exec …) must be run on the Docker host, not inside the container (containers typically don’t have the docker CLI).
So we have two ways forward — pick whichever access you actually have:
Option A) You can open a shell inside the openclaw-gateway container
Then run these inside the container (no docker needed) and paste output:
openclaw status --all
openclaw channels status --probe
And grab the real error (file log tail):
ls -la /tmp/openclaw
tail -n 200 "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"
Option B) You can’t run any shell commands, only use the ZimaOS UI (or Portainer/CasaOS)
Then open the container in the UI and copy/paste the logs around the time you send a WhatsApp message (we need the lines that include ERR / stack trace, not just the chat.history line).
Quick clarification (important)
When you say “HTTP 500 on the WhatsApp to OpenClaw”:
- Are you using OpenClaw’s built-in WhatsApp Web channel (QR “Linked Devices”), or
- some WhatsApp webhook bridge (Twilio/Cloud API/deepclaw/etc.)?
If you answer that + paste either the openclaw status --all output or the /tmp/openclaw/openclaw-*.log tail, we can pinpoint why it stopped replying.
fix it
You just pasted live secrets (Twilio Auth Token, OpenAI key, Home Assistant token, etc.) into a public Discord channel.
- Delete that message immediately (or at least edit + redact).
- Rotate/revoke:
- Twilio Auth Token (Twilio Console → Account → API keys / Auth token rotation)
- OpenAI API key
- Home Assistant long-lived token
- Anything else you consider sensitive (ElevenLabs, etc.)
Now, about “WhatsApp → OpenClaw gives HTTP 500”:
Key point
If you’re using OpenClaw’s built-in WhatsApp Web (QR “Linked Devices”), there is no HTTP webhook involved, so you would not see “HTTP 500” in WhatsApp. You’d just see the bot not reply.
So either:
- your WhatsApp is going through some webhook bridge (Twilio/Cloud API/etc.), or
- WhatsApp Web is disconnected and you’re seeing the 500 somewhere else (deepclaw logs, a proxy, etc.)
The one thing we need next (to stop guessing)
From inside the openclaw-gateway container (use ZimaOS/Portainer “Console/Exec” if needed), run and paste:
openclaw channels status --probe
That will tell us if WhatsApp is linked / disconnected / logged out.
And paste the real error around the time it fails:
tail -n 200 "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)"
Likely problem from your config
You’ve configured only one model: ollama/gpt-oss:120b-cloud via http://192.168.1.44:11434/v1.
If the gateway can’t reach that Ollama endpoint (or the model name doesn’t exist), the agent will fail and you’ll get errors/no replies.
Quick connectivity check from inside the container:
curl -sS http://192.168.1.44:11434/v1/models | head
Post the output of those 3 commands (status + log tail + models curl) and we can get you back to “messages show up + replies work” fast.
I can’t directly “fix it” from here (I don’t have access to your ZimaOS box), but based on the config you pasted there are two very likely hard failures we can fix quickly.
0) First: you leaked secrets
Please delete/edit that config paste and rotate at least:
- Twilio Auth Token
- OpenAI API key
- Home Assistant long-lived token
(Anyone who saw that message can take over those accounts / burn credits.)
1) Your model config is probably broken → OpenClaw can’t generate replies
Right now your only model is:
ollama/gpt-oss:120b-cloud at http://192.168.1.44:11434/v1
If that model doesn’t exist in Ollama (or Ollama isn’t reachable from the container), OpenClaw will error out and you’ll effectively get “no messages / 500s”.
Fix: point OpenClaw at a model that actually exists in Ollama.
On the machine running Ollama, check what’s installed:
- in Ollama UI or via terminal:
ollama list - or via HTTP:
http://192.168.1.44:11434/api/tags
Then change your OpenClaw model to one of those exact IDs (example: llama3.3, qwen2.5-coder:32b, etc.)
So in openclaw.json set:
agents: { defaults: { model: { primary: "ollama/<REAL_MODEL_ID_FROM_OLLAMA>" } } }
Restart the gateway container after editing.
2) WhatsApp “stopped showing messages” is usually: container got recreated → lost WhatsApp link
In Docker, if ~/.openclaw state isn’t persisted, WhatsApp creds vanish and it stops receiving messages until you re-link.
Fix: make sure your compose has persistent volumes for:
~/.openclaw/(state/credentials)~/.openclaw/workspace(workspace)
Then re-link WhatsApp (QR “Linked Devices”) from the gateway host/CLI.
What I need from you (so we stop guessing)
Since you said you can’t run docker exec commands, please paste the gateway log errors from your UI (Portainer / ZimaOS containers view):
- open
openclaw-gateway→ Logs - scroll to the moment you send a WhatsApp message
- paste the lines that include
ERR,error,All models failed,ECONNREFUSED,model not found, etc.
That one snippet will tell us whether it’s:
- WhatsApp not linked, or
- Ollama unreachable, or
- wrong model id, or
- something else.
If you paste ~50 lines around the error, I’ll tell you exactly what to change (and where) to get replies back.
please fix my config and my container was working before thatwith that moddle
I can help you fix the config, but first: you posted live API keys/tokens. Please delete that message and rotate (Twilio Auth Token + OpenAI key + Home Assistant token). Assume they’re compromised.
Now: your config is doing a bunch of unrelated things at once (WhatsApp + deepclaw + Twilio voice-call plugin + BlueBubbles + Whisper). To get you back to “it was working”, I’d simplify it and re-add pieces.
The config changes I recommend (safe + minimal)
A) If you’re using deepclaw, enable chat completions in OpenClaw
deepclaw calls OpenClaw via POST /v1/chat/completions, which is disabled by default unless you turn it on. Add this:
{
gateway: {
http: {
endpoints: {
chatCompletions: { enabled: true },
},
},
},
}
(Ref: https://docs.openclaw.ai/gateway/openai-http-api)
B) Don’t run both deepclaw and the OpenClaw voice-call Twilio plugin (for now)
deepclaw already handles Twilio itself. Running the OpenClaw voice-call plugin alongside it can add confusion and extra failing webhooks.
So temporarily disable/remove this block:
plugins: {
entries: {
"voice-call": { enabled: true, config: { /* twilio… */ } }
}
}
(You can add it back later if you want OpenClaw-native voice calling instead of deepclaw.)
C) WhatsApp: confirm whether selfChatMode is correct
- If OpenClaw is linked to your personal WhatsApp and you’re using “Message yourself”: keep
selfChatMode: true. - If OpenClaw is linked to a separate WhatsApp number: set
selfChatMode: false(self chat mode can break expectations).
I’d also temporarily make DMs “allowlist” (no pairing complexity while debugging):
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+61451811123"],
selfChatMode: true // or false depending on your setup
}
}
One non-config thing that commonly breaks WhatsApp in Docker
If the container got recreated and your ~/.openclaw state directory isn’t persisted, WhatsApp credentials disappear and it “stops receiving messages” until you re-link.
So even with a perfect config, you may still need to re-scan the QR (Linked Devices).
I need one detail to finish “fix it” properly
Which one are you running right now?
- deepclaw (python server + ngrok) and Twilio points to deepclaw, OR
- OpenClaw’s voice-call plugin (Twilio points directly to OpenClaw plugin webhook), OR
- neither (just WhatsApp)
And please paste (redacted) the last ~30 lines of the OpenClaw log where the 500 happens — that will tell us if it’s:
- Ollama unreachable (
ECONNREFUSED) - model name mismatch (
model not found) - WhatsApp logged out
- or something else
If you can’t run commands, just copy the lines from your container log UI.
openclaw-gateway | 2026-02-09T13:13:03.340Z [gateway] log file: /tmp/openclaw/openclaw-2026-02-09.log
openclaw-gateway | 2026-02-09T13:13:03.344Z [browser/service] Browser control se
openclaw-gateway | 2026-02-09T13:13:03.378Z [voice-call] Webhook server listening on http://127.0.0.1:3334/voice/webhook
openclaw-gateway | 2026-02-09T13:13:03.381Z [gateway] [voice-call] Runtime initialized
openclaw-gateway | 2026-02-09T13:13:03.381Z [gateway] [voice-call] Webhook URL: http://127.0.0.1:3334/voice/webhook
openclaw-gateway | 2026-02-09T13:13:03.693Z [ws] webchat connected conn=111699b5-f917-4d24-9f18-aef428a7d273 remote=192.168.1.52 client=openclaw-control-ui webchat vdev
openclaw-gateway | 2026-02-09T13:13:04.045Z [bluebubbles] [default] BlueBubbles server macOS 15.7.3
openclaw-gateway | 2026-02-09T13:13:04.047Z [bluebubbles] [default] BlueBubbles webhook listening on /https://jack-unimprovised-dauntingly.ngrok-free.dev/bluebubbles-webhook
openclaw-gateway | 2026-02-09T13:13:05.012Z [whatsapp] Listening for personal WhatsApp inbound messages.
openclaw-gateway | 2026-02-09T13:13:45.717Z [ws] ⇄ res ✓ channels.status 53ms conn=111699b5…d273 id=1cb4c881…0658
openclaw-gateway | 2026-02-09T13:13:48.780Z [ws] webchat disconnected code=1005 reason=n/a conn=111699b5-f917-4d24-9f18-aef428a7d273
openclaw-gateway | 2026-02-09T13:13:48.815Z [ws] webchat connected conn=0b650bc8-9de5-4925-97d8-65916210defb remote=192.168.1.52 client=openclaw-control-ui webchat vdev
openclaw-gateway | 2026-02-09T13:14:01.718Z [ws] ⇄ res ✓ channels.status 61ms conn=0b650bc8…defb id=f8181aef…0ac8
openclaw-gateway | 2026-02-09T13:18:13.600Z [reload] config change detected; evaluating reload (meta.lastTouchedAt, models.providers.ollama.models, channels.bluebubbles.enabled)
openclaw-gateway | 2026-02-09T13:18:13.602Z [reload] config change requires gateway restart (meta.lastTouchedAt)
openclaw-gateway | 2026-02-09T13:18:13.603Z [gateway] signal SIGUSR1 received
openclaw-gateway | 2026-02-09T13:18:13.604Z [gateway] received SIGUSR1; restarting
openclaw-gateway | 2026-02-09T13:18:13.615Z [gmail-watcher] gmail watcher stopped
openclaw-gateway | 2026-02-09T13:18:13.876Z [ws] webchat disconnected code=1012 reason=service restart conn=0b650bc8-9de5-4925-97d8-65916210defb
openclaw-gateway | 2026-02-09T13:18:13.905Z [canvas] host mounted at http://0.0.0.0:18789/__openclaw__/canvas/ (root /home/node/.openclaw/canvas)
openclaw-gateway | 2026-02-09T13:18:13.916Z [heartbeat] started
openclaw-gateway | 2026-02-09T13:18:13.918Z [gateway] agent model: ollama/gpt-oss:120b-cloud
openclaw-gateway | 2026-02-09T13:18:13.920Z [gateway] listening on ws://0.0.0.0:18789 (PID 1)
openclaw-gateway | 2026-02-09T13:18:13.921Z [gateway] log file: /tmp/openclaw/openclaw-2026-02-09.log
openclaw-gateway | 2026-02-09T13:18:13.924Z [browser/service] Browser control service ready (profiles=2)
openclaw-gateway | 2026-02-09T13:18:13.935Z [whatsapp] [default] starting provider (+61451811123)
openclaw-gateway | 2026-02-09T13:18:13.941Z [voice-call] Webhook server listening on http://127.0.0.1:3334/voice/webhook
openclaw-gateway | 2026-02-09T13:18:13.943Z [gateway] [voice-call] Runtime initialized
openclaw-gateway | 2026-02-09T13:18:13.945Z [gateway] [voice-call] Webhook URL: http://127.0.0.1:3334/voice/webhook
openclaw-gateway | 2026-02-09T13:18:14.694Z [ws] webchat connected conn=eaf3c92b-395f-4908-a97e-06947bb45aa9 remote=192.168.1.52 client=openclaw-control-ui webchat vdev
openclaw-gateway | 2026-02-09T13:18:16.017Z [whatsapp] Listening for personal WhatsApp inbound messages.
openclaw-gateway | 2026-02-09T13:18:16.224Z [ws] ⇄ res ✓ chat.history 61ms conn=eaf3c92b…5aa9 id=dd722235…8227
openclaw-gateway | 2026-02-09T13:18:28.746Z [ws] ⇄ res ✓ chat.history 82ms conn=eaf3c92b…5aa9 id=12f48a71…6be1
openclaw-gateway | 2026-02-09T13:18:47.076Z [ws] ⇄ res ✓
I can’t directly edit your container, but I can give you a “known-good” config to paste that gets you back to WhatsApp + Ollama only (and removes the stuff most likely to be causing the 500s).
Also: please don’t repost the old config again — it contained live keys/tokens. Delete it + rotate those creds.
1) What your log is telling us
Your gateway is running and WhatsApp is starting:
[whatsapp] ... starting providerListening for personal WhatsApp inbound messages.agent model: ollama/gpt-oss:120b-cloud
But you’re not showing any actual model error lines in the log paste. Those will be in the file it mentions:
/tmp/openclaw/openclaw-2026-02-09.log
That file will contain the real “why 500”.
2) “Fix config” (minimal, stable baseline)
Edit your openclaw.json to this shape (keep your Ollama IP, your WhatsApp allowFrom, and set selfChatMode correctly). The key changes are:
- disable Twilio voice-call plugin + BlueBubbles plugin for now
- fix the Ollama model entry so
maxTokensisn’t insane (yours was > context window)
{
models: {
providers: {
ollama: {
baseUrl: "http://192.168.1.44:11434/v1",
apiKey: "ollama-local",
api: "openai-completions",
models: [
{
id: "gpt-oss:120b-cloud",
name: "gpt-oss:120b-cloud",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 32000,
maxTokens: 4096
}
]
}
}
},
agents: {
defaults: {
model: { primary: "ollama/gpt-oss:120b-cloud" }
}
},
channels: {
whatsapp: {
// during debugging, avoid pairing complexity:
dmPolicy: "allowlist",
allowFrom: ["+61451811123"],
// ONLY keep this true if you are running on your *personal* WhatsApp number
// and testing via "Message yourself".
selfChatMode: true
}
},
plugins: {
enabled: true,
entries: {
whatsapp: { enabled: true },
// turn these off while debugging WhatsApp replies:
"voice-call": { enabled: false },
bluebubbles: { enabled: false }
}
}
}
Then restart the gateway/container.
Why this helps: if the problem is “model call fails → gateway throws 500”, lowering maxTokens and removing extra plugins eliminates a lot of failure modes.
3) The one log snippet that will end this
In your container UI (Portainer/ZimaOS), open the file log:
/tmp/openclaw/openclaw-2026-02-09.log
…and paste the lines around the error after you send a WhatsApp message. Search for things like:
All models failedECONNREFUSED 192.168.1.44:11434model not foundcontext_length/max_tokens
If you paste ~40 lines around the first error, I’ll tell you the exact remaining change (it’ll be something like “Ollama not reachable from container” vs “wrong model id” vs “WhatsApp got unlinked”).
its not my model or whats app
Then we’re missing the actual error.
The log chunk you pasted is only normal startup + Control UI reconnects. There’s zero error/stack trace in it, so nobody can tell what’s causing the HTTP 500 from that.
The 500 will always have an error line in the file log
Your gateway itself tells you where it writes the real errors:
/tmp/openclaw/openclaw-2026-02-09.log
In ZimaOS/Portainer, open the openclaw-gateway container → Files / Console and grab the lines around the error right after you trigger it (send a WhatsApp msg / whatever triggers the 500). Search in that file for:
ERRERRORAll models failedECONNREFUSEDmodel not found
Paste ~30–50 lines around the first error. Without that, we’re guessing.
If you want a “stop the bleeding” config anyway (to prove it’s not WhatsApp/model)
Temporarily disable everything that can throw 500s (Twilio voice-call plugin, BlueBubbles plugin, extra skills). Run WhatsApp only for 5 minutes:
{
models: { providers: { ollama: { baseUrl: "http://192.168.1.44:11434/v1", apiKey: "ollama-local", api: "openai-completions" } } },
agents: { defaults: { model: { primary: "ollama/gpt-oss:120b-cloud" } } },
channels: { whatsapp: { dmPolicy: "allowlist", allowFrom: ["+61451811123"], selfChatMode: true } },
plugins: { enabled: true, entries: { whatsapp: { enabled: true }, "voice-call": { enabled: false }, bluebubbles: { enabled: false } } }
}
Restart container, test WhatsApp. If that works, we re-enable one component at a time until it breaks (that’s how we “fix it” reliably).
But the fastest path is still: paste the error lines from /tmp/openclaw/openclaw-2026-02-09.log.
its not whatsapp your not listening and its not ollama either im not seeing any words in the openclaw ui
i cant get to the log files
If you can’t access /tmp/openclaw/openclaw-*.log, we can still get the same error another way.
Option 1 (best): use the Control UI “Logs” tab
You already have the Control UI connected (client=openclaw-control-ui in your logs).
- Open the dashboard:
http://<zimacube-ip>:18789/ - Go to Logs
- Reproduce the problem (send the WhatsApp msg / trigger the thing that causes 500)
- Copy/paste the red error lines from the Logs view
That Logs tab tails the file log via RPC, so you don’t need filesystem access.
Option 2: temporarily redirect file logs into the container logs (so you can paste them)
Edit openclaw.json and add this temporarily:
{
logging: {
level: "debug",
file: "/dev/stdout",
consoleLevel: "debug",
consoleStyle: "pretty"
}
}
Restart the container, reproduce once, then the real error should show up directly in the container logs you’re already pasting here.
(After we fix it, set logging.file back to default or remove it.)
One quick check you can do without any file access
When you reproduce, do you see any new log lines like whatsapp/inbound right when you send the message?
- If yes: WhatsApp is reaching the gateway, and the 500 is from the model/tool run → we need the error line (Options 1/2).
- If no: it’s not receiving WhatsApp messages at all (usually unlinked/disconnected or you’re not actually using the built-in WhatsApp Web channel).
If you tell me whether the Control UI “Logs” tab works for you, I’ll pick the shortest path.
how do i wipe everything and start fresh while keeping the ollama and ui
First: you pasted live tokens/keys earlier. Please delete that Discord message and rotate Twilio/AuthToken + OpenAI + Home Assistant (assume they’re compromised).
Now, to wipe OpenClaw completely and start fresh while keeping Ollama + the UI:
Option A (cleanest): run OpenClaw’s built-in reset
This wipes OpenClaw state (config, sessions, credentials, workspace), but does not touch your Ollama machine.
Inside the openclaw-gateway container console (Portainer/ZimaOS usually has an “Exec/Console” button), run:
openclaw reset --scope full --yes --non-interactive
Then re-run onboarding:
openclaw onboard
Docs: https://docs.openclaw.ai/help/faq#how-do-i-completely-reset-openclaw-but-keep-it-installed
After that:
- the UI is still at
http://<host>:18789/ - you’ll need to re-link WhatsApp (QR / Linked Devices)
- re-add your Ollama provider (same baseUrl as before)
Option B (Docker “nuke from orbit”): delete the persisted OpenClaw state volume/folder
If you can’t run openclaw reset, you can wipe by deleting the folder/volume that’s mounted as OpenClaw state.
In your container UI, open Container details → Mounts/Volumes and find what host path maps to:
~/.openclaw(often/home/node/.openclawinside the container)
Then delete that host folder (or remove the named volume) and restart/recreate the container.
This achieves the same effect as a full reset, but it’s more manual.
Quick question so I tell you the exact clicks
Are you managing this with Portainer / ZimaOS “Apps” UI? If yes, tell me which, and paste the Mounts section for openclaw-gateway (just the paths, redact nothing-sensitive). Then I’ll tell you exactly which folder/volume to delete to wipe OpenClaw while leaving Ollama untouched.
zima apps ui
In the ZimaOS Apps UI, you basically have two “start fresh” paths. One is a proper OpenClaw reset (best), the other is uninstall + delete app data (works even if you can’t run commands).
Before you do anything: please delete the config message you posted earlier (it contained live tokens) and rotate those keys/tokens.
Path A (best): run openclaw reset inside the OpenClaw container
- ZimaOS Apps → click your OpenClaw app → look for something like Terminal / Console / Exec (wording varies).
- Run:
openclaw reset --scope full --yes --non-interactive
openclaw onboard
This wipes OpenClaw’s config/creds/sessions/workspace and rebuilds it, but does not touch Ollama (since Ollama is on another host).
After onboarding you’ll need to:
- re-enter your Ollama baseUrl/model
- re-link WhatsApp (QR / Linked Devices) if you use it
Path B (no terminal needed): uninstall OpenClaw + delete its data/volumes
- ZimaOS Apps → OpenClaw → Uninstall/Remove
- When it asks whether to keep data, choose remove/delete app data / volumes (the wording is usually “Delete data” / “Remove volumes” / “Purge”)
- Reinstall OpenClaw from the app store and run onboarding again.
That achieves the “wipe everything” effect because it deletes the persisted ~/.openclaw state that the container was using.
Quick question so I can tell you exactly what button to press
When you open the OpenClaw app in ZimaOS, do you see a Terminal/Console/Exec button anywhere, or only Logs/Restart/Stop?
$ openclaw reset --scope full --yes --non-interactive
/bin/sh: 2: openclaw: Permission denied
openclaw: Permission denied means the shell you’re using can see an openclaw executable, but the container user isn’t allowed to run it (wrong container, wrong file perms, or the binary is on a noexec mount).
Since you’re on the Zima Apps UI, the simplest “wipe everything and start fresh” is UI-driven (no CLI needed):
Easiest reset on ZimaOS (recommended)
- Zima Apps UI → OpenClaw → Stop
- Uninstall/Remove
- When prompted, choose Delete data / Remove volumes / Purge (wording varies)
- Reinstall OpenClaw
- Re-run onboarding and re-enter only:
- Ollama base URL (
http://192.168.1.44:11434/v1) - your model id
- re-link WhatsApp (scan QR) if you use WhatsApp Web
This keeps Ollama untouched (it’s on a different host) and the UI comes back automatically with the fresh install.
If you want to reset without uninstalling (works if you have a terminal in the container)
You can wipe OpenClaw state by renaming its state folder (safer than deleting):
ls -la /home/node
ls -la /home/node/.openclaw
mv /home/node/.openclaw /home/node/.openclaw.bak
Then restart the OpenClaw app/container from the UI.
If you still want the CLI reset (optional)
In the Docker setup, CLI commands are often run in a separate openclaw-cli container. In the Zima UI, check whether your app has a second container called something like openclaw-cli. If yes, open a terminal there and run:
openclaw reset --scope full --yes --non-interactive
If you tell me what buttons you see on the OpenClaw app page (especially anything like “Delete Data”, “Volumes”, “Storage”, or a list of containers), I’ll tell you the exact clicks.
Okay I have bluebubbles setup and I can send messages from Openclaw to iMessages but can’t see iMessages to Openclaw
If OpenClaw → iMessage works but iMessage → OpenClaw doesn’t, that almost always means: OpenClaw can reach the BlueBubbles REST API, but BlueBubbles webhooks are not reaching your OpenClaw Gateway (or they’re being rejected).
Here’s the checklist that fixes 95% of cases:
1) Fix webhookPath (common misconfig)
In OpenClaw config, channels.bluebubbles.webhookPath must be a path only, not a full URL.
Correct:
channels: {
bluebubbles: {
webhookPath: "/bluebubbles-webhook",
}
}
Wrong (breaks inbound):
webhookPath: "https://....ngrok-free.app/bluebubbles-webhook"
If your logs ever showed something like:
BlueBubbles webhook listening on /https://...
that’s the smoking gun.
2) Point BlueBubbles Server webhooks to your Gateway (full URL)
In the BlueBubbles macOS Server app → Webhooks:
Set the webhook URL to your Gateway URL + webhookPath, and include the password:
Example (LAN):
http://<your-zimacube-ip>:18789/bluebubbles-webhook?password=<BLUEBUBBLES_PASSWORD>
If you’re using a tunnel instead:
https://<your-public-url>/bluebubbles-webhook?password=<BLUEBUBBLES_PASSWORD>
Use the same port you open the OpenClaw dashboard with (often 18789).
3) Make sure OpenClaw isn’t blocking DMs (pairing/allowlist)
To remove access-control as a variable while testing, set temporarily:
channels: { bluebubbles: { dmPolicy: "open" } }
(Then tighten it back to allowlist once inbound works.)
4) How to confirm quickly
After saving the webhook in BlueBubbles, send yourself an iMessage and watch for new BlueBubbles inbound lines in the OpenClaw logs.
If BlueBubbles shows webhook delivery errors (401/403 = password mismatch; timeout = wrong URL/port/firewall), paste that error text and I’ll tell you exactly which side is wrong.
If you paste your current channels.bluebubbles block (with passwords removed), I’ll sanity-check it.
{
channels: {
bluebubbles: {
enabled: true,
serverUrl: "http://192.168.1.117:1234",
password: "",
webhookPath: "https://jack-unimprovised-dauntingly.ngrok-free.dev/bluebubbles-webhook",
},
},
}
That config is the reason inbound doesn’t work.
Fix 1: webhookPath must be a path, not a full URL
Set it to the default path:
channels: {
bluebubbles: {
enabled: true,
serverUrl: "http://192.168.1.117:1234",
password: "<YOUR_BLUEBUBBLES_API_PASSWORD>",
webhookPath: "/bluebubbles-webhook",
// optional while testing:
// dmPolicy: "open",
},
}
Fix 2: The BlueBubbles server must be configured to POST webhooks to your Gateway (full URL)
In the BlueBubbles macOS server app (Webhooks settings), set the webhook URL to your OpenClaw Gateway, e.g. (LAN example):
http://<ZIMACUBE_IP>:18789/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_API_PASSWORD>
If you really need ngrok, then ngrok should point at your OpenClaw Gateway, and BlueBubbles should use that ngrok URL (still ending in /bluebubbles-webhook?...). But that URL goes in BlueBubbles’ webhook config — not in webhookPath.
After changing it
Restart the OpenClaw gateway container, then send an iMessage to yourself. You should start seeing inbound BlueBubbles webhook log lines and OpenClaw should reply.
If you tell me your ZimaCube’s LAN IP and what port your OpenClaw UI is on (likely 18789), I’ll write the exact webhook URL to paste into BlueBubbles.
192.168.1.44:18789
Great — then set it up like this:
1) OpenClaw config (path only)
channels: {
bluebubbles: {
enabled: true,
serverUrl: "http://192.168.1.117:1234",
password: "<YOUR_BLUEBUBBLES_API_PASSWORD>",
webhookPath: "/bluebubbles-webhook",
// optional for testing:
// dmPolicy: "open",
},
}
2) BlueBubbles Server webhook URL (full URL to your Gateway)
In the BlueBubbles macOS Server app → Webhooks, set the webhook to:
http://192.168.1.44:18789/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_API_PASSWORD>
(Use the same password you set in OpenClaw config.)
3) Restart + test
- Restart the OpenClaw gateway container
- Send an iMessage to that Mac / chat
- You should now see inbound events and OpenClaw should respond
If it still doesn’t, the next two checks are:
- your gateway bind mode (must listen on LAN, not just 127.0.0.1)
- firewall/network rules between
192.168.1.117(Mac) →192.168.1.44:18789(ZimaCube)
{
"status": "error",
"tool": "write",
"error": "EISDIR: illegal operation on a directory, open '/home/node/.openclaw/workspace'"
}
i get this error
?
How do you install deepclaw on Openclaw?
“DeepClaw” isn’t something that ships with core OpenClaw, so the install depends on what you mean:
If “DeepClaw” is a skill (most likely)
Install it via ClawHub:
- Install ClawHub CLI:
npm i -g clawhub
# or
pnpm add -g clawhub
- Search for the exact skill slug:
clawhub search deepclaw
- Install it (use the slug you found):
clawhub install <skill-slug>
OpenClaw will pick it up from your workspace’s skills/ folder on the next new session (so start a new chat/session, or restart the gateway if needed).
Docs: https://docs.openclaw.ai/tools/clawhub
If you meant a model/provider (e.g. “DeepSeek”-style)
You don’t “install” models in OpenClaw—you add provider credentials and then select a model. Tell me which provider you’re using (OpenRouter? local LM Studio? etc.) and I’ll point you at the right doc section.
If you can drop a link (GitHub/ClawHub page) to what you’re calling “deepclaw”, I can give the exact steps.
https://github.com/deepgram/deepclaw here’s the GitHub
How would I install this GitHub
Drop the GitHub URL and I’ll tell you the exact install command (it depends on whether it’s a skill or a plugin).
In the meantime, here are the two common cases:
1) If the repo is an OpenClaw skill (it contains a SKILL.md)
Clone/copy it into your OpenClaw workspace’s skills/ folder:
openclaw config get agents.defaults.workspace
# then:
cd <that-workspace>
mkdir -p skills
git clone <github-url> skills/<skill-name>
Then start a new session (skills are picked up on next session) or restart the gateway.
Docs: https://docs.openclaw.ai/tools/skills
2) If the repo is an OpenClaw plugin (it contains openclaw.plugin.json)
Clone it anywhere, then install from the local path:
git clone <github-url> ~/tmp/my-plugin
openclaw plugins install ~/tmp/my-plugin
# restart gateway after installing
Docs: https://docs.openclaw.ai/tools/plugin
Send the repo link and I’ll confirm which one it is.
That repo isn’t an OpenClaw plugin you “install into OpenClaw” — it’s a separate Python service (“deepclaw”) that talks to your OpenClaw Gateway and gives it phone-call voice via Deepgram + Twilio/Telnyx.
1) Enable OpenClaw’s OpenAI-compatible HTTP endpoint
deepclaw needs /v1/chat/completions, which is disabled by default:
openclaw config set gateway.http.endpoints.chatCompletions.enabled true
openclaw gateway restart
OpenClaw docs (auth + endpoint details):
https://docs.openclaw.ai/gateway/openai-http-api
You’ll also need your gateway token:
openclaw config get gateway.auth.token
2) Install + run deepclaw (Python)
git clone https://github.com/deepgram/deepclaw
cd deepclaw
pip install -e .
cp .env.example .env
Edit .env and set at least:
DEEPGRAM_API_KEY=...- Twilio or Telnyx creds
OPENCLAW_GATEWAY_URL=http://127.0.0.1:18789OPENCLAW_GATEWAY_TOKEN=...
Then run:
python -m deepclaw
3) (Optional but recommended) Install the included OpenClaw skill
So OpenClaw can guide setup:
cp -r skills/deepclaw-voice ~/.openclaw/skills/
Then start a new OpenClaw session so it reloads skills.
Skills docs: https://docs.openclaw.ai/tools/skills
4) Expose it + connect your phone provider
Typically:
ngrok http 8000
Then set your Twilio/Telnyx webhook URL to the ngrok URL (see their README).
Security gotcha
Don’t leave an ngrok URL publicly discoverable. Treat it like a public API to your OpenClaw credits; lock it down (private URL, IP allowlist, auth, etc.).
If you tell me whether you’re on Windows/WSL, Linux, or macOS + Twilio vs Telnyx, I can paste the exact minimal commands for that setup.
deepclaw is not “installed into OpenClaw” like a normal plugin. It’s a separate Python server you run next to OpenClaw, and it calls into your OpenClaw Gateway over HTTP.
If your goal is “I want to phone-call my OpenClaw”, the minimal checklist is:
- OpenClaw is already running (gateway up on e.g.
http://127.0.0.1:18789) - Enable the HTTP endpoint deepclaw needs:
openclaw config set gateway.http.endpoints.chatCompletions.enabled true
openclaw gateway restart
openclaw config get gateway.auth.token
- Install + run deepclaw:
git clone https://github.com/deepgram/deepclaw
cd deepclaw
pip install -e .
cp .env.example .env # then edit .env with your keys + gateway url/token
python -m deepclaw
- Expose deepclaw to the internet (ngrok) and point Twilio/Telnyx webhooks at it:
ngrok http 8000
Two quick questions so I can give you the exact “do this / paste that” steps:
- What OS are you on (Windows/WSL, Linux, macOS)?
- Are you using Twilio or Telnyx (or neither yet)?
So Openclaw is running on a zimacube running zimaos in a docker container and could I run deepclaw on Mac and point it to the container
Yes — that setup makes sense.
Architecture: deepclaw can run on your Mac, and it will call your OpenClaw Gateway in the ZimaOS Docker container over the network. Separately, Twilio/Telnyx will call deepclaw (so deepclaw still needs to be internet-reachable via ngrok or similar).
What you need on the ZimaOS/OpenClaw (Docker) side
- Make the Gateway reachable from your Mac
- Container must publish the gateway port (default 18789) to the LAN (
-p 18789:18789in Docker / equivalent in ZimaOS UI). - OpenClaw must bind to LAN, not loopback. In config that’s:
gateway.bind: "lan"
- Make sure Gateway auth is set (required for non-loopback binds)
gateway.auth.mode: "token"gateway.auth.token: "…"
FAQ reference (bind + token): https://docs.openclaw.ai/help/faq#i-set-gatewaybind-lan-or-tailnet-and-now-nothing-listens--the-ui-says-unauthorized
- Enable the HTTP endpoint deepclaw needs
deepclaw uses OpenClaw’s OpenAI-compatible endpoint:
gateway.http.endpoints.chatCompletions.enabled: true
Docs: https://docs.openclaw.ai/gateway/openai-http-api
What you set on the Mac (deepclaw)
In deepclaw’s .env:
OPENCLAW_GATEWAY_URL=http://<zima-ip-or-hostname>:18789OPENCLAW_GATEWAY_TOKEN=<your gateway.auth.token>
Then deepclaw runs on the Mac and proxies calls to the ZimaOS-hosted OpenClaw.
Quick sanity test (from the Mac)
Before involving Twilio/ngrok, test the connection from the Mac to the ZimaOS gateway:
curl -sS http://<zima-ip>:18789/v1/chat/completions \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"model":"openclaw","messages":[{"role":"user","content":"hi"}]}'
If you tell me how you’re running the OpenClaw container (docker run line / compose snippet / ZimaOS template), I can point out exactly where to set the port mapping + gateway.bind.
Zimaos template
You there?
Yep.
If you’re stuck right now, paste one of these and I’ll tell you what to change:
-
The ZimaOS Docker config for OpenClaw (screenshot or the docker run / compose snippet), especially the ports section.
-
From your Mac, what happens with:
curl -v http://<zima-ip>:18789/health
(or if /health 404s, just curl -v http://<zima-ip>:18789/ and paste the first ~20 lines)
Most common issue in your setup is: the container is only binding to 127.0.0.1 (loopback) or the port isn’t published, so the Mac can’t reach it.
I can reach the zimacube
Nice — if you can reach the ZimaCube host, the next question is: can your Mac reach the OpenClaw Gateway port inside the container?
From your Mac, run one of these:
A) Just test the port is open
nc -vz <zima-ip> 18789
B) Test the exact endpoint deepclaw needs (expects either 401 or a JSON response)
curl -i http://<zima-ip>:18789/v1/chat/completions
What the result means
- Connection refused / timeout → Docker/ZimaOS isn’t publishing the port, or OpenClaw is still bound to loopback inside the container.
Fixes are usually:
-
publish
18789:18789in the container settings -
set
gateway.bind: "lan"(so it listens on0.0.0.0, not127.0.0.1) -
HTTP 401 Unauthorized → perfect: it’s reachable, auth is working.
-
404 Not Found on
/v1/chat/completions→ you still need to enable: -
gateway.http.endpoints.chatCompletions.enabled: true
And yes: once the Mac can reach http://<zima-ip>:18789, you can run deepclaw on the Mac and set:
OPENCLAW_GATEWAY_URL=http://<zima-ip>:18789OPENCLAW_GATEWAY_TOKEN=<gateway.auth.token>
If you paste your ZimaOS container “ports” screenshot (or the compose snippet), I’ll tell you exactly what to change.
It connects perfectly
Cool — then you’re basically done on the networking side.
Next steps are just making deepclaw point at it:
- On your Mac (deepclaw folder), set in
.env:
OPENCLAW_GATEWAY_URL=http://<zima-ip>:18789OPENCLAW_GATEWAY_TOKEN=<your gateway token>- and enable
gateway.http.endpoints.chatCompletions.enabled: trueon the OpenClaw side if you haven’t already.
- Quick verify from the Mac (this should return JSON, not hang):
curl -sS http://<zima-ip>:18789/v1/chat/completions \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"model":"openclaw","messages":[{"role":"user","content":"hi from deepclaw test"}]}'
- Run deepclaw:
python -m deepclaw
After that, the remaining work is Twilio/Telnyx + ngrok (so Twilio can reach your Mac). If you tell me which provider you picked (Twilio vs Telnyx), I’ll give you the exact webhook URL path you need to paste into their console.
Can I run ngrok on my zimacube for that? As I already have ngrok on my mac for bluebubbles
Yes, you can run ngrok on the ZimaCube — but it only helps if it’s tunneling to wherever deepclaw is listening.
You have 3 workable options:
Option A (simplest): keep ngrok on the Mac and run 2 tunnels
If deepclaw runs on your Mac (:8000) and BlueBubbles is also on your Mac, you can run one ngrok agent with multiple tunnels (one for each local port). This avoids extra LAN hops and firewall weirdness.
Option B: run ngrok on the ZimaCube, but tunnel to the Mac’s deepclaw
This works if:
- deepclaw on the Mac listens on the LAN (e.g.
0.0.0.0:8000, not just127.0.0.1) - your Mac firewall allows inbound from the ZimaCube to port
8000
Then configure ngrok on ZimaCube to forward to MAC_IP:8000 (ngrok can tunnel to a non-local upstream via addr: <ip>:<port> in ngrok config).
Option C: run deepclaw on the ZimaCube too
Then ngrok on the ZimaCube is totally straightforward (ngrok http 8000), and deepclaw talks to OpenClaw locally.
If you tell me:
- where BlueBubbles is running (Mac or ZimaCube), and
- where you plan to run deepclaw (Mac or ZimaCube),
I’ll tell you the cleanest exact setup for ngrok (and what to put into Twilio/Telnyx).
after a reboot bluebubbles isnt work
BlueBubbles dying after a reboot is usually one of these: it didn’t auto-start, its IP/hostname changed, or it needs an unlocked/login session (if it’s on macOS).
A couple quick checks so I can point you at the right fix:
- Where is your BlueBubbles server running?
- On the ZimaOS box (Docker container)?
- On a Mac (BlueBubbles Server app)?
- After reboot, is it actually running?
- If Docker/ZimaOS: can you paste:
docker ps -adocker logs --tail=200 bluebubbles(or whatever the container name is)- Also check the container’s restart policy (in UI or:
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' bluebubbles)- You generally want
unless-stoppedoralways.
- You generally want
- Did the server address change?
- If your ZimaOS/Mac got a new LAN IP after reboot, the BlueBubbles clients will “stop working” until you update the address.
- Fix: give that machine a DHCP reservation (static IP) or use a hostname instead of a raw IP.
If you tell me Docker vs Mac + paste the logs tail, I’ll tell you exactly what to change. (Feel free to redact tokens/URLs.)
so its running on mac
If BlueBubbles Server is on a Mac, it often “breaks after reboot” for one of these boring reasons:
- Mac is sitting at the login screen / user not logged in
- BlueBubbles won’t run properly until the Mac user session is logged in + unlocked.
- Check: is the Mac actually logged into your user account after reboot?
- BlueBubbles Server didn’t auto-start
- Open the BlueBubbles Server app on the Mac and see if it says it’s connected/ready.
- Then enable auto-start:
- macOS System Settings → General → Login Items → add/enable BlueBubbles Server
- Mac got a new LAN IP after reboot
- Your clients will fail to connect if they still point at the old IP.
- Check the Mac’s current IP in System Settings → Network and update the client, or set a DHCP reservation in your router so the Mac keeps the same IP.
Tell me what “isn’t work” means on your side (client can’t connect vs messages not sending), and whether the Mac is logged in + awake, and I’ll narrow it down fast.
i get ngrok 404 error not found for bluebubbles
ngrok 404 Not Found usually means you’re opening an ngrok URL that doesn’t currently have an active tunnel behind it (common right after a reboot).
On the Mac:
- Open BlueBubbles Server and check it actually says the server is running + connected.
- If it looks stuck: Stop server → Start server (or quit/reopen the app).
- In BlueBubbles Server, go to the ngrok section and look at the current ngrok URL.
- If you’re on free ngrok, the URL often changes after restart.
Your old URL will give a 404 → update your BlueBubbles client / anything using it (OpenClaw config, etc.) to the new URL.
- Make sure it auto-recovers after reboot:
- Add BlueBubbles Server to macOS Login Items
- Ensure the Mac user is actually logged in after reboot (not sitting at the login screen)
If you paste (screenshot/text) what BlueBubbles shows for Server status + ngrok URL after reboot, I can tell you which of the above it is in 10 seconds.
so its through webhooks
Yep — OpenClaw’s BlueBubbles integration receives incoming iMessages via webhooks.
If you’re seeing an ngrok 404, it’s almost always one of these:
- Wrong webhook URL (missing the path)
- The webhook must hit the gateway’s webhook route, not just the ngrok base URL.
- Default is:
https://<your-ngrok-domain>/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_PASSWORD> - If you changed it in OpenClaw config (
channels.bluebubbles.webhookPath), the URL has to match that path.
- Stale ngrok URL (free ngrok changes after reboot)
- After reboot the old ngrok domain often points to nothing → 404.
- Fix: copy the new ngrok URL and update the webhook target in BlueBubbles.
Quick sanity check: is the 404 page clearly ngrok-branded (“tunnel not found”), or is it an OpenClaw/gateway 404 (e.g. “Cannot GET /…”)?
- ngrok-branded 404 ⇒ URL changed / tunnel not running
- gateway 404 ⇒ wrong path (not
/bluebubbles-webhook) or BlueBubbles channel not enabled
Docs (with the exact webhook example): https://docs.openclaw.ai/channels/bluebubbles
If the ngrok tunnel is “running” but you still get a 404, it’s almost always one of these two:
- You’re hitting the wrong path
- Opening the ngrok URL in a browser like
https://xxxx.ngrok.app/can totally show 404 — that doesn’t mean the webhook is wrong. - For BlueBubbles → OpenClaw, the URL must be exactly:
https://<ngrok-domain>/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_PASSWORD>
(or whatever you set aschannels.bluebubbles.webhookPath)
- ngrok is tunneling the wrong thing (wrong host/port)
- The webhook must go to the OpenClaw gateway (on ZimaOS), usually port 3000.
- If you’re running ngrok on the Mac and it’s forwarding to the Mac (or to the BlueBubbles port) instead of forwarding to the ZimaOS gateway, you’ll get 404/incorrect responses.
Can you paste the single line from ngrok that shows the current Forwarding URL (and where it forwards, e.g. http://localhost:3000), and tell me what port your OpenClaw gateway is on? Then I can tell you exactly what to put into the BlueBubbles webhook setting.
Docs reference (webhook example): https://docs.openclaw.ai/channels/bluebubbles
http://localhost:12345 and then openclaw is 18789
You’ve got the ports flipped.
localhost:12345= BlueBubbles Server API (on the Mac):18789= OpenClaw Gateway (on ZimaOS)
Webhooks go from BlueBubbles → OpenClaw, so the webhook URL must hit the OpenClaw port (18789), not 12345.
If Mac + ZimaOS are on the same LAN (no ngrok needed)
In BlueBubbles Server → Webhooks, set something like:
http://<ZIMAOS_LAN_IP>:18789/bluebubbles-webhook?password=<YOUR_BB_API_PASSWORD>
And in OpenClaw config, make sure:
channels.bluebubbles.serverUrlis NOThttp://localhost:12345(that would mean “localhost on ZimaOS”)- it should be:
http://<MAC_LAN_IP>:12345
If you want to keep ngrok
Run ngrok pointing at OpenClaw (18789) (ideally on the ZimaOS box), and set the webhook to:
https://<ngrok-domain>/bluebubbles-webhook?password=<...>
If you paste your Mac LAN IP and ZimaOS LAN IP (e.g. 192.168.x.x), I’ll tell you the exact two URLs to put in each place. Docs: https://docs.openclaw.ai/channels/bluebubbles
Those aren’t IP addresses — localhost just means “this same machine”.
What you need are two LAN IPs (usually 192.168.x.x / 10.x.x.x):
- Mac IP (where BlueBubbles runs): macOS System Settings → Network → (Wi‑Fi/Ethernet) → Details → IP Address
- ZimaOS IP (where OpenClaw runs): ZimaOS UI → network info (or your router’s device list)
Then configure like this (no ngrok needed if both are on the same home network):
1) OpenClaw → talk to BlueBubbles (outbound)
channels.bluebubbles.serverUrl = "http://<MAC_IP>:12345"
2) BlueBubbles → send webhooks to OpenClaw (inbound)
In BlueBubbles Server Webhook URL:
http://<ZIMAOS_IP>:18789/bluebubbles-webhook?password=<YOUR_BB_PASSWORD>
If you paste the Mac IP + ZimaOS IP (just the 192.168... numbers), I’ll reply with the exact two URLs filled in.
192.168.1.117 for mac and 192.168.1.44 for zimaos
Perfect — here are the exact URLs.
OpenClaw config (on ZimaOS) → BlueBubbles Server (on Mac)
Set:
channels.bluebubbles.serverUrl=http://192.168.1.117:12345
BlueBubbles Server webhook (on Mac) → OpenClaw Gateway (on ZimaOS)
Set the webhook URL to:
http://192.168.1.44:18789/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_PASSWORD>
Notes:
- That
/bluebubbles-webhookpath must match your OpenClawchannels.bluebubbles.webhookPath(default is exactly that). - Once you switch to LAN IPs, you can ditch ngrok entirely (more reliable, no URL changes).
If it still doesn’t fire: open the webhook URL in a browser (with the password) and tell me what you see (404 vs “method not allowed” vs something else).
comes up saying method not allowed
“Method not allowed” is actually a good sign here.
You’re opening the webhook URL in a browser, which sends a GET request — but the BlueBubbles webhook endpoint only accepts POST (BlueBubbles will POST to it), so you’ll get 405 Method Not Allowed when testing manually.
Next things to verify:
-
In BlueBubbles Server (on the Mac), the webhook URL is set exactly to:
http://192.168.1.44:18789/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_PASSWORD>
(no extra spaces, correct password) -
Send a real iMessage to that BlueBubbles-connected account and watch:
- BlueBubbles Server logs (it should show the webhook delivery)
- OpenClaw logs (you should see an inbound BlueBubbles event)
- Pairing may block replies by default
OpenClaw defaults todmPolicy: "pairing"for BlueBubbles, so the first message from you may generate a pairing code. You’ll need to approve it (openclaw pairing list bluebubbles/openclaw pairing approve ...) or switch policy/allowlist.
If you tell me whether OpenClaw is running via Docker on ZimaOS (and what the container name is), I can tell you the exact docker logs ... | grep bluebubbles command to confirm the webhook is arriving.
it comes up not found for the nrock webhook
If you’re getting “not found” on the ngrok webhook, that’s a different failure than the LAN test:
- LAN URL gave “Method Not Allowed” → that proves OpenClaw is reachable at
192.168.1.44:18789and the route exists. - ngrok “not found” almost always means your ngrok URL is not pointing at the OpenClaw gateway (or it’s an old/stale ngrok URL).
Easiest: don’t use ngrok (since you’re on the same LAN)
In BlueBubbles, keep the webhook as:
http://192.168.1.44:18789/bluebubbles-webhook?password=...
If you do want ngrok
Make sure ngrok is tunneling to the ZimaOS gateway port, not BlueBubbles:
ngrok must forward to: http://192.168.1.44:18789
Then BlueBubbles webhook should be:
https://<your-ngrok-domain>/bluebubbles-webhook?password=...
Can you paste the exact ngrok “Forwarding” line (the one that shows https://... -> http://...), and the exact webhook URL you entered into BlueBubbles? That’ll tell us immediately what’s mismatched.
That ngrok line explains the whole thing:
https://...ngrok-free.dev -> http://localhost:1234
Because ngrok is running on your Mac, localhost:1234 means “the Mac” — so you’re tunneling BlueBubbles, not OpenClaw. When BlueBubbles hits https://…/bluebubbles-webhook, it gets forwarded to the Mac:1234, which (correctly) returns Not Found because BlueBubbles doesn’t have /bluebubbles-webhook.
What you want is: ngrok → ZimaOS OpenClaw gateway (192.168.1.44:18789).
Fix (pick one)
Option A (recommended): don’t use ngrok at all (LAN works)
Webhook in BlueBubbles:
http://192.168.1.44:18789/bluebubbles-webhook?password=...
Option B: use ngrok, but tunnel to OpenClaw
Run ngrok so it forwards to:
http://192.168.1.44:18789
So the forwarding line should look like:
https://<something>.ngrok-free.dev -> http://192.168.1.44:18789
Then set BlueBubbles webhook to:
https://<something>.ngrok-free.dev/bluebubbles-webhook?password=...
One more quick check: earlier you said BlueBubbles API is localhost:12345, but ngrok shows localhost:1234 — which port is BlueBubbles actually using on the Mac? (OpenClaw’s channels.bluebubbles.serverUrl should be http://192.168.1.117:<BLUEBUBBLES_PORT>.)
Yep — that is the correct webhook shape for LAN:
http://192.168.1.44:18789/bluebubbles-webhook?password=...
Now do these two sanity checks (this is where it usually still goes wrong):
- OpenClaw (on ZimaOS) config
channels.bluebubbles.webhookPathis either unset (defaults to/bluebubbles-webhook) or matches what you’re usingchannels.bluebubbles.passwordmatches thatpassword=...exactlychannels.bluebubbles.serverUrlpoints to the Mac’s BlueBubbles API, e.g.:
http://192.168.1.117:<BLUEBUBBLES_PORT>
- BlueBubbles server port mismatch
Earlier you said12345, but your ngrok line showed1234. Which one is BlueBubbles actually running on? (Whatever it is, OpenClaw’sserverUrlmust use that port.)
After that:
- restart OpenClaw gateway + BlueBubbles Server
- send a real iMessage in — if OpenClaw is still on default
dmPolicy: "pairing", you should see a pairing code and need to approve it.
If you paste your OpenClaw channels.bluebubbles block (redact password), I’ll spot the mismatch immediately.
the openclaw isnt running under localhost:18789
Right — localhost:18789 only works on the machine that’s actually running OpenClaw.
- On your Mac,
localhost:18789= the Mac (so it will not be OpenClaw). - From the Mac → ZimaOS, you must use:
http://192.168.1.44:18789/
If http://192.168.1.44:18789/ doesn’t load from the Mac, then OpenClaw on ZimaOS is likely:
- bound to loopback only (
gateway.bind: "loopback"), or - running in Docker but the port isn’t published to the host.
Fix on ZimaOS/OpenClaw:
- Set
gateway.bind: "lan"and restart the gateway - If Docker: make sure you’ve published the port (host
18789→ container18789)
Once that works, BlueBubbles webhook should be:
http://192.168.1.44:18789/bluebubbles-webhook?password=...
Can you confirm: from the Mac, what happens when you open http://192.168.1.44:18789/ (connects, refused, timeout, etc.)?
it connect
Good — if http://192.168.1.44:18789/ connects from the Mac, then you can (and should) skip ngrok entirely.
Now make sure BlueBubbles is pointing its webhook to that same LAN address:
BlueBubbles webhook URL (on the Mac):
http://192.168.1.44:18789/bluebubbles-webhook?password=<YOUR_BLUEBUBBLES_PASSWORD>
Quick verification from the Mac (optional but super useful):
- If you open that URL in a browser and it says “Method Not Allowed” → that’s expected (browser uses GET; BlueBubbles will POST).
- If it says “Not Found” → your path doesn’t match OpenClaw’s
channels.bluebubbles.webhookPath(default is/bluebubbles-webhook) or the BlueBubbles channel isn’t enabled.
Also double-check OpenClaw can reach the BlueBubbles API:
channels.bluebubbles.serverUrlshould behttp://192.168.1.117:<bluebubbles-port>(whatever port BlueBubbles shows for its API)
If you tell me what BlueBubbles shows as the API port (1234 vs 12345) and what OpenClaw returns when you hit /bluebubbles-webhook (404 vs 405), I can pinpoint the exact mismatch.
so i can send messages from openclaw to bluebubbles but not from imessages on my phone to bluebubbles to openclaw
If OpenClaw → BlueBubbles works, then OpenClaw can reach the BlueBubbles REST API (serverUrl + password are good). The missing leg is incoming events, which is either:
A) The Mac/BlueBubbles isn’t seeing the iMessage at all
Quick check: when you send an iMessage from your phone, does it show up in Messages.app on the Mac?
- No → this is an iMessage/Messages.app sync/login issue (Mac not logged in/unlocked, Messages not signed in, Mac asleep, etc.). BlueBubbles can’t forward messages the Mac never receives.
- Yes → go to B.
B) BlueBubbles sees it, but the webhook to OpenClaw isn’t firing / is rejected
In BlueBubbles Server (Mac) → Webhooks, you should see delivery attempts. Confirm:
- Webhook URL is the LAN one:
http://192.168.1.44:18789/bluebubbles-webhook?password=<same password as OpenClaw channels.bluebubbles.password> - It’s not still pointing at ngrok.
- Check the HTTP status code BlueBubbles reports for the webhook POST.
If you tell me:
- “Does the message appear on the Mac in Messages.app?” (yes/no) and
- What BlueBubbles shows for the webhook delivery status/code (200/401/404/etc)
…I can tell you the exact fix.
1 yes and 2 it shows no error
This is very likely because those messages from your phone are being seen as “from me” (same iMessage account as the Mac), and OpenClaw’s BlueBubbles plugin intentionally ignores fromMe=true messages to prevent infinite loops.
So the flow you’re testing is basically:
- OpenClaw → BlueBubbles → iMessage ✅ (works)
- iPhone (same Apple ID) → iMessage sync to Mac (as fromMe) → BlueBubbles → webhook → OpenClaw ❌ (dropped on purpose)
Quick proof
Have someone else (different number / Apple ID) iMessage that account. If OpenClaw suddenly reacts (often with a pairing code), your setup is correct.
How to “chat with your assistant” yourself
You need the BlueBubbles Mac to be signed into a different iMessage identity than your phone, e.g. a dedicated “bot” Apple ID/email on the Mac (then you iMessage that from your phone).
If you want, tell me: are you using the same Apple ID on the Mac and iPhone for Messages? If yes, I’ll outline the cleanest “dedicated bot Apple ID” setup.
they are diffrent apple ids
so its iphone (diffrent apple id) -> i message sync to mac (diffrent apple id) -> bluebubbles-> webhook-> openclaw
?
hello? you still there @latent bramble
Yep, still here.
Main point: if your iPhone + the Mac are on the same iMessage account, messages you send will arrive on the Mac as fromMe, and OpenClaw ignores fromMe BlueBubbles events (to avoid reply loops). That matches exactly what you’re seeing: OpenClaw → BlueBubbles works, but your own phone → OpenClaw doesn’t.
Try this to confirm:
- Have a friend / another number iMessage the Mac account. If OpenClaw responds (maybe with a pairing code), your webhook is fine.
Tell me: are the Mac and your iPhone signed into the same Apple ID for iMessage?
the mac and iphone and signed into diffrent apple id for imessages
Got it — if the Mac + iPhone are on different iMessage Apple IDs, then the “fromMe messages are ignored” thing is probably not the issue.
At this point we need to answer one question: is OpenClaw actually receiving the webhook POSTs or not?
1) Check if OpenClaw is receiving anything (fastest signal)
On the ZimaOS box (where OpenClaw runs), tail the logs while you send a test iMessage from your phone:
- Docker:
docker logs -f <openclaw-container-name> | grep -i bluebubbles
You’re looking for lines like:
webhook received ...webhook accepted ...- or
webhook rejected: unauthorized ... - or
Blocked ... (dmPolicy=...)
If you see nothing at all when you send an iMessage, then BlueBubbles isn’t POSTing to OpenClaw (wrong webhook config / webhooks disabled / wrong event type).
2) Force-test the webhook endpoint (from the Mac)
Run this from the Mac (replace the password):
curl -i -X POST "http://192.168.1.44:18789/bluebubbles-webhook?password=YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-d '{"type":"new-message","message":{"text":"webhook test","handle":{"address":"test@example.com"},"guid":"test-guid","isFromMe":false}}'
- If that returns
200 okand OpenClaw logs show it, the OpenClaw webhook handler is fine. - If it returns
401 unauthorized, the webhook password doesn’t matchchannels.bluebubbles.password.
3) If OpenClaw is receiving webhooks but not replying
Then it’s usually pairing/allowlist. After you send an iMessage, run:
openclaw pairing list bluebubbles
If you paste the first couple BlueBubbles-related log lines you see when you send a message (or tell me “no logs at all”), I’ll tell you exactly which branch you’re on. Docs ref: https://docs.openclaw.ai/channels/bluebubbles
i dont think the openclaw is allowing the webhook to come through
If the webhook URL in a browser gives “Method Not Allowed”, that only proves the route exists — it does not prove the webhook is allowed/auth’d (auth is only checked on POST).
OpenClaw “allows” a BlueBubbles webhook only if:
- it hits the right path (
/bluebubbles-webhook) - it’s a POST
- and the
password=(orguid=) matcheschannels.bluebubbles.password(same password you set in BlueBubbles API settings)
Fastest way to confirm whether OpenClaw is blocking it (run on the Mac)
Replace REAL_PASSWORD with the actual one:
curl -i -X POST "http://192.168.1.44:18789/bluebubbles-webhook?password=REAL_PASSWORD" \
-H "Content-Type: application/json" \
-d '{"type":"new-message","message":{"text":"webhook test","handle":{"address":"test@example.com"},"guid":"test-guid","isFromMe":false}}'
What you should see:
200 OK→ OpenClaw is accepting webhooks. Then BlueBubbles isn’t sending them (or is sending a different payload/type), and we should look at BlueBubbles’s webhook “last delivery” / logs.401 unauthorized→ the password in the webhook URL does not match what OpenClaw has inchannels.bluebubbles.password.
If you paste the HTTP/… status line you get from that curl, we can immediately pick the next step.
openclaw-gateway | 2026-02-11T21:00:56.598Z Failed to discover Ollama models: TypeError: fetch failed
thats the error i get
this is the error i get openclaw-gateway | 2026-02-11T21:00:56.598Z Failed to discover Ollama models: TypeError: fetch failed @latent bramble
That log line is about Ollama model auto-discovery, not BlueBubbles:
Failed to discover Ollama models: TypeError: fetch failed
OpenClaw tries to talk to Ollama at the default URL (http://127.0.0.1:11434/...). On ZimaOS/Docker, 127.0.0.1 is usually inside the container, so it’ll fail unless Ollama is running in that same container (it isn’t).
Fix options
A) If you’re NOT trying to use Ollama: disable it
- Remove/unset
OLLAMA_API_KEY(often the thing that “opts in” to discovery), and/or removemodels.providers.ollamafrom your OpenClaw config / container env. - Restart OpenClaw.
B) If you ARE trying to use Ollama: point OpenClaw at the real Ollama host
- Wherever Ollama is running, make sure you can reach it from the OpenClaw container, then set:
models.providers.ollama.baseUrl: "http://<OLLAMA_IP>:11434/v1"- If Ollama is on the same ZimaOS host, you can often use:
http://192.168.1.44:11434/v1(only works if Ollama is listening on LAN, not just localhost)
Docs: https://docs.openclaw.ai/providers/ollama
Two quick questions so I can give you the exact config snippet for ZimaOS:
- Are you actually trying to run OpenClaw on Ollama (local models), or was that accidental?
- What does
openclaw --versionshow on the ZimaOS box?
yes and its 2026.2.9
That error means: the OpenClaw Gateway can’t reach Ollama at http://127.0.0.1:11434 from where it’s running.
On ZimaOS this is almost always because OpenClaw is running in Docker and 127.0.0.1 inside the container ≠ the host.
Quick check (tells us exactly what’s wrong)
Run these and paste results:
- On the ZimaOS host:
curl -sS -m 2 http://127.0.0.1:11434/api/tags || echo FAIL
- Inside the OpenClaw container (guessing it’s named
openclaw-gateway):
docker exec -it openclaw-gateway sh -lc 'curl -sS -m 2 http://127.0.0.1:11434/api/tags || echo FAIL'
Most common fix (if #1 works but #2 fails)
Run OpenClaw with host networking, so it can hit the host’s 127.0.0.1:11434:
- docker-compose:
services:
openclaw-gateway:
network_mode: "host"
…and make sure you’ve opted into discovery with:
OLLAMA_API_KEY=ollama-local(any value is fine)
Then restart the container.
its set to bridge and its locally so thats not the ip for the ollama container
@latent bramble you dont like replying to me much anymore
{
"id": "gpt-oss:20b-cloud",
"name": "gtp-oss:20b(cloud)",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 32048,
"maxTokens": 81920
That JSON blob is just the model definition (totally fine), but it won’t fix the root problem: the Gateway can’t reach Ollama, so discovery fails with fetch failed.
To actually use that model via Ollama, you need both:
- Ollama reachable from the OpenClaw container
- From inside the OpenClaw container, this must work:
curl -sS -m 2 http://<OLLAMA_HOST>:11434/api/tags
If Ollama is running on the ZimaOS host, <OLLAMA_HOST> is not 127.0.0.1 (that’s inside the container).
Common working choices on Linux/Docker:
http://192.168.1.44:11434(if Ollama listens on LAN)- or
http://host.docker.internal:11434(if you addhost-gateway)
- OpenClaw pointing at that Ollama baseUrl
Inopenclaw.json:
{
models: {
providers: {
ollama: {
baseUrl: "http://<OLLAMA_HOST>:11434/v1",
apiKey: "ollama-local", // any value ok
api: "openai-completions",
// models: [...] // optional; if you set this, discovery is skipped
}
}
},
agents: {
defaults: { model: { primary: "ollama/gpt-oss:20b-cloud" } }
}
}