Some checks failed
Tests / test (push) Has been cancelled
`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 的, 没人替你装。
239 lines
17 KiB
Markdown
239 lines
17 KiB
Markdown
# 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:
|
||
1. **Portable USB** (`portable/`): Run from USB on existing Mac/Windows, zero install. **This is the only form CI publishes** (Windows full zip; Mac runs `setup.sh` on first launch).
|
||
2. **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).
|
||
3. **One-line install** (`install/`): `curl | bash` or `irm | 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; see `u-claw-app/DEPRECATED.md`. The `desktop-windows`/`desktop-mac` CI jobs were removed from `release.yml`.
|
||
>
|
||
> **Removed: `usb-release/`** — an abandoned older predecessor of `portable/` (last touched 2026-04, `core/`+`skills/` layout, referenced nowhere). Deleted 2026-06-19.
|
||
|
||
## Development Commands
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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 at
|
||
> `gitea.fanghe.it.com/zhenghy/u-claw` and do **not** send changes back — the overseas
|
||
> build removes the China-market defaults that are the point of the upstream project.
|
||
> See `origin.json` for 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.html` lives 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 at `resources/runtime/node-{platform}-{arch}` then falls back to system `node`
|
||
- **Download sources (overseas build, 2026-08-17)**: Node.js binaries from `nodejs.org/dist`, npm packages from `registry.npmjs.org`, GitHub assets direct. No China-routed mirrors or GitHub proxies remain in scripts, launchers or CI — `tests/no-china-sources.test.mjs` fails the build if any come back.
|
||
- **`OPENCLAW_VERSION` file**: 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 into `portable/` so USB users / `check-update.mjs` can compare installed vs latest. Bump this file to upgrade.
|
||
- **Environment variables**: `OPENCLAW_HOME`, `OPENCLAW_STATE_DIR`, `OPENCLAW_CONFIG_PATH` control where OpenClaw reads config
|
||
- **macOS quarantine**: Mac scripts run `xattr -rd com.apple.quarantine` to 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.json` and 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 backs
|
||
`Config.html` — it writes `openclaw.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 个可在纯脚本层复刻的手段:
|
||
|
||
1. **缓存搬本机**(`portable-cache.mjs`):浏览器 user-data(OpenClaw 硬编码在 `CONFIG_DIR/browser/`,无单独环境变量,故用 junction/symlink 重定向)+ V8 编译缓存(`NODE_COMPILE_CACHE`)落本机 SSD。业务数据(`openclaw.json`、`memory`、账号)仍留 U 盘,便携性不变。UUID 隔离让 D:→E: 换盘符仍命中同一份本机缓存。
|
||
2. **Node 编译缓存**:`openclaw.mjs` 本就调 `module.enableCompileCache()`,但默认落系统 temp(可能被清)。启动脚本显式把 `NODE_COMPILE_CACHE` 指向本机固定目录,二次启动稳定命中。
|
||
3. **启动首屏**(`loading.html`):双击即弹,自轮询自跳转。
|
||
4. **首轮预热**(`prewarm.mjs`):后台唤醒 config/model。
|
||
5. **动态探测**: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/` and `portable/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` (not `openclaw-cn` or any community fork)
|
||
- All npm installs reference `openclaw@latest` (official package)
|
||
- External links point to `u-claw.org` (our site) or `github.com/openclaw/openclaw` (upstream)
|
||
- No references to competitor products (Qclaw, AutoClaw) in any tracked files
|
||
- Skill marketplace links point to `skillhub.tencent.com` or `github.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](https://gitea.fanghe.it.com/zhenghy/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 仓库保持一致,改一边要记得同步另一边
|