@enactprotocol/cli 2.0.0 → 2.0.1

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 (111) hide show
  1. package/dist/commands/auth/index.d.ts +12 -0
  2. package/dist/commands/auth/index.d.ts.map +1 -0
  3. package/dist/commands/auth/index.js +743 -0
  4. package/dist/commands/auth/index.js.map +1 -0
  5. package/dist/commands/cache/index.d.ts +11 -0
  6. package/dist/commands/cache/index.d.ts.map +1 -0
  7. package/dist/commands/cache/index.js +304 -0
  8. package/dist/commands/cache/index.js.map +1 -0
  9. package/dist/commands/config/index.d.ts +11 -0
  10. package/dist/commands/config/index.d.ts.map +1 -0
  11. package/dist/commands/config/index.js +138 -0
  12. package/dist/commands/config/index.js.map +1 -0
  13. package/dist/commands/env/index.d.ts +11 -0
  14. package/dist/commands/env/index.d.ts.map +1 -0
  15. package/dist/commands/env/index.js +303 -0
  16. package/dist/commands/env/index.js.map +1 -0
  17. package/dist/commands/exec/index.d.ts +12 -0
  18. package/dist/commands/exec/index.d.ts.map +1 -0
  19. package/dist/commands/exec/index.js +154 -0
  20. package/dist/commands/exec/index.js.map +1 -0
  21. package/dist/commands/get/index.d.ts +11 -0
  22. package/dist/commands/get/index.d.ts.map +1 -0
  23. package/dist/commands/get/index.js +151 -0
  24. package/dist/commands/get/index.js.map +1 -0
  25. package/dist/commands/index.d.ts +24 -0
  26. package/dist/commands/index.d.ts.map +1 -0
  27. package/dist/commands/index.js +27 -0
  28. package/dist/commands/index.js.map +1 -0
  29. package/dist/commands/inspect/index.d.ts +13 -0
  30. package/dist/commands/inspect/index.d.ts.map +1 -0
  31. package/dist/commands/inspect/index.js +199 -0
  32. package/dist/commands/inspect/index.js.map +1 -0
  33. package/dist/commands/install/index.d.ts +16 -0
  34. package/dist/commands/install/index.d.ts.map +1 -0
  35. package/dist/commands/install/index.js +520 -0
  36. package/dist/commands/install/index.js.map +1 -0
  37. package/dist/commands/list/index.d.ts +15 -0
  38. package/dist/commands/list/index.d.ts.map +1 -0
  39. package/dist/commands/list/index.js +103 -0
  40. package/dist/commands/list/index.js.map +1 -0
  41. package/dist/commands/publish/index.d.ts +11 -0
  42. package/dist/commands/publish/index.d.ts.map +1 -0
  43. package/dist/commands/publish/index.js +274 -0
  44. package/dist/commands/publish/index.js.map +1 -0
  45. package/dist/commands/report/index.d.ts +12 -0
  46. package/dist/commands/report/index.d.ts.map +1 -0
  47. package/dist/commands/report/index.js +279 -0
  48. package/dist/commands/report/index.js.map +1 -0
  49. package/dist/commands/run/index.d.ts +16 -0
  50. package/dist/commands/run/index.d.ts.map +1 -0
  51. package/dist/commands/run/index.js +525 -0
  52. package/dist/commands/run/index.js.map +1 -0
  53. package/dist/commands/search/index.d.ts +12 -0
  54. package/dist/commands/search/index.d.ts.map +1 -0
  55. package/dist/commands/search/index.js +275 -0
  56. package/dist/commands/search/index.js.map +1 -0
  57. package/dist/commands/setup/index.d.ts +11 -0
  58. package/dist/commands/setup/index.d.ts.map +1 -0
  59. package/dist/commands/setup/index.js +241 -0
  60. package/dist/commands/setup/index.js.map +1 -0
  61. package/dist/commands/sign/index.d.ts +17 -0
  62. package/dist/commands/sign/index.d.ts.map +1 -0
  63. package/dist/commands/sign/index.js +507 -0
  64. package/dist/commands/sign/index.js.map +1 -0
  65. package/dist/commands/trust/index.d.ts +13 -0
  66. package/dist/commands/trust/index.d.ts.map +1 -0
  67. package/dist/commands/trust/index.js +366 -0
  68. package/dist/commands/trust/index.js.map +1 -0
  69. package/dist/commands/unyank/index.d.ts +11 -0
  70. package/dist/commands/unyank/index.d.ts.map +1 -0
  71. package/dist/commands/unyank/index.js +87 -0
  72. package/dist/commands/unyank/index.js.map +1 -0
  73. package/dist/commands/yank/index.d.ts +13 -0
  74. package/dist/commands/yank/index.d.ts.map +1 -0
  75. package/dist/commands/yank/index.js +109 -0
  76. package/dist/commands/yank/index.js.map +1 -0
  77. package/dist/index.d.ts +10 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +67 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/types.d.ts +69 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +15 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/utils/errors.d.ts +159 -0
  86. package/dist/utils/errors.d.ts.map +1 -0
  87. package/dist/utils/errors.js +321 -0
  88. package/dist/utils/errors.js.map +1 -0
  89. package/dist/utils/exit-codes.d.ts +83 -0
  90. package/dist/utils/exit-codes.d.ts.map +1 -0
  91. package/dist/utils/exit-codes.js +126 -0
  92. package/dist/utils/exit-codes.js.map +1 -0
  93. package/dist/utils/ignore.d.ts +25 -0
  94. package/dist/utils/ignore.d.ts.map +1 -0
  95. package/dist/utils/ignore.js +123 -0
  96. package/dist/utils/ignore.js.map +1 -0
  97. package/dist/utils/index.d.ts +8 -0
  98. package/dist/utils/index.d.ts.map +1 -0
  99. package/dist/utils/index.js +12 -0
  100. package/dist/utils/index.js.map +1 -0
  101. package/dist/utils/output.d.ts +103 -0
  102. package/dist/utils/output.d.ts.map +1 -0
  103. package/dist/utils/output.js +201 -0
  104. package/dist/utils/output.js.map +1 -0
  105. package/dist/utils/spinner.d.ts +83 -0
  106. package/dist/utils/spinner.d.ts.map +1 -0
  107. package/dist/utils/spinner.js +162 -0
  108. package/dist/utils/spinner.js.map +1 -0
  109. package/package.json +5 -5
  110. package/src/index.ts +4 -0
  111. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,520 @@
1
+ /**
2
+ * enact install command
3
+ *
4
+ * Install a tool to the project or globally.
5
+ * All tools are extracted to ~/.enact/cache/{tool}/{version}/
6
+ * - Project install: Adds entry to .enact/tools.json
7
+ * - Global install: Adds entry to ~/.enact/tools.json
8
+ *
9
+ * Supports local paths and registry tools with verification.
10
+ */
11
+ import { cpSync, existsSync, mkdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
12
+ import { dirname, join, resolve } from "node:path";
13
+ import { createApiClient, downloadBundle, getAttestationList, getToolInfo, getToolVersion, verifyAllAttestations, } from "@enactprotocol/api";
14
+ import { addToolToRegistry, getCacheDir, getInstalledVersion, getMinimumAttestations, getProjectEnactDir, getToolCachePath, getTrustPolicy, getTrustedAuditors, loadConfig, loadManifestFromDir, pathExists, } from "@enactprotocol/shared";
15
+ import { EXIT_FAILURE, EXIT_TRUST_ERROR, ManifestError, RegistryError, TrustError, colors, confirm, dim, error, formatError, handleError, info, json, keyValue, newline, success, suggest, symbols, withSpinner, } from "../../utils";
16
+ /**
17
+ * Parse tool@version syntax
18
+ */
19
+ function parseToolSpec(spec) {
20
+ // Handle scoped packages like @scope/tool@version
21
+ const match = spec.match(/^(@[^@/]+\/[^@]+|[^@]+)(?:@(.+))?$/);
22
+ if (match?.[1]) {
23
+ return {
24
+ name: match[1],
25
+ version: match[2],
26
+ };
27
+ }
28
+ return { name: spec, version: undefined };
29
+ }
30
+ /**
31
+ * Copy a directory recursively
32
+ */
33
+ function copyDir(src, dest) {
34
+ mkdirSync(dest, { recursive: true });
35
+ cpSync(src, dest, { recursive: true });
36
+ }
37
+ /**
38
+ * Check if a tool name looks like a local path
39
+ * Local paths start with ./, ../, or /
40
+ */
41
+ function isLocalPath(toolName) {
42
+ return (toolName === "." ||
43
+ toolName.startsWith("./") ||
44
+ toolName.startsWith("../") ||
45
+ toolName.startsWith("/"));
46
+ }
47
+ /**
48
+ * Extract a tar.gz bundle to a directory
49
+ * Uses tar command (available on all supported platforms)
50
+ */
51
+ async function extractBundle(bundleData, destPath) {
52
+ // Create a temporary file for the bundle
53
+ const tempFile = join(getCacheDir(), `bundle-${Date.now()}.tar.gz`);
54
+ mkdirSync(dirname(tempFile), { recursive: true });
55
+ writeFileSync(tempFile, Buffer.from(bundleData));
56
+ // Create destination directory
57
+ mkdirSync(destPath, { recursive: true });
58
+ // Extract using tar command (available on all supported platforms)
59
+ const proc = Bun.spawn(["tar", "-xzf", tempFile, "-C", destPath], {
60
+ stdout: "pipe",
61
+ stderr: "pipe",
62
+ });
63
+ const exitCode = await proc.exited;
64
+ // Clean up temp file
65
+ try {
66
+ unlinkSync(tempFile);
67
+ }
68
+ catch {
69
+ // Ignore cleanup errors
70
+ }
71
+ if (exitCode !== 0) {
72
+ const stderr = await new Response(proc.stderr).text();
73
+ throw new Error(`Failed to extract bundle: ${stderr}`);
74
+ }
75
+ }
76
+ /**
77
+ * Format bytes to human-readable string
78
+ */
79
+ function formatBytes(bytes) {
80
+ if (bytes === 0)
81
+ return "0 B";
82
+ const k = 1024;
83
+ const sizes = ["B", "KB", "MB", "GB"];
84
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
85
+ return `${(bytes / k ** i).toFixed(1)} ${sizes[i]}`;
86
+ }
87
+ /**
88
+ * Install from the registry
89
+ */
90
+ async function installFromRegistry(toolName, version, options, ctx) {
91
+ const config = loadConfig();
92
+ const registryUrl = process.env.ENACT_REGISTRY_URL ??
93
+ config.registry?.url ??
94
+ "https://siikwkfgsmouioodghho.supabase.co/functions/v1";
95
+ const authToken = config.registry?.authToken;
96
+ const client = createApiClient({
97
+ baseUrl: registryUrl,
98
+ authToken: authToken,
99
+ });
100
+ // Get tool info to find latest version if not specified
101
+ let targetVersion = version;
102
+ let toolInfo;
103
+ try {
104
+ if (!targetVersion) {
105
+ // Fetch tool metadata to get latest version
106
+ const metadata = await withSpinner(`Fetching ${toolName} info...`, async () => getToolInfo(client, toolName), `${symbols.success} Found ${toolName}`);
107
+ targetVersion = metadata.latestVersion;
108
+ }
109
+ // Get version-specific info
110
+ toolInfo = await withSpinner(`Fetching ${toolName}@${targetVersion} details...`, async () => getToolVersion(client, toolName, targetVersion), `${symbols.success} Got version details`);
111
+ }
112
+ catch (err) {
113
+ throw new RegistryError(`Failed to fetch tool info: ${formatError(err)}`);
114
+ }
115
+ // Check if version is yanked
116
+ if (toolInfo.yanked) {
117
+ const yankMessage = toolInfo.yankReason
118
+ ? `Version ${targetVersion} has been yanked: ${toolInfo.yankReason}`
119
+ : `Version ${targetVersion} has been yanked`;
120
+ if (options.allowYanked) {
121
+ info(`${symbols.warning} ${yankMessage}`);
122
+ if (toolInfo.yankReplacement) {
123
+ dim(` Recommended replacement: ${toolInfo.yankReplacement}`);
124
+ }
125
+ }
126
+ else if (ctx.isInteractive) {
127
+ info(`${symbols.warning} ${yankMessage}`);
128
+ if (toolInfo.yankReplacement) {
129
+ info(`Recommended replacement: ${toolInfo.yankReplacement}`);
130
+ const useReplacement = await confirm(`Install ${toolInfo.yankReplacement} instead?`);
131
+ if (useReplacement) {
132
+ // Recursively install the replacement version
133
+ return installFromRegistry(toolName, toolInfo.yankReplacement, options, ctx);
134
+ }
135
+ }
136
+ const proceed = await confirm("Install yanked version anyway?");
137
+ if (!proceed) {
138
+ info("Installation cancelled.");
139
+ process.exit(0);
140
+ }
141
+ }
142
+ else {
143
+ error(`${yankMessage}`);
144
+ if (toolInfo.yankReplacement) {
145
+ info(`Recommended replacement: ${toolInfo.yankReplacement}`);
146
+ suggest(`Run: enact install ${toolName}@${toolInfo.yankReplacement}`);
147
+ }
148
+ info("Use --allow-yanked to install yanked versions.");
149
+ process.exit(EXIT_FAILURE);
150
+ }
151
+ }
152
+ // Check trust policy - fetch and verify attestations
153
+ try {
154
+ const trustPolicy = getTrustPolicy();
155
+ const minimumAttestations = getMinimumAttestations();
156
+ const trustedAuditors = getTrustedAuditors();
157
+ // Fetch attestations from registry
158
+ const attestationsResponse = await getAttestationList(client, toolName, targetVersion);
159
+ const attestations = attestationsResponse.attestations;
160
+ if (attestations.length === 0) {
161
+ // No attestations found
162
+ info(`${symbols.warning} Tool ${toolName}@${targetVersion} has no attestations.`);
163
+ if (trustPolicy === "require_attestation") {
164
+ error("Trust policy requires attestations. Installation blocked.");
165
+ info("Configure trust policy in ~/.enact/config.yaml");
166
+ process.exit(EXIT_TRUST_ERROR);
167
+ }
168
+ else if (ctx.isInteractive && trustPolicy === "prompt") {
169
+ const proceed = await confirm("Install unverified tool?");
170
+ if (!proceed) {
171
+ info("Installation cancelled.");
172
+ process.exit(0);
173
+ }
174
+ }
175
+ else if (!ctx.isInteractive && trustPolicy === "prompt") {
176
+ error("Cannot install unverified tools in non-interactive mode.");
177
+ info("Run interactively to confirm installation.");
178
+ process.exit(EXIT_TRUST_ERROR);
179
+ }
180
+ // trustPolicy === "allow" - continue without prompting
181
+ }
182
+ else {
183
+ // Verify attestations locally (never trust registry's verification status)
184
+ const verifiedAuditors = await verifyAllAttestations(client, toolName, targetVersion, toolInfo.bundle?.hash ?? "");
185
+ // Check verified auditors against trust config using provider:identity format
186
+ const trustedVerifiedAuditors = verifiedAuditors
187
+ .filter((auditor) => trustedAuditors.includes(auditor.providerIdentity))
188
+ .map((auditor) => auditor.providerIdentity);
189
+ if (trustedVerifiedAuditors.length > 0) {
190
+ // Check if we meet minimum attestations threshold
191
+ if (trustedVerifiedAuditors.length < minimumAttestations) {
192
+ info(`${symbols.warning} Tool ${toolName}@${targetVersion} has ${trustedVerifiedAuditors.length} trusted attestation(s), but ${minimumAttestations} required.`);
193
+ dim(`Trusted attestations: ${trustedVerifiedAuditors.join(", ")}`);
194
+ if (trustPolicy === "require_attestation") {
195
+ error(`Trust policy requires at least ${minimumAttestations} attestation(s) from trusted identities. Installation blocked.`);
196
+ suggest("Run 'enact trust <identity>' to add more trusted identities");
197
+ process.exit(EXIT_TRUST_ERROR);
198
+ }
199
+ else if (ctx.isInteractive && trustPolicy === "prompt") {
200
+ const proceed = await confirm("Install with fewer attestations than required?");
201
+ if (!proceed) {
202
+ info("Installation cancelled.");
203
+ process.exit(0);
204
+ }
205
+ }
206
+ else if (!ctx.isInteractive && trustPolicy === "prompt") {
207
+ error("Cannot install tool without meeting minimum attestation requirement in non-interactive mode.");
208
+ process.exit(EXIT_TRUST_ERROR);
209
+ }
210
+ // trustPolicy === "allow" - continue without prompting
211
+ }
212
+ else {
213
+ // Tool meets or exceeds minimum attestations
214
+ if (options.verbose) {
215
+ success(`Tool verified by ${trustedVerifiedAuditors.length} trusted identity(ies): ${trustedVerifiedAuditors.join(", ")}`);
216
+ }
217
+ }
218
+ }
219
+ else {
220
+ // Has attestations but none from trusted auditors
221
+ info(`${symbols.warning} Tool ${toolName}@${targetVersion} has ${verifiedAuditors.length} attestation(s), but none from trusted auditors.`);
222
+ if (trustPolicy === "require_attestation") {
223
+ error("Trust policy requires attestations from trusted identities. Installation blocked.");
224
+ dim(`Your trusted auditors: ${trustedAuditors.join(", ")}`);
225
+ dim(`Tool attested by: ${verifiedAuditors.map((a) => a.providerIdentity).join(", ")}`);
226
+ suggest("Run 'enact trust <auditor>' to add a trusted auditor");
227
+ process.exit(EXIT_TRUST_ERROR);
228
+ }
229
+ else if (ctx.isInteractive && trustPolicy === "prompt") {
230
+ dim(`Attested by: ${verifiedAuditors.map((a) => a.providerIdentity).join(", ")}`);
231
+ dim(`Your trusted auditors: ${trustedAuditors.join(", ")}`);
232
+ const proceed = await confirm("Install anyway?");
233
+ if (!proceed) {
234
+ info("Installation cancelled.");
235
+ process.exit(0);
236
+ }
237
+ }
238
+ else if (!ctx.isInteractive && trustPolicy === "prompt") {
239
+ error("Cannot install tool without trusted attestations in non-interactive mode.");
240
+ process.exit(EXIT_TRUST_ERROR);
241
+ }
242
+ // trustPolicy === "allow" - continue without prompting
243
+ }
244
+ }
245
+ }
246
+ catch (err) {
247
+ if (options.verbose) {
248
+ dim(`Trust check failed: ${formatError(err)}`);
249
+ }
250
+ // Continue with installation if trust check fails (with warning)
251
+ info(`${symbols.warning} Could not verify trust status. Proceeding with caution.`);
252
+ }
253
+ // Download bundle
254
+ let bundleResult;
255
+ try {
256
+ bundleResult = await withSpinner(`Downloading ${toolName}@${targetVersion}...`, async () => downloadBundle(client, {
257
+ name: toolName,
258
+ version: targetVersion,
259
+ verify: true,
260
+ acknowledgeYanked: toolInfo.yanked === true || options.allowYanked === true,
261
+ }), `${symbols.success} Downloaded`);
262
+ }
263
+ catch (err) {
264
+ throw new RegistryError(`Failed to download bundle: ${formatError(err)}`);
265
+ }
266
+ // Verify hash if provided
267
+ if (toolInfo.bundle?.hash) {
268
+ const downloadedHash = bundleResult.hash.replace("sha256:", "");
269
+ const expectedHash = toolInfo.bundle.hash.replace("sha256:", "");
270
+ if (downloadedHash !== expectedHash) {
271
+ throw new TrustError(`Bundle hash mismatch! The downloaded file may be corrupted or tampered with.${options.verbose ? `\nExpected: ${expectedHash}\nGot: ${downloadedHash}` : ""}`);
272
+ }
273
+ }
274
+ // All installs: extract to cache and update tools.json
275
+ const isGlobal = options.global ?? false;
276
+ const scope = isGlobal ? "global" : "project";
277
+ const cachePath = getToolCachePath(toolName, targetVersion);
278
+ // Check if already installed in the target scope
279
+ const existingVersion = getInstalledVersion(toolName, scope, isGlobal ? undefined : ctx.cwd);
280
+ if (existingVersion && !options.force) {
281
+ if (existingVersion === targetVersion) {
282
+ info(`Tool ${toolName}@${targetVersion} is already installed ${isGlobal ? "globally" : "in this project"}.`);
283
+ return;
284
+ }
285
+ if (ctx.isInteractive) {
286
+ const shouldOverwrite = await confirm(`Tool ${toolName}@${existingVersion} is installed. Update to ${targetVersion}?`);
287
+ if (!shouldOverwrite) {
288
+ info("Installation cancelled.");
289
+ return;
290
+ }
291
+ }
292
+ else {
293
+ error(`Tool ${toolName}@${existingVersion} is already installed. Use --force to update.`);
294
+ process.exit(EXIT_FAILURE);
295
+ }
296
+ }
297
+ // Extract bundle to cache
298
+ try {
299
+ await withSpinner(`Extracting ${toolName}...`, async () => {
300
+ // Remove existing directory if force
301
+ if (pathExists(cachePath)) {
302
+ rmSync(cachePath, { recursive: true, force: true });
303
+ }
304
+ await extractBundle(bundleResult.data, cachePath);
305
+ }, `${symbols.success} Extracted to ${cachePath}`);
306
+ }
307
+ catch (err) {
308
+ throw new RegistryError(`Failed to extract bundle: ${formatError(err)}`);
309
+ }
310
+ // Update tools.json for the appropriate scope
311
+ addToolToRegistry(toolName, targetVersion, scope, isGlobal ? undefined : ctx.cwd);
312
+ // Output result
313
+ if (options.json) {
314
+ json({
315
+ installed: true,
316
+ tool: toolName,
317
+ version: targetVersion,
318
+ location: cachePath,
319
+ scope,
320
+ hash: bundleResult.hash,
321
+ size: bundleResult.size,
322
+ verified: true,
323
+ });
324
+ return;
325
+ }
326
+ newline();
327
+ keyValue("Tool", toolName);
328
+ keyValue("Version", targetVersion ?? "unknown");
329
+ keyValue("Location", cachePath);
330
+ keyValue("Scope", isGlobal ? "global (~/.enact/tools.json)" : "project (.enact/tools.json)");
331
+ keyValue("Size", formatBytes(bundleResult.size));
332
+ keyValue("Hash", `${bundleResult.hash.substring(0, 20)}...`);
333
+ newline();
334
+ success(`Installed ${colors.bold(toolName)}@${targetVersion}`);
335
+ }
336
+ /**
337
+ * Install from a local path
338
+ *
339
+ * Both global and project installs:
340
+ * 1. Copy tool to cache (~/.enact/cache/{tool}/{version}/)
341
+ * 2. Update tools.json (global: ~/.enact/tools.json, project: .enact/tools.json)
342
+ */
343
+ async function installFromPath(sourcePath, options, ctx) {
344
+ const resolvedPath = resolve(ctx.cwd, sourcePath);
345
+ // Load manifest from source
346
+ const loaded = loadManifestFromDir(resolvedPath);
347
+ if (!loaded) {
348
+ throw new ManifestError(`No valid manifest found in: ${resolvedPath}`);
349
+ }
350
+ const manifest = loaded.manifest;
351
+ const isGlobal = options.global ?? false;
352
+ const version = manifest.version ?? "0.0.0";
353
+ const scope = isGlobal ? "global" : "project";
354
+ // All tools go to cache
355
+ const cachePath = getToolCachePath(manifest.name, version);
356
+ // Check if already installed in the target scope
357
+ const existingVersion = getInstalledVersion(manifest.name, scope, isGlobal ? undefined : ctx.cwd);
358
+ if (existingVersion && !options.force) {
359
+ if (existingVersion === version) {
360
+ info(`Tool ${manifest.name}@${version} is already installed ${isGlobal ? "globally" : "in this project"}.`);
361
+ return;
362
+ }
363
+ if (ctx.isInteractive) {
364
+ const shouldOverwrite = await confirm(`Tool ${manifest.name}@${existingVersion} is installed. Update to ${version}?`);
365
+ if (!shouldOverwrite) {
366
+ info("Installation cancelled.");
367
+ return;
368
+ }
369
+ }
370
+ else {
371
+ error(`Tool ${manifest.name}@${existingVersion} is already installed. Use --force to update.`);
372
+ process.exit(EXIT_FAILURE);
373
+ }
374
+ }
375
+ // Copy tool to cache
376
+ await withSpinner(`Installing ${manifest.name}...`, async () => {
377
+ if (pathExists(cachePath)) {
378
+ rmSync(cachePath, { recursive: true, force: true });
379
+ }
380
+ mkdirSync(dirname(cachePath), { recursive: true });
381
+ copyDir(resolvedPath, cachePath);
382
+ }, `${symbols.success} Installed ${manifest.name}`);
383
+ // Update tools.json for the appropriate scope
384
+ addToolToRegistry(manifest.name, version, scope, isGlobal ? undefined : ctx.cwd);
385
+ if (options.json) {
386
+ json({
387
+ installed: true,
388
+ tool: manifest.name,
389
+ version: manifest.version,
390
+ location: cachePath,
391
+ scope,
392
+ });
393
+ return;
394
+ }
395
+ newline();
396
+ keyValue("Tool", manifest.name);
397
+ keyValue("Version", manifest.version ?? "unversioned");
398
+ keyValue("Location", cachePath);
399
+ keyValue("Scope", isGlobal ? "global (~/.enact/tools.json)" : "project (.enact/tools.json)");
400
+ newline();
401
+ success(`Installed ${colors.bold(manifest.name)}`);
402
+ }
403
+ /**
404
+ * Install from a tool name (registry tool)
405
+ */
406
+ async function installFromName(toolSpec, options, ctx) {
407
+ const { name: toolName, version } = parseToolSpec(toolSpec);
408
+ // If it looks like a local path, use installFromPath
409
+ if (isLocalPath(toolName)) {
410
+ return installFromPath(toolName, options, ctx);
411
+ }
412
+ // Otherwise, it's a registry tool - fetch from registry
413
+ return installFromRegistry(toolName, version, options, ctx);
414
+ }
415
+ /**
416
+ * Install all tools from project .enact/tools.json
417
+ */
418
+ async function installProjectTools(options, ctx) {
419
+ const projectDir = getProjectEnactDir(ctx.cwd);
420
+ if (!projectDir) {
421
+ info("No .enact/ directory found. Nothing to install.");
422
+ suggest("Run 'enact install <tool>' to install a specific tool.");
423
+ return;
424
+ }
425
+ const toolsJsonPath = join(projectDir, "tools.json");
426
+ if (!existsSync(toolsJsonPath)) {
427
+ info("No .enact/tools.json found. Nothing to install.");
428
+ suggest("Run 'enact install <tool>' to install a specific tool.");
429
+ return;
430
+ }
431
+ // Parse tools.json
432
+ let toolsConfig;
433
+ try {
434
+ const content = await Bun.file(toolsJsonPath).text();
435
+ toolsConfig = JSON.parse(content);
436
+ }
437
+ catch (err) {
438
+ throw new ManifestError(`Failed to parse .enact/tools.json: ${formatError(err)}`);
439
+ }
440
+ if (!toolsConfig.tools || Object.keys(toolsConfig.tools).length === 0) {
441
+ info("No tools specified in .enact/tools.json");
442
+ return;
443
+ }
444
+ // Install each tool
445
+ const tools = Object.entries(toolsConfig.tools);
446
+ info(`Installing ${tools.length} tool(s) from tools.json...`);
447
+ newline();
448
+ let installed = 0;
449
+ let failed = 0;
450
+ for (const [toolName, toolVersion] of tools) {
451
+ try {
452
+ const toolSpec = toolVersion ? `${toolName}@${toolVersion}` : toolName;
453
+ await installFromName(toolSpec, { ...options, json: false }, ctx);
454
+ installed++;
455
+ }
456
+ catch (err) {
457
+ error(`Failed to install ${toolName}: ${formatError(err)}`);
458
+ failed++;
459
+ }
460
+ }
461
+ newline();
462
+ if (failed === 0) {
463
+ success(`Installed all ${installed} tool(s) successfully`);
464
+ }
465
+ else {
466
+ info(`Installed ${installed} tool(s), ${failed} failed`);
467
+ }
468
+ if (options.json) {
469
+ json({
470
+ installed,
471
+ failed,
472
+ total: tools.length,
473
+ });
474
+ }
475
+ }
476
+ /**
477
+ * Install command handler
478
+ */
479
+ async function installHandler(tool, options, ctx) {
480
+ // If no tool specified, install from project
481
+ if (!tool) {
482
+ return installProjectTools(options, ctx);
483
+ }
484
+ // Check if it's a path
485
+ if (tool === "." || tool.startsWith("./") || tool.startsWith("/") || tool.startsWith("..")) {
486
+ return installFromPath(tool, options, ctx);
487
+ }
488
+ // Otherwise, try to resolve as tool name (local or registry)
489
+ return installFromName(tool, options, ctx);
490
+ }
491
+ /**
492
+ * Configure the install command
493
+ */
494
+ export function configureInstallCommand(program) {
495
+ program
496
+ .command("install")
497
+ .alias("i")
498
+ .description("Install a tool to the project or globally")
499
+ .argument("[tool]", "Tool to install (name[@version], path, or '.' for current directory)")
500
+ .option("-g, --global", "Install globally (adds to ~/.enact/tools.json)")
501
+ .option("-f, --force", "Overwrite existing installation")
502
+ .option("--allow-yanked", "Allow installing yanked versions")
503
+ .option("-v, --verbose", "Show detailed output")
504
+ .option("--json", "Output result as JSON")
505
+ .action(async (tool, options) => {
506
+ const ctx = {
507
+ cwd: process.cwd(),
508
+ options,
509
+ isCI: Boolean(process.env.CI),
510
+ isInteractive: process.stdout.isTTY ?? false,
511
+ };
512
+ try {
513
+ await installHandler(tool, options, ctx);
514
+ }
515
+ catch (err) {
516
+ handleError(err, options.verbose ? { verbose: true } : undefined);
517
+ }
518
+ });
519
+ }
520
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/install/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * enact list command
3
+ *
4
+ * List installed tools from tools.json registries.
5
+ * - Default: project tools (via .enact/tools.json)
6
+ * - --global/-g: global tools (via ~/.enact/tools.json)
7
+ *
8
+ * All tools are stored in ~/.enact/cache/{tool}/{version}/
9
+ */
10
+ import type { Command } from "commander";
11
+ /**
12
+ * Configure the list command
13
+ */
14
+ export declare function configureListCommand(program: Command): void;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/list/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoGzC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuB3D"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * enact list command
3
+ *
4
+ * List installed tools from tools.json registries.
5
+ * - Default: project tools (via .enact/tools.json)
6
+ * - --global/-g: global tools (via ~/.enact/tools.json)
7
+ *
8
+ * All tools are stored in ~/.enact/cache/{tool}/{version}/
9
+ */
10
+ import { listInstalledTools, tryLoadManifestFromDir } from "@enactprotocol/shared";
11
+ import { dim, error, formatError, header, info, json, newline, table, } from "../../utils";
12
+ /**
13
+ * List tools from tools.json registry
14
+ */
15
+ function listToolsFromRegistry(scope, cwd) {
16
+ const tools = [];
17
+ const installedTools = listInstalledTools(scope, cwd);
18
+ for (const tool of installedTools) {
19
+ // Load manifest from cache to get description
20
+ const loaded = tryLoadManifestFromDir(tool.cachePath);
21
+ tools.push({
22
+ name: tool.name,
23
+ description: loaded?.manifest.description ?? "-",
24
+ version: tool.version,
25
+ location: tool.cachePath,
26
+ scope,
27
+ });
28
+ }
29
+ return tools;
30
+ }
31
+ /**
32
+ * List command handler
33
+ */
34
+ async function listHandler(options, ctx) {
35
+ const allTools = [];
36
+ if (options.global) {
37
+ // Global tools (via ~/.enact/tools.json)
38
+ const globalTools = listToolsFromRegistry("global");
39
+ allTools.push(...globalTools);
40
+ }
41
+ else {
42
+ // Project tools (via .enact/tools.json)
43
+ const projectTools = listToolsFromRegistry("project", ctx.cwd);
44
+ allTools.push(...projectTools);
45
+ }
46
+ // Output
47
+ if (options.json) {
48
+ json(allTools);
49
+ return;
50
+ }
51
+ if (allTools.length === 0) {
52
+ if (options.global) {
53
+ info("No global tools installed.");
54
+ dim("Install globally with 'enact install <tool> -g'");
55
+ }
56
+ else {
57
+ info("No project tools installed.");
58
+ dim("Install with 'enact install <tool>' or use '-g' for global");
59
+ }
60
+ return;
61
+ }
62
+ header(options.global ? "Global Tools" : "Project Tools");
63
+ newline();
64
+ const columns = [
65
+ { key: "name", header: "Name", width: 28 },
66
+ { key: "description", header: "Description", width: 50 },
67
+ ];
68
+ if (options.verbose) {
69
+ columns.push({ key: "version", header: "Version", width: 10 });
70
+ columns.push({ key: "location", header: "Location", width: 40 });
71
+ }
72
+ table(allTools, columns);
73
+ newline();
74
+ dim(`Total: ${allTools.length} tool(s)`);
75
+ }
76
+ /**
77
+ * Configure the list command
78
+ */
79
+ export function configureListCommand(program) {
80
+ program
81
+ .command("list")
82
+ .alias("ls")
83
+ .description("List installed tools")
84
+ .option("-g, --global", "List global tools (via ~/.enact/tools.json)")
85
+ .option("-v, --verbose", "Show detailed output including paths")
86
+ .option("--json", "Output as JSON")
87
+ .action(async (options) => {
88
+ const ctx = {
89
+ cwd: process.cwd(),
90
+ options,
91
+ isCI: Boolean(process.env.CI),
92
+ isInteractive: process.stdout.isTTY ?? false,
93
+ };
94
+ try {
95
+ await listHandler(options, ctx);
96
+ }
97
+ catch (err) {
98
+ error(formatError(err));
99
+ process.exit(1);
100
+ }
101
+ });
102
+ }
103
+ //# sourceMappingURL=index.js.map