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

20 KiB
Raw Permalink Blame History

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

# 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 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 driveopenclaw.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

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