Methodology

How we measure ship status.

OSSEAN reports one number about 728 repositories: when GitHub last saw a push. Everything else on this site — the counts, the badges, the leaderboard — is that one number and a date. This page is the whole method, including the parts that make it weaker.

The honest-claims contract

What we claim, and what we refuse to claim.

This is the contract the product is built against. It is published as written, not summarised, because the limitations are the point.

  1. The measured quantity is pushed_at from the GitHub API: the last time any branch of the repository received a push. Everywhere in the product it is phrased as a push — “last push,” “pushed 3 days ago” — never “actively maintained,” “healthy,” or “alive.”

  2. A push is not a release, a commit is not a feature, and a merged PR is not a shipped product.

  3. Bot pushes count. Dependabot, translation sync bots, gh-pages deploys, and generated-docs commits all bump pushed_at. We do not filter them and we do not claim to.

  4. A quiet repo may be a finished one. A stable library with no open work reads as silent here. That is a limitation of the metric, stated as such on the detail page and on the silent list.

  5. Development can move. Work migrating to a monorepo, a fork, or a private mirror shows as silent even though the product ships. The directory records the repo it was pointed at.

  6. The score is trivially gameable by pushing an empty commit daily. Mitigations: pushBits caps at 25 of 100 points; the release component needs a real tagged release; the roster cannot be bought into, since a listing comes from a published confidence gate or from a person, and never from a sponsorship; and score is never the default sort (stars are). We publish the algorithm rather than pretending it is hard to game.

  7. Snapshot age is always visible: every page’s footer dates the daily run it was built from, and any repo with lastGoodAt older than 3 days is labelled unverified, not guessed. After 14 failed fetches in a row a repo is marked gone instead, which reads as silent and says why on its page.

  8. License status is GitHub’s license.spdx_id, not legal advice. 25% of the directory — 179 of 728 repositories — is NOASSERTION/null and is shown as “license unknown,” never as “open” or “closed.”

Thresholds

Four states, 30 and 120 days.

Days are counted from pushed_at to the moment of the daily run described below. The two cut-offs sit on a real cliff in the data: 78% of repositories clear 30 days, and the next three months add 7%. Archived, disabled, and deleted repositories are forced to silent whatever their last push says.

StateRuleReposWhat it does and does not mean
Still shipping≤ 30 days since the last push566Someone pushed to some branch inside the window. Not a release, not a feature.
Slowed31–120 days50Quiet, not gone. A deliberately thin transition band.
Gone silent> 120 days, or archived, disabled, or deleted112No push in four months, or archived. Some of these are finished, not dead.
Unverifiedour own fetch has failed for 3+ days0We could not ask GitHub, so we do not answer. This is not a judgement about the repo.

Ship score

0 to 100, and how each point is earned.

The score exists for ranking and sorting only. Status stays threshold-driven so it can be explained in one sentence. Four parts add up, every input is a stored field, and the whole thing is recomputable from the published snapshot — a threshold change is a rerun, not a re-fetch.

Recency — up to 55 points
Halves every 45 days since the last push. A repo pushed today gets the full 55; at 45 days it has 27, at 90 days 14.
Cadence — up to 25 points
How many of the last 32 daily checks saw a new push. Twenty days out of the window is full marks. This is the part an empty daily commit can farm, which is why it is capped at a quarter of the score.
Releases — up to 12 points
Halves every 180 days since the latest tagged release. Unknown scores zero rather than a penalty, so a project we have not checked for releases is never punished for our gap.
Openness — up to 8 points
8 for an OSI-approved license, 4 when GitHub cannot parse one, 0 otherwise. Archived, disabled, or deleted repositories score 0 overall regardless of the other three parts.

Where the data comes from

One GitHub call per repo, once a day.

The directory is a roster of 728 repositories. A daily job maps over that list, asks the GitHub REST API for each repository, and writes one snapshot file — the same file this page, the homepage, and every badge read from. Every status and day count on the site is measured against that file’s timestamp — 11 Oct 2026 for this build, printed at the foot of every page — never against the day you happen to be reading. The roster itself grows once a week, on its own: a separate job walks GitHub for every repository that has crossed 10,000 stars, puts each one to the classifier, and adds it only when the answer is os_startup at 0.9 confidence or better. Everything under that bar is written to a review file and waits for a person — 183 repositories are waiting today. Nothing is ever removed automatically: a listing leaves only when a human opens a pull request, and a sponsorship has never added one.

When a fetch fails we keep the last good record and mark the repository unverified after 3 days rather than letting an old number pass as current. Star and fork counts on a detail page can be refreshed live from your own browser; the ship status stays pinned to the snapshot, because that is the number we can date.

Classification

What the classifier reads, and what it cannot.

Every repository in the directory has been read by Jev, the classifier built by TypeSafe, which answers six questions about it in a single request: what kind of project it is, which product category it belongs to, who it is built for, which proprietary product it is most often positioned against, whether it is designed to be self-hosted, and whether the company behind it sells a hosted version. It reads three fields and nothing else — the repository’s full name, its description and its homepage URL. It does not open the code, the README, the issue tracker or the website, so a project that describes itself badly is classified badly, and the fix is a better description rather than an appeal to us.

The weekly discovery job adds a repository to the roster only when the answer to the first question is os_startup at 0.9 confidence or better — the bar the classifier’s own documentation sets for acting on a consequential decision without a person. Anything under it goes to a review file and waits: 183 repositories are in that queue today, and they are counted here rather than listed, because an unreviewed machine doubt about a named project is not something to publish. The full probability distribution of every answer is stored, not just the verdict, which is why each project’s own page prints its numbers and why moving a threshold on this site is a rebuild rather than a re-run of the classifier.

The 598 repositories listed in the 2025 crawl were categorised by Gemini. In September 2026 every one of them was re-judged by Jev, and 148 of them scored under 0.5 on “is this the codebase of a company?”. They have not been removed. They are flagged for a human, the disagreement is printed on each of their own pages under “How it got here”, and a removal is still a pull request someone opens — deleting 148 listings because a second classifier disagreed with the first would be trusting the new model exactly as blindly as the old one.

728 repositories labelled · 126 added by the discovery job · 1647 judged in total, including the ones that were never added. See every arrival →