# Contributing ## The mental model, first > **This repository is the USB drive's contents** — scripts, HTML, small files. > **After `setup.sh` it is a working drive** — the above plus Node.js and OpenClaw. It is not a build tool that produces a drive. It *is* the drive. That one idea explains most of the layout. Four distribution forms, deliberately independent — changing one does not touch the others: | Directory | Form | Entry point | |---|---|---| | `portable/` | USB drive — **the main product** | `advanced/setup.sh` → `START HERE - Mac.command` | | `bootable/` | Linux USB that boots a machine with no OS | `1-prepare-usb.ps1` → `4-copy-to-usb.ps1` | | `install/` | One-line network install | `install.sh` / `install.ps1` | | `u-claw-app/` | Electron desktop — **deprecated**, archive only | not built | ## 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**: this build removes the China-market defaults that are the point of the upstream project. If you are fixing something we inherited unchanged, consider telling them too. ## Getting set up ```bash git clone ssh://git@gitea.fanghe.it.com:222/zhenghy/u-claw.git cd u-claw # Enable the pre-push hook. Nothing installs it for you, and it is the only # thing reliably running the tests — see below. git config core.hooksPath .githooks # The fastest thing to iterate on is the portable build cd portable/advanced && bash setup.sh # fetches Node.js + OpenClaw into ../app/ cd .. && bash "START HERE - Mac.command" ``` | Platform | State | |---|---| | macOS Apple Silicon | ✅ main development platform | | macOS Intel | ✅ works — `setup.sh` fetches `node-mac-x64` first | | Windows x64 | 🚧 **needs verification** — see below | | Linux x64 | ✅ via `bootable/` | > **Windows currently carries unverified changes.** A large amount of PowerShell > and several `.bat` path-resolution changes were written on a Mac with no > PowerShell available, so they have never been through a parser. If you have a > Windows machine, running that check is the single most useful thing you can do > right now. `U盘实测清单.md` in the workspace root has the exact commands. ## Tests ```bash node --test # everything node --test tests/windows-launchers.test.mjs # one file ``` **Not `node --test tests/`.** Node reads that path as a module to load and dies with "Cannot find module" — zero tests run, exit code 1. That form was the documented command here for a long time, which is a good part of why the suite went unrun for the life of the project. The suite asserts on the *text and behaviour* of scripts rather than spawning OpenClaw: that `.bat` files stay pure ASCII (Chinese Windows `cmd.exe` reads non-ASCII as GBK and mis-parses), that `.command` files stay LF-only, that no China-routed download source comes back, that both installers resolve skills identically, that every UI string exists in every language, and that nothing points at a host `origin.json` does not declare. CI runs it where a runner exists (`.gitea/workflows/tests.yml`, mirrored to `.github/`). On our Gitea there is currently no registered runner, so the pre-push hook is doing the work. Install it. ## Filing an issue **A bug report needs four things**, or nobody can act on it: 1. OS and version — `macOS 14.5`, `Windows 11 23H2` 2. Which form — portable / install / bootable 3. **The full error as text.** Not a screenshot of text. 4. What you already tried **A feature request needs a situation, not a feature.** "I'd like X" is not enough to discuss. "I'm doing Y, I need X, because Z" is. ## Sending a change Before you write it: - **Does anyone need this?** For anything large, open an issue first. - **Does it break another form?** A change in `portable/` should not affect `bootable/`. - **Did you run it?** Not just the tests — the actual thing. Do not: - Commit `node_modules/`, `app/`, `data/`, `*.dmg`, `*.exe` — all in `.gitignore` - Put an API key, token or password in any file - Reformat unrelated code ("ran prettier over everything" makes review impossible) - Open a PR with a title and no description Commit messages: say what changed and why, in a sentence someone can act on. ``` fix(install.sh): npm wrapper cannot be run through node directly feat(skills): add linkedin-post docs: note Windows 11 ARM64 support ``` Not `update`, `fix`, or `changed some files`. ```bash git switch -c fix/something # never work on main git add # not git add . git push -u origin fix/something ``` ## Notes per form **`portable/`** - Never commit `app/` or `data/` — `setup.sh` produces them - `.command` files need the executable bit and LF endings - `.bat` files must be pure ASCII with CRLF, and must not contain an unescaped `)` inside an `IF (...)` block — that closes the block early and the window flash-exits. There is a test for it, and it has caught real regressions. - User config lives in `data/.openclaw/openclaw.json`. That file being on the drive is the entire portability story; do not move it. - User-facing text belongs in `lib/messages/*.json`, never in a script **`bootable/`** - The four PowerShell scripts must run **in order** - Fully self-contained: it references nothing from `portable/` on purpose **`install/`** - These run through `curl | bash` with **no checkout**, so they cannot read `origin.json` and carry URLs as literals. `tests/origin.test.mjs` fails if those literals drift from `origin.json` — that is what stops a host migration from half-happening. - Neither script may contain skill text. Both call `lib/install-skills.mjs`. **`u-claw-app/`** — deprecated 2026-06-19, kept for archive. Do not add to it.