vskill 0.2.10 → 0.2.12
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.
- package/LICENSE +21 -0
- package/README.md +178 -145
- package/dist/commands/add.js +40 -31
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +6 -5
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/find.js +10 -5
- package/dist/commands/find.js.map +1 -1
- package/dist/utils/claude-cli.d.ts +7 -3
- package/dist/utils/claude-cli.js +8 -4
- package/dist/utils/claude-cli.js.map +1 -1
- package/dist/utils/claude-cli.test.js +10 -0
- package/dist/utils/claude-cli.test.js.map +1 -1
- package/dist/utils/prompts.js +65 -17
- package/dist/utils/prompts.js.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anton Abyzov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,226 +1,259 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">vskill</h1>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>The package manager for AI skills.</strong><br/>
|
|
5
|
+
Scan. Verify. Install. Across 49 agent platforms.
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
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
|
+
<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-49_platforms-0969DA" alt="49 agents" />
|
|
12
|
+
<img src="https://img.shields.io/badge/plugins-12-8B5CF6" alt="12 plugins" />
|
|
13
|
+
<img src="https://img.shields.io/badge/skills-41-10B981" alt="41 skills" />
|
|
14
|
+
<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" />
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<br/>
|
|
4
19
|
|
|
5
20
|
```bash
|
|
6
|
-
npx vskill install remotion-
|
|
7
|
-
npx vskill install remotion-dev/skills/remotion-best-practices # specific skill (3-part)
|
|
8
|
-
npx vskill install remotion-best-practices # registry lookup
|
|
21
|
+
npx vskill install remotion-best-practices
|
|
9
22
|
```
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
<br/>
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
## The Problem
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
**36.82% of AI skills have security flaws** ([Snyk ToxicSkills](https://snyk.io/blog/toxicskills-malicious-ai-agent-skills-clawhub/)).
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
# Install a specific plugin (recommended)
|
|
19
|
-
npx vskill install --repo anton-abyzov/vskill --plugin frontend
|
|
30
|
+
When you install a skill today, you're trusting blindly:
|
|
20
31
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
- **No scanning** — malicious prompts execute with full system access
|
|
33
|
+
- **No versioning** — silent updates can inject anything, anytime
|
|
34
|
+
- **No deduplication** — the same skill lives in 3 repos, all diverging
|
|
35
|
+
- **No blocklist** — known-bad skills install just fine
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
git clone https://github.com/anton-abyzov/vskill.git
|
|
27
|
-
npx vskill install --plugin-dir ./vskill --plugin frontend
|
|
28
|
-
```
|
|
37
|
+
vskill fixes all of this.
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
<br/>
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
## How It Works
|
|
33
42
|
|
|
34
43
|
```
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
45
|
+
│ Source │────>│ Scan │────>│ Verify │────>│ Install │
|
|
46
|
+
│ │ │ │ │ │ │ │
|
|
47
|
+
│ GitHub │ │ 38 rules │ │ LLM │ │ Pin SHA │
|
|
48
|
+
│ Registry │ │ Blocklist│ │ analysis │ │ Lock ver │
|
|
49
|
+
│ Local │ │ Patterns │ │ Intent │ │ Symlink │
|
|
50
|
+
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
|
40
51
|
```
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
Every install goes through the security pipeline. No exceptions. No `--skip-scan`.
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
<br/>
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Install from any GitHub repo
|
|
61
|
+
npx vskill install remotion-dev/skills/remotion-best-practices
|
|
62
|
+
|
|
63
|
+
# Install by name (registry lookup)
|
|
64
|
+
npx vskill install remotion-best-practices
|
|
65
|
+
|
|
66
|
+
# Browse a repo and pick interactively
|
|
67
|
+
npx vskill install remotion-dev/skills
|
|
68
|
+
|
|
69
|
+
# Install a plugin (Claude Code)
|
|
70
|
+
npx vskill install --repo anton-abyzov/vskill --plugin frontend
|
|
48
71
|
```
|
|
49
72
|
|
|
50
|
-
|
|
73
|
+
Or install globally: `npm install -g vskill`
|
|
51
74
|
|
|
52
|
-
|
|
53
|
-
|--------|--------|
|
|
54
|
-
| frontend | `frontend-core`, `architect`, `design`, `design-system`, `nextjs`, `figma`, `code-explorer`, `i18n` |
|
|
55
|
-
| backend | `nodejs`, `python`, `dotnet`, `go`, `rust`, `java-spring`, `graphql`, `db-optimizer` |
|
|
56
|
-
| infra | `terraform`, `aws`, `azure`, `gcp`, `github-actions`, `devops`, `devsecops`, `secrets`, `observability`, `opentelemetry` |
|
|
57
|
-
| mobile | `react-native`, `expo`, `flutter`, `swiftui`, `jetpack`, `capacitor`, `deep-linking`, `testing`, `appstore` |
|
|
58
|
-
| ml | `engineer`, `mlops`, `data-scientist`, `fine-tuning`, `rag`, `langchain`, `huggingface`, `edge`, `specialist` |
|
|
59
|
-
| testing | `unit`, `e2e`, `performance`, `accessibility`, `mutation`, `qa` |
|
|
60
|
-
| k8s | `manifests`, `helm`, `gitops`, `security` |
|
|
61
|
-
| payments | `payment-core`, `billing`, `pci` |
|
|
62
|
-
| cost | `cloud-pricing`, `optimization`, `aws` |
|
|
63
|
-
| kafka | `architect`, `ops`, `streams-topology`, `n8n` |
|
|
64
|
-
| confluent | `kafka-connect`, `ksqldb`, `schema-registry` |
|
|
65
|
-
| docs | `docusaurus`, `technical-writing`, `brainstorming` |
|
|
66
|
-
| security | `security-core`, `patterns`, `simplifier` |
|
|
67
|
-
| skills | `scout` |
|
|
68
|
-
| blockchain | `blockchain-core` |
|
|
75
|
+
<br/>
|
|
69
76
|
|
|
70
|
-
##
|
|
77
|
+
## Three-Tier Verification
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
| Tier | How | Trust Level |
|
|
80
|
+
|:-----|:----|:------------|
|
|
81
|
+
| **Scanned** | 38 deterministic pattern checks against known attack vectors | Baseline |
|
|
82
|
+
| **Verified** | Pattern scan + LLM-based intent analysis for subtle threats | Recommended |
|
|
83
|
+
| **Certified** | Full manual security review by the vskill team | Highest |
|
|
75
84
|
|
|
76
|
-
vskill
|
|
85
|
+
Every install is at minimum **Scanned**. The `vskill.lock` file tracks the SHA-256 hash, scan date, and tier for every installed skill. Running `vskill update` diffs against the locked version and re-scans before applying.
|
|
77
86
|
|
|
78
|
-
|
|
87
|
+
<br/>
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
## 49 Agent Platforms
|
|
81
90
|
|
|
82
|
-
|
|
83
|
-
vskill install remotion-dev/skills
|
|
84
|
-
```
|
|
91
|
+
vskill auto-detects your installed agents and installs skills to all of them at once.
|
|
85
92
|
|
|
86
|
-
|
|
93
|
+
**CLI & Terminal** — Claude Code, Cursor, GitHub Copilot, Windsurf, Codex, Gemini CLI, Amp, Cline, Roo Code, Goose, Aider, Kilo, Devin, OpenHands, Qwen Code, Trae, and more
|
|
87
94
|
|
|
88
|
-
|
|
95
|
+
**IDE Extensions** — VS Code, JetBrains, Zed, Neovim, Emacs, Sublime Text, Xcode
|
|
89
96
|
|
|
90
|
-
|
|
91
|
-
vskill install remotion-dev/skills/remotion-best-practices
|
|
92
|
-
```
|
|
97
|
+
**Cloud & Hosted** — Replit, Bolt, v0, GPT Pilot, Plandex, Sweep
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
<br/>
|
|
95
100
|
|
|
96
|
-
|
|
101
|
+
## Plugin Marketplace
|
|
102
|
+
|
|
103
|
+
vskill ships **41 expert skills** organized into **12 domain plugins**. Each plugin has its own namespace — install only what you need.
|
|
97
104
|
|
|
98
105
|
```bash
|
|
99
|
-
vskill install
|
|
106
|
+
npx vskill install --repo anton-abyzov/vskill --plugin frontend
|
|
107
|
+
npx vskill install --repo anton-abyzov/vskill --plugin infra
|
|
100
108
|
```
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
### 4. Registry lookup
|
|
110
|
+
Then invoke as `/plugin:skill` in your agent:
|
|
105
111
|
|
|
106
|
-
```
|
|
107
|
-
|
|
112
|
+
```
|
|
113
|
+
/frontend:nextjs /infra:aws /mobile:flutter
|
|
114
|
+
/ml:rag /testing:mutation /security:patterns
|
|
108
115
|
```
|
|
109
116
|
|
|
110
|
-
|
|
117
|
+
### Available Plugins
|
|
111
118
|
|
|
112
|
-
|
|
119
|
+
<table>
|
|
120
|
+
<tr>
|
|
121
|
+
<td width="50%" valign="top">
|
|
113
122
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
```
|
|
123
|
+
**frontend** — React 19, Next.js, Figma, i18n, design systems
|
|
124
|
+
- `frontend-core` `design` `figma` `i18n` `nextjs`
|
|
117
125
|
|
|
118
|
-
|
|
126
|
+
**backend** — Java Spring Boot, Rust
|
|
127
|
+
- `java-spring` `rust`
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
**infra** — AWS, Azure, GCP, CI/CD, secrets, observability
|
|
130
|
+
- `aws` `azure` `gcp` `github-actions` `devsecops` `opentelemetry` `secrets`
|
|
121
131
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
132
|
+
**mobile** — React Native, Flutter, SwiftUI, Jetpack, app store
|
|
133
|
+
- `react-native` `expo` `flutter` `swiftui` `jetpack` `capacitor` `deep-linking` `testing` `appstore`
|
|
134
|
+
|
|
135
|
+
**ml** — RAG, LangChain, Hugging Face, fine-tuning, edge ML
|
|
136
|
+
- `rag` `langchain` `huggingface` `fine-tuning` `edge`
|
|
137
|
+
|
|
138
|
+
**testing** — Performance, accessibility, mutation testing
|
|
139
|
+
- `performance` `accessibility` `mutation`
|
|
140
|
+
|
|
141
|
+
</td>
|
|
142
|
+
<td width="50%" valign="top">
|
|
125
143
|
|
|
126
|
-
|
|
144
|
+
**kafka** — Kafka Streams, n8n workflows
|
|
145
|
+
- `streams-topology` `n8n`
|
|
127
146
|
|
|
128
|
-
|
|
147
|
+
**confluent** — Kafka Connect, ksqlDB, Schema Registry
|
|
148
|
+
- `kafka-connect` `ksqldb` `schema-registry`
|
|
129
149
|
|
|
130
|
-
|
|
150
|
+
**payments** — Billing, subscriptions, PCI compliance
|
|
151
|
+
- `billing` `pci`
|
|
131
152
|
|
|
132
|
-
|
|
153
|
+
**security** — Vulnerability pattern detection
|
|
154
|
+
- `patterns`
|
|
133
155
|
|
|
134
|
-
|
|
135
|
-
-
|
|
136
|
-
- **Method** — Symlink (default, saves disk) or Copy (for agents that need it)
|
|
137
|
-
- **Skill selection** — when a repo has multiple skills, pick which ones to install
|
|
138
|
-
- **Claude Code native plugin** — when installing a plugin with Claude Code detected, choose native plugin install (recommended) or skill extraction
|
|
156
|
+
**blockchain** — Solidity, Foundry, smart contracts
|
|
157
|
+
- `blockchain-core`
|
|
139
158
|
|
|
140
|
-
|
|
159
|
+
**skills** — Skill discovery and recommendations
|
|
160
|
+
- `scout`
|
|
161
|
+
|
|
162
|
+
</td>
|
|
163
|
+
</tr>
|
|
164
|
+
</table>
|
|
165
|
+
|
|
166
|
+
<br/>
|
|
141
167
|
|
|
142
168
|
## Commands
|
|
143
169
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
170
|
+
```
|
|
171
|
+
vskill install <source> Install skill after security scan
|
|
172
|
+
vskill find <query> Search the verified-skill.com registry
|
|
173
|
+
vskill scan <path> Run security scan without installing
|
|
174
|
+
vskill list Show installed skills with status
|
|
175
|
+
vskill remove <skill> Remove an installed skill
|
|
176
|
+
vskill update [skill] Update with diff scanning (--all for everything)
|
|
177
|
+
vskill audit [path] Full project security audit with LLM analysis
|
|
178
|
+
vskill info <skill> Show detailed skill information
|
|
179
|
+
vskill submit <source> Submit a skill for verification
|
|
180
|
+
vskill blocklist Manage blocked malicious skills
|
|
181
|
+
vskill init Initialize vskill in a project
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
<details>
|
|
185
|
+
<summary><strong>Install flags</strong></summary>
|
|
159
186
|
|
|
160
187
|
| Flag | Description |
|
|
161
|
-
|
|
162
|
-
| `--yes`
|
|
163
|
-
| `--global`
|
|
188
|
+
|:-----|:------------|
|
|
189
|
+
| `--yes` `-y` | Accept defaults, no prompts |
|
|
190
|
+
| `--global` `-g` | Install to global scope |
|
|
164
191
|
| `--copy` | Copy files instead of symlinking |
|
|
165
|
-
| `--skill <name>` |
|
|
166
|
-
| `--plugin <name>` |
|
|
167
|
-
| `--plugin-dir <path>` |
|
|
168
|
-
| `--repo <owner/repo>` |
|
|
169
|
-
| `--agent <id>` | Target a specific agent (e.g.,
|
|
192
|
+
| `--skill <name>` | Pick a specific skill from a multi-skill repo |
|
|
193
|
+
| `--plugin <name>` | Pick a plugin from a marketplace repo |
|
|
194
|
+
| `--plugin-dir <path>` | Local directory as plugin source |
|
|
195
|
+
| `--repo <owner/repo>` | Remote GitHub repo as plugin source |
|
|
196
|
+
| `--agent <id>` | Target a specific agent (e.g., `cursor`) |
|
|
170
197
|
| `--force` | Install even if blocklisted |
|
|
171
|
-
| `--cwd <path>` | Override project root
|
|
198
|
+
| `--cwd <path>` | Override project root |
|
|
199
|
+
| `--all` | Install all skills from a repo |
|
|
172
200
|
|
|
173
|
-
|
|
201
|
+
</details>
|
|
174
202
|
|
|
175
|
-
|
|
203
|
+
<br/>
|
|
176
204
|
|
|
177
|
-
|
|
205
|
+
## Security Audit
|
|
178
206
|
|
|
179
|
-
|
|
207
|
+
Scan entire projects for security issues — not just skills:
|
|
180
208
|
|
|
181
|
-
|
|
209
|
+
```bash
|
|
210
|
+
vskill audit # scan current directory
|
|
211
|
+
vskill audit --ci --report sarif # CI-friendly SARIF output
|
|
212
|
+
vskill audit --severity high,critical # filter by severity
|
|
213
|
+
```
|
|
182
214
|
|
|
183
|
-
|
|
215
|
+
<br/>
|
|
184
216
|
|
|
185
|
-
|
|
186
|
-
- **Inside a plugin**: [`anthropics/claude-code`](https://github.com/anthropics/claude-code/blob/main/plugins/frontend-design/skills/frontend-design/SKILL.md)
|
|
217
|
+
## Skills vs Plugins
|
|
187
218
|
|
|
188
|
-
|
|
219
|
+
**Skills** are single `SKILL.md` files that work with any of the 49 supported agents. They follow the [Agent Skills Standard](https://agentskills.io) — drop a `SKILL.md` into the agent's commands directory.
|
|
189
220
|
|
|
190
|
-
|
|
221
|
+
**Plugins** are multi-component containers for Claude Code. They bundle skills, hooks, commands, and agents under a single namespace with enable/disable support and marketplace integration.
|
|
191
222
|
|
|
192
|
-
|
|
223
|
+
<br/>
|
|
193
224
|
|
|
194
|
-
|
|
225
|
+
## Why Deduplication Matters
|
|
195
226
|
|
|
196
|
-
|
|
197
|
-
2. Registers the plugin directory as a marketplace: `claude plugin marketplace add <path>`
|
|
198
|
-
3. Installs the plugin natively: `claude plugin install <plugin>@<marketplace>`
|
|
227
|
+
Even Anthropic ships the same skill in two places:
|
|
199
228
|
|
|
200
|
-
|
|
229
|
+
- [`anthropics/skills/frontend-design`](https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md) (standalone)
|
|
230
|
+
- [`anthropics/claude-code/.../frontend-design`](https://github.com/anthropics/claude-code/blob/main/plugins/frontend-design/skills/frontend-design/SKILL.md) (plugin)
|
|
201
231
|
|
|
202
|
-
|
|
232
|
+
Install both? Duplicates. They diverge? Inconsistencies. vskill gives you one install path with version pinning and dedup, regardless of source.
|
|
203
233
|
|
|
204
|
-
|
|
234
|
+
<br/>
|
|
205
235
|
|
|
206
|
-
|
|
236
|
+
## Registry
|
|
207
237
|
|
|
208
|
-
|
|
238
|
+
Browse and search verified skills at **[verified-skill.com](https://verified-skill.com)**.
|
|
209
239
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
| **Certified** | Full manual security review | Highest Trust |
|
|
240
|
+
```bash
|
|
241
|
+
vskill find "react native" # search from CLI
|
|
242
|
+
vskill info remotion-best-practices # skill details
|
|
243
|
+
```
|
|
215
244
|
|
|
216
|
-
|
|
245
|
+
<br/>
|
|
217
246
|
|
|
218
|
-
|
|
247
|
+
## Contributing
|
|
219
248
|
|
|
220
|
-
|
|
249
|
+
Submit your skill for verification:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
vskill submit your-org/your-repo/your-skill
|
|
253
|
+
```
|
|
221
254
|
|
|
222
|
-
|
|
255
|
+
<br/>
|
|
223
256
|
|
|
224
257
|
## License
|
|
225
258
|
|
|
226
|
-
MIT
|
|
259
|
+
[MIT](LICENSE)
|
package/dist/commands/add.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// vskill install -- install a skill from GitHub or local plugin directory
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
-
import { mkdirSync,
|
|
4
|
+
import { mkdirSync, writeFileSync, readFileSync, existsSync, copyFileSync, statSync, chmodSync, readdirSync, rmSync, } from "node:fs";
|
|
5
5
|
import { join, resolve, basename } from "node:path";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
7
|
import { execSync } from "node:child_process";
|
|
@@ -159,12 +159,29 @@ async function installMarketplaceRepo(owner, repo, manifestContent, opts, preSel
|
|
|
159
159
|
console.log(dim(`Auto-selecting all ${plugins.length} plugins (--yes/--all)`));
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
+
else if (plugins.length === 1) {
|
|
163
|
+
// Single plugin — skip multi-select, just proceed
|
|
164
|
+
const p = plugins[0];
|
|
165
|
+
const isInstalled = installedSet.has(p.name);
|
|
166
|
+
if (isInstalled) {
|
|
167
|
+
const prompter = createPrompter();
|
|
168
|
+
const reinstall = await prompter.promptConfirm(`${bold(p.name)} is already installed. Reinstall?`, true);
|
|
169
|
+
if (!reinstall) {
|
|
170
|
+
console.log(dim("Aborted."));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log(` ${green("+")} ${bold(p.name)}${p.description ? dim(` — ${p.description}`) : ""}`);
|
|
176
|
+
}
|
|
177
|
+
selectedPlugins = plugins;
|
|
178
|
+
}
|
|
162
179
|
else {
|
|
163
180
|
const prompter = createPrompter();
|
|
164
181
|
const indices = await prompter.promptCheckboxList(plugins.map((p) => ({
|
|
165
182
|
label: p.name + (installedSet.has(p.name) ? dim(" (installed)") : ""),
|
|
166
183
|
description: p.description,
|
|
167
|
-
checked: preSelected ? preSelected.includes(p.name) :
|
|
184
|
+
checked: preSelected ? preSelected.includes(p.name) : installedSet.has(p.name),
|
|
168
185
|
})), { title: "Select plugins to install" });
|
|
169
186
|
if (indices.length === 0) {
|
|
170
187
|
console.log(dim("No plugins selected. Aborting."));
|
|
@@ -174,26 +191,16 @@ async function installMarketplaceRepo(owner, repo, manifestContent, opts, preSel
|
|
|
174
191
|
}
|
|
175
192
|
// Attempt native Claude Code install
|
|
176
193
|
const hasClaude = !opts.copy && isClaudeCliAvailable();
|
|
177
|
-
let tmpDir = null;
|
|
178
194
|
let marketplaceRegistered = false;
|
|
179
195
|
if (hasClaude) {
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
marketplaceRegistered = registerMarketplace(tmpDir);
|
|
189
|
-
regSpin.stop();
|
|
190
|
-
if (!marketplaceRegistered) {
|
|
191
|
-
console.log(yellow(" Failed to register marketplace — will use extraction fallback."));
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
cloneSpin.stop();
|
|
196
|
-
console.log(yellow(" Clone failed — will use extraction fallback."));
|
|
196
|
+
// Register marketplace via git URL — Claude Code clones to its own
|
|
197
|
+
// persistent location, avoiding the stale-temp-dir bug.
|
|
198
|
+
const gitUrl = `https://github.com/${owner}/${repo}`;
|
|
199
|
+
const regSpin = spinner("Registering marketplace with Claude Code");
|
|
200
|
+
marketplaceRegistered = registerMarketplace(gitUrl);
|
|
201
|
+
regSpin.stop();
|
|
202
|
+
if (!marketplaceRegistered) {
|
|
203
|
+
console.log(yellow(" Failed to register marketplace — will use extraction fallback."));
|
|
197
204
|
}
|
|
198
205
|
}
|
|
199
206
|
// Install each plugin
|
|
@@ -232,13 +239,6 @@ async function installMarketplaceRepo(owner, repo, manifestContent, opts, preSel
|
|
|
232
239
|
}
|
|
233
240
|
}
|
|
234
241
|
}
|
|
235
|
-
// Cleanup temp directory
|
|
236
|
-
if (tmpDir) {
|
|
237
|
-
try {
|
|
238
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
239
|
-
}
|
|
240
|
-
catch { /* ignore */ }
|
|
241
|
-
}
|
|
242
242
|
// Update lockfile
|
|
243
243
|
const lockForWrite = ensureLockfile(lockDir);
|
|
244
244
|
for (const r of results) {
|
|
@@ -354,7 +354,7 @@ function cleanPluginCache(pluginName, marketplace) {
|
|
|
354
354
|
* - --copy flag is NOT set
|
|
355
355
|
* - User opts in (interactive prompt) OR --yes flag is set
|
|
356
356
|
*/
|
|
357
|
-
async function tryNativeClaudeInstall(marketplacePath, marketplaceContent, pluginName, opts) {
|
|
357
|
+
async function tryNativeClaudeInstall(marketplacePath, marketplaceContent, pluginName, opts, gitUrl) {
|
|
358
358
|
if (opts.copy)
|
|
359
359
|
return false;
|
|
360
360
|
if (!isClaudeCliAvailable())
|
|
@@ -372,9 +372,10 @@ async function tryNativeClaudeInstall(marketplacePath, marketplaceContent, plugi
|
|
|
372
372
|
if (choice !== 0)
|
|
373
373
|
return false;
|
|
374
374
|
}
|
|
375
|
-
// Register marketplace
|
|
375
|
+
// Register marketplace — prefer git URL (persistent) over local path
|
|
376
|
+
// (which may be a temp dir that gets deleted after install).
|
|
376
377
|
const regSpin = spinner("Registering marketplace with Claude Code");
|
|
377
|
-
const registered = registerMarketplace(marketplacePath);
|
|
378
|
+
const registered = registerMarketplace(gitUrl || marketplacePath);
|
|
378
379
|
if (!registered) {
|
|
379
380
|
regSpin.stop();
|
|
380
381
|
console.log(yellow(" Failed to register marketplace — falling back to extraction."));
|
|
@@ -725,7 +726,15 @@ async function installPluginDir(basePath, pluginName, opts) {
|
|
|
725
726
|
const hasClaude = selectedAgents.some((a) => a.id === "claude-code");
|
|
726
727
|
let claudeNativeSuccess = false;
|
|
727
728
|
if (hasClaude) {
|
|
728
|
-
|
|
729
|
+
// Try to extract git remote URL for persistent marketplace registration.
|
|
730
|
+
// Falls back to the local path if the dir is not a git repo.
|
|
731
|
+
let gitUrl;
|
|
732
|
+
try {
|
|
733
|
+
gitUrl = execSync("git remote get-url origin", { cwd: resolve(basePath), stdio: ["pipe", "pipe", "ignore"], timeout: 5_000 })
|
|
734
|
+
.toString().trim() || undefined;
|
|
735
|
+
}
|
|
736
|
+
catch { /* not a git repo or no remote — use local path */ }
|
|
737
|
+
claudeNativeSuccess = await tryNativeClaudeInstall(resolve(basePath), mktContent, pluginName, opts, gitUrl);
|
|
729
738
|
}
|
|
730
739
|
// Filter Claude Code out of extraction if native install succeeded
|
|
731
740
|
const extractionAgents = claudeNativeSuccess
|