@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 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 readFileSync8, existsSync as existsSync9 } from "fs";
732
- import { join as join11, dirname as dirname3 } from "path";
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 existsSync3 } from "fs";
741
- import { join as join3 } from "path";
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
- async function runPostOnboarding() {
941
- const inquirer = (await import("inquirer")).default;
942
- console.log("");
943
- console.log(chalk2.bold.cyan(" You are authenticated. What would you like to do next?"));
944
- console.log("");
945
- const { path: selectedPath } = await inquirer.prompt([{
946
- type: "list",
947
- name: "path",
948
- message: "Choose your path:",
949
- choices: [
950
- {
951
- name: `${chalk2.green("A")} Initialize this project — create .mutagentrc.json + install the CLI skill`,
952
- value: "init"
953
- },
954
- {
955
- name: `${chalk2.green("B")} Install a lifecycle tool — helix / diagnostics / evaluator`,
956
- value: "install"
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
- name: `${chalk2.green("C")} Exit — explore the CLI on your own`,
960
- value: "exit"
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
- if (selectedPath === "init") {
966
- console.log(chalk2.bold(" Project setup:"));
967
- console.log("");
968
- console.log(` 1. ${chalk2.green("mutagent init")}`);
969
- console.log(" Scaffold .mutagentrc.json and select your workspace");
970
- console.log("");
971
- console.log(` 2. ${chalk2.green("mutagent skills install")}`);
972
- console.log(" Install the MutagenT CLI skill for AI coding agents");
973
- console.log("");
974
- console.log(` 3. ${chalk2.green("mutagent providers list")}`);
975
- console.log(" Confirm an LLM provider is configured");
976
- console.log("");
977
- } else if (selectedPath === "install") {
978
- console.log(chalk2.bold(" Install a lifecycle tool:"));
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(" You can run `mutagent --help` anytime to see available commands."));
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 = existsSync3(join3(cwd, ".mutagentrc.json"));
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(" 1. Run: mutagent skills install (install the CLI skill for AI agents)");
2635
- output.info(` 2. Add MutagenT tracing to your ${confirmedFramework.name} code via ${confirmedFramework.mutagentPackage}`);
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: skillInstalled ? "Verify workspace. Run: mutagent workspaces list --json" : [
2683
- "MANDATORY: Ask the user whether they want to install the MutagenT CLI skill and Claude Code hooks.",
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 writeFileSync3 } from "fs";
2734
- import { dirname, join as join6 } from "path";
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 self-hosts.
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\` | self-hosted install | Pendingmay return \`NOT_IMPLEMENTED\` for now |
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
- - If \`helix\` returns \`NOT_IMPLEMENTED\`: explain that self-hosted helix install is still pending (tracked upstream) and suggest \`diagnostics\` / \`evaluator\`, which install from public npm today.
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 like the npm packages — it self-hosts and may not be wired yet.
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 = join6(repoRoot, SKILL_DIR);
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 = join6(skillDir, relPath);
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
- writeFileSync3(destPath, finalContent, "utf-8");
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 readFileSync4, writeFileSync as writeFileSync4, renameSync, unlinkSync, existsSync as existsSync7 } from "fs";
3511
- import { join as join7 } from "path";
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 join7(tmpdir(), `mutagent-hook-${sessionId}.json`);
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(readFileSync4(path, "utf-8"));
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
- writeFileSync4(tmpPath, JSON.stringify(state), "utf-8");
3537
- renameSync(tmpPath, path);
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 readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
4189
- import { join as join8 } from "path";
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 = join8(cwd, ".claude");
4252
- const settingsPath = join8(claudeDir, "settings.local.json");
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 = readFileSync5(settingsPath, "utf-8");
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
- writeFileSync5(backupPath, raw, "utf-8");
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
- writeFileSync5(settingsPath, JSON.stringify(settings, null, 2) + `
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 readFileSync7 } from "fs";
4441
- import { join as join10, dirname as dirname2 } from "path";
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 join9 } from "path";
4727
+ import { join as join10 } from "path";
4450
4728
  import {
4451
4729
  existsSync as fsExistsSync,
4452
4730
  statSync as fsStatSync,
4453
- readFileSync as readFileSync6,
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: readFileSync6(path, "utf-8"), truncated: false };
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 = join9(current, entry.name);
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 ?? join9(home, ".omp", "agent");
4776
+ const ompBase = env.PI_CODING_AGENT_DIR ?? join10(home, ".omp", "agent");
4499
4777
  return [
4500
- { harness: "claude-code", dir: join9(home, ".claude", "projects") },
4501
- { harness: "codex", dir: join9(home, ".codex", "sessions") },
4502
- { harness: "omp", dir: join9(ompBase, "sessions") }
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 = join10(__dirname2, "..", "..", "package.json");
4557
- const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
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 = join11(__dirname2, "..", "..", "package.json");
4851
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
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 → mutagent skills install
4867
- ${chalk18.bold("Lifecycle Tools")} mutagent install <diagnostics|evaluator> ${chalk18.dim("(login-gated; helix pending #1191)")}
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")} ${chalk18.dim("(install via")} ${chalk18.cyan("mutagent skills install")}${chalk18.dim(")")}
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 diagnostics ${chalk18.dim("Install diagnostics from npm (login-gated)")}
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 (pending #1191) | diagnostics | evaluator")}
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=9788EBFA942A533664756E2164756E21
5174
+ //# debugId=8FB723E6C0DFB02564756E2164756E21
4976
5175
  //# sourceMappingURL=cli.js.map