How We Score

A maintenance-health score derived from observable GitHub activity and workflow signals. It is not a security, license, or compliance assessment. Every project is evaluated across 8 weighted GitHub-backed signals and combined into a single 0-100 score.

Scope: This is a maintenance-health score. It is designed to help humans and AI agents decide whether a dependency still looks actively maintained. It is not a security, license, or compliance verdict.
Signal Weights
Last Commit 25%
Last Release 15%
PR 15%
Issue Staleness 10%
Recent Contribs 10%
Bus Factor 10%
CI/CD Activity 10%
Stars 5%
Last Commit Last Release PR Responsiveness Issue Staleness Recent Contributors Bus Factor CI/CD Activity Stars

Signals

Last Commit 25%

How recently the default branch received a commit. This is the strongest indicator that someone is actively working on the project.

RecencyScore
Within 30 days100
Within 90 days75
Within 180 days50
Within 1 year25
Over 1 year ago0
Note: Stability override: Projects with no open issues, no open PRs, and 10+ closed issues score 100 even if the last commit was over a year ago.

Source: defaultBranchRef.target.history(first: 1) · Direct measurement

Last Release 15%

When the most recent release was published. Regular releases indicate a project that ships to users, not just commits to main.

RecencyScore
Within 90 days100
Within 180 days75
Within 1 year50
Over 1 year ago0

Source: releases(last: 1) · Direct measurement

PR Responsiveness 15%

Median age of the 20 most recently updated open pull requests. It is a sampled proxy for maintainer responsiveness, not a full-history measurement.

Median PR AgeScore
Under 7 days100
Under 30 days75
Under 90 days50
Over 90 days25
Note: Inbox zero: If there are no open PRs and the project has a history of closed issues, the score is 100. If there is no issue history at all, the score defaults to 75.

Source: pullRequests(first: 20, states: OPEN, orderBy: UPDATED_AT) · Sampled proxy

Issue Staleness 10%

Median age of the last comment on the 50 most recently updated open issues. It is a sampled proxy for maintainer triage activity.

Median Comment AgeScore
Under 7 days100
Under 30 days75
Under 90 days50
Over 90 days25
Note: Inbox zero: No open issues plus a history of closed issues scores 100. No issue history at all scores 75.

Source: issues(first: 50, states: OPEN, orderBy: UPDATED_AT) · Sampled proxy

Recent Contributors 10%

Unique commit authors in the last 90 days, sampled from up to 100 recent commits on the default branch.

Contributors (90d)Score
6 or more100
2 - 575
150
00

Source: defaultBranchRef.target.history(first: 100, since: 90d ago) · Sampled proxy

Bus Factor 10%

Share of recent commits from the top contributor, derived from the same 90-day / 100-commit contributor sample.

Top Contributor %Score
Under 50%100
50% - 69%75
70% - 89%50
90% and above25
Note: Solo-maintainer forgiveness: small projects under 1,000 stars with a dominant contributor score 85 instead of 25.

Source: Calculated from sampled commit author distribution · Sampled proxy

CI/CD Activity 10%

Checks whether CI workflows exist, how recently they ran, how often they ran in the last 30 days, and a sampled recent success rate.

FactorMax Points
Workflows present30
Last run within 7 days30
30+ runs/month20
90%+ success rate20

Source: object(expression: "HEAD:.github/workflows") + REST /actions/runs · Sampled proxy

Stars 5%

Absolute GitHub star count as a low-weight proxy for community interest. Popularity does not imply maintenance.

StarsScore
1,000+100
100 - 99975
10 - 9950
Under 1025

Source: stargazerCount · Direct measurement

Verdicts

The weighted score maps to one of five verdicts — each describes the observed maintenance state, not a trajectory or risk guarantee.

🟢
Healthy
80 – 100
🟡
Stable
60 – 79
🟠
Degraded
40 – 59
🔴
Critical
20 – 39
Unmaintained
0 – 19

See for yourself:

Overrides

Archived repositories are automatically scored 0 with the verdict "Unmaintained" regardless of other signals. If the repository owner has explicitly archived it, the project is no longer maintained.

Caching

Results are cached to avoid excessive API calls and to keep responses fast. Free-to-use requests share one cache policy:

AccessFresh TTLStale TTL
Free to use1 day2 days

Cache Status

API responses use canonical cache status names so agents can tell whether a score came from a fresh fetch or a cached evaluation.

StatusMeaning
l1-hitL1 cache hit
l2-hitL2 cache hit
l2-staleL2 stale
l2-stale-degradedL2 stale (degraded)
l3-missLive fetch

During the stale window, you'll receive the cached result immediately while a background refresh runs. After the stale window, a fresh fetch is triggered synchronously.