Two lines of work had to meet. `main` rewrote what hanzo.sh IS — the installer
downloads one prebuilt native binary per tool, checksum-verified, and names the
three tools it cannot fetch instead of substituting a package manager for them.
This branch rewrote how the page is BUILT — @hanzo/ui on @hanzo/gui, with the
48 generated shadcn files, the 27 Radix packages and Tailwind deleted.
Neither is discardable, so the resolution takes both: main's public/install.sh,
its shims, its deploy workflow and its copy; this branch's components, tokens
and shared chrome.
Where they contradicted each other, main's facts win, because the installer is
the thing that is true:
* `| sh`, not `| bash`. The installer is POSIX now and the polyglot declares
#!/bin/sh; publishing `bash` while llms.txt published `sh` is what shipped
`set: Illegal option -o pipefail` to everyone who copied the other half.
* No bundles, no package managers, no uv. `--bundle full|rust|python`, the
pip/uvx/cargo/npm row and the three per-language package panels all describe
an installer that no longer exists. src/site.ts now mirrors install.sh's
TOOLS and unavailable_rows and nothing else.
* Features is deleted rather than restyled. Four invented product claims and
an "innovative container solutions" strapline are template filler whichever
design system draws them; main deleted them and they do not come back.
Packages -> Tools and Bundles -> Unavailable: same two shapes, now rendering
what the installer does.
Co-authored-by: Hanzo Dev <[email protected]>
3.0 KiB
hanzo.sh
The install surface for the Hanzo tools. One command:
curl -fsSL https://hanzo.sh | sh
That downloads one prebuilt native binary per tool, verifies its sha256, and puts it on PATH — no runtime, no package manager, no build step:
| tool | also installed as | source |
|---|---|---|
hanzo |
hanzo-node |
hanzoai/cli |
hanzo-mcp |
mcp |
hanzoai/mcp |
dev |
— | hanzoai/dev |
Each pair is one build, symlinked, so the two names can never be two versions. Re-run to upgrade. One tool at a time:
curl -fsSL https://hanzo.sh/cli | sh
curl -fsSL https://hanzo.sh/mcp | sh
curl -fsSL https://hanzo.sh/dev | sh
This repo
dist/index.html is a polyglot — the same bytes are the landing page in a
browser and the installer under sh. public/install.sh is the installer;
scripts/build-polyglot.js wraps the built HTML in a heredoc and appends it.
Downloading is NOT implemented here. hanzoai/cli/install.sh is the one
implementation of "fetch a Hanzo binary" — platform detection, asset naming,
checksum verification, the second-name symlink — and this drives it once per
tool. Keep it that way; a second copy of platform detection is a second thing to
drift.
The page is Vite + React 19 on @hanzo/ui over the @hanzo/gui backend,
with @hanzo/design tokens (monochrome, dark-default, self-hosted Geist), the
@hanzo/logo mark via BrandMark, and the header/footer content from
@hanzo/products so this property cannot drift from the rest of the estate. No
Tailwind, no shadcn, no Radix. One route. src/site.ts is the page as data —
the install commands, the tools, what is not installed yet — and everything in
src/components/ only renders it.
pnpm install
pnpm dev # vite, :8080
pnpm build # -> dist/, including the polyglot rewrite
pnpm typecheck # tsgo, the native TypeScript compiler
pnpm lint
Test an installer change without deploying, under both published shells:
cd dist && python3 -m http.server 8791 &
curl -fsSL http://127.0.0.1:8791 | sh
curl -fsSL http://127.0.0.1:8791 | bash
Deploying
.github/workflows/deploy.yml builds, publishes the Cloudflare Worker, then
re-fetches https://hanzo.sh and fails if the live bytes are not the bytes it
just built. This host was hand-published for a long time, which is how a merged
fix sat unseen for weeks while curl hanzo.sh | sh kept handing out the old
installer — so verifying the live URL is part of deploying, not a follow-up.
gh workflow run deploy.yml -R hanzo-apps/hanzo.sh --ref main
Run it explicitly. The workflow declares on: push too, but pushes to this repo
are not currently creating runs — measured, cause not established; see
LLM.md. Until that is fixed, a merge is not a deploy, so check:
curl -sS https://hanzo.sh | md5sum
LLM.md has the details, including the unfinished migration to hanzoai/static.