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

@elyx-design/cli

v0.0.1-nightly.14809.5c7efbe47

Published

Command-line tools for Elyx

Readme

@elyx-design/cli

The command-line interface for Elyx.

Install it globally and run elyx from your terminal:

npm install --global @elyx-design/cli
elyx --help

Open a project folder in the matching Elyx app release (development, nightly, preview, or public):

elyx .
elyx /path/to/project

This package provides the JavaScript launcher. The native executable is installed through an optional package selected for the current operating system and architecture.

Linux support

The Linux CLI currently supports x86-64 systems using glibc. Ubuntu 24.04 is the tested environment, and libc++ and Fontconfig must be installed on the system. Alpine and other musl-based distributions are not currently supported.

Development

cli.ts is the npm launcher. src/ contains the native entry point, commands, and their tests and fixtures. CMakeLists.txt builds the native elyx executable using Mosaic's shared language and rendering code. cmake/ contains embedded resource generators. cpp-vendors.yml declares CLI11, libgit2, and the demo project used by --create.

Run from the repository root:

mise run vendors:elyx
mise run elyx:build
mise run elyx:test:cpp
mise run cli:build

The native debug executable is written to out/native/debug/elyx within this directory. The npm launcher builds to dist/cli.js. The published npm package includes only the launcher, README, and license; platform packages supply the native executable.

The daemon also compiles rendering, inspection, lint, and scene code from src/. Mosaic uses its native font-loading code.

The Figma reader and its CLI adapter live in src/fig/. Its miniz and Zstandard dependencies are also listed in cpp-vendors.yml and are only configured by the native CLI build. The daemon also builds the reader and converter using its own pinned dependencies for sidebar .fig imports.

Building an Elyx model

For .fig decoding and the elyx fig inspect and elyx fig convert commands, see the Figma reader and converter.

ElyxLang::ElyxModelBuilder builds objects from Model.h without creating an MSWorld. It uses elyxSchema() to find fields, check units, select the existing value codec, and order properties. build() transfers the declarations into a ModelValue containing a ModelBoard.

Pass an ElyxModelBuilder::Layer tree to addLayer(). Children keep their input order and are declared inside their parent, alongside the children: references. Names must be unique among siblings; separate parents can reuse a child name. The schema determines which layer types accept children.

Properties currently support literal lengths, such as frame width and height, and a single solid fill supplied as an MSColor. Color channels, including alpha, must be finite values between 0 and 1. The builder validates the fill through the schema's shorthand expansion, paint branch, and color codec, then keeps the typed color for formatting. Paint lists and paint objects are not yet supported.

Unknown properties, invalid or duplicate symbols, invalid lengths, unsupported property structures, and nesting beyond 512 child levels return an error. A failed addLayer() leaves the entire document unchanged, even when the error is in a descendant. Accepted values are copied; the builder does not omit defaults.

The model carries a distinct namespace for each layer's declarations. The formatter uses those namespaces to render local child references without an external namespace resolver.

The schema must outlive the builder. The process-wide elyxSchema() does.

Create a frame with colored children and write it to disk

#include <fstream>
#include <stdexcept>
#include <utility>

#include "ElyxLang/ElyxFormatter.h"
#include "ElyxLang/ElyxModelBuilder.h"
#include "ElyxLang/ElyxSchema.h"
#include "primitives/MSColor.h"

int main() {
  using namespace ElyxLang;

  ElyxModelBuilder document{Schema::elyxSchema()};
  ElyxModelBuilder::Layer card{
      .kind = ModelBuiltinBase::Frame,
      .name = "card",
  };
  card.properties.add("width", ModelValue{ast::Length::Pixel(320)});
  card.properties.add("height", ModelValue{ast::Length::Pixel(200)});
  card.properties.add("fill", ModelValue{MSColor::White()});

  ElyxModelBuilder::Layer rectangle{
      .kind = ModelBuiltinBase::Frame,
      .name = "rectangle",
  };
  rectangle.properties.add("left", ModelValue{ast::Length::Pixel(16)});
  rectangle.properties.add("top", ModelValue{ast::Length::Pixel(24)});
  rectangle.properties.add("width", ModelValue{ast::Length::Pixel(80)});
  rectangle.properties.add("height", ModelValue{ast::Length::Pixel(40)});
  rectangle.properties.add("fill", ModelValue{MSColor::Red()});
  card.children.push_back(std::move(rectangle));

  ElyxModelBuilder::Layer translucent{
      .kind = ModelBuiltinBase::Frame,
      .name = "translucent",
  };
  translucent.properties.add("left", ModelValue{ast::Length::Pixel(128)});
  translucent.properties.add("top", ModelValue{ast::Length::Pixel(24)});
  translucent.properties.add("width", ModelValue{ast::Length::Pixel(80)});
  translucent.properties.add("height", ModelValue{ast::Length::Pixel(40)});
  translucent.properties.add("fill", ModelValue{MSColor::Blue().withAlpha(0.5F)});
  card.children.push_back(std::move(translucent));

  if (auto result = document.addLayer(card); !result) {
    throw std::runtime_error(result.error());
  }
  auto model = std::move(document).build();

  pp::DocumentBuilder output;
  pp::PrettyPrinter printer;
  pp::DefaultLayout layout;
  const auto &formatted = printer.pp(output, model);

  std::ofstream file;
  file.exceptions(std::ios::failbit | std::ios::badbit);
  file.open("card.elyx");
  file << printer.render(formatted, layout);
  file.close();
}

Additional paint types and references to other scopes are later steps. The Figma converter calls this shared language API; the CLI handles arguments and output files.

Layer targets

Inspection returns a target on component nodes and bounds, hit, and rectangle results. It contains filePath, sourceRef, and overridePath; a null target means the runtime layer has no reusable source address. Other fields such as symbol, ref, and path describe the layer, rather than identifying an exact instance occurrence.

Use the target's file path as the CLI input, sourceRef as inspect's --ref or render's --symbol, and overridePath as --override-path. For example:

elyx inspect component screen.elyx --ref=musicPlayer.track.save
elyx inspect bounds screen.elyx --ref=card --override-path="'ui.Body.Label"
elyx render screen.elyx --symbol=card --override-path="'ui.Body.Label" -o label.png

Copy override paths from inspection; their namespace qualifiers distinguish imported descendants. Ambiguous source references fail instead of choosing an instance. In MCP, pass the returned object as query.target to inspect bounds/component, target to render, or an entry in focus's targets array. Spatial inspect queries use query.filePath. To render a whole document, pass target: {filePath: "screen.elyx"}.