codex-skill
Advanced tools
+32
-4
@@ -8,3 +8,3 @@ #!/usr/bin/env node | ||
| import { promises as fs } from "fs"; | ||
| import { existsSync } from "fs"; | ||
| import { existsSync, readFileSync } from "fs"; | ||
| import os from "os"; | ||
@@ -15,3 +15,4 @@ import path from "path"; | ||
| var program = new Command(); | ||
| program.name("codex-skill").description("Manage Codex skills from a registry.").version("0.1.0").option("--registry <pathOrUrl>", "Registry index URL or file path"); | ||
| var CLI_VERSION = readCliVersion(); | ||
| program.name("codex-skill").description("Manage Codex skills from a registry.").version(CLI_VERSION).option("--registry <pathOrUrl>", "Registry index URL or file path"); | ||
| program.command("list").description("List skills from the registry.").action(async () => { | ||
@@ -136,3 +137,9 @@ const index = await loadRegistryIndex(); | ||
| if (isHttp(source)) { | ||
| const response = await fetch(source); | ||
| const response = await fetch(withNoCache(source), { | ||
| cache: "no-store", | ||
| headers: { | ||
| "cache-control": "no-cache", | ||
| pragma: "no-cache" | ||
| } | ||
| }); | ||
| if (!response.ok) { | ||
@@ -149,3 +156,9 @@ throw new Error(`Failed to fetch ${source}: ${response.status}`); | ||
| if (isHttp(source)) { | ||
| const response = await fetch(source); | ||
| const response = await fetch(withNoCache(source), { | ||
| cache: "no-store", | ||
| headers: { | ||
| "cache-control": "no-cache", | ||
| pragma: "no-cache" | ||
| } | ||
| }); | ||
| if (!response.ok) { | ||
@@ -163,5 +176,20 @@ throw new Error(`Failed to fetch ${source}: ${response.status}`); | ||
| } | ||
| function withNoCache(source) { | ||
| const url = new URL(source); | ||
| url.searchParams.set("_", `${Date.now()}`); | ||
| return url.toString(); | ||
| } | ||
| function sha256(buffer) { | ||
| return createHash("sha256").update(buffer).digest("hex"); | ||
| } | ||
| function readCliVersion() { | ||
| try { | ||
| const packageJsonPath = new URL("../package.json", import.meta.url); | ||
| const raw = readFileSync(packageJsonPath, "utf-8"); | ||
| const parsed = JSON.parse(raw); | ||
| return parsed.version ?? "0.0.0"; | ||
| } catch { | ||
| return "0.0.0"; | ||
| } | ||
| } | ||
| function resolveSkillsDestination(target) { | ||
@@ -168,0 +196,0 @@ if (target) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { spawn } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { existsSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport process from \"node:process\";\n\nconst DEFAULT_REGISTRY_URL =\n \"https://raw.githubusercontent.com/iluxu/codex-skills-registry/main/index.json\";\n\ntype IndexSkill = {\n name: string;\n description?: string;\n author?: string;\n tags?: string[];\n compatibility?: string[];\n latest: string;\n artifact?: {\n url: string;\n sha256?: string;\n entry?: string;\n };\n manifest: string;\n};\n\ntype RegistryIndex = {\n registry: string;\n version: string;\n updatedAt: string;\n skills: IndexSkill[];\n};\n\ntype ManifestVersion = {\n version: string;\n releasedAt: string;\n artifact?: {\n url: string;\n sha256?: string;\n entry?: string;\n };\n};\n\ntype SkillManifest = {\n name: string;\n version?: string;\n description?: string;\n author?: string;\n entry?: string;\n tags?: string[];\n compatibility?: string[];\n install?: {\n type: string;\n destination?: string;\n notes?: string;\n };\n versions: ManifestVersion[];\n};\n\nconst program = new Command();\n\nprogram\n .name(\"codex-skill\")\n .description(\"Manage Codex skills from a registry.\")\n .version(\"0.1.0\")\n .option(\"--registry <pathOrUrl>\", \"Registry index URL or file path\");\n\nprogram\n .command(\"list\")\n .description(\"List skills from the registry.\")\n .action(async () => {\n const index = await loadRegistryIndex();\n index.skills.forEach((skill) => {\n const tags = skill.tags?.length ? ` [${skill.tags.join(\", \")}]` : \"\";\n const version = skill.latest ? ` (${skill.latest})` : \"\";\n console.log(`${skill.name}${version} — ${skill.description ?? \"\"}${tags}`.trim());\n });\n });\n\nprogram\n .command(\"search\")\n .description(\"Search skills by name, description, or tags.\")\n .argument(\"<query>\", \"Search query\")\n .action(async (query: string) => {\n const index = await loadRegistryIndex();\n const needle = query.toLowerCase();\n const results = index.skills.filter((skill) => {\n const haystack = [skill.name, skill.description ?? \"\", ...(skill.tags ?? [])]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(needle);\n });\n\n if (!results.length) {\n console.log(\"No skills found.\");\n return;\n }\n\n results.forEach((skill) => {\n console.log(`${skill.name} — ${skill.description ?? \"\"}`.trim());\n });\n });\n\nprogram\n .command(\"get\")\n .description(\"Fetch a skill manifest.\")\n .argument(\"<name>\", \"Skill name\")\n .action(async (name: string) => {\n const { index, registrySource } = await loadRegistryIndexWithSource();\n const skill = findSkill(index, name);\n const manifest = await loadManifest(registrySource, skill.manifest);\n console.log(JSON.stringify(manifest, null, 2));\n });\n\nprogram\n .command(\"install\")\n .description(\"Download and install a skill artifact.\")\n .argument(\"<name>\", \"Skill name\")\n .option(\"--version <version>\", \"Specific version\")\n .option(\"--to <path>\", \"Destination directory for skills\")\n .option(\"--out <path>\", \"Output artifact path (optional)\")\n .action(async (name: string, options: { version?: string; out?: string; to?: string }) => {\n const { index, registrySource } = await loadRegistryIndexWithSource();\n const skill = findSkill(index, name);\n const manifest = await loadManifest(registrySource, skill.manifest);\n const version = options.version ?? skill.latest;\n const entry = manifest.versions.find((item) => item.version === version);\n\n if (!entry) {\n throw new Error(`Version not found: ${version}`);\n }\n\n const artifact = entry.artifact ?? skill.artifact;\n if (!artifact?.url) {\n throw new Error(\"No artifact url available for this version.\");\n }\n\n const artifactSource = resolveRelativeSource(registrySource, artifact.url);\n const outputPath = options.out\n ? path.resolve(process.cwd(), options.out)\n : await createTempFile(`${skill.name}-${version}.skill`);\n\n const buffer = await loadBinary(artifactSource);\n await fs.writeFile(outputPath, buffer);\n\n if (artifact.sha256) {\n const digest = sha256(buffer);\n if (digest !== artifact.sha256) {\n throw new Error(`SHA256 mismatch: expected ${artifact.sha256}, got ${digest}`);\n }\n }\n\n const destination = resolveSkillsDestination(options.to);\n await fs.mkdir(destination, { recursive: true });\n await unzipArchive(outputPath, destination);\n console.log(`Installed ${skill.name} to ${destination}`);\n });\n\nprogram.parseAsync().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n});\n\nasync function loadRegistryIndex(): Promise<RegistryIndex> {\n const { index } = await loadRegistryIndexWithSource();\n return index;\n}\n\nasync function loadRegistryIndexWithSource(): Promise<{ index: RegistryIndex; registrySource: string }> {\n const registrySource = resolveRegistrySource();\n const index = await loadJson<RegistryIndex>(registrySource);\n return { index, registrySource };\n}\n\nfunction resolveRegistrySource(): string {\n const opts = program.opts<{ registry?: string }>();\n if (opts.registry) {\n return opts.registry;\n }\n\n const envRegistry = process.env.REGISTRY_URL;\n if (envRegistry) {\n return envRegistry;\n }\n\n const localCandidates = [\n path.resolve(process.cwd(), \"codex-skills-registry\", \"index.json\"),\n path.resolve(process.cwd(), \"..\", \"codex-skills-registry\", \"index.json\"),\n path.resolve(process.cwd(), \"repos\", \"codex-skills-registry\", \"index.json\"),\n path.resolve(process.cwd(), \"..\", \"repos\", \"codex-skills-registry\", \"index.json\")\n ];\n for (const candidate of localCandidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return DEFAULT_REGISTRY_URL;\n}\n\nfunction findSkill(index: RegistryIndex, name: string): IndexSkill {\n const normalized = name.trim().toLowerCase();\n const skill = index.skills.find((entry) => entry.name.toLowerCase() === normalized);\n if (!skill) {\n throw new Error(`Skill not found: ${name}`);\n }\n return skill;\n}\n\nasync function loadManifest(registrySource: string, manifestPath: string): Promise<SkillManifest> {\n const manifestSource = resolveRelativeSource(registrySource, manifestPath);\n return loadJson<SkillManifest>(manifestSource);\n}\n\nfunction resolveRelativeSource(base: string, relativePath: string): string {\n if (isHttp(relativePath) || relativePath.startsWith(\"file://\")) {\n return relativePath;\n }\n\n if (isHttp(base)) {\n return new URL(relativePath, base).toString();\n }\n\n if (base.startsWith(\"file://\")) {\n const basePath = new URL(base).pathname;\n return path.resolve(path.dirname(basePath), relativePath);\n }\n\n return path.resolve(path.dirname(base), relativePath);\n}\n\nasync function loadJson<T>(source: string): Promise<T> {\n if (isHttp(source)) {\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${source}: ${response.status}`);\n }\n return (await response.json()) as T;\n }\n\n const filePath = source.startsWith(\"file://\") ? new URL(source).pathname : source;\n const raw = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nasync function loadBinary(source: string): Promise<Buffer> {\n if (isHttp(source)) {\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${source}: ${response.status}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n const filePath = source.startsWith(\"file://\") ? new URL(source).pathname : source;\n return fs.readFile(filePath);\n}\n\nfunction isHttp(value: string): boolean {\n return value.startsWith(\"http://\") || value.startsWith(\"https://\");\n}\n\nfunction sha256(buffer: Buffer): string {\n return createHash(\"sha256\").update(buffer).digest(\"hex\");\n}\n\nfunction resolveSkillsDestination(target?: string): string {\n if (target) {\n return path.resolve(process.cwd(), target);\n }\n\n const codexHome = process.env.CODEX_HOME;\n if (codexHome) {\n return path.join(codexHome, \"skills\");\n }\n\n return path.join(os.homedir(), \".codex\", \"skills\");\n}\n\nasync function createTempFile(filename: string): Promise<string> {\n const dir = await fs.mkdtemp(path.join(os.tmpdir(), \"codex-skill-\"));\n return path.join(dir, filename);\n}\n\nasync function unzipArchive(zipPath: string, destination: string): Promise<void> {\n try {\n await runCommand(\"unzip\", [\"-o\", zipPath, \"-d\", destination]);\n return;\n } catch (error) {\n if (process.platform === \"win32\" && isMissingCommand(error)) {\n const originalPath = zipPath;\n let archivePath = zipPath;\n if (path.extname(zipPath).toLowerCase() !== \".zip\") {\n archivePath = await createTempFile(`${path.basename(zipPath, path.extname(zipPath))}.zip`);\n await fs.copyFile(zipPath, archivePath);\n }\n\n try {\n const script = [\n \"Expand-Archive\",\n \"-LiteralPath\",\n `'${escapePowerShell(archivePath)}'`,\n \"-DestinationPath\",\n `'${escapePowerShell(destination)}'`,\n \"-Force\"\n ].join(\" \");\n await runCommand(\"powershell\", [\"-NoProfile\", \"-Command\", script]);\n } finally {\n if (archivePath !== originalPath) {\n await fs.unlink(archivePath).catch(() => undefined);\n }\n }\n return;\n }\n if (isMissingCommand(error)) {\n throw new Error(\"unzip not found. Install unzip or extract the .skill manually.\");\n }\n throw error;\n }\n}\n\nfunction runCommand(command: string, args: string[]): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { stdio: \"inherit\" });\n child.on(\"error\", (error) => {\n reject(error);\n });\n child.on(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`${command} failed with code ${code ?? \"unknown\"}`));\n }\n });\n });\n}\n\nfunction isMissingCommand(error: unknown): boolean {\n return (error as NodeJS.ErrnoException)?.code === \"ENOENT\";\n}\n\nfunction escapePowerShell(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n"],"mappings":"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","names":[]} | ||
| {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { spawn } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport process from \"node:process\";\n\nconst DEFAULT_REGISTRY_URL =\n \"https://raw.githubusercontent.com/iluxu/codex-skills-registry/main/index.json\";\n\ntype IndexSkill = {\n name: string;\n description?: string;\n author?: string;\n tags?: string[];\n compatibility?: string[];\n latest: string;\n artifact?: {\n url: string;\n sha256?: string;\n entry?: string;\n };\n manifest: string;\n};\n\ntype RegistryIndex = {\n registry: string;\n version: string;\n updatedAt: string;\n skills: IndexSkill[];\n};\n\ntype ManifestVersion = {\n version: string;\n releasedAt: string;\n artifact?: {\n url: string;\n sha256?: string;\n entry?: string;\n };\n};\n\ntype SkillManifest = {\n name: string;\n version?: string;\n description?: string;\n author?: string;\n entry?: string;\n tags?: string[];\n compatibility?: string[];\n install?: {\n type: string;\n destination?: string;\n notes?: string;\n };\n versions: ManifestVersion[];\n};\n\nconst program = new Command();\nconst CLI_VERSION = readCliVersion();\n\nprogram\n .name(\"codex-skill\")\n .description(\"Manage Codex skills from a registry.\")\n .version(CLI_VERSION)\n .option(\"--registry <pathOrUrl>\", \"Registry index URL or file path\");\n\nprogram\n .command(\"list\")\n .description(\"List skills from the registry.\")\n .action(async () => {\n const index = await loadRegistryIndex();\n index.skills.forEach((skill) => {\n const tags = skill.tags?.length ? ` [${skill.tags.join(\", \")}]` : \"\";\n const version = skill.latest ? ` (${skill.latest})` : \"\";\n console.log(`${skill.name}${version} — ${skill.description ?? \"\"}${tags}`.trim());\n });\n });\n\nprogram\n .command(\"search\")\n .description(\"Search skills by name, description, or tags.\")\n .argument(\"<query>\", \"Search query\")\n .action(async (query: string) => {\n const index = await loadRegistryIndex();\n const needle = query.toLowerCase();\n const results = index.skills.filter((skill) => {\n const haystack = [skill.name, skill.description ?? \"\", ...(skill.tags ?? [])]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(needle);\n });\n\n if (!results.length) {\n console.log(\"No skills found.\");\n return;\n }\n\n results.forEach((skill) => {\n console.log(`${skill.name} — ${skill.description ?? \"\"}`.trim());\n });\n });\n\nprogram\n .command(\"get\")\n .description(\"Fetch a skill manifest.\")\n .argument(\"<name>\", \"Skill name\")\n .action(async (name: string) => {\n const { index, registrySource } = await loadRegistryIndexWithSource();\n const skill = findSkill(index, name);\n const manifest = await loadManifest(registrySource, skill.manifest);\n console.log(JSON.stringify(manifest, null, 2));\n });\n\nprogram\n .command(\"install\")\n .description(\"Download and install a skill artifact.\")\n .argument(\"<name>\", \"Skill name\")\n .option(\"--version <version>\", \"Specific version\")\n .option(\"--to <path>\", \"Destination directory for skills\")\n .option(\"--out <path>\", \"Output artifact path (optional)\")\n .action(async (name: string, options: { version?: string; out?: string; to?: string }) => {\n const { index, registrySource } = await loadRegistryIndexWithSource();\n const skill = findSkill(index, name);\n const manifest = await loadManifest(registrySource, skill.manifest);\n const version = options.version ?? skill.latest;\n const entry = manifest.versions.find((item) => item.version === version);\n\n if (!entry) {\n throw new Error(`Version not found: ${version}`);\n }\n\n const artifact = entry.artifact ?? skill.artifact;\n if (!artifact?.url) {\n throw new Error(\"No artifact url available for this version.\");\n }\n\n const artifactSource = resolveRelativeSource(registrySource, artifact.url);\n const outputPath = options.out\n ? path.resolve(process.cwd(), options.out)\n : await createTempFile(`${skill.name}-${version}.skill`);\n\n const buffer = await loadBinary(artifactSource);\n await fs.writeFile(outputPath, buffer);\n\n if (artifact.sha256) {\n const digest = sha256(buffer);\n if (digest !== artifact.sha256) {\n throw new Error(`SHA256 mismatch: expected ${artifact.sha256}, got ${digest}`);\n }\n }\n\n const destination = resolveSkillsDestination(options.to);\n await fs.mkdir(destination, { recursive: true });\n await unzipArchive(outputPath, destination);\n console.log(`Installed ${skill.name} to ${destination}`);\n });\n\nprogram.parseAsync().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n});\n\nasync function loadRegistryIndex(): Promise<RegistryIndex> {\n const { index } = await loadRegistryIndexWithSource();\n return index;\n}\n\nasync function loadRegistryIndexWithSource(): Promise<{ index: RegistryIndex; registrySource: string }> {\n const registrySource = resolveRegistrySource();\n const index = await loadJson<RegistryIndex>(registrySource);\n return { index, registrySource };\n}\n\nfunction resolveRegistrySource(): string {\n const opts = program.opts<{ registry?: string }>();\n if (opts.registry) {\n return opts.registry;\n }\n\n const envRegistry = process.env.REGISTRY_URL;\n if (envRegistry) {\n return envRegistry;\n }\n\n const localCandidates = [\n path.resolve(process.cwd(), \"codex-skills-registry\", \"index.json\"),\n path.resolve(process.cwd(), \"..\", \"codex-skills-registry\", \"index.json\"),\n path.resolve(process.cwd(), \"repos\", \"codex-skills-registry\", \"index.json\"),\n path.resolve(process.cwd(), \"..\", \"repos\", \"codex-skills-registry\", \"index.json\")\n ];\n for (const candidate of localCandidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return DEFAULT_REGISTRY_URL;\n}\n\nfunction findSkill(index: RegistryIndex, name: string): IndexSkill {\n const normalized = name.trim().toLowerCase();\n const skill = index.skills.find((entry) => entry.name.toLowerCase() === normalized);\n if (!skill) {\n throw new Error(`Skill not found: ${name}`);\n }\n return skill;\n}\n\nasync function loadManifest(registrySource: string, manifestPath: string): Promise<SkillManifest> {\n const manifestSource = resolveRelativeSource(registrySource, manifestPath);\n return loadJson<SkillManifest>(manifestSource);\n}\n\nfunction resolveRelativeSource(base: string, relativePath: string): string {\n if (isHttp(relativePath) || relativePath.startsWith(\"file://\")) {\n return relativePath;\n }\n\n if (isHttp(base)) {\n return new URL(relativePath, base).toString();\n }\n\n if (base.startsWith(\"file://\")) {\n const basePath = new URL(base).pathname;\n return path.resolve(path.dirname(basePath), relativePath);\n }\n\n return path.resolve(path.dirname(base), relativePath);\n}\n\nasync function loadJson<T>(source: string): Promise<T> {\n if (isHttp(source)) {\n const response = await fetch(withNoCache(source), {\n cache: \"no-store\",\n headers: {\n \"cache-control\": \"no-cache\",\n pragma: \"no-cache\"\n }\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch ${source}: ${response.status}`);\n }\n return (await response.json()) as T;\n }\n\n const filePath = source.startsWith(\"file://\") ? new URL(source).pathname : source;\n const raw = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nasync function loadBinary(source: string): Promise<Buffer> {\n if (isHttp(source)) {\n const response = await fetch(withNoCache(source), {\n cache: \"no-store\",\n headers: {\n \"cache-control\": \"no-cache\",\n pragma: \"no-cache\"\n }\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch ${source}: ${response.status}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n const filePath = source.startsWith(\"file://\") ? new URL(source).pathname : source;\n return fs.readFile(filePath);\n}\n\nfunction isHttp(value: string): boolean {\n return value.startsWith(\"http://\") || value.startsWith(\"https://\");\n}\n\nfunction withNoCache(source: string): string {\n const url = new URL(source);\n url.searchParams.set(\"_\", `${Date.now()}`);\n return url.toString();\n}\n\nfunction sha256(buffer: Buffer): string {\n return createHash(\"sha256\").update(buffer).digest(\"hex\");\n}\n\nfunction readCliVersion(): string {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url);\n const raw = readFileSync(packageJsonPath, \"utf-8\");\n const parsed = JSON.parse(raw) as { version?: string };\n return parsed.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction resolveSkillsDestination(target?: string): string {\n if (target) {\n return path.resolve(process.cwd(), target);\n }\n\n const codexHome = process.env.CODEX_HOME;\n if (codexHome) {\n return path.join(codexHome, \"skills\");\n }\n\n return path.join(os.homedir(), \".codex\", \"skills\");\n}\n\nasync function createTempFile(filename: string): Promise<string> {\n const dir = await fs.mkdtemp(path.join(os.tmpdir(), \"codex-skill-\"));\n return path.join(dir, filename);\n}\n\nasync function unzipArchive(zipPath: string, destination: string): Promise<void> {\n try {\n await runCommand(\"unzip\", [\"-o\", zipPath, \"-d\", destination]);\n return;\n } catch (error) {\n if (process.platform === \"win32\" && isMissingCommand(error)) {\n const originalPath = zipPath;\n let archivePath = zipPath;\n if (path.extname(zipPath).toLowerCase() !== \".zip\") {\n archivePath = await createTempFile(`${path.basename(zipPath, path.extname(zipPath))}.zip`);\n await fs.copyFile(zipPath, archivePath);\n }\n\n try {\n const script = [\n \"Expand-Archive\",\n \"-LiteralPath\",\n `'${escapePowerShell(archivePath)}'`,\n \"-DestinationPath\",\n `'${escapePowerShell(destination)}'`,\n \"-Force\"\n ].join(\" \");\n await runCommand(\"powershell\", [\"-NoProfile\", \"-Command\", script]);\n } finally {\n if (archivePath !== originalPath) {\n await fs.unlink(archivePath).catch(() => undefined);\n }\n }\n return;\n }\n if (isMissingCommand(error)) {\n throw new Error(\"unzip not found. Install unzip or extract the .skill manually.\");\n }\n throw error;\n }\n}\n\nfunction runCommand(command: string, args: string[]): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { stdio: \"inherit\" });\n child.on(\"error\", (error) => {\n reject(error);\n });\n child.on(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`${command} failed with code ${code ?? \"unknown\"}`));\n }\n });\n });\n}\n\nfunction isMissingCommand(error: unknown): boolean {\n return (error as NodeJS.ErrnoException)?.code === \"ENOENT\";\n}\n\nfunction escapePowerShell(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n"],"mappings":"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","names":[]} |
+1
-1
| { | ||
| "name": "codex-skill", | ||
| "version": "0.1.3", | ||
| "version": "0.1.4", | ||
| "description": "CLI for installing and managing Codex skills from a registry.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
29320
7.85%259
12.12%