Skip to main content

acronymkit

CI Python License: MIT Typed OpenSSF Scorecard

Bi-directional, multi-tiered acronym processing for production systems. Generate acronyms from text, synthesise backronyms, extract abbreviations already defined in a document, and resolve ambiguous ones from context — from one typed library with a Tier 0 path that needs nothing but the standard library.

from acronymkit import AcronymEngine

engine = AcronymEngine()
engine.generate("Application Programming Interface").primary_acronym   # 'API'
engine.generate("Portable Document Format").primary_acronym            # 'PDF'

Generation is measured, and nothing else measures it. Fed the 1,221 human-authored short-form/long-form pairs of the MED1250 gold standard backwards, acronymkit returns the abbreviation the human actually chose at rank 1 for 75.5 % of the 546 pairs an initialism generator can address, and within the top 25 for 89.7 %. No competing library has a number here, because no competing library generates.

Extraction is measured too, against four other systems through one harness: precision 92.07 %, recall 76.99 %, F1 83.85 %. We are third of five there, and the table showing exactly that is in docs/EVALUATION.md — including where we lose.

Why

The open-source acronym ecosystem is split in two, with nothing in between:

What it does well Where it stops
Naive string utilities — acronymcreator, countless gists Fast, no dependencies No tokenisation grammar, no phonetics, no semantics
Corpus matchers — ACRONYM (Cook, 2019) Finds candidates that spell real words Offline batch, static corpus, no library bindings
Rule-based extractors — Schwartz & Hearst (2003) in scispaCy, Blackstone F₁ > 96 % on inline definitions, cheap Strictly extractive; the definition must be present
Neural disambiguators — AcroBERT, SDU/SciAD/GLADIS Resolves standalone acronyms from context GPU-bound, slow cold start, research codebases

A system that needs to generate, extract and resolve has to stitch three incompatible codebases together. acronymkit is the missing single library.

Install

pip install acronymkit

The base install is the complete Tier 0 engine — extraction, generation, backronyms, scoring, CLI-free API — with pydantic as the only runtime dependency. Optional extras add higher tiers:

pip install "acronymkit[cli]"          # click-powered command line
pip install "acronymkit[nlp]"          # Tier 1: spaCy / NLTK part-of-speech evidence
pip install "acronymkit[all]"          # everything

CI enforces the split: a dedicated job installs the base package alone and asserts that no optional dependency reaches sys.modules after a full generate + extract + backronym + disambiguate cycle.

What it does

Forward generation

from acronymkit import AcronymEngine, Config
from acronymkit.enums import EngineTier, ScoringStrategy

engine = AcronymEngine(Config(
    engine_tier=EngineTier.HYBRID_NLP,
    scoring_strategy=ScoringStrategy.STRICT_INITIALISM,
    include_articles=False,
    min_word_length=2,
    max_acronym_length=6,
))

result = engine.generate("Application Programming Interface")
result.primary_acronym                    # 'API'
result.score                              # 21.297
result.primary.breakdown.explain()
# 'S = 1*30.000 + 0.25*-2.811 + 2*0.000 - 25*0.000 = 21.297'

[(c.acronym, round(c.score, 2)) for c in result.alternatives[:4]]
# [('API', 21.3), ('APIN', 15.42), ('APRI', 15.38), ('APPI', 15.29)]

Every candidate carries a per-character alignment trace and a term-by-term score decomposition, so a ranking decision is always explainable.

Backronym synthesis

Align a phrase onto a target word:

result = engine.generate_backronym(
    phrase="Network Exchange Unified Security",
    target_word="NEXUS",
)
result.primary_expansion            # 'Network Exchange Unified Security'
result.candidates[0].coverage       # 1.0
[m.kind.value for m in result.candidates[0].mappings]
# ['initial', 'initial', 'contiguous', 'initial', 'initial']

Note the contiguous mapping: E and X both come from "Exchange". Sub-word matches are first-class, exactly as in the ACRONYM formulation.

Or expand a word with no source phrase at all:

engine.synthesize_backronym("NEXUS").candidates[0].expansion_text
# 'nag ear xenon urn sad'

Extraction (Schwartz & Hearst)

engine.extract_definitions(
    "The National Aeronautics and Space Administration (NASA) launched the mission."
)
# [AcronymPair(short_form='NASA', long_form='National Aeronautics and Space Administration')]

Both arrangements are supported — Long Form (Short Form) and the inverted Short Form (Long Form) — with exact source spans (text[pair.short_form_span[0]:...] == short_form always holds) and a confidence estimate. Prose parentheticals such as (see Figure 3) and enumerations such as (1) … (2) … are correctly rejected.

Measured, not asserted. On the MED1250 gold standard (1,221 human-annotated pairs from the Ab3P corpus): precision 92.07 %, recall 76.99 %, F1 83.85 %, at 4,219 documents/second. High precision with recall the weak side is the expected shape for this algorithm — it refuses rather than guesses. The full breakdown, including where the misses come from and one optimisation that was tried and reverted, is in docs/EVALUATION.md. Reproduce with:

python tools/fetch_data.py med1250 && python bench/run_extraction.py

Contextual disambiguation

from acronymkit.disambiguation import ExpansionDictionary

vocab = ExpansionDictionary({"MS": [
    "multiple sclerosis", "Microsoft", "mass spectrometry", "manuscript",
]})

engine.disambiguate("MS", "The patient was diagnosed with MS after an MRI showed brain lesions.",
                    dictionary=vocab).primary_expansion   # 'multiple sclerosis'
engine.disambiguate("MS", "The MS Office suite shipped a new version of Word and Excel.",
                    dictionary=vocab).primary_expansion   # 'Microsoft'
engine.disambiguate("MS", "Peak intensity in the MS spectrum identified the ionised compound.",
                    dictionary=vocab).primary_expansion   # 'mass spectrometry'

With no dictionary supplied, the engine builds one from the document's own inline definitions, so a term defined once on first use resolves everywhere afterwards.

Governed naming — expansion with no sentence to lean on

A schema-governance pipeline needs the opposite and simpler thing. Given a bare column token and a governed vocabulary, return the long form — deterministically, with no prose to disambiguate against, and with a record of which catalog entry produced each word.

from acronymkit.governed import GovernedNamer, load_bundle

# A real standard is a directory of files, and one line reads it:
#     nds = GovernedNamer.from_bundle("nds_standard/")
#     nds = GovernedNamer(load_bundle("nds_standard/"), policy)   # the same, unbundled
# Inline below, so this block runs with nothing on disk.
nds = GovernedNamer.from_mapping(
    {"TXN": "Transaction", "APPLNT": "Applicant", "ID": "Identifier",
     "NBR": "Number", "NUM": "Number", "DT": "Date"},
    approved_abbreviations=["TXN", "APPLNT", "ID", "NBR", "DT"],
    class_words={"ID": "Identifier", "DT": "Date"},
)

nds.expand_identifier("TXN_APPLNT_ID").phrase        # 'Transaction Applicant Identifier'
nds.expand_identifier("TXN_KYC_ID").is_fully_known   # False — the catalog has no KYC
nds.normalize("txnApplntNum")                        # 'TXN_APPLNT_NBR'

GovernedNamer binds one vocabulary and one policy and then takes the subject as its only argument; expand_many and check_many take a whole corpus. A naming standard on disk is a catalog, three allow-lists, a class-word map, a pin sheet and a term glossary, which is what from_bundle and load_bundle read; from_csv and from_json read the narrower shapes.

Nothing is dropped in silence. A character the splitter cannot account for is reported rather than discarded, and is_fully_known is true only when every token resolved and nothing went unaccounted for:

nds.expand_identifier("TXN_©_ID").phrase           # 'Transaction Identifier'
nds.expand_identifier("TXN_©_ID").unaccounted      # ('©',)
nds.expand_identifier("TXN_©_ID").is_fully_known   # False

Your acronyms win. with_custom layers an overlay above the catalog and reports it as such:

result = nds.with_custom({"KYC": "Know Your Customer"}).expand_token("KYC")
result.long, result.source.value      # ('Know Your Customer', 'custom')

Three directions over one vocabulary — expand_identifier reads a physical name, to_physical_name renders a logical one, is_compliant checks a name somebody else wrote — so a catalog change moves all three at once. Every answer carries the rule that produced it, the catalog row behind it and the candidates it beat.

This is not disambiguation, and that is the design. A column name is not a sentence: there is no context to weigh, so the answer comes from the catalog or it does not come at all. An unknown token is reported as unknown, with zero confidence, never approximated — because an unknown reported as unknown is recoverable and an unknown quietly guessed is not. Governed mode is exact by construction, which is a tautology rather than a measurement, and no accuracy figure is attached to it anywhere in this project. docs/GOVERNED_NAMING.md has the precedence chain, every verb with runnable output, the four invariants and an honest limits section.

Multilingual — English complete, others experimental

Categorised stop-word taxonomies ship for English, French, Spanish and German, and generation works for all four:

from acronymkit.enums import Language
AcronymEngine(Config(language=Language.FR)).generate("Système de Gestion de Base de Données")  # SGBD
AcronymEngine(Config(language=Language.DE)).generate("Allgemeine Deutsche Automobil Club")     # ADAC

But only English ships a lexicon and a character model. For fr/es/de, Λ(A) is identically zero (no candidate is ever reported as a dictionary word) and Φ(A) is uniform (pronounceability stops discriminating). Positional fidelity carries generation on its own, which is why the examples above are still correct — but treat those languages as experimental.

This is deliberate. The v0.1.0 word lists for those languages were model-authored, which made every dictionary claim about them unverifiable, and unlike English there is no permissively licensed replacement to swap in: the available Hunspell dictionaries are copyleft, and German's only permissive arm grants distribution solely alongside ODF applications. Given the choice between invented data and no data, no data is correct — invented data produces confident wrong answers a caller cannot detect.

The engine says so rather than degrading silently:

result = AcronymEngine(Config(language=Language.FR)).generate("Système de Gestion de Base de Données")
result.metadata.warnings
# ["no bundled lexicon for language 'fr': Lambda(A) is always 0, ...",
#  "no bundled n-gram model for language 'fr': Phi(A) is uniform, ..."]

To get real coverage, install a dictionary yourself — it stays on your machine, so its licence is your call, not ours:

python tools/fetch_data.py hunspell-fr
python tools/build_lexicons.py --language fr --output ~/fr.txt
Config(language=Language.FR, lexicon_path=Path("~/fr.txt").expanduser())

Execution tiers

Tier EngineTier Dependencies Latency Use for
0 ZERO_DEPENDENCY stdlib + Pydantic 98 µs/call, 2.3 ms to import Edge, high-throughput indexing, hot paths
1 STATISTICAL_NLP spaCy or NLTK single-digit ms POS-aware generation on messy human text
1 HYBRID_NLP optional either Production default — degrades gracefully
2 NEURAL ONNX Runtime — Phase 3, not in this release
— AUTO — — Best tier available at import time

Degradation is never silent in the payload: the effective tier lands in metadata.engine_tier, the requested one in metadata.requested_tier, and the reason in metadata.warnings. Set Config(strict=True) to turn degradation into a TierUnavailableError instead.

The scoring function

Candidates are ranked by a configurable composite objective:

$$S(A, T) = \alpha \sum_{i} \omega(c_i, w_{j(i)}) ;+; \beta , \Phi(A) ;+; \gamma , \Lambda(A) ;-; \delta , \Psi(T, A)$$

Term Meaning
ω(cᵢ, w) Positional mapping weight — 10 when cᵢ is the initial character of w, 3 when internal or terminal, 2 when it directly follows a previously matched character of the same token
Φ(A) Phonotactic pronounceability — mean character-bigram log-likelihood, (1/(k−1))·Σ log P(c_{m+1} | c_m)
Λ(A) Lexical match — 1 when A is a real word in the target lexicon (a successful backronym), else 0
Ψ(T, A) Information loss — count of semantically critical tokens the acronym drops

Φ behaves the way you would hope: Φ("SCALE") = −2.29, Φ("PDF") = −6.22, Φ("XKCD") = −7.46.

The syllable heuristic underpinning it is measured, not asserted: against the 117,485 CMUdict entries it scores 84.1 % exact and 99.5 % within one syllable (mean absolute error 0.16). Reproduce with python tools/build_lexicons.py --validate-syllables.

Presets

ScoringStrategy selects a calibrated (α, β, γ, δ) vector:

Strategy Behaviour
STRICT_INITIALISM Default. Positional fidelity dominates; reproduces the textbook initialism
BALANCED_PRONOUNCEABLE A real trade: pronounceability and dictionary hits can outrank the literal initialism
MAX_PRONOUNCEABLE Phonotactics dominate — for product and project naming
DICTIONARY_BACKRONYM A real word outweighs almost everything else
CUSTOM You supply ScoringWeights
# "Structured Query Language Transaction Protocol"
STRICT_INITIALISM   -> 'SQLTP'   pronounceability 0.11
MAX_PRONOUNCEABLE   -> 'SQULTP'  pronounceability 0.65

# "Network Exchange Unified Security"
DICTIONARY_BACKRONYM -> 'NEXUS'  (dictionary word, score 92.95)

The defaults are calibrated rather than guessed, by a committed script (tools/tune_presets.py) so the claim is falsifiable. STRICT_INITIALISM reproduces all sixteen entries of a canonical corpus of textbook initialisms (API, PDF, NASA, HTML, RAM, CPU, GPU, SCUBA, LASER, SQL, CRM, QA, TCP, SOAP, BIOS, ROM), and keeps doing so when β, γ or δ are perturbed by 50–100 % — a genuine plateau rather than a fitted point. tests/test_scoring_presets.py pins the corpus so retuning cannot silently regress it.

BALANCED_PRONOUNCEABLE deliberately does not reproduce that corpus, and it is worth knowing why. Against the real 76,879-word lexicon there is provably no coefficient vector that both weights dictionary hits meaningfully and returns every textbook initialism: suppressing a vowel insertion needs a length penalty above ~14, which then over-penalises the short acronyms instead. So the preset honours its name — it returns QUA for "Quality Assurance", because "qua" is a word. See docs/DECISIONS.md.

One deliberate deviation from the published formulation. The positional term is a sum, so it grows monotonically with length — used unmodified as a generation objective it prefers PODOFO to PDF. ScoringWeights.length_penalty (default 8.0) closes that gap, sitting between contiguous_weight (2) and initial_weight (10) so that covering a new token nets +2 while taking a second letter from a token already used nets −6. Set length_penalty=0.0 to recover the unmodified objective exactly.

Command line

pip install "acronymkit[cli]"
acronymkit generate "Self Contained Underwater Breathing Apparatus" --top 3
Phrase:  Self Contained Underwater Breathing Apparatus
Primary: SCUBA  (score 27.264)

RANK  ACRONYM   SCORE  PRONOUNCE  DICT
----  -------  ------  ---------  ----
   1  SCUBA    27.264       0.75  yes
   2  SCOUBA   19.352       0.77  no
   3  SCUBRA   19.284       0.75  no

Score breakdown for SCUBA:
  TERM               VALUE  COEFF  CONTRIBUTION
  ----------------  ------  -----  ------------
  positional        50.000      1        50.000
  phonotactic       -2.943   0.25        -0.736
  lexical            1.000      2         2.000
  information_loss   0.000     25        -0.000
  total                                  27.264

Also available: backronym, synthesize, extract, score, tokens, schema, version. Every command takes --format json for the schema-conformant payload, and extract reads stdin.

Governed naming from the command line

Seven more commands read a governed vocabulary. expand-token, expand-identifier, physical-name, check-name and normalize-name answer one subject each — check-name exits 1 when the name does not conform, so it works as a gate. Two answer a whole schema in one process:

acronymkit governed-batch --dictionary std/ --op expand < columns.txt > answers.jsonl
acronymkit governed-audit --dictionary std/ --suggest   < columns.txt

governed-batch streams: one record per line in, one JSON object per line out, nothing accumulates, so a fifty-thousand-column schema costs the same memory as a hundred-column one and the reader sees the first answer before the last question is asked. --op selects expand, physical, check, normalize or audit; every record carries line, input and any id it arrived with. An error rides on its own record and never aborts the run, the process exits 1 if any record failed, and the one-line summary goes to stderr so every line of stdout is a record. This is the command that makes the library usable from another language: answering one name takes microseconds and starting a Python interpreter takes tens of milliseconds, so a pipeline that shells out per column pays almost all of its cost outside the work.

governed-audit reduces the same corpus to one report — coverage, round-trip breaks, compliance findings by reason code, and the unknown-token backlog ranked by how often each token appears and in how many of them. --suggest proposes catalog rows to write, --limit controls truncation, --details keeps one record per name in the JSON.

--dictionary takes a bundle directory, a JSON catalog or a CSV on all seven, with --dictionary-format, --columns and --delimiter saying how to read it — and it refuses to guess which way round a two-column CSV is meant to be read, because both readings are valid vocabularies that mean different things. Every command here except governed-batch also takes --format json.

docs/QUICKSTART_GOVERNED.md runs all of it end to end, from a spreadsheet export to a diff against whatever you use today. Driving governed-batch from another runtime is docs/JAVA_INTEROP.md, with a runnable Maven project in examples/java/.

Batch and async

batch = engine.batch_generate(phrases, max_workers=8)
batch.succeeded          # results in submission order
batch.errors             # {index: message} — one failure never aborts the batch

results = await engine.abatch_generate(phrases, concurrency=16)

A single AcronymEngine is immutable and safe to share across threads and event loops.

Interoperability

Results serialise to a versioned JSON Schema, schemas/acronym-engine-result.schema.json, shared with the planned acronym4j Java port:

from acronymkit.serialization import validate_result
validate_result(result.to_dict())      # raises if the payload drifts from the contract

Data provenance

The bundled English lexicon is derived from SCOWL (size cut ≤ 60, 76,879 entries) and the syllable validation from CMUdict. Both are permissively licensed and redistributed with their notices in the resource headers. Every asset is pinned to a commit or release tarball and verified by SHA-256, because a silent upstream edit to a word list changes Λ(A), which changes every score.

data/LICENSES.md is the ledger: source, licence, checksum, and — for anything not redistributable — the reasoning for why not. tools/build_lexicons.py refuses to write a non-redistributable asset into the package, so the rule is enforced by code rather than by diligence.

python tools/fetch_data.py --list        # the registry
python tools/fetch_data.py --verify      # re-check every checksum

Honest scope

  • Extraction is evaluated on two corpora, both biomedical. MED1250 is biomedical abstracts and is a tuning set — its miss taxonomy has been read in full. PLOD was added to close the domain-generalisation gap and turned out not to: it is PLOS journal text, also dominated by the life sciences. No evidence exists for legal, financial or general-web text. Treat the comparison as sound and the absolute level as provisional.
  • System rankings are corpus-dependent, and we have measured that. pyab3p beats us on MED1250; we beat it on PLOD's span-detection task. Any single-corpus ranking, including ours, should be read with that in mind.
  • 14.01 % of that corpus is found by no system at all, ours or anyone's. The practical ceiling is 85.99 %, not 100 %, and every figure here should be read against it.
  • English only. French, Spanish and German ship no lexicon; those languages degrade honestly and say so in metadata.warnings.
  • Disambiguation is measured and it loses. On SDU@AAAI-21 it scores 41.65 % accuracy against 72.84 % for simply always picking the most common expansion. It beats random, so the context signal is real, but on that benchmark it is worth less than memorising frequencies. Use it for document-local resolution, where inline definitions carry it; do not expect it to win a disambiguation benchmark.
  • Every number in this README is generated from bench/results.json, and CI fails the build if a performance claim anywhere in the docs or the source cannot be traced back to a benchmark run.

Documentation

  • Architecture — subsystem map, tier policy, resource formats, extension points
  • Governed naming — deterministic short→long expansion against a schema catalog: the custom-first precedence chain, every verb with real output, the four invariants, and why refusing to guess is the right design for governed data
  • Governed naming in five minutes — the same subsystem from the command line, from a spreadsheet export to a whole schema in one process, ending in a diff against the implementation you have now
  • Technical note: the governed JSON wire contract — the exact JSON shape of every DTO and fixture, written so a port can be validated against the same golden files. No JVM artifact exists; this is what would make writing one mechanical
  • Calling this library from the JVM — which route a Java Maven project should take and what each one needs on the machine: the governed-batch co-process, GraalPy as a Maven dependency, Py4J, JPype and a hand-written port, with the measurements behind the recommendation
  • examples/java/ — a runnable Maven project for the recommended route: a co-process client, the wire format by hand, and the real output. No CI job builds it
  • Contributing — the invariants that are easy to break by accident
  • Technical note: using a ranking function as a generation objective
  • Evaluation — measured extraction accuracy against a gold standard
  • Decisions — what was tried and rejected, and why
  • Enterprise review — the short answer for someone deciding whether to allow this package: air-gapped install, security posture with each claim's proof named, and the exact error text when something is missing
  • Support matrix — capability by tier by "works offline" by "what it needs", including what English ships that fr/es/de do not
  • Offline and air-gap review — the long form: how the no-network claim was measured, what the measurements cannot see, and how to reproduce them
  • Installing without PyPI — release-asset wheel, git tag, source checkout, or a per-platform offline bundle that installs with --no-index and needs no package index at all
  • Security policy — threat model and disclosure
  • Changelog

Extending

You want to… Do this
Use a bigger dictionary Config(lexicon_path=Path("/usr/share/dict/words"))
Score against a domain corpus CharNGramModel.train(my_words) → JSON → Config(ngram_model_path=…)
Add a language Add stopwords_<lang>.json + lexicon_<lang>.txt, generate ngram_<lang>.json, add a Language member
Change ranking Config(scoring_strategy=ScoringStrategy.CUSTOM, scoring_weights=ScoringWeights(...))
Suppress domain noise Config(custom_stop_words=frozenset({"solution", "platform"}))
Plug in your own tagger Implement the NlpBackend protocol

Roadmap

  • Phase 1 — Tier 0 engine and extractive foundation. ✅ Shipped in 0.1.0
  • Phase 2 — Statistical NLP and phonetic scoring. ✅ Shipped in 0.1.0
  • Phase 3 — Tier 2 neural disambiguation. Quantised sentence encoder via ONNX Runtime (no PyTorch runtime dependency), indexed against SciAD/GLADIS-scale expansion dictionaries. LexicalDisambiguator already implements the contract the neural backend will satisfy, and EngineTier.NEURAL is accepted today, so selecting it is forward-compatible.
  • Phase 4 — acronym4j on Maven Central. API parity, byte-identical JSON, same schema.

Licence

MIT

Metadata

Release files for acronymkit 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for acronymkit 0.3.0
File Size Uploaded
acronymkit-0.3.0.tar.gz 1.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for acronymkit 0.3.0
File Interpreter ABI Platform
acronymkit-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.7 MB

Release files / acronymkit-0.3.0.tar.gz

Download URL acronymkit-0.3.0.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
7a909c7af7f1c8a2e3b2f1cdcc9d7ae09d67a60c7ad5f436dff7711f901f4fe7
BLAKE2b-256 checksum
How to use checksums
ee8ca2848d5f5ca28a21c169b2bc7a8e9ff5a294df7615e57f30bc26a930ecc4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.

Transparency log

Release files / acronymkit-0.3.0-py3-none-any.whl

Download URL acronymkit-0.3.0-py3-none-any.whl
Size 564.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fade7bfbe2e001c49a5172b8c4a5b02c3f4d2db38b7279adff38dfdfa4d81e0c
BLAKE2b-256 checksum
How to use checksums
5558ae64ce2b4fcc57a1ae86b641d8942019b108e10959196345ea50b12469e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page