@lpm-registry/cli 0.5.0 → 0.6.0
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/CHANGELOG.md +16 -0
- package/bin/lpm.js +157 -213
- package/index.d.ts +2 -2
- package/lib/commands/quality.js +3 -3
- package/lib/quality/checks.js +37 -37
- package/lib/quality/display.js +4 -4
- package/lib/quality/score.js +5 -5
- package/lib/quality/swift-checks.js +18 -18
- package/package.json +6 -1
- package/scripts/install-binary.js +178 -37
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.6.0] - 2026-04-01
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Platform optionalDependencies (esbuild pattern)** — Native Rust binary now delivered via platform-specific npm packages (`@lpm-registry/cli-darwin-arm64`, etc.) instead of postinstall download. npm automatically installs only the matching platform package.
|
|
10
|
+
- **Hard-link optimization** — Postinstall hard-links the native binary over `bin/lpm.js`, so `lpm` on PATH executes the Rust binary directly with zero Node.js overhead.
|
|
11
|
+
- **3-tier binary resolution** — Entry point tries: (1) platform package binary, (2) GitHub Releases download fallback, (3) JS CLI fallback. Covers `--no-optional`, cross-device mounts, and offline scenarios.
|
|
12
|
+
- **`LPM_BINARY_PATH` env override** — Point to a custom binary for debugging or local development.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **Rust binary v0.6.0** — Sigstore provenance signing, behavioral + supply-chain security tags, `lpm self-update`, `lpm tunnel`, `lpm vault`, `lpm migrate`, `lpm graph`, TUI dashboard, Xcode project editing, import rewriting enhancements, and more.
|
|
17
|
+
- Quality check field renamed `maxPoints` → `max_points` for consistency with registry API responses.
|
|
18
|
+
- `bin/lpm.js` rewritten from simple lpm-bin delegate to full 3-tier resolver with platform package support.
|
|
19
|
+
- `scripts/install-binary.js` rewritten with esbuild-pattern hard-link optimization.
|
|
20
|
+
|
|
5
21
|
## [0.5.0] - 2026-03-25
|
|
6
22
|
|
|
7
23
|
### Changed
|
package/bin/lpm.js
CHANGED
|
@@ -1,33 +1,76 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* LPM CLI Entry Point — Minimal fallback wrapper.
|
|
5
|
+
*
|
|
6
|
+
* In most cases, this file has been replaced by a hard link to the native
|
|
7
|
+
* Rust binary during postinstall (zero Node.js overhead). This JS wrapper
|
|
8
|
+
* only runs when:
|
|
9
|
+
*
|
|
10
|
+
* 1. Hard-link failed (cross-device mount, permissions)
|
|
11
|
+
* 2. npm rebuild recreated the symlink
|
|
12
|
+
* 3. Binary download failed during postinstall
|
|
13
|
+
*
|
|
14
|
+
* Resolution order:
|
|
15
|
+
* 1. Try platform package binary (optionalDependencies)
|
|
16
|
+
* 2. Try lpm-bin in bin/ directory (GitHub Releases download)
|
|
17
|
+
* 3. Fall through to JS CLI implementation
|
|
18
|
+
*/
|
|
19
|
+
|
|
3
20
|
import { execFileSync } from "node:child_process"
|
|
4
21
|
import fs from "node:fs"
|
|
22
|
+
import { createRequire } from "node:module"
|
|
23
|
+
import os from "node:os"
|
|
5
24
|
import path from "node:path"
|
|
6
25
|
import { fileURLToPath } from "node:url"
|
|
7
26
|
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
27
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
28
|
+
const require = createRequire(import.meta.url)
|
|
29
|
+
|
|
30
|
+
// ─── Try native binary (Tier 1: platform package) ──────────────────
|
|
31
|
+
|
|
32
|
+
const PLATFORMS = {
|
|
33
|
+
"darwin-arm64": { pkg: "@lpm-registry/cli-darwin-arm64", binary: "lpm" },
|
|
34
|
+
"darwin-x64": { pkg: "@lpm-registry/cli-darwin-x64", binary: "lpm" },
|
|
35
|
+
"linux-x64": { pkg: "@lpm-registry/cli-linux-x64", binary: "lpm" },
|
|
36
|
+
"linux-arm64": { pkg: "@lpm-registry/cli-linux-arm64", binary: "lpm" },
|
|
37
|
+
"win32-x64": { pkg: "@lpm-registry/cli-win32-x64", binary: "lpm.exe" },
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Allow override via environment variable (for debugging / custom builds)
|
|
41
|
+
const envBinary = process.env.LPM_BINARY_PATH
|
|
42
|
+
if (envBinary && fs.existsSync(envBinary)) {
|
|
43
|
+
runBinary(envBinary)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Try platform package from optionalDependencies
|
|
47
|
+
const platform = `${process.platform}-${os.arch()}`
|
|
48
|
+
const platformInfo = PLATFORMS[platform]
|
|
12
49
|
|
|
13
|
-
if (
|
|
50
|
+
if (platformInfo) {
|
|
14
51
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
})
|
|
20
|
-
process.exit(0)
|
|
21
|
-
} catch (err) {
|
|
22
|
-
// execFileSync throws on non-zero exit — propagate the exit code
|
|
23
|
-
if (err.status != null) {
|
|
24
|
-
process.exit(err.status)
|
|
52
|
+
const pkgJsonPath = require.resolve(`${platformInfo.pkg}/package.json`)
|
|
53
|
+
const binaryPath = path.join(path.dirname(pkgJsonPath), platformInfo.binary)
|
|
54
|
+
if (fs.existsSync(binaryPath)) {
|
|
55
|
+
runBinary(binaryPath)
|
|
25
56
|
}
|
|
26
|
-
|
|
57
|
+
} catch {
|
|
58
|
+
// Package not installed
|
|
27
59
|
}
|
|
28
60
|
}
|
|
29
61
|
|
|
30
|
-
// ───
|
|
62
|
+
// ─── Try native binary (Tier 2: downloaded by postinstall) ─────────
|
|
63
|
+
|
|
64
|
+
const legacyBinaryName =
|
|
65
|
+
process.platform === "win32" ? "lpm-bin.exe" : "lpm-bin"
|
|
66
|
+
const legacyBinaryPath = path.join(__dirname, legacyBinaryName)
|
|
67
|
+
|
|
68
|
+
if (fs.existsSync(legacyBinaryPath)) {
|
|
69
|
+
runBinary(legacyBinaryPath)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ─── JS CLI fallback (Tier 3) ──────────────────────────────────────
|
|
73
|
+
|
|
31
74
|
import { Command } from "commander"
|
|
32
75
|
import updateNotifier from "update-notifier"
|
|
33
76
|
import { add } from "../lib/commands/add.js"
|
|
@@ -65,7 +108,6 @@ import { uninstall } from "../lib/commands/uninstall.js"
|
|
|
65
108
|
import { whoami } from "../lib/commands/whoami.js"
|
|
66
109
|
|
|
67
110
|
// Load package.json
|
|
68
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
69
111
|
const pkg = JSON.parse(
|
|
70
112
|
fs.readFileSync(path.join(__dirname, "../package.json"), "utf-8"),
|
|
71
113
|
)
|
|
@@ -80,16 +122,12 @@ program
|
|
|
80
122
|
.description("CLI for Licensed Package Manager")
|
|
81
123
|
.version(pkg.version)
|
|
82
124
|
|
|
83
|
-
//
|
|
84
|
-
// Authentication Commands
|
|
85
|
-
// ============================================================================
|
|
86
|
-
|
|
125
|
+
// Authentication
|
|
87
126
|
program
|
|
88
127
|
.command("login")
|
|
89
128
|
.alias("l")
|
|
90
129
|
.description("Authenticate with the registry")
|
|
91
130
|
.action(login)
|
|
92
|
-
|
|
93
131
|
program
|
|
94
132
|
.command("logout")
|
|
95
133
|
.alias("lo")
|
|
@@ -97,307 +135,213 @@ program
|
|
|
97
135
|
.option("--revoke", "Also revoke the token on the server")
|
|
98
136
|
.option("--clear-cache", "Clear local package cache")
|
|
99
137
|
.action(logout)
|
|
100
|
-
|
|
101
138
|
program
|
|
102
139
|
.command("whoami")
|
|
103
140
|
.description("Check current authenticated user")
|
|
104
141
|
.option("--json", "Output in JSON format")
|
|
105
142
|
.action(whoami)
|
|
106
143
|
|
|
107
|
-
//
|
|
108
|
-
// Package Management Commands
|
|
109
|
-
// ============================================================================
|
|
110
|
-
|
|
144
|
+
// Package Management
|
|
111
145
|
program
|
|
112
146
|
.command("init")
|
|
113
147
|
.description("Interactively create a package.json for LPM")
|
|
114
148
|
.action(init)
|
|
115
|
-
|
|
116
149
|
program
|
|
117
150
|
.command("install [packages...]")
|
|
118
151
|
.alias("i")
|
|
119
|
-
.description("Install packages
|
|
152
|
+
.description("Install packages")
|
|
120
153
|
.option("--json", "Machine-readable JSON output")
|
|
121
|
-
.option("--no-skills", "Skip fetching Agent Skills
|
|
122
|
-
.option(
|
|
123
|
-
"--no-editor-setup",
|
|
124
|
-
"Skip auto-configuring AI editor integration for skills",
|
|
125
|
-
)
|
|
126
|
-
.option("--pm <manager>", "Package manager to use (npm, pnpm, yarn, bun)")
|
|
154
|
+
.option("--no-skills", "Skip fetching Agent Skills")
|
|
155
|
+
.option("--pm <manager>", "Package manager to use")
|
|
127
156
|
.action(install)
|
|
128
|
-
|
|
129
157
|
program
|
|
130
158
|
.command("uninstall <packages...>")
|
|
131
159
|
.aliases(["un", "unlink"])
|
|
132
|
-
.description("Uninstall packages
|
|
133
|
-
.option("--pm <manager>", "Package manager to use
|
|
160
|
+
.description("Uninstall packages")
|
|
161
|
+
.option("--pm <manager>", "Package manager to use")
|
|
134
162
|
.action(uninstall)
|
|
135
|
-
|
|
136
163
|
program
|
|
137
164
|
.command("publish")
|
|
138
165
|
.alias("p")
|
|
139
166
|
.description("Publish a package to the registry")
|
|
140
|
-
.option("--check", "
|
|
141
|
-
.option(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
)
|
|
145
|
-
.option(
|
|
146
|
-
"--provenance",
|
|
147
|
-
"Force OIDC token exchange for secret-free publishing (auto-detected in GitHub Actions with id-token: write)",
|
|
148
|
-
)
|
|
149
|
-
.option(
|
|
150
|
-
"--dry-run",
|
|
151
|
-
"Validate and preview the publish (files, size, OIDC status) without uploading",
|
|
152
|
-
)
|
|
167
|
+
.option("--check", "Quality check only")
|
|
168
|
+
.option("--min-score <score>", "Minimum quality score")
|
|
169
|
+
.option("--provenance", "Force OIDC provenance")
|
|
170
|
+
.option("--dry-run", "Preview without publishing")
|
|
153
171
|
.action(publish)
|
|
154
|
-
|
|
155
172
|
program
|
|
156
173
|
.command("add <package>")
|
|
157
|
-
.description("
|
|
158
|
-
.option("-p, --path <path>", "Target directory
|
|
159
|
-
.option("-f, --force", "Overwrite existing files
|
|
160
|
-
.option("-y, --yes", "Accept defaults
|
|
161
|
-
.option("--alias <alias>", "Import alias prefix
|
|
162
|
-
.option("--target <name>", "Swift SPM target
|
|
163
|
-
.option("--
|
|
164
|
-
.option("--
|
|
165
|
-
.option("--json", "Machine-readable JSON output")
|
|
166
|
-
.option("--dry-run", "Preview what would happen without writing files")
|
|
167
|
-
.option("--no-skills", "Skip fetching Agent Skills after add")
|
|
174
|
+
.description("Extract package source code")
|
|
175
|
+
.option("-p, --path <path>", "Target directory")
|
|
176
|
+
.option("-f, --force", "Overwrite existing files")
|
|
177
|
+
.option("-y, --yes", "Accept defaults")
|
|
178
|
+
.option("--alias <alias>", "Import alias prefix")
|
|
179
|
+
.option("--target <name>", "Swift SPM target")
|
|
180
|
+
.option("--json", "JSON output")
|
|
181
|
+
.option("--dry-run", "Preview only")
|
|
168
182
|
.action(add)
|
|
169
|
-
|
|
170
183
|
program
|
|
171
184
|
.command("remove <package>")
|
|
172
185
|
.alias("rm")
|
|
173
|
-
.description(
|
|
174
|
-
"Remove a previously added package (e.g., MCP servers from editors)",
|
|
175
|
-
)
|
|
186
|
+
.description("Remove a previously added package")
|
|
176
187
|
.action(remove)
|
|
177
188
|
|
|
178
|
-
//
|
|
179
|
-
// Package Discovery Commands
|
|
180
|
-
// ============================================================================
|
|
181
|
-
|
|
189
|
+
// Discovery
|
|
182
190
|
program
|
|
183
191
|
.command("search <query>")
|
|
184
|
-
.description("Search
|
|
185
|
-
.option("--limit <n>", "
|
|
186
|
-
.option("--json", "
|
|
187
|
-
.action((
|
|
188
|
-
search(query, { ...options, limit: parseInt(options.limit, 10) }),
|
|
189
|
-
)
|
|
190
|
-
|
|
192
|
+
.description("Search packages")
|
|
193
|
+
.option("--limit <n>", "Max results", "20")
|
|
194
|
+
.option("--json", "JSON output")
|
|
195
|
+
.action((q, o) => search(q, { ...o, limit: parseInt(o.limit, 10) }))
|
|
191
196
|
program
|
|
192
197
|
.command("info <package>")
|
|
193
|
-
.description("
|
|
194
|
-
.option("--json", "
|
|
198
|
+
.description("Package info")
|
|
199
|
+
.option("--json", "JSON output")
|
|
195
200
|
.option("-a, --all-versions", "Show all versions")
|
|
196
201
|
.action(info)
|
|
197
|
-
|
|
198
202
|
program
|
|
199
203
|
.command("check-name <name>")
|
|
200
|
-
.description("Check
|
|
201
|
-
.option("--json", "
|
|
204
|
+
.description("Check name availability")
|
|
205
|
+
.option("--json", "JSON output")
|
|
202
206
|
.action(checkName)
|
|
203
|
-
|
|
204
207
|
program
|
|
205
208
|
.command("quality <package>")
|
|
206
|
-
.description("
|
|
207
|
-
.option("--json", "
|
|
209
|
+
.description("Quality report")
|
|
210
|
+
.option("--json", "JSON output")
|
|
208
211
|
.action(quality)
|
|
209
212
|
|
|
210
|
-
//
|
|
211
|
-
// Security & Maintenance Commands
|
|
212
|
-
// ============================================================================
|
|
213
|
-
|
|
213
|
+
// Maintenance
|
|
214
214
|
program
|
|
215
215
|
.command("audit [action]")
|
|
216
|
-
.description("
|
|
217
|
-
.option("--json", "
|
|
218
|
-
.option(
|
|
219
|
-
"--level <level>",
|
|
220
|
-
"Minimum severity to report (low, moderate, high, critical)",
|
|
221
|
-
)
|
|
216
|
+
.description("Security audit")
|
|
217
|
+
.option("--json", "JSON output")
|
|
218
|
+
.option("--level <level>", "Minimum severity")
|
|
222
219
|
.action(audit)
|
|
223
|
-
|
|
224
220
|
program
|
|
225
221
|
.command("outdated")
|
|
226
|
-
.description("Check
|
|
227
|
-
.option("--json", "
|
|
228
|
-
.option("--all", "Show all
|
|
222
|
+
.description("Check outdated deps")
|
|
223
|
+
.option("--json", "JSON output")
|
|
224
|
+
.option("--all", "Show all deps")
|
|
229
225
|
.action(outdated)
|
|
226
|
+
program.command("doctor").description("Health check").action(doctor)
|
|
230
227
|
|
|
231
|
-
|
|
232
|
-
.command("doctor")
|
|
233
|
-
.description("Check the health of your LPM setup")
|
|
234
|
-
.action(doctor)
|
|
235
|
-
|
|
236
|
-
// ============================================================================
|
|
237
|
-
// Configuration Commands
|
|
238
|
-
// ============================================================================
|
|
239
|
-
|
|
228
|
+
// Configuration
|
|
240
229
|
program
|
|
241
230
|
.command("setup")
|
|
242
|
-
.description("Configure .npmrc
|
|
231
|
+
.description("Configure .npmrc")
|
|
243
232
|
.option("-r, --registry <url>", "Custom registry URL")
|
|
244
|
-
.option(
|
|
245
|
-
|
|
246
|
-
"Exchange CI OIDC token for install access (no secrets needed)",
|
|
247
|
-
)
|
|
248
|
-
.option(
|
|
249
|
-
"--scoped",
|
|
250
|
-
"Only route @lpm.dev packages through LPM (don't proxy npm)",
|
|
251
|
-
)
|
|
233
|
+
.option("--oidc", "Exchange OIDC token")
|
|
234
|
+
.option("--scoped", "Scoped registry only")
|
|
252
235
|
.action(setup)
|
|
253
|
-
|
|
254
236
|
program
|
|
255
237
|
.command("npmrc")
|
|
256
|
-
.description("Generate
|
|
257
|
-
.option("-d, --days <number>", "Token expiry
|
|
258
|
-
.option(
|
|
259
|
-
"--scoped",
|
|
260
|
-
"Only route @lpm.dev packages through LPM (don't proxy npm)",
|
|
261
|
-
)
|
|
238
|
+
.description("Generate read-only .npmrc token")
|
|
239
|
+
.option("-d, --days <number>", "Token expiry days")
|
|
240
|
+
.option("--scoped", "Scoped registry only")
|
|
262
241
|
.action(npmrc)
|
|
263
|
-
|
|
264
242
|
program
|
|
265
243
|
.command("config [action] [key] [value]")
|
|
266
|
-
.description("Manage CLI
|
|
244
|
+
.description("Manage CLI config")
|
|
267
245
|
.action(config)
|
|
268
|
-
|
|
269
246
|
program
|
|
270
247
|
.command("set <key> <value>")
|
|
271
248
|
.description('Shortcut for "lpm config set"')
|
|
272
|
-
.action((
|
|
273
|
-
|
|
249
|
+
.action((k, v) => config("set", k, v))
|
|
274
250
|
program
|
|
275
251
|
.command("cache <action>")
|
|
276
|
-
.description("Manage local
|
|
252
|
+
.description("Manage local cache")
|
|
277
253
|
.action(cache)
|
|
278
254
|
|
|
279
|
-
//
|
|
280
|
-
// Utility Commands
|
|
281
|
-
// ============================================================================
|
|
282
|
-
|
|
255
|
+
// Utility
|
|
283
256
|
program
|
|
284
257
|
.command("open")
|
|
285
|
-
.description("Open
|
|
258
|
+
.description("Open dashboard in browser")
|
|
286
259
|
.action(openDashboard)
|
|
287
|
-
|
|
288
260
|
program
|
|
289
261
|
.command("run <script>")
|
|
290
|
-
.description("Run npm scripts
|
|
262
|
+
.description("Run npm scripts")
|
|
291
263
|
.allowUnknownOption()
|
|
292
264
|
.action(run)
|
|
293
265
|
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const token = program
|
|
299
|
-
.command("token")
|
|
300
|
-
.description("Manage authentication tokens")
|
|
301
|
-
|
|
302
|
-
token
|
|
303
|
-
.command("rotate")
|
|
304
|
-
.description("Rotate the current token")
|
|
305
|
-
.action(rotateToken)
|
|
306
|
-
|
|
307
|
-
// ============================================================================
|
|
308
|
-
// Pool Revenue (Subcommand)
|
|
309
|
-
// ============================================================================
|
|
310
|
-
|
|
311
|
-
const pool = program.command("pool").description("Pool revenue commands")
|
|
266
|
+
// Subcommands
|
|
267
|
+
const token = program.command("token").description("Token management")
|
|
268
|
+
token.command("rotate").description("Rotate token").action(rotateToken)
|
|
312
269
|
|
|
270
|
+
const pool = program.command("pool").description("Pool revenue")
|
|
313
271
|
pool
|
|
314
272
|
.command("stats")
|
|
315
|
-
.description("
|
|
316
|
-
.option("--json", "
|
|
273
|
+
.description("Pool earnings")
|
|
274
|
+
.option("--json", "JSON output")
|
|
317
275
|
.action(poolStats)
|
|
318
276
|
|
|
319
|
-
|
|
320
|
-
// MCP Server (Subcommand)
|
|
321
|
-
// ============================================================================
|
|
322
|
-
|
|
323
|
-
const mcp = program.command("mcp").description("MCP server commands")
|
|
324
|
-
|
|
277
|
+
const mcp = program.command("mcp").description("MCP server")
|
|
325
278
|
mcp
|
|
326
279
|
.command("setup")
|
|
327
|
-
.description("Configure
|
|
328
|
-
.option("--project", "
|
|
280
|
+
.description("Configure MCP server")
|
|
281
|
+
.option("--project", "Project-level config")
|
|
329
282
|
.action(mcpSetup)
|
|
330
|
-
|
|
331
283
|
mcp
|
|
332
284
|
.command("remove")
|
|
333
|
-
.description("Remove
|
|
334
|
-
.option("--project", "
|
|
285
|
+
.description("Remove MCP server")
|
|
286
|
+
.option("--project", "Project-level only")
|
|
335
287
|
.action(mcpRemove)
|
|
336
|
-
|
|
337
288
|
mcp
|
|
338
289
|
.command("status")
|
|
339
|
-
.description("
|
|
340
|
-
.option("--verbose", "Show
|
|
290
|
+
.description("MCP server status")
|
|
291
|
+
.option("--verbose", "Show diagnostics")
|
|
341
292
|
.action(mcpStatus)
|
|
342
293
|
|
|
343
|
-
|
|
344
|
-
// Agent Skills (Subcommand)
|
|
345
|
-
// ============================================================================
|
|
346
|
-
|
|
347
|
-
const skills = program
|
|
348
|
-
.command("skills")
|
|
349
|
-
.description("Manage Agent Skills for AI coding assistants")
|
|
350
|
-
|
|
294
|
+
const skills = program.command("skills").description("Agent Skills")
|
|
351
295
|
skills
|
|
352
296
|
.command("validate")
|
|
353
|
-
.description("Validate
|
|
354
|
-
.option("--json", "
|
|
297
|
+
.description("Validate skills files")
|
|
298
|
+
.option("--json", "JSON output")
|
|
355
299
|
.action(skillsValidate)
|
|
356
|
-
|
|
357
300
|
skills
|
|
358
301
|
.command("install [package]")
|
|
359
|
-
.description(
|
|
360
|
-
|
|
361
|
-
)
|
|
362
|
-
.option("--json", "Output in JSON format")
|
|
363
|
-
.option(
|
|
364
|
-
"--no-editor-setup",
|
|
365
|
-
"Skip auto-configuring AI editor integration for skills",
|
|
366
|
-
)
|
|
302
|
+
.description("Install skills")
|
|
303
|
+
.option("--json", "JSON output")
|
|
367
304
|
.action(skillsInstall)
|
|
368
|
-
|
|
369
305
|
skills
|
|
370
306
|
.command("list")
|
|
371
|
-
.description("List available skills
|
|
372
|
-
.option("--json", "
|
|
307
|
+
.description("List available skills")
|
|
308
|
+
.option("--json", "JSON output")
|
|
373
309
|
.action(skillsList)
|
|
374
|
-
|
|
375
310
|
skills
|
|
376
311
|
.command("clean")
|
|
377
|
-
.description("Remove
|
|
378
|
-
.option("--json", "
|
|
312
|
+
.description("Remove installed skills")
|
|
313
|
+
.option("--json", "JSON output")
|
|
379
314
|
.action(skillsClean)
|
|
380
315
|
|
|
381
|
-
|
|
382
|
-
// Marketplace (Subcommand)
|
|
383
|
-
// ============================================================================
|
|
384
|
-
|
|
385
|
-
const marketplace = program
|
|
386
|
-
.command("marketplace")
|
|
387
|
-
.description("Marketplace commands")
|
|
388
|
-
|
|
316
|
+
const marketplace = program.command("marketplace").description("Marketplace")
|
|
389
317
|
marketplace
|
|
390
318
|
.command("compare <input>")
|
|
391
|
-
.description("Find comparable packages
|
|
392
|
-
.option("--json", "
|
|
319
|
+
.description("Find comparable packages")
|
|
320
|
+
.option("--json", "JSON output")
|
|
393
321
|
.option("--category <category>", "Filter by category")
|
|
394
|
-
.option("--limit <n>", "
|
|
322
|
+
.option("--limit <n>", "Max results")
|
|
395
323
|
.action(marketplaceCompare)
|
|
396
|
-
|
|
397
324
|
marketplace
|
|
398
325
|
.command("earnings")
|
|
399
|
-
.description("
|
|
400
|
-
.option("--json", "
|
|
326
|
+
.description("Revenue summary")
|
|
327
|
+
.option("--json", "JSON output")
|
|
401
328
|
.action(marketplaceEarnings)
|
|
402
329
|
|
|
403
330
|
program.parse()
|
|
331
|
+
|
|
332
|
+
// ─── Helper ────────────────────────────────────────────────────────
|
|
333
|
+
|
|
334
|
+
function runBinary(binaryPath) {
|
|
335
|
+
try {
|
|
336
|
+
execFileSync(binaryPath, process.argv.slice(2), {
|
|
337
|
+
stdio: "inherit",
|
|
338
|
+
env: process.env,
|
|
339
|
+
})
|
|
340
|
+
process.exit(0)
|
|
341
|
+
} catch (err) {
|
|
342
|
+
if (err.status != null) {
|
|
343
|
+
process.exit(err.status)
|
|
344
|
+
}
|
|
345
|
+
// Binary failed to execute — fall through to JS CLI
|
|
346
|
+
}
|
|
347
|
+
}
|
package/index.d.ts
CHANGED
package/lib/commands/quality.js
CHANGED
|
@@ -178,8 +178,8 @@ export async function quality(nameInput, options = {}) {
|
|
|
178
178
|
const icon = check.passed ? chalk.green("✓") : chalk.red("✗")
|
|
179
179
|
const label = check.passed ? check.label : chalk.dim(check.label)
|
|
180
180
|
const points = check.passed
|
|
181
|
-
? chalk.dim(` ${check.points}/${check.
|
|
182
|
-
: chalk.dim(` 0/${check.
|
|
181
|
+
? chalk.dim(` ${check.points}/${check.max_points}`)
|
|
182
|
+
: chalk.dim(` 0/${check.max_points}`)
|
|
183
183
|
const detail = check.detail ? chalk.dim(` — ${check.detail}`) : ""
|
|
184
184
|
console.log(` ${icon} ${label}${points}${detail}`)
|
|
185
185
|
}
|
|
@@ -191,7 +191,7 @@ export async function quality(nameInput, options = {}) {
|
|
|
191
191
|
const tips = failed.slice(0, 3)
|
|
192
192
|
for (const check of tips) {
|
|
193
193
|
const tip = TIPS[check.id] || `Improve: ${check.id}`
|
|
194
|
-
console.log(chalk.dim(` Tip: ${tip} (+${check.
|
|
194
|
+
console.log(chalk.dim(` Tip: ${tip} (+${check.max_points} points)`))
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
}
|