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

@myelinbridge/cli

v0.11.1

Published

Myelin Partner Ingestion CLI — push R&D data deliveries from a pipeline: preflight against the client's quality rules, resumable upload, submit, track review outcomes.

Downloads

1,101

Readme

@myelinbridge/cli

Push R&D data deliveries into Myelin from a pipeline — preflight against the client's published quality rules, resumable upload, submit, and track review outcomes. Full API reference: https://myelinbridge.com/developers.

Quick start (~10 minutes from key to first submit)

export MYELIN_API_KEY=myl_live_…     # created by your bridge owner in Bridge → API

npx @myelinbridge/cli ping                 # verifies auth, prints your projects
npx @myelinbridge/cli datasets             # what you can deliver to, and whose move it is
npx @myelinbridge/cli contract --dataset onco1-wes            # what is expected of your delivery
npx @myelinbridge/cli sample-depth 1 --dataset onco1-wes      # once, before your first submit
npx @myelinbridge/cli roles --dataset onco1-wes               # which file plays which role
npx @myelinbridge/cli roles set samplesheet /metadata/samplesheet.csv --dataset onco1-wes
npx @myelinbridge/cli check ./run_042 --dataset onco1-wes    # validate BEFORE uploading a byte
npx @myelinbridge/cli push  ./run_042 --dataset onco1-wes --submit
  • Declare your sample depth once, first. The client creates and describes the dataset; you own your output structure, so you tell Myelin at which folder depth a sample sits — 0 = the delivery root is one sample, 1 (default) = each top-level folder is a sample, 2 = one level deeper. Sample-scoped quality checks group by it, so getting it right up front is what makes per-sample verdicts mean anything. It is idempotent (safe to assert on every pipeline run, before and after the lock) and locks once your first batch leaves draft, so that verdicts stay comparable across deliveries — after that, re-asserting the current value still succeeds and only a change exits 2. This is the only dataset field you can write.

  • Declare which file plays which role — whenever you like (0.11.0). Quality checks read files by ROLE (samplesheet, checksum_manifest, qc_report, subject_roster, capture_bed), not by a filing convention you never agreed to. roles shows what is declared and what Myelin detected in your deliveries; roles set <role> <path> confirms a file; roles none <role> states your dataset has no such file (a statement, not a gap). Nothing is ever required to deliver — an undeclared role just means the checks that read it report "could not check" instead of running, so declaring is how you activate more checks before upload and catch problems before review does. Unlike sample-depth it never locks, and it is idempotent, so a pipeline can assert it on every run. The samplesheet is sticky: send it once and every later delivery reconciles against it — a partial delivery (93 of 96) is reported as a state, never as a failure.

  • A missing path in roles set is refused, not guessed (0.11.1). Flags are not positional arguments: roles set samplesheet --dataset onco1-wes (path omitted) used to declare the samplesheet at the literal path --dataset and print a tick. Every samplesheet check then reported "could not check — the declared file is not in the delivery" on a delivery that was fine. The command now exits with its usage line instead.

  • --dataset takes the slug in any case (0.11.0). Slugs are matched case-insensitively (onco1-wes and ONCO1-WES name the same dataset); an id or an exact name works too.

  • Resume = re-run. push is idempotent: already-uploaded files are skipped (path + size), and within a large file, parts that already landed are skipped too (S3 multipart). Uploads go direct to storage over short-lived presigned URLs — no credential is stored on your machine, and revoking the API key cuts off signing immediately.

  • Transient failures retry themselves. Since 0.8.0 a rate limit (429) waits out Retry-After and retries on every command, and a part upload that hits a storage hiccup (5xx, an edge timeout, an expired URL) re-signs, backs off, and retries up to 4 attempts before surfacing — an unattended pipeline run survives a blip. A retried --submit whose first attempt actually landed gets a success echo (already_submitted: true), not a false failure.

  • Slow connections shrink their parts. Since 0.9.0, when the same part dies twice on a timeout (the edge kills any PUT that runs too long — HTTP 524), push restarts the file with smaller parts, 64 → 16 → 5 MB, instead of retrying the same slice into the same wall. A hospital-grade uplink down to roughly 30 KB/s can now complete a delivery; it is slower, but it finishes.

  • Every file is fingerprinted. Since 0.7.0, push computes an MD5 of each file while it uploads and records it with the delivery. If the client's quality contract includes a checksum-manifest check, your delivery verifies against your own md5_manifest.csv instead of reading as "unverifiable".

  • Read the contract before you build the delivery. contract prints what the client expects — every check as one plain sentence, grouped by what it answers (completeness, structure, validity, consistency, integrity, privacy), and marked ! when a failure blocks validation or ? when the client's reviewer confirms it rather than asking you to fix it. It also tells you which checks check can verify locally and which only run once the files are uploaded, so nothing about the bar is a surprise at review time.

  • check costs nothing. It evaluates your local file list against the dataset's quality checks server-side — same engine, same verdicts as submit — without uploading. Exit code 2 means the delivery would not be validatable as it stands: a blocking rule fails, or a blocking rule could not be evaluated at all.

  • A check has five answers, not three (since 0.10.0). Alongside passed, flagged and failed, the engine can now say it could not check something (a missing precondition, or a rule it cannot evaluate) and that a rule does not apply to your delivery. This matters to you in one specific way: a rule the client wrote badly used to come back as a failure on your delivery. It now says the rule could not be evaluated, and tells you it is not yours to fix. check prints the count it could not check and what each one needs — supply it and those checks run on your next delivery, which is fewer rejections later.

  • Some checks are confirmed, not fixed. A rule marked needs confirmation asks nothing of you: the client's reviewer records what they decided and the delivery proceeds. check reports these and never exits 2 on them.

  • The fix loop is machine-readable. On changes_requested, myelin status <batch> --json returns the failed files, reviewer comments, and rule remediation hints; fix, re-push --submit, unchanged files keep their review votes.

  • Limits. push declares 500 files per call and chunks automatically — nothing for you to split. check sends your whole file list in one preflight call, which accepts at most 10 000 files — a larger delivery cannot be preflighted by check today (the API answers 400 too_many_files); its checks still run at submit. A delivery holds at most 25 000 files (submit refuses above that with 422 submit_blocked), and a checksum manifest is inspected up to 16 MiB.

If you are the client, not the partner

Two kinds of key exist, and they are not interchangeable. Everything above needs a partner key (write: upload, submit). A client key is read-only and answers the question your own systems ask once the data has landed: the bucket is full of UUIDs — what is this?

Where they live follows from what they are. A partner key belongs to one bridge, because a partner does. A client key belongs to your organisation: one key, every partner, one answer. Your organisation admin creates it in Organisation → API keys. To narrow one to a single partner's data, scope it to that partner's projects.

export MYELIN_API_KEY=myl_live_…

# What has landed, newest first (page with --cursor from the printed next_cursor)
myelin deliveries --dataset <dataset-id>

# What is this object, exactly?
myelin resolve gs://acme-landing/inbox/acme-cro/4319…/de99…/7aa5…/data/SAMPLE_01/reads.fastq.gz
#   file · gs://…/reads.fastq.gz
#     project   ONCO1 — Oncology discovery
#     dataset   WES batch 7 (Genomics)
#     batch     ONCO1-WES-007 · #7
#     validated 2026-08-07T18:05:12Z · delivered 2026-08-07T18:06:20Z
#     manifest  gs://…/7aa5…/_myelin/manifest.json
#     file      reads.fastq.gz · 4096 bytes

resolve accepts a full gs:///s3:// URI, a bare prefix, or a single id, and answers at whatever granularity the path supports.

Each delivery also carries the same record as a file, written next to the data at _myelin/manifest.json (plus _myelin/files.csv, a flat table you can load straight into a warehouse). Prefer the file for anything auditable: it is frozen at delivery time, needs no credentials, and does not depend on Myelin being reachable. Use the API when you want it live.

A partner key calling these gets 403 wrong_key_side, and vice versa.

Machine mode

Every command takes --json. Exit codes: 0 ok · 1 error · 2 blocked (blocking preflight failure, a blocking rule the engine could not evaluate, locked delivery, blocked submit, locked sample depth).

check --json carries the numbers to branch on rather than the prose:

| Field | | |---|---| | blocking_failures | Blocking rules that were evaluated and failed. Unchanged meaning since the first release. | | blocking_not_evaluated | Blocking rules the engine could not evaluate. New in 0.10.0 — these stop the reviewer validating just as surely, which is why check now exits 2 on them too. | | must_acknowledge_failures | Rules the client asked to be told about. Reported, never exited on. | | counts | passed, flagged, failed, not_evaluated, not_applicable (which sum to evaluated), plus deferred, manual and checks (evaluated + deferred + manual === checks). |

Every per-check result carries details.abstained when the engine did not conclude: rule means the client's rule could not be evaluated and there is nothing on your side to fix; data means something the check needs is missing from the delivery; nothing_to_evaluate means the rule matched none of your files. Branch on that before you page anyone.

API errors carry structure, not just prose: in --json mode an error is { "error", "code", "status", "request_id" } — branch on code, and quote the request_id when reporting a problem (it is printed in human mode too; it lets Myelin find the exact server-side log line). myelin version prints the CLI version.

Environment

| Variable | | |---|---| | MYELIN_API_KEY | Required. Created by your bridge owner in Bridge → API. | | MYELIN_API_URL | Optional. Defaults to https://myelinbridge.com/api/v1. | | MYELIN_API_HEADER | Optional. Extra headers sent with every API call, one Name: value per line — for a Myelin deployment fronted by something that authenticates before Myelin does (a corporate gateway, an SSO-protected preview). It can never override Authorization. |

Webhooks instead of polling

Register an HTTPS endpoint (portal Bridge → API, or POST /v1/webhook-endpoints) to receive signed events (batch.validated, batch.changes_requested, batch.transferred, …). Verification snippets: https://myelinbridge.com/developers. Polling fallback: GET /v1/events?cursor=….