*hanzo.txt*  Multi-vendor AI login and provider for Vim and Neovim.

===============================================================================
CONTENTS                                                       *hanzo-contents*

  1. AI Login ................................... |hanzo-ailogin|
    1.1 Commands ................................ |hanzo-ailogin-commands|
    1.2 Vendors ................................. |hanzo-ailogin-vendors|
    1.3 Shared credentials ...................... |hanzo-ailogin-credentials|
    1.4 Headless / SSH .......................... |hanzo-ailogin-headless|
    1.5 Configuration ........................... |hanzo-ailogin-config|
  2. Local-first routing ........................ |hanzo-routing|
    2.1 g:hanzo_route ........................... |g:hanzo_route|
    2.2 Endpoints ............................... |hanzo-routing-endpoints|

===============================================================================
1. AI Login                                                     *hanzo-ailogin*

`:AILogin` is a unified, multi-vendor login. It is NOT vendor-locked: you can
log in with Hanzo ID, ChatGPT, or Claude, or just paste an API key.

It does NOT reimplement OAuth. The OAuth/device-code flows are delegated to the
already-installed `dev` CLI (Hanzo Dev), and the AI provider reads the SAME
credential stores `dev` writes. Log in once and both the CLI and the editor are
authenticated.

-------------------------------------------------------------------------------
1.1 Commands                                           *hanzo-ailogin-commands*

`:AILogin` [{vendor}]                                                *:AILogin*

  With no argument, shows a menu (Enter defaults to Hanzo ID):
    1) Hanzo ID    2) ChatGPT    3) Claude    4) API key    5) Cancel

  With an argument, logs in directly. {vendor} is one of:
    claude | chatgpt | hanzo | apikey
  (the aliases `anthropic`, `openai`/`gpt`, and `api-key` are also accepted).

`:AILogout`                                                         *:AILogout*

  Clears the shared credential stores by running `dev logout`.

`:AIStatus`                                                         *:AIStatus*
`:AIWhoami`                                                         *:AIWhoami*

  Shows the active route (local vs cloud, see |hanzo-routing|), then
  `dev login status` and the active provider (|g:hanzo_provider|). Example: >
      route=local engine http://127.0.0.1:36900 (default) [UP]
      route=cloud provider=openai (cloud https://api.hanzo.ai)
<

`:HanzoLogin`                                                     *:HanzoLogin*

  Back-compat alias for `:AILogin hanzo`.

-------------------------------------------------------------------------------
1.2 Vendors                                             *hanzo-ailogin-vendors*

  Hanzo    Browser/device-code OAuth via `dev login --device-code`.
           Sets |g:hanzo_provider| to "hanzo".

  ChatGPT  OpenAI OAuth via `dev login --chatgpt --device-code`.
           Sets |g:hanzo_provider| to "openai".

  Claude   Prompts (hidden) for an Anthropic API key and stores it via
           `dev login --with-api-key`. Sets |g:hanzo_provider| to "anthropic".
           If you have no key, set $ANTHROPIC_API_KEY instead.

  API key  Prompts (hidden) for an API key for the active provider and stores
           it via `dev login --with-api-key`.

-------------------------------------------------------------------------------
1.3 Shared credentials                             *hanzo-ailogin-credentials*

The provider resolves a credential for the active |g:hanzo_provider| in the
same order the `dev` CLI uses, then sends the correct header per vendor:

  anthropic  $ANTHROPIC_API_KEY -> Claude Code keychain (macOS)
             header: `x-api-key` + `anthropic-version`
  openai     $OPENAI_API_KEY    -> ~/.codex/auth.json
             header: `Authorization: Bearer`
  hanzo      $HANZO_API_KEY     -> ~/.hanzo/auth.json
             header: `Authorization: Bearer`

If nothing resolves, the provider falls back to the existing `api_key` config
so current setups keep working.

Secrets are entered with |inputsecret()| and piped to `dev` over stdin. `dev`
owns the on-disk store (`~/.codex`, `~/.hanzo`, mode `0600`). Nothing is
echoed, logged, or placed on a command line.

-------------------------------------------------------------------------------
1.4 Headless / SSH                                    *hanzo-ailogin-headless*

On a headless or SSH box there is no browser, so the OAuth vendors use the
device-code flow automatically. The code and verification URL render in a
`:terminal` window and the callback completes there.

-------------------------------------------------------------------------------
1.5 Configuration                                       *hanzo-ailogin-config*

                                                                     *g:ai_cli*
`g:ai_cli`                                                  (default: "dev")

  The CLI binary `:AILogin` delegates OAuth flows to. Override to point at a
  different `dev`-compatible binary: >
      let g:ai_cli = 'dev'
<
If `g:ai_cli` is not on $PATH, `:AILogin` falls back to prompting for an API
key, stores it where the provider reads it, and notes that the `dev` CLI is
needed for OAuth logins.

===============================================================================
2. Local-first routing                                          *hanzo-routing*

`:AI` and `:Hanzo` talk to the native local Hanzo engine when it is running and
fall back to your cloud account otherwise -- "native node if running, else
cloud account". The local engine is the OpenAI-compatible server the Hanzo
desktop app spawns and keeps alive (its node manager); hanzo.vim never starts
or stops it. When the engine is up, requests go to it directly with NO auth and
stay on your machine. See the active choice at any time with |:AIStatus|.

By default (no `g:neural` providers configured) hanzo.vim registers the Hanzo
provider as Neural's provider, so `:AI` is local-first out of the box.

-------------------------------------------------------------------------------
2.1 g:hanzo_route                                              *g:hanzo_route*

`g:hanzo_route`                                              (default: "auto")

  auto   Probe the local engine's /health; use it if up, else the cloud
         account. An explicitly chosen cloud vendor (|g:hanzo_provider| set to
         "anthropic"/"openai") with a resolved credential takes precedence, so
         a deliberate cloud choice still wins.
  local  Always the native local engine (no auth).
  cloud  Always the cloud account (resolved credentials). >

      let g:hanzo_route = 'auto'
<
The /health probe is cached for a few seconds so typing does not re-probe the
engine on every keystroke.

-------------------------------------------------------------------------------
2.2 Endpoints                                        *hanzo-routing-endpoints*

                                                            *g:hanzo_local_url*
`g:hanzo_local_url`                       (default: "http://127.0.0.1:36900")
  The native local engine's OpenAI-compatible base URL.

                                                          *g:hanzo_local_model*
`g:hanzo_local_model`                                    (default: "default")
  The model id the local engine serves.

                                                            *g:hanzo_cloud_url*
`g:hanzo_cloud_url`                          (default: "https://api.hanzo.ai")
  The cloud account gateway used on the cloud route. Authenticated with the
  resolved account credentials (see |hanzo-ailogin-credentials|).

                                                         *g:hanzo_llm_gateway*
`g:hanzo_llm_gateway`                                            (default: "")
  Optional override of the cloud base, e.g. a local gateway on
  "http://localhost:4000". Empty means use |g:hanzo_cloud_url|.

All endpoints are OpenAI-compatible: `POST {base}/v1/chat/completions`.

===============================================================================
 vim:tw=78:ts=8:ft=help:norl:
