hanzoai/dev went public defaulting to someone else's cloud. Four things were
wrong, and all four now have a test that fails if they come back.
DEFAULT PROVIDER AND MODEL. built_in_model_providers() gains `hanzo` -- the
Hanzo Cloud at api.hanzo.ai/v1, Responses wire, bearer from HANZO_USER_KEY --
and it is the default. The default model is zen5-coder. This was not cosmetic:
the old default is not in the gateway catalog, so it 400s against our own
cloud. Measured, not assumed:
POST api.hanzo.ai/v1/responses model=gpt-5-codex -> 400 "model is not
available. Use GET /v1/models to list available models"
POST api.hanzo.ai/v1/responses model=zen5-coder -> 200, clean output
Our own CLI already documented the bug from the other side -- dev.rs says
"Name the model too -- codex's built-in default is not in the gateway catalog
and would 400" and passes `-c model=` on every launch to work around it. It
also asserts that on the native gateway NO model_provider override is needed,
which is only true once `hanzo` is the built-in default. It is now.
zen5-coder over enso because dev is a coding agent and because enso returns
system-prompt text on the Responses wire that dev actually speaks; zen5-coder
returns the answer. Model ids were read from GET /v1/models with a bearer, not
guessed. Other providers stay fully configurable -- this is the default, not
the only choice.
THE LOGIN COMMAND. Messages said `code login` / `codex login`. The real command
is `hanzo auth login` (`hanzo login` is not a command -- it is swallowed as an
AI task). It now lives once, as auth::LOGIN_COMMAND, so no message can drift
into naming a command that does not exist. References to this binary's own
subcommand became `dev login`.
A BINARY NAMED dev. HEAD built `code` and `codex` and nothing named `dev`, so a
release cut today would ship no `dev` -- and `hanzo code` launches a bare `dev`
off PATH, so every new install would break. `dev` is now the canonical bin,
declared first; `code` remains as an alias to the same program, never the
reverse. The CLI identifies as `dev` / "Hanzo Dev", not "OpenAI Codex".
OUR NAMESPACES. The pipeline published to @just-every/* on npm and pushed
formulae to just-every/homebrew-tap. Both of ours already exist and are already
populated at v0.6.91 -- @hanzo/dev plus all five @hanzo/dev-<target> packages,
and hanzoai/homebrew-tap's Formula/hanzo-dev.rb, which installs `dev` and
expects assets named dev-<triple>. Nothing here is squatted; this is our own
distribution, reclaimed. Assets are renamed to match the formula.
Two live supply-chain bugs fell out of that, both worse than a naming problem:
postinstall.js (runs on every npm install) and the tui auto-updater fetched
from a third party's releases -- the updater also told our users to
`npm install -g @just-every/code@latest`. Worse, a shadowed `isWSL` const put
the two fast paths in the temporal dead zone, so their catch blocks swallowed
the error and EVERY install fell through to that download: the five published
platform packages were never used, and the third-party fetch was not an edge
case but the only path that ran. Fixed and exercised in a sandbox across all
three paths. codex-cli/.pack/ -- a committed `npm pack` artifact CI
regenerates, and the reason the bad URL had two homes -- is now untracked.
DURABILITY, because upstream-merge.yml merges openai/codex every 30 minutes.
A one-time edit to a default is a suggestion that survives until the next
merge. Two mechanisms:
- .github/merge-policy.json prefer_ours_globs listed only codex-rs/** while
the workspace that SHIPS is code-rs/**, so it protected nothing that
ships. The identity-bearing code-rs files are now listed.
- code-rs/core/tests/hanzo_identity.rs asserts all four properties -- the
provider, a Zen default, a bin named dev, and no third-party publish
target. Upstream has no such file, so a merge cannot conflict with it or
carry the guard away with the thing it guards. Policy can be edited;
a red build cannot be ignored.
The gate is not decorative: it failed on the un-retargeted pipeline
("release.yml still references `@just-every/`") and went green only when the
pipeline was actually fixed.
Verified: cargo build --bin dev clean; hanzo_identity 4/4; code-core lib
332 passed, 1 failed -- git_info::test_collect_git_info_with_remote, which
fails identically on a clean origin/main checkout here because this machine
has a global [email protected]:.insteadof rewrite. Pre-existing and
environmental, not from this change.
$ dev exec "say OK" # fresh profile, no config
Hanzo Dev v0.0.0
model: zen5-coder
provider: hanzo
Co-authored-by: Hanzo Dev <[email protected]>
Hanzo Dev
Hanzo Dev is our coding agent. It runs in your terminal, reads and edits the
repository you point it at, runs commands in a sandbox, and drives a browser
when a task needs one. Models are served by Hanzo AI —
enso and the zen5 family — over the metered gateway at api.hanzo.ai.
It ships inside the Hanzo CLI. hanzo dev is the command.
![]() A session in progress |
![]() Reviewing a diff |
|---|---|
![]() Driving a browser |
![]() Several agents on one task |
Install
curl -fsSL https://hanzo.sh | sh
hanzo auth login
hanzo auth login signs you in through Hanzo IAM and links the machine to your
account. Then, from any repository:
hanzo dev
Give it the task on the command line to run headless instead:
hanzo dev "fix the failing tests in ./core and explain what was wrong"
Choosing a model
Model ids come from the gateway, which is the only authority on the catalog — there is no allowlist in the client.
hanzo dev --model enso # our frontier model
hanzo dev --model enso-ultra # the largest reasoning tier
hanzo dev --model zen5-coder # tuned for code
Browse everything available with curl https://catalog.hanzo.ai/v1/models.
Backends
Hanzo Dev is the default and the one we build. The same session launcher can also drive two other agents if you already have them installed, so you can keep one set of habits across all three:
hanzo dev # our agent (default)
hanzo dev claude # or: hanzo code --claude
hanzo dev codex # or: hanzo code --codex
hanzo dev is a spelling of hanzo code dev, not a second implementation —
every spelling resolves through the same launcher.
Options
hanzo dev [OPTIONS] [BACKEND|TASK] [TASK] [-- <PASSTHROUGH>...]
--model <MODEL> Gateway model id, e.g. enso, enso-ultra, zen5-coder
--backend <NAME> dev (default) | claude | codex
--brand <BRAND> Tenant for auth: hanzo | lux | zoo | pars | bootnode
--ask Ask before each action instead of auto-approving (alias: --safe)
--no-sandbox Drop the sandbox and auto-approve. Per-invocation, never persisted
--no-route Call the backend's own model account instead of the metered gateway
--no-mcp Do not attach the Hanzo MCP toolset
--project-mcp Also load the repo's own .mcp.json servers (off by default — a repo is untrusted)
--link / --no-link Stream the session to Hanzo cloud, or never
--resume <ID> Resume a prior linked session by its cloud session id
-c, --config <FILE> Use a specific config file
-v, --verbose Increase logging verbosity
Anything after -- is passed verbatim to the backend.
Two defaults worth knowing. Sessions run sandboxed and auto-approve inside that
sandbox; --ask tightens it, --no-sandbox removes it. Model calls route
through api.hanzo.ai so usage is metered on your Hanzo account; --no-route
sends them to the backend's own account instead.
In a session
Type / for the full list. The ones you will reach for:
/plan create a comprehensive plan (multiple agents)
/solve solve a challenging problem (multiple agents)
/code perform a coding task (multiple agents)
/auto work autonomously on long tasks with Auto Drive
/agents create and configure agents
/browser open the internal browser
/chrome connect to a running Chrome over CDP
/diff show the git diff, including untracked files
/review review your changes for potential issues
/undo restore the workspace to the last snapshot
/branch work on a branch in a worktree
/merge merge the worktree branch back to the default
/model choose model and reasoning effort
/reasoning change reasoning effort (minimal/low/medium/high)
/theme switch color themes
/status session configuration and token usage
/limits weekly and hourly rate limits
/mcp manage MCP servers (status/on/off/add)
/init write an AGENTS.md for this repository
/resume resume a past session for this folder
/new start a new chat
Full list with descriptions: docs/slash-commands.md.
Project context
Run /init in a repository and Hanzo Dev writes an AGENTS.md describing what
it found. Edit that file — it is read at the start of every session in that
directory, so it is where project conventions, architecture notes and "do not
touch this" rules belong.
Tools
The Hanzo MCP toolset is attached by default: filesystem, shell, browser, and
the rest of the Hanzo surface. Add your own servers with /mcp add, or per
repository in .mcp.json — the latter is off unless you pass --project-mcp,
because a repository you just cloned should not get to run a server with your
session's key.
Documentation
Building from source
git clone https://github.com/hanzoai/dev.git
cd dev
./build-fast.sh
./build-fast.sh is the required check — it must pass cleanly, warnings
included. See DEVELOPING.md and LLM.md for the
workspace layout and the rules that apply inside it.
Contributing
Branch, make the change, make ./build-fast.sh pass, open a pull request.
Bugs and feature requests: github.com/hanzoai/dev/issues.
License
Apache-2.0 — see LICENSE.
Lineage
Hanzo Dev is a fork of just-every/code, which is
itself a fork of openai/codex. Both are Apache-2.0,
and this repository preserves the upstream LICENSE and NOTICE. Hanzo Dev is not
affiliated with, sponsored by, or endorsed by either project.




