🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

getsuperpower

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

getsuperpower - npm Package Compare versions

Comparing version
0.3.0
to
0.3.1
+7
-3
package.json
{
"name": "getsuperpower",
"version": "0.3.0",
"version": "0.3.1",
"type": "module",
"repository": {
"type": "git",
"url": "https://github.com/0xroylee/getsuperpower"
},
"bin": {

@@ -18,6 +22,6 @@ "getsuperpower": "dist/cli.js"

"build": "bun build --target=bun --outfile=dist/cli.js src/cli.ts",
"test": "bun test",
"test": "bun test tests",
"ci:test": "find tests -maxdepth 1 -name '*.test.ts' ! -name '*.e2e.test.ts' -print0 | xargs -0 bun test",
"ci:check": "biome check . && bun run typecheck && bun run ci:test",
"coverage": "bun test --coverage --coverage-reporter=lcov --coverage-dir=coverage && bun scripts/check-coverage.ts 90 coverage/lcov.info",
"coverage": "bun test tests --coverage --coverage-reporter=lcov --coverage-dir=coverage && bun scripts/check-coverage.ts 90 coverage/lcov.info",
"coverage:check": "bun scripts/check-coverage.ts 90 coverage/lcov.info",

@@ -24,0 +28,0 @@ "deps:check-recency": "bun scripts/check-package-recency.ts",

+11
-49

@@ -19,2 +19,9 @@ <img src="/assets/getsupwerpower.jpg" alt="GetSuperpower" width="640" />

Install from a public git repository:
```bash
npx getsuperpower install https://github.com/acme/release-review.git
npx getsuperpower install 'https://github.com/acme/workflows.git#examples/release-review'
```
List installed GetSuperpowers:

@@ -32,33 +39,4 @@

```mermaid
flowchart LR
Install["getsuperpower install"]
Manifest["workflow.json<br/>what to install"]
Entry["entry skill<br/>what users call"]
Skills["sub-skills<br/>what the agent uses"]
Agent["Claude / Codex / opencode / Cursor / GitHub Copilot"]
Result["workflow result"]
<img src="assets/diagrams/getsuperpower-how-it-works.svg" alt="GetSuperpower workflow diagram" width="720" />
Install --> Manifest
Manifest --> Entry
Manifest --> Skills
Entry --> Agent
Skills --> Agent
Agent --> Result
classDef command fill:#dbeafe,stroke:#2563eb,color:#172554;
classDef manifest fill:#dcfce7,stroke:#16a34a,color:#052e16;
classDef entry fill:#f3e8ff,stroke:#9333ea,color:#3b0764;
classDef skills fill:#ffedd5,stroke:#f97316,color:#431407;
classDef agent fill:#fef9c3,stroke:#ca8a04,color:#422006;
classDef result fill:#e0f2fe,stroke:#0284c7,color:#082f49;
class Install command;
class Manifest manifest;
class Entry entry;
class Skills skills;
class Agent agent;
class Result result;
```
`workflow.json` installs the skill tree. The entry skill runs it. Sub-skills are the steps the agent follows.

@@ -68,22 +46,4 @@

```mermaid
sequenceDiagram
autonumber
actor User as User
participant CLI as GetSuperpower CLI
participant Workflow as workflow json
participant Skills as entry skill and sub skills
participant State as workflow records
participant Agent as AI agent
<img src="assets/diagrams/getsuperpower-install-sequence.svg" alt="GetSuperpower install and run sequence diagram" width="920" />
User->>CLI: install or clone a GetSuperpower
CLI->>Workflow: read workflow.json skills and steps
CLI->>Skills: install required skills
CLI->>State: save .getsuperpower/workflows record
User->>Agent: call the entry skill
Agent->>Workflow: follow the skill tree
Agent->>Skills: use sub-skills in order
Agent-->>User: return the workflow result
```
## Try A Callable Workflow

@@ -176,2 +136,3 @@

| `npx getsuperpower clone product-dev` | Same as install; deploy a GetSuperpower by name or source. |
| `npx getsuperpower install https://github.com/acme/release-review.git` | Install a GetSuperpower from a public git repo. |
| `npx getsuperpower deps <source>` | Show required skills before install or clone. |

@@ -207,2 +168,3 @@ | `npx getsuperpower list` | Show installed GetSuperpowers. |

bun run check
bun scripts/smoke-public-git-install.ts
```

@@ -209,0 +171,0 @@

@@ -17,3 +17,3 @@ #!/usr/bin/env bun

const CLI_VERSION = "0.3.0";
const CLI_VERSION = "0.3.1";

@@ -20,0 +20,0 @@ interface CommanderVersionInternals {

@@ -16,2 +16,3 @@ import { homedir } from "node:os";

loadWorkflowBundle,
type WorkflowGitCommandRunner,
} from "./runtimes/ponytrail";

@@ -81,2 +82,3 @@

installExternalSkillDependency?: GetSuperpowerExternalSkillDependencyInstaller;
workflowGitCommandRunner?: WorkflowGitCommandRunner;
}

@@ -101,3 +103,3 @@

.description("Compatibility alias for GetSuperpower authoring.");
configureAuthorCommands(bundleCommand, options.rootDir);
configureAuthorCommands(bundleCommand, options);

@@ -117,9 +119,12 @@ const workflowCommand = program

): void {
configureAuthorCommands(command, options.rootDir);
configureAuthorCommands(command, options);
configureInstallCommand(command, options);
configureListCommand(command, options.rootDir);
configureDependencyCommand(command, options.rootDir);
configureDependencyCommand(command, options);
}
function configureAuthorCommands(command: Command, rootDir: string): void {
function configureAuthorCommands(
command: Command,
options: ConfigureGetSuperpowerCommandOptions,
): void {
command

@@ -129,6 +134,6 @@ .command("init")

.argument("<name>", "GetSuperpower name")
.option("--dir <dir>", "directory that will contain the GetSuperpower", rootDir)
.option("--dir <dir>", "directory that will contain the GetSuperpower", options.rootDir)
.action(async (name: string, commandOptions: { dir: string }) => {
const scaffold = await createWorkflowBundleScaffold({
rootDir: resolvePath(rootDir, commandOptions.dir),
rootDir: resolvePath(options.rootDir, commandOptions.dir),
name,

@@ -147,7 +152,15 @@ });

.action(async (path: string) => {
const bundle = await loadWorkflowBundle(path, { cwd: rootDir });
console.log(`GetSuperpower valid: ${bundle.manifest.name}@${bundle.manifest.version}`);
console.log(`${pc.dim("Steps:")} ${bundle.manifest.steps.length}`);
console.log(`${pc.dim("Skills:")} ${bundle.manifest.skills.length}`);
const bundle = await loadWorkflowBundle(path, {
cwd: options.rootDir,
...(options.workflowGitCommandRunner
? { runGitCommand: options.workflowGitCommandRunner }
: {}),
});
try {
console.log(`GetSuperpower valid: ${bundle.manifest.name}@${bundle.manifest.version}`);
console.log(`${pc.dim("Steps:")} ${bundle.manifest.steps.length}`);
console.log(`${pc.dim("Skills:")} ${bundle.manifest.skills.length}`);
} finally {
await bundle.cleanup?.();
}
});

@@ -198,3 +211,8 @@ }

const targetDir = resolvePath(options.rootDir, commandOptions.dir);
const bundle = await loadWorkflowBundle(source, { cwd: options.rootDir });
const bundle = await loadWorkflowBundle(source, {
cwd: options.rootDir,
...(options.workflowGitCommandRunner
? { runGitCommand: options.workflowGitCommandRunner }
: {}),
});
const installAgents = parseSkillInstallAgents(commandOptions.agents);

@@ -204,23 +222,27 @@ const homeDir = resolveHomePath(commandOptions.home);

for (const skillSource of getWorkflowSkillInstallSources(bundle)) {
const skillResult = await installGetSuperpowerSkillDependency({
rootDir: targetDir,
source: skillSource,
homeDir,
agents: installAgents,
installSkill: options.installSkill,
installExternalSkillDependency:
options.installExternalSkillDependency ?? installExternalSkillDependencyWithSkillsCli,
installedExternalPackages,
});
try {
for (const skillSource of getWorkflowSkillInstallSources(bundle)) {
const skillResult = await installGetSuperpowerSkillDependency({
rootDir: targetDir,
source: skillSource,
homeDir,
agents: installAgents,
installSkill: options.installSkill,
installExternalSkillDependency:
options.installExternalSkillDependency ?? installExternalSkillDependencyWithSkillsCli,
installedExternalPackages,
});
options.printSkillInstallResult(skillResult.skillInstall, "install", {
showPostSkillChangeWelcome: false,
});
}
options.printSkillInstallResult(skillResult.skillInstall, "install", {
showPostSkillChangeWelcome: false,
});
}
const install = await installWorkflowBundle({ rootDir: targetDir, bundle });
const install = await installWorkflowBundle({ rootDir: targetDir, bundle });
console.log(`GetSuperpower installed: ${install.workflow.name}`);
console.log(`${pc.dim("GetSuperpower file:")} ${install.path}`);
console.log(`GetSuperpower installed: ${install.workflow.name}`);
console.log(`${pc.dim("GetSuperpower file:")} ${install.path}`);
} finally {
await bundle.cleanup?.();
}
}

@@ -389,3 +411,6 @@

function configureDependencyCommand(command: Command, rootDir: string): void {
function configureDependencyCommand(
command: Command,
options: ConfigureGetSuperpowerCommandOptions,
): void {
command

@@ -397,8 +422,16 @@ .command("deps")

.action(async (source: string) => {
const bundle = await loadWorkflowBundle(source, { cwd: rootDir });
console.log(`GetSuperpower dependencies: ${bundle.manifest.name}`);
for (const skill of bundle.manifest.skills) {
const optional = skill.optional ? " (optional)" : "";
console.log(`- ${skill.source}${optional}`);
const bundle = await loadWorkflowBundle(source, {
cwd: options.rootDir,
...(options.workflowGitCommandRunner
? { runGitCommand: options.workflowGitCommandRunner }
: {}),
});
try {
console.log(`GetSuperpower dependencies: ${bundle.manifest.name}`);
for (const skill of bundle.manifest.skills) {
const optional = skill.optional ? " (optional)" : "";
console.log(`- ${skill.source}${optional}`);
}
} finally {
await bundle.cleanup?.();
}

@@ -405,0 +438,0 @@ });

import { existsSync } from "node:fs";
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
import { mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, isAbsolute, join, resolve } from "node:path";

@@ -57,2 +58,31 @@ import { z } from "zod";

export interface WorkflowGitCommand {
executable: string;
args: string[];
cwd: string;
env: Record<string, string | undefined>;
}
export interface WorkflowGitCommandResult {
stdout: string;
stderr: string;
exitCode: number;
}
export type WorkflowGitCommandRunner = (
command: WorkflowGitCommand,
) => Promise<WorkflowGitCommandResult>;
export type WorkflowBundleSource =
| {
kind: "bundled" | "local";
path: string;
}
| {
kind: "git";
url: string;
commit?: string;
subdirectory?: string;
};
export interface WorkflowBundle {

@@ -62,3 +92,4 @@ manifest: WorkflowBundleManifest;

manifestPath: string;
bundled: boolean;
source: WorkflowBundleSource;
cleanup?: () => Promise<void>;
}

@@ -74,6 +105,3 @@

export interface InstalledWorkflowBundle extends WorkflowBundleManifest {
source: {
kind: "bundled" | "local";
path: string;
};
source: WorkflowBundleSource;
}

@@ -88,18 +116,40 @@

source: string,
options: { cwd?: string } = {},
options: {
cwd?: string;
runGitCommand?: WorkflowGitCommandRunner;
tempDir?: string;
} = {},
): Promise<WorkflowBundle> {
const sourceDir = resolveWorkflowBundleSource(source, options.cwd ?? process.cwd());
const manifestPath = sourceDir.endsWith(workflowFileName)
? sourceDir
: join(sourceDir, workflowFileName);
const manifestDir = sourceDir.endsWith(workflowFileName) ? dirname(sourceDir) : sourceDir;
const rawManifest = await readFile(manifestPath, "utf8");
const manifest = WorkflowBundleManifestSchema.parse(JSON.parse(rawManifest));
const resolvedSource = await resolveWorkflowBundleSource(source, {
cwd: options.cwd ?? process.cwd(),
...(options.runGitCommand ? { runGitCommand: options.runGitCommand } : {}),
...(options.tempDir ? { tempDir: options.tempDir } : {}),
});
const manifestPath = resolvedSource.sourceDir.endsWith(workflowFileName)
? resolvedSource.sourceDir
: join(resolvedSource.sourceDir, workflowFileName);
const manifestDir = resolvedSource.sourceDir.endsWith(workflowFileName)
? dirname(resolvedSource.sourceDir)
: resolvedSource.sourceDir;
return {
manifest,
sourceDir: manifestDir,
manifestPath,
bundled: isBundledWorkflowSource(source),
};
try {
const rawManifest = await readFile(manifestPath, "utf8");
const manifest = WorkflowBundleManifestSchema.parse(JSON.parse(rawManifest));
return {
manifest,
sourceDir: manifestDir,
manifestPath,
source: resolvedSource.source,
...(resolvedSource.cleanup ? { cleanup: resolvedSource.cleanup } : {}),
};
} catch (error) {
await resolvedSource.cleanup?.();
if (resolvedSource.source.kind === "git" && isMissingFileError(error)) {
throw new Error(
`No GetSuperpower workflow manifest was found at ${manifestPath} from public git source: ${resolvedSource.source.url}`,
);
}
throw error;
}
}

@@ -192,6 +242,3 @@

...bundle.manifest,
source: {
kind: bundle.bundled ? "bundled" : "local",
path: bundle.sourceDir,
},
source: bundle.source,
};

@@ -281,8 +328,28 @@ }

function resolveWorkflowBundleSource(source: string, cwd: string): string {
interface ResolvedWorkflowBundleSource {
sourceDir: string;
source: WorkflowBundleSource;
cleanup?: () => Promise<void>;
}
async function resolveWorkflowBundleSource(
source: string,
options: {
cwd: string;
runGitCommand?: WorkflowGitCommandRunner;
tempDir?: string;
},
): Promise<ResolvedWorkflowBundleSource> {
const gitSource = parseGitWorkflowSource(source);
if (gitSource) {
return cloneGitWorkflowSource(gitSource, options);
}
if (isLocalWorkflowSource(source)) {
return isAbsolute(source) ? source : resolve(cwd, source);
const sourceDir = isAbsolute(source) ? source : resolve(options.cwd, source);
return { sourceDir, source: { kind: "local", path: sourceDir } };
}
return join(findBundledWorkflowsDir(), source);
const sourceDir = join(findBundledWorkflowsDir(), source);
return { sourceDir, source: { kind: "bundled", path: sourceDir } };
}

@@ -302,6 +369,153 @@

function isBundledWorkflowSource(source: string): boolean {
return !isLocalWorkflowSource(source);
interface GitWorkflowSource {
cloneUrl: string;
url: string;
subdirectory?: string;
}
function parseGitWorkflowSource(source: string): GitWorkflowSource | null {
let url: URL;
try {
url = new URL(source);
} catch {
return null;
}
if (url.protocol !== "https:" && url.protocol !== "file:") {
return null;
}
const subdirectory = parseGitWorkflowSubdirectory(url.hash);
url.hash = "";
return {
cloneUrl: url.toString(),
url: source,
...(subdirectory ? { subdirectory } : {}),
};
}
function parseGitWorkflowSubdirectory(hash: string): string | undefined {
if (!hash) {
return undefined;
}
const rawHash = decodeURIComponent(hash.slice(1));
const params = new URLSearchParams(rawHash);
const candidate = params.get("path") ?? (rawHash.includes("=") ? undefined : rawHash);
if (!candidate) {
return undefined;
}
const normalized = candidate
.split("/")
.filter((part) => part.length > 0 && part !== ".")
.join("/");
if (!normalized) {
return undefined;
}
if (
normalized === ".." ||
normalized.startsWith("../") ||
normalized.includes("/../") ||
isAbsolute(normalized)
) {
throw new Error(`Unsupported public git workflow subdirectory: ${candidate}`);
}
return normalized;
}
async function cloneGitWorkflowSource(
source: GitWorkflowSource,
options: {
cwd: string;
runGitCommand?: WorkflowGitCommandRunner;
tempDir?: string;
},
): Promise<ResolvedWorkflowBundleSource> {
const tempRoot = await mkdtemp(join(options.tempDir ?? tmpdir(), "getsuperpower-git-"));
const checkoutDir = join(tempRoot, "checkout");
const cleanup = () => rm(tempRoot, { recursive: true, force: true });
try {
await runRequiredGitCommand(
{
executable: "git",
args: ["clone", "--depth", "1", source.cloneUrl, checkoutDir],
cwd: options.cwd,
env: process.env,
},
options.runGitCommand,
`Public git workflow source could not be fetched: ${source.url}`,
);
const commitResult = await runOptionalGitCommand(
{
executable: "git",
args: ["rev-parse", "HEAD"],
cwd: checkoutDir,
env: process.env,
},
options.runGitCommand,
);
const commit = commitResult.exitCode === 0 ? commitResult.stdout.trim() : undefined;
const sourceDir = source.subdirectory ? join(checkoutDir, source.subdirectory) : checkoutDir;
return {
sourceDir,
source: {
kind: "git",
url: source.url,
...(commit ? { commit } : {}),
...(source.subdirectory ? { subdirectory: source.subdirectory } : {}),
},
cleanup,
};
} catch (error) {
await cleanup();
throw error;
}
}
async function runRequiredGitCommand(
command: WorkflowGitCommand,
runGitCommand: WorkflowGitCommandRunner | undefined,
failureMessage: string,
): Promise<WorkflowGitCommandResult> {
const result = await runOptionalGitCommand(command, runGitCommand);
if (result.exitCode !== 0) {
const detail = [result.stderr.trim(), result.stdout.trim()].filter(Boolean).join("\n");
throw new Error(detail ? `${failureMessage}\n${detail}` : failureMessage);
}
return result;
}
async function runOptionalGitCommand(
command: WorkflowGitCommand,
runGitCommand: WorkflowGitCommandRunner | undefined,
): Promise<WorkflowGitCommandResult> {
if (runGitCommand) {
return runGitCommand(command);
}
const subprocess = Bun.spawn([command.executable, ...command.args], {
cwd: command.cwd,
stdout: "pipe",
stderr: "pipe",
env: command.env,
});
const [stdout, stderr, exitCode] = await Promise.all([
new Response(subprocess.stdout).text(),
new Response(subprocess.stderr).text(),
subprocess.exited,
]);
return { stdout, stderr, exitCode };
}
function isMissingFileError(error: unknown): boolean {
return (error as NodeJS.ErrnoException).code === "ENOENT";
}
function findBundledWorkflowsDir(): string {

@@ -308,0 +522,0 @@ const currentDir = dirname(new URL(import.meta.url).pathname);

Sorry, the diff of this file is too big to display