skops writes its version into a file it does not track
skops is a Python library helping you share your scikit-learn based models and put them in production
At a glance
- What is it?
- A small library with two modules: one to persist scikit-learn estimators without pickle, one to write the model card that explains them. Its packaging is more interesting than its README, which is mostly badges.
- Who is it for?
- Use skops when the artefact you are shipping is a scikit-learn estimator and the receiving team will not unpickle arbitrary objects from you, since that is the one problem it solves and solves well. Read the persistence guide before assuming coverage: it handles sklearn estimators and more, not every object, so check your pipeline contains custom classes it has seen.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 8, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The installed version is written to a file that git ignores
The package declares its version as dynamic and never writes it down. The manifest says the version comes from git tags: a tag on a commit makes that commit the release version, and later commits on the main branch become a development version with a numbered suffix. The generated version file is written when the package is built or installed, and the manifest states plainly that this file is not tracked in git. So the version you see on an installed copy is a build artefact, not a source file, and two checkouts of the same repository state can report different versions depending on what the tags say. The version scheme is named explicitly as the one that maps a release branch onto a PEP 440 compatible string, and the build hook that writes the file is declared in its own table.
python -m pip install skopsInstall from a released tag if you want the version in the package metadata to match the release you think you are using.
Three VCS tools in the build requirements, one only for a scheme
The build requirements look redundant until you read the comment on them. Three tools are declared: the main build backend, a version-control plugin for it, and a separate version control tool with a floor. The comment explains why the third one is pinned at that floor: version ten is the first release that knows the version scheme this project uses. So it is not there to compute the version, since the plugin does that, but because the scheme itself is implemented in that package and an older one would not understand it. The backend is the modern one rather than the classic setuptools path, and the licence file is declared through the backend's metadata table rather than through a classifier string. None of this is visible from the README, which is the practical argument for reading a manifest before adopting a serialization library.
Two modules with two different jobs
The library is two things, and the split is the reason it is worth having rather than a single function. One module handles persistence: it secures estimators and related objects without using pickle, so the file you hand to another team is not an instruction for their interpreter to execute. The other builds a model card, which is documentation: it explains what the model does and how it should be used. Those are separate concerns in practice. Persistence is a transport and format problem, decided once per release cycle. A model card is a per-model artefact, written for the humans who will rely on the prediction and for the reviewers who have to approve it. The documentation is split the same way, with one page for persistence and another for the card, which tells you they are meant to be learned separately as well as used separately.
Half the examples demonstrate persistence and half the card
The example set is small and named by task rather than by function, which makes the coverage obvious at a glance. Three of them use the standard scikit-learn example material: a California housing regression plot, a generic tabular regression plot and a text classification plot. Those are the persistence examples in effect, because the point is that a model trained on well-known data survives the round trip. The other two are card examples, and having two of them matters: one is a custom model card, built from scratch, and the other is the standard path. That pairing is the useful part. A tool that only generates a card automatically tells you nothing about what to do when the automatic route does not fit your model, which is exactly the case the custom example exists to cover. The examples directory also has its own readme separate from the project one.
The README is the PyPI long description and it is all badges
The readme in the manifest points at a reStructuredText file, and that file is also what PyPI renders on the project page. Which means every reference in it has to resolve on PyPI's own renderer rather than only in a git checkout. The file opens with a mode declaration, then five image substitution definitions for badges: documentation, a test workflow whose alternative text names Linux, macOS and Windows, coverage, the package index, and a lint badge whose image URL points at the linter's own project rather than a hosted service. Then a logo image, then the project name as a section heading underlined with equals signs. The prose that follows is four sentences describing the two modules, a note about the documentation, and a contribution pointer. Issues are collected on the tracker with a request to search first.
Six Python versions declared, and a redundant OS classifier set
The interpreter floor is 3.9, and the classifier list names every minor version from 3.9 upward through 3.14 and beyond. That combination is worth pausing on: a floor with no ceiling and classifiers for each minor means the project tests across the range it claims, and a classifier listing a version is a maintenance commitment rather than a guess. The operating system classifiers are more casual by comparison. Windows, POSIX, Unix and macOS are all listed, which is a set with real overlap since macOS is a Unix system and Unix is a POSIX system. Index pages match on any single classifier, so the practical effect is that the package is discoverable under each of those search terms. The status classifier is Beta, and the audience is declared twice, once for research and once for developers, which matches a library that is both a research tool and something you would wire into a service.
Two environment systems, plus an unexplained directory
The repository root shows a conventional Python project with a few unconventional touches. Conventional: a lint configuration through pre-commit, a coverage configuration, a readthedocs configuration, a manifest for source distribution inclusion, a security policy, and an archival metadata file for source archives. Unconventional: a Pixi environment directory alongside a lock file, meaning the development environment is managed by a second tool in addition to whatever the packaging metadata implies, and a scripts directory that the packaging metadata does not mention. The directory nobody can account for from the documentation is spaces/. Nothing in the readme, the manifest or the file listing explains what lives there, and it is not obviously generated. If you are contributing, that is the first thing to ask about, because a directory with no stated purpose in a library about safe persistence is worth understanding before you put anything in it.
Editorial conclusion
Use skops when the artefact you are shipping is a scikit-learn estimator and the receiving team will not unpickle arbitrary objects from you, since that is the one problem it solves and solves well. Read the persistence guide before assuming coverage: it handles sklearn estimators and more, not every object, so check your pipeline contains custom classes it has seen. Pin your install rather than tracking a branch, because the version is derived from git tags and a clone off main reports a development version.
Frequently asked questions
skops vs joblib
The README does not compare them. What it states is that skops.io persists sklearn estimators and more securely without using pickle. Joblib is not mentioned anywhere in the documentation provided.
skops vs onnx
The README does not make that comparison either. It describes skops as a Python library for sharing scikit-learn based models, with skops.io for persistence and skops.card for model cards. ONNX does not appear in the documentation.
What does skops do?
Two things. skops.io persists scikit-learn estimators and related objects securely without pickle, and skops.card builds a model card explaining what a model does and how it should be used.
How do I install skops?
One command: python -m pip install skops. The package requires Python 3.9 or newer and is classified as Beta.
Does skops replace pickle?
For sklearn estimators, yes, that is the stated purpose of skops.io: secure persistence without using pickle. The documentation scopes it to sklearn estimators and more, not to arbitrary Python objects.
How is the skops version number determined?
From git tags, using a version-control plugin at build time. A release tag makes that commit the release version and later commits on main become a development version. The generated file holding the number is not tracked in git.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/skops-dev-skops)