Reflexo Release
Myriad-Dreamin/typst.ts
Guide Reflexo/typst.ts release preparation and operator handoffs.
This skill should be used when working across the JS/WASM boundary in brepjs — writing or debugging code in src/kernel/occt, src/kernel/occtWasm, or src/kernel/brepkit, or diagnosing symptoms like…
$ npx skills add andymai/brepjs --skill wasm-interop -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install andymai/brepjs wasm-interop --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/wasm-interop .claude/skills/wasm-interop && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "wasm-interop" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interop into .claude/skills/wasm-interop/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wasm-interop", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interopType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add andymai/brepjs --skill wasm-interop -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install andymai/brepjs wasm-interop --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/wasm-interop .agents/skills/wasm-interop && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "wasm-interop" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interop into .agents/skills/wasm-interop/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wasm-interop", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add andymai/brepjs --skill wasm-interop -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install andymai/brepjs wasm-interop --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/wasm-interop .cursor/skills/wasm-interop && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "wasm-interop" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interop into .cursor/skills/wasm-interop/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wasm-interop", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/andymai/brepjs.git --path .claude/skills/wasm-interop--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add andymai/brepjs --skill wasm-interop -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install andymai/brepjs wasm-interop --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/wasm-interop .gemini/skills/wasm-interop && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "wasm-interop" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interop into .gemini/skills/wasm-interop/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wasm-interop", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install andymai/brepjs wasm-interopInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add andymai/brepjs --skill wasm-interop -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/wasm-interop .github/skills/wasm-interop && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "wasm-interop" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interop into .github/skills/wasm-interop/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wasm-interop", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add andymai/brepjs --skill wasm-interop -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install andymai/brepjs wasm-interop --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/wasm-interop .opencode/skills/wasm-interop && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "wasm-interop" agent skill from https://github.com/andymai/brepjs/tree/main/.claude/skills/wasm-interop into .opencode/skills/wasm-interop/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wasm-interop", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
wasm-interopThis skill should be used when working across the JS/WASM boundary in brepjs — writing or debugging code in src/kernel/occt, src/kernel/occtWasm, or src/kernel/brepkit, or diagnosing symptoms like…
Wasm Interop is an agent skill from andymai/brepjs. This skill should be used when working across the JS/WASM boundary in brepjs — writing or debugging code in src/kernel/occt, src/kernel/occtWasm, or src/kernel/brepkit, or diagnosing symptoms like "enum comparison is always false", "GetType returned an object not a number", "mesh vertices are garbage or zeros", "detached ArrayBuffer", ".map on a Uint32Array produces wrong values", "brepjs kernel not initialized", "brepjssingle.js is missing", "init() falls back to the wrong kernel", "dynamic import of occt-wasm…
Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/opencascade-build.md`).
It sits in DevOps & Cloud. It works with WebAssembly, Docker and Vite. The repository describes itself as: Web CAD library with exact B-Rep geometry. The licence is Apache-2.0.
Read from SKILL.md and the folder at commit 6e20740. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
bashFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Wasm Interop loads about 3k tokens when it runs, and up to ~5.5k if it reads all its reference files. Until then it costs about 207 tokens; SKILL.md has 1,225 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from andymai/brepjs at commit 6e20740, republished under its Apache-2.0 licence (© andymai). 1,225 words, ~3,032 tokens.
.claude/skills/wasm-interop/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Cover the mechanics of the JS↔WASM boundary in the kernel adapters: how Emscripten enums cross, how to read the WASM heap without corrupting it, how initialization and the bundler-safe fallback chain work, and why every shipped build is single-threaded. Adapter/registry/capability design lives in the kernel-abstraction skill — this skill stays on the raw Emscripten mechanics.
src/kernel/occt/ (brepjs-opencascade facade), src/kernel/occtWasm/ (occt-wasm, the default kernel), or src/kernel/brepkit/.OCCT is bound with embind, which surfaces C++ enums as objects, not numbers.
Values coming OUT — never compare a raw enum result to an integer. Extract with the canonical idiom (src/kernel/occt/geometryQueryOps.ts):
const typeVal = adaptor.GetType();
// OCCT Emscripten returns enum objects with a .value property
const idx = typeof typeVal === 'number' ? typeVal : Number(typeVal?.value ?? typeVal);Then map the number through a Record<number, string> (geometryQueryOps.ts). The same pattern recurs in nurbsQueryOps.ts and manifold/repairOps.ts.
Values going IN — pass the enum object straight from the oc instance, not an integer. Constructors and comparisons both accept the object form (src/kernel/occt/topologyOps.ts):
const ta = oc.TopAbs_ShapeEnum;
new oc.TopExp_Explorer_2(shape, ta.TopAbs_FACE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE);Identity comparison against the object works and is preferred over .value on the IN side (geometryQueryOps.ts):
const orient = shape.Orientation_1();
if (orient === oc.TopAbs_Orientation.TopAbs_FORWARD) return 'forward';Enum-object maps are cached per oc instance in a WeakMap (topologyOps.ts) — build once, reuse; do not rebuild them per call.
Overloaded constructors get numeric suffixes. Embind renames overloads _1, _2, … — TopExp_Explorer_2, BRepAdaptor_Curve_2, Orientation_1. A "not a constructor" or wrong-arity error usually means the wrong suffix; grep a working call site (geometryQueryOps.ts) for the right one.
| Symptom | Cause | Fix |
|---|---|---|
| Enum comparison always false | Compared object to an int | Extract .value, or compare against oc.<Enum>.<MEMBER> |
GetType() returns [object] | Embind enum object | Use the .value extraction idiom |
X_2 is not a constructor | Wrong embind overload suffix | Match the _N at a known-good call site |
Read heap pointers, slice before the next WASM call. The brepjs-opencascade facade returns raw pointers + sizes; copy into an owned TypedArray before any other WASM call could grow or relocate the heap — the build sets ALLOW_MEMORY_GROWTH=1, so a stale heap view becomes a detached/garbage buffer (src/kernel/occt/meshOps.ts). Divide byte pointers by 4 for the 32-bit heap index, slice, then free the C++ side with raw.delete() (meshOps.ts):
const offset = ptr / 4; // byte ptr → HEAPF32 index
return heap.slice(offset, offset + size); // copy now, before any other WASM callThe occt-wasm adapter reads element-by-element with a ?? 0 fallback because noUncheckedIndexedAccess is on (src/kernel/occtWasm/meshOps.ts); it uses >> 2 for the same byte→index divide. For a structurally-guaranteed index (WASM ABI fixed arrays, post-bounds-check loops) use the sanctioned escape hatch wasmIndex<T>(arr, i) in src/utils/vec3.ts instead of a bare !.
Convert Uint32Array to number[] only for JS array methods. .map/.filter/.flatMap on a Uint32Array coerce results back to u32 (and cannot produce objects), so convert first with toArray(ids) = Array.from(ids) (src/kernel/brepkit/helpers.ts). This is not a rule about passing arrays into the kernel — brepkit methods accept Uint32Array | number[], and booleanOps.ts passes new Uint32Array(...) straight into bk.compoundFuse(...). (CLAUDE.md's blanket "always convert before passing to kernel methods" overstates it; the real reason is the map/filter coercion.)
No zero-copy between separate WASM linear memories — each kernel instance owns its own heap, so copy bytes across with copyWasmBytes(bytes) (helpers.ts) or re-serialize via a BREP string. See docs/decisions/0013-voxel-domain.md.
| Symptom | Cause | Fix |
|---|---|---|
| Mesh vertices are garbage / zeros after a later op | Heap view read after a WASM call grew it | Slice into an owned array immediately |
| Detached ArrayBuffer error | Held a HEAP view across an allocation | Copy first; never store a raw heap subarray |
.map on IDs yields wrong values | u32 coercion of typed-array map | Array.from(ids) / toArray first |
| Off-by-4 / nonsense offsets | Used byte pointer as element index | Divide by 4 (ptr / 4 or >> 2) |
Handle .delete() on occt-wasm and brepkit handles is a no-op — those adapters use an arena/id model, not per-handle embind objects (occtWasm/occtWasmTypes.ts, brepkit/helpers.ts). Free with the adapter's dispose/release, not by chasing .delete(). Disposal semantics belong to the memory-and-disposal skill.
init() (src/kernel/index.ts) is idempotent (returns the current kernel id immediately) and tries, in order: occt-wasm → brepjs-opencascade (initFromOC, returns 'occt') → brepkit-wasm, throwing with install instructions if none load. brepjs/quick (src/quick.ts) does the same as a top-level await but with the brepjs-opencascade fallback only (no brepkit). All three kernel packages are optional peerDependencies (package.json).
Every optional backend loads through importOptionalBackend(specifier) (src/kernel/optionalBackend.ts). The specifier is a variable so no bundler (esbuild, Rollup, Vite import-analysis) can statically resolve it — an uninstalled peer stays a runtime import instead of hard-failing the build. A string literal with only a @vite-ignore comment regressed when Vite reflowed the comment (#1726). When adding a new optional backend, route it through this function; never write a literal import('occt-wasm').
initFromOC(oc) (index.ts) resets seven feature-detection caches (measure, transform, boolean/loft/extrude/shell/fillet batch), registers DefaultAdapter as 'occt', and forces it default. Call it when hand-wiring the brepjs-opencascade instance; skipping the cache reset leaves stale capability flags.
prewarm() (index.ts) builds and disposes a 1×1×1 box to pay OCCT's ~400-900 ms first-call JIT cost off the critical path. Fire-and-forget after init() resolves.
getKernel() throws brepjs kernel not initialized. Call initFromOC() or registerKernel() when nothing is registered — that message means init was skipped, not that WASM is broken.
Missing WASM artifacts. packages/brepjs-opencascade/src/*.js and *.wasm are gitignored (.gitignore:31-36); only .d.ts files are tracked. A brepjs_single.js is missing error means restore them from the published tarball with bash scripts/ensure-wasm.sh (version-stamped via src/.wasm-version; CI runs it) — not a Docker build.
Tests. tests/setup.ts re-exports initOC (alias of initOCCT) from tests/setup-kernel.ts; TEST_KERNEL selects occt | brepkit | occt-wasm | manifold, defaulting to occt-wasm. Under vitest, brepkit-wasm is aliased to its Node CJS entry because the ESM entry uses the unsupported WASM-ESM-integration proposal (vitest.config.ts). See the writing-tests skill for the multi-kernel test setup.
Every shipped kernel build is single-threaded. The brepjs-opencascade build compiles without -pthread (packages/brepjs-opencascade/build-config/brepjs.yml), and occt-wasm's README states "Single WASM thread — each kernel instance is single-threaded." Consequences:
op.SetRunParallel(true) (src/kernel/occt/booleanOps.ts) and the facade's SetRunParallel(Standard_True) degrade to sequential in a threadless build — effectively no-ops. Do not expect a speedup from them; the meshing path passes isInParallel = Standard_False deliberately.src/worker/ exchanges BREP strings across the boundary (workerHandler.ts calls initFn(msg.wasmUrl) on init), and occt-wasm ships an occt-wasm/worker export (OcctWorker.spawn, Comlink) whose handles are worker-local. A handle from one instance is meaningless in another.Vitest test-runner config (pool, workers, memory cap, timeout) is owned by the writing-tests skill; the WASM-specific reason those knobs stay conservative is that OCCT WASM linear memory grows monotonically across a fork's files, so over-committing workers trips timeouts (#1102).
Reproduce a suspected kernel bug in JS/TS against the installed WASM first. A Docker rebuild of the OpenCascade WASM (ghcr.io/andymai/opencascade.js:v8, via the brepjs-opencascade buildWasm/buildSingle scripts, then wasm-opt) takes on the order of hours — treat it as the last resort. Complete all C++ facade edits before starting a build. The C++ binding surface (facade classes like MeshExtractor, BooleanBatch, BooleanPipeline, EvolutionExtractor, TopoDS_Cast, manual Bnd_Box bindings) and the emcc flags live in build-config/brepjs.yml; see references/opencascade-build.md for the inventory and flag list. Note docs/compatibility.md still says "WASM SIMD ❌ Not used" — that line is stale; the build passes -msimd128 -mrelaxed-simd. Trust the yml.
references/opencascade-build.md — brepjs.yml C++ facade-class inventory + emcc flags.docs/kernel-swap.md — full init/registration guide for all three kernels.docs/compatibility.md — bundler externalization, WASM variants/sizes, threading (SIMD line is stale).docs/memory-management.md — using/Symbol.dispose, DisposalScope, manual delete().kernel-abstraction skill — KernelAdapter, capabilities, withKernel/quality-tier semantics.memory-and-disposal skill — handle lifecycle and disposal ordering.writing-tests skill — vitest runner config and multi-kernel test setup.© andymai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file (references) in .claude/skills/wasm-interop of andymai/brepjs.
Open the folder on GitHubat commit 6e20740
Wasm Interop next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Wasm Interop this skillandymai/brepjs | 115 | — | ~3k | Automated safety check: Pass | Apache-2.0 | |
| Reflexo ReleaseMyriad-Dreamin/typst.ts | 1.2k | — | ~1.5k | Automated safety check: Pass | Apache-2.0 | |
| Compile Php WasmWordPress/wordpress-playground | 2k | — | ~2.8k | Automated safety check: Pass | GPL-2.0 | |
| Fungienbop/fungi | 132 | — | ~2.9k | Automated safety check: Pass | Apache-2.0 | |
| Devinggo Generatorhuagelong/devinggo | 122 | — | ~3.3k | Automated safety check: Pass | Apache-2.0 | |
| Pwa ReleaseAHS12/thoth-blueprint | 625 | — | ~505 | Automated safety check: Pass | GPL-3.0 |
Myriad-Dreamin/typst.ts
Guide Reflexo/typst.ts release preparation and operator handoffs.
WordPress/wordpress-playground
Compile PHP.wasm main modules and side modules (dynamic extensions) for Node.js and web platforms.
enbop/fungi
Install, configure, and operate the Fungi CLI across devices.
huagelong/devinggo
DevingGo 代码生成器 CLI 工具集。当用户需要生成 CRUD 代码、创建模块、管理 Worker 任务、 导入导出模块、或需要快速搭建后端/前端代码时使用。适用于任何涉及代码生成、模块管理、 数据库表对应的前后端代码生成的场景。
AHS12/thoth-blueprint
Safely change Vite, service-worker, offline fallback, cache, Docker, Vercel, or release-distribution behavior.
latitude-dev/latitude-llm
Adding or reading env vars, updating .env.example, or validating config at startup with parseEnv / parseEnvOptional.
andymai/brepjs
A skill your agent uses when authoring or editing a brepjs .brep.ts part — writing the geometry with the functional API (box, cylinder, fuse, cut, fillet, sketch→extrude…), declaring an expected…
andymai/brepjs
This skill should be used when managing WASM handle lifetimes or hunting memory leaks in brepjs — when a task mentions "createHandle() without using keyword risks WASM memory leak"…
andymai/brepjs
A skill your agent uses when a valid brepjs part should look designed rather than glued-from-primitives (products, toys, mechanisms, anything a human eyeballs), and when exporting/handing off the…
andymai/brepjs
This skill should be used when writing, running, or fixing tests in the brepjs repository — when a task says "add a test", "write a regression test", "tests are failing", "test timed out", "coverage…
andymai/brepjs
This skill should be used when adding or extending a geometric shape operation in brepjs — the end-to-end recipe once the target module is chosen (which is decided by architecture-navigation) — when…
andymai/brepjs
This skill should be used when deciding which layer or module a new file, function, or directory belongs in, or when a layer-boundary check fails.
Works with
Categories
This skill should be used when working across the JS/WASM boundary in brepjs — writing or debugging code in src/kernel/occt, src/kernel/occtWasm, or src/kernel/brepkit, or diagnosing symptoms like…. Wasm Interop is an agent skill from andymai/brepjs.
Wasm Interop fits situations like: devOps & Cloud work in your project.
Run `npx skills add andymai/brepjs --skill wasm-interop -a claude-code`. Or copy the skill folder (.claude/skills/wasm-interop in andymai/brepjs) into .claude/skills/wasm-interop in your project. Claude Code loads it when a task matches its description.
Run `npx skills add andymai/brepjs --skill wasm-interop -a codex`. Or copy the skill folder (.claude/skills/wasm-interop in andymai/brepjs) into .agents/skills/wasm-interop in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add andymai/brepjs --skill wasm-interop -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/wasm-interop, .gemini/skills/wasm-interop, .github/skills/wasm-interop and .opencode/skills/wasm-interop in your project.
Going by SKILL.md and its folder, Wasm Interop needs the command-line tools its instructions call (bash). Our summary lists: Docker.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Wasm Interop is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.5k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Wasm Interop: Reflexo Release (Myriad-Dreamin/typst.ts, 1.2k stars), Compile Php Wasm (WordPress/wordpress-playground, 2k stars), Fungi (enbop/fungi, 132 stars) and Devinggo Generator (huagelong/devinggo, 122 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
andymai (a GitHub user) maintains it in andymai/brepjs, which has 115 GitHub stars. The repository holds 21 skills in this directory. The repository was last updated on October 8, 2026.
Source: andymai/brepjs on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.