Files
u-claw/CLAUDE.md
zheng 3221856d50
Some checks failed
Tests / test (push) Has been cancelled
docs: 文档改为英文,并修正过时内容
不是翻译 —— 多数文档描述的行为已经不存在了。

先修一个更基本的问题:我们不拥有 u-claw.org 域名,那是上游的。所以之前写在
README、诊断包提示、联系方式里的 help@u-claw.org 全都会把用户的问题发给
上游 —— 一个没有理由回复的人。改为指向我们自己的 issue tracker,并加断言
禁止再出现指向该域名的支持入口。

重写(内容过时,不是语言问题):
- install/README.md —— 还写着 10 个中国技能、DeepSeek 优先、国内镜像。
  现在按实际流程写:技能读 manifest、模型菜单 Gemini 优先、bundle 有
  SHA256 校验。并如实写明 curl|bash 在受管企业电脑上会被 EDR 拦。
- CLAUDE.md 的模型配置整节 —— 还在描述虾盘云首选卡片和 12 个 provider,
  那个界面已经换成单框 Key 输入了。
- SECURITY.md —— 安全报告原本指向上游维护者个人邮箱。fork 之后那条路由
  是错的:漏洞会发给写不了这份代码、也修不了的人。
- CONTRIBUTING.md —— 补上 fork 关系、pre-push 钩子怎么装、以及
  `node --test tests/` 为什么不能用。

翻译并保留:
- bootable/README.md、TROUBLESHOOTING.md —— 面向用户,顺带把
  「国内镜像」「小米/华为 BIOS 按键」等换成目标市场的实际情况

HANDOFF.md 重写为一份事故复盘:原文一半是过时的一次性交接笔记(引用的
website/guide.html 已不在本仓库),另一半是 persistence.dat 未格式化导致
启动失败的排查记录 —— 后者有长期价值,尤其是「读 offset 1080 的两字节
验证 ext4」这个判断方法,已同时写进 bootable/README.md。

bootable/IMPROVEMENTS_SUMMARY.md 保留中文,加了说明:它是上游 fork 前的
历史改进记录,没人引用,描述的是已完成的工作而非当前行为。翻译它反而会
让人误以为是现行文档。

新增 skills/en/uclaw-help —— 把「怎么用、东西在哪、出问题怎么办」做成
内置知识,每个角色都装。方案 C10.8:能问的产品才是不需要学的产品。
2026-08-17 19:12:07 +08:00

289 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
```
repository (git) = the drive's skeleton — scripts, HTML, small files
↓ bash setup.sh
working folder = the drive's contents — skeleton + Node.js + OpenClaw
↓ copy onto a USB drive
USB drive = plug in and go
```
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 bootable USB. Fully self-contained — references nothing
from the other modules, on purpose.
Four PowerShell scripts, run on Windows, in order.
Ventoy 1.0.99 + Ubuntu 24.04 LTS + casper-rw persistence
linux-setup/setup-openclaw.sh installs into /opt/u-claw/
Mirror: gitea.fanghe.it.com/zhenghy/u-claw-linux
install/ One-line network install (curl | bash / irm | iex).
install.sh (Mac/Linux) + install.ps1 (Windows)
Detect → Node.js → OpenClaw → QQ plugin → skills (from
skills/manifest.json) → model → start script → verify.
Installs to ~/.uclaw/; same result as advanced/Mac-Install.command.
These run with no checkout, so they cannot read origin.json
and carry URLs as literals — tests/origin.test.mjs keeps the
two in step.
```
> **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 1878918799 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** (1878918799) AND
the **config-server** (`config-server/server.js`, 1878818798). 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` | **The startup-speed core.** Moves the heavy, rebuildable caches off the USB drive onto local disk: works out a cache root (win `%LOCALAPPDATA%\U-Claw\<slot>`, mac `~/Library/Caches/U-Claw`, linux `$XDG_CACHE_HOME`), keyed by a UUID so the same cache is reused when the drive gets a different letter. Emits `NODE_COMPILE_CACHE`, and redirects `data/.openclaw/browser` to local disk via a junction (Windows) or symlink (macOS) — the browser profile's endless small random writes are what makes a USB drive feel broken. Prints `KEY=VALUE` for the launcher to read. Fails silently: if it cannot, the cache stays on the drive and startup continues. |
| `prewarm.mjs` | Wakes the gateway once it is listening: background `GET /ready``/status``/models` with the auth token, so the config and model subsystems are warm before the user's first message. Zero dependencies, short timeout, detached. |
| `loading.html` | The splash. Opens the instant the launcher starts, so a slow first run looks like progress rather than a frozen black window. Polls `/ready` once a second and moves on when the gateway answers — which sidesteps the old "dashboard opened before the gateway existed, connection refused" failure (issues #46, #48). Port arrives as `?port=`. |
| `start.mjs` | **All startup logic (since 2026-08-17).** Runtime detection, data folders, cache acceleration, default config, dependency install, NO_PROXY, WeChat plugin, config-server launch and port discovery, gateway port scan, opening the splash and Settings, prewarm, the fallback watcher, and cleanup on exit. The `.bat` and `.command` files are ~30-line shells over it. Two reasons: the platforms cannot drift apart again, and every user-facing string becomes translatable — neither is possible while the logic lives in a `.bat` that must stay pure ASCII. |
| `i18n.mjs` + `messages/{en,zh-CN}.json` | Strings for the launcher and the local pages. Resolution order: explicit override > `uclaw.locale` on the drive > system locale > `en`. **The language follows the drive, not the machine** — someone who set it up in Chinese and plugs it into a colleague's English Windows still gets Chinese. Keys are semantic, and a missing one falls back to readable English rather than leaking the key. |
| `self-heal.mjs` | Checks and repairs run when startup fails, before the user is told anything. Missing folders, a damaged settings file (moved aside, never deleted), a leftover port record, an interrupted copy, a dangling cache link. What it cannot fix produces a redacted diagnostics report. Every repair must be safe on a healthy drive — they all run whenever startup fails, including for reasons none of them explain. |
| `provider-detect.mjs` | Maps an API key prefix to its provider, so nobody has to know what a Base URL is. `sk-ant-` must be checked before the plain `sk-` catch-all. |
| ~~`wait-gateway.bat`~~ | Removed 2026-08-17. The fallback watcher moved into `start.mjs` as `watchGatewayReady()`, so macOS has it too — it was Windows-only before. |
### Why startup is fast off a slow drive (2026-06-17)
Running from a USB drive is slow for three separate reasons, and each needed its
own fix: **small random writes on the drive**, **no feedback on the first
screen**, and **a genuinely cold first run**.
1. **Move the caches to local disk** (`portable-cache.mjs`). The browser profile
is the worst offender — OpenClaw hardcodes it at `CONFIG_DIR/browser/` with no
environment variable to move it, so we redirect it with a junction (Windows)
or symlink (macOS). The V8 compile cache goes the same way via
`NODE_COMPILE_CACHE`. **Business data stays on the drive**`openclaw.json`,
`memory`, accounts — so portability is unaffected. A UUID key means the same
cache is reused when the drive comes up as `E:` instead of `D:`.
2. **Pin the compile cache.** `openclaw.mjs` already calls
`module.enableCompileCache()`, but it defaults to system temp, which gets
cleaned. Pointing `NODE_COMPILE_CACHE` at a stable local directory makes the
second launch reliably fast rather than occasionally fast.
3. **Show something immediately** (`loading.html`). It opens on double-click and
polls for readiness itself.
4. **Warm the gateway** (`prewarm.mjs`) in the background once the port answers.
5. **Poll instead of guessing.** Windows used to `timeout /t 2` waiting for the
config server; it now polls the port and proceeds the moment it is up.
> OpenClaw's own temp, lock and chrome-mcp files already go to `os.tmpdir()` —
> system temp, **not the drive** — so they need no handling. The only thing that
> genuinely lands on the drive is what lives under `OPENCLAW_HOME=data/`.
> **No tracking.** This build contains none of the commercial-version logic —
> no device fingerprinting (`fingerprint.mjs`), no automatic account creation
> (`bootstrap-xiapan.mjs` / `xiapan-client.mjs`), no crash reporting
> (`report-bug.mjs`). Upstream removed them on 2026-06-17. Nothing is bound to a
> device and nothing is uploaded to `api.u-claw.org`.
### Choosing a model (rewritten 2026-08-17)
Settings is `config-server/public/index.html`. `Config.html` in `advanced/` is a
redirect shim to it — the old standalone copy called the API on a root-relative
path while only ever being opened from `file://`, so its Save button had been
failing silently.
**The first screen asks for one thing: an API key.** It used to lay out twelve
provider cards and then demand a Base URL and a model name — three technical
fields on the first screen a non-technical user ever saw.
The key itself says which provider it belongs to (`lib/provider-detect.mjs`
maps the prefix), so:
1. Paste the key
2. After an 800ms pause, `POST /api/test-key` sends a 1-token request and reports
what actually happened — "connected in 340ms", or a sentence saying what to do
3. A model dropdown appears once it works, so the choice is not locked to
whatever the first key implied
The check runs server-side deliberately: the browser cannot reach most model
endpoints cross-origin, and doing it in the config server means the key never
leaves the machine by any path the page controls.
Endpoint and model name still exist, under a collapsed *Advanced* section that
only opens by itself when the key is not one we recognise.
Everything is written to `data/.openclaw/openclaw.json` on the drive.
## 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 the release page, 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 go to `origin.json`'s `urls`, or to `github.com/openclaw/openclaw` for the runtime.
We do **not** own `u-claw.org` — that is the upstream project's domain, so never
offer an address on it as a support route.
- 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 — run `setup.sh` first to fetch `node-mac-x64`
- Windows x64: 🚧 **Carries unverified changes.** A large amount of PowerShell and
the `.bat` path resolution were written on a Mac with no PowerShell available and
have never been through a parser. See `U盘实测清单.md` in the workspace root.
- Linux x64 (bootable USB): ✅ see `bootable/`, mirrored at [u-claw-linux](https://gitea.fanghe.it.com/zhenghy/u-claw-linux)
## Bootable Linux Key Details
- **Built on**: Windows 10/11, PowerShell as Administrator, four scripts in order
- **Drive**: 32 GB or larger, USB 3.0
- **Stack**: Ventoy 1.0.99 → Ubuntu 24.04 ISO → casper-rw persistence → OpenClaw in /opt/u-claw/
- **Sources**: ISO from releases.ubuntu.com, Node.js from nodejs.org, packages from registry.npmjs.org
- **Environment**: `OPENCLAW_HOME=/opt/u-claw/data/.openclaw`
- **Self-contained**: references nothing from `portable/` or `u-claw-app/`, so a change here cannot break them or vice versa
- **Mirrored**: kept identical to the u-claw-linux repo — a change in one needs the same change in the other