Files
hanzo.sh-native/README.md
zeekayandHanzo Dev d04c728bb5 merge main: the installer's truth, under the design system's page
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]>
2026-08-03 17:45:09 -07:00

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.