@learnrudi/cli 1.3.0 → 1.5.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.
Files changed (2) hide show
  1. package/dist/index.cjs +445 -196
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -199,6 +199,16 @@ __export(src_exports, {
199
199
  searchPackages: () => searchPackages,
200
200
  verifyHash: () => verifyHash
201
201
  });
202
+ function getLocalRegistryPaths() {
203
+ if (process.env.USE_LOCAL_REGISTRY !== "true") {
204
+ return [];
205
+ }
206
+ return [
207
+ import_path2.default.join(process.cwd(), "registry", "index.json"),
208
+ import_path2.default.join(process.cwd(), "..", "registry", "index.json"),
209
+ "/Users/hoff/dev/RUDI/registry/index.json"
210
+ ];
211
+ }
202
212
  async function fetchIndex(options = {}) {
203
213
  const { url = DEFAULT_REGISTRY_URL, force = false } = options;
204
214
  const localResult = getLocalIndex();
@@ -276,7 +286,7 @@ function getCacheMtime() {
276
286
  }
277
287
  }
278
288
  function getLocalIndex() {
279
- for (const localPath of LOCAL_REGISTRY_PATHS) {
289
+ for (const localPath of getLocalRegistryPaths()) {
280
290
  if (import_fs2.default.existsSync(localPath)) {
281
291
  try {
282
292
  const index = JSON.parse(import_fs2.default.readFileSync(localPath, "utf-8"));
@@ -367,7 +377,7 @@ function getPackageKinds() {
367
377
  async function downloadPackage(pkg, destPath, options = {}) {
368
378
  const { onProgress } = options;
369
379
  const registryPath = pkg.path;
370
- for (const basePath of LOCAL_REGISTRY_PATHS) {
380
+ for (const basePath of getLocalRegistryPaths()) {
371
381
  const registryDir = import_path2.default.dirname(basePath);
372
382
  const pkgSourcePath = import_path2.default.join(registryDir, registryPath);
373
383
  if (import_fs2.default.existsSync(pkgSourcePath)) {
@@ -608,7 +618,7 @@ async function extractBinaryFromPath(extractedPath, binaryPattern, destPath) {
608
618
  }
609
619
  }
610
620
  async function loadToolManifest(toolName) {
611
- for (const basePath of LOCAL_REGISTRY_PATHS) {
621
+ for (const basePath of getLocalRegistryPaths()) {
612
622
  const registryDir = import_path2.default.dirname(basePath);
613
623
  const manifestPath = import_path2.default.join(registryDir, "catalog", "binaries", `${toolName}.json`);
614
624
  if (import_fs2.default.existsSync(manifestPath)) {
@@ -676,7 +686,7 @@ async function copyDirectory(src, dest) {
676
686
  }
677
687
  }
678
688
  }
679
- var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, LOCAL_REGISTRY_PATHS, PACKAGE_KINDS2, KIND_PLURALS, RUNTIMES_RELEASE_VERSION;
689
+ var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, PACKAGE_KINDS2, KIND_PLURALS, RUNTIMES_RELEASE_VERSION;
680
690
  var init_src2 = __esm({
681
691
  "../packages/registry-client/src/index.js"() {
682
692
  import_fs2 = __toESM(require("fs"), 1);
@@ -686,11 +696,6 @@ var init_src2 = __esm({
686
696
  DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/learn-rudi/registry/main/index.json";
687
697
  RUNTIMES_DOWNLOAD_BASE = "https://github.com/learn-rudi/registry/releases/download";
688
698
  CACHE_TTL = 24 * 60 * 60 * 1e3;
689
- LOCAL_REGISTRY_PATHS = process.env.USE_LOCAL_REGISTRY === "true" ? [
690
- import_path2.default.join(process.cwd(), "registry", "index.json"),
691
- import_path2.default.join(process.cwd(), "..", "registry", "index.json"),
692
- "/Users/hoff/dev/RUDI/registry/index.json"
693
- ] : [];
694
699
  PACKAGE_KINDS2 = ["stack", "prompt", "runtime", "binary", "agent"];
695
700
  KIND_PLURALS = {
696
701
  binary: "binaries"
@@ -776,17 +781,17 @@ var require_visit = __commonJS({
776
781
  visit.BREAK = BREAK;
777
782
  visit.SKIP = SKIP;
778
783
  visit.REMOVE = REMOVE;
779
- function visit_(key, node, visitor, path17) {
780
- const ctrl = callVisitor(key, node, visitor, path17);
784
+ function visit_(key, node, visitor, path18) {
785
+ const ctrl = callVisitor(key, node, visitor, path18);
781
786
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
782
- replaceNode(key, path17, ctrl);
783
- return visit_(key, ctrl, visitor, path17);
787
+ replaceNode(key, path18, ctrl);
788
+ return visit_(key, ctrl, visitor, path18);
784
789
  }
785
790
  if (typeof ctrl !== "symbol") {
786
791
  if (identity.isCollection(node)) {
787
- path17 = Object.freeze(path17.concat(node));
792
+ path18 = Object.freeze(path18.concat(node));
788
793
  for (let i = 0; i < node.items.length; ++i) {
789
- const ci = visit_(i, node.items[i], visitor, path17);
794
+ const ci = visit_(i, node.items[i], visitor, path18);
790
795
  if (typeof ci === "number")
791
796
  i = ci - 1;
792
797
  else if (ci === BREAK)
@@ -797,13 +802,13 @@ var require_visit = __commonJS({
797
802
  }
798
803
  }
799
804
  } else if (identity.isPair(node)) {
800
- path17 = Object.freeze(path17.concat(node));
801
- const ck = visit_("key", node.key, visitor, path17);
805
+ path18 = Object.freeze(path18.concat(node));
806
+ const ck = visit_("key", node.key, visitor, path18);
802
807
  if (ck === BREAK)
803
808
  return BREAK;
804
809
  else if (ck === REMOVE)
805
810
  node.key = null;
806
- const cv = visit_("value", node.value, visitor, path17);
811
+ const cv = visit_("value", node.value, visitor, path18);
807
812
  if (cv === BREAK)
808
813
  return BREAK;
809
814
  else if (cv === REMOVE)
@@ -824,17 +829,17 @@ var require_visit = __commonJS({
824
829
  visitAsync.BREAK = BREAK;
825
830
  visitAsync.SKIP = SKIP;
826
831
  visitAsync.REMOVE = REMOVE;
827
- async function visitAsync_(key, node, visitor, path17) {
828
- const ctrl = await callVisitor(key, node, visitor, path17);
832
+ async function visitAsync_(key, node, visitor, path18) {
833
+ const ctrl = await callVisitor(key, node, visitor, path18);
829
834
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
830
- replaceNode(key, path17, ctrl);
831
- return visitAsync_(key, ctrl, visitor, path17);
835
+ replaceNode(key, path18, ctrl);
836
+ return visitAsync_(key, ctrl, visitor, path18);
832
837
  }
833
838
  if (typeof ctrl !== "symbol") {
834
839
  if (identity.isCollection(node)) {
835
- path17 = Object.freeze(path17.concat(node));
840
+ path18 = Object.freeze(path18.concat(node));
836
841
  for (let i = 0; i < node.items.length; ++i) {
837
- const ci = await visitAsync_(i, node.items[i], visitor, path17);
842
+ const ci = await visitAsync_(i, node.items[i], visitor, path18);
838
843
  if (typeof ci === "number")
839
844
  i = ci - 1;
840
845
  else if (ci === BREAK)
@@ -845,13 +850,13 @@ var require_visit = __commonJS({
845
850
  }
846
851
  }
847
852
  } else if (identity.isPair(node)) {
848
- path17 = Object.freeze(path17.concat(node));
849
- const ck = await visitAsync_("key", node.key, visitor, path17);
853
+ path18 = Object.freeze(path18.concat(node));
854
+ const ck = await visitAsync_("key", node.key, visitor, path18);
850
855
  if (ck === BREAK)
851
856
  return BREAK;
852
857
  else if (ck === REMOVE)
853
858
  node.key = null;
854
- const cv = await visitAsync_("value", node.value, visitor, path17);
859
+ const cv = await visitAsync_("value", node.value, visitor, path18);
855
860
  if (cv === BREAK)
856
861
  return BREAK;
857
862
  else if (cv === REMOVE)
@@ -878,23 +883,23 @@ var require_visit = __commonJS({
878
883
  }
879
884
  return visitor;
880
885
  }
881
- function callVisitor(key, node, visitor, path17) {
886
+ function callVisitor(key, node, visitor, path18) {
882
887
  if (typeof visitor === "function")
883
- return visitor(key, node, path17);
888
+ return visitor(key, node, path18);
884
889
  if (identity.isMap(node))
885
- return visitor.Map?.(key, node, path17);
890
+ return visitor.Map?.(key, node, path18);
886
891
  if (identity.isSeq(node))
887
- return visitor.Seq?.(key, node, path17);
892
+ return visitor.Seq?.(key, node, path18);
888
893
  if (identity.isPair(node))
889
- return visitor.Pair?.(key, node, path17);
894
+ return visitor.Pair?.(key, node, path18);
890
895
  if (identity.isScalar(node))
891
- return visitor.Scalar?.(key, node, path17);
896
+ return visitor.Scalar?.(key, node, path18);
892
897
  if (identity.isAlias(node))
893
- return visitor.Alias?.(key, node, path17);
898
+ return visitor.Alias?.(key, node, path18);
894
899
  return void 0;
895
900
  }
896
- function replaceNode(key, path17, node) {
897
- const parent = path17[path17.length - 1];
901
+ function replaceNode(key, path18, node) {
902
+ const parent = path18[path18.length - 1];
898
903
  if (identity.isCollection(parent)) {
899
904
  parent.items[key] = node;
900
905
  } else if (identity.isPair(parent)) {
@@ -1502,10 +1507,10 @@ var require_Collection = __commonJS({
1502
1507
  var createNode = require_createNode();
1503
1508
  var identity = require_identity();
1504
1509
  var Node = require_Node();
1505
- function collectionFromPath(schema, path17, value) {
1510
+ function collectionFromPath(schema, path18, value) {
1506
1511
  let v = value;
1507
- for (let i = path17.length - 1; i >= 0; --i) {
1508
- const k = path17[i];
1512
+ for (let i = path18.length - 1; i >= 0; --i) {
1513
+ const k = path18[i];
1509
1514
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
1510
1515
  const a = [];
1511
1516
  a[k] = v;
@@ -1524,7 +1529,7 @@ var require_Collection = __commonJS({
1524
1529
  sourceObjects: /* @__PURE__ */ new Map()
1525
1530
  });
1526
1531
  }
1527
- var isEmptyPath = (path17) => path17 == null || typeof path17 === "object" && !!path17[Symbol.iterator]().next().done;
1532
+ var isEmptyPath = (path18) => path18 == null || typeof path18 === "object" && !!path18[Symbol.iterator]().next().done;
1528
1533
  var Collection = class extends Node.NodeBase {
1529
1534
  constructor(type, schema) {
1530
1535
  super(type);
@@ -1554,11 +1559,11 @@ var require_Collection = __commonJS({
1554
1559
  * be a Pair instance or a `{ key, value }` object, which may not have a key
1555
1560
  * that already exists in the map.
1556
1561
  */
1557
- addIn(path17, value) {
1558
- if (isEmptyPath(path17))
1562
+ addIn(path18, value) {
1563
+ if (isEmptyPath(path18))
1559
1564
  this.add(value);
1560
1565
  else {
1561
- const [key, ...rest] = path17;
1566
+ const [key, ...rest] = path18;
1562
1567
  const node = this.get(key, true);
1563
1568
  if (identity.isCollection(node))
1564
1569
  node.addIn(rest, value);
@@ -1572,8 +1577,8 @@ var require_Collection = __commonJS({
1572
1577
  * Removes a value from the collection.
1573
1578
  * @returns `true` if the item was found and removed.
1574
1579
  */
1575
- deleteIn(path17) {
1576
- const [key, ...rest] = path17;
1580
+ deleteIn(path18) {
1581
+ const [key, ...rest] = path18;
1577
1582
  if (rest.length === 0)
1578
1583
  return this.delete(key);
1579
1584
  const node = this.get(key, true);
@@ -1587,8 +1592,8 @@ var require_Collection = __commonJS({
1587
1592
  * scalar values from their surrounding node; to disable set `keepScalar` to
1588
1593
  * `true` (collections are always returned intact).
1589
1594
  */
1590
- getIn(path17, keepScalar) {
1591
- const [key, ...rest] = path17;
1595
+ getIn(path18, keepScalar) {
1596
+ const [key, ...rest] = path18;
1592
1597
  const node = this.get(key, true);
1593
1598
  if (rest.length === 0)
1594
1599
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -1606,8 +1611,8 @@ var require_Collection = __commonJS({
1606
1611
  /**
1607
1612
  * Checks if the collection includes a value with the key `key`.
1608
1613
  */
1609
- hasIn(path17) {
1610
- const [key, ...rest] = path17;
1614
+ hasIn(path18) {
1615
+ const [key, ...rest] = path18;
1611
1616
  if (rest.length === 0)
1612
1617
  return this.has(key);
1613
1618
  const node = this.get(key, true);
@@ -1617,8 +1622,8 @@ var require_Collection = __commonJS({
1617
1622
  * Sets a value in this collection. For `!!set`, `value` needs to be a
1618
1623
  * boolean to add/remove the item from the set.
1619
1624
  */
1620
- setIn(path17, value) {
1621
- const [key, ...rest] = path17;
1625
+ setIn(path18, value) {
1626
+ const [key, ...rest] = path18;
1622
1627
  if (rest.length === 0) {
1623
1628
  this.set(key, value);
1624
1629
  } else {
@@ -4122,9 +4127,9 @@ var require_Document = __commonJS({
4122
4127
  this.contents.add(value);
4123
4128
  }
4124
4129
  /** Adds a value to the document. */
4125
- addIn(path17, value) {
4130
+ addIn(path18, value) {
4126
4131
  if (assertCollection(this.contents))
4127
- this.contents.addIn(path17, value);
4132
+ this.contents.addIn(path18, value);
4128
4133
  }
4129
4134
  /**
4130
4135
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -4199,14 +4204,14 @@ var require_Document = __commonJS({
4199
4204
  * Removes a value from the document.
4200
4205
  * @returns `true` if the item was found and removed.
4201
4206
  */
4202
- deleteIn(path17) {
4203
- if (Collection.isEmptyPath(path17)) {
4207
+ deleteIn(path18) {
4208
+ if (Collection.isEmptyPath(path18)) {
4204
4209
  if (this.contents == null)
4205
4210
  return false;
4206
4211
  this.contents = null;
4207
4212
  return true;
4208
4213
  }
4209
- return assertCollection(this.contents) ? this.contents.deleteIn(path17) : false;
4214
+ return assertCollection(this.contents) ? this.contents.deleteIn(path18) : false;
4210
4215
  }
4211
4216
  /**
4212
4217
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -4221,10 +4226,10 @@ var require_Document = __commonJS({
4221
4226
  * scalar values from their surrounding node; to disable set `keepScalar` to
4222
4227
  * `true` (collections are always returned intact).
4223
4228
  */
4224
- getIn(path17, keepScalar) {
4225
- if (Collection.isEmptyPath(path17))
4229
+ getIn(path18, keepScalar) {
4230
+ if (Collection.isEmptyPath(path18))
4226
4231
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
4227
- return identity.isCollection(this.contents) ? this.contents.getIn(path17, keepScalar) : void 0;
4232
+ return identity.isCollection(this.contents) ? this.contents.getIn(path18, keepScalar) : void 0;
4228
4233
  }
4229
4234
  /**
4230
4235
  * Checks if the document includes a value with the key `key`.
@@ -4235,10 +4240,10 @@ var require_Document = __commonJS({
4235
4240
  /**
4236
4241
  * Checks if the document includes a value at `path`.
4237
4242
  */
4238
- hasIn(path17) {
4239
- if (Collection.isEmptyPath(path17))
4243
+ hasIn(path18) {
4244
+ if (Collection.isEmptyPath(path18))
4240
4245
  return this.contents !== void 0;
4241
- return identity.isCollection(this.contents) ? this.contents.hasIn(path17) : false;
4246
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path18) : false;
4242
4247
  }
4243
4248
  /**
4244
4249
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -4255,13 +4260,13 @@ var require_Document = __commonJS({
4255
4260
  * Sets a value in this document. For `!!set`, `value` needs to be a
4256
4261
  * boolean to add/remove the item from the set.
4257
4262
  */
4258
- setIn(path17, value) {
4259
- if (Collection.isEmptyPath(path17)) {
4263
+ setIn(path18, value) {
4264
+ if (Collection.isEmptyPath(path18)) {
4260
4265
  this.contents = value;
4261
4266
  } else if (this.contents == null) {
4262
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path17), value);
4267
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path18), value);
4263
4268
  } else if (assertCollection(this.contents)) {
4264
- this.contents.setIn(path17, value);
4269
+ this.contents.setIn(path18, value);
4265
4270
  }
4266
4271
  }
4267
4272
  /**
@@ -6213,9 +6218,9 @@ var require_cst_visit = __commonJS({
6213
6218
  visit.BREAK = BREAK;
6214
6219
  visit.SKIP = SKIP;
6215
6220
  visit.REMOVE = REMOVE;
6216
- visit.itemAtPath = (cst, path17) => {
6221
+ visit.itemAtPath = (cst, path18) => {
6217
6222
  let item = cst;
6218
- for (const [field, index] of path17) {
6223
+ for (const [field, index] of path18) {
6219
6224
  const tok = item?.[field];
6220
6225
  if (tok && "items" in tok) {
6221
6226
  item = tok.items[index];
@@ -6224,23 +6229,23 @@ var require_cst_visit = __commonJS({
6224
6229
  }
6225
6230
  return item;
6226
6231
  };
6227
- visit.parentCollection = (cst, path17) => {
6228
- const parent = visit.itemAtPath(cst, path17.slice(0, -1));
6229
- const field = path17[path17.length - 1][0];
6232
+ visit.parentCollection = (cst, path18) => {
6233
+ const parent = visit.itemAtPath(cst, path18.slice(0, -1));
6234
+ const field = path18[path18.length - 1][0];
6230
6235
  const coll = parent?.[field];
6231
6236
  if (coll && "items" in coll)
6232
6237
  return coll;
6233
6238
  throw new Error("Parent collection not found");
6234
6239
  };
6235
- function _visit(path17, item, visitor) {
6236
- let ctrl = visitor(item, path17);
6240
+ function _visit(path18, item, visitor) {
6241
+ let ctrl = visitor(item, path18);
6237
6242
  if (typeof ctrl === "symbol")
6238
6243
  return ctrl;
6239
6244
  for (const field of ["key", "value"]) {
6240
6245
  const token = item[field];
6241
6246
  if (token && "items" in token) {
6242
6247
  for (let i = 0; i < token.items.length; ++i) {
6243
- const ci = _visit(Object.freeze(path17.concat([[field, i]])), token.items[i], visitor);
6248
+ const ci = _visit(Object.freeze(path18.concat([[field, i]])), token.items[i], visitor);
6244
6249
  if (typeof ci === "number")
6245
6250
  i = ci - 1;
6246
6251
  else if (ci === BREAK)
@@ -6251,10 +6256,10 @@ var require_cst_visit = __commonJS({
6251
6256
  }
6252
6257
  }
6253
6258
  if (typeof ctrl === "function" && field === "key")
6254
- ctrl = ctrl(item, path17);
6259
+ ctrl = ctrl(item, path18);
6255
6260
  }
6256
6261
  }
6257
- return typeof ctrl === "function" ? ctrl(item, path17) : ctrl;
6262
+ return typeof ctrl === "function" ? ctrl(item, path18) : ctrl;
6258
6263
  }
6259
6264
  exports2.visit = visit;
6260
6265
  }
@@ -7539,14 +7544,14 @@ var require_parser = __commonJS({
7539
7544
  case "scalar":
7540
7545
  case "single-quoted-scalar":
7541
7546
  case "double-quoted-scalar": {
7542
- const fs19 = this.flowScalar(this.type);
7547
+ const fs20 = this.flowScalar(this.type);
7543
7548
  if (atNextItem || it.value) {
7544
- map.items.push({ start, key: fs19, sep: [] });
7549
+ map.items.push({ start, key: fs20, sep: [] });
7545
7550
  this.onKeyLine = true;
7546
7551
  } else if (it.sep) {
7547
- this.stack.push(fs19);
7552
+ this.stack.push(fs20);
7548
7553
  } else {
7549
- Object.assign(it, { key: fs19, sep: [] });
7554
+ Object.assign(it, { key: fs20, sep: [] });
7550
7555
  this.onKeyLine = true;
7551
7556
  }
7552
7557
  return;
@@ -7674,13 +7679,13 @@ var require_parser = __commonJS({
7674
7679
  case "scalar":
7675
7680
  case "single-quoted-scalar":
7676
7681
  case "double-quoted-scalar": {
7677
- const fs19 = this.flowScalar(this.type);
7682
+ const fs20 = this.flowScalar(this.type);
7678
7683
  if (!it || it.value)
7679
- fc.items.push({ start: [], key: fs19, sep: [] });
7684
+ fc.items.push({ start: [], key: fs20, sep: [] });
7680
7685
  else if (it.sep)
7681
- this.stack.push(fs19);
7686
+ this.stack.push(fs20);
7682
7687
  else
7683
- Object.assign(it, { key: fs19, sep: [] });
7688
+ Object.assign(it, { key: fs20, sep: [] });
7684
7689
  return;
7685
7690
  }
7686
7691
  case "flow-map-end":
@@ -11181,8 +11186,8 @@ var require_utils = __commonJS({
11181
11186
  }
11182
11187
  return ind;
11183
11188
  }
11184
- function removeDotSegments(path17) {
11185
- let input = path17;
11189
+ function removeDotSegments(path18) {
11190
+ let input = path18;
11186
11191
  const output = [];
11187
11192
  let nextSlash = -1;
11188
11193
  let len = 0;
@@ -11381,8 +11386,8 @@ var require_schemes = __commonJS({
11381
11386
  wsComponent.secure = void 0;
11382
11387
  }
11383
11388
  if (wsComponent.resourceName) {
11384
- const [path17, query] = wsComponent.resourceName.split("?");
11385
- wsComponent.path = path17 && path17 !== "/" ? path17 : void 0;
11389
+ const [path18, query] = wsComponent.resourceName.split("?");
11390
+ wsComponent.path = path18 && path18 !== "/" ? path18 : void 0;
11386
11391
  wsComponent.query = query;
11387
11392
  wsComponent.resourceName = void 0;
11388
11393
  }
@@ -14735,12 +14740,12 @@ var require_dist2 = __commonJS({
14735
14740
  throw new Error(`Unknown format "${name}"`);
14736
14741
  return f;
14737
14742
  };
14738
- function addFormats2(ajv2, list, fs19, exportName) {
14743
+ function addFormats2(ajv2, list, fs20, exportName) {
14739
14744
  var _a;
14740
14745
  var _b;
14741
14746
  (_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14742
14747
  for (const f of list)
14743
- ajv2.addFormat(f, fs19[f]);
14748
+ ajv2.addFormat(f, fs20[f]);
14744
14749
  }
14745
14750
  module2.exports = exports2 = formatsPlugin;
14746
14751
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -14814,51 +14819,60 @@ rudi - RUDI CLI
14814
14819
  USAGE
14815
14820
  rudi <command> [options]
14816
14821
 
14817
- COMMANDS
14818
- search <query> Search for stacks, prompts, runtimes, binaries, agents
14819
- search --all List all available packages in registry
14820
- install <pkg> Install a package (stack, prompt, runtime, binary, agent)
14821
- remove <pkg> Remove an installed package
14822
- update [pkg] Update packages (or all if no pkg specified)
14823
- run <stack> [args] Run a stack with optional arguments
14824
- list [kind] List installed packages (stacks, prompts, runtimes, binaries, agents)
14825
-
14826
- secrets set <name> Set a secret
14827
- secrets list List configured secrets (masked)
14828
- secrets remove <name> Remove a secret
14829
-
14822
+ INTROSPECTION
14823
+ home Show ~/.rudi structure and installed packages
14824
+ stacks List installed stacks
14825
+ runtimes List installed runtimes
14826
+ binaries List installed binaries
14827
+ agents List installed agents
14828
+ prompts List installed prompts
14829
+ doctor Check system health and dependencies
14830
+ doctor --all Show all available runtimes/binaries from registry
14831
+
14832
+ PACKAGE MANAGEMENT
14833
+ search <query> Search registry for packages
14834
+ search --all List all available packages
14835
+ install <pkg> Install a package
14836
+ remove <pkg> Remove a package
14837
+ update [pkg] Update packages
14838
+ run <stack> Run a stack
14839
+
14840
+ DATABASE
14830
14841
  db stats Show database statistics
14831
14842
  db search <query> Search conversation history
14843
+ db reset --force Delete all data
14844
+ db vacuum Compact and reclaim space
14845
+ db tables Show table row counts
14832
14846
 
14833
- import sessions Import sessions from AI providers (claude, codex, gemini)
14834
- import status Show import status for all providers
14835
-
14836
- logs [options] Query agent visibility logs
14847
+ SESSION IMPORT
14848
+ import sessions Import from AI providers (claude, codex, gemini)
14849
+ import status Show import status
14837
14850
 
14838
- doctor Check system health and configuration
14851
+ SECRETS
14852
+ secrets set <name> Set a secret
14853
+ secrets list List configured secrets
14854
+ secrets remove <name> Remove a secret
14839
14855
 
14840
14856
  OPTIONS
14841
14857
  -h, --help Show help
14842
14858
  -v, --version Show version
14843
14859
  --verbose Verbose output
14844
14860
  --json Output as JSON
14845
- --force Force operation (skip confirmations)
14861
+ --force Force operation
14846
14862
 
14847
14863
  EXAMPLES
14848
- rudi search pdf Search for PDF-related stacks
14849
- rudi install pdf-creator Install the pdf-creator stack
14850
- rudi run pdf-creator Run the pdf-creator stack
14851
- rudi list stacks List installed stacks
14852
- rudi secrets set VERCEL_KEY Set a secret
14853
-
14854
- PACKAGE NAMESPACES
14855
- stack:name A stack (executable workflow)
14856
- prompt:name A prompt template
14857
- runtime:name A runtime interpreter (node, python, deno, bun)
14858
- binary:name A utility binary (ffmpeg, imagemagick, ripgrep)
14859
- agent:name An AI CLI tool (claude, codex, gemini, copilot)
14860
-
14861
- If no namespace is given, 'stack:' is assumed.
14864
+ rudi home Show ~/.rudi structure
14865
+ rudi runtimes List installed runtimes
14866
+ rudi install runtime:python Install Python in ~/.rudi
14867
+ rudi install binary:ffmpeg Install ffmpeg
14868
+ rudi doctor --all Show all available deps
14869
+
14870
+ PACKAGE TYPES
14871
+ stack:name MCP server stack
14872
+ runtime:name Node, Python, Deno, Bun
14873
+ binary:name ffmpeg, ripgrep, etc.
14874
+ agent:name Claude, Codex, Gemini CLIs
14875
+ prompt:name Prompt template
14862
14876
  `);
14863
14877
  }
14864
14878
  function printCommandHelp(command) {
@@ -15002,6 +15016,27 @@ EXAMPLES
15002
15016
  rudi import sessions claude Import only Claude sessions
15003
15017
  rudi import sessions --dry-run Preview without importing
15004
15018
  rudi import status Check what's available to import
15019
+ `,
15020
+ home: `
15021
+ rudi home - Show ~/.rudi structure and status
15022
+
15023
+ USAGE
15024
+ rudi home [options]
15025
+
15026
+ OPTIONS
15027
+ --verbose Show package details
15028
+ --json Output as JSON
15029
+
15030
+ SHOWS
15031
+ - Directory structure with sizes
15032
+ - Installed package counts
15033
+ - Database status
15034
+ - Quick commands reference
15035
+
15036
+ EXAMPLES
15037
+ rudi home
15038
+ rudi home --verbose
15039
+ rudi home --json
15005
15040
  `,
15006
15041
  doctor: `
15007
15042
  rudi doctor - System health check
@@ -15011,13 +15046,20 @@ USAGE
15011
15046
 
15012
15047
  OPTIONS
15013
15048
  --fix Attempt to fix issues
15049
+ --all Show all available runtimes/binaries from registry
15014
15050
 
15015
15051
  CHECKS
15016
15052
  - Directory structure
15017
15053
  - Database integrity
15018
15054
  - Installed packages
15019
- - Required runtimes
15055
+ - Available runtimes (node, python, deno, bun)
15056
+ - Available binaries (ffmpeg, ripgrep, etc.)
15020
15057
  - Secrets configuration
15058
+
15059
+ EXAMPLES
15060
+ rudi doctor
15061
+ rudi doctor --fix
15062
+ rudi doctor --all
15021
15063
  `,
15022
15064
  logs: `
15023
15065
  rudi logs - Query agent visibility logs
@@ -15611,6 +15653,7 @@ var import_fs5 = __toESM(require("fs"), 1);
15611
15653
  var import_path5 = __toESM(require("path"), 1);
15612
15654
  var import_child_process = require("child_process");
15613
15655
  init_src();
15656
+ init_src2();
15614
15657
  function checkRuntime(runtime) {
15615
15658
  const name = runtime.replace(/^runtime:/, "");
15616
15659
  const rudiPath = import_path5.default.join(PATHS.runtimes, name);
@@ -15760,16 +15803,57 @@ function getVersion(binPath, name) {
15760
15803
  }
15761
15804
  }
15762
15805
  function getAvailableDeps() {
15763
- const runtimes = ["node", "python", "deno", "bun"].map((name) => ({
15806
+ const installedRuntimes = scanDirectory(PATHS.runtimes);
15807
+ const installedBinaries = scanDirectory(PATHS.binaries);
15808
+ const commonRuntimes = ["node", "python", "deno", "bun"];
15809
+ const commonBinaries = ["ffmpeg", "ripgrep", "sqlite3", "jq", "yq", "git", "docker", "rg"];
15810
+ const runtimeNames = [.../* @__PURE__ */ new Set([...installedRuntimes, ...commonRuntimes])];
15811
+ const binaryNames = [.../* @__PURE__ */ new Set([...installedBinaries, ...commonBinaries])];
15812
+ const runtimes = runtimeNames.map((name) => ({
15764
15813
  name,
15765
15814
  ...checkRuntime(name)
15766
15815
  }));
15767
- const binaries = ["ffmpeg", "ripgrep", "sqlite3", "jq", "yq", "git", "docker"].map((name) => ({
15816
+ const binaries = binaryNames.filter((name) => name !== "rg").map((name) => ({
15768
15817
  name,
15769
15818
  ...checkBinary(name)
15770
15819
  }));
15771
15820
  return { runtimes, binaries };
15772
15821
  }
15822
+ function scanDirectory(dir) {
15823
+ if (!import_fs5.default.existsSync(dir)) return [];
15824
+ try {
15825
+ return import_fs5.default.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
15826
+ } catch {
15827
+ return [];
15828
+ }
15829
+ }
15830
+ async function getAllDepsFromRegistry() {
15831
+ const index = await fetchIndex();
15832
+ const runtimes = (index.packages?.runtimes?.official || []).map((rt) => {
15833
+ const name = rt.id.replace(/^runtime:/, "");
15834
+ const check = checkRuntime(name);
15835
+ return {
15836
+ name,
15837
+ registryVersion: rt.version,
15838
+ description: rt.description,
15839
+ ...check,
15840
+ status: check.available ? check.source === "rudi" ? "installed" : "system" : "available"
15841
+ };
15842
+ });
15843
+ const binaries = (index.packages?.binaries?.official || []).map((bin) => {
15844
+ const name = bin.id.replace(/^binary:/, "");
15845
+ const check = checkBinary(name);
15846
+ return {
15847
+ name,
15848
+ registryVersion: bin.version,
15849
+ description: bin.description,
15850
+ managed: bin.managed !== false,
15851
+ ...check,
15852
+ status: check.available ? check.source === "rudi" ? "installed" : "system" : "available"
15853
+ };
15854
+ });
15855
+ return { runtimes, binaries };
15856
+ }
15773
15857
 
15774
15858
  // src/commands/search.js
15775
15859
  function pluralizeKind(kind) {
@@ -16564,11 +16648,11 @@ async function runStack(id, options = {}) {
16564
16648
  const startTime = Date.now();
16565
16649
  const packagePath = getPackagePath(id);
16566
16650
  const manifestPath = import_path7.default.join(packagePath, "manifest.json");
16567
- const { default: fs19 } = await import("fs");
16568
- if (!fs19.existsSync(manifestPath)) {
16651
+ const { default: fs20 } = await import("fs");
16652
+ if (!fs20.existsSync(manifestPath)) {
16569
16653
  throw new Error(`Stack manifest not found: ${id}`);
16570
16654
  }
16571
- const manifest = JSON.parse(fs19.readFileSync(manifestPath, "utf-8"));
16655
+ const manifest = JSON.parse(fs20.readFileSync(manifestPath, "utf-8"));
16572
16656
  const { command, args } = resolveCommandFromManifest(manifest, packagePath);
16573
16657
  const secrets = await getSecrets(manifest.requires?.secrets || []);
16574
16658
  const runEnv = {
@@ -17479,7 +17563,7 @@ CREATE TABLE IF NOT EXISTS sessions (
17479
17563
  project_id TEXT,
17480
17564
 
17481
17565
  -- Origin tracking
17482
- origin TEXT NOT NULL CHECK (origin IN ('promptstack', 'provider-import', 'mixed')),
17566
+ origin TEXT NOT NULL CHECK (origin IN ('rudi', 'provider-import', 'mixed')),
17483
17567
  origin_imported_at TEXT,
17484
17568
  origin_native_file TEXT,
17485
17569
 
@@ -18978,20 +19062,29 @@ async function cmdDoctor(args, flags) {
18978
19062
  }
18979
19063
  console.log("\n\u2699\uFE0F Runtimes");
18980
19064
  try {
18981
- const { runtimes, binaries } = getAvailableDeps();
19065
+ const { runtimes, binaries } = flags.all ? await getAllDepsFromRegistry() : getAvailableDeps();
18982
19066
  for (const rt of runtimes) {
18983
19067
  const icon = rt.available ? "\u2713" : "\u25CB";
18984
19068
  const version = rt.version ? `v${rt.version}` : "";
18985
- const source = rt.source ? `(${rt.source})` : "not found";
19069
+ const source = rt.available ? `(${rt.source})` : flags.all ? "available" : "not found";
18986
19070
  console.log(` ${icon} ${rt.name}: ${version} ${source}`);
18987
19071
  }
18988
19072
  console.log("\n\u{1F527} Binaries");
18989
19073
  for (const bin of binaries) {
18990
19074
  const icon = bin.available ? "\u2713" : "\u25CB";
18991
19075
  const version = bin.version ? `v${bin.version}` : "";
18992
- const source = bin.source ? `(${bin.source})` : "not found";
19076
+ const managed = bin.managed === false ? " (external)" : "";
19077
+ const source = bin.available ? `(${bin.source})` : flags.all ? `available${managed}` : "not found";
18993
19078
  console.log(` ${icon} ${bin.name}: ${version} ${source}`);
18994
19079
  }
19080
+ if (flags.all) {
19081
+ const availableRuntimes = runtimes.filter((r) => !r.available).length;
19082
+ const availableBinaries = binaries.filter((b) => !b.available && b.managed !== false).length;
19083
+ if (availableRuntimes + availableBinaries > 0) {
19084
+ console.log(`
19085
+ Install with: rudi install runtime:<name> or rudi install binary:<name>`);
19086
+ }
19087
+ }
18995
19088
  } catch (error) {
18996
19089
  console.log(` \u2717 Error checking dependencies: ${error.message}`);
18997
19090
  }
@@ -19029,9 +19122,143 @@ async function cmdDoctor(args, flags) {
19029
19122
  }
19030
19123
  }
19031
19124
 
19032
- // src/commands/update.js
19125
+ // src/commands/home.js
19033
19126
  var import_fs14 = __toESM(require("fs"), 1);
19034
19127
  var import_path13 = __toESM(require("path"), 1);
19128
+ function formatBytes2(bytes) {
19129
+ if (bytes === 0) return "0 B";
19130
+ const k = 1024;
19131
+ const sizes = ["B", "KB", "MB", "GB"];
19132
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
19133
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
19134
+ }
19135
+ function getDirSize(dir) {
19136
+ if (!import_fs14.default.existsSync(dir)) return 0;
19137
+ let size = 0;
19138
+ try {
19139
+ const entries = import_fs14.default.readdirSync(dir, { withFileTypes: true });
19140
+ for (const entry of entries) {
19141
+ const fullPath = import_path13.default.join(dir, entry.name);
19142
+ if (entry.isDirectory()) {
19143
+ size += getDirSize(fullPath);
19144
+ } else {
19145
+ size += import_fs14.default.statSync(fullPath).size;
19146
+ }
19147
+ }
19148
+ } catch {
19149
+ }
19150
+ return size;
19151
+ }
19152
+ function countItems(dir) {
19153
+ if (!import_fs14.default.existsSync(dir)) return 0;
19154
+ try {
19155
+ return import_fs14.default.readdirSync(dir).filter((f) => !f.startsWith(".")).length;
19156
+ } catch {
19157
+ return 0;
19158
+ }
19159
+ }
19160
+ async function cmdHome(args, flags) {
19161
+ console.log("\u2550".repeat(60));
19162
+ console.log("RUDI Home: " + PATHS.home);
19163
+ console.log("\u2550".repeat(60));
19164
+ if (flags.json) {
19165
+ const data = {
19166
+ home: PATHS.home,
19167
+ directories: {},
19168
+ packages: {},
19169
+ database: {}
19170
+ };
19171
+ const dirs2 = [
19172
+ { key: "stacks", path: PATHS.stacks },
19173
+ { key: "prompts", path: PATHS.prompts },
19174
+ { key: "runtimes", path: PATHS.runtimes },
19175
+ { key: "binaries", path: PATHS.binaries },
19176
+ { key: "agents", path: PATHS.agents },
19177
+ { key: "cache", path: PATHS.cache }
19178
+ ];
19179
+ for (const dir of dirs2) {
19180
+ data.directories[dir.key] = {
19181
+ path: dir.path,
19182
+ exists: import_fs14.default.existsSync(dir.path),
19183
+ items: countItems(dir.path),
19184
+ size: getDirSize(dir.path)
19185
+ };
19186
+ }
19187
+ for (const kind of ["stack", "prompt", "runtime", "binary", "agent"]) {
19188
+ data.packages[kind] = getInstalledPackages(kind).length;
19189
+ }
19190
+ data.database = {
19191
+ initialized: isDatabaseInitialized(),
19192
+ size: getDbSize() || 0
19193
+ };
19194
+ console.log(JSON.stringify(data, null, 2));
19195
+ return;
19196
+ }
19197
+ console.log("\n\u{1F4C1} Directory Structure\n");
19198
+ const dirs = [
19199
+ { name: "stacks", path: PATHS.stacks, icon: "\u{1F4E6}", desc: "MCP server stacks" },
19200
+ { name: "prompts", path: PATHS.prompts, icon: "\u{1F4DD}", desc: "Prompt templates" },
19201
+ { name: "runtimes", path: PATHS.runtimes, icon: "\u2699\uFE0F", desc: "Node, Python, Deno, Bun" },
19202
+ { name: "binaries", path: PATHS.binaries, icon: "\u{1F527}", desc: "ffmpeg, ripgrep, etc." },
19203
+ { name: "agents", path: PATHS.agents, icon: "\u{1F916}", desc: "Claude, Codex, Gemini CLIs" },
19204
+ { name: "cache", path: PATHS.cache, icon: "\u{1F4BE}", desc: "Registry cache" }
19205
+ ];
19206
+ for (const dir of dirs) {
19207
+ const exists = import_fs14.default.existsSync(dir.path);
19208
+ const count = countItems(dir.path);
19209
+ const size = getDirSize(dir.path);
19210
+ console.log(`${dir.icon} ${dir.name}/`);
19211
+ console.log(` ${dir.desc}`);
19212
+ if (exists) {
19213
+ console.log(` ${count} items, ${formatBytes2(size)}`);
19214
+ } else {
19215
+ console.log(` (not created)`);
19216
+ }
19217
+ console.log();
19218
+ }
19219
+ console.log("\u{1F4BE} Database");
19220
+ const dbPath = import_path13.default.join(PATHS.home, "rudi.db");
19221
+ if (import_fs14.default.existsSync(dbPath)) {
19222
+ const dbSize = getDbSize() || import_fs14.default.statSync(dbPath).size;
19223
+ console.log(` ${formatBytes2(dbSize)}`);
19224
+ console.log(` ${dbPath}`);
19225
+ } else {
19226
+ console.log(` Not initialized`);
19227
+ }
19228
+ console.log();
19229
+ console.log("\u2550".repeat(60));
19230
+ console.log("Installed Packages");
19231
+ console.log("\u2550".repeat(60));
19232
+ const kinds = ["stack", "prompt", "runtime", "binary", "agent"];
19233
+ let total = 0;
19234
+ for (const kind of kinds) {
19235
+ const packages = getInstalledPackages(kind);
19236
+ const label = kind === "binary" ? "Binaries" : `${kind.charAt(0).toUpperCase() + kind.slice(1)}s`;
19237
+ console.log(` ${label.padEnd(12)} ${packages.length}`);
19238
+ if (packages.length > 0 && flags.verbose) {
19239
+ for (const pkg of packages.slice(0, 3)) {
19240
+ console.log(` - ${pkg.name || pkg.id}`);
19241
+ }
19242
+ if (packages.length > 3) {
19243
+ console.log(` ... and ${packages.length - 3} more`);
19244
+ }
19245
+ }
19246
+ total += packages.length;
19247
+ }
19248
+ console.log("\u2500".repeat(30));
19249
+ console.log(` ${"Total".padEnd(12)} ${total}`);
19250
+ console.log("\n\u{1F4CB} Quick Commands");
19251
+ console.log("\u2500".repeat(30));
19252
+ console.log(" rudi list stacks Show installed stacks");
19253
+ console.log(" rudi list runtimes Show installed runtimes");
19254
+ console.log(" rudi list binaries Show installed binaries");
19255
+ console.log(" rudi doctor --all Check system dependencies");
19256
+ console.log(" rudi db stats Database statistics");
19257
+ }
19258
+
19259
+ // src/commands/update.js
19260
+ var import_fs15 = __toESM(require("fs"), 1);
19261
+ var import_path14 = __toESM(require("path"), 1);
19035
19262
  var import_child_process3 = require("child_process");
19036
19263
  init_src();
19037
19264
  init_src2();
@@ -19057,7 +19284,7 @@ async function cmdUpdate(args, flags) {
19057
19284
  async function updatePackage(pkgId, flags) {
19058
19285
  const [kind, name] = parsePackageId(pkgId);
19059
19286
  const installPath = getPackagePath(pkgId);
19060
- if (!import_fs14.default.existsSync(installPath)) {
19287
+ if (!import_fs15.default.existsSync(installPath)) {
19061
19288
  return { success: false, error: "Package not installed" };
19062
19289
  }
19063
19290
  const pkg = await getPackage(pkgId);
@@ -19080,7 +19307,7 @@ async function updatePackage(pkgId, flags) {
19080
19307
  }
19081
19308
  if (pkg.pipPackage) {
19082
19309
  try {
19083
- const venvPip = import_path13.default.join(installPath, "venv", "bin", "pip");
19310
+ const venvPip = import_path14.default.join(installPath, "venv", "bin", "pip");
19084
19311
  (0, import_child_process3.execSync)(`"${venvPip}" install --upgrade ${pkg.pipPackage}`, {
19085
19312
  stdio: flags.verbose ? "inherit" : "pipe"
19086
19313
  });
@@ -19097,7 +19324,7 @@ async function updatePackage(pkgId, flags) {
19097
19324
  if (kind === "runtime" && !pkg.npmPackage && !pkg.pipPackage) {
19098
19325
  try {
19099
19326
  const { downloadRuntime: downloadRuntime2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
19100
- import_fs14.default.rmSync(installPath, { recursive: true, force: true });
19327
+ import_fs15.default.rmSync(installPath, { recursive: true, force: true });
19101
19328
  await downloadRuntime2(name, pkg.version || "latest", installPath, {
19102
19329
  onProgress: (p) => {
19103
19330
  if (flags.verbose) console.log(` ${p.phase}...`);
@@ -19117,8 +19344,8 @@ async function updateAll(flags) {
19117
19344
  let failed = 0;
19118
19345
  for (const kind of kinds) {
19119
19346
  const dir = kind === "runtime" ? PATHS.runtimes : kind === "stack" ? PATHS.stacks : PATHS.prompts;
19120
- if (!import_fs14.default.existsSync(dir)) continue;
19121
- const entries = import_fs14.default.readdirSync(dir, { withFileTypes: true });
19347
+ if (!import_fs15.default.existsSync(dir)) continue;
19348
+ const entries = import_fs15.default.readdirSync(dir, { withFileTypes: true });
19122
19349
  for (const entry of entries) {
19123
19350
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
19124
19351
  const pkgId = `${kind}:${entry.name}`;
@@ -19137,14 +19364,14 @@ Updated ${updated} package(s)${failed > 0 ? `, ${failed} failed` : ""}`);
19137
19364
  }
19138
19365
  function getInstalledVersion(installPath, npmPackage) {
19139
19366
  try {
19140
- const pkgJsonPath = import_path13.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
19141
- if (import_fs14.default.existsSync(pkgJsonPath)) {
19142
- const pkgJson = JSON.parse(import_fs14.default.readFileSync(pkgJsonPath, "utf-8"));
19367
+ const pkgJsonPath = import_path14.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
19368
+ if (import_fs15.default.existsSync(pkgJsonPath)) {
19369
+ const pkgJson = JSON.parse(import_fs15.default.readFileSync(pkgJsonPath, "utf-8"));
19143
19370
  return pkgJson.version;
19144
19371
  }
19145
- const rootPkgPath = import_path13.default.join(installPath, "package.json");
19146
- if (import_fs14.default.existsSync(rootPkgPath)) {
19147
- const rootPkg = JSON.parse(import_fs14.default.readFileSync(rootPkgPath, "utf-8"));
19372
+ const rootPkgPath = import_path14.default.join(installPath, "package.json");
19373
+ if (import_fs15.default.existsSync(rootPkgPath)) {
19374
+ const rootPkg = JSON.parse(import_fs15.default.readFileSync(rootPkgPath, "utf-8"));
19148
19375
  const dep = rootPkg.dependencies?.[npmPackage];
19149
19376
  if (dep) return dep.replace(/[\^~]/, "");
19150
19377
  }
@@ -19153,30 +19380,30 @@ function getInstalledVersion(installPath, npmPackage) {
19153
19380
  return null;
19154
19381
  }
19155
19382
  function updateRuntimeMetadata(installPath, updates) {
19156
- const metaPath = import_path13.default.join(installPath, "runtime.json");
19383
+ const metaPath = import_path14.default.join(installPath, "runtime.json");
19157
19384
  try {
19158
19385
  let meta = {};
19159
- if (import_fs14.default.existsSync(metaPath)) {
19160
- meta = JSON.parse(import_fs14.default.readFileSync(metaPath, "utf-8"));
19386
+ if (import_fs15.default.existsSync(metaPath)) {
19387
+ meta = JSON.parse(import_fs15.default.readFileSync(metaPath, "utf-8"));
19161
19388
  }
19162
19389
  meta = { ...meta, ...updates };
19163
- import_fs14.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
19390
+ import_fs15.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
19164
19391
  } catch {
19165
19392
  }
19166
19393
  }
19167
19394
 
19168
19395
  // db/index.js
19169
19396
  var import_better_sqlite32 = __toESM(require("better-sqlite3"), 1);
19170
- var import_path14 = __toESM(require("path"), 1);
19397
+ var import_path15 = __toESM(require("path"), 1);
19171
19398
  var import_os4 = __toESM(require("os"), 1);
19172
- var import_fs15 = __toESM(require("fs"), 1);
19173
- var PROMPT_STACK_HOME = import_path14.default.join(import_os4.default.homedir(), ".prompt-stack");
19174
- var DB_PATH2 = import_path14.default.join(PROMPT_STACK_HOME, "prompt-stack.db");
19399
+ var import_fs16 = __toESM(require("fs"), 1);
19400
+ var RUDI_HOME2 = import_path15.default.join(import_os4.default.homedir(), ".rudi");
19401
+ var DB_PATH2 = import_path15.default.join(RUDI_HOME2, "rudi.db");
19175
19402
  var db2 = null;
19176
19403
  function getDb2(options = {}) {
19177
19404
  if (!db2) {
19178
- if (!import_fs15.default.existsSync(PROMPT_STACK_HOME)) {
19179
- import_fs15.default.mkdirSync(PROMPT_STACK_HOME, { recursive: true });
19405
+ if (!import_fs16.default.existsSync(RUDI_HOME2)) {
19406
+ import_fs16.default.mkdirSync(RUDI_HOME2, { recursive: true });
19180
19407
  }
19181
19408
  db2 = new import_better_sqlite32.default(DB_PATH2, {
19182
19409
  readonly: options.readonly || false
@@ -19334,7 +19561,7 @@ function getBeforeCrashLogs() {
19334
19561
  }
19335
19562
 
19336
19563
  // src/commands/logs.js
19337
- var import_fs16 = __toESM(require("fs"), 1);
19564
+ var import_fs17 = __toESM(require("fs"), 1);
19338
19565
  function parseTimeAgo(str) {
19339
19566
  const match = str.match(/^(\d+)([smhd])$/);
19340
19567
  if (!match) return null;
@@ -19434,7 +19661,7 @@ function exportLogs(logs, filepath, format) {
19434
19661
  });
19435
19662
  content = JSON.stringify(formatted, null, 2);
19436
19663
  }
19437
- import_fs16.default.writeFileSync(filepath, content, "utf-8");
19664
+ import_fs17.default.writeFileSync(filepath, content, "utf-8");
19438
19665
  return filepath;
19439
19666
  }
19440
19667
  function printStats(stats) {
@@ -19560,8 +19787,8 @@ async function handleLogsCommand(args, flags) {
19560
19787
  }
19561
19788
 
19562
19789
  // src/commands/which.js
19563
- var fs17 = __toESM(require("fs/promises"), 1);
19564
- var path15 = __toESM(require("path"), 1);
19790
+ var fs18 = __toESM(require("fs/promises"), 1);
19791
+ var path16 = __toESM(require("path"), 1);
19565
19792
  var import_child_process4 = require("child_process");
19566
19793
  init_src();
19567
19794
  async function cmdWhich(args, flags) {
@@ -19630,7 +19857,7 @@ Installed stacks:`);
19630
19857
  if (runtimeInfo.entry) {
19631
19858
  console.log("");
19632
19859
  console.log("Run MCP server directly:");
19633
- const entryPath = path15.join(stackPath, runtimeInfo.entry);
19860
+ const entryPath = path16.join(stackPath, runtimeInfo.entry);
19634
19861
  if (runtimeInfo.runtime === "node") {
19635
19862
  console.log(` echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node ${entryPath}`);
19636
19863
  } else if (runtimeInfo.runtime === "python") {
@@ -19649,27 +19876,27 @@ Installed stacks:`);
19649
19876
  async function detectRuntime(stackPath) {
19650
19877
  const runtimes = ["node", "python"];
19651
19878
  for (const runtime of runtimes) {
19652
- const runtimePath = path15.join(stackPath, runtime);
19879
+ const runtimePath = path16.join(stackPath, runtime);
19653
19880
  try {
19654
- await fs17.access(runtimePath);
19881
+ await fs18.access(runtimePath);
19655
19882
  if (runtime === "node") {
19656
- const distEntry = path15.join(runtimePath, "dist", "index.js");
19657
- const srcEntry = path15.join(runtimePath, "src", "index.ts");
19883
+ const distEntry = path16.join(runtimePath, "dist", "index.js");
19884
+ const srcEntry = path16.join(runtimePath, "src", "index.ts");
19658
19885
  try {
19659
- await fs17.access(distEntry);
19886
+ await fs18.access(distEntry);
19660
19887
  return { runtime: "node", entry: `${runtime}/dist/index.js` };
19661
19888
  } catch {
19662
19889
  try {
19663
- await fs17.access(srcEntry);
19890
+ await fs18.access(srcEntry);
19664
19891
  return { runtime: "node", entry: `${runtime}/src/index.ts` };
19665
19892
  } catch {
19666
19893
  return { runtime: "node", entry: null };
19667
19894
  }
19668
19895
  }
19669
19896
  } else if (runtime === "python") {
19670
- const entry = path15.join(runtimePath, "src", "index.py");
19897
+ const entry = path16.join(runtimePath, "src", "index.py");
19671
19898
  try {
19672
- await fs17.access(entry);
19899
+ await fs18.access(entry);
19673
19900
  return { runtime: "python", entry: `${runtime}/src/index.py` };
19674
19901
  } catch {
19675
19902
  return { runtime: "python", entry: null };
@@ -19685,21 +19912,21 @@ async function checkAuth(stackPath, runtime) {
19685
19912
  const authFiles = [];
19686
19913
  let configured = false;
19687
19914
  if (runtime === "node" || runtime === "python") {
19688
- const runtimePath = path15.join(stackPath, runtime);
19689
- const tokenPath = path15.join(runtimePath, "token.json");
19915
+ const runtimePath = path16.join(stackPath, runtime);
19916
+ const tokenPath = path16.join(runtimePath, "token.json");
19690
19917
  try {
19691
- await fs17.access(tokenPath);
19918
+ await fs18.access(tokenPath);
19692
19919
  authFiles.push(`${runtime}/token.json`);
19693
19920
  configured = true;
19694
19921
  } catch {
19695
- const accountsPath = path15.join(runtimePath, "accounts");
19922
+ const accountsPath = path16.join(runtimePath, "accounts");
19696
19923
  try {
19697
- const accounts = await fs17.readdir(accountsPath);
19924
+ const accounts = await fs18.readdir(accountsPath);
19698
19925
  for (const account of accounts) {
19699
19926
  if (account.startsWith(".")) continue;
19700
- const accountTokenPath = path15.join(accountsPath, account, "token.json");
19927
+ const accountTokenPath = path16.join(accountsPath, account, "token.json");
19701
19928
  try {
19702
- await fs17.access(accountTokenPath);
19929
+ await fs18.access(accountTokenPath);
19703
19930
  authFiles.push(`${runtime}/accounts/${account}/token.json`);
19704
19931
  configured = true;
19705
19932
  } catch {
@@ -19709,9 +19936,9 @@ async function checkAuth(stackPath, runtime) {
19709
19936
  }
19710
19937
  }
19711
19938
  }
19712
- const envPath = path15.join(stackPath, ".env");
19939
+ const envPath = path16.join(stackPath, ".env");
19713
19940
  try {
19714
- const envContent = await fs17.readFile(envPath, "utf-8");
19941
+ const envContent = await fs18.readFile(envPath, "utf-8");
19715
19942
  const hasValues = envContent.split("\n").some((line) => {
19716
19943
  const trimmed = line.trim();
19717
19944
  if (!trimmed || trimmed.startsWith("#")) return false;
@@ -19755,8 +19982,8 @@ function checkIfRunning(stackName) {
19755
19982
  }
19756
19983
 
19757
19984
  // src/commands/auth.js
19758
- var fs18 = __toESM(require("fs/promises"), 1);
19759
- var path16 = __toESM(require("path"), 1);
19985
+ var fs19 = __toESM(require("fs/promises"), 1);
19986
+ var path17 = __toESM(require("path"), 1);
19760
19987
  var import_child_process5 = require("child_process");
19761
19988
  init_src();
19762
19989
  var net = __toESM(require("net"), 1);
@@ -19788,26 +20015,26 @@ function isPortAvailable(port) {
19788
20015
  async function detectRuntime2(stackPath) {
19789
20016
  const runtimes = ["node", "python"];
19790
20017
  for (const runtime of runtimes) {
19791
- const runtimePath = path16.join(stackPath, runtime);
20018
+ const runtimePath = path17.join(stackPath, runtime);
19792
20019
  try {
19793
- await fs18.access(runtimePath);
20020
+ await fs19.access(runtimePath);
19794
20021
  if (runtime === "node") {
19795
- const authTs = path16.join(runtimePath, "src", "auth.ts");
19796
- const authJs = path16.join(runtimePath, "dist", "auth.js");
20022
+ const authTs = path17.join(runtimePath, "src", "auth.ts");
20023
+ const authJs = path17.join(runtimePath, "dist", "auth.js");
19797
20024
  try {
19798
- await fs18.access(authTs);
20025
+ await fs19.access(authTs);
19799
20026
  return { runtime: "node", authScript: authTs, useTsx: true };
19800
20027
  } catch {
19801
20028
  try {
19802
- await fs18.access(authJs);
20029
+ await fs19.access(authJs);
19803
20030
  return { runtime: "node", authScript: authJs, useTsx: false };
19804
20031
  } catch {
19805
20032
  }
19806
20033
  }
19807
20034
  } else if (runtime === "python") {
19808
- const authPy = path16.join(runtimePath, "src", "auth.py");
20035
+ const authPy = path17.join(runtimePath, "src", "auth.py");
19809
20036
  try {
19810
- await fs18.access(authPy);
20037
+ await fs19.access(authPy);
19811
20038
  return { runtime: "python", authScript: authPy, useTsx: false };
19812
20039
  } catch {
19813
20040
  }
@@ -19857,14 +20084,14 @@ Installed stacks:`);
19857
20084
  console.log(`Using port: ${port}`);
19858
20085
  console.log("");
19859
20086
  let cmd;
19860
- const cwd = path16.dirname(authInfo.authScript);
20087
+ const cwd = path17.dirname(authInfo.authScript);
19861
20088
  if (authInfo.runtime === "node") {
19862
- const distAuth = path16.join(cwd, "..", "dist", "auth.js");
20089
+ const distAuth = path17.join(cwd, "..", "dist", "auth.js");
19863
20090
  let useBuiltInPort = false;
19864
20091
  let tempAuthScript = null;
19865
20092
  try {
19866
- await fs18.access(distAuth);
19867
- const distContent = await fs18.readFile(distAuth, "utf-8");
20093
+ await fs19.access(distAuth);
20094
+ const distContent = await fs19.readFile(distAuth, "utf-8");
19868
20095
  if (distContent.includes("findAvailablePort")) {
19869
20096
  console.log("Using compiled authentication script...");
19870
20097
  cmd = `node ${distAuth}${accountEmail ? ` ${accountEmail}` : ""}`;
@@ -19873,11 +20100,11 @@ Installed stacks:`);
19873
20100
  } catch {
19874
20101
  }
19875
20102
  if (!useBuiltInPort) {
19876
- const authContent = await fs18.readFile(authInfo.authScript, "utf-8");
20103
+ const authContent = await fs19.readFile(authInfo.authScript, "utf-8");
19877
20104
  const tempExt = authInfo.useTsx ? ".ts" : ".mjs";
19878
- tempAuthScript = path16.join(cwd, "..", `auth-temp${tempExt}`);
20105
+ tempAuthScript = path17.join(cwd, "..", `auth-temp${tempExt}`);
19879
20106
  const modifiedContent = authContent.replace(/localhost:3456/g, `localhost:${port}`).replace(/server\.listen\(3456/g, `server.listen(${port}`);
19880
- await fs18.writeFile(tempAuthScript, modifiedContent);
20107
+ await fs19.writeFile(tempAuthScript, modifiedContent);
19881
20108
  if (authInfo.useTsx) {
19882
20109
  cmd = `npx tsx ${tempAuthScript}${accountEmail ? ` ${accountEmail}` : ""}`;
19883
20110
  } else {
@@ -19892,12 +20119,12 @@ Installed stacks:`);
19892
20119
  stdio: "inherit"
19893
20120
  });
19894
20121
  if (tempAuthScript) {
19895
- await fs18.unlink(tempAuthScript);
20122
+ await fs19.unlink(tempAuthScript);
19896
20123
  }
19897
20124
  } catch (error) {
19898
20125
  if (tempAuthScript) {
19899
20126
  try {
19900
- await fs18.unlink(tempAuthScript);
20127
+ await fs19.unlink(tempAuthScript);
19901
20128
  } catch {
19902
20129
  }
19903
20130
  }
@@ -19995,6 +20222,28 @@ async function main() {
19995
20222
  case "login":
19996
20223
  await cmdAuth(args, flags);
19997
20224
  break;
20225
+ case "home":
20226
+ case "status":
20227
+ await cmdHome(args, flags);
20228
+ break;
20229
+ // Shortcuts for listing specific package types
20230
+ case "stacks":
20231
+ await cmdList(["stacks"], flags);
20232
+ break;
20233
+ case "prompts":
20234
+ await cmdList(["prompts"], flags);
20235
+ break;
20236
+ case "runtimes":
20237
+ await cmdList(["runtimes"], flags);
20238
+ break;
20239
+ case "binaries":
20240
+ case "bins":
20241
+ case "tools":
20242
+ await cmdList(["binaries"], flags);
20243
+ break;
20244
+ case "agents":
20245
+ await cmdList(["agents"], flags);
20246
+ break;
19998
20247
  case "help":
19999
20248
  printHelp(args[0]);
20000
20249
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learnrudi/cli",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "RUDI CLI - Install and manage MCP stacks, runtimes, and AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",