libyears

Questions

The word is new to most people, and so is measuring a codebase this way. These are the questions that come up first, answered for anyone who runs, maintains or pays for software.

What is a libyear?

A libyear is one library, one year behind its newest release. If your project uses a version of a library published in March 2021 and the newest version came out in March 2025, that library is four libyears behind. Add up every library in a project and you have the project’s number.

Ten libraries each a year behind is ten libyears. So is one library ten years behind. Zero means everything is current. The measure was proposed by researchers in 2015 and is used by Renovate, Sonatype and others because it answers a plain question: how much of the world moved on without you?

How is the number worked out?

From two dates per library: when the version you have was published, and when the newest stable version was published. Both come from the npm registry. Which version you have is read from your lockfile, the file your package manager writes to record exactly what it installed.

The headline counts the libraries you chose directly. The ones those pull in behind them are shown too, but not added to the total, because nobody upgrades them on purpose.

What is a good number?

There is no universal line, and anyone who gives you one is guessing. A project under a libyear or two is being looked after. A few is normal for something in steady use. Tens mean an upgrade project is waiting, whether or not anyone has scheduled it.

The more useful question is the direction. A number that creeps up every month is a project nobody is maintaining; one that drops after each sprint is one somebody is. The dashboard shows both the level and the trend, and lets you set a threshold per client so you hear about it when a project crosses the line.

My application works. Why does it matter that its libraries are old?

Because it stops being true quietly. Old versions stop receiving security fixes, so a vulnerability found next year is fixed only in a version you are not on. The language runtime it depends on reaches its end of life. And the longer the gap, the bigger the jump when you finally have to move.

Small updates done often are cheap: a minor version rarely changes how anything works. Skip them for two years and the same libraries are now several major versions ahead, each one having removed or renamed something your code uses. That is the point at which an afternoon’s update becomes a month’s project, usually discovered when something else forces it.

What is a major version, and why does upgrading break things?

Library versions are numbered major.minor.patch, for example 18.2.0. A patch fixes bugs. A minor adds features without changing existing ones. A major is the maintainers saying: this version removes or changes something, and code written for the old one may not work. React 17 to 18, Next.js 12 to 13, Node 16 to 20 are all majors.

One major at a time is manageable. Three at once, across a dozen libraries that depend on each other, is where projects stall. The dashboard counts majors behind separately from libyears for that reason, and the upgrade brief orders the work so each step leaves the application running.

What does end of life mean?

The date after which the people who make something stop fixing it, including security holes. Node.js versions, frameworks and databases all publish these dates in advance. An application on an end-of-life runtime is not broken, but every vulnerability found from that day on stays open, which is why the health grade caps it below 50 regardless of everything else.

The dates for the common ones are on pages like /eol/nodejs, with no account needed.

What do Needs attention, Quick wins, Health and the grade mean?

Needs attention counts libraries with a published vulnerability that is critical or high and, for the critical ones, confirmed by more than one source, so a single automated report does not page you. Quick wins are vulnerabilities a small update would close, with no major version to cross: the best rows on the page, because they are real security fixes that cost an afternoon.

Health is 0 to 100, combining how far behind the project is, whether its libraries are still maintained, and what is dangerous today, with hard caps: an end-of-life runtime caps it at 49, an open critical vulnerability at 59. The grade is the same number as a letter: A from 85, B from 70, C from 55, D from 40, F below that. The dashboard shows each part beside the total so the number can be argued with.

What does it read from my repositories?

Two kinds of file. The manifest (package.json) lists what your project asked for. The lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml or bun.lock) records exactly what was installed. It also reads Dockerfiles and CI workflow files, because container images and CI actions are dependencies too. It never reads your source code and never clones a repository.

Private package names, the ones that would tell an outsider what your internal systems are called, never leave the system. The security page lists every file path it can fetch.

Will it change my code or open pull requests?

No. It is read-only by design. It never writes to a repository, never opens a pull request and never installs anything. The upgrade brief it produces is a document you hand to a developer, or to whichever coding agent you already use, as a pre-filled issue.

How is this different from Dependabot or Renovate?

Those tools open a pull request for each outdated library in each repository. They are good at that, and they work fine alongside this. What they do not give you is one screen across every repository you look after, a number you can put in front of a client, or an order to do the work in.

Most teams with forty repositories also have four hundred open bot pull requests nobody reads. The problem was never knowing that something is outdated. It is knowing which project to deal with first.

What if a repository has no lockfile?

It is still scanned, from the ranges declared in the manifest, and marked as approximate. A range like ^18.0.0 says what was asked for, not what was installed, so the numbers for that repository are a floor rather than a measurement. Committing the lockfile fixes it.

Do I have to install the GitHub App?

No. npx libyears in any project prints the same report from your machine, offline, and sends nothing anywhere. The App is what gives you the dashboard across many repositories, rescans on a schedule, and the client reports.

Which languages does it cover?

JavaScript and TypeScript projects that install from npm, with any of the four package managers, plus the Node runtime, container base images and GitHub Actions they run on. Python and Ruby are next.

What does it cost?

Five private repositories are free, and public repositories are always free. Paid plans are priced per repository, never per developer, from $19 a month. The pricing page has the ladder, and the showcase lets you see the dashboard on ten well-known projects before signing in.

Something missing? Write to hello@libyears.com or see the dashboard on ten well-known projects in the showcase.