Sync Host Views Skill
The VS Code extension owns all webview "views" (a.k.a. screens). The Visual Studio extension and the JetBrains plugin are thin hosts that load a subset of the same compiled webview bundles inside a WebView2 / JCEF browser.
This skill keeps those hosts current without changing which views they ship:
- ✅ Refresh the content of views a host already ships (so a screen never goes stale).
- 🛑 Never silently add a new VS Code view to a host. New views are detected and handed to the user to decide.
- 🔎 Flag views a host references that VS Code no longer builds (orphans).
One view == one screen
Each entry in the VS Code esbuild entryPoints map is exactly one webview bundle
and one user-facing screen. "Add a screen" therefore means "add a bundle to the
host include list and wire up navigation to it" — that is the human decision
this skill protects.
The three sources of truth
| Role | File | Symbol |
|---|---|---|
| Canonical view set (VS Code) | vscode-extension/esbuild.js |
entryPoints keys mapping to src/webview/<name>/main.ts |
| Built artifacts | vscode-extension/dist/webview/<name>.js |
one .js per view (produced by npm run package) |
| Visual Studio host list | visualstudio-extension/src/CopilotTokenTracker/CopilotTokenTracker.csproj |
_WebviewBundle Include="…\dist\webview\<name>.js" items |
| Visual Studio committed bundles | visualstudio-extension/src/CopilotTokenTracker/webview/<name>.js |
refreshed copies packaged into the VSIX |
| JetBrains host list | jetbrains-plugin/build.gradle.kts |
prepareBundledAssets → from(".../dist/webview") { include("<name>.js", …) } |
At the time of writing VS Code builds 11 views and both hosts ship the same
7: chart, details, diagnostics, environmental, fluency-level-viewer, maturity, usage. The remaining VS Code-only views are dashboard,
efficiency, logviewer and whatsnew — intentionally not shipped by the
hosts.
Why the two hosts differ in practice
- Visual Studio commits the bundle files into the repo (
webview/*.js), so they can drift out of date independently of the VS Code build. This skill refreshes them. - JetBrains copies the bundles at Gradle build time straight from
vscode-extension/dist/webview, so its tracked views are always content-fresh; only its include list can drift from the canonical set. This skill compares that list.
What the script reports
sync-host-views.js classifies, per host, every canonical view as:
- tracked — the host ships this view. For Visual Studio it additionally checks the committed bundle against the freshly built dist bundle (sha256) and reports any that are stale.
- NEW — VS Code builds it but the host does not list it. Requires a human
decision; the script exits
3. - ORPHAN — the host lists a view VS Code no longer builds. Mechanical drift;
the script exits
1.
It also flags Visual Studio list/file inconsistencies: a name in the csproj with no committed file, or a committed file not referenced by the csproj.
Usage
# Detect drift and new screens (read-only). Run from the repo root.
node .github/skills/sync-host-views/sync-host-views.js
# Machine-readable output (CI / further processing).
node .github/skills/sync-host-views/sync-host-views.js --json
# Refresh the committed Visual Studio bundles from dist (tracked views only —
# never adds a view). Requires vscode-extension/dist/webview to be built first.
node .github/skills/sync-host-views/sync-host-views.js --refresh
# Help.
node .github/skills/sync-host-views/sync-host-views.js --help
Build the bundles first if dist/webview is empty:
cd vscode-extension && npm run package
Exit codes
| Code | Meaning |
|---|---|
0 |
Hosts are in sync; nothing stale |
1 |
Mechanical drift the agent can fix (stale VS bundles, orphan entries, csproj/file mismatch) |
2 |
Configuration error (a source file was not found / a block moved) |
3 |
NEW views detected — stop and ask the user (takes precedence over 1) |
Workflow for the agent
- Run the detector.
node .github/skills/sync-host-views/sync-host-views.js - If Visual Studio bundles are stale (exit 1): run
--refresh, then rebuild the VS extension and run its tests (see the Visual Studio instructions). Commit the refreshedwebview/*.js. This keeps existing screens up to date. - If exit 3 (NEW views): do NOT add them automatically. Ask the user, one
view at a time, whether each new VS Code screen should be added to Visual Studio
and/or JetBrains. Example question: "VS Code added a
logviewerscreen that neither host ships. Add it to Visual Studio, JetBrains, both, or skip?" Only after the user opts in:- Visual Studio: add
<_WebviewBundle Include="..\..\..\vscode-extension\dist\webview\<name>.js" />to theCopyWebviewBundlestarget inCopilotTokenTracker.csproj, copy the bundle intowebview/<name>.js, and wire navigation inToolWindow/TokenTrackerControl.xaml.cs(NavigateToViewAsyncswitch) plus any toolbar/menu entry. CheckWebBridge/ThemedHtmlBuilder.csfor view-specific hide rules. - JetBrains: add
"<name>.js"to theinclude(...)list in theprepareBundledAssetstask inbuild.gradle.kts, and wire navigation in the plugin's tool-window/host code.
- Visual Studio: add
- If exit 1 due to an ORPHAN: a host lists a view VS Code removed. Confirm the removal was intended, then drop the entry from the host list (and the committed VS bundle) — again, surface this to the user since it removes a screen.
- Re-run the detector until it is clean (or only the intentional NEW views the user chose to skip remain).
Sub-screens / tabs (out of automatic scope)
Some bundles contain multiple sub-screens or tabs (e.g. the chart view's
by model / by editor / by repository toggles, or the tables on the details
page). Those live inside a single bundle and are refreshed automatically when
the bundle is refreshed — there is no separate include entry to add. If a host
needs to hide a specific sub-screen it is done with a CSS rule in
ThemedHtmlBuilder.cs (Visual Studio) or the equivalent JetBrains host HTML. When
refreshing bundles, skim the VS Code diff for new sub-screens that a host may need
to hide or reveal, and raise anything notable with the user.
Related files
vscode-extension/esbuild.js— canonicalentryPointsview listvisualstudio-extension/src/CopilotTokenTracker/CopilotTokenTracker.csproj—CopyWebviewBundlestarget (_WebviewBundleincludes) and committed-bundle packagingvisualstudio-extension/src/CopilotTokenTracker/webview/*.js— committed VS bundlesvisualstudio-extension/src/CopilotTokenTracker/ToolWindow/TokenTrackerControl.xaml.cs—NavigateToViewAsyncview switch (where a new screen is wired up)visualstudio-extension/src/CopilotTokenTracker/WebBridge/ThemedHtmlBuilder.cs— per-view / per-sub-screen hide CSSjetbrains-plugin/build.gradle.kts—prepareBundledAssetswebviewinclude(...).github/skills/validate-editor-names/— complementary skill for editor-name parity