The Problem

Users who want a locally‑run, always‑on personal assistant must stitch together multiple messaging APIs, voice pipelines, and LLM back‑ends themselves. Maintaining the glue code, handling secrets, and keeping the system up‑to‑date is error‑prone and fragments across many language runtimes.

What This Does

clawdbot (a fork of OpenClaw) bundles a set of self‑contained extensions that each speak a channel (WhatsApp, Discord, BlueBubbles, Matrix, etc.) and a core gateway that routes messages to LLM providers (Anthropic, OpenAI).

Key source locations:

  • extensions/ – 9 independent channel adapters, each with its own index.ts entry (e.g., extensions/discord/index.ts).
  • src/agents/ – payload helpers for Anthropic (anthropic-payload-log.ts).
  • extensions/memory-lancedb/ – the default vector store implementation; extensions/memory-lancedb/index.ts contains the execute function (line 316) that initializes the DB and is the most isolated entry point (reaches 205 functions, called nowhere else).

Common utilities (parse, delete, resolve, normalizeAccountId) appear in 60+ call sites each, making them the highest‑impact change nodes.

How It Is Wired

Execution starts in one of the extension entry points or a script. The most visible script entry is scripts/bench-model.ts (main at line 81) which calls 125 functions and is invoked by a single caller.

A typical message flow (e.g., a Discord inbound DM) follows:

  1. extensions/discord/index.ts receives the webhook and calls handleIncomingDM (found in extensions/tlon/src/monitor/index.ts, line 160).
  2. handleIncomingDM → processMessage → sendGroupMessage → poke (filesystem write via this.open).
  3. Core routing uses resolve (61 call sites) to map a channel‑specific payload to a unified internal format.

Database writes go through the LanceDB adapter:

  • execute → initiateCall → persistCallRecord → fsp.appendFile (filesystem).

The vector store resolves embeddings via createFeishuClient (22 call sites) and runZca (21 call sites).

The most “blast‑radius” functions are delete (65 callers) and parse (61 callers); any change here ripples through most extensions and the core gateway. The call graph shows a dense hub around the resolve* family, indicating that routing logic is the primary integration point.

External effects are limited to five functions: three network calls, one model inference, and one cryptographic operation (validateTwilioSignature in extensions/voice-call/src/webhook-security.ts). File I/O occurs in the DB persistence path, asset copying (scripts/bench-model.ts → copyA2uiAssets), and runtime state loads (ensureRuntime → loadActiveCallsFromStore).

How To Use It

# Clone the repo (exact URL required)
git clone https://github.com/moses-y/clawdbot.git
cd clawdbot

# Install dependencies with pnpm (lockfile present)
pnpm install

# Create a runtime config from the example
cp .env.example .env   # edit .env to add your LLM API keys, channel tokens, etc.

# Build and run the gateway in Docker (Dockerfile present)
docker build -t clawdbot:latest .
docker run -d -p 18789:18789 --env-file .env clawdbot:latest

The gateway listens on port 18789 (see Dockerfile and runtime docs). Channel adapters are loaded automatically from the extensions/ folder; each one registers its webhook routes during the Docker container start‑up.

If you prefer a local Node process, the package’s bin (defined in package.json) exposes the openclaw CLI used in the upstream README (openclaw gateway --port 18789 --verbose). The CLI reads the same .env file.

Real‑World Use

A small office deploys the Docker container on a Raspberry Pi. The .env contains an Anthropic API key and a Discord bot token. Incoming Discord messages trigger extensions/discord/index.ts, which resolves the payload, calls the LLM via the gateway, and returns the assistant’s reply on the same channel. All conversation history is persisted in the LanceDB store (extensions/memory-lancedb/), enabling context‑aware responses without external services.

Code Health & Issues

  • High – vendor/a2ui/renderers/angular/.npmrc is tracked despite .gitignore; likely contains credentials. Remove with git rm --cached and rotate secrets.
  • High – GitHub Actions use mutable tags (@v3, @v4). Pin each to a commit SHA to prevent supply‑chain hijack.
  • Medium – Workflows lack explicit permissions for GITHUB_TOKEN; add permissions: contents: read (or finer).
  • Medium – Dockerfile uses mutable base node:22-bookworm; replace with digest (node@sha256:<digest>).
  • Medium – No dependency‑vulnerability scan in CI; add dependency-review-action or osv-scanner.
  • Medium – Checkout step keeps the token (persist-credentials: true); set to false and pass explicit token only where needed.
  • Low – CI jobs lack timeout-minutes; set reasonable limits to avoid overlapping runs.

The Bottom Line

clawdbot delivers a modular, multi‑channel personal assistant with a clear separation of channel adapters and a shared LLM gateway. The codebase is large (6 k files) but well‑structured; the call‑graph hubs (delete, parse, resolve*) are the primary levers for change. Health issues are mostly operational (unpinned actions, secret leakage) rather than functional bugs. It is suitable for teams comfortable managing Docker containers and secret rotation, but requires careful remediation of the high‑severity findings before production use.