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

@oren-sh/cli

v0.13.0

Published

Universal pipelines — tasks como contratos, rodando em qualquer lugar

Readme

@oren-sh/cli

Oren's pipeline runner. It reads contracts, resolves implementations and runs each step as an isolated container, orchestrated by Dagger.

It implements the specification in ../spec — this repository does not define the contract format, it only executes it.

0.3.0 breaks everything that came before. The oren.yaml format changed completely from 0.2.x: arguments/extra-args became inputs, config became typed dependencies, and the protocol between CLI and worker stopped using argv and stdout delimiters. Pipelines and workers from 0.2.x do not run here. While the version is 0.x, the format may still change.

Start with GUIDE.md — a project from scratch, step by step, with every command verified.

npm install -g @oren-sh/cli

Usage

oren init              # a project that uses tasks
oren init worker <n>   # a fresh task, with a worker (--template shell|node)
oren add <source>      # brings a task into the project
oren install           # resolves images to digests and writes oren.lock
oren validate          # checks everything without starting a single container
oren doctor            # checks the prerequisites
oren run dev           # runs the `dev` pipeline from oren.yaml
oren run dev --yes     # authorizes dependencies without confirmation (CI)

oren generate gitlab dev -o .gitlab-ci.yml     # translates for the CI
oren generate cloudbuild dev -o cloudbuild.yaml

oren cache             # entries, space used and the ceiling
oren cache prune       # frees what is unused
oren cache limit 20GB  # caps the growth

Options: -f pipeline file, -p properties file, -r local registry, -v execution-engine log.

Example

cd examples/hello
oren validate
oren run dev

Two chained steps, one of them writing back to the host, with a secret input and secrecy propagation — it doubles as a smoke test of the whole flow.

Layout

| Directory | Responsibility | | ------------------- | ----------------------------------------------------------------------- | | src/spec/ | Document loading and validation, the type registry, semver | | src/registry/ | Contract and implementation resolution (local files and the remote registry) | | src/pipeline/ | Expressions with secrecy propagation, step resolution, orchestration | | src/runtime/ | Protocol v1 and container execution | | src/consent/ | Dependency authorization and its cache | | src/state/ | Run state in .oren/runs/ |

Decisions worth knowing

No live state between steps. Outputs are written to .oren/runs/<id>/ and read back from there. It keeps the local mode equivalent to the generated mode, where every step becomes a separate CI job and nothing survives between them.

Secrecy is contagious. An ordinary field that interpolates another step's secret output becomes secret itself — redacted in the log and in the on-disk state. Without that, embedding the credential in any string would be enough for it to resurface.

The CLI grants exactly what was declared. An implementation that uses the Docker socket without declaring engine/docker fails at execution. It is what stops under-declaring from becoming a ranking advantage in the catalogue.

The worker's identity is immutable. oren.lock stores the digest-pinned reference (repo@sha256:...) or the build's content digest. It is what anchors consent: without it the identity would be the tag, and republishing alpine:3.20 with different content would silently transfer the authorization to unreviewed code. Running without a lockfile works, but warns.

Consent is recorded, not asked every time. .oren/consent.json is made to be committed: the team inherits the decision and a privilege escalation becomes a diff in code review. The fingerprint covers image and dependencies, so a fresh image or a fresh dependency invalidates the earlier authorization.

Output outside the contract fails the step, even with exit code zero.

The worker's log is captured and attributed to the step. The engine's LogOutput shows the graph's operations (withExec, withNewFile), not what the worker printed — without capture, its output would never reach the user. Known limitation: it appears at the end of the step, because the SDK exposes no stream during execution.

Input with a secret field travels as a secret, not as a file. The engine prints the content of withNewFile in its progress, so --verbose would leak in plain text everything the CLI carefully redacts. Inputs without secrets stay ordinary files, which are visible and cacheable.

The execution engine is dedicated to Oren. It is not a fork: it is the official registry.dagger.io/engine image, running in its own container (oren-engine-<version>) and volume (oren-cache-<version>), selected by the SDK via _EXPERIMENTAL_DAGGER_RUNNER_HOST.

Without that, cache prune would wipe the cache of every other Dagger use on the machine and cache limit would rewrite the user's global ~/.config/dagger/engine.json. Dagger is an implementation detail of Oren and should have no consequences outside it.

The container and the volume carry the version because BuildKit's cache format has no guaranteed compatibility across versions; when a new one comes up, Oren's older ones are removed so the disk does not accumulate one copy per update. Two known risks: the environment variable carries the _EXPERIMENTAL_ prefix and may change without notice, and the cache is not shared with other Dagger uses — common layers get downloaded twice.

The worker can be built by the execution engine. An implementation declares build: { context } instead of image, and the image is built on the spot, cached by content. Without this, local development would demand docker build followed by docker save, because the engine does not see the machine's Docker daemon. An implementation with build is not publishable: whoever consumes it needs the built image.

A task with an external effect is not cached. The contract declares effects: external for push, remote tags, deploys — things whose value is not in the output. Without that the engine would return the cached result and the effect would never happen again, with the pipeline reporting success.

CI generation

oren generate <target> <environment> translates the pipeline into the platform's native configuration. The same contracts and the same digest-pinned images, executed by native jobs instead of the CLI.

It demands oren.lock: without pinned images, the generated configuration would run whatever the tag points at on any given day — losing the reproducibility that justifies generating. Implementations with build: are refused, because a runner does not have the worker's directory.

| Target | State | | --- | --- | | gitlab | output validated against GitLab CI's official schema | | github | not validated against the real platform — derived from the documentation | | cloudbuild | not validated against the real platform — derived from the documentation |

Known limitation: the worker's image needs jq when an input comes from another step — it is what assembles input.json inside the job, including interpolation in mixed text (v${outputs['x'].y}-rc), which is supported.

Authentication

oren login              # opens the browser (device flow)
oren login --token      # paste a token already issued in the web interface
echo $TOKEN | oren login --token

The default is the device flow (RFC 8628): the CLI shows a short code, you authenticate in the browser, and the CLI polls until someone approves.

Open in the browser: https://registry.oren.sh/device
and enter the code: WDJB-MJHT

      waiting for authorization…
✓ authenticated as techlite

The CLI never sees the password. That is what makes password managers, second factors and federated accounts work — none of the three fits in a terminal prompt.

What stays on disk is always a revocable token, in ~/.oren/credentials.json with mode 600. The password, when used at all, serves once and is neither stored nor resent.

--token exists because typing the password into a terminal has costs no implementation care removes: a password manager cannot reach a terminal prompt, 2FA has nowhere to go, a federated account has no password to type, and the habit of typing the registry password into a CLI is the very gesture phishing wants to train.

The token never comes as an argument — whatever is on the command line stays in the shell history and shows up in ps for any process on the machine. It comes from an echo-free prompt, or from stdin.

In CI, OREN_TOKEN — no login at all.

E-mail and password existed here and left. With SSO on the registry it went from merely uncomfortable to impossible: a federated account has no password to type.

The flow has one known attack — someone opens the request on their machine and talks another person into approving the code. Nothing in the protocol prevents it; what prevents it is the approval screen saying what is at stake and never approving on its own, even with the code pre-filled in the URL.

Language

The CLI speaks English by default and Portuguese when the environment asks. The choice comes, in this order, from OREN_LANG, LC_ALL, LC_MESSAGES and LANG; a language without a catalogue falls back to English.

OREN_LANG=pt oren run dev

The catalogues live in src/i18n/. English is canonical: it defines the TYPE the other languages have to satisfy, so a missing key does not compile — it does not become a message that silently vanishes at the wrong moment. The tests run with OREN_LANG=en pinned, and assertions compare against the catalogue instead of repeating the sentence.

What is NOT translated: command names (oren run is the same word everywhere, and translating them would invalidate every tutorial) and the help's metavalues (<source>, [pipeline]).

Registries

Contracts and implementations are read from .oren/registry/ (*.task.yaml, *.impl.yaml) and from the remote registry — the public one at https://registry.oren.sh, or whatever OREN_REGISTRY / .oren/config.json points at. The local files win: they are the development loop.

Development

npm run sync-spec   # copies schemas and types from ../spec
npm run build
npm test            # unit tests, no Docker (test runs build first)
npm run test:e2e    # 17 end-to-end tests against a real container, ~2min
npm run test:all

The end-to-end tests exist because the three most serious bugs of the first version got past typecheck and unit tests: authorization announced but not recorded, an engine-wrapped error surfacing as a stack trace, and a secret value leaking through interpolation in an ordinary field. Each of them has a test today that fails if the fix is undone — verified by reintroducing the bugs.

They skip on their own when Docker is absent, instead of failing.

sync-spec runs automatically on build. Point OREN_SPEC_PATH if the spec repository is not sitting alongside.

Not implemented

The image source (contract read from OCI labels) and published base images.