“The era of asking AI ‘how to do things’ is over. From now on, it’s the era of having AI ‘do things for you.'”
Have you heard of “OpenClaw (formerly Clawdbot),” the OSS project that’s been getting a ton of attention on GitHub? There have been so many name changes that I decided to do a fresh install from scratch.
In simple terms, think of it as “a brilliant butler living inside your PC.” Just talk to it through Slack or Discord, and it’ll autonomously handle all sorts of tasks for you — manipulating files on your PC, managing servers, gathering information from the web, you name it.
The biggest selling point? It runs locally, not as a cloud service. Your data stays in your hands while you build a collaborative environment with a trustworthy AI partner.
In this article, I’ll walk you through how to install OpenClaw. We’ll be installing on Ubuntu 25.04, specifically on a remote PC accessed via SSH.
Prerequisites
- OS: Ubuntu 25.04 (remote PC via SSH)
- Node.js: v24.x
- Authentication: Claude Code setup-token (no API key required)
Goal
Get to a state where you can chat with Claude Opus 4.6 using openclaw tui.
Article Outline
- Phase 1: Installation and Build — clone → pnpm → build
- Phase 2: Starting Onboarding — Security check → QuickStart → clawdbot → openclaw migration
- Phase 3: Onboarding Configuration — Model/Auth/Channel/Skills selection
- Phase 4: The Battle Against Token Mismatch — token mismatch → port conflict → farewell clawdbot-gateway
- Phase 5: Resolution the Next Morning — A reboot fixes things, landmines defused
- Phase 6: CLI Setup and Auth Configuration — npm install -g → openclaw configure → setup-token
- Phase 7: Verification and Final Touches — ui:build → successful conversation via tui
Phase 1: Installation and Build
Let’s start by checking your Node version.
node -v
npm -v
Here’s what I got — and about that npm warning (spoiler: you can ignore it for now):
node -v npm -v v24.13.0 npm warn Unknown project config "allow-build-scripts". This will stop working in the next major version of npm. 11.6.2
The npm warn Unknown project config "allow-build-scripts"... means:
- There’s an
allow-build-scriptsentry in your project or personal .npmrc - But npm 11.x is basically saying “I have no idea what that setting is”
…and that’s it. It’s almost never fatal at this point.
If you want to fix it (optional):
# Check where it's defined
npm config get userconfig
npm config get globalconfig
# Look for it in the project root
ls -la .npmrc
# If it's in .npmrc, delete or comment out the relevant line
Now for the main event — clone from the official repo and move into the created directory.
openclaw/openclaw: Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞
git clone https://github.com/openclaw/openclaw.git
cd openclaw
Next, we need to set up “pnpm,” the package management tool required to run OpenClaw’s code (i.e., install it).
corepack enable
pnpm -v || corepack prepare pnpm@latest --activate
pnpm -v
Here’s the result — pnpm 10.23.0 is installed, so we should be good to proceed straight through dependencies → UI → build → onboard.
mamu@evo-x2:~/openclaw$ corepack enable mamu@evo-x2:~/openclaw$ pnpm -v || corepack prepare pnpm@latest --activate ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-10.23.0.tgz ? Do you want to continue? \[Y/n\] y
10.23.0 mamu@evo-x2:~/openclaw$ pnpm -v 10.23.0
Now that we’ve got our tool (pnpm) ready from the previous step, it’s time to move on to “assembling (building) the OpenClaw application itself.”
If we compare it to cooking: “buy the ingredients (install), prep the plating (ui:build), and finish the dish (build).”
pnpm install
pnpm ui:build
pnpm build
Here are the results. pnpm install → ui:build → build all succeeded. Far from “blindly running commands and hoping for the best” — the logs actually look remarkably clean.
mamu@evo-x2:~/openclaw$ pnpm install pnpm ui:build pnpm build Scope: all 34 workspace projects Lockfile is up to date, resolution step is skipped Packages: +1004 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
╭───────────────────────────────────────────────────╮ │ │ │ Update available! 10.23.0 → 10.28.2. │ │ Changelog: https://pnpm.io/v/10.28.2 │ │ To update, run: corepack use pnpm@10.28.2 │ │ │ ╰───────────────────────────────────────────────────╯
WARN Tarball download average speed 16 KiB/s (size 31 KiB) is below 50 KiB/s: https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz (GET)edb-linux-x64-musl@0.23.0: 28.44 MB/48.03 MB Packages are hard linked from the content-addressable store to the virtual store. Content-addressable store is at: /home/mamu/.local/share/pnpm/store/v10 Virtual store is at: node\_modules/.pnpm Downloading @lancedb/lancedb-linux-x64-musl@0.23.0: 48.03 MB/48.03 MB, done Downloading @wasm-audio-decoders/opus-ml@0.0.2: 6.39 MB/6.39 MB, done Downloading @img/sharp-libvips-linux-x64@1.2.4: 7.53 MB/7.53 MB, done Downloading @img/sharp-libvips-linuxmusl-x64@1.2.4: 7.65 MB/7.65 MB, done Downloading @rolldown/binding-linux-x64-musl@1.0.0-rc.3: 8.26 MB/8.26 MB, done Downloading @napi-rs/canvas-linux-x64-gnu@0.1.90: 13.91 MB/13.91 MB, done Downloading pdfjs-dist@5.4.624: 9.97 MB/9.97 MB, done Downloading @lancedb/lancedb-linux-x64-gnu@0.23.0: 47.87 MB/47.87 MB, done Downloading @rolldown/binding-linux-x64-gnu@1.0.0-rc.3: 8.30 MB/8.30 MB, done Downloading node-llama-cpp@3.15.1: 28.13 MB/28.13 MB, done Downloading @typescript/native-preview-linux-x64@7.0.0-dev.20260205.1: 8.33 MB/8.33 MB, done Downloading @node-llama-cpp/linux-x64@3.15.1: 7.16 MB/7.16 MB, done Downloading ogg-opus-decoder@1.7.3: 6.87 MB/6.87 MB, done Downloading @napi-rs/canvas-linux-x64-musl@0.1.90: 13.30 MB/13.30 MB, done Downloading @oxlint/linux-x64-gnu@1.43.0: 5.25 MB/5.25 MB, done Downloading @node-llama-cpp/linux-x64-vulkan@3.15.1: 23.80 MB/23.80 MB, done Downloading @napi-rs/canvas-linux-x64-gnu@0.1.89: 13.88 MB/13.88 MB, done Downloading @oxlint-tsgolint/linux-x64@0.11.4: 11.62 MB/11.62 MB, done Downloading @napi-rs/canvas-linux-x64-musl@0.1.89: 13.28 MB/13.28 MB, done Downloading @node-llama-cpp/linux-x64-cuda@3.15.1: 121.76 MB/121.76 MB, done Downloading @node-llama-cpp/linux-x64-cuda-ext@3.15.1: 195.17 MB/195.17 MB, done Progress: resolved 1004, reused 0, downloaded 1003, added 1004, done node\_modules/.pnpm/protobufjs@7.5.4/node\_modules/protobufjs: Running postinstall script, done in 91ms node\_modules/.pnpm/node-llama-cpp@3.15.1\_typescript@5.9.3/node\_modules/node-llama-cpp: Running postinstall script... node\_modules/.pnpm/node-llama-cpp@3.15.1\_typescript@5.9.3/node\_modules/node-llama-cpp: Running postinstall script, done in 366msodules/.pnpm/protobufjs@6.8.8/node\_modules/protobufjs: Running postinstall script, done in 112ms node\_modules/.pnpm/esbuild@0.27.3/node\_modules/esbuild: Running postinstall script, done in 111ms node\_modules/.pnpm/protobufjs@8.0.0/node\_modules/protobufjs: Running postinstall script... node\_modules/.pnpm/protobufjs@8.0.0/node\_modules/protobufjs: Running postinstall script, done in 74mspto-nodejs: Running p node\_modules/.pnpm/@matrix-org+matrix-sdk-crypto-nodejs@0.4.0/node\_modules/@matrix-org/matrix-sdk-crypto-nodejs: Running postinstall script, done in 1s node\_modules/.pnpm/@whiskeysockets+baileys@7.0.0-rc.9\_audio-decode@2.2.3\_sharp@0.34.5/node\_modules/@whiskeysockets/baileysnode\_modules/.pnpm/@whiskeysockets+baileys@7.0.0-rc.9\_audio-decode@2.2.3\_sharp@0.34.5/node\_modules/@whiskeysockets/baileys: Running preinstall script, done in 54ms
dependencies: + @agentclientprotocol/sdk 0.14.1 + @aws-sdk/client-bedrock 3.984.0 + @buape/carbon 0.14.0 + @clack/prompts 1.0.0 + @grammyjs/runner 2.0.3 + @grammyjs/transformer-throttler 1.2.1 + @homebridge/ciao 1.3.4 + @larksuiteoapi/node-sdk 1.58.0 + @line/bot-sdk 10.6.0 + @lydell/node-pty 1.2.0-beta.3 + @mariozechner/pi-agent-core 0.52.6 + @mariozechner/pi-ai 0.52.6 + @mariozechner/pi-coding-agent 0.52.6 + @mariozechner/pi-tui 0.52.6 + @mozilla/readability 0.6.0 + @napi-rs/canvas 0.1.89 + @sinclair/typebox 0.34.47 + @slack/bolt 4.6.0 + @slack/web-api 7.13.0 + @whiskeysockets/baileys 7.0.0-rc.9 + ajv 8.17.1 + chalk 5.6.2 + chokidar 5.0.0 + cli-highlight 2.1.11 + commander 14.0.3 + croner 10.0.1 + discord-api-types 0.38.38 + dotenv 17.2.4 + express 5.2.1 + file-type 21.3.0 + grammy 1.39.3 + hono 4.11.7 + jiti 2.6.1 + json5 2.2.3 + jszip 3.10.1 + linkedom 0.18.12 + long 5.3.2 + markdown-it 14.1.0 + node-edge-tts 1.2.10 + node-llama-cpp 3.15.1 + osc-progress 0.3.0 + pdfjs-dist 5.4.624 + playwright-core 1.58.1 + proper-lockfile 4.1.2 + qrcode-terminal 0.12.0 + sharp 0.34.5 + signal-utils 0.21.1 + sqlite-vec 0.1.7-alpha.2 + tar 7.5.7 + tslog 4.10.2 + undici 7.20.0 + ws 8.19.0 + yaml 2.8.2 + zod 4.3.6
devDependencies: + @grammyjs/types 3.23.0 + @lit-labs/signals 0.2.0 + @lit/context 1.1.6 + @types/express 5.0.6 + @types/markdown-it 14.1.2 + @types/node 25.2.1 + @types/proper-lockfile 4.1.4 + @types/qrcode-terminal 0.12.2 + @types/ws 8.18.1 + @typescript/native-preview 7.0.0-dev.20260205.1 + @vitest/coverage-v8 4.0.18 + lit 3.3.2 + ollama 0.6.3 + oxfmt 0.28.0 + oxlint 1.43.0 + oxlint-tsgolint 0.11.4 + rolldown 1.0.0-rc.3 + tsdown 0.20.3 + tsx 4.21.0 + typescript 5.9.3 + vitest 4.0.18
╭ Warning ───────────────────────────────────────────────────────────────────────────────────╮ │ │ │ Ignored build scripts: core-js. │ │ Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts. │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯
. prepare$ command -v git >/dev/null 2>&1 && git config core.hooksPath git-hooks || exit 0 └─ Done in 46ms Done in 17.9s using pnpm v10.23.0
> openclaw@2026.2.4 ui:build /home/mamu/openclaw > node scripts/ui.js build
> openclaw-control-ui@ build /home/mamu/openclaw/ui > vite build
vite v7.3.1 building client environment for production... ✓ 127 modules transformed. ../dist/control-ui/index.html 0.69 kB │ gzip: 0.37 kB ../dist/control-ui/assets/index-BoXosYY6.css 80.85 kB │ gzip: 13.95 kB ../dist/control-ui/assets/index-Dm6g1E26.js 538.46 kB │ gzip: 135.21 kB │ map: 1,475.17 kB
(!) Some chunks are larger than 500 kB after minification. Consider: - Using dynamic import() to code-split the application - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. ✓ built in 649ms
> openclaw@2026.2.4 build /home/mamu/openclaw > pnpm canvas:a2ui:bundle && tsdown && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/write-build-info.ts && node --import tsx scripts/write-cli-compat.ts
> openclaw@2026.2.4 canvas:a2ui:bundle /home/mamu/openclaw > bash scripts/bundle-a2ui.sh
✔ Build complete in 3789ms
✔ Build complete in 3769ms
✔ Build complete in 3791ms
[copy-hook-metadata] Copied boot-md/HOOK.md [copy-hook-metadata] Copied command-logger/HOOK.md [copy-hook-metadata] Copied session-memory/HOOK.md [copy-hook-metadata] Copied soul-evil/HOOK.md [copy-hook-metadata] Done
What Those “Warnings” Mean (Just the Key Points)
1) Update available! 10.23.0 → 10.28.2
Just pnpm letting you know there’s an update. Ignore it for now (if it ain’t broke, don’t fix it). If it bothers you, run this later:
corepack use pnpm@10.28.2
pnpm -v
2) Tarball download average speed ... below 50 KiB/s
Just a “that was slow” warning. It didn’t fail, so we’re fine.
3) Ignored build scripts: core-js / pnpm approve-builds
This one’s the most important.
- Recent versions of pnpm tend to block postinstall / build scripts from dependencies by default as a safety measure
- This means the
core-jsscript was skipped - In most cases, ignoring core-js causes no real harm (though depending on the project, it can occasionally cause tests or certain features to break later)
If you want to play it safe, run this once to selectively approve what you need:
pnpm approve-builds
(If core-js shows up, it’s generally safe to approve. But if you’re the cautious type, “approve it only if something breaks” works too.)
Phase 2: Starting Onboarding
The build is done, so next up is onboard → daemon (gateway) startup.
pnpm openclaw onboard --install-daemon
pnpm openclaw gateway status
pnpm openclaw dashboard
🦞 OpenClaw 2026.2.4 (c75275f) — iMessage green bubble energy, but for everyone.
│ ◇ Doctor changes ───────────────────────────────────────────────────────────────────────╮ │ │ │ - State dir: /home/mamu/.clawdbot → /home/mamu/.openclaw (legacy path now symlinked) │ │ │ ├────────────────────────────────────────────────────────────────────────────────────────╯ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ██░▄▄▄░██░▄▄░██░▄▄▄██░▀██░██░▄▄▀██░████░▄▄▀██░███░██ ██░███░██░▀▀░██░▄▄▄██░█░█░██░█████░████░▀▀░██░█░█░██ ██░▀▀▀░██░█████░▀▀▀██░██▄░██░▀▀▄██░▀▀░█░██░██▄▀▄▀▄██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ 🦞 OPENCLAW 🦞 ┌ OpenClaw onboarding │ ◇ Security ──────────────────────────────────────────────────────────────────────────────╮ │ │ │ Security warning — please read. │ │ │ │ OpenClaw is a hobby project and still in beta. Expect sharp edges. │ │ This bot can read files and run actions if tools are enabled. │ │ A bad prompt can trick it into doing unsafe things. │ │ │ │ If you're not comfortable with basic security and access control, don't run OpenClaw. │ │ Ask someone experienced to help before enabling tools or exposing it 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
First things first: hit Yes on this screen
What you’re looking at is a confirmation asking “You understand this is risky, right? You really want to continue?” Unless you select Yes here, the daemon won’t install and the gateway won’t start.
The browser not opening is totally normal — just open it manually
pnpm openclaw dashboard can fail to auto-launch a browser depending on your environment (over SSH / no GUI / xdg-open not configured / Wayland quirks), so just open the URL yourself.
After you’ve gone all the way through onboarding, run this first:
pnpm openclaw gateway status
Check that it says running.
Then, to get the dashboard URL so you can open it yourself:
pnpm openclaw dashboard --print-url
(If --print-url doesn’t exist, the URL should show up in the logs when you run dashboard. If it doesn’t, skip ahead to “Port check” below.)
Check if the daemon was installed (systemd)
Since you used --install-daemon, in most cases a systemd user service will have been created.
systemctl --user status openclaw-gateway.service --no-pager
If it’s not running:
systemctl --user restart openclaw-gateway.service
journalctl --user -u openclaw-gateway.service -n 200 --no-pager
Quickest checklist when the dashboard still won’t show up
1) Check which ports are listening
(The default port for OpenClaw’s dashboard can vary by environment, so start by checking what’s actually LISTENing)
ss -lntp | grep -E 'openclaw|node' | head -n 20
2) Check OpenClaw’s logs
pnpm openclaw gateway logs --tail 200
A word on security (minimum safe operation practices to address the onboarding warning)
As the screen says, just follow these basics and you’ll be on the safe side for now:
- Don’t expose it externally (localhost only, to start)
- Start with tools at minimum / disabled
- If you do integrate with anything, set up an allowlist / mention gating first (don’t let it act on its own)
What to do next (in this order)
- Select Yes on the onboarding screen
- Once it finishes, run:
pnpm openclaw gateway statussystemctl --user status openclaw-gateway.service --no-pager - Display the dashboard URL and open it yourself:
pnpm openclaw dashboard --print-url
At this point, what the logs are showing is that it’s just paused in the middle of onboarding. When you enter yes, you’ll see:
◇ I understand this is powerful and inherently risky. Continue? │ Yes │ ◆ Onboarding mode │ ● QuickStart (Configure details later via openclaw configure.) │ ○ Manual
Wait, do I even need the browser command?
Basically: nope. Because you’re connected over SSH. The browser (dashboard) is just a visual management UI — OpenClaw itself works perfectly fine as long as the CLI and daemon (gateway) are running.
When you would need the browser (dashboard)
- Pairing (QR/auth) or when you want to do initial setup through a GUI
- When you want to visually check the status of channels/connections
- When you want to click around in settings (sometimes easier than CLI)
Put another way, experienced users routinely run things without ever opening the dashboard.
Running browser-free (CLI-only workflow)
At minimum, this is all you need:
pnpm openclaw gateway status
pnpm openclaw doctor
pnpm openclaw security audit --deep
pnpm openclaw logs --tail 200 # if available; otherwise use gateway logs
If the daemon is alive, you’re golden:
systemctl --user status openclaw-gateway.service --no-pager
So what’s the “browser command” even for?
openclaw dashboard is just a convenience feature that:
- Spins up the local URL
- Tries to open a browser using something like
xdg-open
That’s it. In environments where that won’t work (SSH / no GUI), it’ll naturally fail — so don’t worry about it.
Recommended approach for your current situation
First, get the gateway running / do pairing / lock down permissions via CLI. The dashboard is for “whenever you feel like looking at it.”
Here, going with QuickStart is fine. All this screen is asking is “how much initial setup do you want to do right now?”
Which one should you pick?
QuickStart (recommended)
- Fastest path to “just get it running”
- You can fine-tune everything later with
openclaw configure - Gets you to a state where the gateway/daemon is up and you can interact with it locally
Manual (not needed right now)
- For people who want to nail down everything upfront — connections (Slack/Discord/etc.), permissions, tools, storage, models, the works
- Pick this if you want to go hardcore on security design from the start
In our case, the goal is “reinstall and get back up,” so QuickStart is the only sensible choice.
Why the “reinstall” was necessary (the name changed)
As the logs showed:
- The state directory changed from
/home/mamu/.clawdbot→/home/mamu/.openclaw(the old one is rescued via symlink)
In other words, since the project name changed, the daemon and config locations moved too, so onboard is just rebuilding the “startup set under the new regime.”
This might look suspicious, but it’s totally normal. The reason is simple: OpenClaw is very likely doing a thing where it “recreates .clawdbot automatically for backward compatibility with the old path.”
The log message said exactly this:
State dir: /home/mamu/.clawdbot → /home/mamu/.openclaw (legacy path now symlinked)
In other words, the philosophy is “if the old path doesn’t exist, create it anyway and drop a symlink there.”
First, let’s confirm: isn’t that a “symlink” rather than a “directory”?
This one command tells you everything:
ls -la ~/.clawdbot ~/.openclaw
readlink -f ~/.clawdbot 2>/dev/null || true
What you’d expect to see:
~/.openclawis the actual directory~/.clawdbot -> /home/mamu/.openclawis a symlink
If that’s the case, you were right to delete it earlier, and onboarding just “brought it back for compatibility.”
mamu@evo-x2:~/openclaw$ ls -la ~/.clawdbot ~/.openclaw readlink -f ~/.clawdbot 2>/dev/null || true lrwxrwxrwx 1 mamu mamu 20 Feb 6 20:28 /home/mamu/.clawdbot -> /home/mamu/.openclaw
/home/mamu/.openclaw: total 16 drwxrwxr-x 3 mamu mamu 4096 Feb 6 17:29 . drwxr-x--x 28 mamu mamu 4096 Feb 6 20:28 .. drwxrwxr-x 2 mamu mamu 4096 Feb 6 17:29 cron -rw-rw-r-- 1 mamu mamu 49 Feb 6 17:29 update-check.json /home/mamu/.openclaw
See — .clawdbot is not a real directory, it’s a symlink, so even though you deleted it earlier, OpenClaw just recreated it for compatibility.
/home/mamu/.clawdbot -> /home/mamu/.openclaw
So the correct understanding right now is:
- The actual data (state dir) lives in
~/.openclaw ~/.clawdbotis just an “entryway” kept around so old config references still work
Plus, the contents of .openclaw are just cron/ and update-check.json, so it’s still totally clean.
So can I delete it?
Here’s the deal:
- If you’re only using OpenClaw going forward,
.clawdbotshould be unnecessary (it’s just kept for compatibility) - But other tools or old scripts might still reference
.clawdbot, so operationally it’s safer to leave it
If you really want things tidy, check the contents and references first. Bottom line:
- Deleting
.clawdbotis basically fine (OpenClaw itself uses.openclawas the real deal) - But some people might run into trouble the moment it’s gone — specifically, anyone who has something from the old clawdbot era (scripts/services/configs) that references
.clawdbot
People who “migrated like an upgrade” are exactly the ones at risk here.
What if it did come back as a real directory?
For instance, if ~/.clawdbot/ is a normal directory with actual contents inside.
In that case, OpenClaw may have created the directory on first run as part of old-to-new migration, or something else referenced the old path and generated it.
To check:
file ~/.clawdbot
du -sh ~/.clawdbot ~/.openclaw 2>/dev/null
The safest approach (recommended)
- Treat
.openclawas the canonical (real) location - Leave
.clawdbotalone as a compatibility symlink
That’s it. Done.
Phase 3: Onboarding Configuration
Proceeding with QuickStart gets you to…
◇ I understand this is powerful and inherently risky. Continue? │ Yes │ ◇ Onboarding mode │ QuickStart │ ◇ QuickStart ─────────────────────────╮ │ │ │ Gateway port: 18789 │ │ Gateway bind: Loopback (127.0.0.1) │ │ Gateway auth: Token (default) │ │ Tailscale exposure: Off │ │ Direct to chat channels. │ │ │ ├──────────────────────────────────────╯ │ ◆ Model/auth provider │ ● xAI (Grok) (API key) │ ○ OpenAI │ ○ Anthropic │ ○ MiniMax │ ○ Moonshot AI (Kimi K2.5) │ ○ Google │ ○ OpenRouter │ ○ Qwen │ ○ Z.AI (GLM 4.7) │ ○ Copilot │ ○ Vercel AI Gateway │ ○ OpenCode Zen │ ○ Xiaomi │ ○ Synthetic │ ○ Venice AI │ ○ Cloudflare AI Gateway │ ○ Skip for now
The browser command is not required (covered in Phase 2). Just open the URL manually. The Dashboard URL will look like http://127.0.0.1:18789/?token=....
What is “Model/auth provider”? (This is separate from Codex / Claude Code settings)
What you’re choosing here is the “LLM provider” that OpenClaw will query.
- Claude Code and Codex are “separate CLI / dev tools” — they’re a different thing from what OpenClaw auto-uses via this screen.
- What OpenClaw needs to know is “which LLM API (or compatible API) should I send requests to?”
So how do you choose in this situation?
In our environment:
- Codex and Claude Code are installed.
- Qwen is running locally
- But the options on this screen include OpenAI/Anthropic/Qwen/OpenRouter… and more
Pattern A: Get it running ASAP (fastest path)
Select “Skip for now” to finish onboarding → fine-tune later with openclaw configure. This is the safest and most reliable option. Better to confirm it boots up first than to fat-finger an API key and cause problems.
Pattern B: Use a cloud API (pick whichever you have a key for)
- Have a Claude key → Anthropic
- Have an OpenAI key → OpenAI
- Have an OpenRouter key → OpenRouter
Pattern C: Use local Qwen (heads up on this one)
The “Qwen” in this menu most likely refers to Qwen’s cloud service (DashScope / Model Studio etc.), not your local Qwen — it’ll want an API key.
The typical way to feed local Qwen into OpenClaw is:
- Run it via Ollama / vLLM / llama.cpp as an OpenAI-compatible endpoint
- On the OpenClaw side, set it up as OpenAI (compatible) and swap out the
base_url(meaning: selecting “Qwen” on this screen won’t magically point to your local instance)
So if local Qwen is your priority, Skip for now and finish onboarding → configure afterward. Least likely to go wrong.
Next move (recommended steps)
- Keep going with QuickStart (Loopback + Token is exactly right. Not exposing it externally is the way)
- For provider, choose Skip for now (just confirm it starts up first)
- After onboarding finishes, run the following to check the status:
pnpm openclaw gateway statuspnpm openclaw dashboard(if it doesn’t open, manually navigate to the URL it prints)
The “does it recreate clawdbot?” question (conclusion: it’s not really “creating” — it’s “preserving for compatibility”)
As you saw, a symlink ~/.clawdbot -> ~/.openclaw gets created. This is just backward compatibility so old path references don’t break. And yes, “deleting it might cause problems for people who upgraded from the old version” is exactly right.
One last thing: do I have to configure Codex / Claude Code?
You don’t need to set them up on this onboarding screen. Getting the OpenClaw gateway/daemon running normally comes first.
After that:
- Configure “which model to send requests to (API / local compatible)” for OpenClaw
- Then if needed, add “coding skills/integrations (Codex / Claude Code)”
That order minimizes the chance of something going wrong.
After selecting Skip for now…
◇ Model/auth provider │ Skip for now │ ◆ Filter models by provider │ ● All providers │ ○ amazon-bedrock │ ○ anthropic │ ○ azure-openai-responses │ ○ cerebras │ ○ github-copilot │ ○ google │ ○ google-antigravity │ ○ google-gemini-cli │ ○ google-vertex │ ○ groq │ ○ huggingface │ ○ kimi-coding │ ○ minimax │ ○ minimax-cn │ ○ mistral │ ○ openai │ ○ openai-codex │ ○ opencode │ ○ openrouter │ ○ vercel-ai-gateway │ ○ xai │ ○ zai
Even with Skip for now, it still makes you pick a “model list” — that seems to be how it works. This isn’t “enter your key right now” — it’s more like a filter for narrowing down which providers you might use later.
How should you pick here?
Bottom line: just leave it on All providers and move on
The reasoning is simple: you haven’t entered any keys yet, and the goal is to finish QuickStart. You can change the settings later. All providers → next is the fastest and safest.
But if you want to be intentional about it
If you’d rather “not have to think about it later,” picking a provider filter follows the same logic as Pattern A/B/C above. For Codex, openai-codex is closest; for Claude Code, anthropic; for local Qwen, openai (compatible endpoint).
One catch though: qwen isn’t in the list, so local Qwen will have to connect as “OpenAI-compatible” anyway.
So what do we actually do this time?
“I just want to get it running” + “I’ll fine-tune settings later” → Leave it on All providers and proceed. That’s the fastest and safest route. You can change the filter anytime — it’s just updating a config under ~/.openclaw.
After leaving it on All providers and proceeding, the default model selection screen appears:
◇ Filter models by provider │ All providers │ ◆ Default model │ ● Keep current (default: anthropic/claude-opus-4-6) │ ○ Enter model manually │ ○ amazon-bedrock/anthropic.claude-3-haiku-20240307-v1:0 │ ○ amazon-bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 │ ...
What should you pick here?
If “I haven’t entered any keys yet / I just want to get it running,” the optimal choice is:
Keep current (default: anthropic/claude-opus-4-6) and move on
Reasoning: without authentication it won’t be able to call the model anyway, and you can change it later. “Keep current” is the right call when startup is the priority.
That said: let’s head off the things that could trip you up later
See Pattern A/B/C above for choosing your auth route. Here’s just the priority breakdown:
1) You want to use Claude Code (my pick)
- Leaving it on the current anthropic/claude-opus-4-6 is fine (though you’ll need Anthropic auth/routing set up later)
2) You want to use Codex
- You’d go to
Enter model manuallyand point it towardopenai-codex/...(whatever shows up in the list) But since you don’t have a key right now, prioritize getting it running first.
3) You want to use local Qwen
- This list seems to be mostly “cloud provider-centric,” so local Qwen will probably need to be set up as an “OpenAI-compatible API” mapped to
openai/... - Meaning it’s more reliable to configure it afterward by putting base_url / api_key (dummy) / model name in the config file, rather than trying to pick it here
After selecting Keep current (default: anthropic/claude-opus-4-6), the channel selection screen appears:
◇ Default model │ Keep current (default: anthropic/claude-opus-4-6) │ ◇ Model check ───────────────────────────────────────────────────────────────────────────╮ │ │ │ No auth configured for provider "anthropic". The agent may fail until credentials are │ │ added. │ │ │ ├─────────────────────────────────────────────────────────────────────────────────────────╯ │ ◇ Channel status ────────────────────────────╮ │ │ │ Telegram: not configured │ │ WhatsApp: not configured │ │ Discord: not configured │ │ Google Chat: not configured │ │ Slack: not configured │ │ Signal: not configured │ │ iMessage: not configured │ │ ... │ ├─────────────────────────────────────────────╯ │ ◆ Select channel (QuickStart) │ ● Telegram (Bot API) (not configured) │ ○ WhatsApp (QR link) │ ○ Discord (Bot API) │ ... │ ○ Skip for now
What’s happening right now (the gist)
1) Model (Anthropic) authentication is not configured
No auth configured for provider "anthropic"— This is saying “the default is anthropic/claude-opus… but you have no key and no login, so that model can’t actually be called. It’ll probably fail later.”
2) Channels (Telegram/Discord/Slack etc.) are not configured
Right now it’s at the stage of “where should I receive messages from?”
The optimal choice here
“I just want to verify it works” + “SSH” + “don’t want to expose it externally” + “no keys yet” → Skip for now is the answer.
Go with this for now: Select channel (QuickStart) → Skip for now
Reasons:
- You can configure channels later anytime
- If you pick Telegram now, it’ll ask for a BotFather token and you’ll get stuck
- Over SSH, the “dashboard” won’t auto-open anyway, so confirming the daemon/gateway is running should come first
What to do after that (confirming “is it alive?”)
Once you’ve finished onboarding all the way through, verify with pnpm openclaw gateway status / pnpm openclaw doctor just like in Phase 2. The browser isn’t needed for SSH workflows (if you want to see it, use SSH port forwarding — more on that later).
“So when do I set up model authentication?”
After you’ve confirmed it starts up. The order is Skip for now → verify gateway → decide on auth route (Pattern A/B/C as discussed above).
Quick notes on what might trip you up on the current screen
- Telegram: Almost certainly going to ask for a Bot token
- Discord/Slack: Requires app registration (a bit involved)
- Skip for now: The fastest path to “local startup verification”
After selecting Skip for now for the channel, the skills configuration prompt appears:
◇ Select channel (QuickStart) │ Skip for now Updated ~/.clawdbot/openclaw.json Workspace OK: ~/.openclaw/workspace Sessions OK: ~/.openclaw/agents/main/sessions │ ◇ Skills status ────────────╮ │ │ │ Eligible: 6 │ │ Missing requirements: 44 │ │ Blocked by allowlist: 0 │ │ │ ├────────────────────────────╯ │ ◆ Configure skills now? (recommended) │ ● Yes / ○ No
Onboarding has now reached the point where the foundation is in place. Based on what’s on screen, the most important thing right now is “don’t pile on skills (= execution permissions) when you have no keys (auth) or channels configured yet.”
What the current screen means (key points)
- Model check: No auth for
anthropic→ with this setup the default model (Claude Opus) can’t be called, and it’ll likely fail later - Channel: All unconfigured → hasn’t been decided where to receive messages from
- openclaw.json updated: Config has been written to
~/.clawdbot/openclaw.json(the actual file lives under~/.openclaw) - Skills status:
- Eligible: 6 (only 6 skills can be activated in the current environment)
- Missing requirements: 44 (44 skills can’t be used due to missing dependencies/keys/etc.)
What to do here (recommendation)
Go with “No” — safest and fastest path
Configure skills now? → No
Reasons:
- Auth (keys) and channels are still unconfigured
- Skills are an entry point for “reading files, running commands, etc.” → Better to nail down startup verification and auth design first to avoid accidents
What comes next (the winning play for SSH setups)
Once you exit onboarding, verify with pnpm openclaw gateway status / doctor (as described earlier). Choosing your auth route (Pattern A/B/C) comes after that, and skills come even after that. The stable order is auth → channels → skills.
After selecting No, the hooks screen (no hooks available), gateway service runtime, and then the token mismatch error appear:
◇ Configure skills now? (recommended) │ No │ ◇ Hooks ... │ ◇ No Hooks Available ... │ ◇ Gateway service runtime ... │ ◐ Installing Gateway service… Installed systemd service: /home/mamu/.config/systemd/user/openclaw-gateway.service ◇ Gateway service installed. │ gateway connect failed: Error: unauthorized: gateway token mismatch (set gateway.remote.token to match gateway.auth.token) ◇ Health check failed: gateway closed (1008): unauthorized: gateway token mismatch (set gateway.remote.token to match gateway.auth.token) Gateway target: ws://127.0.0.1:18789 Source: local loopback Config: /home/mamu/.openclaw/openclaw.json Bind: loopback
Phase 4: The Battle Against Token Mismatch
The logs say it all:
unauthorized: gateway token mismatch (set gateway.remote.token to match gateway.auth.token)gateway closed (1008): unauthorizedinvalid connect params: at /client/id ...
In other words:
- The token the gateway expects (
gateway.auth.token) - The token the client has (
gateway.remote.token)
These two don’t match. Since the onboard process installed a systemd service (the gateway) partway through, it’s common to end up with a mismatch where “only one side got the new config.”
First things first: make the tokens match in the config file
That said, you can also just pick Yes to continue for now and fix it later. The config file is at the path shown in the logs:
/home/mamu/.openclaw/openclaw.json
First, check what’s in it:
cat ~/.openclaw/openclaw.json | sed -n '1,200p'
Then look for the gateway section (grep works fine):
grep -n '"gateway"' -n ~/.openclaw/openclaw.json
grep -n 'auth' ~/.openclaw/openclaw.json
grep -n 'remote' ~/.openclaw/openclaw.json
grep -n 'token' ~/.openclaw/openclaw.json
What you want to see (conceptually):
gateway.auth.tokenexistsgateway.remote.tokenexists- Both are exactly the same
Fix it by hand (quickest way)
Open it in an editor:
nano ~/.openclaw/openclaw.json
Copy the value of gateway.auth.token and paste it into gateway.remote.token. (If only one of them exists, just set them both to the same value.)
After fixing: restart the gateway service
This is installed as a user systemd service, so use --user:
systemctl --user daemon-reload
systemctl --user restart openclaw-gateway.service
systemctl --user status openclaw-gateway.service --no-pager -l
Check the logs too:
journalctl --user -u openclaw-gateway.service -n 80 --no-pager
Connection check (no browser needed)
Over SSH, this is all you need:
pnpm openclaw gateway status
pnpm openclaw doctor
If you just want to check basic connectivity, try the HTTP side:
curl -I http://127.0.0.1:18789/ | head
About “/client/id must be equal to constant”
This usually shows up alongside connection parameter mismatches (client id / token / handshake). In most cases, it goes away on its own once you fix the tokens and restart.
One last question: bash completion?
Enable bash shell completion for openclaw?
Yes is fine. It’s harmless — it just enables tab completion. (If you’re worried, picking No won’t affect anything either.)
After picking Yes, the onboard completion screen appears:
◇ Enable bash shell completion for openclaw? │ Yes │ ◇ Shell completion ... │ ◇ Dashboard ready ───────────────────────────────────────────────────────╮ │ │ │ Dashboard link: http://127.0.0.1:18789/ │ │ Copy/paste this URL in a browser on this machine to control OpenClaw. │ │ No GUI detected. Open from your computer: │ │ ssh -N -L 18789:127.0.0.1:18789 mamu@192.168.0.108 │ │ Then open: │ │ http://localhost:18789/ │ │ ... │ ├─────────────────────────────────────────────────────────────────────────╯ │ └ Onboarding complete. Use the dashboard link above to control OpenClaw.
This is telling you to open it in a browser — but not a browser on the server. It means open it in a browser on your local machine (since you’re connected via SSH).
What to do right now (shortest path)
Open the dashboard via SSH port forwarding. If you’re using VS Code’s Remote-SSH, port forwarding might already be working automatically. To set up the tunnel manually from PowerShell:
ssh -N -L 18789:127.0.0.1:18789 mamu@192.168.0.108
Then open http://localhost:18789/ in your local browser. You can configure and check things via the CLI without a browser, but honestly, it’s just easier with the browser.
However: that “token mismatch” will kill the dashboard if you ignore it
If the token mismatch from earlier is still there, the UI will just show red errors when you open it. Set up the tunnel first, check in the browser, and if you see “unauthorized,” go fix the tokens.
But then you hit this in the browser:
Control UI assets not found. Build them with
pnpm ui:build(auto-installs UI deps), or runpnpm ui:devduring development.
This simply means the UI (static files) hasn’t been built yet, or the gateway can’t find them where it expects them to be. The logs earlier said “Control UI assets missing; building…” but it either crashed partway through or the build output ended up somewhere unexpected. Hit Ctrl+C to stop the wizard for now.
Root cause found
Gateway failed to start: another gateway instance is already listening on ws://127.0.0.1:18789
...
- pid 2128 mamu: clawdbot-gateway (127.0.0.1:18789)
- Another process is listening on this port.
Same conclusion: port 18789 is being held by “pid 2128 clawdbot-gateway.” OpenClaw isn’t broken — the seat is just already taken.
Fix: evict the old clawdbot-gateway that’s hogging port 18789
1) First, stop whatever’s squatting on the port
The culprit is pid 2128, clawdbot-gateway, which is LISTENing on 18789. Stop the process and confirm the port is freed up.
# Check which PID has 18789 (skip if you already know)
ss -ltnp | grep 18789
# Stop the old gateway
kill 2128
# Confirm it's free
ss -ltnp | grep 18789 || echo "OK: 18789 freed"
If you see OK: 18789 freed, stage one is clear.
2) Important: if it comes back after you kill it, systemd is respawning it
If kill works but the same PID (or a new one) pops back up within seconds, the old clawdbot has a user systemd service set to keep it alive.
Hunt down the clawdbot units
systemctl --user list-units --type=service | grep -Ei 'clawdbot|claw'
systemctl --user list-unit-files | grep -Ei 'clawdbot|claw'
Whatever clawdbot-*.service (or similar) you find, stop + disable it:
# Example: if clawdbot-gateway.service exists
systemctl --user disable --now clawdbot-gateway.service
The disable is essential to prevent it from coming back after a reboot.
3) Start the OpenClaw side
Once the old one is gone and 18789 is free, start OpenClaw.
Starting via systemd (user service)
systemctl --user restart openclaw-gateway
systemctl --user status openclaw-gateway --no-pager
Starting manually to check
/home/mamu/.nvm/versions/node/v24.13.0/bin/node \
/home/mamu/openclaw/dist/index.js gateway --port 18789
Finally, confirm that OpenClaw actually has the port:
ss -ltnp | grep 18789
What you want to see is something like users:(("node",pid=...)) — an OpenClaw process owning the port.
4) For SSH setups, open the dashboard via port forwarding
Use ssh -N -L 18789:127.0.0.1:18789 mamu@192.168.0.108 as described above to set up the tunnel, then open http://localhost:18789/ in your browser.
Quick tips
- OpenClaw did nothing wrong: the startup failure was just “someone else was already sitting in seat 18789”
- kill is a band-aid: the real fix is
systemctl --user disable --now <old-service> - UI build (pnpm ui:build) is harmless: it just generates static files, and it’s a separate issue from what we dealt with here
If you want to keep the old clawdbot (coexistence)
- Run OpenClaw on a different port (e.g., 18889)
- The dashboard URL changes accordingly
# Example: starting OpenClaw on a different port
systemctl --user stop openclaw-gateway
openclaw configure --section gateway # Change the port to 18889 here, or edit the config file directly
systemctl --user restart openclaw-gateway
If you don’t need the old clawdbot anymore (full removal)
- Disable all clawdbot user services
- If needed, note that ~/.clawdbot is a symlink — be careful not to accidentally nuke ~/.openclaw when cleaning up (this is important)
Is a build necessary?
You can build whenever you want — before or after — but the safest order is:
- Resolve the port conflict first (stop/disable clawdbot-gateway)
- Start the OpenClaw gateway and confirm 18789 belongs to OpenClaw
- Then, only if it complains about missing UI, run
pnpm ui:build(only when needed)
Building the UI will absolutely not fix the port conflict. Only run cd ~/openclaw && pnpm ui:build when you see Control UI assets not found. Building early won’t hurt, but it doesn’t touch the root cause at all.
Phase 5: Resolution the Next Morning
When I checked things the next morning, the conclusion was: OpenClaw was running just fine. All those “it won’t start” and “the port is taken” errors from the day before weren’t OpenClaw bugs — it was simply a matter of who had grabbed port 18789 at the time.
Morning check results
1) What’s actually running
A ps check showed that openclaw-gateway was the one running:
ps aux | egrep 'clawdbot|openclaw' | grep -v grep
mamu 2092 0.7 0.3 … openclaw-gateway (plus other related processes)
So OpenClaw itself is the one holding port 18789 now.
2) systemd status (user services)
systemctl --user also shows openclaw-gateway as running:
systemctl --user list-units --type=service --state=running | egrep 'clawdbot|openclaw'
openclaw-gateway.service loaded active running OpenClaw Gateway (v2026.2.4)
Here’s the important part:
systemctl --user list-unit-files | egrep 'clawdbot|openclaw'
clawdbot-gateway.service enabled
openclaw-gateway.service enabled
The clawdbot-gateway service definition is still there (enabled). But the one actually running is openclaw-gateway. In other words, “it’s not actively causing trouble right now,” but the landmine is still there (it could come back and cause a conflict in the future).
Why “manual startup fails” (and why that’s perfectly normal)
Yesterday, clawdbot-gateway was occupying 18789, so OpenClaw couldn’t start and threw errors. But today, after a PC reboot, openclaw-gateway started up first.
If you try this in that state:
node ... dist/index.js gateway --port 18789
Of course, since the gateway is already running, you get:
- Double startup (gateway already running)
- Port in use (Port 18789 is already in use)
And it gets rejected. This is not a problem — it’s working correctly.
In other words, it’s not “can’t start” — it’s “tried to start but was stopped because it’s already running.”
Appendix: Defuse the clawdbot-gateway “landmine” (optional)
Right now openclaw-gateway has the port and everything is fine, but there’s a chance clawdbot could start up again in the future and cause another port conflict. So it might be worth wrapping up like this:
“Everything’s working now. But the clawdbot unit is still enabled, so if you want to prevent future conflicts, disabling it is the safe move.”
systemctl --user disable --now clawdbot-gateway.service
systemctl --user daemon-reload
systemctl --user reset-failed
Wrap-up
Only run pnpm ui:build if you get the UI assets error. After a reboot the next morning, everything was working. Yesterday, clawdbot-gateway was holding port 18789. Today, openclaw-gateway was already running, and the manual startup attempt was just rejected as a “double startup” — nothing more.
What to check next (this is the finish line)
Just do the following and you’re good.
Can you open the dashboard?
Open http://localhost:18789/ via the SSH port forward described above.
What if you get another UI error?
If you see Control UI assets not found, run pnpm ui:build and restart the gateway (see Phase 4). The screen loads, but the Web UI can’t authenticate against the gateway’s WebSocket. The red error in the screenshot is the key:
unauthorized: gateway token missing (Open the dashboard URL and paste the token in Control UI settings)
This means the token is either missing or wrong, so Health stays stuck on Offline.
Phase 6: CLI Setup and Auth Configuration
The bottom line: all you need to do is “paste the Gateway token into the UI”
OpenClaw uses Token authentication by default. That token should be in ~/.openclaw/openclaw.json on the server side.
1) Check the token on the server side (via SSH)
cat ~/.openclaw/openclaw.json | sed -n 's/.*"token": *"\([^"]*\)".*/\1/p'
If you have jq installed, this is the safer option:
jq -r '.gateway.auth.token' ~/.openclaw/openclaw.json
For more on jq, check out this article:

The string you get here is the token you need to paste into the Control UI.
2) On the browser side
- Paste it into the Gateway Token field
- Click Connect — if the red
token missingmessage disappears, you’re good.
If it still doesn’t work after pasting (common pitfalls)
A) “token missing” turns into “token invalid / unauthorized”
This likely means you’re looking at the wrong token (maybe from a different process or config file). To check:
systemctl --user status openclaw-gateway --no-pager -l
cat ~/.openclaw/openclaw.json | head
B) There’s no token in the file at all
Do what the red box in the UI tells you — generate one and paste it in. The command shown in that red box is: openclaw doctor --generate-gateway-token. If you’re running things through pnpm:
pnpm openclaw doctor --generate-gateway-token
Paste the generated token into the UI and hit Connect.
What about “Password (not stored)”?
Since we’re using Token auth, you basically don’t need it. Leave it blank unless you’ve explicitly switched to password-based authentication.
What “Password (not stored)” actually is
This is an alternative authentication route for connecting from the Control UI (browser) to the Gateway. Depending on the setup, some environments use a “shared password” approach — that’s all it is.
- Token (gateway token) method — This is what we’re using now. Enter the Gateway Token in the Control UI and you’re connected. Leave the Password field empty.
- If you’ve switched to password mode (explicitly configured) — The system will ask for a Password instead of a Token. Only then do you use this field.
And as the UI says with (not stored), the password isn’t saved on the browser side, so you’ll likely get prompted for it every time. That’s why tokens are just easier.
Best practice for this setup
- Gateway runs as a daemon via systemd (openclaw-gateway.service)
- Control UI only needs the Gateway Token
- Don’t touch the Password field (leave it blank)
If you see Health OK / Connected, you’re done.
Up to this point, the Gateway itself was running fine, but I was confused because I couldn’t run openclaw in the terminal. The reason was dead simple — the Gateway was started via systemd, but I hadn’t actually installed the CLI (openclaw command) yet. The fix is to run npm install -g . (install from the repo) to enable the openclaw command, then connect with openclaw tui. If you have token auth enabled, connect explicitly like this: openclaw tui --url ws://127.0.0.1:18789 --token <token>.
A) Install the current repo (~/openclaw) globally “as-is” as the CLI (recommended)
This approach takes what you’ve already built and turns it into the openclaw command.
cd ~/openclaw
npm install -g .
hash -r
command -v openclaw
openclaw --version
mamu@evo-x2:~/openclaw$ npm install -g .
added 1 package in 245ms
mamu@evo-x2:~/openclaw$ hash -r
mamu@evo-x2:~/openclaw$ command -v openclaw
/home/mamu/.nvm/versions/node/v24.13.0/bin/openclaw
mamu@evo-x2:~/openclaw$ openclaw --version
2026.2.4
B) Install the published openclaw package from npm
The “just install the distributed version” approach.
npm install -g openclaw
hash -r
command -v openclaw
openclaw --version
If
command -v openclawshows a path, you win. (The macOS instructions also assume you install vianpm install -g openclaw@..., so philosophically, this is the “proper” way.)
First things first: a quick sanity check (recommended)
1) Make sure it’s alive
openclaw --help
If you get a list of subcommands, that’s proof the CLI is installed correctly.
2) Can it connect to the Gateway? (this is the big one)
openclaw tui
At this point, the situation is basically “the Gateway (the vessel) is running, but the ‘brain’ (the model) has no auth configured, so the TUI is stuck waiting for a response.” In fact, during onboarding, you probably saw this:
No auth configured for provider "anthropic". The agent may fail until credentials are added.— That’s exactly what’s showing up as “pondering…” in the TUI.
And per OpenClaw’s wizard spec, Anthropic supports not just API keys but also “Claude Code OAuth” and “paste a setup-token” as auth methods.
Bottom line: success? The Gateway is good. The LLM is not there yet.
Here’s where things stand:
openclaw-gateway.service: active (running)- Then
token_missingturned intowebchat connected(because we pasted the token)
So the Gateway setup is a success. However, Anthropic auth (to actually use Claude as the LLM) is a separate matter entirely, and that part isn’t done yet.
Why the TUI isn’t responding right now
You typed something like:
“Tell me the name of the model you’re currently using”
into the TUI, and it’s been “pondering” for 2-3 minutes. That’s usually one of these:
- No Anthropic auth configured (most likely)
- The default model is still set to Anthropic, but there’s no auth for it
- Model resolution failed entirely (stuck on “unknown”)
The wizard spec even mentions “show a ‘missing auth’ warning during model check” — that’s just what’s happening in real life.
So how do we fix it? (fastest terminal route)
The goal here is “I want to use Auth (Claude Code’s authentication) instead of an API key,” so here’s what you need to do.
A) Reuse Claude Code’s OAuth credentials (recommended)
According to the wizard, on Linux/Windows, OpenClaw can reuse ~/.claude/.credentials.json.
So:
- Make sure Claude Code is already logged in on this machine
- Then configure OpenClaw to use Anthropic OAuth
The exact command varies by environment, so the safest bet is to use OpenClaw’s built-in flow:
openclaw configure(interactive — lets you configure Models/Auth settings)- If you can specify a section:
openclaw configure --section models/--section auth
This “configure” entry point officially exists, as shown on the onboarding screen (“you can change this later with openclaw configure“).
B) The setup-token method (reliable even over SSH)
This is the approach described in the wizard spec:
- Run
claude setup-tokenin some terminal - Paste the token that appears (name can be left blank)
This creates a route where Anthropic works without an API key.
Running openclaw configure:
◇ Existing config detected ─────────╮ │ │ workspace: ~/.openclaw/workspace │ │ gateway.mode: local │ │ gateway.port: 18789 │ │ gateway.bind: loopback │ ├────────────────────────────────────╯ │ ◆ Where will the Gateway run? │ ● Local (this machine) (Gateway reachable (ws://127.0.0.1:18789)) │ ○ Remote (info-only)
This screen means you’re successfully into the configuration UI — both the CLI and Gateway are visible. Gateway reachable (ws://127.0.0.1:18789) appearing confirms connectivity.
Pick Local and hit Enter (Remote is only for “connecting to a Gateway on a different host”).
Select Model section, then Anthropic, then Anthropic token (paste setup-token):
◇ Anthropic auth method │ ● Anthropic token (paste setup-token) (run `claude setup-token` elsewhere, then paste the token here) │ ○ Anthropic API key │ ○ Back
This is exactly the “use Auth instead of an API key” route.
Here’s what to do
- In a separate terminal (or on your local PC):
claude setup-token
- Copy the generated setup-token
- Paste it into the current screen at Anthropic token (paste setup-token) and proceed
Where do you run claude setup-token?
- Over SSH is fine (as long as the
claudecommand is installed on the SSH target) - If the SSH target doesn’t have
claude/ isn’t logged in:- Run
claude setup-tokenon your local machine (Windows side) → just paste the token into OpenClaw on the SSH side — that works too
- Run
Do you need ANTHROPIC_API_KEY for this?
Nope. (You’d only need it if you selected “Anthropic API key”)
OpenClaw can use Anthropic via an API key, but in this case we just pasted a Claude Code setup-token and it worked for authentication.
In this case, the setup-token was generated on Windows PowerShell, which triggered browser authentication, and the token appeared in PowerShell.
◇ Paste Anthropic setup-token │ sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │ ◆ Token name (blank = default) │ default
The Token name (blank = default) is just a “label” for saving the token on the OpenClaw side.
- If in doubt, just press Enter with it blank (= uses “default”)
- If you want to manage multiple tokens (work/personal/testing), give it a recognizable name like
anthropic-winorclaude-code
Either way, it has virtually no impact on functionality (it’s just a management label for “which token to reference”).
Then select anthropic/claude-opus-4-6 from the model list and complete the configuration:
◇ Anthropic OAuth models │ anthropic/claude-opus-4-6 Updated ~/.openclaw/openclaw.json │ ◆ Select sections to configure │ ○ Continue
Select Continue to finish the configuration wizard:
◇ Select sections to configure │ Continue Missing Control UI assets. Build them with `pnpm ui:build` (auto-installs UI deps). │ ◇ Control UI ────────────────────────────────────╮ │ │ Web UI: http://127.0.0.1:18789/ │ │ Gateway WS: ws://127.0.0.1:18789 │ │ Gateway: reachable │ ├─────────────────────────────────────────────────╯ │ └ Configure complete.
Setup complete! The “Missing Control UI assets” message is an error from the UI perspective (the browser can’t display anything), but it simply means the Control UI static files (dist/control-ui) haven’t been built yet.
So the bottom line:
- If you see this message in the browser →
pnpm ui:buildis required - If you’ve already run
pnpm ui:buildand still see it → the build output is in the wrong location / the gateway is looking at an old path / the artifacts got deleted
Phase 7: Verification and Final Touches
The shortest path to “done” (this covers 90% of it)
cd ~/openclaw
pnpm ui:build
systemctl --user restart openclaw-gateway
Then do a hard reload (cached assets love to stick around):
- On a Windows browser:
Ctrl + F5(orCtrl+Shift+R)
If you still see “Missing assets” (you can diagnose this in 1 minute)
1) Are the build artifacts actually there?
ls -la ~/openclaw/dist/control-ui/ | head
If you see index.html and assets/, the build output is fine.
2) Is the Gateway actually looking at those artifacts? (check the logs)
journalctl --user -u openclaw-gateway -n 80 -o cat --no-pager
If Control UI assets not found still shows up here, the reference path is probably wrong.
Why does “it might not actually be an error” even come up?
The openclaw configure CLI message “Missing Control UI assets …” is sometimes shown as a warning meaning “the UI is optional — the Gateway itself works fine without it.” But in our case, the browser shows nothing but that message = it’s fatal from a UI perspective, so from a user experience standpoint, it’s absolutely an error.
Even if the Gateway itself is running, the Control UI is a separate thing. If the UI’s static files haven’t been built, the browser stops at “Missing assets.” Fix:
pnpm ui:buildthen restart the Gateway.
Next up: “admin-ish” management commands
OpenClaw is split into the “Gateway (always running)” and the “CLI/TUI (the operator’s interface).” Let’s start by proving that things are actually running behind the scenes.
3) Gateway status (as seen from the CLI side)
openclaw gateway status
4) Clean up duplicate processes or anything weird
openclaw gateway stop
Important: if you see “assets not found” in the Control UI
As mentioned above, pnpm ui:build followed by a Gateway restart fixes it. If you’ve already built, no need to do it again. “If the UI opens, you win.”
Ready to configure things? (next steps)
5) Walk through the interactive configuration (model/auth/web search, etc.)
openclaw configure
This is where we set up Anthropic using the “setup-token (Auth method)”. The key point here is that instead of pasting an API key directly, you go through browser auth and paste a token. (The flow: run claude setup-token in Windows PowerShell, authenticate in the browser, get a token, paste it on the Linux side.)
Want to peek at the config file?
6) Check your current configuration on the spot
cat ~/.openclaw/openclaw.json
If anthropic/claude-opus-4-6 appears in there, the “Claude is the brain” setup is complete.
Recommended order (when in doubt, follow this)
openclaw tui(the main event: can you actually have a conversation?)openclaw gateway status(proof that things are running in the background)openclaw configure(laying groundwork for later: model/auth/tools)cat ~/.openclaw/openclaw.json(see the actual config)
Missing Control UI assets... isn’t “config failure” — it just means “the UI hasn’t been built yet” (see Phase 4).
Now let’s retry the quick verification that failed earlier:
openclaw tui
Once the TUI launches, type:
Tell me the name of the model you’re currently using
And you should get back:
I’m using anthropic/claude-opus-4-6.
If the status bar at the bottom also shows anthropic/claude-opus-4-6, that’s proof that the entire chain — OpenClaw, Gateway, and Claude (Auth) — is fully connected.
What to do next (recommended order)
openclaw gateway status— Proof that the Gateway is running in the backgroundcat ~/.openclaw/openclaw.json— Show the actual config- The Control UI assets warning doesn’t matter if the TUI works. Only run
pnpm ui:buildand restart the Gateway if you want a nicer browser-side UI experience.
Does token consumption change?
The short answer: it’s basically Claude that eats the tokens. OpenClaw itself doesn’t magically increase token usage — it depends on what and how much you send to Claude. That said, having OpenClaw in the middle does introduce factors that can push consumption up or down.
Patterns that increase usage (often caused by OpenClaw)
- Keeping long session histories and sending them all at once every time
- Feeding raw tool output (long logs/JSON/HTML) straight to the LLM
- Using heavy “thinking mode/reasoning” models where internal reasoning runs deep
- Stacking “system instructions + skill descriptions + environment info” in the prompt
In other words, it’s not “because OpenClaw is running” — it’s that your OpenClaw usage patterns determine how much information gets sent to the LLM.
Patterns that reduce usage (when OpenClaw works well)
- OpenClaw summarizes history before sending it
- Tool results get trimmed to only the relevant parts before being sent
- Sessions are split by purpose to keep context clean
Where you might “feel a difference” in consumption
Even though you’re using the same Claude under the hood:
- Claude Code (the
claudecommand) has a “dev-oriented style” (lots of file references and tool calls) - OpenClaw has an “agent-oriented style” (sessions/tools/channels/skills)
The way they send things is different, so token usage patterns will differ too.
Something you can check right now
In openclaw tui, you should see something like:
tokens 0/200k
This number goes up as you keep chatting. It increases not “because OpenClaw is running,” but because the input sent to Claude + the output Claude returns keeps accumulating.
OpenClaw is the “vessel (hands and feet),” Claude is the “brain.” What determines cost (tokens) is how much information OpenClaw passes to Claude.

