Skip to content
    ↑↓ select↵ openesc close
    English中文

    Data and ranking

    Rankings shape what developers pick, so the algorithm has to be inspectable. This page covers where the data comes from, how the score is computed, and which plugins get excluded.

    Where the data comes from

    Three sources, all crawled automatically. Nothing is entered by hand:

    • npm registry — every package carrying the opencode-plugin keyword, for its name, version, description, licence, deprecation status and repository URL.
    • GitHub GraphQL API — stars, forks, open issues, last commit date, archived status, topics and README, fetched in batches per repository.
    • npm downloads API — downloads over the last 7 and 30 days.

    Everything is re-crawled daily and the whole site is rebuilt. The current snapshot was generated on2026-08-20, covering 1553 plugins across14 categories.

    How the composite score works

    Ranking on stars alone has a structural problem: stars are cumulative, so they permanently favour whoever published first. A plugin released last week gaining 50 stars a day may not crack the top 100. So the composite score blends four signals:

    score = 0.35 × credited stars (log-normalised)
          + 0.35 × monthly downloads (log-normalised)
          + 0.20 × activity (decayed by last commit date)
          + 0.10 × growth (30-day star gain, normalised by size)
    
    archived repositories: final score × 0.35
    
    credited stars = min(repo stars, max(monthly downloads × 8, 1000))

    A few deliberate trade-offs:

    • Logarithmic, not linear. The real gap between 100k stars and 10k stars is far smaller than the numbers suggest; linear normalisation would let the head of the list flatten everything else.
    • Downloads weigh the same as stars. A star means "this looks good"; a download means "I actually run this". Downloads are harder to game but get inflated by transitive dependencies, so the two hold each other in check.
    • Growth is normalised by size. A 100-star project gaining 50 stars deserves more attention than a 5,000-star project gaining the same 50.
    • Archived is not deleted. An archived project can still be the best available option — it just has nobody maintaining it. So it is down-weighted rather than removed.

    Why stars get discounted

    Stars belong to a repository; downloads belong to a package.A plugin published from a large project's monorepo inherits that repository's entire star count.@mem0/opencode-plugin shows 63k stars not because the plugin is popular, but becausemem0ai/mem0 has 63k stars.

    Without a correction, the top of the board fills with packages doing a few dozen downloads a month — on our first full crawl, the number one package had 270k stars and 49 monthly downloads.

    So stars only count as far as the package's own install base can support. Plugins people actually use clear that ceiling easily; a package that merely sits next to a famous README does not. The floor of 1,000 keeps a newly published plugin with no downloads yet from being zeroed out.

    Around 18 packages currently trigger this correction. Their real star count is still shown, but marked with a *; hover it to see the number actually credited.

    Other known biases

    • Trending needs history. Growth is computed by diffing daily snapshots, so that board is nearly empty when the site is freshly deployed and only becomes meaningful after a few days.
    • Only npm-published plugins are indexed. Purely local plugins — scripts living in.opencode/plugins/ — cannot be discovered automatically.
    • Downloads are polluted by transitive dependencies. If a plugin is depended on by another popular package, its download count includes people who never chose it directly.

    How categories are assigned

    Rule matching over the package name, description, npm keywords and GitHub topics. The first matching category wins, so the category list is ordered by specificity. Automatic categorisation is wrong sometimes — a manual override layer fixes it, see the submit page.

    How health badges are decided

    BadgeTrigger
    Repository archivedThe GitHub repository is marked archived
    Deprecated on npmThe latest version carries a deprecated field
    No commits in over a yearLast commit > 365 days ago
    No commits in six monthsLast commit > 180 days ago
    No public repositorynpm metadata has no resolvable repository URL
    No documentationREADME missing or shorter than 200 characters
    No licence declaredNeither npm nor GitHub reports a licence
    Actively maintainedNone of the above triggered

    What gets excluded

    A package needs at least one of these to be listed: a description, a README, any stars, more than 50 monthly downloads, or a manual featured flag. That filters out a substantial number of empty packages and test publishes. There is also a manual blocklist for obvious placeholders and spam.

    About this site

    OpenDock is not affiliated with opencode. It is an independent community directory. All plugin data comes from public APIs, and the site itself is fully static.

    Analytics and privacy

    This site uses a self-hosted Umami instance (umami.qunqin.org) to count visits, and records anonymised session replays for 15% of sessions, so we can see which plugins people actually look for and where the site gets in the way. No advertising, no third-party trackers, and nothing is sold or shared.

    Those scripts do not load until you press "Allow". A prompt appears in the corner on your first visit; your choice is stored locally in your browser, and clearing site data lets you choose again. If you decline, no analytics script is loaded and no usage data leaves your browser.

    One thing declining does not stop: plugin author avatars are served from GitHub's own CDN (avatars.githubusercontent.com), so your browser requests them whenever a listing is on screen. That is inherent to showing the avatars at all, and GitHub sees those requests the same way it would if you visited the repository directly.