Nothing ships forever. Everything ebbs.
The open almanac of software end-of-life.
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.
- 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.
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/ebbRequires Node.js 22 or newer for Node environments, or modern Browsers / Edge runtimes. ESM only.
| 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; // 2Import 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.
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.
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: deprecatedOr audit an entire CycloneDX SBOM:
- uses: velella-sh/ebb@v0
with:
file: bom.json
fail-on: unsupportedAutomatically 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.
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.
Install the official Ebb skill across your agent environment using the skills CLI:
npx skills add velella-sh/ebbThe 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.
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.
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.
{
"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/.
| 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. |
Every rule cites authoritative evidence with strict auditability and health monitoring:
- Provenance audit trail: Every rule specifies its creation
method(manual,imported, orupstream), reviewers list, and importer metadata. - Continuous link checks: Sources are locked in
registry/sources.lock.jsonand audited weekly by.github/workflows/sources.ymlwith 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 issueandhelp wantedfor straightforward replacement. See docs/sources-of.md.
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 |
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.
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 |
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.
If your project reads its lifecycle data from Ebb, you are welcome to show it:
[](https://github.com/velella-sh/ebb)Corrections and new rules are welcome. A rule needs an authoritative source. See CONTRIBUTING.md to get started.
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.