# Zoo / Hanzo Desktop Stack Decomposition of the desktop-app architecture so Zoo AI Desktop is a declarative brand variant of Hanzo Desktop with no forked source. ## Repos | Path | Role | Language | |------|------|----------| | `~/work/hanzo/desktop` (`hanzoai/desktop`) | Canonical desktop source. Tauri 2.x + React. | Rust + TypeScript | | `~/work/zoo/app` (`zooai/app`) | Thin pnpm shim. `pnpm build` → `BRAND=zoo` upstream build. | Bash + assets | | `~/work/hanzo/node` | AI agent backend: chat router, MCP server, agent harness, tool runner. | Rust | | `~/work/zoo/node` | Native chain node `zood` (consensus + EVM + AI-mining precompiles). | Go | | `~/work/lux/consensus` | Quasar consensus engine consumed by both nodes. | Go (with Rust FFI) | | `~/work/zoo/logo` | Canonical brand-asset source for `~/work/zoo/app/brand/`. | SVG + PNG | | `~/work/zoo/universe` | This repo. Architecture + ops docs. | Markdown + compose | `zood` and `hanzo-node` are **not interchangeable**. `hanzo-node` is the AI/agent router that the desktop app talks to over local HTTP. `zood` is the chain node (validators + EVM + precompiled AI-mining contract). The desktop ships `hanzo-node` as a sidecar; the chain RPC is remote. ## Brand variants from one source The Hanzo Desktop source supports both Hanzo and Zoo brands via: * `libs/brand-config/` — single `BrandConfig` exported by `getBrand()` * `apps/hanzo-desktop/src-tauri/tauri.conf.{hanzo,zoo}.json` — overlay merged before invoking `tauri build` * `apps/hanzo-desktop/scripts/brand-build.cjs` — pre-merges Tauri config and patches `Info.plist` to fix `CFBundleIdentifier` propagation * `apps/hanzo-desktop/src-tauri/src/local_hanzo_node/hanzo_node_options.rs` — `option_env!("BRAND")` switches initial agent names at compile time * `apps/hanzo-desktop/public/{visor,zoo-logo}.svg` + `{onboarding,zoo-onboarding}.png` — both brands' assets coexist; React picks via `getBrand().brand` ## BrandConfig ```ts interface BrandConfig { brand: 'hanzo' | 'zoo'; name: string; // "Hanzo" | "Zoo" productName: string; // "Hanzo Desktop" | "Zoo Desktop" identifier: string; // com.hanzo.desktop | com.zoo.desktop logo: { light, dark, favicon }; colors: { primary, bg, fg }; hosts: string[]; // hanzo.ai | zoo.ngo, zoo.network storeUrl: { mac, win, ios, android }; // Native chain identity. Mining checkpoints submit to the AI-mining // precompile on the brand's primary EVM/A-chain. network: { rpc: string; // https://rpc.hanzo.network | https://rpc.zoo.network chainId: number; // 36900 hanzo / 200200 zoo token: string; // $AI | $ZOO aiMiningPrecompile: `0x${string}`; // 0x0300...0000 blockExplorer: string; }; // Cloud AI inference (chat completions + embeddings). Distinct from chain RPC. inferenceEndpoint: string; // https://gateway.hanzo.ai // OAuth IAM provider for "Login with ". iam: { baseUrl, clientId, redirectUri, callbackEvent }; } ``` ## Chain IDs | Network | chainId | RPC | |---|---|---| | Hanzo Mainnet | 36900 | https://rpc.hanzo.network | | Hanzo Testnet | 36901 | https://rpc.hanzo-test.network | | Zoo Mainnet | 200200 | https://rpc.zoo.network | | Zoo Testnet | 200201 | https://rpc.zoo-test.network | | Zoo Devnet | 200202 | https://rpc.zoo-dev.network | AI-mining precompile: `0x0300000000000000000000000000000000000000` on each. ## Sidecars | Binary | Purpose | Brand | |---|---|---| | `hanzo-node` | AI agent router, chat, MCP, tool runner | both | | `deno`, `uv` | Tool sandboxes for hanzo-tools-runner | both | **Removed**: `ollama`. Embeddings + LLM inference now go through the cloud inference endpoint or via hanzo-node's built-in embedding (when available). This drops ~62 MB from the bundle and removes a managed sidecar process. ## Build ```sh # Hanzo brand (canonical) cd ~/work/hanzo/desktop/apps/hanzo-desktop npm run build:hanzo # -> Hanzo.app, com.hanzo.desktop # Zoo brand (declarative shim) cd ~/work/zoo/app pnpm build # -> Zoo.app, com.zoo.desktop # Internally: ln -s brand/icons -> upstream/src-tauri/icons/zoo, # then BRAND=zoo VITE_BRAND=zoo npm run build:zoo upstream-side. ``` ## Releases | Brand | Registry | Releases | |---|---|---| | Hanzo | ghcr.io/hanzoai/* | github.com/hanzoai/desktop | | Zoo | ghcr.io/zooai/* | github.com/zooai/desktop | Container registries do not mix per the rule in `~/.claude/CLAUDE.md`. ## Reading order for new contributors 1. `~/work/hanzo/desktop/libs/brand-config/src/index.ts` — the contract 2. `~/work/hanzo/desktop/apps/hanzo-desktop/scripts/brand-build.cjs` — how Tauri configs merge 3. `~/work/zoo/app/scripts/build.sh` — how the shim invokes the upstream build 4. `~/work/hanzo/desktop/apps/hanzo-desktop/src-tauri/src/local_hanzo_node/hanzo_node_options.rs` — how `option_env!("BRAND")` selects the initial agents