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

@ubox-tools/cli

v0.3.1

Published

Author Ubox experiences locally and sync them to the Ubox platform

Readme

ubox CLI

Author Ubox experiences locally — by hand or with an AI agent — keep them under git, and sync them to the Ubox platform (https://ubox-api.ubox.world) with direct API calls.

npm install -g @ubox-tools/cli
ubox login
ubox init "My Experience"
# …author apps under apps/<name>/…
ubox push

Prefer not to install it globally? Run any command through npx instead — it fetches the latest published version on demand:

npx @ubox-tools/cli login
npx @ubox-tools/cli init "My Experience"
npx @ubox-tools/cli push
  • Node 18+ required.
  • Every command works non-interactively (flags + env vars) for CI and AI agents; interactive prompts are sugar on top when a TTY is present.

Concepts

An experience is a git-managed folder containing one or more apps. Each app maps to a remote application on the platform; an application runs on a player (the platform's "ubox" entity) inside an xpace (a physical place).

The link between your local folder and the platform lives in ubox.json (the manifest) at the project root. It records each app's remote applicationId, the asset round-trip map, and any player/installation IDs — commit it. Everything else about history is git's job: the CLI always overwrites the application's current version in place; platform-side versions are not used.

Project layout

My Experience/
├── ubox.json               # manifest — links local apps to remote IDs (commit this)
├── CLAUDE.md               # agent guidance (or GEMINI.md with --gemini)
├── docs/                   # Ubox library docs, downloaded by `ubox init`
├── assets/                 # assets shared by all apps
└── apps/
    └── main/
        ├── index.html      # → html
        ├── style.css       # → css
        ├── data.js         # → data_source
        ├── ubox.js         # → ubox_events
        ├── logic.js        # → business_logic
        ├── workflow.js     # → workflow
        ├── parameters.json # app parameters (see below)
        └── assets/         # assets private to this app (optional)

The six file names are fixed — they map one-to-one onto the application's six code fields. An app is any directory under apps/ containing at least one of them (or a parameters.json).

Assets

Reference assets by natural relative path in your source:

<img src="assets/logo.png">           <!-- app-local asset -->
<img src="../../assets/shared.png">   <!-- shared root asset -->
body { background: url(assets/bg.jpg); }

On push, the CLI uploads the referenced files and rewrites the paths to the platform's {resources:images/logo.png} tokens; on pull, tokens are rewritten back to relative paths and the files are downloaded. The original filename is the join key, so the round-trip is lossless. You never write resource tokens by hand.

Parameters

parameters.json is an array of parameter objects:

[
  {
    "key": "inactivityTimeout",
    "value": "150000",
    "default_value": "150000",
    "description": "Milliseconds of no movement before an idle user is kicked"
  }
]

All values are strings on the platform — the CLI coerces numbers/booleans (150000"150000") and rejects anything else with a pointed error. Reference a parameter in source as {parameter:key}; the platform resolves it at load time, and ubox dev resolves it locally (value, falling back to default_value when empty). A value may itself contain {player:<appName>} — a cross-app link that ubox dev resolves to that app's local URL, including a ?api_key=<uuid> query mirroring the production player-link shape (e.g. for a QR code pointing at a companion mobile app). After a sync, see .ubox/reference.md for a generated table of every asset and parameter token.

index.html during authoring

With ubox dev you don't need any local <link>/<script> tags — the dev server assembles the page exactly like the production player (css into a <style> tag, the four JS files into a single <script> at the end, body wrapped in <div id="myDiv">). You may still include local tags for the other five files so the app also runs in a plain browser; both ubox dev and push strip tags that reference exactly style.css, data.js, ubox.js, logic.js, or workflow.js. CDN and other references are kept.


Authentication

ubox login                 # prompts for email + password, stores a token
ubox whoami                # show identity + host in use
ubox logout                # remove stored credentials

Credentials are stored in ~/.config/ubox/credentials.json (mode 600).

For CI / agents, environment variables override the stored file:

| Variable | Meaning | |---|---| | UBOX_TOKEN | bearer token (skips ubox login) | | UBOX_HOST | API host override | | UBOX_EMAIL / UBOX_PASSWORD | non-interactive ubox login |

A 401 clears stored credentials automatically (never an env token).


Commands

Global flags: --host <url>, --json (machine-readable output), --yes (skip prompts; fail if input is missing), -v/--verbose.

Project

ubox init [name] [theme]     # scaffold a new experience (downloads latest docs)
ubox init                    # no name = init the current directory, git-style
ubox init --update           # refresh docs/ in an existing project
ubox init --gemini           # write GEMINI.md instead of CLAUDE.md

Sync

ubox link <appName> [id|name]        # attach an existing remote application;
                                     # a name searches with an interactive picker
ubox link --app <appName>=<id|name>  # flag form, repeatable

ubox pull [appName…]                 # populate local files from the remote app(s)
ubox pull <appName> --app <id|name>  # link and pull in one step

ubox status [appName…]               # local vs remote diff + token reference

ubox push [appName…]                 # push source + assets + params (all apps if omitted)
ubox push source|assets|params [appName…]   # a single phase
ubox push … --force                  # push even when everything matches

push is idempotent: assets are skipped when their bytes already match the remote blob, parameters and source when they equal the remote values. A first push of an unlinked app creates the remote application (named "<project> <appName>"), or offers to adopt an existing one with that exact name.

Local development

ubox dev [-p <port>] [--ws-port <n>] [--host <ip>] [--no-reload] [--no-log] [--log-filter <cmds>]

Runs the experience locally, offline — no login needed:

  • Production-shaped pages. Each app is served at /apps/<name>/ assembled exactly like the player builds it (css in <style>, the four JS files in one <script> in data → ubox → logic → workflow order, body in <div id="myDiv">) — with {parameter:…} and {player:…} tokens resolved from parameters.json.
  • Message relay. A local WebSocket relay replaces the Ubox messaging server; a UboxClient shim is injected so ubox-data-xpace works unchanged and apps talk to each other across tabs (or devices, with --host <lan-ip>).
  • Live reload. Edits under apps/ and assets/ reload connected browsers (--no-reload to disable).
  • Dashboard. The page at / launches your apps and monitors the relay live: connected clients, shared variables (from app_online / var_changed messages), and a filterable message log — click a message for its full payload. Relay messages also log to the terminal (--log-filter setVar,launch to narrow, --no-log to silence).

The default 127.0.0.1 binding is deliberate: browsers only grant camera/microphone and crypto.subtle to secure contexts, and plain-HTTP LAN origins don't qualify. Use --host <lan-ip> when you need other devices to connect and don't need those APIs.

Applications

ubox app list [--search <term>] [--page <n>] [--limit <n>]
ubox app create <name> [--link <appName>]   # --link records the id on a local app
ubox app update <appName> [--name <n>]      # rename remote (default "<project> <appName>")

Players

ubox player list
ubox player create --name <n> --xpace <name|id> [--app <appName>]
ubox player install [appName] [--player <id|name>]
ubox player activate [appName] [--player <id|name>]
ubox player public [appName] [--player <id|name>] [--on|--off]   # default --on

App-scoped player commands target, in order: an explicit --player, the player recorded for that app in ubox.json, or an interactive picker. Omit appName on install/activate to browse instead: pick a player, then pick from its available (install) or installed (activate) apps — handy outside a project, or for apps that aren't part of the experience. "Publishing" an experience means making its player public — applications themselves are never made public.


Non-interactive / CI usage

export UBOX_TOKEN=…            # or UBOX_EMAIL/UBOX_PASSWORD + `ubox login`
ubox push --yes --json         # no prompts; JSON report on stdout
  • --yes auto-accepts single-match confirmations (e.g. name adoption) and fails with a clear message where input would be required.
  • --json prints a machine-readable result object for scripting.
  • Exit code is non-zero on failure.

Known platform limitations

The CLI detects these server-side bugs and degrades with explicit messages rather than failing opaquely:

  • Freshly-created apps can't be installed yet. Applications created through the API don't appear in a player's available list, which blocks player install for them. Apps created in the studio install normally.
  • Parameter sync fails while an app is installed on any player. Sync parameters before the first install; on re-deploys the CLI skips the step with a warning when the PUT is rejected (and skips it entirely when nothing changed).
  • Same-second uploads can overwrite each other's file. Uploaded resource blobs are stored at second-resolution timestamp paths. push assets works around it (one file per request, spacing per extension) and verifies for collisions afterwards.
  • Server-side application search is unreliable for newly-created apps — app list and name-based lookups are advisory; a numeric id always works.
  • Deletes are unavailable for applications, players, and xpaces (server errors) — create carefully.

Development

npm run build       # tsc → dist/
npm run dev         # tsc --watch
npm test            # unit tests (transform + project + dev modules)

Repo guide for contributors and agents: CLAUDE.md. Design document: SPEC.md. Empirical API endpoint status: api_working_reference.md.