poetry2nix reads your lock file so you do not have to write Nix expressions
Convert poetry projects to nix automagically [maintainer=]
At a glance
- What is it?
- poetry2nix converts a Poetry project into a Nix derivation by parsing pyproject.toml and poetry.lock, exposing a small API of mkPoetryApplication and related attributes. Its own README marks it unmaintained and points new users at uv and uv2nix instead.
- Who is it for?
- Adopt poetry2nix if you already have a Poetry project with a committed poetry.lock and need a reproducible Nix build today without hand writing Nix expressions for every dependency. Do not start a new project on it, because the README states the creator and long-term maintainer is no longer using Poetry or poetry2nix, the project is looking for maintainers, and support for PEP 621 metadata and Poetry 2.0 is unlikely to arrive.
- 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 received new commits within the last day.
- What is it written in?
- Mainly Nix, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The README opens with a maintenance warning, not a feature list
poetry2nix turns Poetry projects into Nix derivations without the need to actually write Nix expressions. It does so by parsing pyproject.toml and poetry.lock and converting them to Nix derivations on the fly.
That is the whole premise, and it is a good one. Packaging a Python project for Nix by hand means writing an expression per dependency, per source, per hash. The lock file already contains the resolved versions, so the tool's job is to translate that existing information rather than invent a new one.
The maintenance notice comes first in the README, which is unusual and worth reading before anything else. The creator and long-term maintainer, adisbladis, is no longer using Poetry or poetry2nix. The project is looking for maintainers.
Two specific gaps are named. Poetry has a number of upcoming large changes, and poetry2nix is unlikely to gain support for PEP 621 pyproject.toml metadata or for Poetry 2.0. Those are not edge cases. PEP 621 is the standard metadata format for Python projects, and Poetry 2.0 is the version that moves toward it. A converter that cannot read the metadata format the ecosystem is converging on has a short shelf life.
So the README gives an explicit redirect. If you are not already using Poetry and poetry2nix, consider uv and uv2nix, both linked from the notice.
The repository facts add context rather than contradiction. The last push was on 2026-10-19 and the repository is not archived, so work continues in the tree. The listed releases are dated March 2025, with tags like 2025.3.1955794 and 2025.3.1774463, which is a versioning scheme built from a date and a build number rather than a semantic version.
Two ways to import it: niv for default.nix, a flake input otherwise
The quickstart offers two integration routes, and the choice between them is the first decision a user makes.
The non-flake route adds a default.nix next to pyproject.toml and poetry.lock. The file imports pinned sources, uses poetry2nix to define a myPythonApp with mkPoetryApplication, and returns it.
# file: default.nix
let
sources = import ./nix/sources.nix;
pkgs = import sources.nixpkgs { };
# Let all API attributes like "poetry2nix.mkPoetryApplication"
# use the packages and versions (python3, poetry etc.) from our pinned nixpkgs above
# under the hood:
poetry2nix = import sources.poetry2nix { inherit pkgs; };
myPythonApp = poetry2nix.mkPoetryApplication { projectDir = ./.; };
in
myPythonAppThe key detail is in the comments. The API attributes such as mkPoetryApplication use the packages and versions, python3 and poetry among them, from the pinned nixpkgs above, under the hood. So the tool itself does not drag its own package set along. It consumes your nixpkgs.
The pinned sources come from the niv tool, and the README gives the three commands to set that up.
nix-shell -p niv
niv init
niv add nix-community/poetry2nixAfter that, the build is nix-build default.nix and the result is a symlinked folder you run from.
nix-build default.nixThe executable you run comes from the scripts section of your pyproject.toml, and the README is explicit that you replace the placeholder with the name of your own script.
./result/bin/<script>The flake route skips niv entirely. The repository is published as a flake input, the example flake.nix declares nixpkgs and poetry2nix as inputs, and the library attribute set is exposed through poetry2nix.lib.mkPoetry2Nix.
inherit (poetry2nix.lib.mkPoetry2Nix { inherit pkgs; }) mkPoetryApplication;
myPythonApp = mkPoetryApplication { projectDir = ./.; };From there the run command is simply nix run ., and the flake also exports a template so a new project can start with nix flake init --template github:nix-community/poetry2nix.
The API is seven attributes, and only three matter on day one
The public API is short enough to read in full, which is unusual for a tool that wraps a complicated format.
mkPoetryApplication creates a Python application. mkPoetryEnv creates a Python environment with an interpreter and all packages from poetry.lock. mkPoetryPackages gives access to the generated packages and other artifacts. mkPoetryScriptsPackage produces a package containing the scripts from tool.poetry.scripts. mkPoetryEditablePackage creates a package with editable sources, where changes in the specified paths are reflected in an interactive nix-shell session without a restart.
Then there are three that exist to fix the rough edges. defaultPoetryOverrides is a set of bundled overrides fixing problems with Python packages, and overrides.withDefaults and overrides.withoutDefaults are convenience functions for specifying overrides on top of, or without, those defaults. cleanPythonSources creates a source filter for Python projects.
The attribute arguments for mkPoetryApplication are mostly optional, which is the useful detail. projectDir is the path to the root of the project and is mandatory. Everything else has a default: src defaults to cleanPythonSources applied to projectDir, pyproject defaults to projectDir plus the pyproject.toml path, poetrylock defaults to the poetry.lock path in the project directory, overrides defaults to defaultPoetryOverrides, meta defaults to an empty set, and python defaults to pkgs.python3. There is also a preferWheels option to use wheels rather than sdist as much as possible.
So the typical call is one argument, and the escape hatches exist for the cases that need them.
The bundled defaults deserve a note, because they encode the accumulated frustration of many Python packages. A default override set that fixes problems with specific packages is exactly what you want in a converter, and exactly what you want to be able to switch off when it gets in your way, which is why overrides.withoutDefaults exists.
An overlay lets you reach the tool through pkgs
The flake provides an overlay that merges poetry2nix into your pkgs so you can access it as pkgs.poetry2nix, and the README explains the edit precisely.
The three lines to replace are pkgs = ..., inherit ... and myPythonApp = ....
pkgs = nixpkgs.legacyPackages.${system}.extend poetry2nix.overlays.default;
myPythonApp = pkgs.poetry2nix.mkPoetryApplication { projectDir = self; };The difference from the earlier example is subtle but real. The library route uses a local inherit to pull mkPoetryApplication into scope, then calls it. The overlay route extends the package set itself, so the function is reachable as an attribute of pkgs, and projectDir becomes self rather than a relative path.
That distinction matters for larger setups. Once the tool is an overlay in your package set, any expression in your flake can build a Poetry application, and shared configuration like your Python version or your override set can live in one place rather than being threaded through each call site.
The repository layout reflects how much machinery is behind this. There are separate directories for fetchers, hooks, overrides, plugins, templates and vendor, plus top-level lib.nix, mk-poetry-dep.nix, overlay.nix, plugins.nix, shell-scripts.nix and editable.nix. The templates directory holds the app flake template the README points to for a larger real-world setup, and fetchers and hooks are where the per-package build handling lives.
The Makefile is small. The default target runs generate and then test, generate calls ./generate.py, and the test target runs flake8 over the Python files in a nix-shell with python3Packages.flake8.
nix-shell -p python3Packages.flake8 --run 'flake8 ./*.py'So the Python side of the project is linted with flake8 and the generation step is a script at the root.
Why the project exists at all, and where the alternative differs
The motivation is worth understanding, because it explains the design choices.
Nix builds software from pinned sources with hashes. Python packaging has never been built for that model. PyPI distributes source distributions and wheels, builds them at install time on the user's machine, and does not guarantee reproducible results. Poetry improves on this with a lock file, but the lock file is a Poetry concept and Nix does not read it.
poetry2nix bridges the two. It reads the lock file and emits Nix derivations, which means your Python dependencies become as reproducible as the rest of your Nix closure.
The alternative the README points to, uv2nix, comes from the same author, adisbladis, and is the successor to the successor of the tool that preceded poetry2nix. The difference in approach is the input format. poetry2nix parses pyproject.toml and poetry.lock, the Poetry-native pair. uv2nix consumes the uv ecosystem instead, so the lock file it reads is the one uv produces.
So the choice is not really between two tools with different features. It is between two dependency ecosystems, and the direction of travel is clear from the maintainer's own recommendation. If your project already uses Poetry, poetry2nix works on it today. If you are starting fresh, the author is telling you to use uv.
There is a second alternative worth naming without reaching for specifics the documentation does not give: writing the Nix expressions by hand, or using a tool that consumes pyproject.toml alone. That approach avoids the lock file dependency but gives up the automatic derivation of the whole dependency tree, which is the part of the job nobody wants to do by hand.
Where poetry2nix is the wrong tool
The clearest case against is a new project. The README's own words are that if you are not already using Poetry and poetry2nix, consider uv and uv2nix, and the stated reason is that support for PEP 621 metadata and Poetry 2.0 is unlikely to arrive. Starting a project on a converter that is unlikely to read the metadata format your package manager is moving toward is a bet with a bad payout.
The second case is an existing project that has not adopted Poetry. The tool's input is pyproject.toml and poetry.lock, and a project that manages dependencies with pip and requirements.txt has neither in the Poetry format.
The third case is lock file churn. The conversion is driven entirely by poetry.lock, and the README lists preferWheels as an option to use wheels rather than sdist as much as possible. Packages whose wheels are missing or stale relative to the sdist, and packages with unusual build backends, are exactly where a lock file driven converter has to make a choice on your behalf. The bundled defaultPoetryOverrides exist because these cases are known, and each override you do not want is another thing to switch off with overrides.withoutDefaults.
The fourth case is a shared library rather than an application. mkPoetryEnv and mkPoetryPackages give you an environment and the generated packages, and the editable package supports interactive development, so the tooling is there. But the tooling is centred on Poetry's model of a project with one lock file and a scripts section, and a library published to an index rather than built as an application does not have that shape.
A practical note on the ecosystem: the whole approach assumes a Nix environment with nix-build or nix available, and the niv route assumes network access to fetch the pinned sources on the first build.
MIT licensed, with the operational cost of an unmaintained converter
The licence field on the repository says MIT, and the LICENSE file at the root is the MIT text, which is permissive enough that the licensing question rarely blocks adoption.
The real cost of this project is operational rather than legal. A converter reads a format that the format owner is changing. Poetry is moving towards PEP 621 metadata and towards version 2.0, and the README states plainly that poetry2nix is unlikely to gain support for either. If your project upgrades Poetry across that boundary, the converter stops understanding your pyproject.toml, and you are either stuck on an old Poetry, or you are writing the Nix expressions by hand, or you migrate to uv and uv2nix.
That is the migration cost to plan for, and it is a one-time cost rather than an ongoing tax. For an existing project with a settled lock file, the value is immediate and the risk is deferred. For a project that will live for years, the deferred risk is the larger number.
The versioning tells its own story. The listed releases carry tags like 2025.3.1955794, 2025.3.1774463 and 2025.3.1035432, three of them within ten days of March 2025. A date and build number scheme fits a project that is built and published by automation rather than cut by hand, which also fits a tool that is consumed as a pinned input by niv or as a flake input.
For that reason the pinning mechanism matters as much as the tool. With niv, the sources are pinned by niv into a sources.nix file in your tree, so the converter version is frozen with your project rather than tracked from upstream. With flakes, the input is pinned through flake.lock. Either way, the version you adopt is a decision recorded in your repository, and the upgrade is an explicit act rather than something that happens to you.
Editorial conclusion
Adopt poetry2nix if you already have a Poetry project with a committed poetry.lock and need a reproducible Nix build today without hand writing Nix expressions for every dependency. Do not start a new project on it, because the README states the creator and long-term maintainer is no longer using Poetry or poetry2nix, the project is looking for maintainers, and support for PEP 621 metadata and Poetry 2.0 is unlikely to arrive. Before committing, read the maintenance notice at the top of the README, check that your poetry.lock format is one the tool can still parse, and decide deliberately between the niv based default.nix route and the flake route, because mixing the two later is the part that costs the most time.
Frequently asked questions
What does poetry2nix do?
It turns Poetry projects into Nix derivations without requiring you to write Nix expressions, by parsing pyproject.toml and poetry.lock and converting them to Nix derivations on the fly.
Is poetry2nix still maintained?
The README marks it as unmaintained. The creator and long-term maintainer is no longer using Poetry or poetry2nix, the project is looking for maintainers, and support for PEP 621 metadata and Poetry 2.0 is considered unlikely. The last push was on 2026-10-19.
How do I use poetry2nix with a flake?
Add github:nix-community/poetry2nix as a flake input, then inherit mkPoetryApplication from poetry2nix.lib.mkPoetry2Nix and call it with projectDir. You can then build and run the app with nix run .
What is the difference between mkPoetryApplication and mkPoetryEnv?
mkPoetryApplication creates a Python application, while mkPoetryEnv creates a Python environment with an interpreter and all packages from poetry.lock. The public API also includes mkPoetryPackages, mkPoetryScriptsPackage and mkPoetryEditablePackage.
What should I use instead of poetry2nix for a new project?
The README itself points to uv and uv2nix, noting that Poetry has upcoming large changes and poetry2nix is unlikely to support PEP 621 pyproject.toml metadata or Poetry 2.0.
How do I override the packages poetry2nix builds from source?
The API ships defaultPoetryOverrides, a bundled set of overrides fixing problems with Python packages, and you can build on top of them with overrides.withDefaults or opt out with overrides.withoutDefaults. mkPoetryApplication also has a preferWheels option.
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/nix-community-poetry2nix)Was this useful?