vskill 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +84 -9
  2. package/agents.json +3 -1
  3. package/dist/agents/agents-registry.d.ts +61 -0
  4. package/dist/agents/agents-registry.js +203 -0
  5. package/dist/agents/agents-registry.js.map +1 -1
  6. package/dist/api/client.d.ts +85 -0
  7. package/dist/api/client.js +193 -24
  8. package/dist/api/client.js.map +1 -1
  9. package/dist/commands/add-lockfile.d.ts +6 -0
  10. package/dist/commands/add-lockfile.js +10 -0
  11. package/dist/commands/add-lockfile.js.map +1 -1
  12. package/dist/commands/add.d.ts +7 -0
  13. package/dist/commands/add.js +110 -2
  14. package/dist/commands/add.js.map +1 -1
  15. package/dist/commands/auth.d.ts +23 -0
  16. package/dist/commands/auth.js +105 -11
  17. package/dist/commands/auth.js.map +1 -1
  18. package/dist/commands/eval/serve.d.ts +2 -0
  19. package/dist/commands/eval/serve.js +126 -4
  20. package/dist/commands/eval/serve.js.map +1 -1
  21. package/dist/commands/orgs.d.ts +21 -0
  22. package/dist/commands/orgs.js +164 -0
  23. package/dist/commands/orgs.js.map +1 -0
  24. package/dist/commands/skill.js +14 -1
  25. package/dist/commands/skill.js.map +1 -1
  26. package/dist/commands/whoami.d.ts +29 -0
  27. package/dist/commands/whoami.js +119 -0
  28. package/dist/commands/whoami.js.map +1 -0
  29. package/dist/discovery/github-tree.d.ts +23 -3
  30. package/dist/discovery/github-tree.js +172 -24
  31. package/dist/discovery/github-tree.js.map +1 -1
  32. package/dist/eval/anthropic-catalog.js +32 -2
  33. package/dist/eval/anthropic-catalog.js.map +1 -1
  34. package/dist/eval/batch-judge.js +1 -0
  35. package/dist/eval/batch-judge.js.map +1 -1
  36. package/dist/eval/llm.d.ts +1 -1
  37. package/dist/eval/llm.js +104 -2
  38. package/dist/eval/llm.js.map +1 -1
  39. package/dist/eval-server/__tests__/helpers/studio-token-test-helpers.d.ts +2 -0
  40. package/dist/eval-server/__tests__/helpers/studio-token-test-helpers.js +20 -0
  41. package/dist/eval-server/__tests__/helpers/studio-token-test-helpers.js.map +1 -0
  42. package/dist/eval-server/active-tenant-routes.d.ts +15 -0
  43. package/dist/eval-server/active-tenant-routes.js +101 -0
  44. package/dist/eval-server/active-tenant-routes.js.map +1 -0
  45. package/dist/eval-server/api-routes.js +17 -2
  46. package/dist/eval-server/api-routes.js.map +1 -1
  47. package/dist/eval-server/desktop-open-routes.d.ts +8 -0
  48. package/dist/eval-server/desktop-open-routes.js +64 -0
  49. package/dist/eval-server/desktop-open-routes.js.map +1 -0
  50. package/dist/eval-server/eval-server.js +82 -5
  51. package/dist/eval-server/eval-server.js.map +1 -1
  52. package/dist/eval-server/export-skill-routes.d.ts +9 -0
  53. package/dist/eval-server/export-skill-routes.js +81 -0
  54. package/dist/eval-server/export-skill-routes.js.map +1 -0
  55. package/dist/eval-server/git-routes.d.ts +1 -0
  56. package/dist/eval-server/git-routes.js +101 -4
  57. package/dist/eval-server/git-routes.js.map +1 -1
  58. package/dist/eval-server/install-engine-routes.d.ts +3 -16
  59. package/dist/eval-server/install-engine-routes.js +9 -124
  60. package/dist/eval-server/install-engine-routes.js.map +1 -1
  61. package/dist/eval-server/install-jobs.d.ts +41 -0
  62. package/dist/eval-server/install-jobs.js +161 -0
  63. package/dist/eval-server/install-jobs.js.map +1 -0
  64. package/dist/eval-server/install-skill-routes.d.ts +74 -11
  65. package/dist/eval-server/install-skill-routes.js +506 -79
  66. package/dist/eval-server/install-skill-routes.js.map +1 -1
  67. package/dist/eval-server/install-state-routes.d.ts +4 -0
  68. package/dist/eval-server/install-state-routes.js +15 -1
  69. package/dist/eval-server/install-state-routes.js.map +1 -1
  70. package/dist/eval-server/oauth-github-routes.d.ts +2 -0
  71. package/dist/eval-server/oauth-github-routes.js +505 -0
  72. package/dist/eval-server/oauth-github-routes.js.map +1 -0
  73. package/dist/eval-server/platform-proxy.d.ts +17 -1
  74. package/dist/eval-server/platform-proxy.js +125 -13
  75. package/dist/eval-server/platform-proxy.js.map +1 -1
  76. package/dist/eval-server/plugin-cli-routes.js +9 -9
  77. package/dist/eval-server/plugin-cli-routes.js.map +1 -1
  78. package/dist/eval-server/remove-skill-routes.d.ts +18 -0
  79. package/dist/eval-server/remove-skill-routes.js +145 -0
  80. package/dist/eval-server/remove-skill-routes.js.map +1 -0
  81. package/dist/eval-server/router.d.ts +17 -3
  82. package/dist/eval-server/router.js +166 -9
  83. package/dist/eval-server/router.js.map +1 -1
  84. package/dist/eval-server/settings-store.js +1 -1
  85. package/dist/eval-server/settings-store.js.map +1 -1
  86. package/dist/eval-server/supported-agents-routes.d.ts +6 -0
  87. package/dist/eval-server/supported-agents-routes.js +41 -0
  88. package/dist/eval-server/supported-agents-routes.js.map +1 -0
  89. package/dist/eval-server/utils/spawn-env.d.ts +1 -0
  90. package/dist/eval-server/utils/spawn-env.js +47 -0
  91. package/dist/eval-server/utils/spawn-env.js.map +1 -0
  92. package/dist/eval-ui/assets/AdvancedTab-D8zbE5fH.js +1 -0
  93. package/dist/eval-ui/assets/{CreateSkillPage-CvdYq8Rr.js → CreateSkillPage-DOBhKdgr.js} +5 -5
  94. package/dist/eval-ui/assets/FindSkillsPalette-CyMmNPr-.js +2 -0
  95. package/dist/eval-ui/assets/GeneralTab-DYR9NWC4.js +1 -0
  96. package/dist/eval-ui/assets/PrivacyTab-CXIqQokl.js +1 -0
  97. package/dist/eval-ui/assets/{SearchPaletteCore-Bf3PBC64.js → SearchPaletteCore-Dn5gQJS_.js} +2 -2
  98. package/dist/eval-ui/assets/SkillDetailPanel-DTrRnyyJ.js +1 -0
  99. package/dist/eval-ui/assets/UpdateDropdown-Cvr2fe0z.js +1 -0
  100. package/dist/eval-ui/assets/UpdatesTab-DwJIUDPX.js +1 -0
  101. package/dist/eval-ui/assets/core-DZAvsxlC.js +1 -0
  102. package/dist/eval-ui/assets/event-CDYWU2X3.js +1 -0
  103. package/dist/eval-ui/assets/globals-BRZwPAPF.js +49 -0
  104. package/dist/eval-ui/assets/globals-C3oEdsJh.css +1 -0
  105. package/dist/eval-ui/assets/index-D7M0Jdss.js +1 -0
  106. package/dist/eval-ui/assets/lifecycle-DSleOV-l.js +1 -0
  107. package/dist/eval-ui/assets/lifecycle-d1Sm9Hts.css +1 -0
  108. package/dist/eval-ui/assets/main-D2shn1dH.js +87 -0
  109. package/dist/eval-ui/assets/preferences-BHZXB5dL.css +1 -0
  110. package/dist/eval-ui/assets/preferences-BKv6X7fK.js +2 -0
  111. package/dist/eval-ui/assets/useDesktopBridge-DxVWbYqK.js +2 -0
  112. package/dist/eval-ui/index.html +4 -2
  113. package/dist/eval-ui/lifecycle.html +33 -0
  114. package/dist/eval-ui/preferences.html +34 -0
  115. package/dist/index.js +47 -1
  116. package/dist/index.js.map +1 -1
  117. package/dist/installer/bundle-files.d.ts +4 -0
  118. package/dist/installer/bundle-files.js +97 -0
  119. package/dist/installer/bundle-files.js.map +1 -0
  120. package/dist/installer/canonical.d.ts +31 -6
  121. package/dist/installer/canonical.js +48 -12
  122. package/dist/installer/canonical.js.map +1 -1
  123. package/dist/installer/clipboard-export.d.ts +19 -0
  124. package/dist/installer/clipboard-export.js +88 -0
  125. package/dist/installer/clipboard-export.js.map +1 -0
  126. package/dist/installer/multi-install.d.ts +43 -0
  127. package/dist/installer/multi-install.js +237 -0
  128. package/dist/installer/multi-install.js.map +1 -0
  129. package/dist/installer/transformers/aider.d.ts +2 -0
  130. package/dist/installer/transformers/aider.js +32 -0
  131. package/dist/installer/transformers/aider.js.map +1 -0
  132. package/dist/installer/transformers/continue-dev.d.ts +2 -0
  133. package/dist/installer/transformers/continue-dev.js +6 -0
  134. package/dist/installer/transformers/continue-dev.js.map +1 -0
  135. package/dist/installer/transformers/cursor.d.ts +2 -0
  136. package/dist/installer/transformers/cursor.js +24 -0
  137. package/dist/installer/transformers/cursor.js.map +1 -0
  138. package/dist/installer/transformers/github-copilot.d.ts +2 -0
  139. package/dist/installer/transformers/github-copilot.js +17 -0
  140. package/dist/installer/transformers/github-copilot.js.map +1 -0
  141. package/dist/installer/transformers/index.d.ts +78 -0
  142. package/dist/installer/transformers/index.js +13 -0
  143. package/dist/installer/transformers/index.js.map +1 -0
  144. package/dist/installer/transformers/junie.d.ts +2 -0
  145. package/dist/installer/transformers/junie.js +6 -0
  146. package/dist/installer/transformers/junie.js.map +1 -0
  147. package/dist/installer/transformers/kiro.d.ts +2 -0
  148. package/dist/installer/transformers/kiro.js +6 -0
  149. package/dist/installer/transformers/kiro.js.map +1 -0
  150. package/dist/installer/transformers/trae.d.ts +2 -0
  151. package/dist/installer/transformers/trae.js +6 -0
  152. package/dist/installer/transformers/trae.js.map +1 -0
  153. package/dist/installer/transformers/windsurf.d.ts +2 -0
  154. package/dist/installer/transformers/windsurf.js +12 -0
  155. package/dist/installer/transformers/windsurf.js.map +1 -0
  156. package/dist/installer/yaml-safe-mutate.d.ts +19 -0
  157. package/dist/installer/yaml-safe-mutate.js +184 -0
  158. package/dist/installer/yaml-safe-mutate.js.map +1 -0
  159. package/dist/lib/active-tenant.d.ts +36 -0
  160. package/dist/lib/active-tenant.js +120 -0
  161. package/dist/lib/active-tenant.js.map +1 -0
  162. package/dist/lib/github-fetch.d.ts +1 -0
  163. package/dist/lib/github-fetch.js +11 -1
  164. package/dist/lib/github-fetch.js.map +1 -1
  165. package/dist/lib/keychain.d.ts +15 -2
  166. package/dist/lib/keychain.js +156 -8
  167. package/dist/lib/keychain.js.map +1 -1
  168. package/dist/lib/migration/keychain-migration.d.ts +35 -0
  169. package/dist/lib/migration/keychain-migration.js +189 -0
  170. package/dist/lib/migration/keychain-migration.js.map +1 -0
  171. package/dist/lib/tenant-resolver.d.ts +38 -0
  172. package/dist/lib/tenant-resolver.js +79 -0
  173. package/dist/lib/tenant-resolver.js.map +1 -0
  174. package/dist/lockfile/types.d.ts +8 -0
  175. package/dist/sidecar/eval-ui-manifest.json +1 -0
  176. package/dist/sidecar/sea-config.json +57 -0
  177. package/dist/sidecar/sea-prep.blob +0 -0
  178. package/dist/sidecar/server.cjs +141627 -0
  179. package/dist/sidecar/vskill-version.txt +1 -0
  180. package/dist/studio/lib/ops-log.js +140 -57
  181. package/dist/studio/lib/ops-log.js.map +1 -1
  182. package/dist/studio/lib/scope-transfer.d.ts +11 -1
  183. package/dist/studio/lib/scope-transfer.js +48 -24
  184. package/dist/studio/lib/scope-transfer.js.map +1 -1
  185. package/dist/studio/routes/index.js +10 -1
  186. package/dist/studio/routes/index.js.map +1 -1
  187. package/dist/studio/routes/ops.js +31 -7
  188. package/dist/studio/routes/ops.js.map +1 -1
  189. package/dist/studio/routes/promote.js +15 -8
  190. package/dist/studio/routes/promote.js.map +1 -1
  191. package/dist/studio/routes/revert.js +12 -1
  192. package/dist/studio/routes/revert.js.map +1 -1
  193. package/dist/studio/routes/test-install.js +13 -8
  194. package/dist/studio/routes/test-install.js.map +1 -1
  195. package/dist/studio-runtime/lockfile.d.ts +51 -0
  196. package/dist/studio-runtime/lockfile.js +216 -0
  197. package/dist/studio-runtime/lockfile.js.map +1 -0
  198. package/dist/updater/source-fetcher.js +2 -2
  199. package/dist/updater/source-fetcher.js.map +1 -1
  200. package/package.json +17 -1
  201. package/dist/eval-ui/assets/FindSkillsPalette-DsSgotS9.js +0 -2
  202. package/dist/eval-ui/assets/SkillDetailPanel-DAD2yJO-.js +0 -1
  203. package/dist/eval-ui/assets/UpdateDropdown-h5Hg3h7Z.js +0 -1
  204. package/dist/eval-ui/assets/index-CKLqBL52.css +0 -1
  205. package/dist/eval-ui/assets/index-JaDg6FlU.js +0 -124
  206. package/dist/eval-ui/assets/skill-studio-logo-CRyKgIrg.png +0 -0
package/README.md CHANGED
@@ -8,20 +8,44 @@
8
8
  <p align="center">
9
9
  <a href="https://www.npmjs.com/package/vskill"><img src="https://img.shields.io/npm/v/vskill?color=cb3837&logo=npm" alt="npm" /></a>
10
10
  <a href="https://www.npmjs.com/package/vskill"><img src="https://img.shields.io/npm/dw/vskill?color=cb3837&logo=npm&label=downloads" alt="downloads" /></a>
11
- <img src="https://img.shields.io/badge/agents-53_platforms-0969DA" alt="53 agents" />
11
+ <a href="https://github.com/anton-abyzov/vskill/stargazers"><img src="https://img.shields.io/github/stars/anton-abyzov/vskill?color=FFD700&logo=github" alt="GitHub stars" /></a>
12
+ <a href="https://github.com/anton-abyzov/vskill/actions/workflows/desktop-release.yml"><img src="https://img.shields.io/github/actions/workflow/status/anton-abyzov/vskill/desktop-release.yml?branch=main&label=desktop%20build&logo=githubactions" alt="desktop build" /></a>
13
+ <img src="https://img.shields.io/badge/agents-54_platforms-0969DA" alt="54 agents" />
12
14
  <img src="https://img.shields.io/badge/plugins-9-8B5CF6" alt="9 plugins" />
13
15
  <img src="https://img.shields.io/badge/skills-16-10B981" alt="16 skills" />
14
16
  <a href="https://verified-skill.com"><img src="https://img.shields.io/badge/registry-verified--skill.com-F59E0B" alt="registry" /></a>
15
- <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT" />
17
+ <a href="https://github.com/anton-abyzov/vskill/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT" /></a>
18
+ </p>
19
+
20
+ <p align="center">
21
+ <strong>Download Skill Studio:</strong><br/><br/>
22
+ <a href="https://github.com/anton-abyzov/vskill/releases/latest/download/Skill.Studio_1.0.16_aarch64.dmg"><img src="https://img.shields.io/badge/Download-macOS-000000?style=for-the-badge&logo=apple&logoColor=white" alt="Download for macOS" /></a>
23
+ <a href="https://github.com/anton-abyzov/vskill/releases/latest/download/Skill.Studio_1.0.16_x64-setup.exe"><img src="https://img.shields.io/badge/Download-Windows-0078D4?style=for-the-badge&logo=windows&logoColor=white" alt="Download for Windows" /></a>
24
+ <a href="https://github.com/anton-abyzov/vskill/releases/latest"><img src="https://img.shields.io/badge/Download-Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black" alt="Download for Linux" /></a>
25
+ </p>
26
+
27
+ <p align="center">
28
+ <em>All releases: <a href="https://github.com/anton-abyzov/vskill/releases">github.com/anton-abyzov/vskill/releases</a></em>
16
29
  </p>
17
30
 
18
31
  <br/>
19
32
 
20
33
  ```bash
34
+ # Browser studio — zero install
21
35
  npx vskill@latest studio # open the local IDE for AI skills
22
36
  npx vskill@latest install remotion-best-practices
23
37
  ```
24
38
 
39
+ Native Mac, Windows, and Linux desktop apps available at
40
+ **[GitHub Releases](https://github.com/anton-abyzov/vskill/releases/latest)** — 1.5 s cold launch,
41
+ no telemetry. macOS Apple Silicon is signed by `Developer ID Application: EasyChamp, Inc.`
42
+ and notarized + stapled by Apple — no Gatekeeper warning.
43
+
44
+ The desktop app wraps the same studio runtime as `npx vskill studio` in a Tauri 2 shell:
45
+ native menu bar, global `⌘K` find-skill palette, `⌘,` Preferences with General / Updates /
46
+ Privacy / Advanced tabs, settings persisted to `~/.vskill/settings.json` (atomic, 0600 perms),
47
+ and signed auto-update via `tauri-plugin-updater` against minisign-signed manifests.
48
+
25
49
  <br/>
26
50
 
27
51
  ## Why vskill
@@ -149,7 +173,8 @@ private catalog.
149
173
  ```bash
150
174
  npx vskill@latest auth login # interactive Device Flow — copy code, visit URL
151
175
  npx vskill@latest auth status # show the current GitHub identity
152
- npx vskill@latest auth logout # forget the GitHub token
176
+ npx vskill@latest auth logout # forget all stored tokens
177
+ npx vskill@latest whoami # combined identity + active tenant snapshot
153
178
  ```
154
179
 
155
180
  How it works:
@@ -157,31 +182,81 @@ How it works:
157
182
  1. `vskill auth login` requests a device + user code from `github.com/login/device/code`.
158
183
  2. You visit `https://github.com/login/device` and enter the 8-character code (rendered as `XXXX-XXXX`).
159
184
  3. The CLI polls `github.com/login/oauth/access_token` until you authorize, then validates against `api.github.com/user`.
160
- 4. The resulting token is stored in your **OS keychain** (macOS Keychain / Windows DPAPI / libsecret).
161
- On systems without a keyring daemon, the token falls back to `~/.vskill/keys.env` with mode `0600` and a startup warning.
185
+ 4. The CLI calls `POST /api/v1/auth/github/exchange-for-vsk-token` to mint a verified-skill API token (`vsk_…`) scoped to the same identity.
186
+ 5. **Both** tokens are stored in your **OS keychain** (macOS Keychain / Windows DPAPI / libsecret) under distinct service names:
187
+ - `com.verifiedskill.desktop` / `github-oauth-token` → `gho_…` (raw GitHub OAuth)
188
+ - `com.verifiedskill.desktop` / `vskill-token` → `vsk_…` (verified-skill API token)
189
+
190
+ On systems without a keyring daemon, both fall back to `~/.vskill/keys.env` with mode `0600` and a startup warning.
191
+
192
+ If the exchange step fails (network error, 5xx), login still succeeds with just the `gho_…` token and the CLI prints `Logged in (legacy mode — some features unavailable)`. Re-run `vskill auth login` later to mint the `vsk_…` token without losing your session.
162
193
 
163
- Where the token is used:
194
+ Where the tokens are used:
164
195
 
196
+ - **`vskill add <skill>`, `vskill list`, `vskill marketplace`** — every request to `verified-skill.com` carries `Authorization: Bearer <vsk_… or gho_…>` (preferring `vsk_` when present). Anonymous requests for public skills still work when no token is stored.
165
197
  - **`vskill install <github-url>`** — added as `Authorization: Bearer …` on every fetch to `api.github.com` and `raw.githubusercontent.com`. Public skills still install anonymously.
166
198
  - **`vskill studio`** — the local eval-server proxies private routes (`/api/v1/private/*`, `/api/v1/tenants/*`) to verified-skill.com with the bearer header injected at the proxy boundary. Your browser never holds the token.
167
199
 
168
200
  Configuration:
169
201
 
170
202
  - `VSKILL_GITHUB_CLIENT_ID` — the OAuth/App `client_id` used during Device Flow. Defaults are baked in for the public Skill Studio App; set this only if you are running a self-hosted variant.
203
+ - `VSKILL_TENANT` — overrides the active tenant for a single invocation (CI / scripted use). See "Tenant resolution priority" below.
171
204
 
172
205
  Inspect status of all credentials in one place:
173
206
 
174
207
  ```bash
175
208
  npx vskill@latest keys list # shows AI provider keys + the github slot
209
+ npx vskill@latest whoami # email, token prefix, active tenant, all tenants
210
+ ```
211
+
212
+ ### Tenants and `vskill orgs`
213
+
214
+ When your GitHub identity belongs to multiple organizations that have the Skill Studio App installed, each org is a **tenant** in verified-skill.com. The CLI calls them "orgs" for symmetry with `gh org`, `gcloud config configurations`, and `kubectl config use-context`.
215
+
216
+ ```bash
217
+ npx vskill@latest orgs list # table: slug | name | role | active (* marks the active tenant)
218
+ npx vskill@latest orgs use <slug> # write currentTenant to ~/.vskill/config.json
219
+ npx vskill@latest orgs current # print the active tenant slug, or `(none)`
176
220
  ```
177
221
 
222
+ `orgs` and `whoami` are anonymous-safe — running them without a stored token prints `Not logged in. Run \`vskill auth login\`.` and exits non-zero (orgs returns 0; whoami returns 1) without crashing.
223
+
224
+ #### Tenant resolution priority
225
+
226
+ When a tenant-scoped command (`vskill add`, `vskill install` for a private skill, etc.) needs to pick an active tenant, it walks this list in order — first match wins:
227
+
228
+ 1. **`--tenant <slug>` flag** — per-command override (highest precedence).
229
+ 2. **`VSKILL_TENANT` env var** — non-interactive / CI use.
230
+ 3. **`currentTenant` in `~/.vskill/config.json`** — the persistent active tenant set by `vskill orgs use` or the Studio sidebar picker.
231
+ 4. **Auto-pick when N=1** — if you belong to exactly one tenant, that one is used silently.
232
+ 5. **Error** — if you belong to N>1 tenants and none of (1)–(3) is set, the CLI prints `Multiple tenants available — set one with \`vskill orgs use <slug>\`.` and exits non-zero. The CLI never silently picks one of N>1.
233
+
234
+ The same `~/.vskill/config.json` is shared with Skill Studio — switching tenants in Studio's sidebar picker updates the same file the CLI reads, so the two surfaces stay in sync.
235
+
236
+ #### `vskill add` resolution order (private skills)
237
+
238
+ When you run `vskill add <skill>`, the resolver tries:
239
+
240
+ 1. The public registry.
241
+ 2. The active tenant's scoped registry (resolved via the priority above).
242
+ 3. Other tenants you belong to, in parallel HEAD requests — first match wins.
243
+
244
+ If a `--tenant <slug>` flag is set, only the public registry and that tenant are tried.
245
+
246
+ Common error messages:
247
+
248
+ - `Skill found in multiple tenants: acme, contoso. Re-run with --tenant <slug> or set an active tenant: vskill orgs use <slug>.` — ambiguity guard for N>1 with no active tenant.
249
+ - `Authentication failed. Run \`vskill auth login\` to re-authenticate.` — the registry returned 401. The keychain is **not** auto-cleared (you might be on a flaky network).
250
+ - `Upgrade required: <message> (<upgradeUrl>)` — the registry returned 402: skill exists in this tenant but you lack entitlement.
251
+
178
252
  ### Private skill workflow
179
253
 
180
- Once authenticated, installing a private org skill is identical to a public one — the CLI silently attaches the keychain token to every `api.github.com` and `raw.githubusercontent.com` request:
254
+ Once authenticated, installing a private org skill is identical to a public one — the CLI silently attaches the keychain token to every request:
181
255
 
182
256
  ```bash
183
- npx vskill@latest auth login # one-time setup
184
- npx vskill@latest add https://github.com/<org>/<repo> # private skill installs same as public
257
+ npx vskill@latest auth login # one-time setup (mints gho_ + vsk_)
258
+ npx vskill@latest orgs use acme # pick a tenant if you belong to multiple
259
+ npx vskill@latest add private-skill # private skill installs same as public
185
260
  ```
186
261
 
187
262
  The local skill bundle on disk **never contains** your GitHub token — the token is used only at fetch time. Your project's `vskill.lock` records `source: "private"` and the org name so future updates re-authenticate correctly.
package/agents.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "generatedAt": "2026-05-07T06:21:42.709Z",
3
+ "generatedAt": "2026-05-31T02:13:32.450Z",
4
4
  "agentPrefixes": [
5
5
  ".adal",
6
6
  ".agent",
@@ -9,6 +9,7 @@
9
9
  ".amp",
10
10
  ".augment",
11
11
  ".bolt",
12
+ ".chatgpt",
12
13
  ".claude",
13
14
  ".cline",
14
15
  ".codebuddy",
@@ -64,6 +65,7 @@
64
65
  ".amp/",
65
66
  ".augment/",
66
67
  ".bolt/",
68
+ ".chatgpt/",
67
69
  ".claude/",
68
70
  ".cline/",
69
71
  ".codebuddy/",
@@ -7,6 +7,7 @@
7
7
  * Source of truth for the count: `TOTAL_AGENTS` (derived from AGENTS_REGISTRY.length).
8
8
  * The numbers in this header are documentation only; tests assert against TOTAL_AGENTS.
9
9
  */
10
+ import type { FormatTransformer } from "../installer/transformers/index.js";
10
11
  export interface FeatureSupport {
11
12
  /** Supports slash commands */
12
13
  slashCommands: boolean;
@@ -67,6 +68,29 @@ export interface AgentDefinition {
67
68
  * instead of install affordances. The catalog still lists the entry
68
69
  * so users searching for the brand can discover it. */
69
70
  isRemoteOnly?: boolean;
71
+ /** 0845 T-001 (AC-US4-01): Install tier.
72
+ * - 1 = drop-in SKILL.md (Claude Code, Codex, Antigravity, ...)
73
+ * - 2 = format-converted (Cursor .mdc, Windsurf, Copilot, ...)
74
+ * - 3 = clipboard-only cloud tools (ChatGPT, v0, bolt.new)
75
+ * When absent the agent is treated as Tier 1. */
76
+ tier?: 1 | 2 | 3;
77
+ /** 0845 T-001 (AC-US4-01): Install surface.
78
+ * - "filesystem" → write to disk under globalSkillsDir / localSkillsDir
79
+ * - "clipboard" → emit a paste-ready blob; no disk write
80
+ * - undefined → defaults to "filesystem" if NOT isRemoteOnly,
81
+ * otherwise excluded from getSupportedAgents()
82
+ * This field — not isRemoteOnly — is the gate Studio uses to decide
83
+ * whether to surface an install affordance. See ADR-0845-01. */
84
+ installMode?: "filesystem" | "clipboard";
85
+ /** 0845 T-001 (AC-US4-01): Pure function transforming a parsed
86
+ * SKILL.md into the list of files to write under the agent's
87
+ * install root. Only set for Tier 2 agents. */
88
+ formatTransformer?: FormatTransformer;
89
+ /** 0845 T-001 (AC-US4-01): Tier 3 only — URL of the tool's docs page
90
+ * explaining how to paste the exported blob. */
91
+ pasteInstructionsUrl?: string;
92
+ /** 0845 T-001: Tier 3 only — link to the tool's docs landing page. */
93
+ docsUrl?: string;
70
94
  }
71
95
  /** 0694 (AC-US1-04): Backward-compat alias map for renamed agent ids.
72
96
  * Consumed by `getAgent()` so existing scripts/lockfiles continue to work
@@ -145,3 +169,40 @@ export declare function getInstallableAgents(): AgentDefinition[];
145
169
  * @returns Array of installed agent definitions
146
170
  */
147
171
  export declare function detectInstalledAgents(): Promise<AgentDefinition[]>;
172
+ /** Enriched registry entry returned by getSupportedAgents(). */
173
+ export interface SupportedAgent {
174
+ id: string;
175
+ displayName: string;
176
+ /** Whether the agent's binary or config dir was detected on this host. */
177
+ detected: boolean;
178
+ /** Install tier — 1 (drop-in) | 2 (format-converted) | 3 (clipboard). */
179
+ tier: 1 | 2 | 3;
180
+ /** "filesystem" or "clipboard" — defaults populated here so consumers
181
+ * don't need to repeat the resolution logic. */
182
+ installMode: "filesystem" | "clipboard";
183
+ /** Tilde-expanded absolute path of the global skills dir. */
184
+ resolvedGlobalDir: string;
185
+ /** Project-relative local skills dir (verbatim from registry). */
186
+ resolvedLocalDir: string;
187
+ /** Tier 3 only — URL of the tool's docs page explaining how to paste. */
188
+ pasteInstructionsUrl?: string;
189
+ /** Tier 3 only — docs landing page for the tool. */
190
+ docsUrl?: string;
191
+ }
192
+ /**
193
+ * 0845 (AC-US1-01, AC-US6-02, AC-US6-03): Returns every registered agent
194
+ * the Studio knows how to install to — Tier 1 / 2 (filesystem) and Tier 3
195
+ * (clipboard). Independent of binary detection: undetected agents are
196
+ * still included, with `detected: false`.
197
+ *
198
+ * The exclusion gate is `installMode`. Entries without an explicit
199
+ * `installMode` default to "filesystem" UNLESS they are flagged
200
+ * `isRemoteOnly: true` — in which case they are excluded (preserves
201
+ * the pre-existing semantics for Devin and Replit, which have no
202
+ * clipboard fallback). Tier 3 entries (chatgpt, bolt-new, v0) are
203
+ * kept by virtue of setting `installMode: "clipboard"` explicitly.
204
+ *
205
+ * Detection probes run in parallel via `Promise.allSettled`
206
+ * (AC-US6-02). `detectInstalledAgents()` is UNCHANGED (AC-US6-03).
207
+ */
208
+ export declare function getSupportedAgents(): Promise<SupportedAgent[]>;
@@ -16,6 +16,16 @@ import { join as joinPath } from "node:path";
16
16
  import { existsSync as fsExistsSync, readdirSync as fsReaddirSync } from "node:fs";
17
17
  import { homedir as osHomedir } from "node:os";
18
18
  import { detectBinary } from "../utils/resolve-binary.js";
19
+ // 0845 T-006..T-010 — per-tool format transformers wired onto Tier-2
20
+ // entries below. Each is a pure function (parsedSkill → files).
21
+ import { cursorTransformer } from "../installer/transformers/cursor.js";
22
+ import { windsurfTransformer } from "../installer/transformers/windsurf.js";
23
+ import { githubCopilotTransformer } from "../installer/transformers/github-copilot.js";
24
+ import { junieTransformer } from "../installer/transformers/junie.js";
25
+ import { kiroTransformer } from "../installer/transformers/kiro.js";
26
+ import { continueDevTransformer } from "../installer/transformers/continue-dev.js";
27
+ import { traeTransformer } from "../installer/transformers/trae.js";
28
+ import { aiderTransformer } from "../installer/transformers/aider.js";
19
29
  /** 0694 (AC-US1-04): Backward-compat alias map for renamed agent ids.
20
30
  * Consumed by `getAgent()` so existing scripts/lockfiles continue to work
21
31
  * after a rename. Keys are legacy ids, values are current canonical ids. */
@@ -63,6 +73,12 @@ export const AGENTS_REGISTRY = [
63
73
  detectInstalled: () => detectBinary('codex'),
64
74
  parentCompany: 'OpenAI',
65
75
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
76
+ // 0845 T-003 (AC-US3-04): explicit Tier 1 drop-in. Codex is a primary
77
+ // Studio install target whose binary often isn't on PATH; tier annotation
78
+ // ensures it surfaces under "Available to install" rather than relying on
79
+ // the optional-field default.
80
+ tier: 1,
81
+ installMode: 'filesystem',
66
82
  },
67
83
  {
68
84
  id: 'cursor',
@@ -73,6 +89,10 @@ export const AGENTS_REGISTRY = [
73
89
  detectInstalled: () => detectBinary('cursor'),
74
90
  parentCompany: 'Anysphere',
75
91
  featureSupport: { slashCommands: true, hooks: false, mcp: true, customSystemPrompt: true },
92
+ // 0845 T-003: Tier 2 — emits `.cursor/rules/<name>.mdc` via transformer.
93
+ tier: 2,
94
+ installMode: 'filesystem',
95
+ formatTransformer: cursorTransformer,
76
96
  },
77
97
  {
78
98
  id: 'gemini-cli',
@@ -83,6 +103,8 @@ export const AGENTS_REGISTRY = [
83
103
  detectInstalled: () => detectBinary('gemini'),
84
104
  parentCompany: 'Google',
85
105
  featureSupport: { slashCommands: false, hooks: false, mcp: true, customSystemPrompt: true },
106
+ tier: 1,
107
+ installMode: 'filesystem',
86
108
  },
87
109
  {
88
110
  // 0694 US-001 (AC-US1-02): renamed from `github-copilot` to free that ID
@@ -116,6 +138,10 @@ export const AGENTS_REGISTRY = [
116
138
  },
117
139
  parentCompany: 'GitHub (Microsoft)',
118
140
  featureSupport: { slashCommands: true, hooks: false, mcp: true, customSystemPrompt: true },
141
+ // 0845 T-003: Tier 2 — emits `.github/instructions/<name>.instructions.md`.
142
+ tier: 2,
143
+ installMode: 'filesystem',
144
+ formatTransformer: githubCopilotTransformer,
119
145
  },
120
146
  {
121
147
  id: 'kimi-cli',
@@ -136,6 +162,8 @@ export const AGENTS_REGISTRY = [
136
162
  detectInstalled: () => detectBinary('opencode'),
137
163
  parentCompany: 'Community',
138
164
  featureSupport: { slashCommands: false, hooks: false, mcp: true, customSystemPrompt: true },
165
+ tier: 1,
166
+ installMode: 'filesystem',
139
167
  },
140
168
  // ----------------------------------------------------------------
141
169
  // Non-universal agents (45)
@@ -149,6 +177,10 @@ export const AGENTS_REGISTRY = [
149
177
  detectInstalled: () => detectBinary('antigravity'),
150
178
  parentCompany: 'Google',
151
179
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
180
+ // 0845 T-002 (AC-US3-01): explicit Tier 1 drop-in. globalSkillsDir override
181
+ // via VSKILL_ANTIGRAVITY_SKILLS_DIR is handled in getSupportedAgents().
182
+ tier: 1,
183
+ installMode: 'filesystem',
152
184
  },
153
185
  {
154
186
  id: 'augment',
@@ -171,6 +203,8 @@ export const AGENTS_REGISTRY = [
171
203
  featureSupport: { slashCommands: true, hooks: true, mcp: true, customSystemPrompt: true },
172
204
  pluginCacheDir: '~/.claude/plugins/cache',
173
205
  pluginMarketplaceDir: '~/.claude/plugins/marketplaces',
206
+ tier: 1,
207
+ installMode: 'filesystem',
174
208
  },
175
209
  {
176
210
  id: 'openclaw',
@@ -181,6 +215,8 @@ export const AGENTS_REGISTRY = [
181
215
  detectInstalled: () => detectBinary('openclaw'),
182
216
  parentCompany: 'Community',
183
217
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
218
+ tier: 1,
219
+ installMode: 'filesystem',
184
220
  },
185
221
  {
186
222
  id: 'replit',
@@ -222,6 +258,10 @@ export const AGENTS_REGISTRY = [
222
258
  detectInstalled: () => detectBinary('continue'),
223
259
  parentCompany: 'Continue',
224
260
  featureSupport: { slashCommands: true, hooks: false, mcp: true, customSystemPrompt: true },
261
+ // 0845 T-003: Tier 2 — emits `.continue/rules/<name>.md` (plain markdown).
262
+ tier: 2,
263
+ installMode: 'filesystem',
264
+ formatTransformer: continueDevTransformer,
225
265
  },
226
266
  {
227
267
  id: 'crush',
@@ -262,6 +302,10 @@ export const AGENTS_REGISTRY = [
262
302
  detectInstalled: () => detectBinary('junie'),
263
303
  parentCompany: 'JetBrains',
264
304
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
305
+ // 0845 T-003: Tier 2 — emits `.junie/rules/<name>.md` (plain markdown).
306
+ tier: 2,
307
+ installMode: 'filesystem',
308
+ formatTransformer: junieTransformer,
265
309
  },
266
310
  {
267
311
  id: 'iflow-cli',
@@ -292,6 +336,10 @@ export const AGENTS_REGISTRY = [
292
336
  detectInstalled: () => detectBinary('kiro'),
293
337
  parentCompany: 'AWS',
294
338
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
339
+ // 0845 T-003: Tier 2 — emits `.kiro/steering/<name>.md` (plain markdown).
340
+ tier: 2,
341
+ installMode: 'filesystem',
342
+ formatTransformer: kiroTransformer,
295
343
  },
296
344
  {
297
345
  id: 'kode',
@@ -392,6 +440,10 @@ export const AGENTS_REGISTRY = [
392
440
  detectInstalled: () => detectBinary('trae'),
393
441
  parentCompany: 'ByteDance',
394
442
  featureSupport: { slashCommands: false, hooks: false, mcp: true, customSystemPrompt: true },
443
+ // 0845 T-003: Tier 2 — emits `.trae/<name>.md` (plain markdown).
444
+ tier: 2,
445
+ installMode: 'filesystem',
446
+ formatTransformer: traeTransformer,
395
447
  },
396
448
  {
397
449
  id: 'trae-cn',
@@ -412,6 +464,10 @@ export const AGENTS_REGISTRY = [
412
464
  detectInstalled: () => detectBinary('windsurf'),
413
465
  parentCompany: 'Codeium',
414
466
  featureSupport: { slashCommands: true, hooks: false, mcp: true, customSystemPrompt: true },
467
+ // 0845 T-003: Tier 2 — emits `.windsurf/rules/<name>.md` (plain markdown).
468
+ tier: 2,
469
+ installMode: 'filesystem',
470
+ formatTransformer: windsurfTransformer,
415
471
  },
416
472
  {
417
473
  id: 'zencoder',
@@ -472,6 +528,10 @@ export const AGENTS_REGISTRY = [
472
528
  detectInstalled: () => detectBinary('aider'),
473
529
  parentCompany: 'Aider',
474
530
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
531
+ // 0845 T-003: Tier 2 — emits conventions file + appends to ~/.aider.conf.yml.
532
+ tier: 2,
533
+ installMode: 'filesystem',
534
+ formatTransformer: aiderTransformer,
475
535
  },
476
536
  {
477
537
  id: 'tabnine',
@@ -499,6 +559,9 @@ export const AGENTS_REGISTRY = [
499
559
  },
500
560
  {
501
561
  // 0694 US-004: bolt.new is a browser-only product. See devin entry above.
562
+ // 0845 T-003: kept isRemoteOnly: true for legacy callers (detectInstalledAgents
563
+ // skips remote-only). The new `installMode: "clipboard"` is the gate Studio
564
+ // uses to surface it under "Cloud only (paste required)". See ADR-0845-01.
502
565
  id: 'bolt-new',
503
566
  displayName: 'bolt.new',
504
567
  localSkillsDir: '.bolt/skills',
@@ -508,9 +571,36 @@ export const AGENTS_REGISTRY = [
508
571
  parentCompany: 'StackBlitz',
509
572
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
510
573
  isRemoteOnly: true,
574
+ tier: 3,
575
+ installMode: 'clipboard',
576
+ pasteInstructionsUrl: 'https://bolt.new/',
577
+ docsUrl: 'https://bolt.new/',
578
+ },
579
+ {
580
+ // 0845 T-003 (AC-US5-01, plan.md §12 concern #1): NEW entry for ChatGPT
581
+ // Custom Instructions / Project Instructions / Custom GPT. A single
582
+ // registry row covers all three paste destinations; the UI may later
583
+ // split them if per-flavor blob shaping is needed. isRemoteOnly stays
584
+ // true so legacy detectInstalledAgents skips it; installMode=clipboard
585
+ // is the new gate that makes Studio surface it as a paste-only target.
586
+ id: 'chatgpt',
587
+ displayName: 'ChatGPT',
588
+ localSkillsDir: '.chatgpt/skills',
589
+ globalSkillsDir: '~/.chatgpt/skills',
590
+ isUniversal: false,
591
+ detectInstalled: async () => false,
592
+ parentCompany: 'OpenAI',
593
+ featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
594
+ isRemoteOnly: true,
595
+ tier: 3,
596
+ installMode: 'clipboard',
597
+ pasteInstructionsUrl: 'https://help.openai.com/en/articles/8096356-chatgpt-custom-instructions',
598
+ docsUrl: 'https://chatgpt.com/#settings/Personalization',
511
599
  },
512
600
  {
513
601
  // 0694 US-004: v0 is a Vercel hosted UI generator. See devin entry above.
602
+ // 0845 T-003: Tier 3 clipboard — see bolt-new note for the isRemoteOnly
603
+ // + installMode dual-flag pattern.
514
604
  id: 'v0',
515
605
  displayName: 'v0',
516
606
  localSkillsDir: '.v0/skills',
@@ -520,6 +610,10 @@ export const AGENTS_REGISTRY = [
520
610
  parentCompany: 'Vercel',
521
611
  featureSupport: { slashCommands: false, hooks: false, mcp: false, customSystemPrompt: true },
522
612
  isRemoteOnly: true,
613
+ tier: 3,
614
+ installMode: 'clipboard',
615
+ pasteInstructionsUrl: 'https://v0.dev/docs',
616
+ docsUrl: 'https://v0.dev/',
523
617
  },
524
618
  {
525
619
  id: 'gpt-pilot',
@@ -813,4 +907,113 @@ export async function detectInstalledAgents() {
813
907
  }));
814
908
  return results.sort((a, b) => a.id.localeCompare(b.id));
815
909
  }
910
+ /**
911
+ * Resolve the global skills dir for a single agent, honoring env overrides.
912
+ * The Antigravity entry supports `VSKILL_ANTIGRAVITY_SKILLS_DIR` so test
913
+ * harnesses (and power users) can redirect installs without forking the
914
+ * registry. See AC-US3-03.
915
+ */
916
+ function resolveGlobalDirForAgent(agent) {
917
+ if (agent.id === "antigravity" && process.env.VSKILL_ANTIGRAVITY_SKILLS_DIR) {
918
+ return process.env.VSKILL_ANTIGRAVITY_SKILLS_DIR;
919
+ }
920
+ return expandHome(agent.globalSkillsDir);
921
+ }
922
+ /**
923
+ * Probe a single agent's binary or config dir in isolation. Used by
924
+ * getSupportedAgents() in parallel — never throws (returns false on
925
+ * any error). Mirrors the two-tier detection logic in
926
+ * detectInstalledAgents() so the two functions agree on "detected".
927
+ */
928
+ async function probeAgentDetected(agent) {
929
+ // Remote-only agents have no local binary to probe. They still surface
930
+ // in getSupportedAgents() when they declare installMode=clipboard, but
931
+ // they are by definition undetectable.
932
+ if (agent.isRemoteOnly === true)
933
+ return false;
934
+ try {
935
+ const detector = agent.detectInstalled;
936
+ if (typeof detector === "function") {
937
+ if (await detector())
938
+ return true;
939
+ }
940
+ else {
941
+ const { exec } = await import("node:child_process");
942
+ const { promisify } = await import("node:util");
943
+ const execAsync = promisify(exec);
944
+ try {
945
+ await execAsync(detector);
946
+ return true;
947
+ }
948
+ catch {
949
+ // fall through to dir fallback
950
+ }
951
+ }
952
+ }
953
+ catch {
954
+ // fall through to dir fallback
955
+ }
956
+ try {
957
+ const { existsSync } = await import("node:fs");
958
+ const { dirname } = await import("node:path");
959
+ const globalDir = expandHome(agent.globalSkillsDir);
960
+ const home = process.env.HOME || process.env.USERPROFILE || "";
961
+ const configDir = dirname(globalDir);
962
+ if (configDir !== home && configDir !== `${home}/.config`) {
963
+ if (existsSync(globalDir))
964
+ return true;
965
+ }
966
+ }
967
+ catch {
968
+ // ignore — agent is simply undetected
969
+ }
970
+ return false;
971
+ }
972
+ /**
973
+ * 0845 (AC-US1-01, AC-US6-02, AC-US6-03): Returns every registered agent
974
+ * the Studio knows how to install to — Tier 1 / 2 (filesystem) and Tier 3
975
+ * (clipboard). Independent of binary detection: undetected agents are
976
+ * still included, with `detected: false`.
977
+ *
978
+ * The exclusion gate is `installMode`. Entries without an explicit
979
+ * `installMode` default to "filesystem" UNLESS they are flagged
980
+ * `isRemoteOnly: true` — in which case they are excluded (preserves
981
+ * the pre-existing semantics for Devin and Replit, which have no
982
+ * clipboard fallback). Tier 3 entries (chatgpt, bolt-new, v0) are
983
+ * kept by virtue of setting `installMode: "clipboard"` explicitly.
984
+ *
985
+ * Detection probes run in parallel via `Promise.allSettled`
986
+ * (AC-US6-02). `detectInstalledAgents()` is UNCHANGED (AC-US6-03).
987
+ */
988
+ export async function getSupportedAgents() {
989
+ const candidates = AGENTS_REGISTRY.filter((a) => {
990
+ if (a.installMode === "clipboard")
991
+ return true;
992
+ if (a.installMode === "filesystem")
993
+ return true;
994
+ // No explicit installMode — default to "filesystem" only when not
995
+ // remote-only. Pure remote-only agents (devin, replit) drop out here.
996
+ return a.isRemoteOnly !== true;
997
+ });
998
+ const detectResults = await Promise.allSettled(candidates.map((a) => probeAgentDetected(a)));
999
+ const supported = candidates.map((a, idx) => {
1000
+ const r = detectResults[idx];
1001
+ const detected = r.status === "fulfilled" ? r.value : false;
1002
+ const result = {
1003
+ id: a.id,
1004
+ displayName: a.displayName,
1005
+ detected,
1006
+ tier: (a.tier ?? 1),
1007
+ installMode: a.installMode ?? "filesystem",
1008
+ resolvedGlobalDir: resolveGlobalDirForAgent(a),
1009
+ resolvedLocalDir: a.localSkillsDir,
1010
+ };
1011
+ if (a.pasteInstructionsUrl)
1012
+ result.pasteInstructionsUrl = a.pasteInstructionsUrl;
1013
+ if (a.docsUrl)
1014
+ result.docsUrl = a.docsUrl;
1015
+ return result;
1016
+ });
1017
+ return supported.sort((a, b) => a.id.localeCompare(b.id));
1018
+ }
816
1019
  //# sourceMappingURL=agents-registry.js.map