Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions CLOUD-SESSIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Cloud coding sessions

`hanzo --cloud` runs work on Hanzo's Go cloud coding service. The Rust CLI submits
the task and returns a session ID. Closing the terminal does not stop the run.
Ordinary `hanzo` runs locally; its cloud session stream is remote observation,
not remote execution.

`--metered` selects Hanzo's metered models for a local session. This replaces
the old `--cloud` model-routing spelling: `--cloud` now means remote execution.

```sh
git push -u origin HEAD
hanzo --cloud "Fix the flaky cache test and run the suite 30 times"
hanzo --cloud "Check the API documentation against the server" --watch
hanzo --cloud --repo github.com/acme/api --base main --mode plan "Explain the cache"
hanzo --cloud # list coding sessions
hanzo --cloud --resume SESSION_ID # inspect status and recent events
hanzo --cloud --resume SESSION_ID --watch
hanzo -p "Add regression tests" --cloud SESSION_ID
hanzo --teleport SESSION_ID
```

`hanzo code --cloud` accepts the same flags. `--claude` and `--codex` select a
cloud harness; the default is Hanzo's `dev` agent. Availability and connected
accounts are checked by the service. `--model` names a model for harnesses that
support it. `--mode plan` reads without pushing; `--mode setup` inspects the
repository's environment. The normal mode is `build`.

Without `--repo`, the CLI reads origin and the current branch, refuses known
unpushed commits or a missing upstream, and warns about uncommitted files.
Only pushed files reach the sandbox. GitHub and Hanzo forge origins are supported;
there is no local repository bundle upload. An explicit `--repo` targets that
remote directly and does not upload or inspect the local checkout.

Follow-up tasks require a finished or paused run. They use the service's `after`
field to continue from prior work on a new branch. This CLI does not currently
redirect a running cloud sandbox. Ctrl-C while watching only detaches the viewer.
The terminal shows recent events; the browser session holds the transcript.

`--teleport` checks the repository identity and clean working tree, fetches the
session branch, and creates `cloud/SESSION_ID`. It never forces a checkout or
overwrites an existing branch. The transcript remains linked in the browser;
native harness conversation import is not implemented.

Cloud runs use the authenticated identity from `hanzo auth login`. Repository
access, environments, sandbox isolation, credentials, execution limits and pull
request creation are enforced by the service. An accepted session means queued
or started, not successfully completed: use `--watch` and inspect its result.
An error result exits nonzero.

Existing resource commands expose the supporting services:

```sh
hanzo provider github user get # connection status
hanzo provider github user connect --help # connect your GitHub identity
hanzo provider github installations # repository installations
hanzo environment list
hanzo environment set --help
hanzo agent coding changes SESSION_ID
hanzo agent coding artifacts SESSION_ID
hanzo agent sessions pause SESSION_ID
hanzo agent sessions stop SESSION_ID
hanzo auto automations --help
```

## Verification and remaining parity work

The CLI workspace tests and spec derivation gates pass. A live read-only run,
`sess_c5ef4906c227756ab6055b729d0f51b8`, cloned GitHub, executed the agent, and
completed successfully. Live session listing, completed-session inspection,
GitHub connection status, and environment listing also answered successfully.

The delegated-identity 402 failure found during live testing is fixed in production
(API v8.5.838 and later). IAM's confined inference token carries a validated
billing organization even though its role is deliberately limited to member.
The API now preserves that validated organization without granting admin access.
A production cloud completion test passed after deployment. Token login and a
local dev task that writes and verifies a file also passed against production.
See [E2E.md](E2E.md) for repeatable source and public-installer checks.

Still unimplemented here: uploading a local repository bundle, importing the
native harness conversation into a local session, and delivering follow-up
instructions to a running cloud sandbox. Scheduling, environment configuration,
pause/stop, PR creation/merge, browser/mobile handoff, and CI auto-fix were not
verified end to end in this change. Published API routes alone do not prove those
workflows.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hanzo-cli"
version = "8.5.751"
version = "8.5.752"
edition = "2021"
authors = ["Hanzo AI"]
description = "Unified CLI for Hanzo AI development tools"
Expand Down
21 changes: 21 additions & 0 deletions E2E.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CLI end-to-end checks

`make test` runs the Rust workspace, command/parser checks, installer fixtures and API-spec drift checks. Live checks are opt-in: unit tests alone do not prove production works.

Run the production checks using your existing login:

```sh
HANZO_E2E_TOKEN="$(hanzo auth token)" make e2e
```

This exercises token login through stdin, identity, authenticated usage JSON, a local `dev` task that writes and verifies a file in a temporary Git repository, and a read-only cloud task that clones a real repository and completes inference. It requires `dev` on PATH. The local and cloud tasks consume normal usage; the cloud test leases a sandbox. It does not log out your existing account or modify the source repository.

Test the public installer and its actual downloaded binaries:

```sh
HANZO_E2E_TOKEN="$(hanzo auth token)" make e2e-installed
```

The installer runs in a temporary directory, verifies release checksums, and installs `hanzo`, `hanzo-node`, `dev`, `gen`, and MCP. Tests use that directory first on PATH. It leaves your normal installation intact. A missing token is an error, and every coding test must actually complete; HTTP errors and a missing output file fail the run.

The tests cover the machine and platform on which they run. They do not replace macOS/Windows installation checks or interactive browser OAuth testing. Token login uses a real existing IAM session; it does not simulate a fresh browser sign-in.
6 changes: 3 additions & 3 deletions LLM.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ hanzo "fix the test" bare session, default backend

**Every other agent is one file**, `gen:src/agents/<name>.rs`: its names,
binary, npm package (`hanzo upgrade <name>` installs it under `~/.hanzo/bin`),
`routable` (its model calls can go through api.hanzo.ai under `--cloud`), `toolset`
`routable` (its model calls can go through api.hanzo.ai under `--metered`), `toolset`
(`Never` / `Always` / `Routed`, when it reads a home of Hanzo's own), `build` (the
argv, env and files of one run, through `Run`) and `read` (its output on a linked
run, through `Reader`). No agent reads another's options; `agents/wire.rs` holds only
Expand All @@ -206,7 +206,7 @@ launcher of the same session path.

**Routing is direct by default** (`--no-route` is gone, being the default). A third-party
tool talks straight to the account it is signed in to: `resolve_routing` returns
`Route::Inherit` and touches no env. `--cloud` (`Options::cloud`) is the opt-in to
`Route::Inherit` and touches no env. `--metered` (`Options::cloud`) is the opt-in to
Hanzo's metered models (the credential plan: provider key, bearer, stored Hanzo key).
`dev` is ours and its account is Hanzo's, so it routes through the gateway when signed in
without a flag. An agent whose file says `routable: false` (Antigravity, Cursor, Gemini,
Expand Down Expand Up @@ -316,7 +316,7 @@ the default), no dollars for a model it does not name. Claude counts cache token
apart from input and dev/codex inside it (`Tally`, `Ended.apart`). *Metered* is
`GET /v1/usage/summary?range=custom&start&end` for the session window, asked only
for a routed run that reported nothing, and labelled org-wide (it includes other
sessions) and possibly lagging. A run on the backend's own account (the default, no `--cloud`;
sessions) and possibly lagging. A run on the backend's own account (the default, no `--metered`;
Cursor, Antigravity: `resolve_routing` always `Inherit` for those two, and
`External::build` attaches no MCP) says "not observed". The cloud summary is read
tolerantly (`Llm::of`): `cacheReadTokens`, `cacheWriteTokens`, `cachedShare` (a
Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,11 @@ build: ## The shipped binary.

lint:
@cargo clippy --locked --all-targets -- -D warnings

.PHONY: e2e e2e-installed
e2e: ## Real login, usage, local dev and cloud sessions (requires HANZO_E2E_TOKEN).
@test -n "$${HANZO_E2E_TOKEN:-}" || { echo 'Set HANZO_E2E_TOKEN using hanzo auth token'; exit 1; }
@cargo test --locked --test production -- --ignored --nocapture --test-threads=1

e2e-installed: ## Install published tools in isolation and test production end to end.
@sh scripts/e2e-installed.sh
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,29 @@ streams live to mission-control. Auto-approve is on by default; the repo's own
Plain `hanzo dev` runs our own Hanzo Dev agent — `curl -fsSL https://hanzo.sh | sh`
installs it. Another tool is a flag: `--claude`, `--codex`, `--cursor` (`--agent`) or
`--agy`. A third-party tool talks straight to the account it is already signed in to;
`--cloud` runs it on Hanzo's metered models instead. Hanzo Dev's account is Hanzo's, so
`--metered` runs it on Hanzo's metered models instead. Hanzo Dev's account is Hanzo's, so
it uses the cloud when you are signed in.

```bash
hanzo dev "port this module to async" # our own agent, headless on that task
hanzo dev --claude "fix the failing test" # Claude Code, on your own Claude account
hanzo dev --claude -- -c # args after `--` go to the tool
hanzo dev --codex --cloud "…" # Codex on Hanzo's metered models
hanzo dev --codex --metered "…" # Codex on Hanzo's metered models
hanzo dev --model enso-ultra "refactor the auth middleware"
hanzo dev --resume <session-id> # continue a prior session
hanzo dev --ask "…" # confirm each action (alias: --safe)
hanzo dev --no-link "…" # keep it local, don't stream to cloud
```

`hanzo code` is the code index (`search`, `index`, `context`, `file`, `tree`, `ask`),
not a launcher. `hanzo code …` and `hanzo run …` as launchers are gone: they answer
with the `hanzo dev` line to use.
`hanzo --cloud "task"` executes remotely in a Hanzo sandbox and returns a session
ID. Add `--watch` to follow progress; closing the terminal leaves the cloud run
working. `hanzo --cloud` lists runs, and `hanzo --teleport SESSION_ID` fetches a
finished run's branch. See [Cloud coding sessions](CLOUD-SESSIONS.md) for setup,
follow-ups, and the supported workflow.

`hanzo code` also serves the code index (`search`, `index`, `context`, `file`,
`tree`, `ask`). Its task form forwards to `hanzo dev`; `hanzo code --cloud` uses
the same remote execution path.

Enso and Zen models (`enso`, `enso-flash`, `enso-pro`, `enso-ultra`, `zen6`, …) are Hanzo's own
family; the gateway is the sole authority on the model catalog.
Expand Down
14 changes: 14 additions & 0 deletions scripts/e2e-installed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
set -eu
: "${HANZO_E2E_TOKEN:?Set HANZO_E2E_TOKEN using hanzo auth token}"
e2e_dir=$(mktemp -d)
trap 'rm -rf "$e2e_dir"' EXIT HUP INT TERM
curl -fsSL https://hanzo.sh -o "$e2e_dir/install.sh"
sh "$e2e_dir/install.sh" --dir "$e2e_dir/bin" hanzo dev gen mcp
for tool in hanzo hanzo-node dev gen hanzo-mcp; do
"$e2e_dir/bin/$tool" --version
done
[ "$("$e2e_dir/bin/hanzo" --version)" = "$("$e2e_dir/bin/hanzo-node" --version)" ]
PATH="$e2e_dir/bin:$PATH" HANZO_E2E_BIN="$e2e_dir/bin/hanzo"
export PATH HANZO_E2E_BIN
cargo test --locked --test production -- --ignored --nocapture --test-threads=1
Loading