Skip to content
velella-shPublic

About

The open almanac of software end-of-life.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

195 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Ebb

Ebb

Nothing ships forever. Everything ebbs.
The open almanac of software end-of-life.

CI Coverage npm JSR skills.sh

Quick start · 5-Min Guide · Examples · Static API · Rules · Data · Performance · Docs · Contributing


Ebb is an open dataset of software lifecycle rules: what is deprecated, unsupported, end-of-life, or removed, since when, and what to move to. It comes with a small TypeScript library for reading it.

Every rule names a component by its Package URL and its versions by a VERS range, so any tool that knows a purl and a version can ask Ebb about it.

The library passes the official purl-spec suite: 586 of 586 tests (fixtures, CI), with one case (types/maven-test.json[13], purl-spec#1027) counted through a documented alternative because the fixture is inconsistent upstream; see tests/purl/README.md.

Why Ebb

  • Evidence, not opinion. Every rule cites the authoritative source behind it, the date that source was read, and who reviewed the rule and when.
  • Broad coverage. 752 rules across 25 ecosystems: language runtimes, npm, PyPI, Maven, NuGet, Cargo, Go, containers, Kubernetes APIs, GitHub Actions, Terraform, and more.
  • Standard identifiers. purl and VERS throughout, with no ecosystem-specific lookup tables to learn.
  • Actionable. Rules carry a replacement and migration guidance: the constraints to keep, the steps to take, and how to verify the change.
  • Measured impact on AI agents. Eliminates deprecated dependency picks entirely (dropping from 38% down to 0% across 100 benchmark tasks; see evals/agents/REPORT.md).
  • LLMs and agents native. Standard machine-readable documentation for models at llms.txt and llms-full.txt, backed by an official MCP server and agent skills.
  • Zero dependencies. Pure ESM with zero runtime dependencies. Instant installs, zero supply-chain risk.
  • Compact footprint. ~268 KB packed tarball with a strict 500 KB budget enforced in CI (docs/SIZE.md).
  • Offline by default. The rules ship inside the package. Newer rules arrive as signed data bundles, verified with Sigstore before use.

Quick start

For a 5-minute walkthrough across the library, CLI, AI agents (MCP & skills), static API, and GitHub Actions, see docs/QUICKSTART.md.

npm install @velella/ebb

Requires Node.js 22 or newer for Node environments, or modern Browsers / Edge runtimes. ESM only.

Supported runtimes

Runtime Support Notes
Node.js >=22 Native CLI, local cache, Sigstore bundle verification
Browsers Chromium, Firefox, WebKit / Safari Zero Node dependencies, offline in-memory data, ~135 KB gzipped (docs/BROWSER.md)
Cloudflare Workers workerd Fast execution under the free plan budget (< 15% limit) (docs/EDGE.md)
Vercel Edge edge-light Native V8 isolate support (docs/EDGE.md)
Deno >=1.40, 2.x Native ESM support via jsr:@velella/ebb or npm: (docs/DENO.md)
Bun >=1.0 Full CLI and library compatibility (docs/BUN.md)
import { check, replacementFor } from "@velella/ebb";

const node = check("node", "18.20.4");
node.status;           // "end-of-life"
node.matches[0]?.date; // "2025-04-30"

const request = check("pkg:npm/request", "2.88.2");
request.status;                              // "deprecated"
replacementFor("pkg:npm/request", "2.88.2"); // "Native fetch or a maintained HTTP client"

check takes a purl or a product name plus a version and returns every matching rule synchronously. Pass an optional asOf day (YYYY-MM-DD) to fill each match's daysLeft; omit it to keep the two-argument form (daysLeft stays null). The first call may block while it reads the active data file; later calls reuse the cached index:

import { check } from "@velella/ebb";

// A deprecated package
// `date: null` means the rule has no deadline date.
// Without `asOf`, `daysLeft` is always null.
check("pkg:npm/left-pad", "1.3.0");
// {
//   schemaVersion: 1,
//   status: "deprecated",
//   matches: [
//     {
//       ruleId: "npm.package.left-pad.deprecated",
//       event: "deprecated",
//       date: null,
//       daysLeft: null,
//       replacement: "String.prototype.padStart()",
//       sources: [
//         {
//           title: "left-pad package deprecation notice",
//           url: "https://www.npmjs.com/package/left-pad",
//           accessedAt: "2026-10-13"
//         }
//       ],
//       reviewedAt: "2026-10-14"
//     }
//   ],
//   version: "1.3.0"
// }

// A safe version
check("pkg:generic/nodejs", "24.0.0");
// { schemaVersion: 1, status: "ok", matches: [], version: "24.0.0" }

// A product name
check("node", "18.20.4");
// {
//   schemaVersion: 1,
//   status: "end-of-life",
//   matches: [
//     {
//       ruleId: "nodejs.runtime.eol-18",
//       event: "end-of-life",
//       date: "2025-04-30",
//       daysLeft: null,
//       replacement: "Node.js 22 LTS or later",
//       sources: [
//         {
//           title: "Node.js Release Working Group schedule",
//           url: "https://github.com/nodejs/Release/blob/main/schedule.json",
//           accessedAt: "2026-10-17"
//         }
//       ],
//       reviewedAt: "2026-10-17"
//     }
//   ],
//   version: "18.20.4"
// }

// Pass `asOf` to measure daysLeft from that day (never from a clock).
check("pkg:generic/nodejs", "22.11.0", "2026-04-01");
// {
//   schemaVersion: 1,
//   status: "scheduled",
//   matches: [
//     {
//       ruleId: "nodejs.runtime.eol-22",
//       event: "scheduled",
//       date: "2027-04-30",
//       daysLeft: 394,
//       replacement: "Node.js 24 LTS or later",
//       sources: [ /* … */ ],
//       reviewedAt: "2026-10-24"
//     }
//   ],
//   version: "22.11.0",
//   asOf: "2026-04-01"
// }

To inspect a component's rules or check a batch of dependencies:

import { checkAll, rulesFor } from "@velella/ebb";

const pythonEolRules = rulesFor("pkg:generic/python", { event: "end-of-life" });
pythonEolRules.some((rule) => rule.id === "python.runtime.eol-3.10-and-older"); // true

const batch = checkAll([
  { purl: "pkg:npm/request", version: "2.88.2" },
  { purl: "pkg:generic/nodejs", version: "18.20.4" },
]);
batch.summary.total; // 2

Import from @velella/ebb. Legacy 0.1.x subpaths keep resolving until 1.0 with @deprecated notices; see docs/API-STABILITY.md for entry-point details.

Command-Line Interface (CLI)

Verify dependencies, run batch SBOM checks, or find modern replacements directly from the terminal without external dependencies:

# Check a package URL with human-readable colored output
npx @velella/ebb check pkg:npm/[email protected]

# Output Markdown for pull request comments
npx @velella/ebb check pkg:npm/[email protected] --format markdown

# Check dependencies from CycloneDX or JSON
npx @velella/ebb check-all bom.json --json

# Find recommended replacement
npx @velella/ebb replacement pkg:npm/[email protected]

# Query upcoming end-of-life events within a time window
npx @velella/ebb upcoming --within 90d --ecosystem nodejs

# List rules whose review window has expired
npx @velella/ebb stale --as-of 2026-11-14

# Inspect evidence sources and review provenance for a rule
npx @velella/ebb sources npm.package.request.deprecated

# Verify a downloaded data bundle or artifact signature offline
npx @velella/ebb verify dist/data/bundle.json

# Update lifecycle data safely and reversibly
npx @velella/ebb update

# Compare two data releases and inspect rule changes
npx @velella/ebb diff 2026.10.01 2026.10.16 --format markdown

# Evaluate lifecycle status as of a specific date (time travel)
npx @velella/ebb as-of 2027-05-01 node 22.11.0
✖ pkg:npm/[email protected]: deprecated
  Rule: npm.package.request.deprecated
  Event: deprecated (2020-02-11)
  Replacement: Native fetch or a maintained HTTP client
  Sources:
    - https://www.npmjs.com/package/request
  Offing can fix this: https://github.com/velella-sh/offing

Supports --format <text|markdown|json>, --fail-on <threshold>, --no-color (respects NO_COLOR), and --no-hint. See docs/cli.md for complete options and exit codes.

GitHub Action

Run continuous lifecycle checks across your pull requests and pipelines using the official GitHub Action:

- name: Audit Dependencies with Ebb
  uses: velella-sh/ebb@v0
  with:
    purls: |
      pkg:npm/[email protected]
      pkg:docker/library/[email protected]
    fail-on: deprecated

Or audit an entire CycloneDX SBOM:

- uses: velella-sh/ebb@v0
  with:
    file: bom.json
    fail-on: unsupported

Automatically generates inline workflow annotations (::warning::, ::error::), writes Markdown tables to the GitHub Actions Job Summary, and supports remediation hints. See action/README.md for details.

AI Agents (MCP & Skills)

Ebb provides official guardrails for AI coding agents (Claude Code, Cursor, Codex, Gemini CLI, Antigravity) to prevent agents from recommending deprecated or end-of-life dependencies.

Agent Skill (skills.sh)

Install the official Ebb skill across your agent environment using the skills CLI:

npx skills add velella-sh/ebb

The skill equips agents with a check-before-add workflow: discovering project runtimes (.nvmrc, Dockerfile), checking new packages before install, and verifying GitHub Actions runner deprecations. See Agent Skills.

MCP Server (@velella/ebb-mcp)

Connect Ebb directly to agent environments via the Model Context Protocol over stdio:

# Claude Code
claude mcp add ebb -- npx -y @velella/ebb-mcp

# Cursor / Codex / Gemini
# Declare in your mcp.json under mcpServers:
# "ebb": { "command": "npx", "args": ["-y", "@velella/ebb-mcp"] }

Exposes check, check_all, replacement_for, and the ebb://upcoming resource. See MCP Server.

Static JSON API

Ebb provides an open, static JSON API served directly from GitHub Pages at https://velella.sh/ebb/api/v1/. Query any component lifecycle without installing any package or running a server:

# Query a package lifecycle with curl
curl -s https://velella.sh/ebb/api/v1/npm/request.json | jq .

# Query an ecosystem
curl -s https://velella.sh/ebb/api/v1/npm.json | jq '{ rulesCount, componentsCount }'

# Query upcoming deadlines
curl -s https://velella.sh/ebb/api/v1/upcoming.json | jq '.upcoming[:3]'

Features include global component indexing (/index.json), name prefix search (/search-index.json), upcoming EOL events (/upcoming.json), ETags for conditional caching, and zero-dependency client helpers (fetchRule, fetchComponent). See docs/static-api.md for full endpoint specifications and client SDK examples.

What a rule looks like

{
  "id": "nodejs.runtime.eol-20",
  "purl": "pkg:generic/nodejs",
  "vers": "vers:semver/>=20.0.0|<21.0.0",
  "event": "end-of-life",
  "title": "Node.js 20 is end-of-life",
  "severity": "high",
  "replacement": "Node.js 22 LTS or later",
  "deadline": "2026-04-30",
  "sources": [
    {
      "title": "Node.js Release Working Group schedule",
      "url": "https://github.com/nodejs/Release/blob/main/schedule.json",
      "accessedAt": "2026-10-17"
    }
  ],
  "provenance": { "observedAt": "2026-10-17", "reviewedAt": "2026-10-17", "reviewer": "arminazimi" },
  "migration": { "constraints": ["…"], "steps": ["…"], "verification": ["…"] }
}

Shortened. The full format is in docs/RULES.md and schemas/.

The data

Path What it is
registry/ The rules, one file per ecosystem (ebb.registry.v2).
schemas/ JSON Schemas for the registry, a single rule, and the data bundle.
cases/ Behaviour cases: this purl at this version is judged by exactly these rules.
data/ The Sigstore trusted root used to verify data bundles offline.

Source health & provenance

Every rule cites authoritative evidence with strict auditability and health monitoring:

  • Provenance audit trail: Every rule specifies its creation method (manual, imported, or upstream), reviewers list, and importer metadata.
  • Continuous link checks: Sources are locked in registry/sources.lock.json and audited weekly by .github/workflows/sources.yml with backoff retry, redirect tracking, and content version verification.
  • Wayback archive preservation: 100% of evidence sources are archived in the Wayback Machine and archive.today, preserving immutable proof of lifecycle events.
  • Community issue triage: Dead links automatically open issues labeled good first issue and help wanted for straightforward replacement. See docs/sources-of.md.

Performance

Ebb is designed for CI pipelines and real-time dependency checks where lookups cannot add noticeable latency. Every rule lookup runs in sub-millisecond time.

Measured using npm run bench:

Operation Target Median latency Throughput
check (single) Single component (pkg:npm/left-pad) 0.0016 ms ~625,000 ops/s
check (per-component) 1,000 components 0.0029 ms ~345,000 ops/s
checkAll 1,000 components batch 0.0525 ms ~19,000 batches/s
Data load All 25 bundled registries (752 rules) 12.7 ms ~79 loads/s

Cold start overhead

Measured across fresh processes (ESM import + cold data load + first check):

  • Node.js 24: ~88 ms total (31 ms import, 55 ms first check)
  • Node.js 22: ~122 ms total (55 ms import, 65 ms first check)

Once loaded into memory, registries and precompiled VERS ranges remain cached, keeping per-component evaluations well under 1 ms.

Examples

Runnable examples for common workflows and deployment environments are located in examples/:

Example Description
package.json Audit Node.js dependencies directly from application manifests
CycloneDX SBOM Evaluate software bills of materials directly via CLI or TypeScript API
Dockerfile Check container base images (FROM) against upstream EOL schedules
GitHub Actions Audit .github/workflows/*.yml for retired runner action versions
Upcoming EOL Forecast lifecycle deadlines and calculate days left (asOf)
Static API Query Ebb from shell scripts with curl and jq without Node.js
Browser Interactive in-memory lifecycle inspection in client-side HTML
Cloudflare & Vercel Deploy Ebb on Edge isolates within free-tier budgets
Deno Native Deno 2.x and JSR import examples
Bun High-throughput lifecycle evaluations under Bun runtime

Documentation

These pages are also published as a site, built with Mizzen and Lateen: https://velella.sh/ebb/.

  • Quickstart: 5-minute guide across library, CLI, AI agents, static API, and GitHub Actions.
  • CLI: command-line interface for offline checks and SBOM batch evaluation.
  • Upcoming deadlines: query scheduled and upcoming end-of-life events within a time window.
  • Time-travel evaluation (asOf): evaluate lifecycle status as of past or future dates with deterministic replay.
  • Stale rule review: find rules past their review window and the weekly maintainer issue.
  • Agent Skills: guardrails for AI coding agents via skills.sh.
  • MCP server: connect Ebb over standard stdio JSON-RPC 2.0.
  • Agent Evaluations: benchmark report measuring agent accuracy with and without Ebb.
  • llms.txt & llms-full.txt: LLM-optimized documentation according to the llms.txt standard.
  • Writing a rule: the format, the evidence policy, and the review workflow.
  • Importers: tools that draft rules from authoritative sources for a maintainer to review.
  • Data bundles, signing and trust: how newer data is published, verified, and pinned.
  • Data freshness policy: how Ebb measures evidence age, enforces review windows, and stays fresh.
  • Data changelog: track additions, updates, deprecations, and removals in the dataset.
  • Design decisions: the records behind the registry format, importers, and data bundles.

Using Ebb in your tool

If your project reads its lifecycle data from Ebb, you are welcome to show it:

eol data by ebb

[![eol data by ebb](https://img.shields.io/badge/eol%20data%20by-ebb-3F6E66?labelColor=1F1F28&style=flat&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAgMTIwIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjEyMCIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJFYmIiPjx0aXRsZT5FYmI8L3RpdGxlPjxwYXRoIGQ9Ik0yNiAzNEg3MEE2IDYgMCAwIDEgNzYgNDBWNDBBNiA2IDAgMCAxIDcwIDQ2SDI2QTYgNiAwIDAgMSAyMCA0MFY0MEE2IDYgMCAwIDEgMjYgMzRaTTM4IDU0SDgyQTYgNiAwIDAgMSA4OCA2MFY2MEE2IDYgMCAwIDEgODIgNjZIMzhBNiA2IDAgMCAxIDMyIDYwVjYwQTYgNiAwIDAgMSAzOCA1NFpNNTAgNzRIOTRBNiA2IDAgMCAxIDEwMCA4MFY4MEE2IDYgMCAwIDEgOTQgODZINTBBNiA2IDAgMCAxIDQ0IDgwVjgwQTYgNiAwIDAgMSA1MCA3NFoiIGZpbGw9IiM3QUE4OUYiLz48L3N2Zz4K)](https://github.com/velella-sh/ebb)

Contributing

Corrections and new rules are welcome. A rule needs an authoritative source. See CONTRIBUTING.md to get started.

License

The code is MIT. The data (registry/ and schemas/) is CC BY 4.0. Credit it as described in ATTRIBUTION.md.


Ebb is part of Velella.

About

The open almanac of software end-of-life.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages