npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@moishy/cubing-core

v0.3.0

Published

Cube engine and solver framework for speedsolving methods: cubie-level state, SiGN notation, ergonomic move-cost models, guided search, and a composable step/strategy/phase pipeline.

Readme

@moishy/cubing-core

The cube engine and solver framework behind moishy-cubing: cubie-level state, notation, a pluggable ergonomic cost model, guided search, and the Step → Strategy → Phase pipeline that methods are built from.

Zero dependencies. Runs on Deno, Node, and in the browser.

deno add jsr:@moishy/cubing-core    # Deno — https://jsr.io/@moishy/cubing-core
npm  install @moishy/cubing-core    # Node — https://www.npmjs.com/package/@moishy/cubing-core

Looking for a ready-made solver? See @moishy/apb. This package is the toolkit you use to build one.

Cube State

State is stored at the cubie level — corner and edge permutation and orientation, plus center orientation — so slice moves, wide moves and whole-cube rotations are all first-class, and "are the centers still where they started?" is a question you can ask.

import {
  applyAlg,
  formatAlg,
  invert,
  isSolved,
  parseAlg,
  solvedCube,
  toFacelets,
} from "@moishy/cubing-core";

const state = applyAlg(solvedCube(), "R U R' U'");
isSolved(state); // false
toFacelets(state); // 54-char facelet string
formatAlg(invert(parseAlg("R U R' U'"))); // "U R U' R'"

Notation is SiGN style: R L U D F B faces, M E S slices, lowercase r l u d f b wides, x y z rotations, ' for counter-clockwise, 2 for a half turn.

Move Cost (MCC)

The library's objective function. Rather than counting moves, it estimates how hard a sequence is to execute — base difficulty per move plus transition penalties for regrips and awkward same-axis sequences.

import { createDefaultMoveCostModel, parseAlg, scoreAlg } from "@moishy/cubing-core";

const twoHanded = createDefaultMoveCostModel();
const oneHanded = createDefaultMoveCostModel({ mode: "OH", handedness: "left" });

scoreAlg(parseAlg("R U R' U'"), twoHanded); // 3.60

Any object with cost(move, context) works, so you can model your own hands. A block-building variant (createBlockCostModel) is also exported — move-count-dominant and wide-averse, for the phases where blockbuilders care about turn count rather than smoothness.

Search

A goal predicate, a move set, and an admissible heuristic:

import { searchAStar, solvedCube } from "@moishy/cubing-core";

const result = searchAStar({
  start: state,
  goal: (s) => /* ... */,
  moves: ["U", "D", "L", "R", "F", "B"],
  heuristic: (s) => /* lower bound on remaining cost */,
  maxDepth: 8,
});
result.moves; // cheapest sequence found
result.nodesVisited;

search (IDA*) and searchAStar (A*, best when you have a strong pruning table) both return the cost-optimal solution. searchAStarMany returns a pool of distinct near-optimal solutions, which is what lets a later step choose the predecessor that suits it.

The heuristic must never overestimate the remaining cost, or optimality is lost.

Building a Method

A method is data. Steps run in order; each registers strategies that race by cost; each strategy is a list of phases that are either searches or algorithm lookups.

import { Method, type MethodDefinition } from "@moishy/cubing-core";

const definition: MethodDefinition = {
  id: "cfop",
  steps: [crossStep, f2lStep, ollStep, pllStep],
  recommendedSettings: { colorNeutrality: "fixed", lookahead: { depth: 1 } },
};

export const cfop = new Method(definition);
const res = await cfop.solve("R U R' U'");

The runner handles strategy racing, phase chaining, cross-step lookahead, color-neutral orientation selection, replacements and extras, and time/abort budgets.

Full walkthrough: Adding a Method.

Documentation

License

MIT © Moshe Rosenberg