Skip to content

Commit e19590f

Browse files
schmonzclaude
andcommitted
docs: README rewrite — the QuickJS-binary-first story
clode is now the published native builder and quaude the locally-fused product; the Node launcher is the classic mode, one paragraph. Deleted: the stale bats instructions (the suite is pure node:test), the long node-pty/pnpm advisories (compressed to three lines), most of the SEA section (now the transitional -node assets, compressed). 188 lines -> 102. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013etF8NEcp8CHMWZxmf1d1h
1 parent e8b6fe4 commit e19590f

1 file changed

Lines changed: 65 additions & 150 deletions

File tree

‎README.md‎

Lines changed: 65 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,65 @@
1-
# clode: run Claude Code under Node
1+
# clode: Claude Code, everywhere
22

3-
Claude Code used to `npm install` anywhere you had Node. Now it's
4-
a binary-only distribution targeting only the most popular recent
5-
operating systems and hardware platforms. Even older x86 (pre-AVX2)
6-
no longer suffices.
3+
Claude Code ships as a binary-only distribution for a handful of popular
4+
platforms. clode re-bases it onto a small C runtime — txiki.js/QuickJS —
5+
and takes it everywhere else: macOS, musl-static Linux across eight
6+
architectures (x64 to s390x to loongarch64), NetBSD, FreeBSD, OpenBSD,
7+
DragonFly, OmniOS, Solaris — with more (Haiku, MidnightBSD, OpenIndiana,
8+
the BSDs on arm64) in the pipeline.
79

8-
Clode fixes this. Anywhere you have Node, run the latest Claude Code.
10+
Two pieces:
911

10-
## Beware
12+
- **clode** — the builder: one self-contained native binary per platform,
13+
needing no Node, no npm, nothing else on disk. The only thing we publish.
14+
- **quaude** — the product it makes: the current Claude Code bundle,
15+
compiled to QuickJS bytecode and fused with a node-compatibility runtime
16+
into one native executable. Derived work: you fuse it locally, and it is
17+
never distributed.
1118

12-
Clode is a hilarious hack that will inevitably stop working. It attempts
13-
to be reasonably robust against many failure modes, but can't possibly
14-
defend against all of them.
19+
## Usage
1520

16-
If you've been wishing you could run Claude Code directly on your weird
17-
machine, use Clode while you still can.
21+
Grab `clode-<version>-<platform>` from Releases, then:
1822

19-
## Usage
23+
```sh
24+
./clode-0.1.2-netbsd-amd64 build # fetch + extract + fuse -> ./quaude
25+
./quaude # run it like `claude`
26+
```
2027

21-
Run `clode` anywhere you'd run `claude`.
28+
Every fuse self-verifies before reporting success: an offline canned
29+
Messages round-trip plus `--quaude-attest` manifest verification. `clode
30+
build` extracts from a Claude Code provider bundle — it finds an
31+
npm-installed one, or point `CLODE_CLAUDE_BIN` at it.
2232

23-
On first run, it'll install its `npm` dependencies into a user-owned dir, fetch and postprocess the latest upstream, then launch it.
33+
The classic mode still works: with Node >= 24 on `PATH`, `clode` launches
34+
the extracted bundle directly under your host Node, anywhere you'd run
35+
`claude`. `clode update` keeps it current, and a daily changelog watch
36+
warns when an upstream change threatens the hack (`clode --clode-watch` on
37+
demand; `CLODE_NO_WATCH=1` off).
2438

25-
Updating is much the same as you're used to, modulo the postprocessing. After
26-
each `clode update`, a warn-only *signals* digest flags anything in the new
27-
release's notes or bundle that bears on clode's ability to keep running the JS
28-
under Node — e.g. a bundled-Bun-runtime bump, a raised Node floor, or new
29-
"requires the native binary" gating. It never blocks the update; in a source
30-
checkout it also writes a reviewable `signals/<ver>.json` snapshot. Override the
31-
notes source with `CLODE_CHANGELOG_URL` (air-gapped/testing).
39+
Either way you'll live without: image/sharp, audio capture, computer-use,
40+
SQLite-backed bits, MSAL, runtime TypeScript, and anything else from
41+
`Bun.*` that's stubbed or missing.
3242

33-
clode also watches for *concerning* upgrades on its own: about once a day a launch
34-
fires a background, changelog-only check, and if a newer Claude Code carries
35-
signals that bear on running under Node it prints a one-line notice next time you
36-
start. Run `clode --clode-watch` to check on demand, or set `CLODE_NO_WATCH=1` to
37-
turn the automatic check off.
43+
## Beware
3844

39-
You'll have to live without:
45+
clode is a hilarious hack that will inevitably stop working. It attempts
46+
to be reasonably robust against many failure modes, but can't possibly
47+
defend against all of them.
4048

41-
- image/sharp
42-
- audio capture
43-
- computer-use
44-
- SQLite-backed bits
45-
- MSAL
46-
- runtime TypeScript
47-
- anything else from `Bun.*` that's stubbed or missing
49+
If you've been wishing you could run Claude Code directly on your weird
50+
machine, use clode while you still can.
4851

4952
## Installation
5053

51-
### Dependencies
52-
53-
- `node` >= 24 and `npm`
54-
- `ugrep` >= 7.5.0, `bfs` >= 3.x (built with Oniguruma), and `rg` for fast searches
54+
From Releases: download, `chmod +x`, done. `SHA256SUMS` covers the native
55+
builders; every binary carries a SLSA provenance attestation
56+
(`gh attestation verify <file> --repo <owner/repo>`).
5557

56-
The launcher itself is a Node program (`#!/usr/bin/env node`), so it needs `node`
57-
on `PATH` to start. An ES5-safe prologue prints a friendly "node too old" message
58-
on an outdated node; a truly missing node yields `env: node: not found`.
58+
For the classic Node-launcher mode instead:
5959

60-
Once you have those:
60+
- `node` >= 24 and `npm` (>= 20 suffices for `clode build` alone)
61+
- `ugrep` >= 7.5.0, `bfs` >= 3.x (built with Oniguruma), and `rg` for fast
62+
searches
6163

6264
```sh
6365
npm pack
@@ -74,114 +76,27 @@ rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/clode"
7476

7577
## Development
7678

77-
### Test dependencies
78-
79-
- `node` >= 24 and `npm` (same as running clode)
80-
- `bats`
81-
- on Linux (and anywhere `node-pty` has no prebuilt binary): a C/C++ toolchain
82-
to compile it — `python3`, `make`, and a C++ compiler (`g++`/`clang++`). These
83-
are the standard `node-gyp` build deps.
84-
85-
The PTY/TUI tests drive clode under a pseudo-terminal via `node-pty` +
86-
`@xterm/headless`. Those are declared in a separate `test/package.json`, and
87-
`npm test` installs them automatically on first run. Because `node-pty` carries a
88-
**native** binary, the harness installs into a per-platform directory
89-
(`test/.harness/<os>-<osver>-<arch>-node<major>/`) rather than a shared
90-
`test/node_modules`, so one machine's compiled binary can't clobber another's on a
91-
shared/NFS workdir — `NODE_PATH` points the tests at the right one. These tests are
92-
**not optional** — the suite fails loudly rather than skipping if the harness can't
93-
load.
94-
95-
> **First install compiles `node-pty` and can take a few minutes.** `node-pty`
96-
> ships prebuilt binaries only for macOS and Windows; on **Linux** there is no
97-
> prebuild, so `npm install` compiles it from source with `node-gyp` (hence the
98-
> toolchain above). The very first build also downloads the Node C++ headers for
99-
> your Node version, so it may sit "quiet" for a while — it is not hung. Later
100-
> installs reuse the cached headers and finish in seconds.
101-
>
102-
> If you install with a package manager that blocks dependency build scripts by
103-
> default (e.g. **pnpm** or **bun**), the compile is skipped and `node-pty` loads
104-
> with "no prebuilt binary"; approve its build script first (pnpm:
105-
> `pnpm approve-builds`, or add it to `onlyBuiltDependencies`; bun:
106-
> `trustedDependencies`). Plain `npm` runs the build script without prompting.
107-
108-
> **A bare `npm install` at the repo root is tolerated, but unnecessary.** The
109-
> "fail-loud" tests (which assert clode dies with a clear message when a runtime dep
110-
> like `ws`/`yaml`/`semver` is absent) are now isolated from the repo's own
111-
> `node_modules` — they run their shim children from a temp copy outside the repo
112-
> tree — so a populated root `node_modules` no longer makes them pass vacuously. You
113-
> still don't need one: runtime deps install into a user-owned dir at runtime, and
114-
> test-harness deps live under `test/`.
115-
116-
Run the whole suite:
117-
11879
```sh
11980
npm test # offline suite (default; no network or login needed)
120-
npm run test:online # also run the network/model tests (needs a logged-in ~/.claude)
121-
```
122-
123-
Run a subset directly (run `npm test` once first — it installs the PTY/TUI harness
124-
into `test/.harness/<tag>/` and the rest resolve it via `NODE_PATH`):
125-
126-
```sh
127-
node --test test/*.test.cjs # JS unit, module, and differential tests
128-
bats test/ # launcher + integration tests
129-
```
130-
131-
### Building a single-file binary (SEA)
132-
133-
clode can be packaged as a stand-alone [Node SEA](https://nodejs.org/api/single-executable-applications.html) —
134-
one executable that embeds Node, the esbuilt launcher, and the runtime deps, so a
135-
target machine needs neither `node` nor `npm`:
136-
137-
```sh
138-
node scripts/build-sea.mjs
139-
```
140-
141-
The output is `build/<os>-<osver>-<arch>-node<major>/clode` (e.g.
142-
`build/darwin-25-arm64-node24/clode`). The build is self-provisioning: it installs
143-
its own build tools (`esbuild`, `postject`) and stages the runtime deps on first run,
144-
then caches them. On macOS it ad-hoc-signs the binary (required, or it won't launch).
145-
146-
**Use an official, non-stripped Node** ≥ 24 as the build node — a nodejs.org build,
147-
or one from `asdf`/`nvm`. The SEA embeds *whichever `node` runs the script*, so:
148-
149-
- A **stripped** node (some distro `/usr/bin/node`) corrupts under `postject` and the
150-
result segfaults at startup. The build's self-check catches this and explains it.
151-
- A node that links **non-system libraries** (e.g. a pkgsrc/Homebrew node pulling in
152-
`/opt/pkg/lib` or `/opt/homebrew` dylibs) produces a binary that only runs where
153-
those libraries exist. An official build links only the OS's own libraries, so the
154-
binary is portable across machines of the same OS/arch.
155-
156-
To embed a specific Node, run the script *with* that Node
157-
(`~/.asdf/installs/nodejs/24.18.0/bin/node scripts/build-sea.mjs`).
158-
159-
Everything lands under a per-platform tag dir (the same tuple the test harness uses),
160-
so builds for different OS/arch/Node coexist on a shared/NFS `build/` tree without
161-
colliding. Set `CLODE_CLAUDE_BIN=/path/to/claude` to have the build additionally boot
162-
the real bundle once as a deep self-check.
163-
164-
### Fusing native binaries (`clode build`)
165-
166-
Two subcommands fuse stand-alone native binaries from the pinned txiki.js
167-
runtime (`build/tjs/tjs`, built by `scripts/build-tjs.mjs`; override with
168-
`CLODE_TJS`). Both artifacts run with **no Node at all** on the machine:
169-
170-
```sh
171-
clode build [--out PATH] # fuse a "quaude" (default ./quaude):
172-
# the extracted Claude Code bundle compiled to
173-
# quickjs bytecode + the node-shim runtime
174-
clode build --self [--out PATH] # fuse a native clode builder (default ./clode-native):
175-
# clode's own launcher + everything `clode build`
176-
# needs, so the BUILDER itself needs no Node
81+
npm run test:online # also the network/model tests (needs a logged-in ~/.claude)
17782
```
17883

179-
`clode build --self` embeds the esbuilt launcher from the newest
180-
`build/*/clode-main.bundle.cjs` (produce it with
181-
`node scripts/build-sea.mjs --bundle-only`; override with `CLODE_MAIN_BUNDLE`).
182-
The resulting `./clode-native` answers `--clode-version`/`--clode-help` and can
183-
itself run `clode-native build` to fuse a quaude. Every fuse self-verifies
184-
before reporting success (an offline canned Messages round-trip plus
185-
`--quaude-attest` manifest verification for quaude; version/help smokes for the
186-
builder). Fused binaries are derived work: they are fused locally and never
187-
distributed.
84+
The PTY/TUI tests drive clode under a pseudo-terminal; the harness
85+
self-installs into `test/.harness/<platform-tag>/` on first run. On Linux
86+
that first run compiles `node-pty` from source (needs `python3`, `make`, a
87+
C++ compiler) and can sit quiet for a few minutes — it is not hung.
88+
89+
Building the pieces from source:
90+
91+
- `node scripts/build-tjs.mjs` — the pinned, patched txiki.js runtime
92+
(`build/tjs/tjs`). Pins in `spike/quickjs/PINS.md`; portability fixups
93+
apply themselves with content verification.
94+
- `clode build --self` — fuse the native builder itself (embeds the
95+
esbuilt launcher from `node scripts/build-sea.mjs --bundle-only` and the
96+
pristine tjs template, so the result needs nothing on disk).
97+
- `node scripts/build-sea.mjs` — the transitional single-file
98+
[Node SEA](https://nodejs.org/api/single-executable-applications.html)
99+
(the `-node`-tagged release assets; Windows's only path today). Run it
100+
with an official, non-stripped Node >= 24 — the SEA embeds whichever
101+
`node` runs the script, and a stripped or non-system-lib node produces a
102+
broken or non-portable binary.

0 commit comments

Comments
 (0)