`node --test tests/` 在 Node 22 上根本不工作 —— Node 把路径当模块加载, 报 "Cannot find module .../tests",退出码 1,零个测试执行。而这条命令在 CLAUDE.md 里被当作标准用法记了很久。这大概就是这套断言从来没人跑起来的 一个主要原因:照文档敲,得到一个看不懂的错误。 正确形式是裸 `node --test`(自动发现 **/*.test.mjs)。四处全改,并加断言 钉住 —— 我自己第一版钩子和 workflow 也照抄了那个错误形式,实测才发现 它会无条件拦住每一次 push。 - .gitea/workflows/tests.yml:Gitea 原生位置。用 node 容器而非 setup-node, 自建 Gitea 上后者要从 GitHub 拉,是新 runner 上又一个可能缺的东西。 容器 tag 与 NODE_VERSION 绑定,否则 CI 测的运行时和出货的不是一个。 - .github/workflows/tests.yml:镜像一份,断言保证两边执行内容一致。 - .githooks/pre-push:不依赖任何 runner 的兜底。实测过它会拦下失败的 push。 写明 --no-verify 怎么跳过 —— 拦不掉的钩子会被第一个被卡住的人删掉。 为什么需要钩子这一层:这台 Gitea 的 Actions 是开着的,但推上去的 workflow 产生了 0 次运行(total_count: 0),runner API 要鉴权查不了,最可能是没注册 runner。钩子是唯一完全不需要服务端支持的一层。 CLAUDE.md 补上 `git config core.hooksPath .githooks` —— 钩子是 per-clone 的, 没人替你装。
17 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview — CRITICAL MENTAL MODEL
This repo IS the USB drive content, minus large dependencies. The relationship:
代码库(git)= U 盘骨架(脚本 + HTML + 小文件)
↓ bash setup.sh
完整文件夹 = U 盘内容(骨架 + Node.js + OpenClaw)
↓ 拷贝到 U 盘
U 盘 = 插上就能用
The repo is NOT a "build tool" or "generator" — it IS the USB structure. setup.sh only fills in large deps that can't go in git. After setup.sh, the portable/ folder is directly copyable to a USB drive.
Distribution forms:
- Portable USB (
portable/): Run from USB on existing Mac/Windows, zero install. This is the only form CI publishes (Windows full zip; Mac runssetup.shon first launch). - Bootable Linux USB (
bootable/): Ventoy + Ubuntu 24.04 — boots any x86_64 PC from USB, no OS needed. Independent module, user-run scripts (not in CI). - One-line install (
install/):curl | bashorirm | iex— download and install from network, no USB needed. User-run scripts (not in CI).
Deprecated (2026-06-19): Electron desktop app (
u-claw-app/, DMG/EXE) is no longer built or published — it was a weaker duplicate of the commercial ClawX desktop and had cold-start gateway-timeout bugs. Code is kept for archive only; seeu-claw-app/DEPRECATED.md. Thedesktop-windows/desktop-macCI jobs were removed fromrelease.yml.Removed:
usb-release/— an abandoned older predecessor ofportable/(last touched 2026-04,core/+skills/layout, referenced nowhere). Deleted 2026-06-19.
Development Commands
# Portable version — build dev copy
cd portable/advanced && bash setup.sh # Downloads Node.js v22 + OpenClaw + plugins into ../app/
cd .. && bash "START HERE - Mac.command" # Launch (Mac). Windows: double-click "START HERE - Windows.bat"
# Copy to USB drive
cp -R portable/ /Volumes/YOUR_USB/U-Claw/
# Electron desktop app
cd u-claw-app && bash setup.sh # One-click: Node.js + Electron + deps
npm run dev # Dev mode
npm run build:mac-arm64 # Build Mac ARM64 DMG
npm run build:win # Build Windows NSIS + portable
# Bootable Linux USB (run on Windows PowerShell as Admin)
cd bootable
.\1-prepare-usb.ps1 # Write Ventoy to USB (formats drive!)
.\2-download-iso.ps1 # Download Ubuntu ISO (~5.8GB)
.\3-create-persistence.ps1 # Create 20GB ext4 persistence image
.\4-copy-to-usb.ps1 # Copy ISO + persistence + scripts to USB
Tests
node --test # Run every test (node:test, no framework dependency)
node --test tests/windows-launchers.test.mjs # Run one file
# NOT `node --test tests/` — Node reads that path as a module to load and dies
# with "Cannot find module". That form was documented here for years, which is
# a good part of why the suite went unrun.
Tests assert on the text/behavior of the launchers and shared .mjs helpers — e.g. that the
Start launchers stay thin shells over lib/start.mjs, that .bat files are pure ASCII with CRLF,
that no China-routed download source comes back, that the two installers resolve skills the same
way, and that every message key exists in every catalogue. They read repo files as strings; they
do not spawn OpenClaw. There is no root
package.json.
Enable the pre-push hook after cloning — it is per-clone and nothing installs it for you:
git config core.hooksPath .githooks
It runs the suite and the generated-file check before anything leaves your machine.
git push --no-verify skips it. This matters because CI cannot be relied on here:
the suite went unrun for the whole life of the upstream project, and on our own
Gitea the workflow produced zero runs — most likely no runner is registered. The
hook is the one layer that works with no server support at all.
As of 2026-08-17 tests also run in CI where a runner exists — .github/workflows/tests.yml runs
node --test on every push and PR. Before that they were local-only, so the guards they
encode could regress unnoticed.
CI workflows (.github/workflows/): release.yml builds Win/Mac portable + desktop and
publishes a GitHub Release on tag push. track-upstream.yml runs daily (cron) — checks
npm view openclaw version against the pinned OPENCLAW_VERSION; if upstream is newer it bumps
both OPENCLAW_VERSION files + the desktop shell version (u-claw-app/package.json patch),
commits, and pushes a new v<shell-version> tag, which in turn triggers release.yml. Supports
workflow_dispatch with force_version / dry_run inputs. OPENCLAW_VERSION is the upstream
pin; u-claw-app/package.json is the shell version (the two are separate).
Testing of the actual runtime should be done in a separate folder or directly on USB. This repo stays clean (no node_modules, no app/ runtime).
Architecture
portable/ THE USB content (= repo + setup.sh downloads)
setup.sh / setup.bat / setup.ps1 — fill in app/ (Node + OpenClaw + plugins)
{Mac,Windows}-Start — launch gateway + config-server, open dashboard/Config
{Mac,Windows}-Menu — interactive CLI launcher (pick start/config/CLI/diagnose)
{Mac,Windows}-Install — copy USB → computer (~/.uclaw/ or %USERPROFILE%)
{Mac,Windows}-Diagnose — health check / collect logs for bug reports
{Mac-OpenClaw-CLI,OpenClaw-CLI.bat} — drop into raw `openclaw` CLI
*.html (Welcome, U-Claw, SkillHub) — local UI pages
Config.html — redirect shim only; the settings UI itself is
config-server/public/index.html (single implementation since 2026-08-17).
The old standalone copy called the API on a root-relative path, which
cannot work from file:// — Save failed silently for anyone who opened it.
config-server/server.js — local HTTP server (port 18788-18798) backing
Config.html: writes openclaw.json, WeChat QR login, update-status API
lib/ — Node helpers (see "lib/ helpers" below)
default-config.json — seed config copied to data/.openclaw/ on first run
app/core/ (OpenClaw) + app/runtime/ (Node.js) — downloaded by setup.sh
data/.openclaw/openclaw.json — user config (on USB, portable)
skills/ Single source of truth for skill content + distribution (2026-08-17).
manifest.json — the only thing installers read
en/<id>/SKILL.md — content
Replaces the old three-way split (portable/skills-cn/ on disk,
heredocs in install.sh, here-strings in install.ps1). See skills/README.md.
Installed by lib/install-skills.mjs; release.yml copies skills/ + the
installer onto the drive so it can re-install offline.
u-claw-app/ [DEPRECATED 2026-06-19, archived — not built/published] Electron desktop app
(main.js ~400 lines). Kept for archive only; see u-claw-app/DEPRECATED.md.
Bundles Node.js in resources/runtime/node-{platform}-{arch}
bootable/ Linux 可启动 U 盘模块(完全独立,不依赖其他模块)
4 步 PowerShell 脚本 (Windows 上制作)
Ventoy 1.0.99 + Ubuntu 24.04 LTS + casper-rw 持久化
linux-setup/ — setup-openclaw.sh 安装到 /opt/u-claw/
独立仓库镜像: gitea.fanghe.it.com/zhenghy/u-claw-linux
install/ 一键在线安装模块(curl | bash / irm | iex)
install.sh (Mac/Linux) + install.ps1 (Windows)
7 步流程: 系统检测 → Node.js → OpenClaw → QQ插件 → 技能(读 skills/manifest.json) → 模型配置 → 启动脚本
安装到 ~/.uclaw/,与 Mac-Install.command 结果相同
This is a fork. Upstream is
github.com/dongsheng123132/u-claw; we host atgitea.fanghe.it.com/zhenghy/u-clawand do not send changes back — the overseas build removes the China-market defaults that are the point of the upstream project. Seeorigin.jsonfor every URL this build fetches at runtime, and the migration notes in the workspace root.The website is upstream's and we do not have it. They split it out on 2026-04-14 (commit
65f830e) into a private repo of their own.guide.htmllives there, so the website work in the overseas plan is blocked until we either get access or build our own.
Both portable and desktop versions auto-find a free port in range 18789–18799 and start the OpenClaw gateway. On first run, they detect whether a model is configured — if not, they open Config.html; otherwise, they open the dashboard.
Key Technical Details
- Node.js discovery: Portable looks at
app/runtime/node-mac-arm64/bin/node; Electron looks atresources/runtime/node-{platform}-{arch}then falls back to systemnode - Download sources (overseas build, 2026-08-17): Node.js binaries from
nodejs.org/dist, npm packages fromregistry.npmjs.org, GitHub assets direct. No China-routed mirrors or GitHub proxies remain in scripts, launchers or CI —tests/no-china-sources.test.mjsfails the build if any come back. OPENCLAW_VERSIONfile: single source of truth for the bundled OpenClaw runtime version (e.g.2026.6.8). CI reads it to pin the npm install; it's copied intoportable/so USB users /check-update.mjscan compare installed vs latest. Bump this file to upgrade.- Environment variables:
OPENCLAW_HOME,OPENCLAW_STATE_DIR,OPENCLAW_CONFIG_PATHcontrol where OpenClaw reads config - macOS quarantine: Mac scripts run
xattr -rd com.apple.quarantineto remove Gatekeeper blocks - Config format:
{"gateway":{"mode":"local","auth":{"token":"uclaw"}},"models":{"mode":"merge","providers":{"xxx":{...}}},"agents":{"defaults":{"model":{"primary":"provider/model"}}}} - Config hot-reload: OpenClaw watches
openclaw.jsonand applies changes without restart - Two local servers on startup: launchers start the OpenClaw gateway (18789–18799) AND
the config-server (
config-server/server.js, 18788–18798). The config-server backsConfig.html— it writesopenclaw.json, drives WeChat QR login, and exposes update-status.
lib/ Helpers (portable)
Pure-Node, zero-dependency .mjs modules (use fetch + node:zlib only). All are designed to
fail silently and run detached so they never block or break OpenClaw startup.
| File | Purpose |
|---|---|
check-update.mjs / publish-latest.mjs |
Portable self-update: check installed vs latest OPENCLAW_VERSION; publish helper. |
portable-cache.mjs |
启动加速核心:把"重 IO、可重建"的缓存从 U 盘搬到本机硬盘。算出本机缓存根(win %LOCALAPPDATA%\U-Claw\<slot> / mac ~/Library/Caches/U-Claw / linux $XDG_CACHE_HOME,UUID 隔离让换盘符仍复用),输出 NODE_COMPILE_CACHE 路径,并把 data/.openclaw/browser 做成 junction(win)/symlink(mac) 指向本机盘——浏览器 user-data 的海量随机小写不再砸 U 盘。CLI 打印 KEY=VALUE 供启动脚本 source。静默失败:取不到就缓存留 U 盘照常启动。 |
prewarm.mjs |
gateway 首轮预热:端口就绪后后台静默 GET /ready→/status→/models(带 x-openclaw-token),把 config/model 子系统在 runtime 内存里热起来,用户首次点发送不再等。零依赖、短超时、后台 detach。 |
loading.html |
启动首屏(splash):双击启动后立刻打开,给即时反馈消除"黑窗假死"。本页每秒 fetch /ready,gateway 真就绪后自动 location.replace 跳 Dashboard——天然规避"gateway 没起就开 Dashboard 拒连"(issue #46/#48)。端口经 ?port= 传入。 |
start.mjs |
启动主逻辑(2026-08-17 起):运行时检测、数据目录、缓存加速、默认配置、依赖安装、NO_PROXY、微信插件、config-server 启动与端口发现、gateway 端口扫描、首屏与控制台打开、预热、兜底轮询、退出清理。.bat/.command 退化为 ~30 行的启动壳。这样两平台不会再漂,且所有面向用户的文案可翻译。 |
i18n.mjs + messages/{en,zh-CN}.json |
启动器与本地页面的词条。语言优先级:显式覆盖 > 盘内配置 uclaw.locale > 系统 locale > en —— 语言跟盘走,不跟机器走。key 用语义命名,缺失自动回落英文。 |
wait-gateway.bat |
已移除(2026-08-17)。兜底轮询并入 start.mjs 的 watchGatewayReady(),现在 macOS 也有了 —— 此前只有 Windows 有。 |
maintain.sh |
Maintenance/diagnostics script. |
启动加速(吸收自 v2 u-clawx 4.0 的工程经验,2026-06-17)
便携版从 U 盘启动慢,瓶颈在 U 盘随机小写 IO + 首屏无反馈 + 首轮冷启动。移植 4.0 的 4 个可在纯脚本层复刻的手段:
- 缓存搬本机(
portable-cache.mjs):浏览器 user-data(OpenClaw 硬编码在CONFIG_DIR/browser/,无单独环境变量,故用 junction/symlink 重定向)+ V8 编译缓存(NODE_COMPILE_CACHE)落本机 SSD。业务数据(openclaw.json、memory、账号)仍留 U 盘,便携性不变。UUID 隔离让 D:→E: 换盘符仍命中同一份本机缓存。 - Node 编译缓存:
openclaw.mjs本就调module.enableCompileCache(),但默认落系统 temp(可能被清)。启动脚本显式把NODE_COMPILE_CACHE指向本机固定目录,二次启动稳定命中。 - 启动首屏(
loading.html):双击即弹,自轮询自跳转。 - 首轮预热(
prewarm.mjs):后台唤醒 config/model。 - 动态探测:Windows 把写死的
timeout /t 2(等 config-server)改成轮询 18788,省掉白等。
注:OpenClaw 自身的临时/lock/chrome-mcp 文件已走
os.tmpdir()(系统 temp,不在 U 盘),无需处理;真正落 U 盘的只有OPENCLAW_HOME=data/下的内容。
纯开源,无追踪: 这个开源版不含设备指纹 (
fingerprint.mjs)、自动开户 (bootstrap-xiapan.mjs/xiapan-client.mjs)、崩溃上报 (report-bug.mjs) 等商业版逻辑——这些已在 2026-06-17 移除。U-Claw 不绑定设备、不打指纹、不向api.u-claw.org上传任何数据。
模型配置 ("选模型填 Key")
设置页(config-server/public/index.html,旧入口 Config.html 会重定向过来)列出模型供用户挑选。首选卡片是 虾盘云 (Xiapan Cloud 中转站,api.u-claw.org/v1)
——一个 Key 调用 DeepSeek / Claude / GPT / 通义 等全部模型,但和其它 provider 一样需要用户自己去
https://u-claw.org/cloud.html 注册拿 Key,不再自动开户。其余 provider (DeepSeek/通义/Kimi/智谱/
豆包/MiniMax/OpenAI/Claude/Groq/硅基流动/自定义) 填各家官方 Key 即可。配置只写本地
data/.openclaw/openclaw.json。
What NOT to Commit
Never commit runtime dependencies or build artifacts. These are all in .gitignore:
portable/app/andportable/data/(runtime + user data)u-claw-app/node_modules/,u-claw-app/release/,u-claw-app/resources/runtime/*.dmg,*.exe,*.blockmap
Release artifacts go to GitHub Releases, not the repo.
Branding Rules
- Use only official
openclaw(notopenclaw-cnor any community fork) - All npm installs reference
openclaw@latest(official package) - External links point to
u-claw.org(our site) orgithub.com/openclaw/openclaw(upstream) - No references to competitor products (Qclaw, AutoClaw) in any tracked files
- Skill marketplace links point to
skillhub.tencent.comorgithub.com/openclaw/clawhub
Platform Support Status
- Mac Apple Silicon (ARM64): ✅ Working
- Mac Intel (x64): ✅ Working(portable 需先运行 setup.sh 下载 node-mac-x64)
- Windows x64: 🚧 In development
- Linux x64 (Bootable USB): ✅
bootable/目录 + 独立仓库 u-claw-linux
Bootable Linux Key Details
- 制作环境: Windows 10/11 + PowerShell (Admin),4 步脚本
- U 盘要求: 32GB+ USB 3.0
- 技术栈: Ventoy 1.0.99 引导 → Ubuntu 24.04 ISO → casper-rw 持久化 → OpenClaw 安装到 /opt/u-claw/
- 下载源: ISO 走 releases.ubuntu.com,Node.js 走 nodejs.org,npm 走 registry.npmjs.org
- Linux 环境变量:
OPENCLAW_HOME=/opt/u-claw/data/.openclaw - bootable/ 完全独立: 不引用 portable/、u-claw-app/ 的任何文件,修改互不影响
- 同步: bootable/ 内容与 u-claw-linux 仓库保持一致,改一边要记得同步另一边