← Commit history
README.md+13−12
@@ -27,12 +27,10 @@ Since v1.1.0 the extension is also the native replacement for host-side `wsl.exe ## Install  ```bash-# Download the binary (includes embedded VSIX + completions + paste-screenshot interceptor)-gh release download --repo adom-inc/adom-vscode --pattern "adom-vscode" --output /usr/local/bin/adom-vscode --clobber-sudo chmod +x /usr/local/bin/adom-vscode--# Self-install everything-adom-vscode install+# The wiki package is the only channel (the GitHub releases stopped at v1.0.6). It ships the+# binary (embedded VSIX + completions + paste-screenshot interceptor), the skills, and runs+# `adom-vscode install` for you. Hydrogen's bootstrap depends on it, so every Adom user has it.+adom-wiki pkg install adom/adom-vscode      # or: adom-wiki pkg update adom/adom-vscode ```  Or via gallia: `node install.mjs` downloads the binary and runs `adom-vscode install`.@@ -81,6 +79,7 @@ Everything the CLI does is a plain HTTP call, so HD, HW, and any script can hit | terminal.tui.dispose | `POST /terminal/tui/dispose` `{id?, name?}` | Close a named TUI terminal by handle | | claude.new | `POST /claude/new` | New Claude Code conversation | | ai.providers | `GET /ai/providers` | Which AIs are installed here (Claude Code, Codex, Kimi, Antigravity), the command a new tab runs, and which icons the user shows |+| ai.install | `POST /ai/install` | Install a missing AI's extension from the title bar (`{type}`: claude, codex, kimi, antigravity); the reply names the CLI the TUI still needs | | ai.new | `POST /ai/new` `{type, tui?, group?, surface?}` | Open a new thread for that AI in an editor group (default: the active one) and keep it there; `tui:true` puts the AI's CLI in a terminal tab instead. Antigravity: its extension is a side-bar view that can also host the conversation in an editor panel (its unlisted `antigravity.moveBetweenEditorAndSidebar`), so the default is a TAB with a new conversation in it while the side bar keeps its own conversation (two at most); `surface:"sidebar"` sends it back | | ai.icons | `POST /ai/icons` `{icons?:[...], hideVendorButtons?:[...]}` | Which AI icons the title bar shows (setting `adom-vscode.aiIcons`) and which of the AI extensions' own tab-strip buttons stay hidden (setting `adom-vscode.hideVendorTabButtons`, default both: Claude Code: Open, Open Codex Sidebar); the menu's checklists write both | | tabs.close | `POST /tabs/close` `{label?, kind?, group?}` | Close every tab matching an exact label and/or kind (claude, codex, kimi, terminal, ...), optionally in one group; the cleanup half of a ralph test |@@ -237,12 +236,12 @@ See [COMMANDS.md](COMMANDS.md) for all VS Code commands usable with `adom-vscode # Build everything locally bash build.sh -# Release (single binary ships everything)-VERSION=$(cat VERSION | tr -d '[:space:]')-gh release create v${VERSION} \-  cli/target/release/adom-vscode \-  --repo adom-inc/adom-vscode \-  --title "v${VERSION}"+# Release: publish to the wiki registry, the only channel users install from. The script+# assembles the page layout, refuses to publish unless VERSION, extension/package.json,+# cli/Cargo.toml, the built binary, and its embedded VSIX all agree (1.1.25 shipped with a+# 1.1.23 binary inside; never again), pushes the page repo, publishes, then downloads the+# published tarball and checks the binary version inside it.+bash scripts/release-wiki.sh ```  ## Version@@ -275,4 +274,6 @@ v1.1.20: /command returns errorCode command_not_found (HTTP 400) with did-you-me  v1.1.21: event-driven tab census + Claude session identity (John 2026-09-03: never poll the iframes again). GET /tabs and the SSE stream GET /tabs/events publish the extension host's own tabGroups census on every change; POST /claude/session-start ingests the Claude SessionStart hook (id + transcript path, before the jsonl is flushed) and GET /claude/sessions lists it; POST /claude/open-session opens an existing conversation by id and confirms the bind (retagging sdk-cli transcripts, which the Claude extension otherwise declines). Capability markers in /health: tabs.list, tabs.events, claude.open-session, claude.session-start, claude.sessions. +v1.1.48: the title-bar AI menu paints from the last answer and refreshes behind itself (no wait on the extension host), is capped to the window height, folds the icon checklist and vendor-button toggles behind Customize, shows a Terminal (TUI) row and icon only when that AI's CLI is on PATH (`tui_available`, `cli_path` on /ai/providers), and offers Install rows for the AIs that are not here (`POST /ai/install`). Published to the wiki by `scripts/release-wiki.sh`, which refuses a mis-stamped package.+ v1.1.26: AI thread icons in the window title bar (John 2026-09-06), the layout-controls row at the top right. VS Code has no contribution point there, so `browser/ai-titlebar.js` rides workbench.html (written by `adom-vscode install`, back on every reload) and calls this extension over `/proxy/<port>/ai/*`: one icon per INSTALLED AI in the vendor's own colour (Claude Code, Codex, and Kimi or Antigravity when their extension is present), a sparkle menu listing every installed AI plus its TUI (the CLI in a terminal tab), and a VS Code-style checklist of which icons to show (saved as `adom-vscode.aiIcons`; TUIs off by default). A click opens the thread in THIS window's active group (each Hydrogen VS Code tab is its own window and extension host; the script matches its visible tabs against every candidate port's census, so the thread never lands in another window) and moves it back if the AI extension split the editor. GET /ai/providers, POST /ai/new {type, tui?, group?} (a TUI goes through the /terminal/tui registry with the AI Threads panel's icon and colour), POST /ai/icons {icons}, POST /tabs/close {label|kind}. The icons are drawn as a real monaco-toolbar (VS Code's own action-item markup, hover and active styling) with monaco-hover tooltips; the menu glyph is a plus with a dropdown chevron. Also: `extensions install --vsix` and `adom-vscode install` used the remote-cli wrapper, which only works inside a VS Code terminal and reported success while installing nothing; both now use the code-server binary and require its own "successfully installed" line.
VERSION+1−1
@@ -1 +1 @@-1.1.26+1.1.48
bin/adom-vscode
⋯ 1 unchanged line ⋯
package.json+2−2
@@ -1,6 +1,6 @@ {   "slug": "adom-vscode",-  "version": "1.1.26",+  "version": "1.1.48",   "type": "app",   "description": "CLI + VS Code extension that lets AI assistants and the Hydrogen Desktop frontend drive VS Code from inside an Adom container: open files, live get/set of any setting/theme/font (no reload), native streamed exec, a frontend event queue, container identity (hd/hw), api-key status/inject, extension query/update, modes, paste screenshots, and any VS Code command via a local HTTP API on port 8821 (with port-file fallback discovery).",   "license": "PROPRIETARY",@@ -46,4 +46,4 @@     "adom-vscode-extensions",     "adom-vscode-modes"   ]-}\ No newline at end of file+}
page.json+2−2
@@ -4,7 +4,7 @@   "slug": "adom-vscode",   "title": "adom-vscode",   "brief": "Let Claude, Codex and Kimi drive VS Code inside your Adom container",-  "version": "1.1.25",+  "version": "1.1.48",   "license": "PROPRIETARY",   "visibility": "public",   "hero": {@@ -141,4 +141,4 @@     "adom-vscode-extensions",     "adom-vscode-modes"   ]-}\ No newline at end of file+}
skills/adom-vscode-container/SKILL.md+4−4
@@ -1,6 +1,6 @@ --- name: adom-vscode-container-description: "Identify the Adom container (ah = local Hydrogen Desktop WSL2 workspace, hw = Adom cloud container), check and inject the Adom api key at /var/run/adom/api-key, discover the extension's real port when 8821 is taken, and feature-detect verbs via GET /health. Trigger words: container type, ah or hw, what kind of container, am I in hydrogen desktop, cloud container, container identity, api key status, is the api key good, refresh api key, inject api key, /var/run/adom/api-key, session key expiring, port discovery, port.json, ADOM_VSCODE_PORT, health verbs, feature detect, carbon url, vscode proxy uri."+description: "Identify the Adom container (hd = local Hydrogen Desktop WSL2 workspace, hw = Adom cloud container), check and inject the Adom api key at /var/run/adom/api-key, discover the extension's real port when 8821 is taken, and feature-detect verbs via GET /health. Trigger words: container type, hd or hw, what kind of container, am I in hydrogen desktop, cloud container, container identity, api key status, is the api key good, refresh api key, inject api key, /var/run/adom/api-key, session key expiring, port discovery, port.json, ADOM_VSCODE_PORT, health verbs, feature detect, carbon url, vscode proxy uri." ---  Parent skill: **adom-vscode**@@ -22,7 +22,7 @@ Returns `kind` plus the raw evidence so callers can gate precisely:  Also included: `hostname`, `os` (from /etc/os-release), `kernel`, `arch`, `workspaceUser`, and `env.carbonUrl` (`ADOM_CARBON_URL`), `env.hydrogenUrl`,-`env.vscodeProxyUri`, plus the `markers` object itself and `execAllowed` (whether the exec verbs are enabled here; they are Hydrogen-local only). HTTP: `GET /container`.+`env.vscodeProxyUri`, plus the `markers` object itself and `execAllowed` (whether the exec verbs are enabled here; they are HD-local only). HTTP: `GET /container`.  ## API key (/var/run/adom/api-key) @@ -39,7 +39,7 @@ adom-vscode apikey set <value>   the frontend completes a login refresh and needs the container to pick up the   new session key. - Typical flow with the queue (adom-vscode ships NO built-in watcher; the-  polling process and its cadence belong to Hydrogen or another owner): that process+  polling process and its cadence belong to HD or another owner): that process   sees the key aging, pushes a `login/refresh-needed` event (see   **adom-vscode-queue**); frontend refreshes the session and calls `apikey   set`; the process confirms via `apikey status` (fresh mtime + new@@ -69,7 +69,7 @@ adom-vscode health  `GET /health` returns `{version, port, preferredPort, portFile, verbs: [...]}`. Gate on the `verbs` array (e.g. `exec.stream`, `queue.push`, `apikey.set`), not-on version strings. Note: `exec` / `exec.stream` only appear on Hydrogen-local+on version strings. Note: `exec` / `exec.stream` only appear on HD-local containers; on cloud (hw) containers they are disabled by security policy and absent from the roster (`execAllowed: false`). An extension that answers /health without a `verbs` field predates 1.1.10 and needs a window reload or update.
skills/adom-vscode-exec/SKILL.md+6−6
@@ -1,26 +1,26 @@ --- name: adom-vscode-exec-description: "Run shell commands inside the Adom container through the adom-vscode extension, streamed live (SSE) or buffered, as the workspace user via a login shell. Hydrogen-LOCAL ONLY: cloud (hw) containers refuse exec (exec_disabled_on_cloud), check /health verbs first. THE native replacement for routing container commands through host-side wsl.exe (which wedges, serializes behind a global lock, and flakes with E_UNEXPECTED). Trigger words: exec disabled, exec_disabled_on_cloud, exec in container, run command in container, adom-vscode exec, stream exec, streamed output, exec stream, container shell, run npm test in container, long running command, exec timeout, exec cwd, no wsl.exe, wsl exec replacement, POST /exec, SSE exec."+description: "Run shell commands inside the Adom container through the adom-vscode extension, streamed live (SSE) or buffered, as the workspace user via a login shell. HD-LOCAL ONLY: cloud (hw) containers refuse exec (exec_disabled_on_cloud), check /health verbs first. THE native replacement for routing container commands through host-side wsl.exe (which wedges, serializes behind a global lock, and flakes with E_UNEXPECTED). Trigger words: exec disabled, exec_disabled_on_cloud, exec in container, run command in container, adom-vscode exec, stream exec, streamed output, exec stream, container shell, run npm test in container, long running command, exec timeout, exec cwd, no wsl.exe, wsl exec replacement, POST /exec, SSE exec." ---  Parent skill: **adom-vscode**  # adom-vscode-exec, run container commands natively -> **Hydrogen-LOCAL ONLY (security policy).** exec runs only on local Hydrogen Desktop+> **HD-LOCAL ONLY (security policy).** exec runs only on local Hydrogen Desktop > workspaces (`container` reports `kind: hd`). Cloud (hw) containers refuse both > exec verbs with `errorCode: exec_disabled_on_cloud` (HTTP 403), and /health > omits `exec` / `exec.stream` from its verb roster there, so feature-detect > before offering exec. Rationale: adom-vscode is a core install for every Adom > user, and an arbitrary-shell verb on an internet-facing cloud container is an-> unnecessary exposure; Hydrogen workspaces sit behind the user's own firewall. On a+> unnecessary exposure; HD workspaces sit behind the user's own firewall. On a > cloud container, run commands in your own terminal/session instead. Debug > escape hatch: `ADOM_VSCODE_ALLOW_EXEC=1` set in the EXTENSION HOST env by the > platform (a remote caller cannot set it).  Commands run as the workspace user (`adom`) via `bash -lc` inside the container, spawned by the extension host itself. LOGIN shell matters: tools like-the bridge CLI need the workspace env from `/etc/profile.d/`, and a bare `-c`+adom-desktop need the workspace env from `/etc/profile.d/`, and a bare `-c` shell runs them env-less (they fail with nothing on stdout).  ## CLI@@ -47,9 +47,9 @@ adom-vscode exec "uname -a" --json                   # buffered: waits, prints o   then `exit {exitCode, timedOut}`. Closing the connection kills the child, so   a frontend that navigates away does not leak processes. -## Why not wsl.exe (the Hydrogen context)+## Why not wsl.exe (the HD context) -Hydrogen's legacy path spawned `wsl.exe -d Adom-Workspace -u adom -- bash -lc <cmd>`+HD's legacy path spawned `wsl.exe -d Adom-Workspace -u adom -- bash -lc <cmd>` on the Windows host behind a global serial lock. That path caused nearly every "wsl.exe is flaky / it wedged" incident: E_UNEXPECTED, management-plane wedges, and everything queued behind one lock, with no VS Code API access. Once the
skills/adom-vscode-queue/SKILL.md+3−3
@@ -1,6 +1,6 @@ --- name: adom-vscode-queue-description: "The shared event queue between container processes and the Hydrogen Desktop / Hydrogen Web frontend, hosted by the adom-vscode extension. Any process pushes events (login refresh needed, long-job progress, arbitrary payloads); the frontend pulls when it wants. Survives window reloads. Trigger words: event queue, queue push, queue pull, push event to frontend, notify ah frontend, frontend event, progress dialog event, api key expiring event, login refresh event, queue status, queue peek, queue topic, adom-vscode queue, POST /queue/push, pull events."+description: "The shared event queue between container processes and the Hydrogen Desktop / Hydrogen Web frontend, hosted by the adom-vscode extension. Any process pushes events (login refresh needed, long-job progress, arbitrary payloads); the frontend pulls when it wants. Survives window reloads. Trigger words: event queue, queue push, queue pull, push event to frontend, notify hd frontend, frontend event, progress dialog event, api key expiring event, login refresh event, queue status, queue peek, queue topic, adom-vscode queue, POST /queue/push, pull events." ---  Parent skill: **adom-vscode**@@ -8,7 +8,7 @@ Parent skill: **adom-vscode** # adom-vscode-queue, container-to-frontend events  A simple durable FIFO inside the extension. Producers are anything in the-container (a watcher, a build, an AI thread); the consumer is usually the Hydrogen/hc+container (a watcher, a build, an AI thread); the consumer is usually the HD/HW frontend polling when it cares. Events survive VS Code window reloads (persisted to `~/.local/share/adom-vscode/queue.json`), are capped at 1000 items, and can carry a per-item TTL.@@ -35,7 +35,7 @@ Each item: `{id, ts, topic, type, payload, ttlSec}`. Default topic is ## Patterns  - **Login refresh**: NOTE, adom-vscode ships NO built-in key watcher; this is-  the pattern for whichever process owns key freshness (an Hydrogen daemon, a cron+  the pattern for whichever process owns key freshness (an HD daemon, a cron   job, any container process). That process decides its own cadence, notices   the session key in `/var/run/adom/api-key` is close to expiry, and pushes   `topic: login, type: refresh-needed`; the frontend pulls, shows the "needs a
skills/adom-vscode-settings/SKILL.md+2−2
@@ -62,10 +62,10 @@ The key map (CLI flag -> settings key): HTTP: `GET /fonts`, `POST /fonts {editorFamily?, proseFamily?, proseCodeFamily?, editorSize?, terminalSize?, proseSize?, proseCodeSize?}` (any subset). -## Resolved fonts, the part Hydrogen needs+## Resolved fonts, the part HD needs  The configured stack often names fonts that are NOT installed on the rendering-side (the user's browser or the Hydrogen webview), so reading the setting alone lies.+side (the user's browser or the HD webview), so reading the setting alone lies. `font get` also returns `resolved`: the first family in each stack that the renderer can truly draw, checked with `document.fonts.check` inside the workbench (via the Adom sidebar webview). If the sidebar webview is not alive