← Commit history
install.sh+64
@@ -269,6 +269,70 @@ PYEOF   fi fi +# 4d. No second copy of a CLI the extension already ships (John 2026-09-20: "i'm trying to+#     achieve no redundancy of code across the vscode extension and the cli/tui"). An+#     `npm install -g --prefix ~/.local @openai/codex` (AdomLapper: 324 MB) or+#     `@anthropic-ai/claude-code` overwrites the golden-image wrapper with the npm bin+#     script, so the box then carries the CLI twice. When the extension's bundled binary is+#     present, remove the npm copy and put the wrapper back. A user who wants the npm channel+#     on purpose can keep it by removing the extension; the extension is the source here.+for pair in "codex|openai.chatgpt|bin/linux-x86_64/codex|@openai/codex" "claude|anthropic.claude-code|resources/native-binary/claude|@anthropic-ai/claude-code"; do+  IFS='|' read -r cli ext rel npmpkg <<<"$pair"+  bundled=$(ls -d "$HOME"/.local/share/code-server/extensions/${ext}-*/${rel} 2>/dev/null | sort -V | tail -1)+  npmdir="$HOME/.local/lib/node_modules/$npmpkg"+  [ -n "$bundled" ] && [ -d "$npmdir" ] || continue+  freed=$(du -sh "$npmdir" 2>/dev/null | cut -f1)+  rm -rf "$npmdir"; rmdir "$(dirname "$npmdir")" 2>/dev/null || true+  [ -L "$HOME/.local/bin/$cli" ] && rm -f "$HOME/.local/bin/$cli"+  echo "  $cli cli: removed the npm copy ($freed freed); the extension already ships this CLI"+done+# The wrappers themselves: (re)write when missing, empty, or replaced by something that is+# not a wrapper while the extension's binary exists. Never touch a user's own symlink into+# ~/.local/share/claude/versions (a deliberate `claude update` native install).+if bundled=$(ls -d "$HOME"/.local/share/code-server/extensions/openai.chatgpt-*/bin/linux-x86_64/codex 2>/dev/null | sort -V | tail -1) && [ -n "$bundled" ]; then+  CW="$HOME/.local/bin/codex"+  if [ ! -s "$CW" ] || { [ ! -L "$CW" ] && ! grep -q "Adom golden image" "$CW"; }; then+    install -d -m 0755 "$HOME/.local/bin"+    cat > "$CW" <<'CODEXW'+#!/bin/sh+# Adom golden image: `codex` is the binary the Codex VS Code extension already ships.+# Resolved fresh on every run so an extension update cannot leave this dangling (the+# extension dir carries its version, and VS Code removes the old one when it updates).+b=$(ls -d "$HOME"/.local/share/code-server/extensions/openai.chatgpt-*/bin/linux-x86_64/codex 2>/dev/null | sort -V | tail -1)+if [ -z "$b" ]; then+  echo "codex: no openai.chatgpt extension found under ~/.local/share/code-server/extensions" >&2+  echo "       reinstall it from Manage AIs" >&2+  exit 127+fi+exec "$b" "$@"+CODEXW+    chmod 0755 "$CW"; echo "  codex cli: wrapper onto the extension's binary restored"+  fi+fi+if bundled=$(ls -d "$HOME"/.local/share/code-server/extensions/anthropic.claude-code-*/resources/native-binary/claude 2>/dev/null | sort -V | tail -1) && [ -n "$bundled" ]; then+  CW="$HOME/.local/bin/claude"+  if [ ! -s "$CW" ] || { [ ! -L "$CW" ] && ! grep -q "Adom golden image" "$CW"; }; then+    install -d -m 0755 "$HOME/.local/bin"+    cat > "$CW" <<'CLAUDEW'+#!/bin/sh+# Adom golden image: `claude` is the binary the Claude Code VS Code extension already+# ships. Resolved fresh on every run so an extension update cannot leave this dangling.+# The CLI's own background updater is OFF here: it would download a second copy into+# ~/.local/share/claude/versions on every interactive launch. The extension update brings+# the new binary; nothing else needs to.+export DISABLE_AUTOUPDATER=1+b=$(ls -d "$HOME"/.local/share/code-server/extensions/anthropic.claude-code-*/resources/native-binary/claude 2>/dev/null | sort -V | tail -1)+if [ -z "$b" ]; then+  echo "claude: no anthropic.claude-code extension found under ~/.local/share/code-server/extensions" >&2+  echo "        reinstall it from Manage AIs" >&2+  exit 127+fi+exec "$b" "$@"+CLAUDEW+    chmod 0755 "$CW"; echo "  claude cli: wrapper onto the extension's binary restored"+  fi+fi+ # 5. code-server config.yaml — silence code-server's own update nags. install -d -m 0755 "$HOME/.config/code-server" cat > "$HOME/.config/code-server/config.yaml" <<'CSCONF'
package.json+14−2
@@ -4,7 +4,7 @@   "type": "bootstrap",   "title": "Adom Hydrogen (platform base)",   "brief": "Layer Hydrogen's workspace onto a standard Adom workstation.",-  "version": "0.5.61",+  "version": "0.5.62",   "description": "Hydrogen's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen on ANY platform: the runtime-neutral hydrogen-* skills and the generic editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hydrogen-windows-bootstrap (WSL2), adom/hydrogen-mac-bootstrap, adom/hydrogen-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.",   "org": "adom",   "tags": [@@ -31,6 +31,18 @@     "hydrogen-* skills",     "build a bootstrap on adom core",     "hydrogen editor configuration",-    "where do hydrogen skills come from"+    "where do hydrogen skills come from",+    "install antigravity",+    "install kimi",+    "sign in to kimi",+    "sign in to antigravity",+    "sign in to codex",+    "which ais are signed in",+    "manage ais",+    "add an ai",+    "ai toolbar button missing",+    "no duplicate cli",+    "agent harness design",+    "auth oracle"   ] }
page.json+14−2
@@ -4,7 +4,7 @@   "type": "bootstrap",   "title": "Adom Hydrogen (platform base)",   "brief": "Layer Hydrogen's workspace onto a standard Adom workstation.",-  "version": "0.5.61",+  "version": "0.5.62",   "description": "Hydrogen's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen on ANY platform: the runtime-neutral hydrogen-* skills and the generic editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hydrogen-windows-bootstrap (WSL2), adom/hydrogen-mac-bootstrap, adom/hydrogen-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.",   "org": "adom",   "tags": [@@ -47,6 +47,18 @@     "hydrogen-* skills",     "build a bootstrap on adom core",     "hydrogen editor configuration",-    "where do hydrogen skills come from"+    "where do hydrogen skills come from",+    "install antigravity",+    "install kimi",+    "sign in to kimi",+    "sign in to antigravity",+    "sign in to codex",+    "which ais are signed in",+    "manage ais",+    "add an ai",+    "ai toolbar button missing",+    "no duplicate cli",+    "agent harness design",+    "auth oracle"   ] }\ No newline at end of file
skills/hydrogen-ai-agents-dev/SKILL.mdadded+170
@@ -0,0 +1,170 @@+---+name: hydrogen-ai-agents-dev+description: The design of Hydrogen's AI agent support for developers working on hydrogen-desktop, adom-vscode, hydrogen-bootstrap or the golden image. What is baked into the golden image versus installed by the user, why the CLI must be the extension's own binary (no duplicates), how each AI's sign-in is detected (the auth oracles), how sign-in is driven for the user (pty login, device codes, paste-back, the extension panel), how the VS Code toolbar decides to show an AI's button, and how the Manage AIs dialog stays in sync with the container. READ before touching agent_harness.rs, PanelAiAccounts.svelte, adom-vscode's ai-titlebar.js or the AI sections of hydrogen-bootstrap and bake-in-distro.sh. Trigger words: agent_harness, agent harness, Provider struct, auth oracle, oracle_cmd, agent-bar.json, ai-titlebar, PanelAiAccounts, manage ais dialog, /agents/facts, no duplicates policy, golden image ai, claude wrapper, codex wrapper, DISABLE_AUTOUPDATER, kimi region, antigravity oauth token, ext_separate_signin, shared_auth.+---++# Hydrogen AI agents: how it is built++One record per AI, owned by Hydrogen, drives everything the user sees: the first-landing+"Choose your AI" dialog, the Manage AIs dialog, the VS Code toolbar buttons, and the Welcome+page line. This skill is the map. The user-facing how-to is+[hydrogen-ai-agents](../hydrogen-ai-agents/SKILL.md).++## The pieces++| piece | where | job |+|---|---|---|+| `Provider` table + `/agents/*` routes | hydrogen-desktop `src-tauri/crates/hydrogen-control/src/agent_harness.rs` | the truth: detect, oracle, install, login, logout, facts, publish agent-bar.json |+| Choose your AI / Manage AIs dialog | `src/lib/components/editor/panels/PanelAiAccounts.svelte` (mounted as an overlay by PanelVisualStudioCode) | renders `/agents/catalog` + `/agents/facts`, drives sign-in |+| toolbar buttons + AI menu | adom-vscode `browser/ai-titlebar.js` (injected into workbench.html) and `extension/src/extension.ts` (`/ai/*` routes on :8821) | draws one button per installed AI, opens threads, "Manage AIs" row |+| golden image | hd-wsl2-image `image/bake-in-distro.sh` | bakes Claude Code + Codex extensions, the `claude`/`codex` wrappers, adom-vscode, bootstrap |+| converge on every workspace | hydrogen-bootstrap `install.sh` sections 4b to 4d | first-run flags, wrapper repair, duplicate removal |+| exec transport | adom-vscode `POST /exec` (container_exec) | every probe runs through this; never wsl.exe (a probe storm once piled up 44 wsl.exe on winvm) |++## Golden image versus user install++Baked (present on every fresh workspace): the Claude Code and Codex VS Code extensions, the+`~/.local/bin/claude` and `~/.local/bin/codex` wrappers, adom-vscode, adom-theme, the+hydrogen-* skills. Installed by the user from Manage AIs: Kimi Code and Antigravity, each as+extension + CLI in one click (`POST /agents/install {key}`: the extension through adom-vscode+`/ai/install {type, extension_only:true}`, the CLI through the provider's `install_cmd`).+Grok is a placeholder (`coming_soon`).++Why this split: the two baked AIs are what every Adom user gets signed in on day one, and+their extensions are large (235 MB and 620 MB) so baking saves the download. Kimi and+Antigravity stay optional; their installs are cheap and their sign-ins need a Google or Kimi+account the user may not have.++## The no-duplicates rule (John, 2026-09-20)++"I'm trying to achieve no redundancy of code across the vscode extension and the cli/tui."++- Where the extension ships the CLI (Claude Code: `resources/native-binary/claude`; Codex:+  `bin/linux-x86_64/codex`), the PATH command is a tiny wrapper that resolves the newest+  extension folder on every run and execs that binary. No second binary, ever.+- The Claude wrapper exports `DISABLE_AUTOUPDATER=1`. Without it, Claude Code's own updater+  (installMethod "native" in `~/.claude.json`) downloads a full second binary into+  `~/.local/share/claude/versions` on an interactive launch, even when already current.+  AdomLapper had four of them (825 MB); arav-rog got one during a sign-in pty.+- Antigravity's extension downloads its own `agy` to `~/.gemini/bin/agy`. `install_cmd` and+  `detect_cmd` link `~/.local/bin/agy` to it and only run the public installer when no copy+  exists. The first cut always ran the installer and left two identical 214 MB binaries.+- Kimi's extension ships no CLI, so `~/.kimi-code/bin/kimi` (2.x) is the only copy and is+  legitimate.+- hydrogen-bootstrap converges every workspace: 4c patches an old wrapper with+  `DISABLE_AUTOUPDATER` and deletes orphaned `~/.local/share/claude`; 4d removes an npm+  `@openai/codex` or `@anthropic-ai/claude-code` under `~/.local/lib` when the extension's+  binary exists and rewrites the wrapper if it was overwritten or emptied.+- `GET /agents/facts` measures all of it in the container (extension folder, CLI kind and+  bytes, data dirs, and a `dupes` list) and the dialog's "?" tooltip shows it, so a+  regression is visible to the user without anyone reading logs.++## Sign-in: detection (the oracles)++Each Provider has an `oracle_cmd`, a shell command run in the container whose stdout decides+"signed in". Rules learned the hard way:++- Read state, never make a network call. Antigravity's first oracle was `agy -p 'ok'`; when+  the account hit Google's 429 quota the dialog showed "Sign in" over a valid session. Now+  it checks `~/.gemini/antigravity-cli/antigravity-oauth-token` for a refresh token.+- Kimi 2.x keeps `[providers."managed:kimi-code".oauth]` in `config.toml` plus+  `credentials/kimi-code*.json`; the oracle globs the credentials dir (or an API key).+- Codex: `codex login status`, falling back to `~/.codex/auth.json`. Claude: the shared+  `~/.claude/.credentials.json` (the extension writes it, the CLI reads it).+- Oracles are cached (`FAST_ORACLE_TTL` 5 s, `ORACLE_IN_FLIGHT` guard) because the catalog+  is polled by several surfaces at once. Slow oracles are marked `oracle_slow` and cached+  longer.+- A failed probe is "unknown", never "not installed" (`detect()` returns Err on transport+  failure). Right after an update relaunch the exec route settles for a few seconds; the+  first cut read every AI as absent and raised the first-landing dialog on a signed-in box.++`shared_auth` on the Provider says whether the extension and the CLI read one credential+store (claude, codex, kimi: true; antigravity: false). `ext_separate_signin` marks the AIs+whose extension signs in on its own (antigravity, kimi as a fallback). Hydrogen cannot read+the Antigravity extension's login (it lives in VS Code's browser-side global storage under+`google.google-antigravity`, only `lastLoginUsername`, tokens in secret storage), so the+dialog says "extension: own sign-in" rather than guessing.++## Sign-in: driving it for the user++`POST /agents/login {key}` runs the provider's `login_cmd` under a pty in the container with+`BROWSER=` pointed at a capture script, then `GET /agents/login-url` streams what the panel+needs: the consent URL (captured from `$BROWSER` or regexed out of the transcript with+`url_regex`), a device code (`code_regex`, Codex), and `needs_input` when the transcript+matches `input_prompt_regex` (the CLI wants a code pasted back). `auto_input` types menu+answers (Antigravity's "Select login method" wants Enter). The session ends when the oracle+flips or on `/agents/login-stop`.++Per AI:+- Claude: the CLI's OAuth in the browser; Hydrogen raises the consent window+  (`raise_window_for_user`) because it used to open behind the app.+- Codex: device code shown in the dialog, user types it on the page.+- Kimi: device flow against kimi.ai. `install_cmd` writes `global` into `~/.kimi-code/region`+  (the installer wrote mainland-cn, which sends the user to a WeChat page and the poll never+  completes). The 2.x login also moves aside a 0.8.x extension-written `config.toml` that+  lacks per-model `protocol` (it made every prompt refuse).+- Antigravity: the extension is primary (John: "stop giving preference to the tui"). The+  dialog's Sign in opens the extension's panel through `POST /agents/open-panel`, counts down+  "closing this dialog in 3, 2, 1" and closes so the panel is not hidden behind it. The CLI+  sign-in is the secondary link; its flow ends on antigravity.google/oauth-callback, a+  paste-only page, so the dialog shows a paste box (`paste_code`) feeding+  `POST /agents/login-input {key, value b64}`. No clipboard sniffing (John: "just give me a+  box to paste the code into").++First-run state for the Claude TUI lives in `~/.claude.json` (`hasCompletedOnboarding`,+`theme`, per-folder `hasTrustDialogAccepted`); the extension never writes it, so a signed-in+user still saw the wizard in a terminal. hydrogen-bootstrap 4b seeds those keys.++## The toolbar button decision++Hydrogen writes `~/.adom/agent-bar.json` whenever an oracle result changes:+`{"authed":[keys], "agents":[{key, cli, extension, extension_id, authed}]}`. adom-vscode+watches it (`fs.watchFile`) and its `/ai/providers` merges it with the extension list:++- `installed = extension || cli`. A main toolbar button appears only when installed, and it+  opens the extension surface (tab or side bar), never the TUI.+- TUI buttons exist for people who like them: off by default, added in the icon chooser, and+  only offered when the CLI exists.+- Antigravity's default surface is the side bar: its "editor tab" mode waits on a remote+  tunnel that never connects under code-server.+- The AI menu lists installed AIs plus an "Install the X extension" row when only the CLI is+  present, and a "Your AIs / Manage AIs" row that calls Hydrogen `POST /agents/present+  {manage:true}` through the control URL in `~/.adom/hydrogen-control-url`.++Signing in therefore lights the button by itself; nothing reloads.++## Keeping the Manage AIs dialog honest++- Every row is rendered from `/agents/catalog` (installed, authed, extension, has_login,+  has_apikey, has_install, shared_auth, extension_signin_separate). The pill says+  "Signed in · extension + CLI" when `shared_auth`, else "CLI signed in" plus "extension: own+  sign-in". The button says "Sign in" when one sign-in covers both, "Sign in extension" when+  it does not.+- The "?" opens a tooltip from `/agents/facts`: extension id, version, bytes; the CLI as a+  wrapper (0 MB extra), an extension-downloaded copy, a pip package, an npm package or a+  standalone binary with its bytes; the sign-in model; data dirs; duplicates; total. It is+  positioned from the button's measured rect as a sibling of the dialog inside the overlay.+  Rendering it in flow made the dialog grow and re-centre, slid the "?" out from under the+  cursor, and looped (John: "the worst human experience ever"). Nothing in that tooltip may+  change layout.+- One shared record per AI: the dialog, the toolbar and the Welcome line never compute their+  own state; they read Hydrogen's. Sign out goes through `/agents/logout` (provider+  `logout_cmd`, plus `ext_logout_cmd` for Kimi's extension) so all three surfaces flip+  together.+- The dialog is draggable by its header and has a close X; the first-landing variant has+  "I'll do this later" and "Continue".++## Ship checklist for a change here++1. Hydrogen: `scripts/bump-version.sh`, commit, push, `mkship.sh` + build on ConfRoomROG,+   ship script installs on the test boxes through `/updater/install`. Never build on a box+   someone is recording on.+2. adom-vscode: `bash build.sh`, `bash scripts/release-wiki.sh` (stamp guards, pushes main).+   Workspaces pull it with `adom-wiki pkg update adom/adom-vscode`.+3. hydrogen-bootstrap: bump `package.json`, `prepublish-check.sh`, `adom-wiki pkg publish+   --org adom --yes`, `adom-wiki repo push adom/hydrogen-bootstrap --files …`. Test any new+   converge block on arav-rog first; it runs on every user's workspace.+4. Golden image: `hd-wsl2-image/scripts/bake-weekly.sh` then `pin-golden.sh`; wrapper text+   lives in `image/bake-in-distro.sh` and must match what bootstrap 4d writes.+5. Verify with `GET /agents/catalog` and `GET /agents/facts?fresh=1` on a box, then look at+   the dialog (screenshot), not just the JSON.
skills/hydrogen-ai-agents/SKILL.mdadded+112
@@ -0,0 +1,112 @@+---+name: hydrogen-ai-agents+description: Install, sign in, sign out and check any AI in a Hydrogen workspace (Claude Code, Codex, Kimi Code, Antigravity) from inside an AI session, through Hydrogen's /agents API, without hand-running installers. READ when the user says "install antigravity", "install kimi", "sign in to codex", "sign in to kimi", "is claude signed in", "sign out of antigravity", "add an AI", "manage AIs", "open the AI panel", or asks why an AI button is missing from the VS Code toolbar. Trigger words: install antigravity, install kimi, install codex, sign in antigravity, sign in kimi, kimi login, agy login, codex login, claude login, which AIs are signed in, manage ais, add an ai, ai toolbar button missing, agents catalog, /agents/install, /agents/login, agent-bar.json.+---++# Hydrogen AI agents: install and sign in from a session++Hydrogen owns AI installs and sign-ins. Do not run `curl … | bash` installers, `npm install -g`,+`pip install kimi-cli` or `claude update` by hand: each of those puts a SECOND copy of a CLI the+VS Code extension already ships into the user's container (see the no-duplicates rule below).+Call Hydrogen's `/agents` API instead. It installs the extension and the CLI together, signs in+the right way for each AI, and keeps the VS Code toolbar and the Manage AIs dialog in step.++## Reach the API from inside the workspace++Hydrogen writes its control URL into the workspace:++```bash+HD=$(cat ~/.adom/hydrogen-control-url)      # e.g. http://127.0.0.1:63549+curl -s "$HD/agents/catalog" | python3 -m json.tool+```++If the file is missing you are not inside a Hydrogen workspace (or Hydrogen is not running);+tell the user to open Hydrogen rather than improvising an install.++## The four AIs and their keys++| key | AI | extension | CLI / TUI | one sign-in covers both? |+|---|---|---|---|---|+| `claude` | Claude Code | anthropic.claude-code (baked into the golden image) | `claude`, a wrapper onto the extension's bundled binary | yes, `~/.claude/.credentials.json` |+| `codex` | Codex | openai.chatgpt (baked in) | `codex`, a wrapper onto the extension's bundled binary | yes, `~/.codex/auth.json` |+| `kimi` | Kimi Code | moonshot-ai.kimi-code (user installs) | `kimi` 2.x, standalone (the extension ships no CLI) | yes, `~/.kimi-code/credentials` |+| `antigravity` | Antigravity | google.google-antigravity (user installs) | `agy`, the copy the extension downloads to `~/.gemini/bin/agy` | NO: the extension signs in inside its own panel, the CLI in a terminal |++`grok` is listed as coming soon and has no install or sign-in yet.++## What each call does++```bash+HD=$(cat ~/.adom/hydrogen-control-url)++# Who is installed and signed in (installed = extension or CLI present; authed = the AI's own oracle)+curl -s "$HD/agents/catalog"++# Sizes, where each piece lives, and any DUPLICATE copies (what the ? in Manage AIs shows)+curl -s "$HD/agents/facts"            # add ?fresh=1 to re-measure++# Install: extension + CLI together (Kimi, Antigravity). cli_only:true skips the extension.+curl -s -X POST "$HD/agents/install" -H 'content-type: application/json' -d '{"key":"antigravity"}'++# Sign in (CLI-driven for claude, codex, kimi; the shared credentials sign the extension in too)+curl -s -X POST "$HD/agents/login" -H 'content-type: application/json' -d '{"key":"kimi"}'+curl -s "$HD/agents/login-url?key=kimi"       # poll: {authed, url, device_code?, needs_input?, detail}+#   - url: hand it to the user as a tappable link (Hydrogen also opens it in their browser)+#   - device_code: the user types it on the page (Codex)+#   - needs_input: the page ends on a "copy this code" screen; paste it back:+curl -s -X POST "$HD/agents/login-input" -H 'content-type: application/json' -d "{\"key\":\"antigravity\",\"value\":\"$(printf %s "$CODE" | base64 -w0)\"}"+curl -s -X POST "$HD/agents/login-stop" -H 'content-type: application/json' -d '{"key":"kimi"}'   # cancel++# Antigravity's EXTENSION sign-in happens inside its VS Code panel; open it for the user:+curl -s -X POST "$HD/agents/open-panel" -H 'content-type: application/json' -d '{"key":"antigravity"}'++# API key instead of OAuth where the AI supports it (base64 on the wire)+curl -s -X POST "$HD/agents/apikey" -H 'content-type: application/json' -d "{\"key\":\"kimi\",\"value\":\"$(printf %s "$KEY" | base64 -w0)\"}"++# Sign out (removes that AI's credentials; for Kimi also the extension's, they are shared)+curl -s -X POST "$HD/agents/logout" -H 'content-type: application/json' -d '{"key":"kimi"}'++# Raise the Manage AIs dialog in Hydrogen for the human to click through+curl -s -X POST "$HD/agents/present" -H 'content-type: application/json' -d '{"manage":true}'+```++A sign-in is done when `GET /agents/catalog` reports `authed: true` for that key. Poll every+few seconds; the human has minutes, not seconds, to click through Google or OpenAI.++## What to tell the user++- **"Install antigravity" / "install kimi"**: call `/agents/install`, wait for `installed: true`+  in the catalog, then start the sign-in. Say what got installed: the extension and the CLI.+- **Sign-in for claude, codex, kimi**: one sign-in covers the extension and the CLI. Give the URL+  as a link. For Codex give the device code too.+- **Sign-in for antigravity**: say plainly that the extension and the CLI sign in separately.+  Open the panel for the extension; run `/agents/login` for the CLI. The CLI flow ends on a+  page that shows a code; ask them to paste it and send it with `/agents/login-input`.+- **Kimi region**: Kimi's installer defaults to mainland China (kimi.com, WeChat). Hydrogen's+  install writes `global` into `~/.kimi-code/region` so sign-in goes to kimi.ai. If a user+  lands on a WeChat page, that file is wrong.+- **Quota is not "signed out"**: an AI that answers 429 (Antigravity: "Individual quota+  reached, resets in Nh") is still signed in. Hydrogen's sign-in check reads the token, not a+  live prompt, so it stays green; explain the quota instead of re-authenticating.++## The VS Code toolbar and the Manage AIs dialog++Hydrogen publishes `~/.adom/agent-bar.json` (`{"authed":[…],"agents":[{key, cli, extension,+extension_id, authed}]}`) every time an oracle changes. adom-vscode watches that file and draws+one toolbar button per INSTALLED AI (extension first; a TUI button only if the user adds it in+the icon chooser and the CLI exists). So after an install or sign-in the button appears on its+own; nothing to reload. The Manage AIs dialog (Hydrogen: Adom menu, profile menu; VS Code: the+AI menu's "Manage AIs" row) reads `/agents/catalog` and `/agents/facts` live.++## The no-duplicates rule++The extension is the source of the CLI wherever it ships one. `claude` and `codex` on PATH are+719- and 830-byte wrappers that exec the extension's bundled binary; `agy` links to the copy the+Antigravity extension downloads; only `kimi` is a standalone binary because its extension ships+none. A second copy (an npm `@openai/codex`, a `claude update` native install under+`~/.local/share/claude/versions`, a second `agy` from the public installer) is a regression:+Manage AIs flags it under "Duplicate" with the bytes it would free, and hydrogen-bootstrap+removes it and restores the wrapper on its next run. If a user asks for the npm or native+channel on purpose, say that the extension then carries the same binary twice.++For the design behind all of this read [hydrogen-ai-agents-dev](../hydrogen-ai-agents-dev/SKILL.md).