clisponsor 1.0.17 → 1.0.20
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/README.md +1 -1
- package/bin/clisponsor.mjs +164 -18
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CLIsponsor Hook
|
|
2
2
|
|
|
3
|
-
Hook package codebase for the `clisponsor` installer and Codex, Claude Code, Gemini, Antigravity, OpenCode, Pi, GitHub Copilot CLI,
|
|
3
|
+
Hook package codebase for the `clisponsor` installer and Codex, Claude Code, Gemini, Antigravity, OpenCode, Pi, GitHub Copilot CLI, Qwen Code, Factory Droid, and Devin hook templates.
|
|
4
4
|
|
|
5
5
|
This codebase owns local installation, device login, diagnostics, and hook adapters. It must not contain public website, dashboard app, API account, or ad-serving server code.
|
|
6
6
|
|
package/bin/clisponsor.mjs
CHANGED
|
@@ -170,6 +170,14 @@ function qwenHome() {
|
|
|
170
170
|
return process.env.QWEN_HOME || path.join(HOME, ".qwen");
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
function factoryHome() {
|
|
174
|
+
return process.env.FACTORY_HOME || path.join(HOME, ".factory");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function devinConfigPath() {
|
|
178
|
+
return process.env.DEVIN_CONFIG_PATH || path.join(xdgConfigHome(), "devin", "config.json");
|
|
179
|
+
}
|
|
180
|
+
|
|
173
181
|
function colorEnabled() {
|
|
174
182
|
return Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
175
183
|
}
|
|
@@ -269,6 +277,8 @@ function isClisponsorCommand(value) {
|
|
|
269
277
|
value.includes("clisponsor_pi_extension") ||
|
|
270
278
|
value.includes("clisponsor_copilot_hook.mjs") ||
|
|
271
279
|
value.includes("clisponsor_qwen_hook.mjs") ||
|
|
280
|
+
value.includes("clisponsor_droid_hook.mjs") ||
|
|
281
|
+
value.includes("clisponsor_devin_hook.mjs") ||
|
|
272
282
|
value.includes(`${path.sep}.clisponsor${path.sep}`) ||
|
|
273
283
|
value.includes("/.clisponsor/") ||
|
|
274
284
|
value.includes("\\.clisponsor\\"))
|
|
@@ -364,6 +374,51 @@ function addQwenCommandHook(settings, eventName, command) {
|
|
|
364
374
|
return true;
|
|
365
375
|
}
|
|
366
376
|
|
|
377
|
+
function addDroidCommandHook(settings, eventName, command) {
|
|
378
|
+
if (!isPlainObject(settings.hooks)) settings.hooks = {};
|
|
379
|
+
const current = Array.isArray(settings.hooks[eventName]) ? settings.hooks[eventName] : [];
|
|
380
|
+
const exists = current.some((entry) => isClisponsorHookEntry(entry));
|
|
381
|
+
if (exists) return false;
|
|
382
|
+
|
|
383
|
+
settings.hooks[eventName] = [
|
|
384
|
+
...current,
|
|
385
|
+
{
|
|
386
|
+
hooks: [
|
|
387
|
+
{
|
|
388
|
+
type: "command",
|
|
389
|
+
command,
|
|
390
|
+
name: "clisponsor",
|
|
391
|
+
timeout: 5,
|
|
392
|
+
},
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
];
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function addDevinCommandHook(settings, eventName, command) {
|
|
400
|
+
if (!isPlainObject(settings.hooks)) settings.hooks = {};
|
|
401
|
+
const current = Array.isArray(settings.hooks[eventName]) ? settings.hooks[eventName] : [];
|
|
402
|
+
const exists = current.some((entry) => isClisponsorHookEntry(entry));
|
|
403
|
+
if (exists) return false;
|
|
404
|
+
|
|
405
|
+
settings.hooks[eventName] = [
|
|
406
|
+
...current,
|
|
407
|
+
{
|
|
408
|
+
matcher: "",
|
|
409
|
+
hooks: [
|
|
410
|
+
{
|
|
411
|
+
type: "command",
|
|
412
|
+
command,
|
|
413
|
+
name: "clisponsor",
|
|
414
|
+
timeout: 5,
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
},
|
|
418
|
+
];
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
|
|
367
422
|
function removeClaudeCommandHooks(settings) {
|
|
368
423
|
if (!isPlainObject(settings.hooks)) return false;
|
|
369
424
|
let changed = false;
|
|
@@ -540,11 +595,17 @@ const event = process.argv[2] || "BeforeAgent";
|
|
|
540
595
|
const outputMode = ${JSON.stringify(outputMode)};
|
|
541
596
|
const placements = { SessionStart: "StartSession", PreInvocation: "StartTurn", BeforeAgent: "StartTurn", UserPromptSubmit: "StartTurn", PreToolUse: "StartTurn", AfterAgent: "EndTurn", PostInvocation: "EndTurn", Stop: "EndTurn", StartTurn: "StartTurn" };
|
|
542
597
|
function writeNoop() {
|
|
543
|
-
if (outputMode === "antigravity") console.log(JSON.stringify({}));
|
|
598
|
+
if (outputMode === "antigravity" || outputMode === "terminalMessage") console.log(JSON.stringify({}));
|
|
544
599
|
}
|
|
545
600
|
function sponsoredLine(line) {
|
|
546
601
|
return "[Sponsored] " + line;
|
|
547
602
|
}
|
|
603
|
+
function writeTerminalMessage(message) {
|
|
604
|
+
const target = process.env.CLISPONSOR_TTY_MESSAGE_PATH || "/dev/tty";
|
|
605
|
+
try {
|
|
606
|
+
fs.appendFileSync(target, "\\nCLIsponsor Message: " + message + "\\n");
|
|
607
|
+
} catch {}
|
|
608
|
+
}
|
|
548
609
|
function readStdin() {
|
|
549
610
|
return new Promise((resolve) => {
|
|
550
611
|
let data = "";
|
|
@@ -597,6 +658,9 @@ try {
|
|
|
597
658
|
const payload = {};
|
|
598
659
|
if (ad.display_line) payload.injectSteps = [{ userMessage: sponsoredLine(ad.display_line) }];
|
|
599
660
|
console.log(JSON.stringify(payload));
|
|
661
|
+
} else if (outputMode === "terminalMessage") {
|
|
662
|
+
if (ad.display_line) writeTerminalMessage(sponsoredLine(ad.display_line));
|
|
663
|
+
console.log(JSON.stringify({}));
|
|
600
664
|
} else if (ad.display_line) {
|
|
601
665
|
console.log(JSON.stringify({ systemMessage: sponsoredLine(ad.display_line) }));
|
|
602
666
|
}
|
|
@@ -1003,7 +1067,7 @@ function installQwen() {
|
|
|
1003
1067
|
const qwenDir = path.join(CONFIG_DIR, "qwen");
|
|
1004
1068
|
fs.mkdirSync(qwenDir, { recursive: true });
|
|
1005
1069
|
const hookPath = path.join(qwenDir, "clisponsor_qwen_hook.mjs");
|
|
1006
|
-
fs.writeFileSync(hookPath, agentHookSource("QwenCode"), { mode: 0o755 });
|
|
1070
|
+
fs.writeFileSync(hookPath, agentHookSource("QwenCode", { outputMode: "terminalMessage" }), { mode: 0o755 });
|
|
1007
1071
|
|
|
1008
1072
|
const settingsPath = path.join(qwenHome(), "settings.json");
|
|
1009
1073
|
const settings = readEditableJson(settingsPath, {});
|
|
@@ -1015,6 +1079,48 @@ function installQwen() {
|
|
|
1015
1079
|
console.log("Qwen Code CLI hook installed.");
|
|
1016
1080
|
}
|
|
1017
1081
|
|
|
1082
|
+
function installDroid() {
|
|
1083
|
+
if (!commandExists("droid")) {
|
|
1084
|
+
console.log("Factory Droid CLI not found. To enable CLIsponsor for Droid, install Droid CLI and rerun: npx clisponsor@latest install");
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
const droidDir = path.join(CONFIG_DIR, "droid");
|
|
1089
|
+
fs.mkdirSync(droidDir, { recursive: true });
|
|
1090
|
+
const hookPath = path.join(droidDir, "clisponsor_droid_hook.mjs");
|
|
1091
|
+
fs.writeFileSync(hookPath, agentHookSource("Droid"), { mode: 0o755 });
|
|
1092
|
+
|
|
1093
|
+
const hooksPath = path.join(factoryHome(), "hooks.json");
|
|
1094
|
+
const hooksConfig = readEditableJson(hooksPath, {});
|
|
1095
|
+
addDroidCommandHook(hooksConfig, "SessionStart", `node ${JSON.stringify(hookPath)} SessionStart`);
|
|
1096
|
+
addDroidCommandHook(hooksConfig, "UserPromptSubmit", `node ${JSON.stringify(hookPath)} UserPromptSubmit`);
|
|
1097
|
+
addDroidCommandHook(hooksConfig, "Stop", `node ${JSON.stringify(hookPath)} Stop`);
|
|
1098
|
+
writeJson(hooksPath, hooksConfig);
|
|
1099
|
+
console.log(`Updated ${hooksPath}`);
|
|
1100
|
+
console.log("Factory Droid CLI hook installed.");
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
function installDevin() {
|
|
1104
|
+
if (!commandExists("devin")) {
|
|
1105
|
+
console.log("Devin CLI not found. To enable CLIsponsor for Devin, install Devin CLI and rerun: npx clisponsor@latest install");
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
const devinDir = path.join(CONFIG_DIR, "devin");
|
|
1110
|
+
fs.mkdirSync(devinDir, { recursive: true });
|
|
1111
|
+
const hookPath = path.join(devinDir, "clisponsor_devin_hook.mjs");
|
|
1112
|
+
fs.writeFileSync(hookPath, agentHookSource("Devin"), { mode: 0o755 });
|
|
1113
|
+
|
|
1114
|
+
const settingsPath = devinConfigPath();
|
|
1115
|
+
const settings = readEditableJson(settingsPath, {});
|
|
1116
|
+
addDevinCommandHook(settings, "SessionStart", `node ${JSON.stringify(hookPath)} SessionStart`);
|
|
1117
|
+
addDevinCommandHook(settings, "UserPromptSubmit", `node ${JSON.stringify(hookPath)} UserPromptSubmit`);
|
|
1118
|
+
addDevinCommandHook(settings, "Stop", `node ${JSON.stringify(hookPath)} Stop`);
|
|
1119
|
+
writeJson(settingsPath, settings);
|
|
1120
|
+
console.log(`Updated ${settingsPath}`);
|
|
1121
|
+
console.log("Devin CLI hook installed.");
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1018
1124
|
function installTargets() {
|
|
1019
1125
|
return [
|
|
1020
1126
|
{ target: "codex", label: "Codex CLI", command: "codex", install: installCodex },
|
|
@@ -1025,6 +1131,8 @@ function installTargets() {
|
|
|
1025
1131
|
{ target: "pi", label: "Pi Coding Agent", command: "pi", install: installPi },
|
|
1026
1132
|
{ target: "copilot", label: "GitHub Copilot CLI", command: "copilot", install: installCopilot },
|
|
1027
1133
|
{ target: "qwen", label: "Qwen Code", command: "qwen", install: installQwen },
|
|
1134
|
+
{ target: "droid", label: "Factory Droid CLI", command: "droid", install: installDroid },
|
|
1135
|
+
{ target: "devin", label: "Devin CLI", command: "devin", install: installDevin },
|
|
1028
1136
|
];
|
|
1029
1137
|
}
|
|
1030
1138
|
|
|
@@ -1081,7 +1189,7 @@ function installAll() {
|
|
|
1081
1189
|
function install() {
|
|
1082
1190
|
const target = process.argv[3] && !process.argv[3].startsWith("--") ? process.argv[3] : "all";
|
|
1083
1191
|
if (!["all", ...targetNames()].includes(target)) {
|
|
1084
|
-
console.error("Unknown install target. Use: codex, claude, gemini, antigravity, opencode, pi, copilot, qwen, or all.");
|
|
1192
|
+
console.error("Unknown install target. Use: codex, claude, gemini, antigravity, opencode, pi, copilot, qwen, droid, devin, or all.");
|
|
1085
1193
|
process.exit(1);
|
|
1086
1194
|
}
|
|
1087
1195
|
renderInstallHeader(target);
|
|
@@ -1189,10 +1297,42 @@ function uninstallQwen() {
|
|
|
1189
1297
|
console.log("Removed Qwen Code hook script.");
|
|
1190
1298
|
}
|
|
1191
1299
|
|
|
1300
|
+
function uninstallDroid() {
|
|
1301
|
+
const hooksPath = path.join(factoryHome(), "hooks.json");
|
|
1302
|
+
const hooksConfig = readEditableJson(hooksPath, {});
|
|
1303
|
+
if (removeClaudeCommandHooks(hooksConfig)) {
|
|
1304
|
+
writeJson(hooksPath, hooksConfig);
|
|
1305
|
+
console.log(`Removed CLIsponsor hooks from ${hooksPath}`);
|
|
1306
|
+
} else {
|
|
1307
|
+
console.log("No CLIsponsor Factory Droid hooks found.");
|
|
1308
|
+
}
|
|
1309
|
+
fs.rmSync(path.join(CONFIG_DIR, "droid", "clisponsor_droid_hook.mjs"), { force: true });
|
|
1310
|
+
try {
|
|
1311
|
+
fs.rmdirSync(path.join(CONFIG_DIR, "droid"));
|
|
1312
|
+
} catch {}
|
|
1313
|
+
console.log("Removed Factory Droid hook script.");
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
function uninstallDevin() {
|
|
1317
|
+
const settingsPath = devinConfigPath();
|
|
1318
|
+
const settings = readEditableJson(settingsPath, {});
|
|
1319
|
+
if (removeClaudeCommandHooks(settings)) {
|
|
1320
|
+
writeJson(settingsPath, settings);
|
|
1321
|
+
console.log(`Removed CLIsponsor hooks from ${settingsPath}`);
|
|
1322
|
+
} else {
|
|
1323
|
+
console.log("No CLIsponsor Devin hooks found.");
|
|
1324
|
+
}
|
|
1325
|
+
fs.rmSync(path.join(CONFIG_DIR, "devin", "clisponsor_devin_hook.mjs"), { force: true });
|
|
1326
|
+
try {
|
|
1327
|
+
fs.rmdirSync(path.join(CONFIG_DIR, "devin"));
|
|
1328
|
+
} catch {}
|
|
1329
|
+
console.log("Removed Devin hook script.");
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1192
1332
|
function uninstall() {
|
|
1193
1333
|
const target = process.argv[3] && !process.argv[3].startsWith("--") ? process.argv[3] : "all";
|
|
1194
|
-
if (!["all", "codex", "claude", "gemini", "antigravity", "agy", "opencode", "pi", "copilot", "qwen"].includes(target)) {
|
|
1195
|
-
console.error("Unknown uninstall target. Use: codex, claude, gemini, antigravity, opencode, pi, copilot, qwen, or all.");
|
|
1334
|
+
if (!["all", "codex", "claude", "gemini", "antigravity", "agy", "opencode", "pi", "copilot", "qwen", "droid", "devin"].includes(target)) {
|
|
1335
|
+
console.error("Unknown uninstall target. Use: codex, claude, gemini, antigravity, opencode, pi, copilot, qwen, droid, devin, or all.");
|
|
1196
1336
|
process.exit(1);
|
|
1197
1337
|
}
|
|
1198
1338
|
if (target === "all" || target === "codex") uninstallCodex();
|
|
@@ -1203,6 +1343,8 @@ function uninstall() {
|
|
|
1203
1343
|
if (target === "all" || target === "pi") uninstallPi();
|
|
1204
1344
|
if (target === "all" || target === "copilot") uninstallCopilot();
|
|
1205
1345
|
if (target === "all" || target === "qwen") uninstallQwen();
|
|
1346
|
+
if (target === "all" || target === "droid") uninstallDroid();
|
|
1347
|
+
if (target === "all" || target === "devin") uninstallDevin();
|
|
1206
1348
|
if (hasFlag("--config")) {
|
|
1207
1349
|
fs.rmSync(CONFIG_PATH, { force: true });
|
|
1208
1350
|
console.log(`Removed ${CONFIG_PATH}`);
|
|
@@ -1256,17 +1398,19 @@ async function doctor() {
|
|
|
1256
1398
|
email: cfg.email || null,
|
|
1257
1399
|
userId: cfg.userId || null,
|
|
1258
1400
|
deviceCode: cfg.deviceCode || null,
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1401
|
+
installed: {
|
|
1402
|
+
codexPluginStaged: fs.existsSync(path.join(CONFIG_DIR, "codex-marketplace", "plugins", "clisponsor")),
|
|
1403
|
+
claudeSettings: fs.existsSync(path.join(HOME, ".claude", "settings.json")),
|
|
1404
|
+
claudeHookScript: fs.existsSync(path.join(CONFIG_DIR, "claude", "clisponsor_claude_hook.mjs")),
|
|
1405
|
+
geminiHookScript: fs.existsSync(path.join(CONFIG_DIR, "gemini", "clisponsor_gemini_hook.mjs")),
|
|
1406
|
+
antigravityHookScript: fs.existsSync(path.join(CONFIG_DIR, "antigravity", "clisponsor_antigravity_hook.mjs")),
|
|
1407
|
+
opencodePlugin: fs.existsSync(path.join(openCodeConfigDir(), "plugins", "clisponsor_opencode_plugin.js")),
|
|
1408
|
+
piExtension: fs.existsSync(path.join(HOME, ".pi", "agent", "extensions", "clisponsor_pi_extension.ts")),
|
|
1409
|
+
copilotHook: fs.existsSync(path.join(copilotHome(), "hooks", "clisponsor.json")),
|
|
1410
|
+
qwenHookScript: fs.existsSync(path.join(CONFIG_DIR, "qwen", "clisponsor_qwen_hook.mjs")),
|
|
1411
|
+
droidHookScript: fs.existsSync(path.join(CONFIG_DIR, "droid", "clisponsor_droid_hook.mjs")),
|
|
1412
|
+
devinHookScript: fs.existsSync(path.join(CONFIG_DIR, "devin", "clisponsor_devin_hook.mjs")),
|
|
1413
|
+
},
|
|
1270
1414
|
network: {},
|
|
1271
1415
|
};
|
|
1272
1416
|
|
|
@@ -1297,6 +1441,8 @@ async function doctor() {
|
|
|
1297
1441
|
console.log(`Pi extension: ${diagnostics.installed.piExtension ? "yes" : "no"}`);
|
|
1298
1442
|
console.log(`GitHub Copilot CLI hook: ${diagnostics.installed.copilotHook ? "yes" : "no"}`);
|
|
1299
1443
|
console.log(`Qwen Code hook script: ${diagnostics.installed.qwenHookScript ? "yes" : "no"}`);
|
|
1444
|
+
console.log(`Factory Droid hook script: ${diagnostics.installed.droidHookScript ? "yes" : "no"}`);
|
|
1445
|
+
console.log(`Devin hook script: ${diagnostics.installed.devinHookScript ? "yes" : "no"}`);
|
|
1300
1446
|
if (skipNetwork) {
|
|
1301
1447
|
console.log("Network: skipped");
|
|
1302
1448
|
} else {
|
|
@@ -1307,9 +1453,9 @@ async function doctor() {
|
|
|
1307
1453
|
|
|
1308
1454
|
function help() {
|
|
1309
1455
|
console.log(`clisponsor commands:
|
|
1310
|
-
clisponsor install [all|codex|claude|gemini|antigravity|opencode|pi|copilot|qwen]
|
|
1456
|
+
clisponsor install [all|codex|claude|gemini|antigravity|opencode|pi|copilot|qwen|droid|devin]
|
|
1311
1457
|
clisponsor login <email> [--label=<device-label>]
|
|
1312
|
-
clisponsor uninstall [all|codex|claude|gemini|antigravity|opencode|pi|copilot|qwen] [--config]
|
|
1458
|
+
clisponsor uninstall [all|codex|claude|gemini|antigravity|opencode|pi|copilot|qwen|droid|devin] [--config]
|
|
1313
1459
|
clisponsor status
|
|
1314
1460
|
clisponsor doctor [--json] [--skip-network]
|
|
1315
1461
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clisponsor",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "CLIsponsor installer for Codex, Claude Code, Gemini, Antigravity, OpenCode, Pi, GitHub Copilot CLI,
|
|
3
|
+
"version": "1.0.20",
|
|
4
|
+
"description": "CLIsponsor installer for Codex, Claude Code, Gemini, Antigravity, OpenCode, Pi, GitHub Copilot CLI, Qwen Code, Factory Droid, and Devin sponsored CLI placements.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20"
|