* infra: standardize ZAP duplex port to 9999 ZAP binary protocol duplex RPC standardizes on :9999 across every service. Lux validator staking/RPC ports (9630/9631 mainnet, 9650/9651 devnet) are unchanged — those are luxd network protocol ports, not ZAP. One ZAP port everywhere (was a mix of 9651/9652/9653/9633/9900). * ci: upstream-sync workflow — auto-merge clean, issue on conflict Periodic sync from just-every/code (the canonical upstream Hanzo dev tracks). Every 6h: fetches upstream, attempts merge, opens PR with automerge label if clean, otherwise opens an issue listing conflicting paths. Bot does not resolve content conflicts. * ci: upstream-sync drafts only, one workflow (drop upstream-merge) - delete upstream-merge.yml (1106 lines, auto-merge, polled every 30 min) in favour of single upstream-sync workflow - upstream points to openai/codex (matches LLM.md), not just-every/code - weekly cron Mon 06:00 UTC (was every 6h) - branch named upstream-sync/<UTC-date> - always opens draft PR, never auto-merges - on conflict, commits markers in place and opens draft PR labelled conflict so the branch is checkoutable for human resolution - LLM.md documents the new flow One way: there is now exactly one upstream-sync entry point.
10 KiB
Hanzo Dev
Fork of OpenAI Codex CLI. Rust-based AI development assistant in the terminal.
- Repo: https://github.com/hanzoai/dev
- Upstream: https://github.com/openai/codex
Stack
- Rust 2024 edition (workspace of ~50 crates)
- TUI via Ratatui 0.29.0
- MCP protocol (server/client/types)
- npm package:
@hanzo/dev(platform-specific binaries via optionalDependencies)
Directory Structure
/Users/z/work/hanzo/dev/
├── codex-rs/ # Rust workspace (main source)
│ ├── cli/ # CLI entrypoint
│ ├── core/ # Business logic, config, auth
│ ├── tui/ # Terminal UI (Ratatui)
│ ├── tui2/ # Next-gen TUI
│ ├── exec/ # Command execution with sandboxing
│ ├── exec-server/ # Execution server
│ ├── protocol/ # Shared protocol definitions
│ ├── mcp-server/ # MCP server
│ ├── mcp-types/ # MCP type definitions
│ ├── login/ # OAuth login flow
│ ├── config/ # Configuration
│ ├── app-server/ # App server
│ ├── linux-sandbox/ # Linux sandboxing
│ ├── ollama/ # Ollama integration
│ ├── lmstudio/ # LM Studio integration
│ └── ... # ~50 total crates
├── codex-cli/ # Legacy TypeScript CLI (deprecated)
├── hanzo-node/ # npm wrapper package
├── hanzo-dev/ # Alt build target
├── tests/ # Integration tests
└── .github/ # CI workflows
Key Crates
| Crate | Purpose |
|---|---|
cli |
CLI binary, arg parsing |
core |
Auth, config, model providers, inference |
tui |
Ratatui terminal interface |
exec |
Sandboxed command execution |
protocol |
Wire protocol definitions |
mcp-server |
MCP server implementation |
login |
OAuth flow for hanzo.id and OpenAI |
hooks |
Hook engine (session-start, stop, after-agent, after-tool-use) |
skills |
Skill discovery, loading, and marketplace |
app-server |
WebSocket/stdio app server for IDE integration |
otel |
OpenTelemetry tracing and metrics |
Auth Modes
| Mode | Token Source | Display |
|---|---|---|
ApiKey |
HANZO_API_KEY / OPENAI_API_KEY env |
"API key (...xxxxx)" |
ChatGPT |
OpenAI OAuth JWT | "Logged in as [email]" |
Hanzo |
hanzo.id Casdoor JWT | "Logged in to Hanzo as [email]" |
Default provider: hanzo at https://api.hanzo.ai/v1
Commands
# Build (codex-rs workspace)
cargo build --manifest-path codex-rs/Cargo.toml --release -p codex-cli
cargo check --manifest-path codex-rs/Cargo.toml
# Build (hanzo-dev workspace)
cargo build --manifest-path hanzo-dev/Cargo.toml --release -p hanzo-dev
# Fast dev build
./build-fast.sh
# Test
cargo test --manifest-path codex-rs/Cargo.toml --all
just test # uses cargo-nextest
# npm package
npm install -g hanzo-node
npx hanzo-node
hanzo "explain this code"
# Format / Lint
cargo fmt
cargo clippy
# Justfile recipes
just codex [args] # Run codex from source
just mcp-server-run [args] # Run MCP server
just write-config-schema # Regenerate config.toml schema
just write-app-server-schema # Regenerate app-server protocol schema
just write-hooks-schema # Regenerate hooks schema
just log [args] # Tail state SQLite logs
Build Profiles
- dev: Incremental compilation, fast iteration
- release: Full LTO, symbol stripping
- Workspace lints:
unwrap_used = "deny",expect_used = "deny"
Merge Strategy (from upstream)
Upstream is openai/codex. Sync is automated via .github/workflows/upstream-sync.yml
(weekly, Mon 06:00 UTC, also workflow_dispatch). The workflow:
- fetches
upstream/main - merges into a fresh
upstream-sync/<UTC-date>branch - opens a draft PR — never auto-merges
- on conflict, commits the merge with conflict markers in place and opens a draft PR
labelled
upstream-sync,conflictlisting the paths
There is exactly one upstream sync workflow. Do not add a second.
Manual resolution recipe when CI flags a conflict:
git fetch origin && git checkout upstream-sync/<date>- resolve conflicts; common areas:
justfile,package.json, hooks, TUI module names - upstream renames to watch:
multi_agents→collab,HookResult→HookOutcome cargo check --manifest-path codex-rs/Cargo.toml- fix any hanzo-dev compile errors that depend on codex-rs types
git push --force-with-lease && gh pr ready
Remotes:
origin—[email protected]:hanzoai/dev.gitopenai—/Users/z/work/openai/codex(local mirror, dev-only convenience)upstream—https://github.com/openai/codex.git(canonical sync source)
npm Distribution
hanzo-node/ provides platform-specific binaries:
hanzo-node-darwin-arm64,hanzo-node-darwin-x64hanzo-node-linux-x64-musl,hanzo-node-linux-arm64-muslhanzo-node-win32-x64
Binary resolution: user cache -> optionalDependency package -> GitHub release download.
Config
Primary config home: ~/.hanzo (legacy ~/.code/~/.codex still read).
Zero Trust SDK (hanzo-zt)
Crate at hanzo-dev/zt/ providing ZT overlay networking with ZAP transport.
Architecture
App → ZAP Client → ZT Transport → ZT Fabric → ZT Service
↓ ↓
Cap'n Proto RPC x509 mTLS overlay
(zero-copy binary) (NAT traversal built-in)
Auth Flow
- Hanzo IAM JWT (from
HANZO_API_KEYenv or~/.hanzo/auth.json) - JWT → ZT controller ext-jwt auth (
/edge/client/v1/authenticate?method=ext-jwt) - Controller returns ZT session token
- Commerce API balance check (no free tier)
- Session used to dial/bind services
Key Types
| Type | Module | Purpose |
|---|---|---|
ZtContext |
context.rs |
Main entry: authenticate, dial, listen, services |
Config / ConfigBuilder |
config.rs |
Controller URL, credentials, billing, timeouts |
HanzoJwtCredentials |
auth.rs |
Resolves JWT from env/file, implements Credentials |
BillingGuard |
billing.rs |
Balance check + usage recording (no free tier) |
ZtTransport |
transport.rs |
ZAP Transport trait impl (feature-gated zap) |
ControllerClient |
controller.rs |
REST client for /edge/client/v1 |
ZtConnection |
connection.rs |
AsyncRead + AsyncWrite over channels |
Features
zap(default) — ZAP Transport trait impl, depends onzap-schematunnel— Reserved for future hanzo-tunnel integration
CLI Integration
hanzo-dev/cli/src/cloud.rs has #[cfg(feature = "zt")] branch:
- URLs starting with
zt://use ZtContext.dial() instead of WebSocket - Feature
zt = ["dep:hanzo-zt"]in cli's Cargo.toml
Testing
cargo check -p hanzo-zt # 0 warnings
cargo test -p hanzo-zt # 9 tests (auth, config, controller, doctest)
Cross-Language SDK Suite
All SDKs follow the same pattern (ZT REST API + ZAP framing + Hanzo IAM + billing):
| Language | Location | Status |
|---|---|---|
| Rust | hanzo-dev/zt/ |
9 tests pass, 0 warnings |
| Go | ~/work/hanzozt/sdk-golang/{zap,auth/hanzo,billing}/ |
5 tests pass (fork deps need module path fix) |
| TypeScript | ~/work/hanzozt/zt-sdk-nodejs/src/{zap,auth,billing}/ |
Complete |
| Python | ~/work/hanzozt/zt-sdk-py/hanzozt/{zap,auth,billing}/ |
11 tests pass |
| C++ | ~/work/hanzozt/zt-sdk-cpp/ |
Builds clean (CMake + libzt) |
| C | ~/work/hanzozt/zt-sdk-c/{includes/zt/zt_zap.h,library/zt_zap.c} |
Syntax checks pass |
ZAP zt:// scheme registered at ~/work/zap/zap/src/transport.rs (7 tests pass, feature-gated).
Documentation Site (zt-docs)
Full docs app at ~/work/hanzo/docs/apps/zt-docs/ → zerotrust.hanzo.ai
- 16 static pages: landing + 12 docs pages + sitemap + 404
- ~4,900 lines of documentation across 12 MDX files
- SDK docs: Rust (436L), Go (902L), TypeScript (908L), Python (606L), C++ (587L), C (655L)
- Core docs: Overview, Getting Started, Architecture, Integration
- Build:
pnpm build --webpack(static export), dev on port 3004 - DNS:
zerotrust.hanzo.aiA →24.199.76.156(hanzo-k8s LB), CF proxied
Known Issues
- Go SDK:
hanzoztfork deps still declareopenzitimodule paths in go.mod - Tunnel feature: path to
hanzo-tunnelcrate TBD (commented out in Cargo.toml) - K8s ingress for
zerotrust.hanzo.ainot yet created (DNS points to LB but no ingress rule)
Rules for AI Assistants
- ALWAYS update LLM.md with significant discoveries
- NEVER commit symlinked files (.AGENTS.md, CLAUDE.md, etc.) -- they are in .gitignore
- NEVER create random summary files -- update THIS file