forgecad 0.1.0 → 0.1.2

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 (48) hide show
  1. package/README.md +12 -1
  2. package/dist/assets/{evalWorker-BYHXxh15.js → evalWorker-1m873KWd.js} +107 -107
  3. package/dist/assets/{index--CYbOPKS.js → index-Dvz3nSDc.js} +356 -339
  4. package/dist/assets/manifold-C38sUiKu.js +16 -0
  5. package/dist/assets/manifold-C44_QbND.wasm +0 -0
  6. package/dist/assets/manifold-Dk2u-lhj.js +16 -0
  7. package/dist/assets/manifold-rOWQW9fU.js +16 -0
  8. package/dist/assets/{reportWorker-B1Zdrz9l.js → reportWorker-Cj587shw.js} +129 -129
  9. package/dist/index.html +1 -1
  10. package/dist-cli/forgecad.js +207 -22
  11. package/dist-skill/SKILL.md +31 -4561
  12. package/dist-skill/docs/API/README.md +24 -0
  13. package/dist-skill/docs/API/guides/modeling-recipes.md +246 -0
  14. package/dist-skill/docs/API/internals/compiler.md +300 -0
  15. package/dist-skill/docs/API/internals/manifold.md +7 -0
  16. package/dist-skill/docs/API/model-building/README.md +31 -0
  17. package/dist-skill/docs/API/model-building/assembly.md +205 -0
  18. package/dist-skill/docs/API/model-building/coordinate-system.md +43 -0
  19. package/dist-skill/docs/API/model-building/entities.md +282 -0
  20. package/dist-skill/docs/API/model-building/geometry-conventions.md +104 -0
  21. package/dist-skill/docs/API/model-building/positioning.md +170 -0
  22. package/dist-skill/docs/API/model-building/reference.md +1936 -0
  23. package/dist-skill/docs/API/model-building/sheet-metal.md +180 -0
  24. package/dist-skill/docs/API/model-building/sketch-anchor.md +32 -0
  25. package/dist-skill/docs/API/model-building/sketch-booleans.md +101 -0
  26. package/dist-skill/docs/API/model-building/sketch-core.md +68 -0
  27. package/dist-skill/docs/API/model-building/sketch-extrude.md +57 -0
  28. package/dist-skill/docs/API/model-building/sketch-on-face.md +98 -0
  29. package/dist-skill/docs/API/model-building/sketch-operations.md +92 -0
  30. package/dist-skill/docs/API/model-building/sketch-path.md +70 -0
  31. package/dist-skill/docs/API/model-building/sketch-primitives.md +104 -0
  32. package/dist-skill/docs/API/model-building/sketch-transforms.md +60 -0
  33. package/dist-skill/docs/API/output/bom.md +53 -0
  34. package/dist-skill/docs/API/output/brep-export.md +82 -0
  35. package/dist-skill/docs/API/output/dimensions.md +62 -0
  36. package/dist-skill/docs/API/runtime/viewport.md +229 -0
  37. package/dist-skill/docs/CLI.md +672 -0
  38. package/dist-skill/docs/CODING.md +345 -0
  39. package/dist-skill/docs/PROGRAM-LEAD.md +180 -0
  40. package/dist-skill/docs/VISION.md +77 -0
  41. package/examples/api/import-group-assembly.forge.js +34 -0
  42. package/examples/api/import-group-source.forge.js +35 -0
  43. package/package.json +2 -2
  44. package/dist/assets/manifold-65fIQlgQ.js +0 -20
  45. package/dist/assets/manifold-B85M7kop.js +0 -20
  46. package/dist/assets/manifold-B8h_vZ5O.js +0 -16
  47. package/dist/assets/manifold-D9yvTBHx.wasm +0 -0
  48. package/dist/assets/manifold-d1UpyLJ8.js +0 -20
package/dist/index.html CHANGED
@@ -8,7 +8,7 @@
8
8
  * { margin: 0; padding: 0; box-sizing: border-box; }
9
9
  html, body, #root { width: 100%; height: 100%; overflow: hidden; background: var(--fc-bg); color: var(--fc-text); font-family: system-ui, -apple-system, sans-serif; }
10
10
  </style>
11
- <script type="module" crossorigin src="/assets/index--CYbOPKS.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-Dvz3nSDc.js"></script>
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // cli/forgecad.ts
4
- import { readFileSync as readFileSync15 } from "fs";
4
+ import { readFileSync as readFileSync16 } from "fs";
5
5
 
6
6
  // cli/check-api-contracts.ts
7
7
  import assert from "assert/strict";
@@ -13856,6 +13856,58 @@ function joint(name, shape, pivot, opts = {}) {
13856
13856
  }
13857
13857
 
13858
13858
  // src/forge/group.ts
13859
+ var _groupPlacementRefs = /* @__PURE__ */ new WeakMap();
13860
+ function getGroupRefs(g) {
13861
+ return _groupPlacementRefs.get(g) ?? createPlacementReferences();
13862
+ }
13863
+ function setGroupRefs(g, refs) {
13864
+ if (hasPlacementReferences(refs)) {
13865
+ _groupPlacementRefs.set(g, clonePlacementReferences(refs));
13866
+ } else {
13867
+ _groupPlacementRefs.delete(g);
13868
+ }
13869
+ return g;
13870
+ }
13871
+ function copyGroupRefs(source, dest) {
13872
+ return setGroupRefs(dest, getGroupRefs(source));
13873
+ }
13874
+ function transformGroupRefs(source, dest, matrix) {
13875
+ const refs = getGroupRefs(source);
13876
+ if (hasPlacementReferences(refs)) {
13877
+ setGroupRefs(dest, transformPlacementReferences(refs, matrix));
13878
+ }
13879
+ return dest;
13880
+ }
13881
+ function eulerRotationMatrix(xDeg, yDeg, zDeg) {
13882
+ return Transform.identity().rotateAxis([1, 0, 0], xDeg).rotateAxis([0, 1, 0], yDeg).rotateAxis([0, 0, 1], zDeg).toArray();
13883
+ }
13884
+ function mirrorPlaneMatrix(normal) {
13885
+ const [nx0, ny0, nz0] = normal;
13886
+ const len2 = Math.hypot(nx0, ny0, nz0);
13887
+ if (len2 < 1e-12) return Transform.identity().toArray();
13888
+ const nx = nx0 / len2, ny = ny0 / len2, nz = nz0 / len2;
13889
+ const m00 = 1 - 2 * nx * nx, m01 = -2 * nx * ny, m02 = -2 * nx * nz;
13890
+ const m10 = -2 * ny * nx, m11 = 1 - 2 * ny * ny, m12 = -2 * ny * nz;
13891
+ const m20 = -2 * nz * nx, m21 = -2 * nz * ny, m22 = 1 - 2 * nz * nz;
13892
+ return [
13893
+ m00,
13894
+ m10,
13895
+ m20,
13896
+ 0,
13897
+ m01,
13898
+ m11,
13899
+ m21,
13900
+ 0,
13901
+ m02,
13902
+ m12,
13903
+ m22,
13904
+ 0,
13905
+ 0,
13906
+ 0,
13907
+ 0,
13908
+ 1
13909
+ ];
13910
+ }
13859
13911
  function normalizeChildName(name) {
13860
13912
  if (typeof name !== "string") return void 0;
13861
13913
  const trimmed = name.trim();
@@ -13917,10 +13969,29 @@ var ShapeGroup = class _ShapeGroup {
13917
13969
  childName(index) {
13918
13970
  return this.childNames[index];
13919
13971
  }
13972
+ /**
13973
+ * Return the named child by name. Throws if not found.
13974
+ * Useful when importing a multipart group and working on components individually.
13975
+ */
13976
+ child(name) {
13977
+ const idx = this.childNames.indexOf(name);
13978
+ if (idx === -1) {
13979
+ const available = this.childNames.filter(Boolean).join(", ") || "none";
13980
+ throw new Error(`ShapeGroup has no child named "${name}". Available: ${available}`);
13981
+ }
13982
+ return this.children[idx];
13983
+ }
13984
+ /** Apply fn to all children, producing a new ShapeGroup that also copies placement refs. */
13920
13985
  mapChildren(fn) {
13921
- return new _ShapeGroup(this.children.map(fn), this.childNames);
13986
+ const next = new _ShapeGroup(this.children.map(fn), this.childNames);
13987
+ return copyGroupRefs(this, next);
13988
+ }
13989
+ /** Apply fn to all children and also transform placement refs by the given matrix. */
13990
+ mapChildrenTransform(fn, matrix) {
13991
+ const next = new _ShapeGroup(this.children.map(fn), this.childNames);
13992
+ return transformGroupRefs(this, next, matrix);
13922
13993
  }
13923
- /** Return a deep-cloned ShapeGroup tree. */
13994
+ /** Return a deep-cloned ShapeGroup tree (refs copied). */
13924
13995
  clone() {
13925
13996
  return this.mapChildren((c) => {
13926
13997
  if (c instanceof _ShapeGroup) return c.clone();
@@ -13934,12 +14005,13 @@ var ShapeGroup = class _ShapeGroup {
13934
14005
  return this.clone();
13935
14006
  }
13936
14007
  translate(x, y, z) {
13937
- return this.mapChildren((c) => {
14008
+ const matrix = Transform.translation(x, y, z).toArray();
14009
+ return this.mapChildrenTransform((c) => {
13938
14010
  if (c instanceof _ShapeGroup) return c.translate(x, y, z);
13939
14011
  if (c instanceof TrackedShape) return c.translate(x, y, z);
13940
14012
  if (c instanceof Shape) return c.translate(x, y, z);
13941
14013
  return c.translate(x, y);
13942
- });
14014
+ }, matrix);
13943
14015
  }
13944
14016
  /** Compute combined bounding box of all 3D children */
13945
14017
  _bbox() {
@@ -14001,7 +14073,18 @@ var ShapeGroup = class _ShapeGroup {
14001
14073
  return { min: b.min, max: b.max };
14002
14074
  })();
14003
14075
  const sbb = this._bbox();
14004
- const tp = target instanceof _ShapeGroup || isAnchor3D(targetAnchor) ? resolveAnchor3D(tbb.min, tbb.max, targetAnchor) : target instanceof TrackedShape ? target.referencePoint(targetAnchor) : target.referencePoint(targetAnchor);
14076
+ let tp;
14077
+ if (isAnchor3D(targetAnchor)) {
14078
+ tp = resolveAnchor3D(tbb.min, tbb.max, targetAnchor);
14079
+ } else if ("referencePoint" in target && typeof target.referencePoint === "function") {
14080
+ tp = target.referencePoint(targetAnchor);
14081
+ } else {
14082
+ const normalized = normalizeAnchor3D(targetAnchor);
14083
+ if (!normalized) {
14084
+ throw new Error(`Unknown anchor "${targetAnchor}" on target`);
14085
+ }
14086
+ tp = resolveAnchor3D(tbb.min, tbb.max, normalized);
14087
+ }
14005
14088
  const sp = resolveAnchor3D(sbb.min, sbb.max, selfAnchor);
14006
14089
  let dx = tp[0] - sp[0], dy = tp[1] - sp[1], dz = tp[2] - sp[2];
14007
14090
  if (offset) {
@@ -14029,12 +14112,13 @@ var ShapeGroup = class _ShapeGroup {
14029
14112
  return this.attachTo(parent, face, opp[face], uvMap[face](u, v, p));
14030
14113
  }
14031
14114
  rotate(x, y, z) {
14032
- return this.mapChildren((c) => {
14115
+ const matrix = eulerRotationMatrix(x, y, z);
14116
+ return this.mapChildrenTransform((c) => {
14033
14117
  if (c instanceof _ShapeGroup) return c.rotate(x, y, z);
14034
14118
  if (c instanceof TrackedShape) return c.rotate(x, y, z);
14035
14119
  if (c instanceof Shape) return c.rotate(x, y, z);
14036
14120
  return c.rotate(x);
14037
- });
14121
+ }, matrix);
14038
14122
  }
14039
14123
  /**
14040
14124
  * Rotate around an arbitrary axis through a pivot point.
@@ -14076,28 +14160,32 @@ var ShapeGroup = class _ShapeGroup {
14076
14160
  }
14077
14161
  /** Apply a 4x4 transform matrix or Transform object to all 3D children. */
14078
14162
  transform(m) {
14079
- return new _ShapeGroup(this.children.map((c) => {
14163
+ const matrix = m instanceof Transform ? m.toArray() : m;
14164
+ const next = new _ShapeGroup(this.children.map((c) => {
14080
14165
  if (c instanceof _ShapeGroup) return c.transform(m);
14081
14166
  if (c instanceof TrackedShape) return c.transform(m);
14082
14167
  if (c instanceof Shape) return c.transform(m);
14083
14168
  throw new Error("ShapeGroup.transform only supports 3D children (Shape/TrackedShape/ShapeGroup). For Sketch children, use 2D transforms (translate/rotate/scale/mirror).");
14084
14169
  }), this.childNames);
14170
+ return transformGroupRefs(this, next, matrix);
14085
14171
  }
14086
14172
  scale(v) {
14087
- return this.mapChildren((c) => {
14173
+ const matrix = Transform.scale(v).toArray();
14174
+ return this.mapChildrenTransform((c) => {
14088
14175
  if (c instanceof _ShapeGroup) return c.scale(v);
14089
14176
  if (c instanceof TrackedShape) return c.scale(v);
14090
14177
  if (c instanceof Shape) return c.scale(v);
14091
14178
  return c.scale(typeof v === "number" ? v : [v[0], v[1]]);
14092
- });
14179
+ }, matrix);
14093
14180
  }
14094
14181
  mirror(normal) {
14095
- return this.mapChildren((c) => {
14182
+ const matrix = mirrorPlaneMatrix(normal);
14183
+ return this.mapChildrenTransform((c) => {
14096
14184
  if (c instanceof _ShapeGroup) return c.mirror(normal);
14097
14185
  if (c instanceof TrackedShape) return c.mirror(normal);
14098
14186
  if (c instanceof Shape) return c.mirror(normal);
14099
14187
  return c.mirror([normal[0], normal[1]]);
14100
- });
14188
+ }, matrix);
14101
14189
  }
14102
14190
  color(hex) {
14103
14191
  return this.mapChildren((c) => {
@@ -14107,6 +14195,70 @@ var ShapeGroup = class _ShapeGroup {
14107
14195
  return c.color(hex);
14108
14196
  });
14109
14197
  }
14198
+ // --- Placement References ---
14199
+ /**
14200
+ * Attach named placement references to this group.
14201
+ * References survive normal transforms (translate/rotate/scale/mirror/transform).
14202
+ *
14203
+ * ```javascript
14204
+ * const bracket = group(
14205
+ * { name: 'Left', shape: leftShape },
14206
+ * { name: 'Right', shape: rightShape },
14207
+ * ).withReferences({
14208
+ * points: { mountCenter: [0, 0, 0] },
14209
+ * });
14210
+ * ```
14211
+ */
14212
+ withReferences(refs) {
14213
+ const next = new _ShapeGroup(this.children, this.childNames);
14214
+ const merged = applyPlacementReferenceInput(getGroupRefs(this), refs);
14215
+ return setGroupRefs(next, merged);
14216
+ }
14217
+ /** List named placement references carried by this group. */
14218
+ referenceNames(kind) {
14219
+ return placementReferenceNames(getGroupRefs(this), kind);
14220
+ }
14221
+ /**
14222
+ * Resolve a named placement reference or built-in Anchor3D to a 3D point.
14223
+ * Named refs take priority over built-in anchors.
14224
+ */
14225
+ referencePoint(ref) {
14226
+ const refs = getGroupRefs(this);
14227
+ if (!isAnchor3D(ref)) {
14228
+ const point2 = resolvePlacementReferencePoint(refs, ref);
14229
+ if (point2) return point2;
14230
+ const normalized = normalizeAnchor3D(ref);
14231
+ if (normalized) {
14232
+ const bb2 = this._bbox();
14233
+ return resolveAnchor3D(bb2.min, bb2.max, normalized);
14234
+ }
14235
+ throw new Error(
14236
+ `Unknown placement reference "${ref}". Available: ${placementReferenceNames(refs).join(", ") || "none"}`
14237
+ );
14238
+ }
14239
+ const bb = this._bbox();
14240
+ return resolveAnchor3D(bb.min, bb.max, ref);
14241
+ }
14242
+ /**
14243
+ * Translate the group so the given reference lands on the target coordinate.
14244
+ *
14245
+ * ```javascript
14246
+ * const placed = importGroup('bracket-assembly.forge.js')
14247
+ * .placeReference('mountCenter', [0, 0, 50]);
14248
+ * ```
14249
+ */
14250
+ placeReference(ref, target, offset) {
14251
+ const sourcePoint = this.referencePoint(ref);
14252
+ let dx = target[0] - sourcePoint[0];
14253
+ let dy = target[1] - sourcePoint[1];
14254
+ let dz = target[2] - sourcePoint[2];
14255
+ if (offset) {
14256
+ dx += offset[0];
14257
+ dy += offset[1];
14258
+ dz += offset[2];
14259
+ }
14260
+ return this.translate(dx, dy, dz);
14261
+ }
14110
14262
  };
14111
14263
  function group(...items) {
14112
14264
  const normalized = normalizeGroupInputs(items);
@@ -18116,6 +18268,26 @@ function executeFile(code, fileName, allFiles, visited, scope = {}, options, exe
18116
18268
  logImportTrace(fileName, scope, options, "importPart", resolvedPath, "error", { requested: name, got });
18117
18269
  throw new Error(`"${resolvedPath}" did not return a Shape (got ${got})`);
18118
18270
  };
18271
+ const importGroup = (name, paramOverrides) => {
18272
+ const { source: src, lookupKey, resolvedPath } = resolveImportSource(fileName, name, allFiles, options);
18273
+ const localOverrides = parseImportParamArgs("importGroup", name, paramOverrides);
18274
+ const childScope = { namePrefix: makeChildScopePrefix(resolvedPath), localOverrides };
18275
+ logImportTrace(fileName, scope, options, "importGroup", resolvedPath, "start", { requested: name, overrides: localOverrides });
18276
+ let result;
18277
+ try {
18278
+ result = executeFile(src, lookupKey, allFiles, visited, childScope, options);
18279
+ } catch (error) {
18280
+ logImportTrace(fileName, scope, options, "importGroup", resolvedPath, "error", { requested: name, error: formatLogError(error) });
18281
+ throw error;
18282
+ }
18283
+ if (result instanceof ShapeGroup) {
18284
+ logImportTrace(fileName, scope, options, "importGroup", resolvedPath, "success", { requested: name, got: "ShapeGroup" });
18285
+ return result;
18286
+ }
18287
+ const got = describeScriptResultType(result);
18288
+ logImportTrace(fileName, scope, options, "importGroup", resolvedPath, "error", { requested: name, got });
18289
+ throw new Error(`"${resolvedPath}" did not return a ShapeGroup (got ${got}). Use group(...) as the return value, or use importPart() for single-shape files.`);
18290
+ };
18119
18291
  const unwrap2 = (s) => s instanceof TrackedShape ? s.toShape() : s;
18120
18292
  const wrappedUnion = (...shapes) => union(...shapes.map(unwrap2));
18121
18293
  const wrappedDifference = (...shapes) => difference(...shapes.map(unwrap2));
@@ -18202,6 +18374,7 @@ function executeFile(code, fileName, allFiles, visited, scope = {}, options, exe
18202
18374
  projectToPlane,
18203
18375
  importSketch,
18204
18376
  importPart,
18377
+ importGroup,
18205
18378
  importSvgSketch,
18206
18379
  dim,
18207
18380
  dimLine,
@@ -35805,12 +35978,14 @@ var API_EXACT_PART_PATHS = [
35805
35978
  "examples/api/colors-union-vs-array.forge.js",
35806
35979
  "examples/api/coordinate-system.forge.js",
35807
35980
  "examples/api/dimensioned-bracket.forge.js",
35981
+ "examples/api/face-transformation-history.forge.js",
35808
35982
  "examples/api/feature-created-faces.forge.js",
35809
35983
  "examples/api/folded-service-panel-cover.forge.js",
35810
35984
  "examples/api/group-vs-union.forge.js",
35811
35985
  "examples/api/import-args-unit.forge.js",
35812
35986
  "examples/api/import-args.forge.js",
35813
35987
  "examples/api/import-dimensions-follow.forge.js",
35988
+ "examples/api/import-group-source.forge.js",
35814
35989
  "examples/api/import-placement-references.forge.js",
35815
35990
  "examples/api/import-placement-widget-source.forge.js",
35816
35991
  "examples/api/import-relative-paths.forge.js",
@@ -35970,6 +36145,11 @@ var RUNTIME_SCENE_ENTRIES = [
35970
36145
  note: "This example is judged by runtime scene behavior rather than by exact part-lowering parity.",
35971
36146
  expect: { minUniqueGroups: 3 }
35972
36147
  },
36148
+ {
36149
+ path: "examples/api/import-group-assembly.forge.js",
36150
+ note: "Multipart importGroup() demo: validates group import, child access, and param overrides at runtime.",
36151
+ expect: { minUniqueGroups: 1 }
36152
+ },
35973
36153
  {
35974
36154
  path: "examples/api/section-plane-visualization.forge.js",
35975
36155
  note: "This example is judged by runtime scene behavior rather than by exact part-lowering parity.",
@@ -41554,7 +41734,7 @@ import { mkdirSync as mkdirSync3, readFileSync as readFileSync10, writeFileSync
41554
41734
  import { dirname as dirname8, extname as extname3, resolve as resolve15 } from "path";
41555
41735
 
41556
41736
  // src/forge/exportMesh.ts
41557
- import { Export3MF } from "manifold-3d/lib/export-3mf.js";
41737
+ import { toArrayBuffer as export3mfToArrayBuffer } from "manifold-3d/lib/export-3mf.js";
41558
41738
  import {
41559
41739
  GLTFNode,
41560
41740
  GLTFNodesToGLTFDoc,
@@ -43678,23 +43858,28 @@ Dimension list${showAll ? "" : " (first 20)"}:`);
43678
43858
  }
43679
43859
 
43680
43860
  // cli/forge-skill.ts
43681
- import { copyFileSync, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
43861
+ import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
43682
43862
  import { homedir as homedir2 } from "os";
43683
43863
  import { join as join7 } from "path";
43684
43864
  async function runSkillInstallCli(_argv = []) {
43685
- const src = resolvePackagePath(import.meta.url, "dist-skill", "SKILL.md");
43686
- if (!existsSync6(src)) {
43865
+ const srcSkill = resolvePackagePath(import.meta.url, "dist-skill", "SKILL.md");
43866
+ const srcDocs = resolvePackagePath(import.meta.url, "dist-skill", "docs");
43867
+ if (!existsSync6(srcSkill)) {
43687
43868
  throw new Error(
43688
- `Built skill file not found at ${src}.
43869
+ `Built skill file not found at ${srcSkill}.
43689
43870
  If you are running from a source checkout, run: npm run build:skill:forgecad`
43690
43871
  );
43691
43872
  }
43692
43873
  const destDir = join7(homedir2(), ".agents", "skills", "forgecad");
43693
43874
  const dest = join7(destDir, "SKILL.md");
43694
43875
  mkdirSync4(destDir, { recursive: true });
43695
- copyFileSync(src, dest);
43876
+ const skillContent = readFileSync15(srcSkill, "utf-8").replaceAll("{{SKILL_DIR}}", destDir);
43877
+ writeFileSync8(dest, skillContent);
43878
+ if (existsSync6(srcDocs)) {
43879
+ cpSync(srcDocs, join7(destDir, "docs"), { recursive: true });
43880
+ }
43696
43881
  console.log(`ForgeCAD skill installed to ${dest}`);
43697
- console.log(`Reload Claude Code to activate.`);
43882
+ console.log(`Reload your agent (Claude Code, Codex, OpenCode, \u2026) to activate.`);
43698
43883
  }
43699
43884
 
43700
43885
  // cli/forgecad.ts
@@ -43850,7 +44035,7 @@ var commands = [
43850
44035
  {
43851
44036
  group: "Shell",
43852
44037
  path: ["skill", "install"],
43853
- summary: "Install the ForgeCAD Claude Code skill to ~/.agents/skills/forgecad/SKILL.md.",
44038
+ summary: "Install the ForgeCAD agent skill to ~/.agents/skills/forgecad/SKILL.md (Claude Code, Codex, OpenCode, \u2026).",
43854
44039
  usage: ["forgecad skill install"],
43855
44040
  examples: ["forgecad skill install"],
43856
44041
  run: runSkillInstallCli
@@ -44316,7 +44501,7 @@ var commands = [
44316
44501
  ];
44317
44502
  function readVersion() {
44318
44503
  try {
44319
- const pkg = JSON.parse(readFileSync15(resolvePackagePath(import.meta.url, "package.json"), "utf-8"));
44504
+ const pkg = JSON.parse(readFileSync16(resolvePackagePath(import.meta.url, "package.json"), "utf-8"));
44320
44505
  return pkg.version || "0.0.0";
44321
44506
  } catch {
44322
44507
  return "0.0.0";