The open Axiom Cloud Hub catalog

Every recipe. No slots, no keys, no limits.

The hub is public and free for every developer. Sign in exists to keep bots off the API — not to unlock anything.

Apache-2.0 CLIBSL 1.1 hubkeeps your formatting
$ pymolt codemods . --package pandas
8
Tier-2 behavioral
hand-written templates
26
curated jumps
in this catalog
PyPI
Tier-1 mechanical
generated on demand
Tier 1

Mechanical

Something was renamed or moved. Read straight out of the release notes for that version jump, and available for anything on PyPI.

- from flask import escape
+ from markupsafe import escape
Tier 2

Behavioral

The call still exists, but it means something different now. Hand-written per library, then re-checked against your own code before a line moves.

- df.sum()
+ df.sum(numeric_only=True)
the default flipped in pandas 2 — the old call silently returns different numbers
Supported libraries

What the hub already knows.

patch versions never matter

Data & scientific

Where a silent default flip corrupts numbers instead of raising.
pandasTier 2
1.x 2.x

Copy-on-Write, numeric_only flip, pd.NA nullable dtypes, inplace chains

numpyTier 2
1.2x 2.x

Removed scalar aliases, promotion rules (NEP 50), copy= semantics

scipyTier 1
1.9 1.14

Relocated submodules and removed legacy solver kwargs

scikit-learnTier 1
1.0 1.5

Estimator kwarg renames, deprecated attribute accessors

polarsTier 1
0.20 1.x

Expression API renames and strictness changes

duckdbTier 1
0.10 1.x

Relation API and result-fetch surface

plotlyTier 1
5.x 6.x

Figure factory removals, template renames

daskTier 1
2023.x 2025.x

Query planner defaults and collection API

Web & API frameworks

Framework majors that move code between packages, not just names.
DjangoTier 2
3.2 5.x

URL/middleware surface, async views, removed model & form APIs

FlaskTier 2
2.0 3.0

Dropped before_first_request, JSON provider, app-context rules

FastAPITier 2
0.9x 0.11x

Pydantic v2 beneath the framework — response & validation edges

aiohttpTier 1
3.8 3.11

Session lifecycle and timeout kwargs

gunicornTier 1
20.x 23.x

Worker config keys and header handling

SeleniumTier 1
3.x 4.x

find_element_by_* removals, options objects

Typing, ORM & validation

The jumps that rewrite how objects are constructed and validated.
PydanticTier 2
v1 v2

validator → field_validator, Config → model_config, .dict() → .model_dump()

SQLAlchemyTier 2
1.4 2.0

2.0 select() style, Session.execute, typed DeclarativeBase

PyMongoTier 1
3.x 4.x

Removed collection helpers and cursor kwargs

redis-pyTier 1
4.x 5.x

Connection pool and async client surface

psycopgTier 1
2 3

Cursor/row-factory API and connection context rules

elasticsearch-pyTier 1
7.x 8.x

Positional-arg removal across the client

Orchestration & platform

Migrations that are really re-architectures — mapped before they're attempted.
AirflowTier 2
2.x 3.0

Provider splits, logical_date rename, no direct metadata-DB access

CeleryTier 1
4.x 5.x

Config key lowercasing and CLI entry points

kafka-pythonTier 1
2.0 2.2

Consumer/producer kwarg drift

PySparkTier 1
3.3 4.x

Removed RDD helpers, Arrow defaults

pytestTier 1
7.x 8.x

Fixture and hook signature changes

OpenCVTier 1
4.5 4.10

Renamed constants and removed C-API shims

What actually moves

Six upgrades, and what changes underneath them.

Not a case study — these are documented changes in these libraries, and you can check every one against their release notes. Pick one to see the molt, the shed skin: the old behavior on the left, what it grew into on the right. The code barely changes. What it does underneath is another matter.

6upgrades3change behavior1are only renames
behavioralneeds caresafe
pandas 1.5.32.2.0
change class: Behavioral
BEHAVIOR_CHANGED
old skin / v1 behavior
totals = df.sum() # silently drops
# non-numeric cols
df["net"].fillna(0, inplace=True)
new skin / v2 behavior
totals = df.sum(numeric_only=True)
# ^ now explicit — otherwise raises
df["net"] = df["net"].fillna(0) # CoW

What actually changes

  • Copy-on-Write: chained inplace assignment stops mutating the original frame
  • numeric_only default flipped to False — reductions that dropped columns now raise
  • pd.NA / nullable dtypes: use pd.isna(), not `is None`

How PyMolt surfaces it — contract traces the boundary under 1.5 and 2.2, then diffs — result_changed flags exactly these.

Your stack isn't listed? It still gets migrated.

Nothing here is a whitelist. The catalog is just the work already done.

Right now, no waiting

Any package on PyPI

Ask for a version pair and the hub reads that release diff on the spot — renames, moved imports, dropped arguments. It does not have to be in the catalog.

On request

Anything that turns out to be behavioral

If the jump changes what code means rather than what it's called, that needs rules written by hand. Tell us which one and it gets built, then added to the catalog for everyone.

Mechanical recipes are instant. Hand-written rules take as long as they take — we'll tell you which.

Request a library
Before you ask security

Your code never goes anywhere.

A recipe request is a package name and two version strings. That is the entire payload — no source, no file names, no lockfile, no telemetry. Rules come back, get re-run against your own code, and only the ones that hold are applied. The round trip, drawn out

the entire request
{
  "package": "pandas",
  "from": "1.5.3",
  "to":   "2.2.0"
}
Three ways to reach the catalog

Cloud, on-prem, or nothing at all.

Axiom Cloud Hub

The default. Public, free, rate-limited by token rather than by wallet.

pymolt auth login

Your own endpoint

Point the CLI at an internal recipe server. Nothing leaves the network.

export PYMOLT_ENDPOINT=…

Offline cache

Recipes replay from .pymolt_cache. An air-gapped machine still migrates.

pymolt codemods . --offline