* fix(ui): disambiguate multi-account session labels Parse the optional account segment on per-account-channel-peer DM and group keys so Control UI no longer falls through to the raw routing key. Append a non-default account as " · accountId" on label, displayName, and fallback so two Alice rows from different Telegram accounts stay distinguishable. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * fix(ui): take the session account from the gateway row The display resolver was reading the account out of the session key and inferring it from label text. That missed the shipped `dm` spelling of direct keys, invented an account-qualified group shape no key builder emits, and treated any name ending in "(<account>)" as already disambiguated. The Gateway already projects the canonical `accountId` onto every session row from the delivery route, so display consumes that and parses the key only for panes rendered before their row arrives. Key parsing now covers both `direct` and the pre-#11881 `dm` spelling, group keys go back to their canonical account-less shape, and the account suffix is applied at a single point instead of five. `resolveChannelSessionInfo` classifies `dm` keys as channel sessions and no longer reads a peer kind sitting in the channel slot as a channel. * fix(ui): stop inferring session identity from rendered text Three related text-inference defects in the same display neighborhood: The account suffix was skipped when the resolved name already ended in " · <account>". That reads rendered output as if it were a fact, and it cannot tell an account apart from a user label that happens to look like one. The suffix is now appended from the recorded account alone. The string it was defending against came from the sidebar rename dialog, which pre-filled with the resolved display name. Submitting persisted a derived string as a real user label, which then outranked every later derivation. Sidebar rows now carry the stored label alongside the resolved one, and rename edits that, matching the Sessions page. Channel classification accepted an account segment before any peer kind, so `agent:<x>:<channel>:<account>:group:<id>` was filed under a channel even though accounts qualify direct chats only and the canonical route parser rejects the shape. The grammar now allows an account only before `direct`/`dm`. Resolver tests now prove the row projection is authoritative rather than duplicating an account the key already carries: one case where only the projection supplies it, and one where the two disagree. * ci: retrigger after check-lint shard cancel Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * test(ui): prove rename opens on the stored label The existing sidebar rename coverage uses a row that already has a stored label, so it passes whether rename pre-fills the stored label or the resolved display name. It could not catch the round-trip this branch repaired. Adds a browser case on a displayName-only row with a projected account: the sidebar shows "Alice · cards" and the rename field opens blank. On the parent commit the field opens holding "Alice · cards", which is the string that used to become a real user label on submit. * fix(ui): do not double-append a stored account suffix A persisted label that already ends in " · accountId" must stay as-is so "Alice · cards" does not become "Alice · cards · cards". Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * docs(ui): name the producer the account suffix check defends The comment above withAccountDisambiguator claimed the rendered name is never inspected, which the suffix check contradicts. State the real contract instead: the account itself still comes only from the recorded value, and the endsWith check is idempotence against the chat pane's inline rename, which seeds its input with the rendered title and persists a partial edit verbatim. --------- Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> Co-authored-by: vyctorbrzezowski <krzyszchweski@gmail.com>
OpenClaw 🦞 — Your assistant, on your devices, in your chats
OpenClaw is a personal AI assistant that runs on your devices and meets you in the channels you already use. It is designed for a single operator and connects models, tools, messaging channels, and optional companion apps through one Gateway.
Website · Docs · Getting started · Showcase · FAQ · Vision · DeepWiki
Install
The installer supports macOS, Linux, and Windows. It provisions a supported Node.js runtime when needed.
# macOS / Linux / WSL2
curl -fsSL https://openclaw.ai/install.sh | bash
# Windows PowerShell
iwr -useb https://openclaw.ai/install.ps1 | iex
Already manage Node.js? Install the published package instead (Node 22.22.3+, 24.15+, or 25.9+):
npm install -g openclaw@latest
See the installation guide for npm 12 lifecycle-script requirements, Docker, Nix, and other deployment paths.
Quick start
openclaw onboard --install-daemon
openclaw gateway status
openclaw dashboard
Onboarding verifies model access, creates the workspace, and configures the Gateway. The last command opens the Control UI; send a message there to confirm the assistant is working. See the getting started guide for channel setup and troubleshooting.
How it fits together
- The Gateway is the local control plane for sessions, tools, events, and channel connections.
- The Control UI, CLI, and TUI connect to the Gateway.
- Channels bring the assistant to WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, and other messaging services.
- Companion apps and nodes add voice, Canvas, camera, screen, and device-local actions on supported platforms.
OpenClaw works with hosted and local model providers. Its tools, skills, and plugins extend what an assistant can do.
Security
Treat inbound messages as untrusted input. DM-capable channels pair unknown senders by default; approve a pairing request with openclaw pairing approve <channel> <code>.
Tools run on the host for the main session unless you configure sandboxing. Read the security guide, exposure runbook, and sandboxing guide before connecting other users or exposing the Gateway remotely.
Documentation
| Goal | Start here |
|---|---|
| Configure models and auth | Models · Model providers |
| Connect a messaging service | Channels |
| Add tools, skills, and plugins | Tools · Skills · Plugins · ClawHub |
| Run apps and device nodes | Platforms · Nodes |
| Use the CLI and chat commands | CLI reference · Slash commands |
| Configure or operate the Gateway | Configuration · Architecture · Updating · Release channels |
Development
The repository is a pnpm workspace. Plain npm install at the repository root is not supported.
git clone https://github.com/openclaw/openclaw.git
cd openclaw
pnpm install
pnpm build
pnpm ui:build
See CONTRIBUTING.md for the contribution workflow and the source setup guide for the development loop.
Community
OpenClaw is developed in the open by the OpenClaw Foundation, a non-profit. See CONTRIBUTING.md for maintainers and contribution guidelines; AI-assisted PRs are welcome.
Use the issue chooser for bugs and feature requests, ask setup questions in Discord, and report vulnerabilities through SECURITY.md. New capabilities usually belong in plugins built on the plugin SDK and shared through ClawHub.
OpenClaw was built for Molty, a space lobster AI assistant, by Peter Steinberger and the community. Explore the project lore, soul.md, Peter's site, Star History, and @openclaw.
Special thanks to Mario Zechner for his support and for pi, and to Adam Doppelt for the lobster.bot domain.
Sponsors
Contributors
Thanks to all clawtributors:
License
MIT © OpenClaw Foundation. See THIRD_PARTY_NOTICES.md for incorporated or adapted code.
