Hanzo Chat (SwiftUI)
Native streaming AI chat — @Observable, AsyncThrowingStream, Hanzo /v1.
Live demo — none. SwiftUI has no web target and cannot be honestly demoed in a browser, so there is no swiftui-chat.hanzo.app page pretending otherwise.
What you get
URLSession.bytes → AsyncThrowingStream<String> so the reply lands token by
token with structured cancellation, @Observable config passed through the
environment, and the SSE parser split out as nonisolated static precisely so
the tests can hit it with no network and no key.
Run it
brew install xcodegen
xcodegen generate
open *.xcodeproj # ⌘R to run, ⌘U to test
Building for iOS — read this first
Our runner fleet cannot produce an iOS build today. Two separate gaps, both measured rather than assumed:
- No macOS runner exists. An archive / IPA needs macOS + Xcode + a signing
identity. Every runner registered to
hanzoai(519 of them) reportsos: linux;luxfihas 151, same;zooaihas none. The only macOS builds in the org today (hanzoai/worldbuild-desktop.yml) run on GitHub-hostedmacos-14, which is what the house CI rule exists to avoid. hanzo-templatesis not in the arcd org list.arcdserveshanzoai, luxfi, zooai, parsdao, zenlm. Until this org is added, even the Linux jobs inhanzo.ymlsitqueuedwith no runner to claim them.
A third gap turned up while wiring this and is already fixed: this org
defaulted GITHUB_TOKEN to read, and hanzoai/ci declares
permissions: packages: write. A caller cannot be granted more than the org
maximum, so every run died as startup_failure before a job was even created —
no logs, no annotation, nothing to read. The org now defaults to write, the
same as hanzoai, and runs reach queued. If you fork these into another org
and see startup_failure with an empty log, check
/orgs/<org>/actions/permissions/workflow first.
So hanzo.yml declares only what a Linux arc runner could run, and the
macOS archive sits in a separate workflow_dispatch-only
.github/workflows/ios.yml — a job pinned to a label nothing advertises would
queue forever if it fired on push.
Both gaps close with the installer, no code change:
# (2) serve this org — re-run on any existing arcd host
~/work/hanzo/arc/scripts/install-arcd.sh \
--labels self-hosted,linux,amd64 \
--orgs hanzoai,luxfi,zooai,parsdao,zenlm,hanzo-templates
# (1) add the macOS lane — on an Apple Silicon Mac, once
xcode-select --install && sudo xcodebuild -license accept
~/work/hanzo/arc/scripts/install-arcd.sh \
--labels self-hosted,macos,arm64,xcode \
--orgs hanzoai,luxfi,zooai,parsdao,zenlm,hanzo-templates
Then runs-on: [self-hosted, macos, arm64, xcode] resolves and ios.yml
archives + exports the IPA. Signing material comes from KMS
(kms.hanzo.ai), never from a checked-in .p12.
CI
hanzo.yml + a seven-line .github/workflows/cicd.yml importing
hanzoai/ci. On every push a Linux arc runner runs:
- parse —
swiftc -parse -swift-version 6 $(find Sources Tests -name '*.swift')
.github/workflows/ios.yml holds the macOS archive job and is
workflow_dispatch only — see above.
Upstream
Derived from hand-written; project generated by yonaskolb/XcodeGen (MIT). This template is MIT; the upstream licence travels with the code it came from.