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

@cloud-cli/on

v1.5.7

Published

CLI entry point for the on plugin ecosystem.

Readme

🏃 @cloud-cli/on

General-purpose workflows

A self-hosted, lightweight, high-performance CI/CD runner engine built for Node.js.

Designed with a strict security-first boundary, native JavaScript AST evaluation, zero-DSL template literals, and a built-in terminal log web dashboard.


🌟 Key Highlights

  • Strict Code/Data Separation: run: steps are executed verbatim as raw process scripts. Expressions and dynamic data bindings are isolated strictly to env:, eliminating shell-injection vectors entirely.
  • Standard ES Template Syntax (${...}): No custom DSL wrappers like ${{ }} or {{ }}. If a field contains ${...}, it evaluates standard JavaScript template string logic via AST.
  • Deterministic Field Evaluation: No silent fallbacks or ambiguous type conversions. Plain strings remain literal strings; conditions in if: fields run as strict JS boolean expressions.
  • Built-in Dark Mode Web UI (/runs): Monitor job statuses live, inspect workspace inputs, and view ANSI-colored terminal log streams rendered in real-time.
  • System & Container Execution Drivers: Run steps directly as detached host process groups or inside isolated Docker/Systemd transient units.
  • Automatic Secret Redaction: Secrets loaded from .env are automatically masked (***) across all terminal log outputs and report snapshots.

📦 Project Structure

my-project/
├── on/                     # Workflow definitions directory
│   ├── release.yml
│   └── test.yml
├── .env                     # Local secrets (git-ignored)
├── runner.config.mjs        # (Optional) Engine configuration
└── package.json

🚀 Quick Start

1. Install & Run

Run the engine directly via npx or pnpm dlx:

# Start full engine (Ingress HTTP Gateway + 5 Worker Loops)
npx @cloud-cli/on start

2. Configure Secrets (.env)

Secrets are automatically loaded from .env at the root of your project. Prefix secrets with SECRET_:

SECRET_NPM_TOKEN="npm_1234567890abcdef"
SECRET_GITHUB_TOKEN="ghp_1234567890abcdef"
SECRET_GITHUB_WEBHOOK_SECRET="my-webhook-secret"

SECRET_GITHUB_WEBHOOK_SECRET is required to validate incoming webhooks from GitHub

3. Define a Workflow (on/release.yml)

name: Build and Publish Release

on:
  github:
    if: inputs.event === 'push' && inputs.branch === 'main'

concurrency:
  group: release-${inputs.repo}
  cancel-in-progress: true

steps:
  - id: checkout
    name: Checkout Code Repository
    env:
      CLONE_URL: ${inputs.clone_url}
      COMMIT_SHA: ${inputs.commit_sha}
    run: |
      git clone --depth 1 "$CLONE_URL" .
      git checkout "$COMMIT_SHA"

  - id: install-and-build
    name: Install Dependencies & Build
    run: |
      pnpm install
      pnpm run build

  - id: publish
    name: Publish to NPM
    env:
      NPM_TOKEN: ${secrets.NPM_TOKEN}
    run: |
      echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
      npx --yes semantic-release@24 -b main --no-ci

💻 CLI Usage & Commands

npx @cloud-cli/on [command] [options]

Commands

| Command | Description | | ------------------- | ---------------------------------------------------------------------------------------- | | start-server | Runs Webhook Ingress Gateway (the HTTP server receiving webhooks). | | start-workers | Runs Worker Polling loops (Scalable Workers). | | validate | Parses and validates all YAML workflows in your workflows folder without executing jobs. |

CLI and Environment Options

| Flag | Option | Default | Env | Description | | ---- | ------------- | --------------------- | --------------------- | ----------------------------------------- | | -h | --help | — | - | Prints CLI help message and exits. | | -c | --config | ./runner.config.mjs | RUNNER_CONFIG_FILE | Path to JavaScript configuration file. | | -d | --database | - | RUNNER_DATABASE_URL | SQLite database file path or HTTP URL. | | -w | --workflows | on/ | RUNNER_WORKFLOWS | Directory where workflow YAML files live. | | -p | --port | 11235 | PORT | Port for the Ingress HTTP server. | | -k | --workers | 5 | RUNNER_WORKERS | Number of worker loop threads to spawn. | | | | | RUNNER_ADMIN_SECRET | Admin token to refresh secrets via API |

Secrets


⚙️ Configuration Reference

You can customize engine behavior using runner.config.mjs in your project root:

// runner.config.mjs
import { HtmlReporter, SlackReporter, JsonFileReporter } from '@cloud-cli/on/reporters';

export default {
  port: 3000,
  workers: 5,
  workflows: '/home/workflows/',
  storagePath: '/tmp/workspaces',
  database: 'https://remote.db.com/',

  // Global environment variables passed to all steps
  env: {
    NODE_ENV: 'production',
  },

  // Custom execution reporters
  reporters: [
    new JsonFileReporter({ outputDir: './reports/json' }),
    new HtmlReporter({ outputDir: './reports/html' }),
    new SlackReporter({
      webhookUrl: process.env.SLACK_WEBHOOK_URL,
      channel: '#ci-deployments',
    }),
  ],
};

📐 Deterministic Evaluation Rules

To prevent syntax ambiguity and injection risks, fields in workflow definitions operate under three strict modes:

┌──────────────────────────────────────────────────────────────────────────┐
│ 1. RAW PASSTHROUGH MODE (`run:`)                                         │
│ • Executed verbatim as a shell process command.                          │
│ • No string replacements or engine parsing performed.                    │
│ • Access environment variables strictly via shell syntax: $MY_VAR.       │
└──────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────┐
│ 2. EXPRESSION MODE (`if:`, `eval:`)                                      │
│ • Evaluated strictly as pure JavaScript expressions via Acorn AST.       │
│ • Must be valid JS syntax (e.g. `inputs.branch === 'main'`).             │
│ • Automatically coerced to boolean in `if:` conditions.                  │
└──────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────┐
│ 3. DETERMINISTIC VALUE MODE (`env:`, `name:`, `image:`, `group:`)        │
│ • Plain strings WITHOUT `${}` remain 100% raw literal strings.            │
│ • Strings WITH `${...}` evaluate as standard ES Template Literals.       │
│ • Example: `node:${inputs.node_version}-alpine`                          │
└──────────────────────────────────────────────────────────────────────────┘

Context Scope Available in Expressions

Within ${...}, if:, and eval: contexts, the following object scopes are exposed:

  • inputs: Payload key-values received from incoming webhooks.
  • env: Merged environment variables from global config and workflow definitions.
  • secrets: Unmasked secret values loaded from .env or environment variables (SECRET_ prefix stripped).
  • steps: Execution statuses and outputs from previous steps in the workflow (steps.<id>.status, steps.<id>.outputs).
  • BUILTIN_HELPERS: JS utilities including String, Number, Boolean, and JSON.parse / JSON.stringify.

🌐 Webhook Ingress Gateway & Dashboard

The Ingress Gateway listens for incoming HTTP requests and serves the live web UI.

Endpoint Matrix

| Method | Endpoint | Description | | ---------- | ------------------ | -------------------------------------------------------------------------------------- | | POST | /webhooks/github | Webhook endpoint for GitHub events. Evaluates on.github.if triggers. | | GET | /runs | Dashboard: Live dark-mode monitoring page listing recent jobs and worker health. | | GET | /runs/:jobId | Job Report: Interactive HTML trace view with step timings and terminal log output. |

Dashboard Features

  • Real-time Auto-Refresh: /runs automatically refreshes job queue statuses (PENDING, RUNNING, SUCCESS, FAILED, CANCELLED).
  • ANSI Terminal Rendering: Uses ansi_up to render bash colors, bold highlights, and console outputs accurately in step log boxes.
  • Payload Inspection: View JSON inputs received from webhooks for easy debugging.

🔒 Security & Hardening

  1. Environment Variable Boundary: By forcing shell steps to consume data via process environment variables ($CLONE_URL), malicious webhook payloads containing shell delimiters (e.g. ; rm -rf /) cannot mutate shell script execution trees.
  2. Prototype Pollution Protection: AST evaluation explicitly blocks access to dangerous JS properties (constructor, __proto__, prototype).
  3. Payload Size Guard: The Ingress server enforces a strict 5MB payload limit to prevent Out-Of-Memory (OOM) denial-of-service attacks.
  4. Signal Traps & Resource Cleanup: Graceful process traps (SIGINT, SIGTERM) ensure active job handles are safely terminated, file descriptors are closed, and temp .env/.out files are removed via try ... finally blocks.

Development

pnpm i
pnpm run lint
pnpm run test
pnpm run build