create-videowright 0.1.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/bin/cli.js +5 -0
- package/bin/index.js +136 -0
- package/package.json +25 -0
package/bin/cli.js
ADDED
package/bin/index.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
|
|
4
|
+
const INSTALL_URL =
|
|
5
|
+
"https://github.com/scosman/videowright/blob/main/packages/lib/skill/install/INSTALL.md";
|
|
6
|
+
|
|
7
|
+
const INSTALL_PROMPT = `Install Videowright using these instructions: ${INSTALL_URL}`;
|
|
8
|
+
|
|
9
|
+
const AGENTS = [
|
|
10
|
+
{ key: "claude", label: "Claude Code", cmd: "claude" },
|
|
11
|
+
{ key: "codex", label: "Codex", cmd: "codex" },
|
|
12
|
+
{ key: "opencode", label: "opencode", cmd: "opencode" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
/** Check if a single binary is available by spawning it with --version. */
|
|
16
|
+
function probeAgent(cmd) {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
try {
|
|
19
|
+
const child = spawn(cmd, ["--version"], { stdio: "ignore" });
|
|
20
|
+
child.on("error", () => resolve(false));
|
|
21
|
+
child.on("exit", (code) => resolve(code === 0));
|
|
22
|
+
} catch {
|
|
23
|
+
resolve(false);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Detect which supported coding agents are installed (in parallel). */
|
|
29
|
+
export async function detectAgents() {
|
|
30
|
+
const results = await Promise.all(AGENTS.map((a) => probeAgent(a.cmd)));
|
|
31
|
+
const detected = {};
|
|
32
|
+
for (let i = 0; i < AGENTS.length; i++) {
|
|
33
|
+
detected[AGENTS[i].key] = results[i];
|
|
34
|
+
}
|
|
35
|
+
return detected;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Pick which agent to hand off to.
|
|
40
|
+
* Returns the agent key, or null if none detected.
|
|
41
|
+
*/
|
|
42
|
+
export async function chooseAgent(detected) {
|
|
43
|
+
const available = AGENTS.filter((a) => detected[a.key]);
|
|
44
|
+
|
|
45
|
+
if (available.length === 0) return null;
|
|
46
|
+
if (available.length === 1) return available[0].key;
|
|
47
|
+
|
|
48
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
49
|
+
|
|
50
|
+
const lines = [
|
|
51
|
+
"Multiple coding agents detected. Which would you like to install Videowright into?",
|
|
52
|
+
];
|
|
53
|
+
for (let i = 0; i < available.length; i++) {
|
|
54
|
+
lines.push(` ${i + 1}) ${available[i].label}`);
|
|
55
|
+
}
|
|
56
|
+
lines.push("");
|
|
57
|
+
const numbers = available.map((_, i) => i + 1);
|
|
58
|
+
const numbersText =
|
|
59
|
+
numbers.length <= 1
|
|
60
|
+
? String(numbers[0])
|
|
61
|
+
: `${numbers.slice(0, -1).join(", ")}, or ${numbers[numbers.length - 1]}`;
|
|
62
|
+
const prompt = `${lines.join("\n")}Enter ${numbersText} [1]: `;
|
|
63
|
+
|
|
64
|
+
const answer = await new Promise((resolve) => {
|
|
65
|
+
rl.question(prompt, (ans) => {
|
|
66
|
+
rl.close();
|
|
67
|
+
resolve(ans.trim());
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (answer === "") return available[0].key;
|
|
72
|
+
|
|
73
|
+
const index = Number.parseInt(answer, 10) - 1;
|
|
74
|
+
if (index >= 0 && index < available.length) return available[index].key;
|
|
75
|
+
|
|
76
|
+
// Invalid input — default to first
|
|
77
|
+
return available[0].key;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Build the CLI command + args to launch the chosen agent with the install prompt. */
|
|
81
|
+
export function handoffCommand(agent) {
|
|
82
|
+
switch (agent) {
|
|
83
|
+
case "claude":
|
|
84
|
+
return { cmd: "claude", args: [INSTALL_PROMPT] };
|
|
85
|
+
case "codex":
|
|
86
|
+
return { cmd: "codex", args: [INSTALL_PROMPT] };
|
|
87
|
+
case "opencode":
|
|
88
|
+
return { cmd: "opencode", args: ["--prompt", INSTALL_PROMPT] };
|
|
89
|
+
default:
|
|
90
|
+
throw new Error(`Unknown agent: ${agent}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Spawn the agent, inheriting stdio so it takes over the terminal. */
|
|
95
|
+
export function spawnAgent(cmd, args) {
|
|
96
|
+
const child = spawn(cmd, args, { stdio: "inherit" });
|
|
97
|
+
|
|
98
|
+
child.on("error", (err) => {
|
|
99
|
+
console.error(
|
|
100
|
+
`Failed to start ${cmd}: ${err.message}\nTry running \`npm init videowright\` again.`,
|
|
101
|
+
);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
child.on("exit", (code) => {
|
|
106
|
+
process.exit(code ?? 0);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function printFallback() {
|
|
111
|
+
console.log("We couldn't find Claude Code, Codex, or opencode installed.");
|
|
112
|
+
console.log("Install one of those, or paste this into your coding agent of choice:");
|
|
113
|
+
console.log("");
|
|
114
|
+
console.log(` ${INSTALL_PROMPT}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function main() {
|
|
118
|
+
const detected = await detectAgents();
|
|
119
|
+
|
|
120
|
+
let agent;
|
|
121
|
+
try {
|
|
122
|
+
agent = await chooseAgent(detected);
|
|
123
|
+
} catch {
|
|
124
|
+
// Non-interactive stdin (piped/closed) — default to first detected agent
|
|
125
|
+
const available = AGENTS.filter((a) => detected[a.key]);
|
|
126
|
+
agent = available.length > 0 ? available[0].key : null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (agent === null) {
|
|
130
|
+
printFallback();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const { cmd, args } = handoffCommand(agent);
|
|
135
|
+
spawnAgent(cmd, args);
|
|
136
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-videowright",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "npm init videowright — detect your coding agent and hand off the Videowright install",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/scosman/videowright.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/scosman/videowright",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/scosman/videowright/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"bin": {
|
|
16
|
+
"create-videowright": "bin/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"files": ["bin"],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "vitest run"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"vitest": "^3.1.3"
|
|
24
|
+
}
|
|
25
|
+
}
|