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

@unoff/cli

v0.4.4

Published

A CLI tool to create plugins for Figma, Penpot, Sketch, and Framer

Downloads

799

Readme

Unoff CLI

A CLI tool to quickly scaffold plugins for Figma, Penpot, Sketch, and Framer with built-in development tools and best practices.

Prerequisites

  • Node.js ≥ 18
  • npm ≥ 9
  • git — required for unoff create (initializes a git repository) and for all unoff add commands (workers, skills, specs use git submodules)

Installing Prerequisites

Homebrew (macOS only)

If you don't have Homebrew installed, open Terminal and install it:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Then verify:

brew --version

Node.js and npm

On macOS: Open Terminal and run:

# Using Homebrew (requires Homebrew to be installed)
brew install node

On Windows:

  1. Download the installer from nodejs.org
  2. Run the installer and follow the setup wizard
  3. Open Command Prompt (cmd.exe) or PowerShell and verify installation:
    node --version
    npm --version

On Linux (Ubuntu/Debian): Open Terminal and run:

sudo apt update
sudo apt install nodejs npm

On Linux (Fedora/CentOS): Open Terminal and run:

sudo dnf install nodejs npm

Git

On macOS: Open Terminal and run:

# Using Homebrew
brew install git

On Windows:

  1. Download the installer from git-scm.com
  2. Run the installer and follow the setup wizard
  3. Open Command Prompt (cmd.exe) or PowerShell and verify installation:
    git --version

On Linux (Ubuntu/Debian): Open Terminal and run:

sudo apt update
sudo apt install git

On Linux (Fedora/CentOS): Open Terminal and run:

sudo dnf install git

Installation

A global install is recommended — it makes every unoff command available directly in any plugin project:

npm install -g @unoff/cli

If you prefer not to install globally, every command works with npx @unoff/cli as a drop-in replacement:

# Instead of: unoff create figma-plugin
npx @unoff/cli create figma-plugin

# Instead of: unoff dev
npx @unoff/cli dev

# Instead of: unoff build
npx @unoff/cli build

Quick Example

# Scaffold a plugin (global install)
unoff create figma-plugin

# Or without global install
npx @unoff/cli create figma-plugin

# Navigate to the plugin directory
cd my-plugin

# Install dependencies
npm install

# Start development (or: npx @unoff/cli dev)
unoff dev

# Figma: Plugins > Development > Import plugin from manifest...
# Penpot: Plugins > Add custom plugin > http://localhost:4400/manifest.json

CLI Commands

unoff help

Show all commands, available platforms, and workers.

unoff create <platform>

Scaffold a new plugin project with an interactive prompt.

| Platform | Status | | --------------- | -------------- | | figma-plugin | ✅ Available | | penpot-plugin | ✅ Available | | sketch-plugin | 🚧 Coming soon | | framer-plugin | 🚧 Coming soon |

The interactive prompt will ask for plugin name, output directory, GitHub username, author, license, and which external services to enable:

| Service | Default | | ------------------------------------ | ------- | | Supabase (Database & Authentication) | ✅ | | Mixpanel (Analytics) | ✅ | | Sentry (Error Monitoring) | ✅ | | Notion (Announcements & Onboarding) | ✅ |

Selected services update the is*Enabled flags in global.config.ts. All environment variable placeholders are always generated in .env.local.

unoff dev

Start development mode (npm run start:dev).

unoff build

Build for production (npm run build:prod).

unoff check

Run lint and type checking sequentially.

unoff format

Format source code with Prettier.

unoff add worker <name>

Add a Cloudflare Worker as a git submodule. Automatically updates package.json workspaces and injects the corresponding start script. You will be prompted for the destination path.

| Worker | Script | Port | | -------------- | --------------------- | ---- | | announcement | start:announcements | 8888 | | auth | start:token | 8787 | | cors | start:cors | 8989 |

unoff add worker announcement
npm install
npm run start:announcements

unoff add skills

Add the unoff-skills repository as a git submodule, then link it into the skills directory of every configured assistant.

unoff add skills
git submodule update --init --recursive

The submodule lands in .unoff/skills/ by default — outside your skills directories on purpose. The repo root holds a unoff-create-plugin/ folder, so cloning it straight into .claude/skills/unoff-create-plugin/ would bury SKILL.md one level too deep and no assistant would ever load it. Instead each skills directory gets a symlink to the skill itself:

.unoff/skills/                                        # submodule (whole repo)
  unoff-create-plugin/SKILL.md
.claude/skills/unoff-create-plugin  ->  ../../.unoff/skills/unoff-create-plugin
.agents/skills/unoff-create-plugin  ->  ../../.unoff/skills/unoff-create-plugin

One source of truth: git submodule update --remote refreshes every assistant at once. On platforms that refuse symlinks the CLI falls back to a copy. Run unoff sync skills after changing which assistants the project targets.

If you already installed the submodule the old way, unoff add skills detects it, moves it up a level, and links it back in.

The version is pinned in your project's history — update it deliberately with git submodule update --remote.

Alternative — skills.sh, if you would rather copy the files than track a submodule:

npx skills add yelbolt/unoff-skills

This installs into every agent directory it detects (.claude/, .cursor/, …) instead of a single path, and records provenance in skills-lock.json. No git submodule, no pinning.

Both give you the skill library only. For skills plus specs plus agents, wired per assistant, see AI assistants below.

unoff add specs

Scaffold a functional spec — what the product does, as opposed to the skills, which describe how it is built. It asks two questions: the folder and the spec name. Nothing else — you should not have to know the architecture before writing down what you want.

unoff add specs
# → specs/credits-paywall.md
---
name: credits-paywall
description: Functional spec — metered exports with a paywall past the free tier.
# Which parts of the plugin this touches: canvas, bridge, ui, config, externals.
# Narrows the skill files your assistant reads. Empty means all of them.
layers: []
# Which platforms this targets: figma, penpot. Empty means all.
platforms: []
status: draft
---

# Credits Paywall

## Problem

## User flow

## Rules

## Acceptance criteria

- [ ] Given <context>, when <action>, then <observable outcome>

## Out of scope

## Implementation notes

layers is what takes an agent from what to build to which architecture docs to read. A spec declaring layers: [ui, config] tells it to load ui/component-patterns.md, config/feature-flags.md and the rest of those layers from the skill library — no guessing.

It ships empty, which reads as "all of them": a working default that costs some context but never routes the agent away from a file it needed. Fill it in when you know — the commented frontmatter says how, and so can your assistant once the spec is written.

unoff sync specs

Regenerate specs/INDEX.md and point every AI instruction file at it. Run it after adding a spec by hand, or after editing frontmatter.

unoff sync specs          # auto-detects specs/, docs/specs/ or .specs/
unoff sync specs docs/specs

It writes a managed block, delimited by <!-- unoff:specs:start --> / <!-- unoff:specs:end -->, into the rules file of each assistant configured in unoff.config.json — see AI assistants for the mapping. Assistants you did not select are never touched.

Two extra behaviours worth knowing:

  • An assistant's canonical entry point (CLAUDE.md, AGENTS.md, .github/copilot-instructions.md) is created if missing. Secondary rules files (Cursor, Windsurf) are only updated when they already exist.
  • Assistants with no agent file format also get the agent role table inlined, so the same routing information reaches them as instructions.

Re-running replaces the block in place — it never duplicates, and everything outside the markers is left untouched. AGENTS.md is the only file created on demand, since it is the cross-agent entry point and templates do not ship one.

The result is that an agent asked to "add the paywall" reads the spec and the matching skill files, instead of one or the other.

Renamed from unoff specs sync. The old form still works and prints a deprecation notice.

unoff sync skills

Re-point every configured skills directory at the skills submodule. Run it after changing the assistant list in unoff.config.json, or after a fresh clone on a platform where the links did not survive.

unoff sync skills

It is idempotent, and it repairs a submodule that was checked out inside a skills directory by moving it up a level first.

unoff remove worker <name>

Remove a worker submodule and clean up package.json (workspaces + scripts).

unoff remove worker announcement

unoff remove skills

Remove the skills submodule from the project, along with the links it placed in each assistant's skills directory.

unoff remove skills

unoff remove specs

Remove the local specs folder and all its contents.

unoff remove specs

AI assistants

The CLI is assistant-agnostic. It installs three pieces, each in the format the assistant actually reads:

| Piece | Answers | Source | | ---------- | -------------- | --------------------------------------------------------------- | | Skills | how we build | yelbolt/unoff-skills | | Specs | what it does | your specs/ folder | | Agents | who does it | agents/ in the same skills repo |

Start here:

unoff ai          # pick assistants, then install all three
unoff ai status   # what is configured, what is installed

Your choice is persisted in unoff.config.json and committed, so the whole team targets the same set. Every other command (add agents, sync specs) reads it. Without a config file, the CLI falls back to detecting which assistants the project already shows traces of.

What each assistant gets

| Assistant | Rules | Skills | Agents | MCP | | --------------- | --------------------------------- | ------------------- | --------------------------- | -------------------------------------- | | Claude Code | CLAUDE.md | .claude/skills/ | .claude/agents/*.md | .claude/settings.jsonurl | | GitHub Copilot | .github/copilot-instructions.md | — via rules path | .github/agents/*.agent.md | .vscode/mcp.jsontype + url | | ChatGPT / Codex | AGENTS.md | .agents/skills/ | role table in rules | .codex/config.tomlTOML | | Cursor | .cursor/rules/project.mdc | — via rules path | role table in rules | .cursor/mcp.jsonurl | | Windsurf | .windsurf/rules/project.md | .windsurf/skills/ | role table in rules | .windsurf/mcp.jsonserverUrl |

Every column is a capability some tools have and others don't, so the CLI degrades rather than pretends:

  • Agents — only Claude Code and Copilot have a file-based format. For the rest, agents become a role table inlined in the rules file they already read: same routing information, expressed as instructions.
  • Skills — only Claude Code, Codex and Windsurf read a skills directory (verified against npx skills add -a '*'; Cursor and Copilot create none). The library is installed once at a canonical path, and every rules file points at it explicitly — so it works even where there is no native directory.
  • MCP — one server definition per platform, four different spellings. Windsurf reads serverUrl and silently ignores a plain url; Codex reads TOML, not JSON; VS Code wants an explicit type: "http". Each platform ships a hosted endpoint and a machine-local one (Figma desktop on 127.0.0.1:3845, the Penpot dev server on localhost:4401). The write merges into existing JSON, so Claude's permissions survive.

The canonical skills path follows the assistants you chose: .claude/skills/… when Claude is in the set, otherwise .agents/skills/…. A Codex-only project never ends up with a .claude/ folder.

unoff add agents

Install the five agents for every configured assistant. Definitions come from agents/ in the skills repo — one source, several output formats.

unoff add agents

| Agent | Layers | Owns | | ---------------------------- | --------------------- | ------------------------------------------------------------------------------- | | unoff-plugin-architect | all | Resolves the target platform, decomposes and sequences work by layer | | unoff-canvas-bridge | canvas, bridge | src/index.ts, src/canvas/, src/bridges/ — Canvas APIs, storage, messaging | | unoff-ui | ui | src/app/ — Preact, @unoff/ui, Nanostores, theming, Tolgee, a11y | | unoff-platform-services | config, externals | global.config.ts, Vite, feature flags, credits, external services, payments | | unoff-conformance-reviewer | all | Quality gate — conventions, message contracts, Figma/Penpot parity, build |

Agents declare layers in the same vocabulary as specs. That is what closes the loop: a spec says which layers it touches, the skill library is organised by layer, and each agent owns a set of layers — so an assistant can resolve both which docs to read and which role to adopt.

Claude Code plugin

Claude users can get skills and agents pre-wired as a plugin instead of running unoff ai:

/plugin marketplace add yelbolt/claude-marketplace
/plugin install unoff@yelbolt

The marketplace is shared with the other yelbolt plugins, so the first command is only needed once. Later releases: /plugin marketplace update yelbolt. Specs still come from unoff add specs and unoff sync specs — they describe your product, not ours.

Features

  • 🚀 Quick setup with interactive CLI
  • 📦 Multiple platform support (Figma ✅, Penpot ✅, Sketch 🚧, Framer 🚧)
  • 🔧 Built-in development server with hot reload
  • 🏗️ Production-ready build system
  • 🎛️ Toggleable external services (Supabase, Mixpanel, Sentry, Notion)
  • 🔐 Authentication scaffolding (Supabase)
  • 💳 License management (LemonSqueezy)
  • 📊 Analytics and monitoring (Mixpanel, Sentry)
  • 🌍 Internationalization (Tolgee)
  • 📢 Announcement & onboarding system (Notion + Cloudflare Workers)
  • ⚙️ Worker management via git submodules (add worker / remove worker)
  • 📚 Skills library via git submodule (add skills / remove skills) or skills.sh
  • 📐 Functional specs discoverable by any LLM (add specs / sync specs) — layer-routed to the implementation skills
  • 🤖 Claude Code plugin with 5 layer-specialized agents (yelbolt/claude-marketplace)
  • 📝 Project specs scaffolding (add specs / remove specs)
  • 📚 Comprehensive AI-assistant documentation

What's included in the template?

UI & Components

  • @unoff/ui — Pre-built UI components for design tool plugins

Authentication & Database

  • Supabase — Backend as a Service for authentication and database

Licensing & Payments

Monitoring & Analytics

  • Sentry — Error tracking and performance monitoring
  • Mixpanel — Product analytics

Content & Communication

  • Notion — CMS for announcements and onboarding
  • Cloudflare Workers — Proxy layer for Notion API (auth + CORS)

Localization

  • Tolgee — Translation management and i18n

Documentation

For detailed usage instructions, see USAGE.md.

Contributing

Contributions are welcome! Please open an issue or pull request on GitHub.

License

MPL-2.0