vskill 0.5.103 → 0.5.105

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 (102) hide show
  1. package/README.md +147 -4
  2. package/agents.json +1 -1
  3. package/dist/agents/agents-registry.d.ts +13 -3
  4. package/dist/agents/agents-registry.js +100 -57
  5. package/dist/agents/agents-registry.js.map +1 -1
  6. package/dist/api/client.d.ts +21 -0
  7. package/dist/api/client.js +39 -5
  8. package/dist/api/client.js.map +1 -1
  9. package/dist/commands/diff.d.ts +6 -0
  10. package/dist/commands/diff.js +104 -0
  11. package/dist/commands/diff.js.map +1 -0
  12. package/dist/commands/eval/serve.js +29 -83
  13. package/dist/commands/eval/serve.js.map +1 -1
  14. package/dist/commands/keys.d.ts +14 -0
  15. package/dist/commands/keys.js +166 -0
  16. package/dist/commands/keys.js.map +1 -0
  17. package/dist/commands/masked-stdin.d.ts +14 -0
  18. package/dist/commands/masked-stdin.js +79 -0
  19. package/dist/commands/masked-stdin.js.map +1 -0
  20. package/dist/commands/skill.d.ts +6 -0
  21. package/dist/commands/skill.js +366 -0
  22. package/dist/commands/skill.js.map +1 -0
  23. package/dist/commands/update.js +15 -4
  24. package/dist/commands/update.js.map +1 -1
  25. package/dist/core/skill-emitter.d.ts +37 -0
  26. package/dist/core/skill-emitter.js +333 -0
  27. package/dist/core/skill-emitter.js.map +1 -0
  28. package/dist/core/skill-generator.d.ts +27 -0
  29. package/dist/core/skill-generator.js +100 -0
  30. package/dist/core/skill-generator.js.map +1 -0
  31. package/dist/eval/anthropic-catalog.d.ts +49 -0
  32. package/dist/eval/anthropic-catalog.js +238 -0
  33. package/dist/eval/anthropic-catalog.js.map +1 -0
  34. package/dist/eval/llm.d.ts +1 -1
  35. package/dist/eval/llm.js +68 -10
  36. package/dist/eval/llm.js.map +1 -1
  37. package/dist/eval/mcp-detector.js +24 -3
  38. package/dist/eval/mcp-detector.js.map +1 -1
  39. package/dist/eval/model-resolver.d.ts +39 -0
  40. package/dist/eval/model-resolver.js +94 -0
  41. package/dist/eval/model-resolver.js.map +1 -0
  42. package/dist/eval/pricing.js +42 -16
  43. package/dist/eval/pricing.js.map +1 -1
  44. package/dist/eval/skill-scanner.d.ts +0 -5
  45. package/dist/eval/skill-scanner.js +0 -12
  46. package/dist/eval/skill-scanner.js.map +1 -1
  47. package/dist/eval-server/api-routes.d.ts +1 -0
  48. package/dist/eval-server/api-routes.js +191 -63
  49. package/dist/eval-server/api-routes.js.map +1 -1
  50. package/dist/eval-server/authoring-routes.js +21 -1
  51. package/dist/eval-server/authoring-routes.js.map +1 -1
  52. package/dist/eval-server/boot-preflight.js +8 -10
  53. package/dist/eval-server/boot-preflight.js.map +1 -1
  54. package/dist/eval-server/darwin-migrator.d.ts +57 -0
  55. package/dist/eval-server/darwin-migrator.js +169 -0
  56. package/dist/eval-server/darwin-migrator.js.map +1 -0
  57. package/dist/eval-server/eval-server.d.ts +1 -0
  58. package/dist/eval-server/eval-server.js +10 -0
  59. package/dist/eval-server/eval-server.js.map +1 -1
  60. package/dist/eval-server/providers.d.ts +7 -12
  61. package/dist/eval-server/providers.js +13 -15
  62. package/dist/eval-server/providers.js.map +1 -1
  63. package/dist/eval-server/settings-store.d.ts +17 -19
  64. package/dist/eval-server/settings-store.js +192 -189
  65. package/dist/eval-server/settings-store.js.map +1 -1
  66. package/dist/eval-server/skill-create-routes.d.ts +62 -0
  67. package/dist/eval-server/skill-create-routes.js +97 -132
  68. package/dist/eval-server/skill-create-routes.js.map +1 -1
  69. package/dist/eval-ui/assets/{CommandPalette-6cLEufX0.js → CommandPalette-DAWyTgXL.js} +1 -1
  70. package/dist/eval-ui/assets/CreateSkillPage-D5xmvnzV.js +12 -0
  71. package/dist/eval-ui/assets/UpdateDropdown-6bfwsX0-.js +1 -0
  72. package/dist/eval-ui/assets/index-C_-YXE6O.js +102 -0
  73. package/dist/eval-ui/index.html +1 -1
  74. package/dist/first-run-onboarding.d.ts +19 -0
  75. package/dist/first-run-onboarding.js +104 -0
  76. package/dist/first-run-onboarding.js.map +1 -0
  77. package/dist/index.js +21 -0
  78. package/dist/index.js.map +1 -1
  79. package/dist/installer/canonical.d.ts +2 -0
  80. package/dist/installer/canonical.js +33 -3
  81. package/dist/installer/canonical.js.map +1 -1
  82. package/dist/studio/lib/ops-log.js +1 -4
  83. package/dist/studio/lib/ops-log.js.map +1 -1
  84. package/dist/studio/lib/scope-transfer.d.ts +0 -10
  85. package/dist/studio/lib/scope-transfer.js +13 -116
  86. package/dist/studio/lib/scope-transfer.js.map +1 -1
  87. package/dist/studio/routes/ops.js +3 -26
  88. package/dist/studio/routes/ops.js.map +1 -1
  89. package/dist/studio/routes/promote.js +15 -9
  90. package/dist/studio/routes/promote.js.map +1 -1
  91. package/dist/studio/routes/test-install.js +11 -4
  92. package/dist/studio/routes/test-install.js.map +1 -1
  93. package/dist/utils/agent-filter.js +5 -4
  94. package/dist/utils/agent-filter.js.map +1 -1
  95. package/dist/utils/resolve-binary.d.ts +22 -0
  96. package/dist/utils/resolve-binary.js +44 -1
  97. package/dist/utils/resolve-binary.js.map +1 -1
  98. package/package.json +3 -1
  99. package/scripts/preuninstall.cjs +2 -9
  100. package/dist/eval-ui/assets/CreateSkillPage-kn7xDaAP.js +0 -12
  101. package/dist/eval-ui/assets/UpdateDropdown-9qR5NxTi.js +0 -1
  102. package/dist/eval-ui/assets/index-4LdVR3Lo.js +0 -102
package/README.md CHANGED
@@ -10,7 +10,7 @@
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
11
  <img src="https://img.shields.io/badge/agents-49_platforms-0969DA" alt="49 agents" />
12
12
  <img src="https://img.shields.io/badge/plugins-5-8B5CF6" alt="5 plugins" />
13
- <img src="https://img.shields.io/badge/skills-7-10B981" alt="7 skills" />
13
+ <img src="https://img.shields.io/badge/skills-8-10B981" alt="8 skills" />
14
14
  <a href="https://verified-skill.com"><img src="https://img.shields.io/badge/registry-verified--skill.com-F59E0B" alt="registry" /></a>
15
15
  <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT" />
16
16
  </p>
@@ -124,7 +124,7 @@ Then invoke as `/plugin:skill` in your agent:
124
124
  | **mobile** | React Native, Expo, Flutter, SwiftUI, Jetpack Compose, app store | `appstore` |
125
125
  | **marketing** | Social media content creation, posting, and engagement across 11 platforms, plus Slack messaging | `social-media-posting` `slack-messaging` |
126
126
  | **google-workspace** | Google Workspace CLI (gws) for Drive, Sheets, Docs, Calendar, Chat, Admin | `gws` |
127
- | **skills** | Skill discovery and recommendations | `scout` |
127
+ | **skills** | Skill discovery, recommendations, and authoring | `scout` `skill-builder` |
128
128
  | **productivity** | Expert network survey completion and paid expertise sharing | `survey-passing` |
129
129
 
130
130
  <br/>
@@ -143,8 +143,50 @@ vskill info <skill> Show detailed skill information
143
143
  vskill submit <source> Submit a skill for verification
144
144
  vskill blocklist Manage blocked malicious skills
145
145
  vskill init Initialize vskill in a project
146
+ vskill diff <s> <from> <to> Show multi-file diff between two versions
147
+ vskill keys <cmd> [provider] Manage LLM API keys (set/list/remove/path)
146
148
  ```
147
149
 
150
+ ## Compare skill versions
151
+
152
+ `vskill diff <skill> <from> <to>` fetches a multi-file diff from
153
+ verified-skill.com and renders it to stdout. The platform-side endpoint
154
+ reuses GitHub's `/compare/A...B` for GitHub-hosted skills, so the full
155
+ bundle (not just `SKILL.md`) is diffed.
156
+
157
+ ```bash
158
+ # Full color diff (respects TTY + NO_COLOR / FORCE_COLOR)
159
+ vskill diff anton-abyzov/vskill/scout 4f2285d 71a9132
160
+
161
+ # Summary only: `filename +N -M` per file + a totals line
162
+ vskill diff anton-abyzov/vskill/scout 4f2285d 71a9132 --stat
163
+
164
+ # Machine-readable raw compare response (pretty JSON, no colors)
165
+ vskill diff anton-abyzov/vskill/scout 4f2285d 71a9132 --json | jq '.files[].filename'
166
+
167
+ # Glob-filter the file list (minimatch)
168
+ vskill diff anton-abyzov/vskill/scout 4f2285d 71a9132 --files "**/SKILL.md"
169
+ ```
170
+
171
+ Flags:
172
+
173
+ | Flag | Description |
174
+ |:-----|:------------|
175
+ | `--stat` | Summary only — one line per file (`filename +N -M`) plus a totals line |
176
+ | `--json` | Pretty-printed raw compare JSON (platform response, filtered by `--files`). No colors — safe to pipe into `jq`. |
177
+ | `--files <pattern>` | Filter the file list via a `minimatch` glob (e.g. `**/*.md`) |
178
+
179
+ **Windows compatibility.** `vskill diff` is pure `fetch()` + `process.stdout.write`
180
+ — zero shell-outs to `git`, `diff`, or `less`. Colors use raw ANSI codes
181
+ (`\x1b[32m` / `\x1b[31m` / `\x1b[90m` / `\x1b[0m`) which Windows Terminal,
182
+ PowerShell 7+, and conhost-enabled cmd.exe (Windows 10 1511+) render
183
+ natively. The windows-latest CI install-smoke job (T-008, 0706) exercises
184
+ `diff --help` on every build, so PowerShell and cmd.exe stay first-class.
185
+
186
+ Golden test case: the `scout` skill between SHAs
187
+ `4f2285d...71a9132` returns 4 files with +590 insertions / -8 deletions.
188
+ See [https://github.com/anton-abyzov/vskill/compare/4f2285d...71a9132](https://github.com/anton-abyzov/vskill/compare/4f2285d...71a9132).
189
+
148
190
  <details>
149
191
  <summary><strong>Install flags</strong></summary>
150
192
 
@@ -166,6 +208,28 @@ vskill init Initialize vskill in a project
166
208
 
167
209
  <br/>
168
210
 
211
+ ## Skill Authoring
212
+
213
+ Create and manage universal cross-tool skills with the `vskill skill` command family.
214
+ The bundled `skill-builder` meta-skill drives the flow from inside any supported
215
+ agent host (Claude Code, Cursor, Codex, Gemini CLI, etc.) with an automatic
216
+ path A/B/C fallback chain.
217
+
218
+ ```bash
219
+ vskill skill new --prompt "lint markdown" --targets=claude-code,codex
220
+ vskill skill import ./existing-skill/SKILL.md
221
+ vskill skill list
222
+ vskill skill info skill-builder
223
+ vskill skill publish skill-builder
224
+ ```
225
+
226
+ Every emitted skill carries an `x-sw-schema-version: 1` marker on its frontmatter,
227
+ and ships with a `<name>-divergence.md` report that documents any frontmatter
228
+ fields dropped or translated per target (e.g. `allowed-tools` → OpenCode
229
+ `permission.bash: ask`).
230
+
231
+ <br/>
232
+
169
233
  ## Security Audit
170
234
 
171
235
  Scan entire projects for security issues — not just skills:
@@ -352,11 +416,88 @@ npx vskill eval generate-all # Batch-generate for all skills
352
416
 
353
417
  Previous benchmark results are displayed on the skill detail page without re-running. Per-case pass/fail status, time, and token usage are shown inline.
354
418
 
419
+ ## API Key Storage
420
+
421
+ `vskill` stores LLM provider API keys (Anthropic, OpenAI, OpenRouter) at `~/.vskill/keys.env` in dotenv format. One file. Same code path on macOS, Linux, and Windows.
422
+
423
+ ### Storage location
424
+
425
+ | Platform | Default path | Permissions |
426
+ |:---|:---|:---|
427
+ | macOS | `~/.vskill/keys.env` | `0600` (owner read/write only) |
428
+ | Linux | `~/.vskill/keys.env` | `0600` (owner read/write only) |
429
+ | Windows | `%USERPROFILE%\.vskill\keys.env` | NTFS ACL (user-scoped) |
430
+
431
+ Override the default with `VSKILL_CONFIG_DIR` — useful for CI, hermetic tests, or multi-profile workflows. Example: `VSKILL_CONFIG_DIR=/tmp/test vskill keys set anthropic`.
432
+
433
+ Get the absolute path at any time:
434
+ ```bash
435
+ vskill keys path
436
+ # /Users/you/.vskill/keys.env
437
+ ```
438
+
439
+ ### Precedence: real env vars ALWAYS win
440
+
441
+ If `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `OPENROUTER_API_KEY` is already set in your shell (from `direnv`, `1password-cli`, a CI secret, dotfiles, etc.), the stored key in `keys.env` is IGNORED for that provider. Real env vars are never overwritten by vskill's boot-time merge. This is the power-user escape hatch — vskill gets out of your way.
442
+
443
+ You can verify the resolved source via `vskill keys list`:
444
+ ```
445
+ provider source key
446
+ anthropic env var ****ABCD
447
+ openai file ****EFGH
448
+ openrouter not set
449
+ ```
450
+
451
+ ### `vskill keys` subcommands
452
+
453
+ ```bash
454
+ # Interactive masked paste (characters not echoed)
455
+ vskill keys set anthropic
456
+
457
+ # Piped stdin (dotfiles, provisioning scripts)
458
+ echo "$ANTHROPIC_KEY" | vskill keys set anthropic
459
+
460
+ # Table with stored/env/not-set status and redacted last-4
461
+ vskill keys list
462
+
463
+ # Idempotent remove (no error if not present)
464
+ vskill keys remove anthropic
465
+
466
+ # Print absolute path (same as the Settings modal footer)
467
+ vskill keys path
468
+ ```
469
+
470
+ All four subcommands work identically on macOS, Linux, and Windows (enforced by a 3-OS CI matrix).
471
+
472
+ ### Security model
473
+
474
+ - Plaintext file, `0600` on POSIX — matches the precedent of `aws`, `kubectl`, and `supabase` credential files. The threat model is "solo developer, local tool, user-home ACLs", NOT "stolen unlocked laptop".
475
+ - Keys are NEVER logged, printed to stdout, or embedded in error messages. Only redacted `****<last-4>` is ever emitted, verified by a log-capture unit test with an injected canary substring.
476
+ - The paste flow in Settings modal clears the input synchronously after POST — the raw key is never held across a React render boundary.
477
+ - If you want encryption at rest, set the provider env vars from your secrets manager (`direnv`, `1password-cli`, `pass`, etc.). The env var precedence rule means vskill will use them transparently and never read `keys.env` for those providers.
478
+
479
+ ### Migration from legacy macOS Keychain tier
480
+
481
+ Users who stored keys via the previous `vskill-<provider>` Keychain entries get a one-click import banner on first boot of vskill >=0.5.70. Old Keychain entries are retained for 30 days post-import as a rollback safety net; after that you can remove them manually with `security delete-generic-password -s vskill-anthropic -a vskill-user`. Non-Darwin platforms: no-op.
482
+
483
+ ### `.gitignore` suggestion
484
+
485
+ If you keep dotfiles in a Git repo, add this to `.gitignore`:
486
+ ```
487
+ ~/.vskill/keys.env
488
+ ```
489
+
490
+ ### First-run onboarding
491
+
492
+ When `vskill studio` starts with no stored key AND no env var set, the terminal prompts you to paste a key BEFORE opening the browser. Paste (masked) + Enter → saved + browser opens. Or decline and get a `vskill keys set <provider>` hint to run later. If ANY provider env var is already set, the prompt is skipped silently — no nagging power users.
493
+
494
+ <br/>
495
+
355
496
  ## Claude Max/Pro subscription compliance
356
497
 
357
498
  vSkill Studio does not consume your Max/Pro subscription quota directly. It delegates to the official [Claude Code CLI](https://docs.claude.com/en/docs/claude-code), the sanctioned consumer per Anthropic's April 2026 Terms of Service update. The Claude adapter never reads `~/.claude/credentials*`, `~/.claude/auth*`, or `~/.claude/token*` — a bundled unit test (`src/eval/__tests__/claude-cli-compliance.test.ts`) plus a dist-bundle grep gate (`scripts/check-bundle-compliance.sh`) enforce this on every build.
358
499
 
359
- Issue API keys for direct access at [platform.claude.com/settings/keys](https://platform.claude.com/settings/keys) or [openrouter.ai/settings/keys](https://openrouter.ai/settings/keys). Keys entered in Studio's Settings modal are stored locally on-device only (in-memory + browser localStorage mirror, or macOS Keychain on opt-in) — never synced, never committed to git, never transmitted off-device except to the provider's own API.
500
+ Issue API keys for direct access at [platform.claude.com/settings/keys](https://platform.claude.com/settings/keys), [platform.openai.com/api-keys](https://platform.openai.com/api-keys), or [openrouter.ai/settings/keys](https://openrouter.ai/settings/keys). Keys entered in Studio's Settings modal (or via `vskill keys set`) are stored locally at `~/.vskill/keys.env` with `0600` permissions on POSIX — never synced, never committed to git, never transmitted off-device except to the provider's own API. See [API Key Storage](#api-key-storage) for the full storage model.
360
501
 
361
502
  ### Model configuration
362
503
 
@@ -365,7 +506,9 @@ The eval system supports multiple LLM providers. Switch between them in the eval
365
506
  | Provider | Models | Requirements |
366
507
  |:---------|:-------|:-------------|
367
508
  | **Claude Code (CLI)** | Sonnet, Opus, Haiku | `@anthropic-ai/claude-code` installed on PATH — Studio delegates to your existing Claude Code session. |
368
- | **Anthropic API** | Claude Sonnet 4.6, Opus 4.6, Haiku 4.5 | `ANTHROPIC_API_KEY` env var |
509
+ | **Anthropic API** | Claude Sonnet 4.6, Opus 4.6, Haiku 4.5 | `ANTHROPIC_API_KEY` env var, or `vskill keys set anthropic` |
510
+ | **OpenAI API** | GPT-4o, GPT-4o-mini, o1-mini | `OPENAI_API_KEY` env var, or `vskill keys set openai` |
511
+ | **OpenRouter** | Any OpenRouter-served model | `OPENROUTER_API_KEY` env var, or `vskill keys set openrouter` |
369
512
  | **Ollama** | Any locally installed model | Ollama running at `localhost:11434` |
370
513
  | **LM Studio** | Any model loaded in LM Studio | LM Studio running at `localhost:1234` (no API key needed) |
371
514
 
package/agents.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "generatedAt": "2026-04-24T18:28:45.900Z",
3
+ "generatedAt": "2026-04-24T22:27:42.739Z",
4
4
  "agentPrefixes": [
5
5
  ".adal",
6
6
  ".agent",
@@ -7,7 +7,6 @@
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
- /** Feature support flags for an agent */
11
10
  export interface FeatureSupport {
12
11
  /** Supports slash commands */
13
12
  slashCommands: boolean;
@@ -30,8 +29,19 @@ export interface AgentDefinition {
30
29
  globalSkillsDir: string;
31
30
  /** Whether this agent supports the universal skill format */
32
31
  isUniversal: boolean;
33
- /** Shell command to detect if the agent is installed */
34
- detectInstalled: string;
32
+ /** Detect whether the agent is installed.
33
+ *
34
+ * 0706 T-002: historically this was a literal shell string (e.g. `'which
35
+ * claude'`) executed through `exec()`. That pipes through `cmd.exe` on
36
+ * Windows where `which`, `~`, `&&`, `2>/dev/null`, etc. don't exist, so
37
+ * detection returned empty on Windows. New preferred form is a function
38
+ * that returns a boolean (using `detectBinary()` + direct fs probes).
39
+ *
40
+ * The string form is retained as a legacy escape hatch so this change is
41
+ * non-breaking for any external consumer who built their own registry
42
+ * row with a shell string. `detectInstalledAgents()` handles both shapes.
43
+ */
44
+ detectInstalled: string | (() => Promise<boolean>);
35
45
  /** Parent company or organization */
36
46
  parentCompany: string;
37
47
  /** Feature support matrix */