Agent skill

Shaperef Lineage

by andymai in andymai/brepjs

This skill should be used when debugging or extending stable references (topological naming) and history replay in brepjs — when a task says "ShapeRef resolves to the wrong face/edge", "ref won't…

Apache-2.0Auto-check passedDevelopment

Install Shaperef Lineage

skills CLI
$ npx skills add andymai/brepjs --skill shaperef-lineage -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install andymai/brepjs shaperef-lineage --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/andymai/brepjs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/shaperef-lineage .claude/skills/shaperef-lineage && rm -rf skills-src

Use ~/.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/

Facts

Skill name
shaperef-lineage
GitHub stars
114
Token cost
~3.8k tokens
SKILL.md length
1,482 words
Files
1
Skills in repo
21
Repo updated
First seen
Licence
Apache-2.0

At a glance

This skill should be used when debugging or extending stable references (topological naming) and history replay in brepjs — when a task says "ShapeRef resolves to the wrong face/edge", "ref won't…

  • Works in 4 steps: Re-derive each of the two bridged faces… → betweenFaces = faces adjacent to both… → Keep only faces whose normal has a… → …
  • Development work in your project
  • SKILL.md covers Mental model in six lines, The occt-wasm generated /…, Symptom → cause → fix and Failure taxonomy by ref kind, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Shaperef Lineage is an agent skill from andymai/brepjs. This skill should be used when debugging or extending stable references (topological naming) and history replay in brepjs — when a task says "ShapeRef resolves to the wrong face/edge", "ref won't resolve / returns not-found / BrokenRef", "resolveRef returns ambiguous", "add a new reference kind / ref type", "fillet face has no stable hash", "generated evolution is empty on occt-wasm", "selection lost after editing an upstream parameter", "history replay re-targets the wrong entity", "role table / assignRoles /…

Its SKILL.md is about 3.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development. It works with WebAssembly. The repository describes itself as: Web CAD library with exact B-Rep geometry. The licence is Apache-2.0.

When your agent uses it

  • Development work in your project

Example prompts

  • “ShapeRef resolves to the wrong face/edge”
  • “ref won”
  • “resolveRef returns ambiguous”
  • “/shaperef-lineage”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Re-derive each of the two bridged faces via the role table, else via facesByNormal (faces whose normal dotted with the captured normal…
  2. betweenFaces = faces adjacent to both bridged faces (via cached edge→face adjacency).
  3. Keep only faces whose normal has a positive component (> BLEND_THRESHOLD = 0.1) along both bridged normals — this rejects the orthogonal…
  4. One survivor → resolved; several → nearest to the captured edgeMidpoint (HINT_MARGIN = 1e-6 tie → ambiguous); none → broken.

What it can do on your machine

Read from SKILL.md and the folder at commit ee50994. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Shaperef Lineage loads about 3.8k tokens when it runs. Until then it costs about 178 tokens; SKILL.md has 1,482 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~178
When it runs · the whole SKILL.md, loaded when a task matches
~3.8k

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.

Safety

Auto-check passed

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.

SKILL.md

The full file from andymai/brepjs at commit ee50994, republished under its Apache-2.0 licence (© andymai). 1,482 words, ~3,804 tokens.

Download SKILL.mdSave it as .claude/skills/shaperef-lineage/SKILL.md (or your agent's skills folder).
name
shaperef-lineage
description
This skill should be used when debugging or extending stable references (topological naming) and history replay in brepjs — when a task says "ShapeRef resolves to the wrong face/edge", "ref won't resolve / returns not-found / BrokenRef", "resolveRef returns ambiguous", "add a new reference kind / ref type", "fillet face has no stable hash", "generated evolution is empty on occt-wasm", "selection lost after editing an upstream parameter", "history replay re-targets the wrong entity", "role table / assignRoles / updateRoles", "lineage ref", "topological naming", "resolveRefParams", "edit-after-reference", or when editing files under src/topology/shapeRef/ or src/operations/historyFns.ts.

Stable references (topological naming) and history replay

Stable references name a face, edge, or vertex by its stable adjacent-neighbour roles instead of a kernel hash, so a selection survives the edits that re-hash the model. The full concept — name-by-neighbours, the four ref kinds, exact vs geometric-fallback confidence, the failure taxonomy, and per-kernel support — is owned by apps/docs/concepts/stable-references.md. Read that page first for the "why"; this skill owns only extension (adding a ref kind) and debugging (a ref that resolves wrong, to nothing, or to the wrong entity after a replay).

The public surface is the brepjs/shapeRef subpath (package.json exports), re-exported from src/shapeRef.ts, src/topology/shapeRef/index.ts, and src/index.ts. Implementation lives under src/topology/shapeRef/.

Mental model in six lines

  • The role table (RoleTable = ReadonlyMap<origin, ReadonlyMap<role, readonly number[]>> in shapeRefTypes.ts) is the spine: origin → role → face hash codes.
  • assignRoles(shape, origin) names faces; updateRoles(roles, origin, evolution) advances those hashes through one operation's ShapeEvolution.
  • Face refs ride hashes through evolution — they can resolve exact.
  • Edge / vertex / derived refs ride their neighbouring face roles, never their own hash — so they sidestep generated hashes entirely.
  • exact = resolved via a tracked hash in the role table; geometric-fallback = resolved via the captured geometric hint (normal, centroid, area).
  • Derived (fillet/chamfer) faces are always geometric — confidence is hardcoded geometric-fallback, they can never be exact.

The occt-wasm generated / fillet gotcha (read this first)

This is the single most important fact in the area, and the cause of most "why won't my fillet face resolve" confusion.

On the OCCT kernels, evolution.generated hashes are never live — they refer to an intermediate shape, not the final result — and fillet/chamfer evolution is empty. Consequences, all deliberate:

  • updateRoles intentionally does not consume evolution.generated (see the comment at the updateRoles docblock in shapeRefFns.ts: "verified: 0 live generated hashes across cut/fuse on occt-wasm"). Naming a generated face via the role table produces a role that never resolves.
  • Derived faces are re-found geometrically, never by hash — see the file header of derivedFaceRefFns.ts.
  • ResolvedDerivedFaceRef.confidence is hardcoded 'geometric-fallback' in shapeRefTypes.ts.
  • Derived-face replay tests are gated to occt-wasm only (not the whole OCCT family) — on OpenCascade.js filleting one edge splits the +Z face into a divergent topology (tests/shapeRefDerivedReplay.test.ts header comment).

How the geometric workaround actually resolves a derived face (resolveDerivedFaceRef in derivedFaceRefFns.ts):

  1. Re-derive each of the two bridged faces via the role table, else via facesByNormal (faces whose normal dotted with the captured normal exceeds NORMAL_MATCH = 0.99).
  2. betweenFaces = faces adjacent to both bridged faces (via cached edge→face adjacency).
  3. Keep only faces whose normal has a positive component (> BLEND_THRESHOLD = 0.1) along both bridged normals — this rejects the orthogonal flanking faces that are also adjacent to both.
  4. One survivor → resolved; several → nearest to the captured edgeMidpoint (HINT_MARGIN = 1e-6 tie → ambiguous); none → broken.

Symptom → cause → fix

SymptomLikely causeFix
Edge/vertex ref returns not-foundRole table stale — facesForRole returned [] because the tracked hash no longer matches any live faceupdateRoles was skipped across an intervening edit; propagate the role table through every operation's ShapeEvolution. Confirm ref.origin matches the string passed to assignRoles. This is the #1 cause.
Face ref resolves to the wrong face on geometric fallbackA scorer reject or a weak hintCheck defaultScorer rejects (below); the true face may be scoring -Infinity. Supply a custom FaceScorer if the geometry is unusual.
resolveRef returns ambiguousTwo candidates tie within a margin, or a duplicated/symmetric featureInspect broken.candidates. Thresholds: AMBIGUITY_THRESHOLD = 0.1 (face scoring), HINT_MARGIN = 1e-6 (edge/vertex/derived hint tiebreak).
Face ref returns deleted; edge/vertex returns not-found for the same vanished featureDifferent taxonomies by kind (below)deleted is expected-skip for a replay engine; edge/vertex/derived can never report deleted (they don't track their own hash) so a vanished entity surfaces as not-found.
Non-primitive origin loses stability on rebuildOnly box/cylinder/cone/sphere get semantic roles; everything else falls back to positional opType:face_NPositional names are stable only if getFaces iteration order is stable across the rebuild. Prefer a primitive origin, or maintain a role table across edits instead of relying on resolveRefIn.
Fillet/chamfer face never resolves via the role tableThe generated-hash reality aboveUse a DerivedFaceRef (geometric), not a face ref. It's inherently geometric-fallback.
Replay re-targets the wrong entityThe step has multiple inputs, or a ref points at a non-3D inputresolveStepParams only auto-resolves single-input 3D steps; multi-input refs stay raw. See history section below.
defaultScorer reject thresholds (scoring.ts)

A debugger hitting a wrong/absent match usually tripped one of these hard rejects:

  • Surface-type set but mismatched → -Infinity (hard reject).
  • Normal set and dot < 0.707 → -Infinity.
  • Centroid set and distSq > 100 (more than 10 units away) → -Infinity; otherwise penalty -distSq/100.
  • Area penalty only when |log(hintArea / faceArea)| > 1.0.
  • After scoring, resolveRef rejects anything below MIN_SCORE = 0.5 → not-found.
Reproduce the role-table path minimally

Mirror tests/shapeRefEditReplay.test.ts — build the table, advance it, resolve:

ts
const roles = new Map([['box', assignRoles(box, 'box')]]);
const ref = createRef('box', 'box:top', topFace);
const { evolution, shape: next } = unwrap(fuseWithEvolution(box, other)); // *WithEvolution → Result
const advanced = updateRoles(roles, 'box', evolution);
const resolved = resolveRef(ref, advanced, next); // 'face' in resolved ? exact/fallback : broken

*WithEvolution wrappers (fuseWithEvolution, filletWithEvolution, …) are the layer-2 source of the ShapeEvolution fed to updateRoles (src/topology/evolutionFns.ts, exported from src/index.ts). Each returns a Result that must be unwrapped or checked before use — mirror tests/shapeRefEditReplay.test.ts, which does const { shape, evolution } = unwrap(fuseResult);.

Failure taxonomy by ref kind

  • Face ref BrokenRef.reason: 'deleted' | 'ambiguous' | 'not-found'. deleted means the role table had the role but its tracked successor was removed.
  • Edge / vertex / derived: reason is only 'ambiguous' | 'not-found' — never deleted. They track adjacent face roles, not their own hash, so a vanished entity is not-found. This is stated in the type docblocks in shapeRefTypes.ts.
  • All broken results carry candidates? — the tied entities to inspect.
Show full SKILL.md (593 more words)Show less

Adding a new reference kind

The four existing kinds (face, edge, vertex, derived) share one contract. To add a fifth, work through this checklist against the real files. Follow the export-surface mechanics in the adding-operations sibling skill — a new create*/resolve* pair must flow through the same six export surfaces plus the brepjs/shapeRef subpath.

  1. Types — in shapeRefTypes.ts add XRef, its XHint, ResolvedXRef (with a confidence), and BrokenXRef. Decide the failure taxonomy up front: it can report deleted only if it tracks its own face hash; if it names itself by neighbour roles (the recommended pattern), its reason is 'ambiguous' | 'not-found' like edge/vertex.
  2. Functions — new xRefFns.ts with createXRef (capture the hint on the pre-edit shape) and resolveXRef. Follow the established pattern: resolve neighbour roles via roleLookup.ts helpers (facesForRole, roleOfFace), disambiguate with the hint, apply an ambiguity margin. Return early not-found when facesForRole yields [].
  3. Dispatch — in refResolveFns.ts add an isXRef structural guard and a branch in resolveLineageRef, and extend the LineageRef union (and ResolvedEntity if it resolves to a new entity type). Guard ordering is load-bearing: guards discriminate structurally, most-specific first. Current order is derived (betweenRoles + op) → edge (faceRoles.length === 2) → vertex (faceRoles.length >= 3) → face (role is a string). Place a new guard so it can't be shadowed by a looser one.
  4. Barrels — export from src/topology/shapeRef/index.ts, src/shapeRef.ts, and src/index.ts. Once it's in the LineageRef union and the guards, it auto-flows through resolveRefParams and history replay for free.
  5. Recursion caveat — resolveRefParams descends via isPlainOptions, which skips arrays it already handled, non-plain-prototype objects, and anything with a wrapped key. Keep the new ref a plain serializable object (like the others); a class instance would be silently skipped by the walker.
  6. Test — add tests/shapeRefXReplay.test.ts gated to occt-wasm. Use the divergence-skip mechanics owned by the writing-tests sibling skill (currentKernelId, shouldSkipSuite, describe.skipIf).

How history replay resolves refs

Replay lets a stored selection survive an upstream parameter edit. The engine is src/operations/historyFns.ts (ModelHistory / OperationStep are pure data; OperationRegistry maps op name → OperationFn).

  • resolveStepParams(params, inputs) resolves refs only for single-input, 3D steps — it calls resolveRefParams against the sole input. Multi-input, ref-free, or non-3D steps are left raw: with several inputs the target input is ambiguous, and resolving against the wrong input would silently return a wrong-shape entity.
  • Called from both replayHistory and replayFrom before invoking the OperationFn.
  • The stored step keeps its raw refs; resolution happens fresh at each replay. A ShapeRef is plain JSON, so it survives serializeHistory/deserializeHistory.
  • modifyStep(stepId, newParams) is the parametric-edit loop: it updates the params then replayFroms that step.
  • tests/historyRefReplay.test.ts is the canonical worked example (re-targets an edge after a box-height edit; multi-input leaves the ref raw).

Replay errors are Result.Err with codes REPLAY_UNKNOWN_OP / REPLAY_MISSING_INPUT / REPLAY_STEP_FAILED / REPLAY_STEP_NOT_FOUND / MODIFY_STEP_NOT_FOUND.

Where evolution comes from

ShapeEvolution = { modified, generated, deleted } (src/kernel/types.ts) is built in src/kernel/occt/evolutionOps.ts and produced by the *WithHistory kernel methods in src/kernel/occt/historyOps.ts (wired via makeHistoryOps). Fillet/chamfer go through BRepFilletAPI_MakeFillet/MakeChamfer; the plumbing populates generated, but on occt-wasm those Generated() results don't map to final-shape faces — the empty/never-live reality above. For anything kernel-side (adding a *WithHistory method, adapter capability differences), defer to the kernel-abstraction sibling skill; for the embind enum/hash-code details underlying evolutionOps.ts, defer to wasm-interop.

Worked examples in the test suite

tests/shapeRefEditReplay.test.ts (modified-face tracking + split-fragment disambiguation), tests/shapeRefDerivedReplay.test.ts (fillet/chamfer normal-blend, occt-wasm-gated), tests/shapeRefEdgeReplay.test.ts, tests/shapeRefVertexReplay.test.ts, tests/historyRefReplay.test.ts, and the unit/integration pair tests/shapeRef.test.ts + tests/shapeRefIntegration.test.ts.

Sibling skills

  • adding-operations — the six export surfaces + function-lookup.md gate a new create*/resolve* pair must pass through.
  • kernel-abstraction — kernel-side evolution, *WithHistory methods, adapters, capability differences.
  • wasm-interop — embind enum .value, Uint32Array conversion, and hash-code details underlying evolutionOps.ts.
  • writing-tests — the kernel-divergence skip pattern for gating a new ref-kind test to occt-wasm.

© 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

Files

Just SKILL.md in .claude/skills/shaperef-lineage of andymai/brepjs.

Open the folder on GitHubat commit ee50994

Compare with similar skills

Shaperef Lineage 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.

Shaperef Lineage compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Shaperef Lineage this skillandymai/brepjs114—~3.8kAutomated safety check: PassApache-2.0
Connection Import WasmfeigeCode/navop1.8k—~2.7kAutomated safety check: PassCustom licence
Changesetwhitphx/stlite1.7k—~1.9kAutomated safety check: PassApache-2.0
Debug Php Wasm Main ModuleWordPress/wordpress-playground2k—~3.1kAutomated safety check: PassGPL-2.0
Code Reviewziggy42/epsilon439—~1.7kAutomated safety check: PassApache-2.0
Debug Php Wasm Side ModulesWordPress/wordpress-playground2k—~2.5kAutomated safety check: PassGPL-2.0

Similar skills

  • Connection Import Wasm

    feigeCode/navop

    A skill your agent uses when implementing, debugging, packaging, or host-enabling onetcli WASM connection importers such as DBeaver, Navicat, Navicat Lite, Termius, connection-import.wit components…

    1.8k GitHub stars~2.7k tokensUpdated today
    DevelopmentAuto-check passed
  • Changeset

    whitphx/stlite

    Create or update a changeset fragment (.changeset/.md) reflecting the changes made in the current session or branch.

    1.7k GitHub stars~1.9k tokensUpdated today
    DevelopmentAuto-check passed
  • Debug Php Wasm Main Module

    WordPress/wordpress-playground

    Debug PHP.wasm main module crashes including Asyncify errors (unreachable, memory access out of bounds), JSPI errors (SuspendError, trying to suspend JS frames), WASM memory growth bugs, and runtime…

    2k GitHub stars~3.1k tokensUpdated today
    DevelopmentAuto-check passed
  • Code Review

    ziggy42/epsilon

    A skill your agent uses when the user asks for a code review.

    439 GitHub stars~1.7k tokensUpdated 3 days ago
    DevelopmentAuto-check passed
  • Debug Php Wasm Side Modules

    WordPress/wordpress-playground

    Debug WASM side modules (dynamic PHP extensions) including dlopen failures, SIDEMODULE loading, JSPI suspension crashes in extensions, C++ weak symbol issues, and extension runtime errors.

    2k GitHub stars~2.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Merjs

    justrach/merjs

    Work with the merjs Zig web framework. An agent skill from justrach/merjs.

    357 GitHub stars~4k tokensUpdated 1 mo ago
    DevelopmentAuto-check: notes

More from andymai/brepjs

All 21 skills in this repo
  • Implement

    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…

    114 GitHub stars~3.4k tokensUpdated today
    Auto-check passed
  • Memory And Disposal

    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"…

    114 GitHub stars~3.1k tokensUpdated today
    Auto-check passed
  • Polish

    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…

    114 GitHub stars~588 tokensUpdated today
    Auto-check passed
  • Wasm Interop

    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…

    114 GitHub stars~3k tokensUpdated today
    Auto-check passed
  • Writing Tests

    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…

    114 GitHub stars~4.3k tokensUpdated today
    Auto-check passed
  • Adding Operations

    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…

    114 GitHub stars~4.4k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Shaperef Lineage

What does Shaperef Lineage do?

This skill should be used when debugging or extending stable references (topological naming) and history replay in brepjs — when a task says "ShapeRef resolves to the wrong face/edge", "ref won't…. Shaperef Lineage is an agent skill from andymai/brepjs.

When should I use Shaperef Lineage?

Shaperef Lineage fits situations like: development work in your project.

How do I install Shaperef Lineage in Claude Code?

Run `npx skills add andymai/brepjs --skill shaperef-lineage -a claude-code`. Or copy the skill folder (.claude/skills/shaperef-lineage in andymai/brepjs) into .claude/skills/shaperef-lineage in your project. Claude Code loads it when a task matches its description.

How do I install Shaperef Lineage in Codex?

Run `npx skills add andymai/brepjs --skill shaperef-lineage -a codex`. Or copy the skill folder (.claude/skills/shaperef-lineage in andymai/brepjs) into .agents/skills/shaperef-lineage in your project. Codex loads it when a task matches its description.

Can I use Shaperef Lineage in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add andymai/brepjs --skill shaperef-lineage -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/shaperef-lineage, .gemini/skills/shaperef-lineage, .github/skills/shaperef-lineage and .opencode/skills/shaperef-lineage in your project.

What does Shaperef Lineage need to run?

SKILL.md names no scripts, command-line tools or credentials: Shaperef Lineage is instructions for the agent only.

Does Shaperef Lineage access the network?

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.

Is Shaperef Lineage safe to install?

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.

What licence does Shaperef Lineage use?

Shaperef Lineage 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.

How many tokens does Shaperef Lineage use?

About 3.8k tokens (SKILL.md is roughly 15k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Shaperef Lineage?

Skills that share tags, products or a category with Shaperef Lineage: Connection Import Wasm (feigeCode/navop, 1.8k stars), Changeset (whitphx/stlite, 1.7k stars), Debug Php Wasm Main Module (WordPress/wordpress-playground, 2k stars) and Code Review (ziggy42/epsilon, 439 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Shaperef Lineage?

andymai (a GitHub user) maintains it in andymai/brepjs, which has 114 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.