morphix-env 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/dist/SKILL.md +14 -2
- package/dist/cli.js +929 -80
- package/dist/index.d.ts +182 -0
- package/dist/index.js +732 -0
- package/package.json +16 -3
package/dist/cli.js
CHANGED
|
@@ -831,8 +831,8 @@ var require_react_development = __commonJS({
|
|
|
831
831
|
function lazyInitializer(payload) {
|
|
832
832
|
if (-1 === payload._status) {
|
|
833
833
|
var resolveDebugValue = null, rejectDebugValue = null, ioInfo = payload._ioInfo;
|
|
834
|
-
null != ioInfo && (ioInfo.start = ioInfo.end = performance.now(), ioInfo.value = new Promise(function(
|
|
835
|
-
resolveDebugValue =
|
|
834
|
+
null != ioInfo && (ioInfo.start = ioInfo.end = performance.now(), ioInfo.value = new Promise(function(resolve7, reject) {
|
|
835
|
+
resolveDebugValue = resolve7;
|
|
836
836
|
rejectDebugValue = reject;
|
|
837
837
|
}));
|
|
838
838
|
ioInfo = payload._result;
|
|
@@ -948,21 +948,21 @@ var require_react_development = __commonJS({
|
|
|
948
948
|
);
|
|
949
949
|
actScopeDepth = prevActScopeDepth;
|
|
950
950
|
}
|
|
951
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
951
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve7, reject) {
|
|
952
952
|
var queue = ReactSharedInternals.actQueue;
|
|
953
953
|
if (null !== queue)
|
|
954
954
|
if (0 !== queue.length)
|
|
955
955
|
try {
|
|
956
956
|
flushActQueue(queue);
|
|
957
957
|
enqueueTask(function() {
|
|
958
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
958
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve7, reject);
|
|
959
959
|
});
|
|
960
960
|
return;
|
|
961
961
|
} catch (error) {
|
|
962
962
|
ReactSharedInternals.thrownErrors.push(error);
|
|
963
963
|
}
|
|
964
964
|
else ReactSharedInternals.actQueue = null;
|
|
965
|
-
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) :
|
|
965
|
+
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve7(returnValue);
|
|
966
966
|
}
|
|
967
967
|
function flushActQueue(queue) {
|
|
968
968
|
if (!isFlushing) {
|
|
@@ -1150,7 +1150,7 @@ var require_react_development = __commonJS({
|
|
|
1150
1150
|
));
|
|
1151
1151
|
});
|
|
1152
1152
|
return {
|
|
1153
|
-
then: function(
|
|
1153
|
+
then: function(resolve7, reject) {
|
|
1154
1154
|
didAwaitActCall = true;
|
|
1155
1155
|
thenable.then(
|
|
1156
1156
|
function(returnValue) {
|
|
@@ -1160,7 +1160,7 @@ var require_react_development = __commonJS({
|
|
|
1160
1160
|
flushActQueue(queue), enqueueTask(function() {
|
|
1161
1161
|
return recursivelyFlushAsyncActWork(
|
|
1162
1162
|
returnValue,
|
|
1163
|
-
|
|
1163
|
+
resolve7,
|
|
1164
1164
|
reject
|
|
1165
1165
|
);
|
|
1166
1166
|
});
|
|
@@ -1174,7 +1174,7 @@ var require_react_development = __commonJS({
|
|
|
1174
1174
|
ReactSharedInternals.thrownErrors.length = 0;
|
|
1175
1175
|
reject(_thrownError);
|
|
1176
1176
|
}
|
|
1177
|
-
} else
|
|
1177
|
+
} else resolve7(returnValue);
|
|
1178
1178
|
},
|
|
1179
1179
|
function(error) {
|
|
1180
1180
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
@@ -1196,15 +1196,15 @@ var require_react_development = __commonJS({
|
|
|
1196
1196
|
if (0 < ReactSharedInternals.thrownErrors.length)
|
|
1197
1197
|
throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
|
1198
1198
|
return {
|
|
1199
|
-
then: function(
|
|
1199
|
+
then: function(resolve7, reject) {
|
|
1200
1200
|
didAwaitActCall = true;
|
|
1201
1201
|
0 === prevActScopeDepth ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
|
|
1202
1202
|
return recursivelyFlushAsyncActWork(
|
|
1203
1203
|
returnValue$jscomp$0,
|
|
1204
|
-
|
|
1204
|
+
resolve7,
|
|
1205
1205
|
reject
|
|
1206
1206
|
);
|
|
1207
|
-
})) :
|
|
1207
|
+
})) : resolve7(returnValue$jscomp$0);
|
|
1208
1208
|
}
|
|
1209
1209
|
};
|
|
1210
1210
|
};
|
|
@@ -12991,7 +12991,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
12991
12991
|
};
|
|
12992
12992
|
}
|
|
12993
12993
|
exports2.prerender = function(children, options) {
|
|
12994
|
-
return new Promise(function(
|
|
12994
|
+
return new Promise(function(resolve7, reject) {
|
|
12995
12995
|
var onHeaders = options ? options.onHeaders : void 0, onHeadersImpl;
|
|
12996
12996
|
onHeaders && (onHeadersImpl = function(headersDescriptor) {
|
|
12997
12997
|
onHeaders(new Headers(headersDescriptor));
|
|
@@ -13035,7 +13035,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13035
13035
|
{ highWaterMark: 0 }
|
|
13036
13036
|
);
|
|
13037
13037
|
stream2 = { postponed: getPostponedState(request), prelude: stream2 };
|
|
13038
|
-
|
|
13038
|
+
resolve7(stream2);
|
|
13039
13039
|
},
|
|
13040
13040
|
void 0,
|
|
13041
13041
|
void 0,
|
|
@@ -13046,7 +13046,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13046
13046
|
});
|
|
13047
13047
|
};
|
|
13048
13048
|
exports2.prerenderToNodeStream = function(children, options) {
|
|
13049
|
-
return new Promise(function(
|
|
13049
|
+
return new Promise(function(resolve7, reject) {
|
|
13050
13050
|
var resumableState = createResumableState(
|
|
13051
13051
|
options ? options.identifierPrefix : void 0,
|
|
13052
13052
|
options ? options.unstable_externalRuntimeSrc : void 0,
|
|
@@ -13078,7 +13078,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13078
13078
|
postponed: getPostponedState(request),
|
|
13079
13079
|
prelude: readable
|
|
13080
13080
|
};
|
|
13081
|
-
|
|
13081
|
+
resolve7(readable);
|
|
13082
13082
|
},
|
|
13083
13083
|
void 0,
|
|
13084
13084
|
void 0,
|
|
@@ -13123,7 +13123,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13123
13123
|
};
|
|
13124
13124
|
};
|
|
13125
13125
|
exports2.renderToReadableStream = function(children, options) {
|
|
13126
|
-
return new Promise(function(
|
|
13126
|
+
return new Promise(function(resolve7, reject) {
|
|
13127
13127
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
13128
13128
|
onAllReady = res;
|
|
13129
13129
|
onFatalError = rej;
|
|
@@ -13173,7 +13173,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13173
13173
|
{ highWaterMark: 0 }
|
|
13174
13174
|
);
|
|
13175
13175
|
stream2.allReady = allReady;
|
|
13176
|
-
|
|
13176
|
+
resolve7(stream2);
|
|
13177
13177
|
},
|
|
13178
13178
|
function(error) {
|
|
13179
13179
|
allReady.catch(function() {
|
|
@@ -13188,7 +13188,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13188
13188
|
});
|
|
13189
13189
|
};
|
|
13190
13190
|
exports2.resume = function(children, postponedState, options) {
|
|
13191
|
-
return new Promise(function(
|
|
13191
|
+
return new Promise(function(resolve7, reject) {
|
|
13192
13192
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
13193
13193
|
onAllReady = res;
|
|
13194
13194
|
onFatalError = rej;
|
|
@@ -13226,7 +13226,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13226
13226
|
{ highWaterMark: 0 }
|
|
13227
13227
|
);
|
|
13228
13228
|
stream2.allReady = allReady;
|
|
13229
|
-
|
|
13229
|
+
resolve7(stream2);
|
|
13230
13230
|
},
|
|
13231
13231
|
function(error) {
|
|
13232
13232
|
allReady.catch(function() {
|
|
@@ -13240,7 +13240,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13240
13240
|
});
|
|
13241
13241
|
};
|
|
13242
13242
|
exports2.resumeAndPrerender = function(children, postponedState, options) {
|
|
13243
|
-
return new Promise(function(
|
|
13243
|
+
return new Promise(function(resolve7, reject) {
|
|
13244
13244
|
var request = resumeAndPrerenderRequest(
|
|
13245
13245
|
children,
|
|
13246
13246
|
postponedState,
|
|
@@ -13272,7 +13272,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13272
13272
|
{ highWaterMark: 0 }
|
|
13273
13273
|
);
|
|
13274
13274
|
stream2 = { postponed: getPostponedState(request), prelude: stream2 };
|
|
13275
|
-
|
|
13275
|
+
resolve7(stream2);
|
|
13276
13276
|
},
|
|
13277
13277
|
void 0,
|
|
13278
13278
|
void 0,
|
|
@@ -13283,7 +13283,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13283
13283
|
});
|
|
13284
13284
|
};
|
|
13285
13285
|
exports2.resumeAndPrerenderToNodeStream = function(children, postponedState, options) {
|
|
13286
|
-
return new Promise(function(
|
|
13286
|
+
return new Promise(function(resolve7, reject) {
|
|
13287
13287
|
var request = resumeAndPrerenderRequest(
|
|
13288
13288
|
children,
|
|
13289
13289
|
postponedState,
|
|
@@ -13304,7 +13304,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13304
13304
|
}
|
|
13305
13305
|
}), writable = createFakeWritableFromReadable(readable);
|
|
13306
13306
|
readable = { postponed: getPostponedState(request), prelude: readable };
|
|
13307
|
-
|
|
13307
|
+
resolve7(readable);
|
|
13308
13308
|
},
|
|
13309
13309
|
void 0,
|
|
13310
13310
|
void 0,
|
|
@@ -28776,7 +28776,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28776
28776
|
ensureCorrectIsomorphicReactVersion();
|
|
28777
28777
|
ensureCorrectIsomorphicReactVersion();
|
|
28778
28778
|
exports2.prerender = function(children, options) {
|
|
28779
|
-
return new Promise(function(
|
|
28779
|
+
return new Promise(function(resolve7, reject) {
|
|
28780
28780
|
var onHeaders = options ? options.onHeaders : void 0, onHeadersImpl;
|
|
28781
28781
|
onHeaders && (onHeadersImpl = function(headersDescriptor) {
|
|
28782
28782
|
onHeaders(new Headers(headersDescriptor));
|
|
@@ -28825,7 +28825,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28825
28825
|
postponed: getPostponedState(request),
|
|
28826
28826
|
prelude: stream2
|
|
28827
28827
|
};
|
|
28828
|
-
|
|
28828
|
+
resolve7(stream2);
|
|
28829
28829
|
},
|
|
28830
28830
|
void 0,
|
|
28831
28831
|
void 0,
|
|
@@ -28836,7 +28836,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28836
28836
|
});
|
|
28837
28837
|
};
|
|
28838
28838
|
exports2.prerenderToNodeStream = function(children, options) {
|
|
28839
|
-
return new Promise(function(
|
|
28839
|
+
return new Promise(function(resolve7, reject) {
|
|
28840
28840
|
var resumableState = createResumableState(
|
|
28841
28841
|
options ? options.identifierPrefix : void 0,
|
|
28842
28842
|
options ? options.unstable_externalRuntimeSrc : void 0,
|
|
@@ -28868,7 +28868,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28868
28868
|
postponed: getPostponedState(request),
|
|
28869
28869
|
prelude: readable
|
|
28870
28870
|
};
|
|
28871
|
-
|
|
28871
|
+
resolve7(readable);
|
|
28872
28872
|
},
|
|
28873
28873
|
void 0,
|
|
28874
28874
|
void 0,
|
|
@@ -28913,7 +28913,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28913
28913
|
};
|
|
28914
28914
|
};
|
|
28915
28915
|
exports2.renderToReadableStream = function(children, options) {
|
|
28916
|
-
return new Promise(function(
|
|
28916
|
+
return new Promise(function(resolve7, reject) {
|
|
28917
28917
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
28918
28918
|
onAllReady = res;
|
|
28919
28919
|
onFatalError = rej;
|
|
@@ -28963,7 +28963,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28963
28963
|
{ highWaterMark: 0 }
|
|
28964
28964
|
);
|
|
28965
28965
|
stream2.allReady = allReady;
|
|
28966
|
-
|
|
28966
|
+
resolve7(stream2);
|
|
28967
28967
|
},
|
|
28968
28968
|
function(error) {
|
|
28969
28969
|
allReady.catch(function() {
|
|
@@ -28978,7 +28978,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28978
28978
|
});
|
|
28979
28979
|
};
|
|
28980
28980
|
exports2.resume = function(children, postponedState, options) {
|
|
28981
|
-
return new Promise(function(
|
|
28981
|
+
return new Promise(function(resolve7, reject) {
|
|
28982
28982
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
28983
28983
|
onAllReady = res;
|
|
28984
28984
|
onFatalError = rej;
|
|
@@ -29016,7 +29016,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29016
29016
|
{ highWaterMark: 0 }
|
|
29017
29017
|
);
|
|
29018
29018
|
stream2.allReady = allReady;
|
|
29019
|
-
|
|
29019
|
+
resolve7(stream2);
|
|
29020
29020
|
},
|
|
29021
29021
|
function(error) {
|
|
29022
29022
|
allReady.catch(function() {
|
|
@@ -29030,7 +29030,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29030
29030
|
});
|
|
29031
29031
|
};
|
|
29032
29032
|
exports2.resumeAndPrerender = function(children, postponedState, options) {
|
|
29033
|
-
return new Promise(function(
|
|
29033
|
+
return new Promise(function(resolve7, reject) {
|
|
29034
29034
|
var request = resumeAndPrerenderRequest(
|
|
29035
29035
|
children,
|
|
29036
29036
|
postponedState,
|
|
@@ -29064,7 +29064,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29064
29064
|
{ highWaterMark: 0 }
|
|
29065
29065
|
);
|
|
29066
29066
|
stream2 = { postponed: getPostponedState(request), prelude: stream2 };
|
|
29067
|
-
|
|
29067
|
+
resolve7(stream2);
|
|
29068
29068
|
},
|
|
29069
29069
|
void 0,
|
|
29070
29070
|
void 0,
|
|
@@ -29075,7 +29075,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29075
29075
|
});
|
|
29076
29076
|
};
|
|
29077
29077
|
exports2.resumeAndPrerenderToNodeStream = function(children, postponedState, options) {
|
|
29078
|
-
return new Promise(function(
|
|
29078
|
+
return new Promise(function(resolve7, reject) {
|
|
29079
29079
|
var request = resumeAndPrerenderRequest(
|
|
29080
29080
|
children,
|
|
29081
29081
|
postponedState,
|
|
@@ -29099,7 +29099,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29099
29099
|
postponed: getPostponedState(request),
|
|
29100
29100
|
prelude: readable
|
|
29101
29101
|
};
|
|
29102
|
-
|
|
29102
|
+
resolve7(readable);
|
|
29103
29103
|
},
|
|
29104
29104
|
void 0,
|
|
29105
29105
|
void 0,
|
|
@@ -29482,9 +29482,9 @@ var require_jsx_runtime = __commonJS({
|
|
|
29482
29482
|
|
|
29483
29483
|
// src/cli.ts
|
|
29484
29484
|
var import_cross_spawn = __toESM(require("cross-spawn"));
|
|
29485
|
-
var
|
|
29486
|
-
var
|
|
29487
|
-
var
|
|
29485
|
+
var import_fs10 = require("fs");
|
|
29486
|
+
var import_os7 = require("os");
|
|
29487
|
+
var import_path10 = require("path");
|
|
29488
29488
|
|
|
29489
29489
|
// src/audit.ts
|
|
29490
29490
|
var import_fs = require("fs");
|
|
@@ -29502,11 +29502,12 @@ function writeAudit(event, homeDir = (0, import_os.homedir)()) {
|
|
|
29502
29502
|
}
|
|
29503
29503
|
|
|
29504
29504
|
// src/composition.ts
|
|
29505
|
-
var
|
|
29505
|
+
var import_os3 = require("os");
|
|
29506
29506
|
|
|
29507
29507
|
// src/config.ts
|
|
29508
29508
|
var import_fs2 = require("fs");
|
|
29509
29509
|
var import_path2 = require("path");
|
|
29510
|
+
var import_os2 = require("os");
|
|
29510
29511
|
var CONFIG_FILE = "mx-env.config.json";
|
|
29511
29512
|
var GLOBAL_CONFIG_DIR = ".mx-env";
|
|
29512
29513
|
var GLOBAL_CONFIG_FILE = "config.json";
|
|
@@ -29534,7 +29535,7 @@ function loadConfigAt(path) {
|
|
|
29534
29535
|
}
|
|
29535
29536
|
function loadConfigLayers(options = {}) {
|
|
29536
29537
|
const cwd = options.cwd || process.cwd();
|
|
29537
|
-
const homeDir = options.homeDir || (0,
|
|
29538
|
+
const homeDir = options.homeDir || (0, import_os2.homedir)();
|
|
29538
29539
|
const globalDir = (0, import_path2.resolve)(homeDir, GLOBAL_CONFIG_DIR);
|
|
29539
29540
|
return {
|
|
29540
29541
|
global: loadConfigAt((0, import_path2.resolve)(globalDir, GLOBAL_CONFIG_FILE)),
|
|
@@ -29549,7 +29550,7 @@ function normalizeProfile(input) {
|
|
|
29549
29550
|
...input?.extends ? { extends: input.extends } : {}
|
|
29550
29551
|
};
|
|
29551
29552
|
}
|
|
29552
|
-
function expandHomePath(path, homeDir = (0,
|
|
29553
|
+
function expandHomePath(path, homeDir = (0, import_os2.homedir)()) {
|
|
29553
29554
|
if (path === "~") return homeDir;
|
|
29554
29555
|
if (path.startsWith("~/")) return (0, import_path2.resolve)(homeDir, path.slice(2));
|
|
29555
29556
|
return path;
|
|
@@ -29580,6 +29581,14 @@ function validateConfig(config, label = CONFIG_FILE) {
|
|
|
29580
29581
|
if (!source.project || !source.config) errors.push(`${label}: Doppler source "${name}" needs project and config`);
|
|
29581
29582
|
if (source.optional) errors.push(`${label}: remote source "${name}" cannot be optional`);
|
|
29582
29583
|
break;
|
|
29584
|
+
case "plugin":
|
|
29585
|
+
if (typeof source.plugin !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(source.plugin)) {
|
|
29586
|
+
errors.push(`${label}: plugin source "${name}" needs a plugin name (letters, digits, ".", "_", "-")`);
|
|
29587
|
+
}
|
|
29588
|
+
if (!Array.isArray(source.keys) || !source.keys.length || source.keys.some((key) => typeof key !== "string" || !key)) {
|
|
29589
|
+
errors.push(`${label}: plugin source "${name}" needs at least one key`);
|
|
29590
|
+
}
|
|
29591
|
+
break;
|
|
29583
29592
|
default:
|
|
29584
29593
|
errors.push(`${label}: source "${name}" has an unsupported provider`);
|
|
29585
29594
|
}
|
|
@@ -29910,6 +29919,31 @@ function resolveDoppler(entry, source, context) {
|
|
|
29910
29919
|
function parseDotenvText(text) {
|
|
29911
29920
|
return (0, import_dotenv3.parse)(text);
|
|
29912
29921
|
}
|
|
29922
|
+
var PLUGIN_TIMEOUT_MS = 3e4;
|
|
29923
|
+
function resolvePlugin(entry, source, context) {
|
|
29924
|
+
const command = `mx-env-provider-${source.plugin}`;
|
|
29925
|
+
const values = {};
|
|
29926
|
+
for (const key of source.keys) {
|
|
29927
|
+
let output;
|
|
29928
|
+
try {
|
|
29929
|
+
output = (0, import_child_process2.execFileSync)(command, [key], {
|
|
29930
|
+
encoding: "utf8",
|
|
29931
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
29932
|
+
env: { ...process.env, ...context.environment },
|
|
29933
|
+
timeout: PLUGIN_TIMEOUT_MS
|
|
29934
|
+
});
|
|
29935
|
+
} catch (error) {
|
|
29936
|
+
if (error?.code === "ENOENT") {
|
|
29937
|
+
if (source.optional) return { name: entry.name, provider: source.provider, values: {}, availability: "missing-optional" };
|
|
29938
|
+
throw new SourceError(entry.name, source.provider, `[morphix-env] plugin source "${entry.name}" needs ${command} on PATH.`);
|
|
29939
|
+
}
|
|
29940
|
+
const reason = typeof error?.code === "string" ? error.code : `exit ${error?.status ?? "unknown"}`;
|
|
29941
|
+
throw new SourceError(entry.name, source.provider, `[morphix-env] plugin source "${entry.name}" failed for key "${key}" (${reason}).`);
|
|
29942
|
+
}
|
|
29943
|
+
values[key] = output.endsWith("\r\n") ? output.slice(0, -2) : output.endsWith("\n") ? output.slice(0, -1) : output;
|
|
29944
|
+
}
|
|
29945
|
+
return { name: entry.name, provider: source.provider, values, availability: "loaded" };
|
|
29946
|
+
}
|
|
29913
29947
|
async function loadSource(entry, context) {
|
|
29914
29948
|
switch (entry.source.provider) {
|
|
29915
29949
|
case "local":
|
|
@@ -29922,6 +29956,8 @@ async function loadSource(entry, context) {
|
|
|
29922
29956
|
return resolveKeychain(entry, entry.source);
|
|
29923
29957
|
case "doppler":
|
|
29924
29958
|
return resolveDoppler(entry, entry.source, context);
|
|
29959
|
+
case "plugin":
|
|
29960
|
+
return resolvePlugin(entry, entry.source, context);
|
|
29925
29961
|
}
|
|
29926
29962
|
}
|
|
29927
29963
|
|
|
@@ -29936,6 +29972,9 @@ var CompositionError = class extends Error {
|
|
|
29936
29972
|
this.name = "CompositionError";
|
|
29937
29973
|
}
|
|
29938
29974
|
};
|
|
29975
|
+
function collectRedactionValues(environment, provenance) {
|
|
29976
|
+
return [...new Set(Object.entries(provenance).filter(([key]) => !isPublicKey(key) && Boolean(environment[key])).map(([key]) => environment[key]).filter(Boolean))];
|
|
29977
|
+
}
|
|
29939
29978
|
function declaredEntries(loaded) {
|
|
29940
29979
|
return new Map(Object.entries(loaded.config.sources || {}).map(([name, source]) => [name, {
|
|
29941
29980
|
name,
|
|
@@ -30045,7 +30084,7 @@ async function composeEnvironment(layers, options = {}) {
|
|
|
30045
30084
|
const environment = { ...options.baseEnvironment || process.env };
|
|
30046
30085
|
const owner = /* @__PURE__ */ new Map();
|
|
30047
30086
|
const sourceStatuses = [];
|
|
30048
|
-
const homeDir = options.homeDir || (0,
|
|
30087
|
+
const homeDir = options.homeDir || (0, import_os3.homedir)();
|
|
30049
30088
|
for (let precedence = 0; precedence < entries.length; precedence++) {
|
|
30050
30089
|
const entry = entries[precedence];
|
|
30051
30090
|
const loaded = await loadSource(entry, {
|
|
@@ -30078,13 +30117,14 @@ async function composeEnvironment(layers, options = {}) {
|
|
|
30078
30117
|
});
|
|
30079
30118
|
}
|
|
30080
30119
|
}
|
|
30120
|
+
const provenance = Object.fromEntries(owner);
|
|
30081
30121
|
return {
|
|
30082
30122
|
environment,
|
|
30083
30123
|
profileName,
|
|
30084
30124
|
sourceStatuses,
|
|
30085
|
-
provenance
|
|
30125
|
+
provenance,
|
|
30086
30126
|
sourceEntries: entries,
|
|
30087
|
-
redactionValues:
|
|
30127
|
+
redactionValues: collectRedactionValues(environment, provenance)
|
|
30088
30128
|
};
|
|
30089
30129
|
}
|
|
30090
30130
|
|
|
@@ -30092,7 +30132,7 @@ async function composeEnvironment(layers, options = {}) {
|
|
|
30092
30132
|
var import_child_process3 = require("child_process");
|
|
30093
30133
|
var import_http = require("http");
|
|
30094
30134
|
var import_fs6 = require("fs");
|
|
30095
|
-
var
|
|
30135
|
+
var import_os4 = require("os");
|
|
30096
30136
|
var import_path6 = require("path");
|
|
30097
30137
|
var import_crypto = require("crypto");
|
|
30098
30138
|
|
|
@@ -36909,7 +36949,7 @@ function localFile(entry, fileIndex = 0) {
|
|
|
36909
36949
|
const source = entry.source;
|
|
36910
36950
|
if (source.provider !== "local" && source.provider !== "dotenvx") throw new Error("Source does not use files");
|
|
36911
36951
|
const raw = source.files[fileIndex];
|
|
36912
|
-
const expanded = expandHomePath(raw, (0,
|
|
36952
|
+
const expanded = expandHomePath(raw, (0, import_os4.homedir)());
|
|
36913
36953
|
return (0, import_path6.isAbsolute)(expanded) ? expanded : (0, import_path6.resolve)(entry.baseDir, expanded);
|
|
36914
36954
|
}
|
|
36915
36955
|
function sourceUrl(entry) {
|
|
@@ -37061,14 +37101,14 @@ async function startEditorServer(encodedState) {
|
|
|
37061
37101
|
});
|
|
37062
37102
|
const closeTimer = setTimeout(() => server.close(), EDITOR_LIFETIME_MS);
|
|
37063
37103
|
closeTimer.unref();
|
|
37064
|
-
await new Promise((
|
|
37104
|
+
await new Promise((resolve7, reject) => {
|
|
37065
37105
|
server.once("error", reject);
|
|
37066
37106
|
server.listen(0, "127.0.0.1", () => {
|
|
37067
37107
|
const address = server.address();
|
|
37068
37108
|
if (!address || typeof address === "string") return reject(new Error("Editor did not receive a loopback port"));
|
|
37069
37109
|
process.stdout.write(`http://127.0.0.1:${address.port}${editorPath(state)}
|
|
37070
37110
|
`);
|
|
37071
|
-
|
|
37111
|
+
resolve7();
|
|
37072
37112
|
});
|
|
37073
37113
|
});
|
|
37074
37114
|
}
|
|
@@ -37089,7 +37129,7 @@ async function launchEditor(entryScript, composition, selectedSource) {
|
|
|
37089
37129
|
detached: true,
|
|
37090
37130
|
stdio: ["ignore", "pipe", "ignore"]
|
|
37091
37131
|
});
|
|
37092
|
-
const url = await new Promise((
|
|
37132
|
+
const url = await new Promise((resolve7, reject) => {
|
|
37093
37133
|
const timer = setTimeout(() => reject(new Error("[morphix-env] Timed out starting local editor.")), 5e3);
|
|
37094
37134
|
child.once("error", () => {
|
|
37095
37135
|
clearTimeout(timer);
|
|
@@ -37099,7 +37139,7 @@ async function launchEditor(entryScript, composition, selectedSource) {
|
|
|
37099
37139
|
clearTimeout(timer);
|
|
37100
37140
|
const url2 = chunk.toString("utf8").trim();
|
|
37101
37141
|
child.stdout?.destroy();
|
|
37102
|
-
|
|
37142
|
+
resolve7(url2);
|
|
37103
37143
|
});
|
|
37104
37144
|
});
|
|
37105
37145
|
child.unref();
|
|
@@ -37182,15 +37222,86 @@ var StreamingRedactor = class {
|
|
|
37182
37222
|
}
|
|
37183
37223
|
};
|
|
37184
37224
|
|
|
37225
|
+
// src/refs.ts
|
|
37226
|
+
var MX_ENV_REFERENCE_SOURCE = "mx-env:\\/\\/([A-Za-z0-9][A-Za-z0-9_-]*)\\/([A-Za-z0-9_][A-Za-z0-9_.-]*)";
|
|
37227
|
+
function referencePattern() {
|
|
37228
|
+
return new RegExp(MX_ENV_REFERENCE_SOURCE, "g");
|
|
37229
|
+
}
|
|
37230
|
+
function findMxEnvReferences(text) {
|
|
37231
|
+
const found = /* @__PURE__ */ new Map();
|
|
37232
|
+
for (const match of text.matchAll(referencePattern())) {
|
|
37233
|
+
const reference = { profile: match[1], key: match[2] };
|
|
37234
|
+
found.set(`${reference.profile}/${reference.key}`, reference);
|
|
37235
|
+
}
|
|
37236
|
+
return [...found.values()];
|
|
37237
|
+
}
|
|
37238
|
+
function hasMxEnvReference(text) {
|
|
37239
|
+
return referencePattern().test(text);
|
|
37240
|
+
}
|
|
37241
|
+
var ReferenceResolver = class {
|
|
37242
|
+
constructor(layers, composeOptions2) {
|
|
37243
|
+
this.layers = layers;
|
|
37244
|
+
this.composeOptions = composeOptions2;
|
|
37245
|
+
this.compositions = /* @__PURE__ */ new Map();
|
|
37246
|
+
}
|
|
37247
|
+
compose(profile) {
|
|
37248
|
+
let pending = this.compositions.get(profile);
|
|
37249
|
+
if (!pending) {
|
|
37250
|
+
pending = composeEnvironment(this.layers, { ...this.composeOptions, profile });
|
|
37251
|
+
this.compositions.set(profile, pending);
|
|
37252
|
+
}
|
|
37253
|
+
return pending;
|
|
37254
|
+
}
|
|
37255
|
+
/**
|
|
37256
|
+
* The value of KEY as `profile` composes it, resolving nested references.
|
|
37257
|
+
* The chain carries `profile/key` tokens of the current resolution path so
|
|
37258
|
+
* only a genuine loop (the same key re-entered) is a cycle — a nested lookup
|
|
37259
|
+
* of a different key in the same profile stays legal.
|
|
37260
|
+
*/
|
|
37261
|
+
async valueOf(profile, key, chain = []) {
|
|
37262
|
+
const token = `${profile}/${key}`;
|
|
37263
|
+
if (chain.includes(token)) return { missing: { profile, key, reason: "cycle" } };
|
|
37264
|
+
let composition;
|
|
37265
|
+
try {
|
|
37266
|
+
composition = await this.compose(profile);
|
|
37267
|
+
} catch {
|
|
37268
|
+
return { missing: { profile, key, reason: "missing" } };
|
|
37269
|
+
}
|
|
37270
|
+
const raw = composition.environment[key];
|
|
37271
|
+
if (raw === void 0 || raw === null) return { missing: { profile, key, reason: "missing" } };
|
|
37272
|
+
if (!hasMxEnvReference(raw)) return { value: raw };
|
|
37273
|
+
const resolved = await this.resolveText(raw, [...chain, token]);
|
|
37274
|
+
if (resolved.missing.length) return { missing: resolved.missing[0] };
|
|
37275
|
+
return { value: resolved.text };
|
|
37276
|
+
}
|
|
37277
|
+
/** Substitutes every resolvable reference; unresolvable ones stay literal. */
|
|
37278
|
+
async resolveText(text, chain = []) {
|
|
37279
|
+
const references = findMxEnvReferences(text);
|
|
37280
|
+
if (!references.length) return { text, missing: [] };
|
|
37281
|
+
const resolved = await Promise.all(references.map(async (reference) => ({
|
|
37282
|
+
reference,
|
|
37283
|
+
result: await this.valueOf(reference.profile, reference.key, chain)
|
|
37284
|
+
})));
|
|
37285
|
+
const values = /* @__PURE__ */ new Map();
|
|
37286
|
+
const missing = [];
|
|
37287
|
+
for (const { reference, result } of resolved) {
|
|
37288
|
+
if (result.value !== void 0) values.set(`${reference.profile}/${reference.key}`, result.value);
|
|
37289
|
+
else if (result.missing) missing.push(result.missing);
|
|
37290
|
+
}
|
|
37291
|
+
const output = text.replace(referencePattern(), (match, profile, key) => values.get(`${profile}/${key}`) ?? match);
|
|
37292
|
+
return { text: output, missing };
|
|
37293
|
+
}
|
|
37294
|
+
};
|
|
37295
|
+
|
|
37185
37296
|
// src/skill.ts
|
|
37186
37297
|
var import_fs7 = require("fs");
|
|
37187
|
-
var
|
|
37298
|
+
var import_os5 = require("os");
|
|
37188
37299
|
var import_path7 = require("path");
|
|
37189
37300
|
var SKILL_TARGETS = ["global", "project", "trellis"];
|
|
37190
37301
|
function resolveSkillPath(target) {
|
|
37191
37302
|
if (target === "project") return (0, import_path7.join)(process.cwd(), ".claude", "skills", "morphix-env", "SKILL.md");
|
|
37192
|
-
if (target === "trellis") return (0, import_path7.join)((0,
|
|
37193
|
-
return (0, import_path7.join)((0,
|
|
37303
|
+
if (target === "trellis") return (0, import_path7.join)((0, import_os5.homedir)(), ".trellis", "skills", "morphix-env", "SKILL.md");
|
|
37304
|
+
return (0, import_path7.join)((0, import_os5.homedir)(), ".claude", "skills", "morphix-env", "SKILL.md");
|
|
37194
37305
|
}
|
|
37195
37306
|
function targetHint(target) {
|
|
37196
37307
|
if (target === "project") {
|
|
@@ -37252,10 +37363,418 @@ function cmdSkill(subcommand, options) {
|
|
|
37252
37363
|
return 0;
|
|
37253
37364
|
}
|
|
37254
37365
|
|
|
37366
|
+
// src/serve.ts
|
|
37367
|
+
var import_http2 = require("http");
|
|
37368
|
+
var import_crypto2 = require("crypto");
|
|
37369
|
+
function authorized(req, token) {
|
|
37370
|
+
const header = req.headers.authorization;
|
|
37371
|
+
const presented = typeof header === "string" && header.startsWith("Bearer ") ? Buffer.from(header.slice("Bearer ".length)) : Buffer.alloc(0);
|
|
37372
|
+
return presented.length === token.length && (0, import_crypto2.timingSafeEqual)(presented, token);
|
|
37373
|
+
}
|
|
37374
|
+
async function startSecretServer(values) {
|
|
37375
|
+
const token = (0, import_crypto2.randomBytes)(24).toString("base64url");
|
|
37376
|
+
const tokenBuffer = Buffer.from(token);
|
|
37377
|
+
const server = (0, import_http2.createServer)((req, res) => {
|
|
37378
|
+
if (!authorized(req, tokenBuffer)) {
|
|
37379
|
+
res.writeHead(401, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37380
|
+
res.end("unauthorized");
|
|
37381
|
+
return;
|
|
37382
|
+
}
|
|
37383
|
+
const path = (req.url || "").split("?")[0];
|
|
37384
|
+
if (req.method !== "GET") {
|
|
37385
|
+
res.writeHead(405, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37386
|
+
res.end("method not allowed");
|
|
37387
|
+
return;
|
|
37388
|
+
}
|
|
37389
|
+
const match = /^\/key\/(.+)$/.exec(path);
|
|
37390
|
+
if (!match) {
|
|
37391
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37392
|
+
res.end("not found");
|
|
37393
|
+
return;
|
|
37394
|
+
}
|
|
37395
|
+
let key;
|
|
37396
|
+
try {
|
|
37397
|
+
key = decodeURIComponent(match[1]);
|
|
37398
|
+
} catch {
|
|
37399
|
+
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37400
|
+
res.end("bad request");
|
|
37401
|
+
return;
|
|
37402
|
+
}
|
|
37403
|
+
if (!Object.prototype.hasOwnProperty.call(values, key)) {
|
|
37404
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37405
|
+
res.end("unknown key");
|
|
37406
|
+
return;
|
|
37407
|
+
}
|
|
37408
|
+
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37409
|
+
res.end(values[key]);
|
|
37410
|
+
});
|
|
37411
|
+
await new Promise((resolvePromise, reject) => {
|
|
37412
|
+
server.once("error", reject);
|
|
37413
|
+
server.listen(0, "127.0.0.1", () => {
|
|
37414
|
+
server.removeListener("error", reject);
|
|
37415
|
+
server.on("error", (error) => {
|
|
37416
|
+
console.error(`[morphix-env] Secret server error: ${error instanceof Error ? error.message : "unknown"}`);
|
|
37417
|
+
});
|
|
37418
|
+
resolvePromise();
|
|
37419
|
+
});
|
|
37420
|
+
});
|
|
37421
|
+
const address = server.address();
|
|
37422
|
+
if (!address || typeof address === "string") {
|
|
37423
|
+
server.close();
|
|
37424
|
+
throw new Error("[morphix-env] Secret server did not receive a loopback port.");
|
|
37425
|
+
}
|
|
37426
|
+
let closed = false;
|
|
37427
|
+
return {
|
|
37428
|
+
endpoint: `http://127.0.0.1:${address.port}`,
|
|
37429
|
+
token,
|
|
37430
|
+
close: () => {
|
|
37431
|
+
if (closed) return;
|
|
37432
|
+
closed = true;
|
|
37433
|
+
server.close();
|
|
37434
|
+
const withConnections = server;
|
|
37435
|
+
if (typeof withConnections.closeAllConnections === "function") withConnections.closeAllConnections();
|
|
37436
|
+
}
|
|
37437
|
+
};
|
|
37438
|
+
}
|
|
37439
|
+
|
|
37440
|
+
// src/shims.ts
|
|
37441
|
+
var import_fs8 = require("fs");
|
|
37442
|
+
var import_os6 = require("os");
|
|
37443
|
+
var import_path8 = require("path");
|
|
37444
|
+
var SHIM_MARKER = "# mx-env shim \u2014 regenerated by `mx-env shell-init`; do not edit by hand.";
|
|
37445
|
+
var RESERVED_SHIM_NAMES = [
|
|
37446
|
+
"run",
|
|
37447
|
+
"fetch",
|
|
37448
|
+
"export",
|
|
37449
|
+
"render",
|
|
37450
|
+
"inject",
|
|
37451
|
+
"generate",
|
|
37452
|
+
"gen",
|
|
37453
|
+
"inspect",
|
|
37454
|
+
"audit",
|
|
37455
|
+
"edit",
|
|
37456
|
+
"doc",
|
|
37457
|
+
"skill",
|
|
37458
|
+
"shell-init",
|
|
37459
|
+
"help",
|
|
37460
|
+
"mx-env",
|
|
37461
|
+
"morphix-env",
|
|
37462
|
+
"__mx_editor"
|
|
37463
|
+
];
|
|
37464
|
+
var SHIM_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
37465
|
+
function shimsDir(homeDir = (0, import_os6.homedir)()) {
|
|
37466
|
+
return (0, import_path8.join)(homeDir, ".mx-env", "shims");
|
|
37467
|
+
}
|
|
37468
|
+
function validateShimList(list, label) {
|
|
37469
|
+
if (list === void 0 || list === null) return [];
|
|
37470
|
+
if (!Array.isArray(list)) return [`${label}: "shims" must be an array of command names`];
|
|
37471
|
+
const errors = [];
|
|
37472
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37473
|
+
for (const entry of list) {
|
|
37474
|
+
if (typeof entry !== "string" || !entry) {
|
|
37475
|
+
errors.push(`${label}: shim entries must be non-empty command names`);
|
|
37476
|
+
continue;
|
|
37477
|
+
}
|
|
37478
|
+
if (!SHIM_NAME_PATTERN.test(entry)) {
|
|
37479
|
+
errors.push(`${label}: shim entry "${entry}" must be a bare command name (letters, digits, ".", "_", "-"; no path separators or whitespace)`);
|
|
37480
|
+
continue;
|
|
37481
|
+
}
|
|
37482
|
+
const lower = entry.toLowerCase();
|
|
37483
|
+
if (RESERVED_SHIM_NAMES.includes(lower)) {
|
|
37484
|
+
errors.push(`${label}: shim entry "${entry}" conflicts with a reserved mx-env command name`);
|
|
37485
|
+
continue;
|
|
37486
|
+
}
|
|
37487
|
+
if (seen.has(lower)) {
|
|
37488
|
+
errors.push(`${label}: duplicate shim entry "${entry}" (comparison is case-insensitive)`);
|
|
37489
|
+
continue;
|
|
37490
|
+
}
|
|
37491
|
+
seen.add(lower);
|
|
37492
|
+
}
|
|
37493
|
+
return errors;
|
|
37494
|
+
}
|
|
37495
|
+
function resolveShimCommands(layers, includeGlobal = true) {
|
|
37496
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37497
|
+
const commands = [];
|
|
37498
|
+
const push = (list) => {
|
|
37499
|
+
if (!Array.isArray(list)) return;
|
|
37500
|
+
for (const entry of list) {
|
|
37501
|
+
if (typeof entry !== "string") continue;
|
|
37502
|
+
const lower = entry.toLowerCase();
|
|
37503
|
+
if (seen.has(lower)) continue;
|
|
37504
|
+
seen.add(lower);
|
|
37505
|
+
commands.push(entry);
|
|
37506
|
+
}
|
|
37507
|
+
};
|
|
37508
|
+
if (includeGlobal) push(layers.global.config.shims);
|
|
37509
|
+
push(layers.project.config.shims);
|
|
37510
|
+
return commands;
|
|
37511
|
+
}
|
|
37512
|
+
function renderShimScript(command) {
|
|
37513
|
+
return `#!/bin/sh
|
|
37514
|
+
${SHIM_MARKER}
|
|
37515
|
+
command -v mx-env >/dev/null 2>&1 || { echo "[mx-env] mx-env not on PATH; reinstall morphix-env or run 'mx-env shell-init --remove' to clean up this shim." >&2; exit 127; }
|
|
37516
|
+
MXENV_SHIM=1 exec mx-env run -- ${command} "$@"
|
|
37517
|
+
`;
|
|
37518
|
+
}
|
|
37519
|
+
function readIfExists(path) {
|
|
37520
|
+
try {
|
|
37521
|
+
return (0, import_fs8.readFileSync)(path, "utf8");
|
|
37522
|
+
} catch {
|
|
37523
|
+
return null;
|
|
37524
|
+
}
|
|
37525
|
+
}
|
|
37526
|
+
function writeShims(commands, homeDir = (0, import_os6.homedir)()) {
|
|
37527
|
+
const dir = shimsDir(homeDir);
|
|
37528
|
+
(0, import_fs8.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
37529
|
+
const wanted = new Set(commands.map((command) => command.toLowerCase()));
|
|
37530
|
+
const written = [];
|
|
37531
|
+
const removed = [];
|
|
37532
|
+
const skipped = [];
|
|
37533
|
+
for (const file of (0, import_fs8.readdirSync)(dir)) {
|
|
37534
|
+
const path = (0, import_path8.join)(dir, file);
|
|
37535
|
+
const content = readIfExists(path);
|
|
37536
|
+
if (content === null || !content.includes(SHIM_MARKER)) continue;
|
|
37537
|
+
if (!wanted.has(file.toLowerCase())) {
|
|
37538
|
+
(0, import_fs8.rmSync)(path);
|
|
37539
|
+
removed.push(file);
|
|
37540
|
+
}
|
|
37541
|
+
}
|
|
37542
|
+
for (const command of commands) {
|
|
37543
|
+
const path = (0, import_path8.join)(dir, command);
|
|
37544
|
+
const content = renderShimScript(command);
|
|
37545
|
+
let isSymlink = false;
|
|
37546
|
+
try {
|
|
37547
|
+
isSymlink = (0, import_fs8.lstatSync)(path).isSymbolicLink();
|
|
37548
|
+
} catch {
|
|
37549
|
+
}
|
|
37550
|
+
const existing = isSymlink ? null : readIfExists(path);
|
|
37551
|
+
if (!isSymlink && existing !== null && !existing.includes(SHIM_MARKER)) {
|
|
37552
|
+
skipped.push(command);
|
|
37553
|
+
continue;
|
|
37554
|
+
}
|
|
37555
|
+
if (isSymlink) (0, import_fs8.rmSync)(path);
|
|
37556
|
+
else if (existing === content) continue;
|
|
37557
|
+
(0, import_fs8.writeFileSync)(path, content, { mode: 493 });
|
|
37558
|
+
(0, import_fs8.chmodSync)(path, 493);
|
|
37559
|
+
written.push(command);
|
|
37560
|
+
}
|
|
37561
|
+
return { written, removed, skipped };
|
|
37562
|
+
}
|
|
37563
|
+
function removeAllShims(homeDir = (0, import_os6.homedir)()) {
|
|
37564
|
+
const dir = shimsDir(homeDir);
|
|
37565
|
+
if (!(0, import_fs8.existsSync)(dir)) return [];
|
|
37566
|
+
const removed = [];
|
|
37567
|
+
for (const file of (0, import_fs8.readdirSync)(dir)) {
|
|
37568
|
+
const path = (0, import_path8.join)(dir, file);
|
|
37569
|
+
const content = readIfExists(path);
|
|
37570
|
+
if (content !== null && content.includes(SHIM_MARKER)) {
|
|
37571
|
+
(0, import_fs8.rmSync)(path);
|
|
37572
|
+
removed.push(file);
|
|
37573
|
+
}
|
|
37574
|
+
}
|
|
37575
|
+
return removed;
|
|
37576
|
+
}
|
|
37577
|
+
function detectHandmadeReservedShims(homeDir = (0, import_os6.homedir)()) {
|
|
37578
|
+
const dir = shimsDir(homeDir);
|
|
37579
|
+
if (!(0, import_fs8.existsSync)(dir)) return [];
|
|
37580
|
+
const found = [];
|
|
37581
|
+
for (const file of (0, import_fs8.readdirSync)(dir)) {
|
|
37582
|
+
if (!RESERVED_SHIM_NAMES.includes(file.toLowerCase())) continue;
|
|
37583
|
+
const content = readIfExists((0, import_path8.join)(dir, file));
|
|
37584
|
+
if (content === null || !content.includes(SHIM_MARKER)) found.push(file);
|
|
37585
|
+
}
|
|
37586
|
+
return found;
|
|
37587
|
+
}
|
|
37588
|
+
var RC_BLOCK_BEGIN = "# >>> mx-env shims >>>";
|
|
37589
|
+
var RC_BLOCK_END = "# <<< mx-env shims <<<";
|
|
37590
|
+
function rcBlock(homeDir = (0, import_os6.homedir)()) {
|
|
37591
|
+
const dir = shimsDir(homeDir);
|
|
37592
|
+
if (/["$`\\]/.test(dir)) {
|
|
37593
|
+
throw new Error("[morphix-env] Shims directory path contains characters that are unsafe in a shell rc line.");
|
|
37594
|
+
}
|
|
37595
|
+
return `${RC_BLOCK_BEGIN}
|
|
37596
|
+
export PATH="${dir}:$PATH"
|
|
37597
|
+
${RC_BLOCK_END}`;
|
|
37598
|
+
}
|
|
37599
|
+
function defaultRcPath(shell, homeDir = (0, import_os6.homedir)()) {
|
|
37600
|
+
const name = shell ? shell.split("/").pop() : "";
|
|
37601
|
+
if (name === "zsh") return (0, import_path8.join)(homeDir, ".zshrc");
|
|
37602
|
+
if (name === "bash") return (0, import_path8.join)(homeDir, ".bashrc");
|
|
37603
|
+
return null;
|
|
37604
|
+
}
|
|
37605
|
+
function writeFileAtomic(path, content) {
|
|
37606
|
+
const tmp = `${path}.mx-env-${process.pid}.tmp`;
|
|
37607
|
+
(0, import_fs8.writeFileSync)(tmp, content);
|
|
37608
|
+
(0, import_fs8.renameSync)(tmp, path);
|
|
37609
|
+
}
|
|
37610
|
+
function upsertRcBlock(rcPath, homeDir = (0, import_os6.homedir)()) {
|
|
37611
|
+
const existing = readIfExists(rcPath) ?? "";
|
|
37612
|
+
const block = rcBlock(homeDir);
|
|
37613
|
+
const pattern = new RegExp(`${escapeRegExp(RC_BLOCK_BEGIN)}[\\s\\S]*?${escapeRegExp(RC_BLOCK_END)}`, "g");
|
|
37614
|
+
if (pattern.test(existing)) {
|
|
37615
|
+
const replaced = existing.replace(pattern, block);
|
|
37616
|
+
if (replaced === existing) return "unchanged";
|
|
37617
|
+
writeFileAtomic(rcPath, replaced.endsWith("\n") ? replaced : `${replaced}
|
|
37618
|
+
`);
|
|
37619
|
+
return "updated";
|
|
37620
|
+
}
|
|
37621
|
+
const separator = existing.length && !existing.endsWith("\n") ? "\n" : "";
|
|
37622
|
+
writeFileAtomic(rcPath, `${existing}${separator}${block}
|
|
37623
|
+
`);
|
|
37624
|
+
return "added";
|
|
37625
|
+
}
|
|
37626
|
+
function removeRcBlock(rcPath) {
|
|
37627
|
+
const existing = readIfExists(rcPath);
|
|
37628
|
+
if (existing === null) return "absent";
|
|
37629
|
+
const pattern = new RegExp(`\\n?${escapeRegExp(RC_BLOCK_BEGIN)}[\\s\\S]*?${escapeRegExp(RC_BLOCK_END)}\\n?`, "g");
|
|
37630
|
+
if (!pattern.test(existing)) return "absent";
|
|
37631
|
+
writeFileAtomic(rcPath, existing.replace(pattern, "\n"));
|
|
37632
|
+
return "removed";
|
|
37633
|
+
}
|
|
37634
|
+
function escapeRegExp(text) {
|
|
37635
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
37636
|
+
}
|
|
37637
|
+
function stripShimsFromPath(pathValue, homeDir = (0, import_os6.homedir)()) {
|
|
37638
|
+
if (!pathValue) return pathValue;
|
|
37639
|
+
const target = shimsDir(homeDir);
|
|
37640
|
+
let targetReal = target;
|
|
37641
|
+
try {
|
|
37642
|
+
targetReal = (0, import_fs8.realpathSync)(target);
|
|
37643
|
+
} catch {
|
|
37644
|
+
}
|
|
37645
|
+
const equal = (a, b) => process.platform === "darwin" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
37646
|
+
const entries = pathValue.split(import_path8.delimiter).filter((entry) => {
|
|
37647
|
+
if (!entry) return true;
|
|
37648
|
+
const literal = entry.replace(/\/+$/, "");
|
|
37649
|
+
let resolved = literal;
|
|
37650
|
+
try {
|
|
37651
|
+
resolved = (0, import_fs8.realpathSync)(literal);
|
|
37652
|
+
} catch {
|
|
37653
|
+
}
|
|
37654
|
+
return !equal(literal, target) && !equal(resolved, targetReal);
|
|
37655
|
+
});
|
|
37656
|
+
return entries.join(import_path8.delimiter);
|
|
37657
|
+
}
|
|
37658
|
+
function sanitizeBootEnv(env = process.env, homeDir) {
|
|
37659
|
+
const originalPath = env.PATH;
|
|
37660
|
+
const viaShim = env.MXENV_SHIM === "1";
|
|
37661
|
+
try {
|
|
37662
|
+
const home = homeDir ?? (0, import_os6.homedir)();
|
|
37663
|
+
const stripped = stripShimsFromPath(originalPath, home);
|
|
37664
|
+
if (stripped !== originalPath) {
|
|
37665
|
+
if (stripped) env.PATH = stripped;
|
|
37666
|
+
else delete env.PATH;
|
|
37667
|
+
}
|
|
37668
|
+
} catch {
|
|
37669
|
+
}
|
|
37670
|
+
delete env.MXENV_SHIM;
|
|
37671
|
+
return { viaShim, originalPath };
|
|
37672
|
+
}
|
|
37673
|
+
function findShadowedCommands(commands, originalPath, homeDir = (0, import_os6.homedir)()) {
|
|
37674
|
+
if (!originalPath) return { absent: [...commands], shadowed: [] };
|
|
37675
|
+
const dirs = originalPath.split(import_path8.delimiter).filter(Boolean);
|
|
37676
|
+
const absent = [];
|
|
37677
|
+
const shadowed = [];
|
|
37678
|
+
for (const command of commands) {
|
|
37679
|
+
const shimPath = (0, import_path8.join)(shimsDir(homeDir), command);
|
|
37680
|
+
let resolvedTo = null;
|
|
37681
|
+
for (const dir of dirs) {
|
|
37682
|
+
const candidate = (0, import_path8.join)(dir, command);
|
|
37683
|
+
try {
|
|
37684
|
+
(0, import_fs8.accessSync)(candidate, import_fs8.constants.X_OK);
|
|
37685
|
+
resolvedTo = candidate;
|
|
37686
|
+
break;
|
|
37687
|
+
} catch {
|
|
37688
|
+
}
|
|
37689
|
+
}
|
|
37690
|
+
const samePath = (a, b) => process.platform === "darwin" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
37691
|
+
if (resolvedTo === null) absent.push(command);
|
|
37692
|
+
else if (!samePath(resolvedTo, shimPath)) shadowed.push(command);
|
|
37693
|
+
}
|
|
37694
|
+
return { absent, shadowed };
|
|
37695
|
+
}
|
|
37696
|
+
|
|
37697
|
+
// src/template.ts
|
|
37698
|
+
var import_child_process4 = require("child_process");
|
|
37699
|
+
var import_fs9 = require("fs");
|
|
37700
|
+
var import_path9 = require("path");
|
|
37701
|
+
function shellQuote(value) {
|
|
37702
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
37703
|
+
}
|
|
37704
|
+
function isShellIdentifier(key) {
|
|
37705
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
37706
|
+
}
|
|
37707
|
+
function findTemplateAnomalies(text) {
|
|
37708
|
+
const anomalies = [];
|
|
37709
|
+
const dollarDollar = text.indexOf("$$");
|
|
37710
|
+
if (dollarDollar >= 0) {
|
|
37711
|
+
anomalies.push(`Escaped dollar $$ at offset ${dollarDollar} is not interpolated; left literal.`);
|
|
37712
|
+
}
|
|
37713
|
+
let index2 = text.indexOf("${");
|
|
37714
|
+
while (index2 >= 0) {
|
|
37715
|
+
const rest = text.slice(index2);
|
|
37716
|
+
if (/^\$\{[A-Za-z_][A-Za-z0-9_]*\}/.test(rest)) {
|
|
37717
|
+
} else if (/^\$\{[A-Za-z_][A-Za-z0-9_]*[:+=-]/.test(rest)) {
|
|
37718
|
+
anomalies.push(`Unsupported \${...} modifier or default at offset ${index2}; only \${NAME} is substituted \u2014 left literal.`);
|
|
37719
|
+
} else {
|
|
37720
|
+
anomalies.push(`Unclosed or invalid \${ at offset ${index2}; left literal.`);
|
|
37721
|
+
}
|
|
37722
|
+
index2 = text.indexOf("${", index2 + 2);
|
|
37723
|
+
}
|
|
37724
|
+
return anomalies;
|
|
37725
|
+
}
|
|
37726
|
+
function templateVariablePattern() {
|
|
37727
|
+
return /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
37728
|
+
}
|
|
37729
|
+
function findTemplateVariables(text) {
|
|
37730
|
+
const names = /* @__PURE__ */ new Set();
|
|
37731
|
+
for (const match of text.matchAll(templateVariablePattern())) names.add(match[1]);
|
|
37732
|
+
return [...names];
|
|
37733
|
+
}
|
|
37734
|
+
function renderTemplate(text, environment) {
|
|
37735
|
+
const missing = /* @__PURE__ */ new Set();
|
|
37736
|
+
const output = text.replace(templateVariablePattern(), (match, name) => {
|
|
37737
|
+
const value = environment[name];
|
|
37738
|
+
if (value === void 0 || value === null) {
|
|
37739
|
+
missing.add(name);
|
|
37740
|
+
return match;
|
|
37741
|
+
}
|
|
37742
|
+
return value;
|
|
37743
|
+
});
|
|
37744
|
+
return { output, missing: [...missing] };
|
|
37745
|
+
}
|
|
37746
|
+
function writePrivateFile(path, content) {
|
|
37747
|
+
const absolute = (0, import_path9.resolve)(path);
|
|
37748
|
+
(0, import_fs9.mkdirSync)((0, import_path9.dirname)(absolute), { recursive: true, mode: 448 });
|
|
37749
|
+
(0, import_fs9.writeFileSync)(absolute, content, { mode: 384 });
|
|
37750
|
+
(0, import_fs9.chmodSync)(absolute, 384);
|
|
37751
|
+
}
|
|
37752
|
+
function gitOutputStatus(path) {
|
|
37753
|
+
const absolute = (0, import_path9.resolve)(path);
|
|
37754
|
+
const cwd = (0, import_path9.dirname)(absolute);
|
|
37755
|
+
const name = (0, import_path9.basename)(absolute);
|
|
37756
|
+
const inside = (0, import_child_process4.spawnSync)("git", ["rev-parse", "--is-inside-work-tree"], { cwd, encoding: "utf8" });
|
|
37757
|
+
if (inside.status !== 0) return "outside-repo";
|
|
37758
|
+
const tracked = (0, import_child_process4.spawnSync)("git", ["ls-files", "--error-unmatch", "--", name], { cwd, encoding: "utf8" });
|
|
37759
|
+
if (tracked.status === 0) return "tracked";
|
|
37760
|
+
const ignored = (0, import_child_process4.spawnSync)("git", ["check-ignore", "-q", "--", name], { cwd, encoding: "utf8" });
|
|
37761
|
+
if (ignored.status === 0) return "ignored";
|
|
37762
|
+
if (ignored.status === 1) return "untracked";
|
|
37763
|
+
return "outside-repo";
|
|
37764
|
+
}
|
|
37765
|
+
function warnOutputGitRisk(path) {
|
|
37766
|
+
const status = gitOutputStatus(path);
|
|
37767
|
+
if (status === "tracked") {
|
|
37768
|
+
console.warn(`[morphix-env] Warning: ${path} is tracked by git; a rendered value could be committed. Add it to .gitignore and untrack it.`);
|
|
37769
|
+
} else if (status === "untracked") {
|
|
37770
|
+
console.warn(`[morphix-env] Warning: ${path} is not git-ignored; add it to .gitignore before committing.`);
|
|
37771
|
+
}
|
|
37772
|
+
}
|
|
37773
|
+
|
|
37255
37774
|
// package.json
|
|
37256
37775
|
var package_default = {
|
|
37257
37776
|
name: "morphix-env",
|
|
37258
|
-
version: "0.
|
|
37777
|
+
version: "0.9.0",
|
|
37259
37778
|
description: "Secret composition CLI \u2014 Infisical, Doppler, macOS Keychain, dotenvx, and local files stay value owners; composes them into one value-safe child environment and ships a built-in Agent Skill (mx-env skill install).",
|
|
37260
37779
|
author: "MorphixAI <dev@morphixai.com>",
|
|
37261
37780
|
homepage: "https://github.com/Morphicai/morphix-env#readme",
|
|
@@ -37270,9 +37789,22 @@ var package_default = {
|
|
|
37270
37789
|
"morphix-env": "./dist/cli.js",
|
|
37271
37790
|
"mx-env": "./dist/cli.js"
|
|
37272
37791
|
},
|
|
37792
|
+
main: "./dist/index.js",
|
|
37793
|
+
types: "./dist/index.d.ts",
|
|
37794
|
+
exports: {
|
|
37795
|
+
".": {
|
|
37796
|
+
types: "./dist/index.d.ts",
|
|
37797
|
+
default: "./dist/index.js"
|
|
37798
|
+
},
|
|
37799
|
+
"./cli": {
|
|
37800
|
+
types: "./dist/cli.d.ts",
|
|
37801
|
+
default: "./dist/cli.js"
|
|
37802
|
+
},
|
|
37803
|
+
"./package.json": "./package.json"
|
|
37804
|
+
},
|
|
37273
37805
|
scripts: {
|
|
37274
|
-
build: "node scripts/build-editor-ui.mjs && tsup src/cli.ts --format cjs --dts --clean --external keytar && node scripts/copy-skill.mjs",
|
|
37275
|
-
dev: "node scripts/build-editor-ui.mjs && tsup src/cli.ts --format cjs --watch",
|
|
37806
|
+
build: "node scripts/build-editor-ui.mjs && tsup src/cli.ts src/index.ts --format cjs --dts --clean --external keytar && node scripts/copy-skill.mjs",
|
|
37807
|
+
dev: "node scripts/build-editor-ui.mjs && tsup src/cli.ts src/index.ts --format cjs --watch",
|
|
37276
37808
|
pretest: "pnpm build",
|
|
37277
37809
|
test: "vitest run",
|
|
37278
37810
|
"test:watch": "vitest",
|
|
@@ -37334,6 +37866,7 @@ function parseArgs(argv) {
|
|
|
37334
37866
|
const args = {
|
|
37335
37867
|
command: "",
|
|
37336
37868
|
subArgs: [],
|
|
37869
|
+
positionals: [],
|
|
37337
37870
|
envFiles: [],
|
|
37338
37871
|
outFile: null,
|
|
37339
37872
|
verbose: false,
|
|
@@ -37346,7 +37879,12 @@ function parseArgs(argv) {
|
|
|
37346
37879
|
printEditorUrl: false,
|
|
37347
37880
|
source: null,
|
|
37348
37881
|
target: null,
|
|
37349
|
-
force: false
|
|
37882
|
+
force: false,
|
|
37883
|
+
dryRun: false,
|
|
37884
|
+
serve: false,
|
|
37885
|
+
write: false,
|
|
37886
|
+
remove: false,
|
|
37887
|
+
unknownFlags: []
|
|
37350
37888
|
};
|
|
37351
37889
|
let i = 2;
|
|
37352
37890
|
const command = argv[i];
|
|
@@ -37385,28 +37923,60 @@ function parseArgs(argv) {
|
|
|
37385
37923
|
if (argv[++i]) args.target = argv[i];
|
|
37386
37924
|
} else if (arg === "--force") {
|
|
37387
37925
|
args.force = true;
|
|
37926
|
+
} else if (arg === "--dry-run") {
|
|
37927
|
+
args.dryRun = true;
|
|
37928
|
+
} else if (arg === "--write") {
|
|
37929
|
+
args.write = true;
|
|
37930
|
+
} else if (arg === "--remove") {
|
|
37931
|
+
args.remove = true;
|
|
37932
|
+
} else if (arg === "--serve") {
|
|
37933
|
+
args.serve = true;
|
|
37388
37934
|
} else if (args.command === "run") {
|
|
37389
37935
|
args.subArgs = argv.slice(i);
|
|
37390
37936
|
break;
|
|
37937
|
+
} else if (!arg.startsWith("-")) {
|
|
37938
|
+
args.positionals.push(arg);
|
|
37939
|
+
} else {
|
|
37940
|
+
args.unknownFlags.push(arg);
|
|
37391
37941
|
}
|
|
37392
37942
|
i++;
|
|
37393
37943
|
}
|
|
37394
37944
|
return args;
|
|
37395
37945
|
}
|
|
37396
|
-
function
|
|
37397
|
-
|
|
37398
|
-
|
|
37946
|
+
function configLayers() {
|
|
37947
|
+
return loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os7.homedir)() });
|
|
37948
|
+
}
|
|
37949
|
+
function composeOptions(args) {
|
|
37950
|
+
return {
|
|
37399
37951
|
profile: args.profile,
|
|
37400
37952
|
noGlobal: args.noGlobal,
|
|
37401
37953
|
noInfisical: args.noInfisical,
|
|
37402
37954
|
envName: args.env,
|
|
37403
37955
|
allowInsecureGlobal: args.allowInsecureGlobal,
|
|
37404
37956
|
envFiles: args.envFiles,
|
|
37405
|
-
homeDir: (0,
|
|
37406
|
-
}
|
|
37957
|
+
homeDir: (0, import_os7.homedir)()
|
|
37958
|
+
};
|
|
37959
|
+
}
|
|
37960
|
+
var bootInfo = { viaShim: false };
|
|
37961
|
+
var shimWarned = false;
|
|
37962
|
+
function warnInvalidShims(layers, includeGlobal) {
|
|
37963
|
+
if (shimWarned) return;
|
|
37964
|
+
shimWarned = true;
|
|
37965
|
+
const problems = [
|
|
37966
|
+
...includeGlobal ? validateShimList(layers.global.config.shims, layers.global.path) : [],
|
|
37967
|
+
...validateShimList(layers.project.config.shims, layers.project.path)
|
|
37968
|
+
];
|
|
37969
|
+
if (problems.length) {
|
|
37970
|
+
console.warn(`[morphix-env] Ignoring invalid "shims" entries (${problems.length} problem(s)); run \`mx-env shell-init\` for the details.`);
|
|
37971
|
+
}
|
|
37972
|
+
}
|
|
37973
|
+
function resolveComposition(args) {
|
|
37974
|
+
const layers = configLayers();
|
|
37975
|
+
warnInvalidShims(layers, !args.noGlobal);
|
|
37976
|
+
return composeEnvironment(layers, composeOptions(args));
|
|
37407
37977
|
}
|
|
37408
37978
|
function generatedOptions(args) {
|
|
37409
|
-
const config = loadConfigLayers({ cwd: process.cwd(), homeDir: (0,
|
|
37979
|
+
const config = loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os7.homedir)() }).project.config;
|
|
37410
37980
|
return {
|
|
37411
37981
|
outFile: args.outFile || config.generate?.out || "public/__env.js",
|
|
37412
37982
|
filter: args.filter || config.generate?.filter || null
|
|
@@ -37415,12 +37985,15 @@ function generatedOptions(args) {
|
|
|
37415
37985
|
function generateClientEnv(outFile, filter, environment) {
|
|
37416
37986
|
let vars = extractPublicVars(environment);
|
|
37417
37987
|
if (filter) vars = Object.fromEntries(Object.entries(vars).filter(([key]) => key.startsWith(filter)));
|
|
37418
|
-
(0,
|
|
37419
|
-
(0,
|
|
37988
|
+
(0, import_fs10.mkdirSync)((0, import_path10.dirname)(outFile), { recursive: true });
|
|
37989
|
+
(0, import_fs10.writeFileSync)(outFile, `window.__ENV=${JSON.stringify(vars)};`);
|
|
37420
37990
|
console.log(`[morphix-env] Generated ${outFile} (${Object.keys(vars).length} client vars)`);
|
|
37421
37991
|
}
|
|
37422
37992
|
async function runChild(command, commandArgs, composition) {
|
|
37423
|
-
return new Promise((
|
|
37993
|
+
return new Promise((resolve7) => {
|
|
37994
|
+
if (composition.environment.PATH) {
|
|
37995
|
+
composition.environment.PATH = stripShimsFromPath(composition.environment.PATH) ?? composition.environment.PATH;
|
|
37996
|
+
}
|
|
37424
37997
|
const child = (0, import_cross_spawn.default)(command, commandArgs, { env: composition.environment, stdio: ["inherit", "pipe", "pipe"] });
|
|
37425
37998
|
const stdout = new StreamingRedactor(composition.redactionValues);
|
|
37426
37999
|
const stderr = new StreamingRedactor(composition.redactionValues);
|
|
@@ -37428,14 +38001,14 @@ async function runChild(command, commandArgs, composition) {
|
|
|
37428
38001
|
child.stderr?.on("data", (chunk) => process.stderr.write(stderr.write(chunk)));
|
|
37429
38002
|
child.on("error", () => {
|
|
37430
38003
|
console.error(`[morphix-env] Failed to execute: ${command}`);
|
|
37431
|
-
|
|
38004
|
+
resolve7(1);
|
|
37432
38005
|
});
|
|
37433
38006
|
child.on("close", (code) => {
|
|
37434
38007
|
const stdoutFinal = stdout.flush();
|
|
37435
38008
|
const stderrFinal = stderr.flush();
|
|
37436
38009
|
if (stdoutFinal) process.stdout.write(stdoutFinal);
|
|
37437
38010
|
if (stderrFinal) process.stderr.write(stderrFinal);
|
|
37438
|
-
|
|
38011
|
+
resolve7(code ?? 1);
|
|
37439
38012
|
});
|
|
37440
38013
|
});
|
|
37441
38014
|
}
|
|
@@ -37447,9 +38020,53 @@ function writeRunAudit(composition, startedAt, outcome, exitCode) {
|
|
|
37447
38020
|
keys: Object.keys(composition.provenance).sort(),
|
|
37448
38021
|
outcome,
|
|
37449
38022
|
exitCode,
|
|
37450
|
-
durationMs: Date.now() - startedAt
|
|
38023
|
+
durationMs: Date.now() - startedAt,
|
|
38024
|
+
via: bootInfo.viaShim ? "shim" : "cli"
|
|
37451
38025
|
});
|
|
37452
38026
|
}
|
|
38027
|
+
async function startServeFor(composition, verbose) {
|
|
38028
|
+
const values = {};
|
|
38029
|
+
for (const key of Object.keys(composition.provenance)) {
|
|
38030
|
+
const value = composition.environment[key];
|
|
38031
|
+
if (value !== void 0) values[key] = value;
|
|
38032
|
+
}
|
|
38033
|
+
const server = await startSecretServer(values);
|
|
38034
|
+
for (const key of Object.keys(values)) {
|
|
38035
|
+
if (!isPublicKey(key)) delete composition.environment[key];
|
|
38036
|
+
}
|
|
38037
|
+
composition.environment.MXENV_ENDPOINT = server.endpoint;
|
|
38038
|
+
composition.environment.MXENV_TOKEN = server.token;
|
|
38039
|
+
composition.redactionValues = [.../* @__PURE__ */ new Set([...composition.redactionValues, server.token])];
|
|
38040
|
+
if (verbose) {
|
|
38041
|
+
console.error(`[morphix-env] Secret server listening on ${server.endpoint} (${Object.keys(values).length} keys; token is visible to the child only).`);
|
|
38042
|
+
}
|
|
38043
|
+
return server;
|
|
38044
|
+
}
|
|
38045
|
+
function warnUnresolvedReference(reference, context) {
|
|
38046
|
+
console.warn(`[morphix-env] Unresolved mx-env://${reference.profile}/${reference.key} reference ${context} (${reference.reason}); left as-is.`);
|
|
38047
|
+
}
|
|
38048
|
+
async function resolveEnvironmentReferences(composition, args) {
|
|
38049
|
+
const targets = Object.entries(composition.environment).filter((entry) => typeof entry[1] === "string" && hasMxEnvReference(entry[1]));
|
|
38050
|
+
if (!targets.length) return;
|
|
38051
|
+
const resolver = new ReferenceResolver(configLayers(), composeOptions(args));
|
|
38052
|
+
const changed = [];
|
|
38053
|
+
for (const [key, value] of targets) {
|
|
38054
|
+
const resolved = await resolver.resolveText(value);
|
|
38055
|
+
if (resolved.missing.length) {
|
|
38056
|
+
for (const reference of resolved.missing) warnUnresolvedReference(reference, `in key "${key}"`);
|
|
38057
|
+
continue;
|
|
38058
|
+
}
|
|
38059
|
+
composition.environment[key] = resolved.text;
|
|
38060
|
+
changed.push(key);
|
|
38061
|
+
}
|
|
38062
|
+
if (changed.length) {
|
|
38063
|
+
const extra = changed.map((key) => composition.environment[key]).filter((value) => Boolean(value));
|
|
38064
|
+
composition.redactionValues = [.../* @__PURE__ */ new Set([
|
|
38065
|
+
...collectRedactionValues(composition.environment, composition.provenance),
|
|
38066
|
+
...extra
|
|
38067
|
+
])];
|
|
38068
|
+
}
|
|
38069
|
+
}
|
|
37453
38070
|
async function cmdRun(args) {
|
|
37454
38071
|
if (!args.subArgs.length) {
|
|
37455
38072
|
console.error("[morphix-env] No command specified. Usage: mx-env run -- <command>");
|
|
@@ -37462,18 +38079,72 @@ async function cmdRun(args) {
|
|
|
37462
38079
|
console.log(`[morphix-env] ${source.name}: ${source.availability} (${source.keyCount} keys)`);
|
|
37463
38080
|
}
|
|
37464
38081
|
}
|
|
38082
|
+
if (args.dryRun) {
|
|
38083
|
+
console.log(`profile: ${composition.profileName}`);
|
|
38084
|
+
for (const key of Object.keys(composition.provenance).sort()) console.log(` ${key}`);
|
|
38085
|
+
return 0;
|
|
38086
|
+
}
|
|
38087
|
+
await resolveEnvironmentReferences(composition, args);
|
|
37465
38088
|
if (args.outFile || generatedOptions(args).outFile) {
|
|
37466
38089
|
const { outFile, filter } = generatedOptions(args);
|
|
37467
|
-
const configured = Boolean(args.outFile || loadConfigLayers({ cwd: process.cwd(), homeDir: (0,
|
|
38090
|
+
const configured = Boolean(args.outFile || loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os7.homedir)() }).project.config.generate);
|
|
37468
38091
|
if (configured) generateClientEnv(outFile, filter, composition.environment);
|
|
37469
38092
|
}
|
|
37470
38093
|
const [command, ...commandArgs] = args.subArgs;
|
|
37471
|
-
const
|
|
37472
|
-
|
|
37473
|
-
|
|
38094
|
+
const secretServer = args.serve ? await startServeFor(composition, args.verbose) : null;
|
|
38095
|
+
try {
|
|
38096
|
+
const exitCode = await runChild(command, commandArgs, composition);
|
|
38097
|
+
writeRunAudit(composition, startedAt, exitCode === 0 ? "success" : "failure", exitCode);
|
|
38098
|
+
return exitCode;
|
|
38099
|
+
} finally {
|
|
38100
|
+
secretServer?.close();
|
|
38101
|
+
}
|
|
38102
|
+
}
|
|
38103
|
+
async function cmdFetch(args) {
|
|
38104
|
+
const key = args.positionals[0];
|
|
38105
|
+
if (!key) {
|
|
38106
|
+
console.error("[morphix-env] Usage: mx-env fetch <key-name>");
|
|
38107
|
+
return 1;
|
|
38108
|
+
}
|
|
38109
|
+
const endpoint = process.env.MXENV_ENDPOINT;
|
|
38110
|
+
const token = process.env.MXENV_TOKEN;
|
|
38111
|
+
if (!endpoint || !token) {
|
|
38112
|
+
console.error('[morphix-env] mx-env fetch needs MXENV_ENDPOINT and MXENV_TOKEN; run it inside "mx-env run --serve -- <command>".');
|
|
38113
|
+
return 1;
|
|
38114
|
+
}
|
|
38115
|
+
let endpointUrl;
|
|
38116
|
+
try {
|
|
38117
|
+
endpointUrl = new URL(endpoint);
|
|
38118
|
+
} catch {
|
|
38119
|
+
console.error("[morphix-env] MXENV_ENDPOINT is not a valid URL.");
|
|
38120
|
+
return 1;
|
|
38121
|
+
}
|
|
38122
|
+
if (!["127.0.0.1", "localhost", "[::1]"].includes(endpointUrl.hostname)) {
|
|
38123
|
+
console.error("[morphix-env] MXENV_ENDPOINT is not a loopback address; refusing to send the fetch token off-machine.");
|
|
38124
|
+
return 1;
|
|
38125
|
+
}
|
|
38126
|
+
try {
|
|
38127
|
+
const response = await fetch(`${endpoint}/key/${encodeURIComponent(key)}`, {
|
|
38128
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
38129
|
+
});
|
|
38130
|
+
if (response.ok) {
|
|
38131
|
+
process.stdout.write(await response.text());
|
|
38132
|
+
return 0;
|
|
38133
|
+
}
|
|
38134
|
+
if (response.status === 404) {
|
|
38135
|
+
console.error(`[morphix-env] Unknown key on the secret server: ${key}`);
|
|
38136
|
+
return 1;
|
|
38137
|
+
}
|
|
38138
|
+
console.error(`[morphix-env] Secret server rejected the request (HTTP ${response.status}).`);
|
|
38139
|
+
return 1;
|
|
38140
|
+
} catch {
|
|
38141
|
+
console.error("[morphix-env] Secret server is unreachable; the parent process may have exited.");
|
|
38142
|
+
return 1;
|
|
38143
|
+
}
|
|
37474
38144
|
}
|
|
37475
38145
|
async function cmdGenerate(args) {
|
|
37476
38146
|
const composition = await resolveComposition(args);
|
|
38147
|
+
await resolveEnvironmentReferences(composition, args);
|
|
37477
38148
|
const { outFile, filter } = generatedOptions(args);
|
|
37478
38149
|
generateClientEnv(outFile, filter, composition.environment);
|
|
37479
38150
|
if (args.verbose) {
|
|
@@ -37495,6 +38166,94 @@ async function cmdInspect(args) {
|
|
|
37495
38166
|
}
|
|
37496
38167
|
return 0;
|
|
37497
38168
|
}
|
|
38169
|
+
async function cmdExport(args) {
|
|
38170
|
+
const startedAt = Date.now();
|
|
38171
|
+
const composition = await resolveComposition(args);
|
|
38172
|
+
const keys = Object.keys(composition.provenance).sort();
|
|
38173
|
+
if (args.dryRun) {
|
|
38174
|
+
for (const key of keys) console.log(key);
|
|
38175
|
+
return 0;
|
|
38176
|
+
}
|
|
38177
|
+
await resolveEnvironmentReferences(composition, args);
|
|
38178
|
+
for (const key of keys) {
|
|
38179
|
+
if (!isShellIdentifier(key)) {
|
|
38180
|
+
console.warn(`[morphix-env] Warning: key "${key}" is not a valid shell identifier; skipped in export output.`);
|
|
38181
|
+
continue;
|
|
38182
|
+
}
|
|
38183
|
+
console.log(`export ${key}=${shellQuote(composition.environment[key] ?? "")}`);
|
|
38184
|
+
}
|
|
38185
|
+
writeRunAudit(composition, startedAt, "success", 0);
|
|
38186
|
+
return 0;
|
|
38187
|
+
}
|
|
38188
|
+
async function cmdRender(args) {
|
|
38189
|
+
const startedAt = Date.now();
|
|
38190
|
+
const [templatePath, outPath] = args.positionals;
|
|
38191
|
+
if (!templatePath || !outPath) {
|
|
38192
|
+
console.error("[morphix-env] Usage: mx-env render <template-file> <output-file> [options]");
|
|
38193
|
+
return 1;
|
|
38194
|
+
}
|
|
38195
|
+
if (!(0, import_fs10.existsSync)(templatePath)) {
|
|
38196
|
+
console.error(`[morphix-env] Template not found: ${templatePath}`);
|
|
38197
|
+
return 1;
|
|
38198
|
+
}
|
|
38199
|
+
const template = (0, import_fs10.readFileSync)(templatePath, "utf8");
|
|
38200
|
+
const composition = await resolveComposition(args);
|
|
38201
|
+
const names = findTemplateVariables(template);
|
|
38202
|
+
const missing = names.filter((name) => composition.environment[name] === void 0 || composition.environment[name] === null);
|
|
38203
|
+
if (missing.length) console.warn(`[morphix-env] Missing variables: ${missing.join(", ")} (left unresolved)`);
|
|
38204
|
+
for (const anomaly of findTemplateAnomalies(template)) console.warn(`[morphix-env] ${anomaly}`);
|
|
38205
|
+
if (args.dryRun) {
|
|
38206
|
+
for (const name of names) console.log(`${name}: ${missing.includes(name) ? "missing" : "resolved"}`);
|
|
38207
|
+
return 0;
|
|
38208
|
+
}
|
|
38209
|
+
await resolveEnvironmentReferences(composition, args);
|
|
38210
|
+
const { output } = renderTemplate(template, composition.environment);
|
|
38211
|
+
warnOutputGitRisk(outPath);
|
|
38212
|
+
writePrivateFile(outPath, output);
|
|
38213
|
+
writeRunAudit(composition, startedAt, "success", 0);
|
|
38214
|
+
console.log(`[morphix-env] Rendered ${templatePath} -> ${outPath} (${names.length} variables, ${missing.length} unresolved)`);
|
|
38215
|
+
return 0;
|
|
38216
|
+
}
|
|
38217
|
+
async function cmdInject(args) {
|
|
38218
|
+
const startedAt = Date.now();
|
|
38219
|
+
const [templatePath, outPath] = args.positionals;
|
|
38220
|
+
if (!templatePath || !outPath) {
|
|
38221
|
+
console.error("[morphix-env] Usage: mx-env inject <template-file> <output-file> [options]");
|
|
38222
|
+
return 1;
|
|
38223
|
+
}
|
|
38224
|
+
if (!(0, import_fs10.existsSync)(templatePath)) {
|
|
38225
|
+
console.error(`[morphix-env] Template not found: ${templatePath}`);
|
|
38226
|
+
return 1;
|
|
38227
|
+
}
|
|
38228
|
+
const template = (0, import_fs10.readFileSync)(templatePath, "utf8");
|
|
38229
|
+
const layers = configLayers();
|
|
38230
|
+
warnInvalidShims(layers, !args.noGlobal);
|
|
38231
|
+
const resolver = new ReferenceResolver(layers, composeOptions(args));
|
|
38232
|
+
const references = findMxEnvReferences(template);
|
|
38233
|
+
if (args.dryRun) {
|
|
38234
|
+
for (const reference of references) {
|
|
38235
|
+
const result = await resolver.valueOf(reference.profile, reference.key);
|
|
38236
|
+
const status = result.value !== void 0 ? "resolved" : result.missing?.reason ?? "missing";
|
|
38237
|
+
console.log(`${reference.profile}/${reference.key}: ${status}`);
|
|
38238
|
+
}
|
|
38239
|
+
return 0;
|
|
38240
|
+
}
|
|
38241
|
+
const resolved = await resolver.resolveText(template);
|
|
38242
|
+
for (const reference of resolved.missing) warnUnresolvedReference(reference, `in ${templatePath}`);
|
|
38243
|
+
warnOutputGitRisk(outPath);
|
|
38244
|
+
writePrivateFile(outPath, resolved.text);
|
|
38245
|
+
writeAudit({
|
|
38246
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38247
|
+
profile: [...new Set(references.map((reference) => reference.profile))].join(",") || "none",
|
|
38248
|
+
sources: [],
|
|
38249
|
+
keys: [...new Set(references.map((reference) => reference.key))].sort(),
|
|
38250
|
+
outcome: "success",
|
|
38251
|
+
exitCode: 0,
|
|
38252
|
+
durationMs: Date.now() - startedAt
|
|
38253
|
+
});
|
|
38254
|
+
console.log(`[morphix-env] Injected ${templatePath} -> ${outPath} (${references.length} references, ${resolved.missing.length} unresolved)`);
|
|
38255
|
+
return 0;
|
|
38256
|
+
}
|
|
37498
38257
|
async function cmdEdit(args) {
|
|
37499
38258
|
if (!args.profile && !args.source) {
|
|
37500
38259
|
console.error("[morphix-env] Specify --profile <name> or --source <name> to open the editor.");
|
|
@@ -37502,7 +38261,7 @@ async function cmdEdit(args) {
|
|
|
37502
38261
|
}
|
|
37503
38262
|
const composition = await resolveComposition(args);
|
|
37504
38263
|
if (args.source && !composition.sourceEntries.some((entry) => entry.name === args.source)) {
|
|
37505
|
-
const layers = loadConfigLayers({ cwd: process.cwd(), homeDir: (0,
|
|
38264
|
+
const layers = loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os7.homedir)() });
|
|
37506
38265
|
const declared = layers.project.config.sources?.[args.source] ? { source: layers.project.config.sources[args.source], baseDir: layers.project.baseDir } : !args.noGlobal && layers.global.config.sources?.[args.source] ? { source: layers.global.config.sources[args.source], baseDir: layers.global.baseDir } : null;
|
|
37507
38266
|
if (!declared) {
|
|
37508
38267
|
console.error(`[morphix-env] Unknown source "${args.source}".`);
|
|
@@ -37520,7 +38279,7 @@ async function cmdEdit(args) {
|
|
|
37520
38279
|
}
|
|
37521
38280
|
async function cmdDoc(args) {
|
|
37522
38281
|
const composition = await resolveComposition(args);
|
|
37523
|
-
const outFile = args.outFile || (0,
|
|
38282
|
+
const outFile = args.outFile || (0, import_path10.join)(process.cwd(), ".agents", "skills", "morphix-env", "SKILL.md");
|
|
37524
38283
|
const keyRows = Object.entries(composition.provenance).sort(([a], [b]) => a.localeCompare(b)).map(([key, provenance]) => `| \`${key}\` | ${provenance.source} (${provenance.provider}) |`).join("\n") || "| _No resolved keys_ | \u2014 |";
|
|
37525
38284
|
const skill = `---
|
|
37526
38285
|
name: morphix-env
|
|
@@ -37554,18 +38313,90 @@ ${keyRows}
|
|
|
37554
38313
|
|
|
37555
38314
|
Secret values and value prefixes do not belong in this Skill, command output, audit records, or conversation context.
|
|
37556
38315
|
`;
|
|
37557
|
-
(0,
|
|
37558
|
-
(0,
|
|
38316
|
+
(0, import_fs10.mkdirSync)((0, import_path10.dirname)(outFile), { recursive: true });
|
|
38317
|
+
(0, import_fs10.writeFileSync)(outFile, skill, { mode: 384 });
|
|
37559
38318
|
console.log(`[morphix-env] Generated value-free workflow Skill: ${outFile}`);
|
|
37560
38319
|
return 0;
|
|
37561
38320
|
}
|
|
38321
|
+
function cmdShellInit(args) {
|
|
38322
|
+
if (process.platform === "win32") {
|
|
38323
|
+
console.error("[morphix-env] shell-init is supported on macOS/Linux only; on Windows keep using explicit `mx-env run -- <command>`.");
|
|
38324
|
+
return 1;
|
|
38325
|
+
}
|
|
38326
|
+
if (args.unknownFlags.length) {
|
|
38327
|
+
console.error(`[morphix-env] shell-init: unrecognized flag(s): ${args.unknownFlags.join(", ")}`);
|
|
38328
|
+
return 1;
|
|
38329
|
+
}
|
|
38330
|
+
if (args.write && args.remove) {
|
|
38331
|
+
console.error("[morphix-env] shell-init: --write and --remove are mutually exclusive.");
|
|
38332
|
+
return 1;
|
|
38333
|
+
}
|
|
38334
|
+
try {
|
|
38335
|
+
return runShellInit(args);
|
|
38336
|
+
} catch (error) {
|
|
38337
|
+
const code = error?.code;
|
|
38338
|
+
console.error(`[morphix-env] shell-init failed${code ? ` (${code})` : ""}: check that your home directory and rc file are writable, then retry.`);
|
|
38339
|
+
return 1;
|
|
38340
|
+
}
|
|
38341
|
+
}
|
|
38342
|
+
function runShellInit(args) {
|
|
38343
|
+
const layers = configLayers();
|
|
38344
|
+
const home = (0, import_os7.homedir)();
|
|
38345
|
+
const rcPath = defaultRcPath(process.env.SHELL, home);
|
|
38346
|
+
if (args.remove) {
|
|
38347
|
+
const removed2 = removeAllShims(home);
|
|
38348
|
+
const rcOutcome = rcPath ? removeRcBlock(rcPath) : "absent";
|
|
38349
|
+
console.log(`[morphix-env] Removed ${removed2.length} shim(s)${removed2.length ? ` (${removed2.join(", ")})` : ""}; rc block ${rcOutcome}${rcPath ? ` in ${rcPath}` : ""}.`);
|
|
38350
|
+
return 0;
|
|
38351
|
+
}
|
|
38352
|
+
const problems = [
|
|
38353
|
+
...validateShimList(layers.global.config.shims, layers.global.path),
|
|
38354
|
+
...validateShimList(layers.project.config.shims, layers.project.path)
|
|
38355
|
+
];
|
|
38356
|
+
if (problems.length) {
|
|
38357
|
+
for (const problem of problems) console.error(`[morphix-env] ${problem}`);
|
|
38358
|
+
return 1;
|
|
38359
|
+
}
|
|
38360
|
+
const commands = resolveShimCommands(layers, !args.noGlobal);
|
|
38361
|
+
const { written, removed, skipped } = writeShims(commands, home);
|
|
38362
|
+
console.log(`[morphix-env] Shims ready in ${shimsDir(home)} (${commands.length} command(s): ${commands.join(", ") || "none"}; ${written.length} written, ${removed.length} removed).`);
|
|
38363
|
+
for (const command of skipped) {
|
|
38364
|
+
console.warn(`[morphix-env] Warning: "${command}" exists in the shims directory as a handmade file (no mx-env marker); refusing to overwrite. Remove or rename it by hand, then re-run shell-init.`);
|
|
38365
|
+
}
|
|
38366
|
+
for (const file of detectHandmadeReservedShims(home)) {
|
|
38367
|
+
console.warn(`[morphix-env] Warning: "${file}" in the shims directory was not created by mx-env and shadows a reserved command; delete it by hand. Do not place files in ${shimsDir(home)} manually.`);
|
|
38368
|
+
}
|
|
38369
|
+
const { absent, shadowed } = findShadowedCommands(commands, bootInfo.originalPath, home);
|
|
38370
|
+
if (absent.length) {
|
|
38371
|
+
console.warn(`[morphix-env] Note: ${absent.join(", ")} cannot be resolved on the current PATH yet \u2014 add the shims directory (below) and open a new shell.`);
|
|
38372
|
+
}
|
|
38373
|
+
if (shadowed.length) {
|
|
38374
|
+
console.warn(`[morphix-env] Warning: these commands resolve to a different executable ahead of their shim: ${shadowed.join(", ")} \u2014 move ${shimsDir(home)} ahead of the entries that provide them.`);
|
|
38375
|
+
}
|
|
38376
|
+
if (args.write) {
|
|
38377
|
+
if (!rcPath) {
|
|
38378
|
+
console.error("[morphix-env] shell-init: cannot infer an rc file from $SHELL (zsh/bash supported); add the PATH line manually.");
|
|
38379
|
+
return 1;
|
|
38380
|
+
}
|
|
38381
|
+
const outcome = upsertRcBlock(rcPath, home);
|
|
38382
|
+
console.log(`[morphix-env] rc block ${outcome} in ${rcPath}. Open a new shell to activate.`);
|
|
38383
|
+
return 0;
|
|
38384
|
+
}
|
|
38385
|
+
console.log(`
|
|
38386
|
+
Add the shims directory to PATH${rcPath ? ` (e.g. in ${rcPath})` : ""}:
|
|
38387
|
+
|
|
38388
|
+
export PATH="${shimsDir(home)}:$PATH"
|
|
38389
|
+
|
|
38390
|
+
Or re-run with --write to let mx-env maintain a marked block in your rc file.`);
|
|
38391
|
+
return 0;
|
|
38392
|
+
}
|
|
37562
38393
|
function cmdAudit(args) {
|
|
37563
|
-
const file = (0,
|
|
37564
|
-
if (!(0,
|
|
38394
|
+
const file = (0, import_path10.join)((0, import_os7.homedir)(), ".mx-env", "audit", `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
38395
|
+
if (!(0, import_fs10.existsSync)(file)) {
|
|
37565
38396
|
console.log("[morphix-env] No audit events for today.");
|
|
37566
38397
|
return 0;
|
|
37567
38398
|
}
|
|
37568
|
-
const lines = (0,
|
|
38399
|
+
const lines = (0, import_fs10.readFileSync)(file, "utf8").trim().split("\n").filter(Boolean);
|
|
37569
38400
|
const selected = args.subArgs[0] === "tail" ? lines.slice(-20) : lines;
|
|
37570
38401
|
for (const line of selected) console.log(line);
|
|
37571
38402
|
return 0;
|
|
@@ -37576,6 +38407,10 @@ morphix-env v${VERSION} \u2014 secret composition and environment delivery
|
|
|
37576
38407
|
|
|
37577
38408
|
Usage:
|
|
37578
38409
|
mx-env run [options] -- <command> Compose env + execute command
|
|
38410
|
+
mx-env fetch <key-name> Print one value from a run --serve secret server
|
|
38411
|
+
mx-env export [options] Print eval-able export KEY='value' lines
|
|
38412
|
+
mx-env render <template> <output> Substitute \${VAR} into a file (mode 0600)
|
|
38413
|
+
mx-env inject <template> <output> Resolve mx-env:// references into a file (mode 0600)
|
|
37579
38414
|
mx-env generate [options] Generate public __env.js
|
|
37580
38415
|
mx-env inspect [options] Print key names, sources, and status only
|
|
37581
38416
|
mx-env doc [options] Generate a value-free project Skill
|
|
@@ -37583,6 +38418,7 @@ Usage:
|
|
|
37583
38418
|
mx-env edit --profile <name> Open the one-shot visual editor
|
|
37584
38419
|
mx-env skill install [--target <t>] Install the Agent Skill (global|project|trellis)
|
|
37585
38420
|
mx-env skill show Show skill install status per target
|
|
38421
|
+
mx-env shell-init [--write|--remove] Generate PATH shims for declared commands
|
|
37586
38422
|
|
|
37587
38423
|
Both mx-env and morphix-env are supported.
|
|
37588
38424
|
|
|
@@ -37592,6 +38428,8 @@ Options:
|
|
|
37592
38428
|
-e, --env <name> Infisical environment override
|
|
37593
38429
|
-o, --out <path> Client __env.js output
|
|
37594
38430
|
--filter <prefix> Include public keys with this prefix
|
|
38431
|
+
--serve Keep composed values out of env; serve them to the child over loopback
|
|
38432
|
+
--dry-run Report key/variable names only, never values
|
|
37595
38433
|
--no-infisical Do not load Infisical sources
|
|
37596
38434
|
--no-global Ignore ~/.mx-env/.env and ~/.mx-env/config.json
|
|
37597
38435
|
--allow-insecure-global Allow a global .env with permissive file mode
|
|
@@ -37604,10 +38442,19 @@ Options:
|
|
|
37604
38442
|
`);
|
|
37605
38443
|
}
|
|
37606
38444
|
async function main() {
|
|
38445
|
+
Object.assign(bootInfo, sanitizeBootEnv());
|
|
37607
38446
|
const args = parseArgs(process.argv);
|
|
37608
38447
|
switch (args.command) {
|
|
37609
38448
|
case "run":
|
|
37610
38449
|
return cmdRun(args);
|
|
38450
|
+
case "fetch":
|
|
38451
|
+
return cmdFetch(args);
|
|
38452
|
+
case "export":
|
|
38453
|
+
return cmdExport(args);
|
|
38454
|
+
case "render":
|
|
38455
|
+
return cmdRender(args);
|
|
38456
|
+
case "inject":
|
|
38457
|
+
return cmdInject(args);
|
|
37611
38458
|
case "generate":
|
|
37612
38459
|
case "gen":
|
|
37613
38460
|
return cmdGenerate(args);
|
|
@@ -37619,6 +38466,8 @@ async function main() {
|
|
|
37619
38466
|
return cmdEdit(args);
|
|
37620
38467
|
case "doc":
|
|
37621
38468
|
return cmdDoc(args);
|
|
38469
|
+
case "shell-init":
|
|
38470
|
+
return cmdShellInit(args);
|
|
37622
38471
|
case "skill": {
|
|
37623
38472
|
const positional = process.argv.slice(3).find((arg) => !arg.startsWith("-")) ?? "install";
|
|
37624
38473
|
return cmdSkill(positional, { target: args.target, force: args.force });
|