The extension hardcodes vscode in both identification mechanisms, so Cursor, Devin Desktop and other forks are all recorded as VS Code. Server-side ingestion is unlocked (coder/coder#28338): app_name is a free-form string, normalized at ingestion.
Scope
- Use
vscode.env.uriScheme as the app name. It is already a unique, stable, machine-readable ID per editor, so there is no appName mapping table to keep in sync as forks rename or localize. NormalizeAppName folds - → _ server-side, so vscode-insiders arrives as the existing registry key vscode_insiders.
- No exceptions: report the scheme verbatim, never rewrite it. Devin Desktop registers
devin natively ("urlProtocol": "devin", with "oldUrlProtocol": "windsurf" kept only so inbound windsurf:// links still open), and oldUrlProtocol is not exposed through the extension API — so env.uriScheme already returns the post-rebrand name with no help from us. Pre-rename Windsurf builds report windsurf, which is an existing registry key in the VS Code family, and that tail shrinks as users upgrade. Comment the rule so a mapping table is not reintroduced later.
- Fall back to
vscode if the scheme is empty. An editor missing from codersdk/appname.go still reports its own scheme and shows under the unknown family until it is added.
- Send it through both mechanisms, which feed different pipelines:
--usage-app=<name> on the ProxyCommand (workspace usage API → session counts)
CODER_SSH_SESSION_TYPE=<name> via SSH SetEnv (agent magic env → session counts + connection log)
- Version gate: one new
FeatureSet flag evaluated on two instances, the existing CLI-binary-version instance and a second built from the already-fetched /api/v2/buildinfo version. Send a non-vscode name only when both pass; otherwise fall back to vscode. Coder ≤ 2.37.x returns HTTP 400 for an unknown app_name, so the gate is load-bearing.
- Release channels stay distinct (
vscode_insiders, devin_next, vscodium_insiders, ...). They are separate installs, the family already provides the rollup, and a split can be collapsed at read time while a collapse can never be split again.
Verified schemes
From product.json / urlProtocol — locally inspected where marked, otherwise from public source or first-party deep links:
| Editor |
Scheme |
Reported as |
Confidence |
| VS Code |
vscode |
vscode |
verified |
| VS Code Insiders |
vscode-insiders |
vscode_insiders |
verified |
| Code - OSS |
code-oss |
code_oss |
verified (microsoft/vscode product.json) |
| VSCodium |
vscodium |
vscodium |
verified (prepare_vscode.sh) |
| VSCodium Insiders |
vscodium-insiders |
vscodium_insiders |
verified (same) |
| Positron |
positron |
positron |
verified (positron:// URI handlers) |
| Cursor |
cursor |
cursor |
verified (local product.json) |
| Devin Desktop |
devin |
devin |
verified (local product.json, oldUrlProtocol: windsurf) |
| Devin Desktop Next |
devin-next |
devin_next |
verified (local product.json, oldUrlProtocol: windsurf-next) |
| Windsurf (pre-rename builds) |
windsurf |
windsurf |
legacy urlProtocol, already a registry key |
| Antigravity |
antigravity |
antigravity |
verified (local product.json) |
| Trae |
trae |
trae |
strong (trae://file/...) |
| Trae CN |
trae-cn |
trae_cn |
reported by third parties |
| Kiro |
kiro |
kiro |
strong (kiro:// OAuth callback) |
vscode-exploration is a real Microsoft-internal scheme but is deliberately not handled: no external users, and an unknown row costs nothing.
Missing registry keys are tracked in coder/coder#29928: code_oss, vscodium_insiders, trae_cn, devin_next.
Gate release: 2.38
The first release containing coder/coder#28338 (merged after the 2.37 branch cut, so no 2.37.x patch carries it). Confirm the number at branch cut.
This supersedes waiting for coder/coder#27412 and coder/coder#27413: the undercount that blocked an earlier gate is gone now that per-app and per-family session minutes are stored (template_usage_stats_session_apps, migration 000596). Both are expected in 2.38; if either lags, the consequence is presentation-only and self-healing — the connection log records the family until #27412, and template insights show family totals until #27413's read path. Session counts, Prometheus and the deployment banner are per-app as of #27411.
Done when
Description updated by Coder Agents on behalf of @EhabY: uriScheme reported verbatim with no rewrites, schemes verified from local product.json, channels kept distinct.
The extension hardcodes
vscodein both identification mechanisms, so Cursor, Devin Desktop and other forks are all recorded as VS Code. Server-side ingestion is unlocked (coder/coder#28338):app_nameis a free-form string, normalized at ingestion.Scope
vscode.env.uriSchemeas the app name. It is already a unique, stable, machine-readable ID per editor, so there is noappNamemapping table to keep in sync as forks rename or localize.NormalizeAppNamefolds-→_server-side, sovscode-insidersarrives as the existing registry keyvscode_insiders.devinnatively ("urlProtocol": "devin", with"oldUrlProtocol": "windsurf"kept only so inboundwindsurf://links still open), andoldUrlProtocolis not exposed through the extension API — soenv.uriSchemealready returns the post-rebrand name with no help from us. Pre-rename Windsurf builds reportwindsurf, which is an existing registry key in the VS Code family, and that tail shrinks as users upgrade. Comment the rule so a mapping table is not reintroduced later.vscodeif the scheme is empty. An editor missing fromcodersdk/appname.gostill reports its own scheme and shows under theunknownfamily until it is added.--usage-app=<name>on the ProxyCommand (workspace usage API → session counts)CODER_SSH_SESSION_TYPE=<name>via SSHSetEnv(agent magic env → session counts + connection log)FeatureSetflag evaluated on two instances, the existing CLI-binary-version instance and a second built from the already-fetched/api/v2/buildinfoversion. Send a non-vscodename only when both pass; otherwise fall back tovscode. Coder ≤ 2.37.x returns HTTP 400 for an unknownapp_name, so the gate is load-bearing.vscode_insiders,devin_next,vscodium_insiders, ...). They are separate installs, the family already provides the rollup, and a split can be collapsed at read time while a collapse can never be split again.Verified schemes
From
product.json/urlProtocol— locally inspected where marked, otherwise from public source or first-party deep links:vscodevscodevscode-insidersvscode_insiderscode-osscode_ossmicrosoft/vscodeproduct.json)vscodiumvscodiumprepare_vscode.sh)vscodium-insidersvscodium_insiderspositronpositronpositron://URI handlers)cursorcursorproduct.json)devindevinproduct.json,oldUrlProtocol: windsurf)devin-nextdevin_nextproduct.json,oldUrlProtocol: windsurf-next)windsurfwindsurfurlProtocol, already a registry keyantigravityantigravityproduct.json)traetraetrae://file/...)trae-cntrae_cnkirokirokiro://OAuth callback)vscode-explorationis a real Microsoft-internal scheme but is deliberately not handled: no external users, and anunknownrow costs nothing.Missing registry keys are tracked in coder/coder#29928:
code_oss,vscodium_insiders,trae_cn,devin_next.Gate release: 2.38
The first release containing coder/coder#28338 (merged after the 2.37 branch cut, so no 2.37.x patch carries it). Confirm the number at branch cut.
This supersedes waiting for coder/coder#27412 and coder/coder#27413: the undercount that blocked an earlier gate is gone now that per-app and per-family session minutes are stored (
template_usage_stats_session_apps, migration 000596). Both are expected in 2.38; if either lags, the consequence is presentation-only and self-healing — the connection log records the family until #27412, and template insights show family totals until #27413's read path. Session counts, Prometheus and the deployment banner are per-app as of #27411.Done when
vscodeagainst an older server or a stale custom CLI binaryDescription updated by Coder Agents on behalf of @EhabY:
uriSchemereported verbatim with no rewrites, schemes verified from localproduct.json, channels kept distinct.