一、项目背景
Clawdbot(后称 Moltbot)支持 WhatsApp、Telegram 等通道,可私有化部署 AI 助手。本文基于 GitHub 仓库 openclaw/openclaw 记录源码部署全过程,提供环境配置与避坑指南。
二、环境准备:Windows 下使用 WSL2
在 Windows CMD 直接部署易报错,推荐在 WSL2(Ubuntu/Debian)中操作。
- 启用 WSL2:开启 Windows 功能中的'适用于 Linux 的 Windows 子系统'和'虚拟机平台',重启后安装 Ubuntu 22.04。
- 配置系统:更新源(建议换阿里源),执行
sudo apt update && sudo apt upgrade -y。 - 安装 Git:
sudo apt install git,验证git --version。 注意:若跳过此步可能导致后续构建报错。
三、Node.js 版本要求
仓库文档要求 Node≥22。建议使用 nvm 管理环境并切换至最新版本。
注意:低于 22 的版本在执行 pnpm install 时会报错。
四、拉取源码与依赖安装
1. 克隆与安装
git clone https://github.com/openclaw/openclaw.git
cd openclaw
pnpm install
常见问题:node-llama-cpp 的 postinstall 脚本可能失败(错误码 3221225477)。该依赖仅用于本地嵌入,若使用远程模型(如 OpenAI)可忽略。解决方案是注释掉 package.json 中的 node-llama-cpp 依赖后重新运行 pnpm install。
2. 构建项目
先构建 UI:
pnpm ui:build
再构建主项目:
pnpm build
若在原生 Windows 上构建需 bash 环境。建议在项目的 /script 目录下创建 Node.js 版本的构建脚本 bundle-a2ui.mjs,内容如下:
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { promises as fs } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
import { promisify } ;
spawnAsync = (spawn);
__filename = (..);
__dirname = path.(__filename);
= path.(__dirname, );
= path.(, );
= path.(, );
= path.(, );
= path.(, );
() {
{
stat = fs.(dir);
stat.();
} {
;
}
}
() {
st = fs.(entryPath);
(st.()) {
entries = fs.(entryPath);
( entry entries) {
(path.(entryPath, entry), files);
}
files;
}
files.(entryPath);
files;
}
() {
p.(path.).();
}
() {
inputPaths = [
path.(, ),
path.(, ),
,
,
];
files = [];
( inputPath inputPaths) {
{
stat = fs.(inputPath);
(stat.() || stat.()) {
(inputPath, files);
}
} {
}
}
files.( (a).((b)));
hash = ();
( filePath files) {
rel = (path.(, filePath));
hash.(rel);
hash.();
content = fs.(filePath);
hash.(content);
hash.();
}
hash.();
}
() {
( {
proc = (command, args, {
...options,
: ,
: ,
});
proc.(, {
(code === ) {
();
} {
( ());
}
});
proc.(, reject);
});
}
() {
{
(!( ()) || !( ())) {
.();
process.();
}
currentHash = ();
shouldBuild = ;
{
previousHash = fs.(, );
outputExists = fs.().( ).( );
(previousHash.() === currentHash && outputExists) {
.();
shouldBuild = ;
}
} {
}
(shouldBuild) {
.();
(, [, , , , path.(, )]);
(, [, , , , path.(, )]);
fs.(, currentHash, );
.();
}
} (error) {
.();
.();
.(error);
process.();
}
}
();


