The Julia package ecosystem: a structural snapshot

Dependency structure, contributor data, and maintenance signals from the General registry, 21 July 2026

All figures are computed from a single dataset describing the General registry on 21 July 2026: every registered package, its dependency edges, its GitHub repository metadata, and its commit authors. Construction and known limitations are described in Methods & limitations.

Explore it yourself

The whole graph is queryable, live, in your browser — open the SPARQL explorer to ask your own questions of it at any point. The rest of this page walks through some of what it can show.

Registry totals

14,026
packages
11,576
contributors
69,406
dependency links
1,807
binary wrappers

_jll wrappers account for 13% of the registry (1,807 packages). Being BinaryBuilder-generated rather than hand-authored, they are excluded from the ranked analyses below, as are standard libraries — the registry represents standard libraries only partially (see Methods), so including them would be inconsistent. “Contributors” counts distinct GitHub accounts credited with at least one commit to at least one registered package. Exclusions are stated per figure.

Dependency load: direct and transitive dependents

For each package, the direct-dependent count is its in-degree in the dependency graph; the transitive-dependent count is the number of packages from which it is reachable. The table ranks by the latter, over registered packages excluding standard libraries and JLL wrappers (see note).

Registered packages (excluding standard libraries and JLL wrappers) ranked by transitive dependents.
# Package Direct Transitive
1 Preferences 220 10,804
2 JLLWrappers 1,735 9,412
3 PrecompileTools 661 7,818
4 OrderedCollections 426 6,674
5 Compat 270 6,491
6 MacroTools 391 6,022
7 DocStringExtensions 763 5,699
8 Reexport 1,169 5,641
9 InverseFunctions 38 5,479
10 ChainRulesCore 268 5,461
11 StaticArraysCore 65 5,358
12 DataAPI 71 5,278
13 DataStructures 678 5,090
14 IrrationalConstants 37 4,995
15 ChangesOfVariables 9 4,991

Direct and transitive counts differ by one to two orders of magnitude at the top of the distribution. The highest-ranked package, Preferences, has 220 direct dependents but is reachable from 10,804 packages (77% of the registry). The ranking is dominated by low-level infrastructure — array and iterator interfaces, compiler and macro utilities, serialization, and numerical primitives — rather than end-user libraries.

Source: registry dependency graph (latest registered version). Direct = number of packages declaring this one as a direct dependency; transitive = number of packages from which it is reachable, computed on the whole graph with strongly-connected-component condensation (cycle-safe). Standard libraries are excluded here because the registry represents them incompletely: only 35 of Julia’s 61 standard libraries are registered in General (e.g. TOML, Artifacts) and would otherwise rank near the top, while the rest (LinearAlgebra, Random, …) are not registry entries and are absent from the graph entirely. See Methods.

GitHub stars versus dependency PageRank

GitHub stars and dependency PageRank measure different things: stars are a user-facing popularity signal, PageRank is computed over the dependency graph and weights a package by the importance of the packages that depend on it. The scatter below plots the two on log axes.

The two quantities are weakly correlated. The points labeled in red are those with high PageRank but fewer than 400 stars — high dependency load paired with limited direct attention. These are typically low-level dependencies that are rarely installed directly and so accumulate few stars relative to their position in the graph.

Source: registry dependency graph (PageRank) × GitHub stars. Stars are a repository-level metric and accumulate over a package’s lifetime, so older packages are advantaged. PageRank is one of several centrality measures; the raw dependent counts in the table above are an alternative.

High transitive-to-direct dependent ratios

The ratio of transitive to direct dependents identifies packages with a small number of direct dependents but a large transitive footprint — utilities depended upon by a few foundational packages that are themselves widely depended upon. These do not appear in star or direct-dependent rankings. The table filters to packages with at least 1,000 transitive dependents and sorts by the ratio.

Packages with few direct but many transitive dependents, ranked by ratio. Restricted to ≥ 1,000 transitive dependents.
Package Direct Transitive Reach multiple
DataValueInterfaces 2 4,067 2,034×
PtrArrays 2 3,394 1,697×
HashArrayMappedTries 1 1,392 1,392×
IntegerMathUtils 1 1,041 1,041×
CommonWorldInvalidations 2 1,200 600×
Gamma 4 2,380 595×
StringManipulation 5 2,896 579×
Ratios 2 1,125 562×
AliasTables 6 3,352 559×
ChangesOfVariables 9 4,991 555×
TensorCore 3 1,577 526×
Reseau 3 1,572 524×

DataValueInterfaces is the extreme case: 2 direct dependents, 4,067 transitive. Such packages are not identifiable from stars or direct-dependent counts; the ratio requires the full transitive closure.

Source: registry dependency graph. “Reach multiple” is transitive ÷ direct dependents. The 1,000-transitive floor removes packages whose high ratio comes from a negligible footprint. JLL wrappers are excluded.

Contributor reach

Joining commit-author data across all repositories gives, per contributor, the number of distinct packages they have committed to. The distribution is long-tailed; the highest-reach accounts appear below.

Accounts by number of distinct non-wrapper packages committed to. Automated and AI-authored accounts are included (see note).
# Account Packages contributed to
1 ranocha 696
2 staticfloat 662
3 tkelman 630
4 ChrisRackauckas 594
5 timholy 572
6 devmotion 447
7 asinghvi17 410
8 KristofferC 397
9 DilumAluthge 391
10 abhro 358
11 blegat 340
12 claude 334
13 ViralBShah 332
14 ChrisRackauckas-Claude 327
15 oscardssmith 297
16 oxinabox 297
17 Keno 289
18 andreasnoack 287
19 giordano 279
20 christopher-dG 278

Reach measures the number of packages touched, not amount or significance of work. A single automated or one-line commit counts the same as sustained authorship, and the measure captures neither review, triage, documentation, nor design. High reach frequently reflects release-engineering and infrastructure roles (registry maintenance, the binary-build system, CI). A GitHub account is not necessarily one person (handle renames, shared or organizational accounts).

Source: contributor lists from each package’s GitHub repository, joined across the ecosystem. Automated and AI-authored accounts are shown as recorded — for example claude (Anthropic), which records commits authored by Claude Code. High-volume CI bots (JuliaTagBot, CompatHelper, dependabot, and similar) are filtered during data collection and are absent from the dataset entirely.

Inactivity among depended-upon packages

Cross-referencing repository activity against dependent counts identifies packages that are archived or long inactive while retaining many dependents. The aggregate below is over the 500 most depended-upon independent packages.

Of the 500 most depended-upon independent packages, 16 are archived or have no commit in the 4 years preceding the snapshot.

Inactive packages (archived, or no commit in four years) among the 500 most depended-upon, ordered by dependent count.
Package Dependents Last commit
LightGraphs 69 archived
Lazy 51 2021-06-01
MCMCChains 42 archived
BinDeps 41 archived
Formatting 39 archived
IfElse 38 archived
TableTraits 35 2021-05-06
IteratorInterfaceExtensions 35 2020-08-22
FastClosures 30 2020-11-05
DataValues 28 2020-08-22
StructEquality 27 2022-07-18
BinaryProvider 22 archived
MathProgBase 21 2020-02-15
IterableTables 19 2020-08-22
URIParser 18 2021-03-11
SparseDiffTools 17 archived

Source: GitHub push timestamps and archive flags × registry dependents. The push timestamp is repository-level, so a subpackage in an active monorepo may appear inactive or vice versa. Dependency edges are the latest registered version only.

The dependency-graph k-core

The k-core is the maximal subgraph in which every vertex has degree ≥ k, on the undirected dependency graph with JLL wrappers and standard libraries removed. k is set automatically to the smallest value whose k-core has at most a few hundred nodes, so the layout stays legible; the resulting k and node count are shown below the figure. Node size and color both encode PageRank. Hover for a name; click a node to highlight its neighborhood — the packages it connects to directly — and see its record below.

Source: registry dependency graph, restricted to its k-core. Node color and size encode PageRank. Label propagation on this subgraph does not resolve distinct communities: the core is densely interconnected rather than partitioned into separable clusters.

Package explorer

Per-package record for any of the 14,026 packages: dependencies, dependents, contributors, and dependency-tree authors — the number of distinct commit-author accounts across the package together with its full transitive dependency tree (that is, every account whose code is pulled in when the package is installed).

Source: registry + GitHub, combined. “Monthly requests” is package-server request volume (juliapkgstats.com) and includes CI traffic — read it as install demand, not distinct users. “Dependency-tree authors” counts distinct commit-author accounts across the package and its transitive dependency closure; high-volume CI bots are filtered during collection.

Methods & limitations

The dataset is produced by a single reproducible pipeline and is contained in one file. The following affect interpretation of the figures above:

  • All figures reflect a single crawl on 21 July 2026.
  • Repository-level vs package-level. Stars, forks, issue counts, commit counts, and contributor lists describe repositories. Packages sharing a monorepo share these numbers; a subpackage can look more active or popular than its own code is.
  • “Requests” are not downloads or users. Package-server request counts include continuous-integration traffic and mirror activity.
  • Commits are a weak proxy for contribution. They omit review, triage, documentation, and design, and vary with squash-vs-merge habits. Named contributor rankings reflect commit reach, nothing finer.
  • Identity is a GitHub account. Handle renames, shared/organizational accounts, and multiple accounts blur person-level counts. Bots are filtered by a best-effort list plus automated/AI accounts; some will slip through.
  • Dependency edges are latest-version hard dependencies between packages registered in General. Weak/extension dependencies and historical dependency changes are not modeled. Standard-library coverage is partial: 35 of Julia’s 61 standard libraries are separately registered in General — the independently-versioned ones (Statistics, TOML, Artifacts, the *_jll binaries, …) — and so are graph nodes; the remaining 26 (LinearAlgebra, Random, Printf, Dates, …) are not registry entries, so neither they nor dependencies on them appear. Because this coverage is partial, standard libraries are excluded from the ranked figures; counts for other packages are unaffected, since standard libraries are dependency sinks.
  • Coverage gaps. Licenses were detected for ~66% of packages (GitHub reports none for the rest); GitHub metadata is missing for the few packages not hosted there.

The underlying dataset is a knowledge graph of 864,488 triples. A triple is the smallest unit of the graph: a single fact written as subject – predicate – object, such as DataFrames → depends on → Tables or Flux → has contributor → CarloLucibello. Dependency edges, contributor links, star counts, licenses, download figures, and every other attribute used above are each stored as one or more triples. Together they describe 14,026 packages as a single queryable graph, and every figure on this page is computed from it directly.

This subject–predicate–object model is RDF (the Resource Description Framework), a long-standing W3C standard for representing data as a graph. Its defining feature here is that each package, person, and license is named by a URL rather than an internal identifier — the package nodes are JuliaHub pages, the people are GitHub profiles, the licenses are SPDX entries. Records that share an identifier can therefore be joined across independently produced datasets without a prearranged schema, which is the property usually meant by “linked data.” The full dataset is a single file and can be queried or combined with other sources directly.

Now go ask your own questions. The whole graph is in the SPARQL explorer — pick an example query or write your own.