Skills › HyperFrames › hyperframes › plugin-cli.mjs
plugin-cli.mjs
89 lines · skills/hyperframes/scripts/plugin-cli.mjs at a595755
1#!/usr/bin/env node
2// Run from the user's project; locate the release from this installed file.
3import { spawnSync } from "node:child_process";
4import { existsSync, readFileSync } from "node:fs";
5import { join, win32 } from "node:path";
6import { fileURLToPath } from "node:url";
7import { isMainModule } from "./lib/main-module.mjs";
9const root = fileURLToPath(new URL("../../../", import.meta.url));
10const manifests = [
11 "plugin.json",
12 ".claude-plugin/plugin.json",
13 ".codex-plugin/plugin.json",
14 ".cursor-plugin/plugin.json",
15 "gemini-extension.json",
16];
18export function pluginVersion(pluginRoot = root) {
19 for (const path of manifests) {
20 const file = join(pluginRoot, path);
21 if (!existsSync(file)) continue;
22 const manifest = JSON.parse(readFileSync(file, "utf8"));
23 if (
24 manifest.name !== "hyperframes" ||
25 !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(manifest.version ?? "")
26 ) {
27 throw new Error(`Invalid HyperFrames plugin release: ${file}`);
28 }
29 return manifest.version;
30 }
31 throw new Error(
32 "No HyperFrames plugin manifest found. This is a standalone skill install; run `npx hyperframes` directly.",
33 );
34}
36export function invocation(
37 args,
38 {
39 version = pluginVersion(),
40 env = process.env,
41 platform = process.platform,
42 node = process.execPath,
43 pathExists = existsSync,
44 } = {},
45) {
46 if (args[0] === "skills")
47 throw new Error(
48 "Bundled skills are release-managed; the person updates HyperFrames through their agent's plugin manager.",
49 );
50 const childEnv = {
51 ...env,
52 HYPERFRAMES_SKIP_SKILLS: "1",
53 HYPERFRAMES_SKILL_PKG_VERSION: version,
54 HYPERFRAMES_PLUGIN_VERSION: version,
55 HYPERFRAMES_NO_UPDATE_CHECK: "1",
56 };
57 if (args[0] === "--script") {
58 if (!args[1]) throw new Error("--script requires a Node script path.");
59 return { command: node, args: args.slice(1), env: childEnv };
60 }
61 const cliArgs = ["--yes", `hyperframes@${version}`, ...args];
62 if (platform !== "win32") return { command: "npx", args: cliArgs, env: childEnv };
63 const candidates = [
64 env.npm_execpath && win32.join(win32.dirname(env.npm_execpath), "npx-cli.js"),
65 win32.join(win32.dirname(node), "node_modules", "npm", "bin", "npx-cli.js"),
66 ].filter(Boolean);
67 const npx = candidates.find(pathExists);
68 if (!npx)
69 throw new Error(
70 "Cannot find npx-cli.js. Install Node.js with npm or run from an npm environment.",
71 );
72 return { command: node, args: [npx, ...cliArgs], env: childEnv };
73}
75if (isMainModule(import.meta.url)) {
76 try {
77 const command = invocation(process.argv.slice(2));
78 const result = spawnSync(command.command, command.args, {
79 env: command.env,
80 stdio: "inherit",
81 windowsHide: true,
82 });
83 if (result.error) throw result.error;
84 process.exitCode = result.status ?? 1;
85 } catch (error) {
86 console.error(error.message);
87 process.exitCode = 1;
88 }
89}