zeekayandHanzo Dev b455fe3138 one installer, three names — generate /install instead of committing it twice
`public/install` was a byte-identical copy of `public/install.sh`, added because
hanzo.ai/install.sh fetches the extensionless path and a 404 there is silent
(curl -f writes nothing and exits 22; sh reading an empty script exits 0; the
documented one-liner reports success and installs nothing). The reason is right.
The mechanism was 328 duplicated lines held together by a sentence in a commit
message saying the two must stay identical.

scripts/build-polyglot.js already reads public/install.sh to build the polyglot,
so it writes dist/install from the same string it already has. One source, three
published faces — `/`, `/install.sh`, `/install` — and the Dockerfile `cmp`s the
last two so "identical" is checked rather than promised.

Also asserted there: dist/install opens with #!/bin/sh and parses under dash. It
is piped into sh by a caller in another repo, so the shell that must accept it is
not the one whoever edits it will test with.

Verified: clean rebuild, all four polyglot asserts, cmp, every served path 200
(/, /install, /install.sh, /cli, /mcp, /dev, /desktop, /bot, /node, /full,
/llms.txt) and a mistyped path still 404s; `curl /install | sh -s -- --help`
prints the installer usage.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-03 18:03:23 -07:00
2024-11-11 12:49:20 +00:00
2026-02-14 05:26:47 -08:00

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.

S
Description
Mirrored from git.hanzo.ai
Readme MIT
1.2 MiB
Languages
TypeScript 86.5%
Shell 8.6%
JavaScript 2.6%
HTML 1.2%
CSS 1.1%