@mutagent/cli 0.1.197 → 0.1.199
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/dist/bin/cli.js +547 -348
- package/dist/bin/cli.js.map +12 -10
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -728,8 +728,8 @@ var init_sdk_client = __esm(() => {
|
|
|
728
728
|
// src/bin/cli.ts
|
|
729
729
|
import { Command as Command12 } from "commander";
|
|
730
730
|
import chalk18 from "chalk";
|
|
731
|
-
import { readFileSync as
|
|
732
|
-
import { join as
|
|
731
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
732
|
+
import { join as join12, dirname as dirname3 } from "path";
|
|
733
733
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
734
734
|
|
|
735
735
|
// src/commands/auth.ts
|
|
@@ -737,8 +737,8 @@ init_config();
|
|
|
737
737
|
init_sdk_client();
|
|
738
738
|
import { Command } from "commander";
|
|
739
739
|
import chalk4 from "chalk";
|
|
740
|
-
import { existsSync as
|
|
741
|
-
import { join as
|
|
740
|
+
import { existsSync as existsSync5 } from "fs";
|
|
741
|
+
import { join as join6 } from "path";
|
|
742
742
|
|
|
743
743
|
// src/lib/output.ts
|
|
744
744
|
import chalk from "chalk";
|
|
@@ -937,54 +937,499 @@ init_errors();
|
|
|
937
937
|
|
|
938
938
|
// src/commands/onboarding.ts
|
|
939
939
|
import chalk2 from "chalk";
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
940
|
+
|
|
941
|
+
// src/lib/rc-config.ts
|
|
942
|
+
init_config();
|
|
943
|
+
import { join as join4 } from "path";
|
|
944
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
945
|
+
|
|
946
|
+
// src/lib/framework-detection.ts
|
|
947
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
948
|
+
import { execSync } from "child_process";
|
|
949
|
+
import { join as join3 } from "path";
|
|
950
|
+
var FRAMEWORK_DETECTION_MAP = {
|
|
951
|
+
"@mastra/core": {
|
|
952
|
+
name: "mastra",
|
|
953
|
+
displayName: "Mastra",
|
|
954
|
+
npmPackage: "@mastra/core"
|
|
955
|
+
},
|
|
956
|
+
"@langchain/langgraph": {
|
|
957
|
+
name: "langgraph",
|
|
958
|
+
displayName: "LangGraph",
|
|
959
|
+
npmPackage: "@langchain/langgraph",
|
|
960
|
+
mutagentPackage: "@mutagent/langgraph"
|
|
961
|
+
},
|
|
962
|
+
langchain: {
|
|
963
|
+
name: "langchain",
|
|
964
|
+
displayName: "LangChain",
|
|
965
|
+
npmPackage: "langchain",
|
|
966
|
+
mutagentPackage: "@mutagent/langchain"
|
|
967
|
+
},
|
|
968
|
+
"@langchain/core": {
|
|
969
|
+
name: "langchain",
|
|
970
|
+
displayName: "LangChain",
|
|
971
|
+
npmPackage: "@langchain/core",
|
|
972
|
+
mutagentPackage: "@mutagent/langchain"
|
|
973
|
+
},
|
|
974
|
+
"@ai-sdk/core": {
|
|
975
|
+
name: "vercel-ai",
|
|
976
|
+
displayName: "Vercel AI SDK",
|
|
977
|
+
npmPackage: "@ai-sdk/core",
|
|
978
|
+
mutagentPackage: "@mutagent/vercel-ai"
|
|
979
|
+
},
|
|
980
|
+
ai: {
|
|
981
|
+
name: "vercel-ai",
|
|
982
|
+
displayName: "Vercel AI SDK",
|
|
983
|
+
npmPackage: "ai",
|
|
984
|
+
mutagentPackage: "@mutagent/vercel-ai"
|
|
985
|
+
},
|
|
986
|
+
"@google/genai": {
|
|
987
|
+
name: "generic",
|
|
988
|
+
displayName: "Google GenAI",
|
|
989
|
+
npmPackage: "@google/genai"
|
|
990
|
+
},
|
|
991
|
+
openai: {
|
|
992
|
+
name: "openai",
|
|
993
|
+
displayName: "OpenAI SDK",
|
|
994
|
+
npmPackage: "openai",
|
|
995
|
+
mutagentPackage: "@mutagent/openai"
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
function detectPackageManager(cwd = process.cwd()) {
|
|
999
|
+
if (existsSync3(join3(cwd, "bun.lockb")) || existsSync3(join3(cwd, "bun.lock"))) {
|
|
1000
|
+
return "bun";
|
|
1001
|
+
}
|
|
1002
|
+
if (existsSync3(join3(cwd, "pnpm-lock.yaml"))) {
|
|
1003
|
+
return "pnpm";
|
|
1004
|
+
}
|
|
1005
|
+
if (existsSync3(join3(cwd, "yarn.lock"))) {
|
|
1006
|
+
return "yarn";
|
|
1007
|
+
}
|
|
1008
|
+
if (existsSync3(join3(cwd, "package-lock.json"))) {
|
|
1009
|
+
return "npm";
|
|
1010
|
+
}
|
|
1011
|
+
try {
|
|
1012
|
+
execSync("bun --version", { stdio: "ignore" });
|
|
1013
|
+
return "bun";
|
|
1014
|
+
} catch {
|
|
1015
|
+
return "npm";
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function getInstallCommand(pm, packages) {
|
|
1019
|
+
const pkgList = packages.join(" ");
|
|
1020
|
+
const commands = {
|
|
1021
|
+
bun: `bun add ${pkgList}`,
|
|
1022
|
+
npm: `npm install ${pkgList}`,
|
|
1023
|
+
yarn: `yarn add ${pkgList}`,
|
|
1024
|
+
pnpm: `pnpm add ${pkgList}`
|
|
1025
|
+
};
|
|
1026
|
+
return commands[pm];
|
|
1027
|
+
}
|
|
1028
|
+
function detectFrameworkFromPackageJson(cwd = process.cwd()) {
|
|
1029
|
+
const pkgPath = join3(cwd, "package.json");
|
|
1030
|
+
if (!existsSync3(pkgPath)) {
|
|
1031
|
+
return null;
|
|
1032
|
+
}
|
|
1033
|
+
let pkg;
|
|
1034
|
+
try {
|
|
1035
|
+
pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
1036
|
+
} catch {
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
1039
|
+
const allDeps = {
|
|
1040
|
+
...pkg.dependencies,
|
|
1041
|
+
...pkg.devDependencies
|
|
1042
|
+
};
|
|
1043
|
+
for (const [depName, framework] of Object.entries(FRAMEWORK_DETECTION_MAP)) {
|
|
1044
|
+
if (depName in allDeps) {
|
|
1045
|
+
return framework;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
return null;
|
|
1049
|
+
}
|
|
1050
|
+
function hasRcConfig(cwd = process.cwd()) {
|
|
1051
|
+
return existsSync3(join3(cwd, ".mutagentrc.json"));
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// src/lib/rc-config.ts
|
|
1055
|
+
function writeRcConfig(config, cwd = process.cwd()) {
|
|
1056
|
+
const rcPath = join4(cwd, ".mutagentrc.json");
|
|
1057
|
+
writeFileSync2(rcPath, JSON.stringify(config, null, 2) + `
|
|
1058
|
+
`);
|
|
1059
|
+
}
|
|
1060
|
+
function scaffoldRcConfig(cwd = process.cwd(), deps = {}) {
|
|
1061
|
+
const load = deps.loadConfig ?? loadConfig;
|
|
1062
|
+
const hasRc = deps.hasRcConfig ?? hasRcConfig;
|
|
1063
|
+
const write = deps.writeRcConfig ?? writeRcConfig;
|
|
1064
|
+
const cfg = load();
|
|
1065
|
+
const rcConfig = {
|
|
1066
|
+
endpoint: cfg.endpoint ?? "https://api.mutagent.io",
|
|
1067
|
+
...cfg.defaultWorkspace ? { defaultWorkspace: cfg.defaultWorkspace } : {},
|
|
1068
|
+
...cfg.defaultOrganization ? { defaultOrganization: cfg.defaultOrganization } : {}
|
|
1069
|
+
};
|
|
1070
|
+
if (hasRc(cwd)) {
|
|
1071
|
+
return { created: false, alreadyPresent: true, config: rcConfig };
|
|
1072
|
+
}
|
|
1073
|
+
write(rcConfig, cwd);
|
|
1074
|
+
return { created: true, alreadyPresent: false, config: rcConfig };
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// src/lib/installer.ts
|
|
1078
|
+
init_errors();
|
|
1079
|
+
init_config();
|
|
1080
|
+
import { spawn as spawn2 } from "child_process";
|
|
1081
|
+
|
|
1082
|
+
// src/lib/installer-helix.ts
|
|
1083
|
+
init_errors();
|
|
1084
|
+
init_config();
|
|
1085
|
+
import { spawn } from "child_process";
|
|
1086
|
+
import { createHash } from "crypto";
|
|
1087
|
+
import { homedir as homedir2 } from "os";
|
|
1088
|
+
import { join as join5 } from "path";
|
|
1089
|
+
import {
|
|
1090
|
+
existsSync as existsSync4,
|
|
1091
|
+
mkdirSync as mkdirSync2,
|
|
1092
|
+
readFileSync as readFileSync4,
|
|
1093
|
+
renameSync,
|
|
1094
|
+
rmSync,
|
|
1095
|
+
writeFileSync as writeFileSync3
|
|
1096
|
+
} from "fs";
|
|
1097
|
+
async function installHelix(opts, deps = {}) {
|
|
1098
|
+
const auth = (deps.resolveAuth ?? defaultResolveAuth)();
|
|
1099
|
+
const fetchImpl = deps.fetchImpl ?? globalThis.fetch;
|
|
1100
|
+
const descriptor = await fetchDescriptor(fetchImpl, auth, opts.version);
|
|
1101
|
+
const baseDir = deps.homeDir ?? join5(homedir2(), ".mutagent", "helix");
|
|
1102
|
+
const versionDir = join5(baseDir, descriptor.version);
|
|
1103
|
+
mkdirSync2(versionDir, { recursive: true });
|
|
1104
|
+
const tgzPath = join5(versionDir, `helix-plugin-${descriptor.version}.tgz`);
|
|
1105
|
+
const tmpPath = `${tgzPath}.${String(process.pid)}.${String(Date.now())}.part`;
|
|
1106
|
+
const download = deps.download ?? defaultDownload;
|
|
1107
|
+
await download(descriptor.url, tmpPath);
|
|
1108
|
+
const sha256 = deps.sha256 ?? defaultSha256;
|
|
1109
|
+
const actual = (await sha256(tmpPath)).toLowerCase();
|
|
1110
|
+
const expected = descriptor.sha256.toLowerCase();
|
|
1111
|
+
if (actual !== expected) {
|
|
1112
|
+
safeRm(tmpPath);
|
|
1113
|
+
throw new MutagentError("INTEGRITY_ERROR", `Downloaded helix plugin failed sha256 verification (expected ${expected.slice(0, 12)}…, got ${actual.slice(0, 12)}…).`, "The download may be corrupt or tampered with. Retry: mutagent install helix");
|
|
1114
|
+
}
|
|
1115
|
+
renameSync(tmpPath, tgzPath);
|
|
1116
|
+
const extract = deps.extract ?? defaultExtract;
|
|
1117
|
+
await extract(tgzPath, versionDir);
|
|
1118
|
+
const locateInitBin = deps.locateInitBin ?? defaultLocateInitBin;
|
|
1119
|
+
const binPath = await locateInitBin(versionDir);
|
|
1120
|
+
const initArgs = ["init", "--harness", opts.harness];
|
|
1121
|
+
if (opts.global)
|
|
1122
|
+
initArgs.push("--global");
|
|
1123
|
+
const runInit = deps.runInit ?? defaultRunInit;
|
|
1124
|
+
const code = await runInit(binPath, initArgs, process.cwd());
|
|
1125
|
+
if (code !== 0) {
|
|
1126
|
+
throw new MutagentError("INSTALL_FAILED", `helix plugin init exited with code ${String(code)}.`, "Re-run: mutagent install helix — or run the plugin init manually and report the error.");
|
|
1127
|
+
}
|
|
1128
|
+
await postTelemetry(fetchImpl, auth, {
|
|
1129
|
+
pkg: "helix",
|
|
1130
|
+
version: descriptor.version,
|
|
1131
|
+
harness: opts.harness,
|
|
1132
|
+
cliVersion: deps.cliVersion ?? readCliVersion()
|
|
1133
|
+
});
|
|
1134
|
+
return { version: descriptor.version };
|
|
1135
|
+
}
|
|
1136
|
+
async function fetchDescriptor(fetchImpl, auth, version) {
|
|
1137
|
+
if (!auth.apiKey) {
|
|
1138
|
+
throw new MutagentError("AUTH_REQUIRED", "Authentication required to install helix.", "Run: mutagent login");
|
|
1139
|
+
}
|
|
1140
|
+
const url = `${auth.apiBase}/api/helix/plugin/download?version=${encodeURIComponent(version)}`;
|
|
1141
|
+
let res;
|
|
1142
|
+
try {
|
|
1143
|
+
res = await fetchImpl(url, {
|
|
1144
|
+
method: "GET",
|
|
1145
|
+
headers: { "x-api-key": auth.apiKey, ...auth.headers }
|
|
1146
|
+
});
|
|
1147
|
+
} catch {
|
|
1148
|
+
throw new MutagentError("SERVER_UNAVAILABLE", "Could not reach the MutagenT plugin broker.", "Check your network connection or verify the endpoint with: mutagent config show");
|
|
1149
|
+
}
|
|
1150
|
+
if (res.status === 401) {
|
|
1151
|
+
throw new MutagentError("AUTH_REQUIRED", "The plugin broker rejected your credentials.", "Re-authenticate: mutagent login");
|
|
1152
|
+
}
|
|
1153
|
+
if (!res.ok) {
|
|
1154
|
+
const detail = await readErrorMessage(res);
|
|
1155
|
+
throw new MutagentError("INSTALL_FAILED", `Plugin broker returned ${String(res.status)}.${detail ? ` ${detail}` : ""}`, "Verify the requested version exists, then retry: mutagent install helix");
|
|
1156
|
+
}
|
|
1157
|
+
const raw = await res.json();
|
|
1158
|
+
if (!isBrokerResponse(raw)) {
|
|
1159
|
+
throw new MutagentError("INSTALL_FAILED", "Plugin broker returned a malformed response (missing version/sha256/url).", "Retry: mutagent install helix — if it persists, report it.");
|
|
1160
|
+
}
|
|
1161
|
+
return raw;
|
|
1162
|
+
}
|
|
1163
|
+
async function postTelemetry(fetchImpl, auth, event) {
|
|
1164
|
+
if (!auth.apiKey)
|
|
1165
|
+
return;
|
|
1166
|
+
try {
|
|
1167
|
+
await fetchImpl(`${auth.apiBase}/api/helix/installs`, {
|
|
1168
|
+
method: "POST",
|
|
1169
|
+
headers: {
|
|
1170
|
+
"Content-Type": "application/json",
|
|
1171
|
+
"x-api-key": auth.apiKey,
|
|
1172
|
+
...auth.headers
|
|
957
1173
|
},
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1174
|
+
body: JSON.stringify(event)
|
|
1175
|
+
});
|
|
1176
|
+
} catch {}
|
|
1177
|
+
}
|
|
1178
|
+
function defaultResolveAuth() {
|
|
1179
|
+
const apiKey = getApiKey();
|
|
1180
|
+
const config = loadConfig();
|
|
1181
|
+
const apiBase = config.endpoint ?? "https://api.mutagent.io";
|
|
1182
|
+
const headers = {};
|
|
1183
|
+
if (config.defaultWorkspace)
|
|
1184
|
+
headers["x-workspace-id"] = config.defaultWorkspace;
|
|
1185
|
+
if (config.defaultOrganization)
|
|
1186
|
+
headers["x-organization-id"] = config.defaultOrganization;
|
|
1187
|
+
return { apiBase, apiKey, headers };
|
|
1188
|
+
}
|
|
1189
|
+
async function defaultDownload(url, destPath) {
|
|
1190
|
+
let res;
|
|
1191
|
+
try {
|
|
1192
|
+
res = await globalThis.fetch(url);
|
|
1193
|
+
} catch {
|
|
1194
|
+
throw new MutagentError("SERVER_UNAVAILABLE", "Failed to download the helix plugin from storage.", "Check your network connection and retry: mutagent install helix");
|
|
1195
|
+
}
|
|
1196
|
+
if (!res.ok) {
|
|
1197
|
+
throw new MutagentError("INSTALL_FAILED", `Plugin download failed with status ${String(res.status)}.`, "The signed URL may have expired — retry: mutagent install helix");
|
|
1198
|
+
}
|
|
1199
|
+
const bytes = Buffer.from(await res.arrayBuffer());
|
|
1200
|
+
writeFileSync3(destPath, bytes);
|
|
1201
|
+
}
|
|
1202
|
+
async function defaultSha256(filePath) {
|
|
1203
|
+
return Promise.resolve(createHash("sha256").update(readFileSync4(filePath)).digest("hex"));
|
|
1204
|
+
}
|
|
1205
|
+
function defaultExtract(tgzPath, destDir) {
|
|
1206
|
+
return new Promise((resolve, reject) => {
|
|
1207
|
+
const child = spawn("tar", ["-xzf", tgzPath, "-C", destDir], {
|
|
1208
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
1209
|
+
});
|
|
1210
|
+
let stderr = "";
|
|
1211
|
+
child.stderr.on("data", (chunk) => {
|
|
1212
|
+
stderr += chunk.toString("utf-8");
|
|
1213
|
+
});
|
|
1214
|
+
child.on("error", (err) => {
|
|
1215
|
+
reject(new MutagentError("INSTALL_FAILED", `Failed to extract the helix plugin: ${err.message}`, 'Ensure "tar" is installed and available on your PATH.'));
|
|
1216
|
+
});
|
|
1217
|
+
child.on("close", (code) => {
|
|
1218
|
+
if (code === 0) {
|
|
1219
|
+
resolve();
|
|
1220
|
+
} else {
|
|
1221
|
+
reject(new MutagentError("INSTALL_FAILED", `Extracting the helix plugin failed (tar exit ${String(code ?? 1)}).${stderr ? ` ${stderr.trim().slice(0, 200)}` : ""}`, "The downloaded archive may be corrupt — retry: mutagent install helix"));
|
|
961
1222
|
}
|
|
962
|
-
|
|
1223
|
+
});
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
function defaultLocateInitBin(extractedDir) {
|
|
1227
|
+
const pkgDir = existsSync4(join5(extractedDir, "package", "package.json")) ? join5(extractedDir, "package") : extractedDir;
|
|
1228
|
+
const pkgJsonPath = join5(pkgDir, "package.json");
|
|
1229
|
+
if (!existsSync4(pkgJsonPath)) {
|
|
1230
|
+
return Promise.reject(new MutagentError("INSTALL_FAILED", "Could not find package.json in the extracted helix plugin.", "The archive layout is unexpected — retry or report: mutagent install helix"));
|
|
1231
|
+
}
|
|
1232
|
+
const raw = JSON.parse(readFileSync4(pkgJsonPath, "utf-8"));
|
|
1233
|
+
const binRel = resolveBinField(raw);
|
|
1234
|
+
if (!binRel) {
|
|
1235
|
+
return Promise.reject(new MutagentError("INSTALL_FAILED", "The helix plugin package.json declares no runnable bin.", "The plugin package is malformed — report: mutagent install helix"));
|
|
1236
|
+
}
|
|
1237
|
+
const binPath = join5(pkgDir, binRel);
|
|
1238
|
+
if (!existsSync4(binPath)) {
|
|
1239
|
+
return Promise.reject(new MutagentError("INSTALL_FAILED", `The helix plugin bin was not found at ${binRel}.`, "The plugin package is incomplete — report: mutagent install helix"));
|
|
1240
|
+
}
|
|
1241
|
+
return Promise.resolve(binPath);
|
|
1242
|
+
}
|
|
1243
|
+
function defaultRunInit(binPath, args, cwd) {
|
|
1244
|
+
return new Promise((resolve, reject) => {
|
|
1245
|
+
const child = spawn("node", [binPath, ...args], { cwd, stdio: "inherit" });
|
|
1246
|
+
child.on("error", (err) => {
|
|
1247
|
+
reject(new MutagentError("INSTALL_FAILED", `Failed to run the helix plugin init: ${err.message}`, 'Ensure "node" is installed and available on your PATH.'));
|
|
1248
|
+
});
|
|
1249
|
+
child.on("close", (code) => {
|
|
1250
|
+
resolve(code ?? 1);
|
|
1251
|
+
});
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
function resolveBinField(pkg) {
|
|
1255
|
+
if (!pkg || typeof pkg !== "object")
|
|
1256
|
+
return;
|
|
1257
|
+
const bin = pkg.bin;
|
|
1258
|
+
if (typeof bin === "string")
|
|
1259
|
+
return bin;
|
|
1260
|
+
if (bin && typeof bin === "object") {
|
|
1261
|
+
const entries = bin;
|
|
1262
|
+
const preferred = entries["mutagent-helix"];
|
|
1263
|
+
if (typeof preferred === "string")
|
|
1264
|
+
return preferred;
|
|
1265
|
+
for (const value of Object.values(entries)) {
|
|
1266
|
+
if (typeof value === "string")
|
|
1267
|
+
return value;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
function isBrokerResponse(value) {
|
|
1273
|
+
if (!value || typeof value !== "object")
|
|
1274
|
+
return false;
|
|
1275
|
+
const v = value;
|
|
1276
|
+
return typeof v.version === "string" && typeof v.sha256 === "string" && typeof v.url === "string";
|
|
1277
|
+
}
|
|
1278
|
+
async function readErrorMessage(res) {
|
|
1279
|
+
try {
|
|
1280
|
+
const body = await res.json();
|
|
1281
|
+
if (body && typeof body === "object") {
|
|
1282
|
+
const b = body;
|
|
1283
|
+
if (typeof b.message === "string")
|
|
1284
|
+
return b.message;
|
|
1285
|
+
if (typeof b.error === "string")
|
|
1286
|
+
return b.error;
|
|
1287
|
+
}
|
|
1288
|
+
} catch {}
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
function readCliVersion() {
|
|
1292
|
+
if (process.env.CLI_VERSION)
|
|
1293
|
+
return process.env.CLI_VERSION;
|
|
1294
|
+
return "unknown";
|
|
1295
|
+
}
|
|
1296
|
+
function safeRm(path) {
|
|
1297
|
+
try {
|
|
1298
|
+
rmSync(path, { force: true });
|
|
1299
|
+
} catch {}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// src/lib/installer.ts
|
|
1303
|
+
var VALID_PACKAGES = ["helix", "diagnostics", "evaluator"];
|
|
1304
|
+
var VALID_HARNESSES = ["claude-code", "codex", "omp"];
|
|
1305
|
+
var VERSION_MATRIX = {
|
|
1306
|
+
helix: "latest",
|
|
1307
|
+
diagnostics: "latest",
|
|
1308
|
+
evaluator: "latest"
|
|
1309
|
+
};
|
|
1310
|
+
var NPM_PACKAGES = {
|
|
1311
|
+
diagnostics: "@mutagent/diagnostics",
|
|
1312
|
+
evaluator: "@mutagent/evaluator"
|
|
1313
|
+
};
|
|
1314
|
+
var defaultRunner = (cmd, args) => new Promise((resolve, reject) => {
|
|
1315
|
+
const child = spawn2(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1316
|
+
let stdout = "";
|
|
1317
|
+
let stderr = "";
|
|
1318
|
+
child.stdout.on("data", (chunk) => {
|
|
1319
|
+
stdout += chunk.toString("utf-8");
|
|
1320
|
+
});
|
|
1321
|
+
child.stderr.on("data", (chunk) => {
|
|
1322
|
+
stderr += chunk.toString("utf-8");
|
|
1323
|
+
});
|
|
1324
|
+
child.on("error", (err) => {
|
|
1325
|
+
reject(new MutagentError("INSTALL_FAILED", `Failed to run ${cmd}: ${err.message}`, `Ensure "${cmd}" is installed and available on your PATH.`));
|
|
1326
|
+
});
|
|
1327
|
+
child.on("close", (code) => {
|
|
1328
|
+
resolve({ code: code ?? 1, stdout, stderr });
|
|
1329
|
+
});
|
|
1330
|
+
});
|
|
1331
|
+
function isValidPackage(pkg) {
|
|
1332
|
+
return VALID_PACKAGES.includes(pkg);
|
|
1333
|
+
}
|
|
1334
|
+
function isValidHarness(harness) {
|
|
1335
|
+
return VALID_HARNESSES.includes(harness);
|
|
1336
|
+
}
|
|
1337
|
+
async function installPackage(pkg, opts, deps = {}) {
|
|
1338
|
+
const isAuthed = deps.isAuthed ?? hasCredentials;
|
|
1339
|
+
if (!isAuthed()) {
|
|
1340
|
+
throw new MutagentError("AUTH_REQUIRED", `Authentication required to install ${pkg}.`, "Run: mutagent login");
|
|
1341
|
+
}
|
|
1342
|
+
if (!isValidPackage(pkg)) {
|
|
1343
|
+
throw new MutagentError("INVALID_ARGUMENTS", `Unknown package "${pkg}". Valid: ${VALID_PACKAGES.join(", ")}`, "Run: mutagent install --help");
|
|
1344
|
+
}
|
|
1345
|
+
if (!isValidHarness(opts.harness)) {
|
|
1346
|
+
throw new MutagentError("INVALID_ARGUMENTS", `Unknown harness "${opts.harness}". Valid: ${VALID_HARNESSES.join(", ")}`, "Run: mutagent install --help");
|
|
1347
|
+
}
|
|
1348
|
+
const version = opts.version ?? VERSION_MATRIX[pkg];
|
|
1349
|
+
if (pkg === "helix") {
|
|
1350
|
+
const { version: resolved } = await installHelix({ harness: opts.harness, global: opts.global, version }, deps.helix ?? {});
|
|
1351
|
+
return {
|
|
1352
|
+
package: pkg,
|
|
1353
|
+
version: resolved,
|
|
1354
|
+
harness: opts.harness,
|
|
1355
|
+
global: opts.global
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
const npmPackage = NPM_PACKAGES[pkg];
|
|
1359
|
+
const args = ["install", "-g", `${npmPackage}@${version}`];
|
|
1360
|
+
const runner = deps.runner ?? defaultRunner;
|
|
1361
|
+
const result = await runner("npm", args);
|
|
1362
|
+
if (result.code !== 0) {
|
|
1363
|
+
const detail = result.stderr.trim();
|
|
1364
|
+
throw new MutagentError("INSTALL_FAILED", `npm failed to install ${npmPackage}@${version} (exit ${String(result.code)}).${detail ? ` ${detail.slice(0, 200)}` : ""}`, "Verify the package and version exist and that you have permission for a global npm install.");
|
|
1365
|
+
}
|
|
1366
|
+
return {
|
|
1367
|
+
package: pkg,
|
|
1368
|
+
version,
|
|
1369
|
+
harness: opts.harness,
|
|
1370
|
+
global: opts.global,
|
|
1371
|
+
command: `npm ${args.join(" ")}`
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
// src/commands/onboarding.ts
|
|
1376
|
+
init_errors();
|
|
1377
|
+
var ONBOARDING_CHOICES = [
|
|
1378
|
+
{ name: "1) Install Helix — set up the ADL lifecycle conductor here", value: "helix" },
|
|
1379
|
+
{ name: "2) Exit — explore the CLI on your own", value: "exit" }
|
|
1380
|
+
];
|
|
1381
|
+
async function defaultSelectAction(choices) {
|
|
1382
|
+
const inquirer = (await import("inquirer")).default;
|
|
1383
|
+
const { action } = await inquirer.prompt([{
|
|
1384
|
+
type: "list",
|
|
1385
|
+
name: "action",
|
|
1386
|
+
message: "What would you like to do next?",
|
|
1387
|
+
choices,
|
|
1388
|
+
default: "helix"
|
|
963
1389
|
}]);
|
|
1390
|
+
return action;
|
|
1391
|
+
}
|
|
1392
|
+
async function runPostOnboarding(deps = {}) {
|
|
1393
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
1394
|
+
const scaffold = deps.scaffoldRcConfig ?? scaffoldRcConfig;
|
|
1395
|
+
const select = deps.selectAction ?? defaultSelectAction;
|
|
1396
|
+
const install = deps.installPackage ?? installPackage;
|
|
964
1397
|
console.log("");
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
console.log("
|
|
970
|
-
|
|
971
|
-
console.log(`
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
console.log(chalk2.
|
|
979
|
-
console.log("");
|
|
980
|
-
console.log(` ${chalk2.green("mutagent install diagnostics")} ${chalk2.dim("Root-cause analysis from your traces")}`);
|
|
981
|
-
console.log(` ${chalk2.green("mutagent install evaluator")} ${chalk2.dim("Build trustworthy eval suites")}`);
|
|
982
|
-
console.log(` ${chalk2.green("mutagent install helix")} ${chalk2.dim("The ADL lifecycle conductor")}`);
|
|
983
|
-
console.log("");
|
|
984
|
-
console.log(chalk2.dim(" All installs are login-gated. Run `mutagent install --help` for flags."));
|
|
1398
|
+
console.log(chalk2.bold.cyan(" You are authenticated."));
|
|
1399
|
+
console.log("");
|
|
1400
|
+
const rc = scaffold(cwd);
|
|
1401
|
+
if (rc.alreadyPresent) {
|
|
1402
|
+
console.log(` ${chalk2.green("✓")} .mutagentrc.json already present`);
|
|
1403
|
+
} else {
|
|
1404
|
+
console.log(` ${chalk2.green("✓")} Created .mutagentrc.json`);
|
|
1405
|
+
}
|
|
1406
|
+
console.log("");
|
|
1407
|
+
const action = await select(ONBOARDING_CHOICES);
|
|
1408
|
+
console.log("");
|
|
1409
|
+
if (action === "helix") {
|
|
1410
|
+
console.log(chalk2.bold(" Installing Helix…"));
|
|
1411
|
+
console.log(chalk2.dim(" Downloading + verifying the plugin, then writing .claude/ + .codex/"));
|
|
985
1412
|
console.log("");
|
|
1413
|
+
try {
|
|
1414
|
+
await install("helix", { harness: "claude-code", global: true });
|
|
1415
|
+
console.log("");
|
|
1416
|
+
console.log(` ${chalk2.green("✓")} Helix ready — run ${chalk2.cyan("*help")} inside your agent`);
|
|
1417
|
+
console.log("");
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
console.log("");
|
|
1420
|
+
if (error instanceof MutagentError) {
|
|
1421
|
+
console.error(` ${chalk2.red("✗")} Helix install failed: ${error.message}`);
|
|
1422
|
+
if (error.suggestion)
|
|
1423
|
+
console.error(` ${chalk2.yellow("→")} ${error.suggestion}`);
|
|
1424
|
+
} else {
|
|
1425
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1426
|
+
console.error(` ${chalk2.red("✗")} Helix install failed: ${message}`);
|
|
1427
|
+
}
|
|
1428
|
+
console.error("");
|
|
1429
|
+
process.exitCode = 1;
|
|
1430
|
+
}
|
|
986
1431
|
} else {
|
|
987
|
-
console.log(chalk2.dim(
|
|
1432
|
+
console.log(chalk2.dim(` Run ${chalk2.cyan("mutagent --help")} to explore the CLI.`));
|
|
988
1433
|
console.log(chalk2.dim(' Hit a snag? Send feedback: mutagent feedback send "what happened"'));
|
|
989
1434
|
console.log("");
|
|
990
1435
|
}
|
|
@@ -1418,7 +1863,7 @@ Examples:
|
|
|
1418
1863
|
}
|
|
1419
1864
|
const isValid = await validateApiKey(apiKey, endpoint);
|
|
1420
1865
|
const cwd = process.cwd();
|
|
1421
|
-
const hasOnboarding =
|
|
1866
|
+
const hasOnboarding = existsSync5(join6(cwd, ".mutagentrc.json"));
|
|
1422
1867
|
if (isJson) {
|
|
1423
1868
|
const statusResult = {
|
|
1424
1869
|
authenticated: isValid,
|
|
@@ -2322,125 +2767,8 @@ init_config();
|
|
|
2322
2767
|
import { Command as Command6 } from "commander";
|
|
2323
2768
|
import inquirer2 from "inquirer";
|
|
2324
2769
|
import chalk12 from "chalk";
|
|
2325
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
2326
2770
|
import { execSync as execSync2 } from "child_process";
|
|
2327
|
-
import { join as join5 } from "path";
|
|
2328
2771
|
init_errors();
|
|
2329
|
-
|
|
2330
|
-
// src/lib/framework-detection.ts
|
|
2331
|
-
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
2332
|
-
import { execSync } from "child_process";
|
|
2333
|
-
import { join as join4 } from "path";
|
|
2334
|
-
var FRAMEWORK_DETECTION_MAP = {
|
|
2335
|
-
"@mastra/core": {
|
|
2336
|
-
name: "mastra",
|
|
2337
|
-
displayName: "Mastra",
|
|
2338
|
-
npmPackage: "@mastra/core"
|
|
2339
|
-
},
|
|
2340
|
-
"@langchain/langgraph": {
|
|
2341
|
-
name: "langgraph",
|
|
2342
|
-
displayName: "LangGraph",
|
|
2343
|
-
npmPackage: "@langchain/langgraph",
|
|
2344
|
-
mutagentPackage: "@mutagent/langgraph"
|
|
2345
|
-
},
|
|
2346
|
-
langchain: {
|
|
2347
|
-
name: "langchain",
|
|
2348
|
-
displayName: "LangChain",
|
|
2349
|
-
npmPackage: "langchain",
|
|
2350
|
-
mutagentPackage: "@mutagent/langchain"
|
|
2351
|
-
},
|
|
2352
|
-
"@langchain/core": {
|
|
2353
|
-
name: "langchain",
|
|
2354
|
-
displayName: "LangChain",
|
|
2355
|
-
npmPackage: "@langchain/core",
|
|
2356
|
-
mutagentPackage: "@mutagent/langchain"
|
|
2357
|
-
},
|
|
2358
|
-
"@ai-sdk/core": {
|
|
2359
|
-
name: "vercel-ai",
|
|
2360
|
-
displayName: "Vercel AI SDK",
|
|
2361
|
-
npmPackage: "@ai-sdk/core",
|
|
2362
|
-
mutagentPackage: "@mutagent/vercel-ai"
|
|
2363
|
-
},
|
|
2364
|
-
ai: {
|
|
2365
|
-
name: "vercel-ai",
|
|
2366
|
-
displayName: "Vercel AI SDK",
|
|
2367
|
-
npmPackage: "ai",
|
|
2368
|
-
mutagentPackage: "@mutagent/vercel-ai"
|
|
2369
|
-
},
|
|
2370
|
-
"@google/genai": {
|
|
2371
|
-
name: "generic",
|
|
2372
|
-
displayName: "Google GenAI",
|
|
2373
|
-
npmPackage: "@google/genai"
|
|
2374
|
-
},
|
|
2375
|
-
openai: {
|
|
2376
|
-
name: "openai",
|
|
2377
|
-
displayName: "OpenAI SDK",
|
|
2378
|
-
npmPackage: "openai",
|
|
2379
|
-
mutagentPackage: "@mutagent/openai"
|
|
2380
|
-
}
|
|
2381
|
-
};
|
|
2382
|
-
function detectPackageManager(cwd = process.cwd()) {
|
|
2383
|
-
if (existsSync4(join4(cwd, "bun.lockb")) || existsSync4(join4(cwd, "bun.lock"))) {
|
|
2384
|
-
return "bun";
|
|
2385
|
-
}
|
|
2386
|
-
if (existsSync4(join4(cwd, "pnpm-lock.yaml"))) {
|
|
2387
|
-
return "pnpm";
|
|
2388
|
-
}
|
|
2389
|
-
if (existsSync4(join4(cwd, "yarn.lock"))) {
|
|
2390
|
-
return "yarn";
|
|
2391
|
-
}
|
|
2392
|
-
if (existsSync4(join4(cwd, "package-lock.json"))) {
|
|
2393
|
-
return "npm";
|
|
2394
|
-
}
|
|
2395
|
-
try {
|
|
2396
|
-
execSync("bun --version", { stdio: "ignore" });
|
|
2397
|
-
return "bun";
|
|
2398
|
-
} catch {
|
|
2399
|
-
return "npm";
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
function getInstallCommand(pm, packages) {
|
|
2403
|
-
const pkgList = packages.join(" ");
|
|
2404
|
-
const commands = {
|
|
2405
|
-
bun: `bun add ${pkgList}`,
|
|
2406
|
-
npm: `npm install ${pkgList}`,
|
|
2407
|
-
yarn: `yarn add ${pkgList}`,
|
|
2408
|
-
pnpm: `pnpm add ${pkgList}`
|
|
2409
|
-
};
|
|
2410
|
-
return commands[pm];
|
|
2411
|
-
}
|
|
2412
|
-
function detectFrameworkFromPackageJson(cwd = process.cwd()) {
|
|
2413
|
-
const pkgPath = join4(cwd, "package.json");
|
|
2414
|
-
if (!existsSync4(pkgPath)) {
|
|
2415
|
-
return null;
|
|
2416
|
-
}
|
|
2417
|
-
let pkg;
|
|
2418
|
-
try {
|
|
2419
|
-
pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
2420
|
-
} catch {
|
|
2421
|
-
return null;
|
|
2422
|
-
}
|
|
2423
|
-
const allDeps = {
|
|
2424
|
-
...pkg.dependencies,
|
|
2425
|
-
...pkg.devDependencies
|
|
2426
|
-
};
|
|
2427
|
-
for (const [depName, framework] of Object.entries(FRAMEWORK_DETECTION_MAP)) {
|
|
2428
|
-
if (depName in allDeps) {
|
|
2429
|
-
return framework;
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
return null;
|
|
2433
|
-
}
|
|
2434
|
-
function hasRcConfig(cwd = process.cwd()) {
|
|
2435
|
-
return existsSync4(join4(cwd, ".mutagentrc.json"));
|
|
2436
|
-
}
|
|
2437
|
-
|
|
2438
|
-
// src/commands/init.ts
|
|
2439
|
-
function writeRcConfig(config, cwd = process.cwd()) {
|
|
2440
|
-
const rcPath = join5(cwd, ".mutagentrc.json");
|
|
2441
|
-
writeFileSync2(rcPath, JSON.stringify(config, null, 2) + `
|
|
2442
|
-
`);
|
|
2443
|
-
}
|
|
2444
2772
|
function createInitCommand() {
|
|
2445
2773
|
const init = new Command6("init").description("Initialize MutagenT in your project").option("--non-interactive", "Skip interactive prompts (defaults to CLI-only mode)").addHelpText("after", `
|
|
2446
2774
|
Examples:
|
|
@@ -2631,9 +2959,8 @@ Modes:
|
|
|
2631
2959
|
}
|
|
2632
2960
|
console.log("");
|
|
2633
2961
|
output.info("Next steps:");
|
|
2634
|
-
output.info(
|
|
2635
|
-
output.info(
|
|
2636
|
-
output.info(" 3. Run: mutagent providers list (confirm an LLM provider is configured)");
|
|
2962
|
+
output.info(` 1. Add MutagenT tracing to your ${confirmedFramework.name} code via ${confirmedFramework.mutagentPackage}`);
|
|
2963
|
+
output.info(" 2. Run: mutagent providers list (confirm an LLM provider is configured)");
|
|
2637
2964
|
} else {
|
|
2638
2965
|
writeRcConfig(rcConfig, cwd);
|
|
2639
2966
|
output.success("Created .mutagentrc.json");
|
|
@@ -2653,60 +2980,9 @@ Modes:
|
|
|
2653
2980
|
}
|
|
2654
2981
|
}
|
|
2655
2982
|
}
|
|
2656
|
-
const skillPath = join5(cwd, ".claude/skills/mutagent-cli/SKILL.md");
|
|
2657
|
-
const skillInstalled = existsSync5(skillPath);
|
|
2658
|
-
if (!isNonInteractive && !skillInstalled) {
|
|
2659
|
-
const { installSkill } = await inquirer2.prompt([{
|
|
2660
|
-
type: "confirm",
|
|
2661
|
-
name: "installSkill",
|
|
2662
|
-
message: "Install MutagenT skill for Claude Code? (Teaches AI agents how to use the CLI)",
|
|
2663
|
-
default: true
|
|
2664
|
-
}]);
|
|
2665
|
-
if (installSkill) {
|
|
2666
|
-
try {
|
|
2667
|
-
const skillDir = join5(cwd, ".claude/skills/mutagent-cli");
|
|
2668
|
-
if (!existsSync5(skillDir)) {
|
|
2669
|
-
mkdirSync2(skillDir, { recursive: true });
|
|
2670
|
-
}
|
|
2671
|
-
execSync2("node " + join5(cwd, "node_modules/.bin/mutagent") + " skills install", {
|
|
2672
|
-
cwd,
|
|
2673
|
-
stdio: "ignore"
|
|
2674
|
-
});
|
|
2675
|
-
output.success("Installed MutagenT CLI skill for Claude Code");
|
|
2676
|
-
} catch {
|
|
2677
|
-
output.info("Install skill manually: mutagent skills install");
|
|
2678
|
-
}
|
|
2679
|
-
}
|
|
2680
|
-
}
|
|
2681
2983
|
const initDirective = {
|
|
2682
|
-
instruction:
|
|
2683
|
-
|
|
2684
|
-
"Use your AskUserQuestion tool to present the following choices:",
|
|
2685
|
-
"1. Install skill + hooks (Recommended) — Installs the CLI skill AND configures Claude Code session telemetry hooks",
|
|
2686
|
-
"2. Install skill only — Installs the CLI skill (teaches AI agents to use MutagenT CLI)",
|
|
2687
|
-
"3. Skip — Do not install",
|
|
2688
|
-
"",
|
|
2689
|
-
"If the user picks option 1, run BOTH commands:",
|
|
2690
|
-
" mutagent skills install --json",
|
|
2691
|
-
" mutagent hooks install --json",
|
|
2692
|
-
"",
|
|
2693
|
-
"If the user picks option 2, run only: mutagent skills install --json",
|
|
2694
|
-
"",
|
|
2695
|
-
"After skill/hooks install, verify workspace: mutagent workspaces list --json"
|
|
2696
|
-
].join(`
|
|
2697
|
-
`),
|
|
2698
|
-
next: ["mutagent workspaces list --json", "mutagent providers list --json"],
|
|
2699
|
-
...!skillInstalled ? {
|
|
2700
|
-
askUserQuestions: [{
|
|
2701
|
-
question: "Would you like to install the MutagenT CLI skill and Claude Code hooks?",
|
|
2702
|
-
options: [
|
|
2703
|
-
{ label: "Install skill + hooks (Recommended)", description: "Installs the CLI skill AND configures Claude Code session telemetry hooks" },
|
|
2704
|
-
{ label: "Install skill only", description: "Installs the CLI skill (teaches AI agents to use MutagenT CLI)" },
|
|
2705
|
-
{ label: "Skip", description: "Do not install" }
|
|
2706
|
-
],
|
|
2707
|
-
multiSelect: false
|
|
2708
|
-
}]
|
|
2709
|
-
} : {}
|
|
2984
|
+
instruction: "Verify workspace. Run: mutagent workspaces list --json",
|
|
2985
|
+
next: ["mutagent workspaces list --json", "mutagent providers list --json"]
|
|
2710
2986
|
};
|
|
2711
2987
|
const summary = {
|
|
2712
2988
|
success: true,
|
|
@@ -2716,7 +2992,6 @@ Modes:
|
|
|
2716
2992
|
framework: confirmedFramework?.name ?? null,
|
|
2717
2993
|
authenticated,
|
|
2718
2994
|
workspaceValidation: workspaceValidation ?? null,
|
|
2719
|
-
skillInstalled: skillInstalled || existsSync5(skillPath),
|
|
2720
2995
|
_directive: initDirective
|
|
2721
2996
|
};
|
|
2722
2997
|
output.output(summary);
|
|
@@ -2730,8 +3005,8 @@ Modes:
|
|
|
2730
3005
|
// src/commands/skills.ts
|
|
2731
3006
|
import { Command as Command7 } from "commander";
|
|
2732
3007
|
import chalk13 from "chalk";
|
|
2733
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync3, writeFileSync as
|
|
2734
|
-
import { dirname, join as
|
|
3008
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3009
|
+
import { dirname, join as join7 } from "path";
|
|
2735
3010
|
import { execSync as execSync3 } from "child_process";
|
|
2736
3011
|
|
|
2737
3012
|
// src/generated/skill-content.ts
|
|
@@ -3099,7 +3374,8 @@ name: mutagent-cli-workflows-install
|
|
|
3099
3374
|
description: |
|
|
3100
3375
|
Meta-installer workflow. Installs a MutagenT package (helix, diagnostics, or
|
|
3101
3376
|
evaluator) into the user's environment via \`mutagent install <package>\`.
|
|
3102
|
-
Login-gated. diagnostics/evaluator come from public npm; helix
|
|
3377
|
+
Login-gated. diagnostics/evaluator come from public npm; helix is fetched
|
|
3378
|
+
from a private registry via a login-brokered signed URL (no static secret).
|
|
3103
3379
|
triggers:
|
|
3104
3380
|
- "install diagnostics"
|
|
3105
3381
|
- "install evaluator"
|
|
@@ -3138,7 +3414,7 @@ Where \`<package>\` is one of:
|
|
|
3138
3414
|
|---|---|---|
|
|
3139
3415
|
| \`diagnostics\` | public npm \`@mutagent/diagnostics\` | Ready to install |
|
|
3140
3416
|
| \`evaluator\` | public npm \`@mutagent/evaluator\` | Ready to install |
|
|
3141
|
-
| \`helix\` |
|
|
3417
|
+
| \`helix\` | private registry via login-brokered signed URL | Ready to install — login-gated download, sha256-verified, then initialized into your project |
|
|
3142
3418
|
|
|
3143
3419
|
**Flags** (verify against \`--help\`):
|
|
3144
3420
|
- \`--harness <claude-code|codex|omp>\` -- target coding-agent harness (default \`claude-code\`).
|
|
@@ -3171,6 +3447,8 @@ Where \`<package>\` is one of:
|
|
|
3171
3447
|
## Examples
|
|
3172
3448
|
|
|
3173
3449
|
\`\`\`bash
|
|
3450
|
+
mutagent install helix --json
|
|
3451
|
+
mutagent install helix --harness codex --json
|
|
3174
3452
|
mutagent install diagnostics --json
|
|
3175
3453
|
mutagent install evaluator --version 1.2.3 --json
|
|
3176
3454
|
mutagent install diagnostics --harness codex --json
|
|
@@ -3181,15 +3459,15 @@ mutagent install diagnostics --harness codex --json
|
|
|
3181
3459
|
## Output handling
|
|
3182
3460
|
|
|
3183
3461
|
- On success (\`{ success: true, package, version, harness, global }\`): tell the user what was installed and the resolved version. Surface \`_links.install\` / \`_links.login\`.
|
|
3184
|
-
-
|
|
3185
|
-
- On an auth error: route to the login workflow, then retry.
|
|
3462
|
+
- For \`helix\`: the CLI resolves a signed download URL from the login broker, downloads + sha256-verifies the plugin, then runs its init into the project. An \`INTEGRITY_ERROR\` means the download failed checksum verification — retry.
|
|
3463
|
+
- On an auth error (including a broker \`AUTH_REQUIRED\`): route to the login workflow, then retry.
|
|
3186
3464
|
|
|
3187
3465
|
---
|
|
3188
3466
|
|
|
3189
3467
|
## Common pitfalls
|
|
3190
3468
|
|
|
3191
3469
|
- Running before login → auth error (install is login-gated).
|
|
3192
|
-
- Assuming \`helix\` installs
|
|
3470
|
+
- Assuming \`helix\` installs from public npm — it is fetched from a private registry via a login-brokered signed URL (the CLI holds no static secret).
|
|
3193
3471
|
- Installing without confirming with the user first (Core Rule 5).
|
|
3194
3472
|
|
|
3195
3473
|
---
|
|
@@ -3383,7 +3661,7 @@ that teaches coding agents how to use the MutagenT CLI effectively.
|
|
|
3383
3661
|
const isJson = parentCmd ? getJsonFlag(parentCmd) : false;
|
|
3384
3662
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
3385
3663
|
const repoRoot = findRepoRoot();
|
|
3386
|
-
const skillDir =
|
|
3664
|
+
const skillDir = join7(repoRoot, SKILL_DIR);
|
|
3387
3665
|
const files = getSkillFiles();
|
|
3388
3666
|
const writtenFiles = [];
|
|
3389
3667
|
let totalBytes = 0;
|
|
@@ -3395,7 +3673,7 @@ that teaches coding agents how to use the MutagenT CLI effectively.
|
|
|
3395
3673
|
return a.localeCompare(b);
|
|
3396
3674
|
});
|
|
3397
3675
|
for (const relPath of sortedKeys) {
|
|
3398
|
-
const destPath =
|
|
3676
|
+
const destPath = join7(skillDir, relPath);
|
|
3399
3677
|
const parentDir = dirname(destPath);
|
|
3400
3678
|
if (!existsSync6(parentDir)) {
|
|
3401
3679
|
mkdirSync3(parentDir, { recursive: true });
|
|
@@ -3404,7 +3682,7 @@ that teaches coding agents how to use the MutagenT CLI effectively.
|
|
|
3404
3682
|
const finalContent = raw.endsWith(`
|
|
3405
3683
|
`) ? raw : `${raw}
|
|
3406
3684
|
`;
|
|
3407
|
-
|
|
3685
|
+
writeFileSync4(destPath, finalContent, "utf-8");
|
|
3408
3686
|
writtenFiles.push({ path: destPath, bytes: finalContent.length });
|
|
3409
3687
|
totalBytes += finalContent.length;
|
|
3410
3688
|
}
|
|
@@ -3507,18 +3785,18 @@ import { Command as Command9 } from "commander";
|
|
|
3507
3785
|
import { randomUUID } from "crypto";
|
|
3508
3786
|
|
|
3509
3787
|
// src/commands/hooks/state.ts
|
|
3510
|
-
import { readFileSync as
|
|
3511
|
-
import { join as
|
|
3788
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, renameSync as renameSync2, unlinkSync, existsSync as existsSync7 } from "fs";
|
|
3789
|
+
import { join as join8 } from "path";
|
|
3512
3790
|
import { tmpdir } from "os";
|
|
3513
3791
|
function stateFilePath(sessionId) {
|
|
3514
|
-
return
|
|
3792
|
+
return join8(tmpdir(), `mutagent-hook-${sessionId}.json`);
|
|
3515
3793
|
}
|
|
3516
3794
|
function readState(sessionId) {
|
|
3517
3795
|
const path = stateFilePath(sessionId);
|
|
3518
3796
|
if (!existsSync7(path))
|
|
3519
3797
|
return null;
|
|
3520
3798
|
try {
|
|
3521
|
-
const raw = JSON.parse(
|
|
3799
|
+
const raw = JSON.parse(readFileSync5(path, "utf-8"));
|
|
3522
3800
|
if (!Array.isArray(raw.parentStack)) {
|
|
3523
3801
|
raw.parentStack = [];
|
|
3524
3802
|
}
|
|
@@ -3533,8 +3811,8 @@ function readState(sessionId) {
|
|
|
3533
3811
|
function writeState(sessionId, state) {
|
|
3534
3812
|
const path = stateFilePath(sessionId);
|
|
3535
3813
|
const tmpPath = `${path}.${process.pid.toString()}.tmp`;
|
|
3536
|
-
|
|
3537
|
-
|
|
3814
|
+
writeFileSync5(tmpPath, JSON.stringify(state), "utf-8");
|
|
3815
|
+
renameSync2(tmpPath, path);
|
|
3538
3816
|
}
|
|
3539
3817
|
function deleteState(sessionId) {
|
|
3540
3818
|
const path = stateFilePath(sessionId);
|
|
@@ -4185,8 +4463,8 @@ async function handlePostToolUseFailure() {
|
|
|
4185
4463
|
}
|
|
4186
4464
|
|
|
4187
4465
|
// src/commands/hooks/install.ts
|
|
4188
|
-
import { readFileSync as
|
|
4189
|
-
import { join as
|
|
4466
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
4467
|
+
import { join as join9 } from "path";
|
|
4190
4468
|
|
|
4191
4469
|
class SettingsParseError extends Error {
|
|
4192
4470
|
settingsPath;
|
|
@@ -4248,17 +4526,17 @@ function migrateV1Hooks(settings) {
|
|
|
4248
4526
|
return migrated;
|
|
4249
4527
|
}
|
|
4250
4528
|
function installHooks(cwd) {
|
|
4251
|
-
const claudeDir =
|
|
4252
|
-
const settingsPath =
|
|
4529
|
+
const claudeDir = join9(cwd, ".claude");
|
|
4530
|
+
const settingsPath = join9(claudeDir, "settings.local.json");
|
|
4253
4531
|
const existed = existsSync8(settingsPath);
|
|
4254
4532
|
let settings = {};
|
|
4255
4533
|
if (existed) {
|
|
4256
|
-
const raw =
|
|
4534
|
+
const raw = readFileSync6(settingsPath, "utf-8");
|
|
4257
4535
|
try {
|
|
4258
4536
|
settings = JSON.parse(raw);
|
|
4259
4537
|
} catch (err) {
|
|
4260
4538
|
const backupPath = `${settingsPath}.bak.${new Date().toISOString().replace(/:/g, "-")}`;
|
|
4261
|
-
|
|
4539
|
+
writeFileSync6(backupPath, raw, "utf-8");
|
|
4262
4540
|
throw new SettingsParseError(settingsPath, backupPath, err);
|
|
4263
4541
|
}
|
|
4264
4542
|
}
|
|
@@ -4291,7 +4569,7 @@ function installHooks(cwd) {
|
|
|
4291
4569
|
if (!existsSync8(claudeDir)) {
|
|
4292
4570
|
mkdirSync4(claudeDir, { recursive: true });
|
|
4293
4571
|
}
|
|
4294
|
-
|
|
4572
|
+
writeFileSync6(settingsPath, JSON.stringify(settings, null, 2) + `
|
|
4295
4573
|
`, "utf-8");
|
|
4296
4574
|
}
|
|
4297
4575
|
if (added.length > 0) {
|
|
@@ -4437,8 +4715,8 @@ times is safe.
|
|
|
4437
4715
|
import { Command as Command10 } from "commander";
|
|
4438
4716
|
import chalk16 from "chalk";
|
|
4439
4717
|
import { type as osType, release as osRelease } from "os";
|
|
4440
|
-
import { readFileSync as
|
|
4441
|
-
import { join as
|
|
4718
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
4719
|
+
import { join as join11, dirname as dirname2 } from "path";
|
|
4442
4720
|
import { fileURLToPath } from "url";
|
|
4443
4721
|
init_errors();
|
|
4444
4722
|
init_config();
|
|
@@ -4446,11 +4724,11 @@ init_config();
|
|
|
4446
4724
|
// src/lib/transcript.ts
|
|
4447
4725
|
init_errors();
|
|
4448
4726
|
import { homedir as osHomedir } from "os";
|
|
4449
|
-
import { join as
|
|
4727
|
+
import { join as join10 } from "path";
|
|
4450
4728
|
import {
|
|
4451
4729
|
existsSync as fsExistsSync,
|
|
4452
4730
|
statSync as fsStatSync,
|
|
4453
|
-
readFileSync as
|
|
4731
|
+
readFileSync as readFileSync7,
|
|
4454
4732
|
readdirSync,
|
|
4455
4733
|
openSync,
|
|
4456
4734
|
readSync,
|
|
@@ -4461,7 +4739,7 @@ var TAIL_BYTES = 200000;
|
|
|
4461
4739
|
function defaultReadTail(path, tailBytes) {
|
|
4462
4740
|
const { size } = fsStatSync(path);
|
|
4463
4741
|
if (size <= tailBytes) {
|
|
4464
|
-
return { content:
|
|
4742
|
+
return { content: readFileSync7(path, "utf-8"), truncated: false };
|
|
4465
4743
|
}
|
|
4466
4744
|
const fd = openSync(path, "r");
|
|
4467
4745
|
try {
|
|
@@ -4484,7 +4762,7 @@ function defaultScan(dir) {
|
|
|
4484
4762
|
return;
|
|
4485
4763
|
}
|
|
4486
4764
|
for (const entry of entries) {
|
|
4487
|
-
const full =
|
|
4765
|
+
const full = join10(current, entry.name);
|
|
4488
4766
|
if (entry.isDirectory())
|
|
4489
4767
|
walk(full);
|
|
4490
4768
|
else if (entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
@@ -4495,11 +4773,11 @@ function defaultScan(dir) {
|
|
|
4495
4773
|
return out;
|
|
4496
4774
|
}
|
|
4497
4775
|
function buildSources(env, home) {
|
|
4498
|
-
const ompBase = env.PI_CODING_AGENT_DIR ??
|
|
4776
|
+
const ompBase = env.PI_CODING_AGENT_DIR ?? join10(home, ".omp", "agent");
|
|
4499
4777
|
return [
|
|
4500
|
-
{ harness: "claude-code", dir:
|
|
4501
|
-
{ harness: "codex", dir:
|
|
4502
|
-
{ harness: "omp", dir:
|
|
4778
|
+
{ harness: "claude-code", dir: join10(home, ".claude", "projects") },
|
|
4779
|
+
{ harness: "codex", dir: join10(home, ".codex", "sessions") },
|
|
4780
|
+
{ harness: "omp", dir: join10(ompBase, "sessions") }
|
|
4503
4781
|
];
|
|
4504
4782
|
}
|
|
4505
4783
|
function resolveTranscript(attach, deps = {}) {
|
|
@@ -4553,8 +4831,8 @@ function getCliVersion() {
|
|
|
4553
4831
|
return process.env.CLI_VERSION;
|
|
4554
4832
|
try {
|
|
4555
4833
|
const __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
4556
|
-
const pkgPath =
|
|
4557
|
-
const pkg = JSON.parse(
|
|
4834
|
+
const pkgPath = join11(__dirname2, "..", "..", "package.json");
|
|
4835
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
4558
4836
|
return pkg.version ?? "0.1.1";
|
|
4559
4837
|
} catch {
|
|
4560
4838
|
return "0.1.1";
|
|
@@ -4719,78 +4997,6 @@ Or set an API key: mutagent config set apiKey <key>`);
|
|
|
4719
4997
|
import { Command as Command11 } from "commander";
|
|
4720
4998
|
import chalk17 from "chalk";
|
|
4721
4999
|
init_errors();
|
|
4722
|
-
|
|
4723
|
-
// src/lib/installer.ts
|
|
4724
|
-
init_errors();
|
|
4725
|
-
init_config();
|
|
4726
|
-
import { spawn } from "child_process";
|
|
4727
|
-
var VALID_PACKAGES = ["helix", "diagnostics", "evaluator"];
|
|
4728
|
-
var VALID_HARNESSES = ["claude-code", "codex", "omp"];
|
|
4729
|
-
var VERSION_MATRIX = {
|
|
4730
|
-
helix: "latest",
|
|
4731
|
-
diagnostics: "latest",
|
|
4732
|
-
evaluator: "latest"
|
|
4733
|
-
};
|
|
4734
|
-
var NPM_PACKAGES = {
|
|
4735
|
-
diagnostics: "@mutagent/diagnostics",
|
|
4736
|
-
evaluator: "@mutagent/evaluator"
|
|
4737
|
-
};
|
|
4738
|
-
var defaultRunner = (cmd, args) => new Promise((resolve, reject) => {
|
|
4739
|
-
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4740
|
-
let stdout = "";
|
|
4741
|
-
let stderr = "";
|
|
4742
|
-
child.stdout.on("data", (chunk) => {
|
|
4743
|
-
stdout += chunk.toString("utf-8");
|
|
4744
|
-
});
|
|
4745
|
-
child.stderr.on("data", (chunk) => {
|
|
4746
|
-
stderr += chunk.toString("utf-8");
|
|
4747
|
-
});
|
|
4748
|
-
child.on("error", (err) => {
|
|
4749
|
-
reject(new MutagentError("INSTALL_FAILED", `Failed to run ${cmd}: ${err.message}`, `Ensure "${cmd}" is installed and available on your PATH.`));
|
|
4750
|
-
});
|
|
4751
|
-
child.on("close", (code) => {
|
|
4752
|
-
resolve({ code: code ?? 1, stdout, stderr });
|
|
4753
|
-
});
|
|
4754
|
-
});
|
|
4755
|
-
function isValidPackage(pkg) {
|
|
4756
|
-
return VALID_PACKAGES.includes(pkg);
|
|
4757
|
-
}
|
|
4758
|
-
function isValidHarness(harness) {
|
|
4759
|
-
return VALID_HARNESSES.includes(harness);
|
|
4760
|
-
}
|
|
4761
|
-
async function installPackage(pkg, opts, deps = {}) {
|
|
4762
|
-
const isAuthed = deps.isAuthed ?? hasCredentials;
|
|
4763
|
-
if (!isAuthed()) {
|
|
4764
|
-
throw new MutagentError("AUTH_REQUIRED", `Authentication required to install ${pkg}.`, "Run: mutagent login");
|
|
4765
|
-
}
|
|
4766
|
-
if (!isValidPackage(pkg)) {
|
|
4767
|
-
throw new MutagentError("INVALID_ARGUMENTS", `Unknown package "${pkg}". Valid: ${VALID_PACKAGES.join(", ")}`, "Run: mutagent install --help");
|
|
4768
|
-
}
|
|
4769
|
-
if (!isValidHarness(opts.harness)) {
|
|
4770
|
-
throw new MutagentError("INVALID_ARGUMENTS", `Unknown harness "${opts.harness}". Valid: ${VALID_HARNESSES.join(", ")}`, "Run: mutagent install --help");
|
|
4771
|
-
}
|
|
4772
|
-
const version = opts.version ?? VERSION_MATRIX[pkg];
|
|
4773
|
-
if (pkg === "helix") {
|
|
4774
|
-
throw new MutagentError("NOT_IMPLEMENTED", "helix self-host install is not available yet — hosting on install.mutagent.io is pending (see issue #1191, task CI1).", "Track: gh issue view 1191. For now install diagnostics/evaluator via npm.");
|
|
4775
|
-
}
|
|
4776
|
-
const npmPackage = NPM_PACKAGES[pkg];
|
|
4777
|
-
const args = ["install", "-g", `${npmPackage}@${version}`];
|
|
4778
|
-
const runner = deps.runner ?? defaultRunner;
|
|
4779
|
-
const result = await runner("npm", args);
|
|
4780
|
-
if (result.code !== 0) {
|
|
4781
|
-
const detail = result.stderr.trim();
|
|
4782
|
-
throw new MutagentError("INSTALL_FAILED", `npm failed to install ${npmPackage}@${version} (exit ${String(result.code)}).${detail ? ` ${detail.slice(0, 200)}` : ""}`, "Verify the package and version exist and that you have permission for a global npm install.");
|
|
4783
|
-
}
|
|
4784
|
-
return {
|
|
4785
|
-
package: pkg,
|
|
4786
|
-
version,
|
|
4787
|
-
harness: opts.harness,
|
|
4788
|
-
global: opts.global,
|
|
4789
|
-
command: `npm ${args.join(" ")}`
|
|
4790
|
-
};
|
|
4791
|
-
}
|
|
4792
|
-
|
|
4793
|
-
// src/commands/install/index.ts
|
|
4794
5000
|
function createInstallCommand(deps) {
|
|
4795
5001
|
const install = new Command11("install").description("Install a MutagenT package (helix, diagnostics, evaluator)").argument("<package>", `Package to install: ${VALID_PACKAGES.join(", ")}`).option("--harness <harness>", `Target harness: ${VALID_HARNESSES.join(", ")}`, "claude-code").option("--global", "Install globally", true).option("--version <version>", "Package version to install (default: latest)").addHelpText("after", `
|
|
4796
5002
|
${chalk17.bold("Arguments & flags:")}
|
|
@@ -4801,15 +5007,18 @@ ${chalk17.bold("Arguments & flags:")}
|
|
|
4801
5007
|
${chalk17.bold("--json")} Structured output
|
|
4802
5008
|
|
|
4803
5009
|
${chalk17.bold("Examples:")}
|
|
5010
|
+
${chalk17.dim("$")} mutagent install helix
|
|
5011
|
+
${chalk17.dim("$")} mutagent install helix --harness codex
|
|
4804
5012
|
${chalk17.dim("$")} mutagent install diagnostics
|
|
4805
5013
|
${chalk17.dim("$")} mutagent install evaluator --version 1.2.3
|
|
4806
5014
|
${chalk17.dim("$")} mutagent install diagnostics --harness codex --json
|
|
4807
5015
|
|
|
4808
5016
|
${chalk17.bold("Packages:")}
|
|
5017
|
+
${chalk17.bold("helix")} ${chalk17.green("(available)")} — the ADL conductor. Downloaded from a private
|
|
5018
|
+
registry via a login-brokered signed URL, sha256-verified, then
|
|
5019
|
+
initialized into your project. No static secret ships in the CLI.
|
|
4809
5020
|
${chalk17.bold("diagnostics")} Public npm package @mutagent/diagnostics ${chalk17.green("(available)")}
|
|
4810
5021
|
${chalk17.bold("evaluator")} Public npm package @mutagent/evaluator ${chalk17.green("(available)")}
|
|
4811
|
-
${chalk17.bold("helix")} ${chalk17.yellow("NOT yet available")} — self-host on install.mutagent.io is pending (#1191).
|
|
4812
|
-
Running it today errors with ${chalk17.bold("NOT_IMPLEMENTED")} by design (no fake install).
|
|
4813
5022
|
|
|
4814
5023
|
${chalk17.yellow("Note:")} install is login-gated. Run ${chalk17.cyan("mutagent login")} first (else exits with a login directive).
|
|
4815
5024
|
`).action(async (pkg, options) => {
|
|
@@ -4847,8 +5056,8 @@ if (process.env.CLI_VERSION) {
|
|
|
4847
5056
|
} else {
|
|
4848
5057
|
try {
|
|
4849
5058
|
const __dirname2 = dirname3(fileURLToPath2(import.meta.url));
|
|
4850
|
-
const pkgPath =
|
|
4851
|
-
const pkg = JSON.parse(
|
|
5059
|
+
const pkgPath = join12(__dirname2, "..", "..", "package.json");
|
|
5060
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
4852
5061
|
cliVersion = pkg.version ?? cliVersion;
|
|
4853
5062
|
} catch {}
|
|
4854
5063
|
}
|
|
@@ -4863,12 +5072,12 @@ program.name("mutagent").description(`MutagenT CLI - command-line client for the
|
|
|
4863
5072
|
});
|
|
4864
5073
|
program.addHelpText("after", `
|
|
4865
5074
|
${chalk18.bold.cyan("WORKFLOWS:")}
|
|
4866
|
-
${chalk18.bold("Setup")} mutagent login → mutagent init
|
|
4867
|
-
${chalk18.bold("Lifecycle Tools")} mutagent install <diagnostics|evaluator> ${chalk18.dim("(login-gated
|
|
5075
|
+
${chalk18.bold("Setup")} mutagent login → mutagent init
|
|
5076
|
+
${chalk18.bold("Lifecycle Tools")} mutagent install <helix|diagnostics|evaluator> ${chalk18.dim("(login-gated)")}
|
|
4868
5077
|
${chalk18.bold("Feedback")} mutagent feedback send "<what happened>" --category <cli|helix|stage:<x>> ${chalk18.dim("[--session <id>] [--attach-transcript]")}
|
|
4869
5078
|
|
|
4870
5079
|
${chalk18.dim("For CLI usage guidance for AI agents, see the Skill at")}
|
|
4871
|
-
${chalk18.cyan(".claude/skills/mutagent-cli/SKILL.md")}
|
|
5080
|
+
${chalk18.cyan(".claude/skills/mutagent-cli/SKILL.md")}
|
|
4872
5081
|
|
|
4873
5082
|
${chalk18.yellow("Non-Interactive Mode (CI/CD & Coding Agents):")}
|
|
4874
5083
|
export MUTAGENT_API_KEY=mt_... ${chalk18.dim("or")} --api-key mt_...
|
|
@@ -4885,11 +5094,10 @@ ${chalk18.yellow("Command Navigation:")}
|
|
|
4885
5094
|
mutagent providers list --json ${chalk18.dim("List configured BYOK providers")}
|
|
4886
5095
|
mutagent providers list --models ${chalk18.dim("See available models per provider")}
|
|
4887
5096
|
|
|
4888
|
-
mutagent install
|
|
5097
|
+
mutagent install helix ${chalk18.dim("Install the ADL lifecycle conductor (login-gated)")}
|
|
4889
5098
|
mutagent install evaluator --version 1.2.3 ${chalk18.dim("Pin a version")}
|
|
4890
|
-
mutagent install --help ${chalk18.dim("helix
|
|
5099
|
+
mutagent install --help ${chalk18.dim("helix | diagnostics | evaluator")}
|
|
4891
5100
|
|
|
4892
|
-
mutagent skills install ${chalk18.dim("Install the MutagenT CLI skill for AI agents")}
|
|
4893
5101
|
mutagent hooks --help ${chalk18.dim("Hook setup for Claude Code session telemetry upload")}
|
|
4894
5102
|
|
|
4895
5103
|
${chalk18.bold.red("Report Issues:")}
|
|
@@ -4909,7 +5117,6 @@ ${chalk18.yellow("Directive System:")}
|
|
|
4909
5117
|
${chalk18.bold("_compat")} Compat metadata: cliVersion, skillVersion, skillMinCliVersion
|
|
4910
5118
|
|
|
4911
5119
|
${chalk18.yellow("AI Agent Rules (MANDATORY for coding agents):")}
|
|
4912
|
-
0. If .claude/skills/mutagent-cli/SKILL.md does not exist, run mutagent skills install first
|
|
4913
5120
|
1. Login (two paths):
|
|
4914
5121
|
- CI / fully automated: export MUTAGENT_API_KEY=mt_... then mutagent login --json
|
|
4915
5122
|
- Helping a user onboard: mutagent login --browser --json
|
|
@@ -4962,15 +5169,7 @@ program.addCommand(createUsageCommand());
|
|
|
4962
5169
|
program.addCommand(createHooksCommand());
|
|
4963
5170
|
program.addCommand(createInstallCommand());
|
|
4964
5171
|
program.addCommand(createFeedbackCommand());
|
|
4965
|
-
var isInteractive = process.stdin.isTTY && !rawArgs.includes("--json") && process.env.CI !== "true";
|
|
4966
|
-
var isSkillCommand = rawArgs[0] === "skills" || rawArgs[0] === "hooks";
|
|
4967
|
-
if (isInteractive && !isSkillCommand) {
|
|
4968
|
-
const skillPath = join11(process.cwd(), ".claude/skills/mutagent-cli/SKILL.md");
|
|
4969
|
-
if (!existsSync9(skillPath)) {
|
|
4970
|
-
console.log(chalk18.dim("MutagenT SKILL not installed. Install it for AI agent support? Run:"), chalk18.cyan("mutagent skills install"));
|
|
4971
|
-
}
|
|
4972
|
-
}
|
|
4973
5172
|
program.parse();
|
|
4974
5173
|
|
|
4975
|
-
//# debugId=
|
|
5174
|
+
//# debugId=8FB723E6C0DFB02564756E2164756E21
|
|
4976
5175
|
//# sourceMappingURL=cli.js.map
|