uv add nimlang
Use Nim in a Python project with nothing but uv.
nimlang is a Python package that ships the Nim compiler in its wheels and compiles C through
zig cc from the ziglang package, so you need no system
Nim and no C compiler.
nimpy is the core Nim dependency: it is the binding
library that exports Nim procs to Python ({.exportpy.}) and lets Nim call Python. Every
Nim extension module built with nimlang uses it.
AI disclosure: this project is mostly vibed. Currently level 7 on visidata AI scale: Human specced, bots coded.
Status: alpha. Ideas for evolution: ROADMAP.md.
Try it: a Python project with a Nim function
uv init uv-add-nimlang-demo && cd uv-add-nimlang-demo
uv add nimlang
uv run nimlang add nimpy # Nim deps go in [tool.nimlang] in pyproject.toml
uv run nimlang info # bundled Nim and zig, and the project's Nim deps
slow.py, you have a slow function in Python:
def fib(n):
return n if n < 2 else fib(n - 1) + fib(n - 2)
fast.nim, you write it in Nim:
import nimpy
proc fib(n: int): int {.exportpy.} =
if n < 2: n else: fib(n - 1) + fib(n - 2)
fast.py, and import it in Python (it needs the extensione module built):
from fast import fib
Build the extension module and compare slow and fast versions with timeit:
uv run nimlang build-ext fast.nim # writes nimfib.<python-tag>.so (.pyd on Windows) next to it
uv run python -m timeit -s "from slow import fib" "fib(30)" # 2 loops, best of 5: 135 msec per loop
uv run python -m timeit -s "from fast import fib" "fib(30)" # 20 loops, best of 5: 10.6 msec per loop
How Nim and Nim dependencies are provided
The Nim compiler comes inside the nimlang wheel for your platform (Linux x86_64/aarch64,
macOS arm64/x86_64, Windows x86_64). Each nimlang release bundles one Nim version, currently
2.2.6, along with atlas. uv run nim runs it with
zig cc as the C compiler and with the project's Nim dependencies on the path:
uv run nim --version # 2.2.6
uv run nim c -r hello.nim
uv run nimlang info # which Nim and zig are used, and the project's Nim deps
On other platforms nimlang uses $NIMLANG_NIM_HOME or a nim on PATH. Choosing the Nim
version per project is on the roadmap.
The C compiler is zig cc from the ziglang package,
installed as a regular dependency.
Nim dependencies are declared in pyproject.toml, next to the Python ones, and pinned in a
lock file, like uv does for Python packages:
[tool.nimlang]
dependencies = ["nimpy", "cligen >= 1.7"]
uv run nimlang add nimpy # adds it to [tool.nimlang] and syncs
uv run nimlang remove nimpy # removes it and syncs
uv run nimlang sync # installs exactly what nimlang.lock pins
uv run nimlang lock # resolves again to the newest allowed versions
- Version constraints use atlas (nimble) syntax: the usual
==,>=,<operators,&to combine them ("nimib >= 0.3 & < 0.4"), and#heador#<commit>for git refs ("nimpy#head"). A package name alone takes the newest release, which the lock then pins. nimlang.lockrecords the git URL and commit of every package, including transitive ones. Commit it, so every checkout and every wheel build uses the same code.- Packages are cloned with the bundled atlas into
.nimlang/(git-ignored), so git is needed. Builds through nimlang see only those packages, never~/.nimble. - nimlang drives atlas for you: there is no
atlascommand, and nimble is not shipped.[tool.nimlang]andnimlang.lockare the only places dependencies are managed.
Ship Nim code in a Python package
uv-add-nimlang-lib-demo is a
minimal package built this way and published on PyPI as nimlang-lib-demo. Its users get
prebuilt wheels and need neither nimlang nor a compiler:
uv run --with nimlang-lib-demo python -m timeit -s "from nimlang_lib_demo.slow import fib" "fib(30)"
uv run --with nimlang-lib-demo python -m timeit -s "from nimlang_lib_demo.fast import fib" "fib(30)"
The setup is nimlang as a build requirement, plus its hatch hook pointing at the Nim files:
[build-system]
requires = ["hatchling", "nimlang"]
build-backend = "hatchling.build"
[tool.hatch.build.hooks.nimlang]
extensions = ["src/mypkg/fast.nim"] # importable as mypkg.fast
# binaries = ["src/mypkg/mytool.nim"] # installed as the `mytool` command
[tool.nimlang]
dependencies = ["nimpy"]
uv build produces a py3-none-<platform> wheel that works on every CPython 3 version.
On Linux it is manylinux-compliant out of the box, and NIMLANG_TARGET=aarch64-macos uv build
cross-builds for other platforms. The demo's CI builds all five platform wheels on one Linux
machine and tests each on its own OS. Code that links a macOS system framework (std/random
needs Security) finds it in the SDK xcrun reports on a Mac; to cross-build such code from
another OS, point SDKROOT at a macOS SDK.
Related projects
- nimpy: Nim-Python bindings, the core dependency of
every extension module (
nimlang add nimpy). - nimpy_numpy: numpy array interop on top of
nimpy, registered in the Nim package list (
nimlang add nimpy_numpy).
Experiments in shipping Nim code to Python with nimlang:
- uv-add-nimlang-lib-demo: minimal
package published on PyPI as
nimlang-lib-demo, with prebuilt wheels for five platforms. - nimpy-numpy: its tests and benchmark build Nim extensions with nimlang (a Vandermonde matrix, standard vs contiguous fast path, against numpy).
- not1d: a minimal Nim port of ot1d (1D optimal transport), as a test of a non-trivial algorithm and of the C++ backend (an optional build uses C++ pdqsort). Not on PyPI; install it from git.
Building nimlang wheels
python scripts/make_wheels.py --nim-dist nim-2.2.6-linux_x64.tar.xz --platform-tag manylinux_2_17_x86_64
CI builds them for Linux (x86_64, aarch64), macOS (arm64, x86_64) and Windows x86_64, and
publishes to PyPI when a v* tag is pushed.
Escape hatch: your own C compiler
If zig cc can't build something, NIMLANG_CC=system makes Nim use its default C compiler
(gcc, clang or MSVC) instead. It is not tested in CI and cannot cross-compile, so it can't
build wheels on Linux, where they always target glibc 2.17.
Metadata
Release files for nimlang 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nimlang-0.0.3.tar.gz | 39.0 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| nimlang-0.0.3-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| nimlang-0.0.3-py3-none-manylinux_2_17_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| nimlang-0.0.3-py3-none-manylinux_2_17_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64 | Details |
| nimlang-0.0.3-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
| nimlang-0.0.3-py3-none-macosx_10_13_x86_64.whl | Python 3 | none | macOS 10.13+ x86-64 | Details |
Total release size: 46.4 MB
Release files / nimlang-0.0.3.tar.gz
| Download URL | nimlang-0.0.3.tar.gz |
|---|---|
| Size | 39.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b4a64f92ff7cdc47c88da3c4c523c86aff327b97072f35a0592fab857d1d7ade
|
|
BLAKE2b-256 checksum How to use checksums |
5a323ca3e2bc70a537e87fb5e83a4f77251175f9316ac2d2e4cb0bbee8813104
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 7, 2026.
Transparency logRelease files / nimlang-0.0.3-py3-none-win_amd64.whl
| Download URL | nimlang-0.0.3-py3-none-win_amd64.whl |
|---|---|
| Size | 13.6 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
79f5f114c9cb8ae6a854aa1eff5785d3ee543b69e2dba1593b119f7f808238aa
|
|
BLAKE2b-256 checksum How to use checksums |
4490e7d8b3aef773d9d31507008714cde8197400a56221296c04de27a411dce8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 7, 2026.
Transparency logRelease files / nimlang-0.0.3-py3-none-manylinux_2_17_x86_64.whl
| Download URL | nimlang-0.0.3-py3-none-manylinux_2_17_x86_64.whl |
|---|---|
| Size | 7.4 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
56468e7785a69b8d51fd48af3f60cd6bccf2c6be43aee3d9720b0fcc60840552
|
|
BLAKE2b-256 checksum How to use checksums |
c8a5c3f4b34cee777d688be40ae9a665a8e3c1d024b5a1488c2cae4c607b3e7e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 7, 2026.
Transparency logRelease files / nimlang-0.0.3-py3-none-manylinux_2_17_aarch64.whl
| Download URL | nimlang-0.0.3-py3-none-manylinux_2_17_aarch64.whl |
|---|---|
| Size | 16.1 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
af242cb200fa428033b79acf49bc7921fd7d149b8c9ebfae85784efa7da36437
|
|
BLAKE2b-256 checksum How to use checksums |
1b81610390d649e869c2ca673ace3744e3591beb6060ca490bed8595080e8728
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 7, 2026.
Transparency logRelease files / nimlang-0.0.3-py3-none-macosx_11_0_arm64.whl
| Download URL | nimlang-0.0.3-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.5 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9c03ea6ba728135e32046632eb96f30b9001a9624e76f9dc83f526a550bb74b8
|
|
BLAKE2b-256 checksum How to use checksums |
f3b94473c6c6bc3fc534dfd7729fade6e7da3c6dc4924f7843026e3bbc948fb8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 7, 2026.
Transparency logRelease files / nimlang-0.0.3-py3-none-macosx_10_13_x86_64.whl
| Download URL | nimlang-0.0.3-py3-none-macosx_10_13_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | Python 3 macOS 10.13+ x86-64 |
|
SHA-256 checksum How to use checksums |
1f967774fe711b821067ca59501797be7d44c6fca9f13822cc0cd840fc358e38
|
|
BLAKE2b-256 checksum How to use checksums |
b8ac6474fa088dc65c04318af251dcea1a3afa627c3e427820bbbb481d8c0da0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Oct 7, 2026.
Transparency log