uvl
uvl lets package managers keep using their normal dependency directories while
a FUSE filesystem redirects the physical files into a shared global store.
The project still sees directories like node_modules or .venv. The files
live under:
~/.uvl/store/<manager>
That keeps normal tool behavior intact while duplicate dependency trees can be stored once and mounted back into each project as a read-only virtual view.
Install
From PyPI:
pipx install uvl-fuse
# or
uv tool install uvl-fuse
From this repository:
❯ git clone https://github.com/ShinapriLN/uvl.git
...
❯ cd uvl
❯ make
...
❯ ./build/uvl --help
uvl: virtual dependency directories backed by a shared FUSE store
Usage:
uvl --fuse <tool> --mnt <dir> Register/fusion a tool mount directory
uvl --fiss <tool> Remove/fission a tool out of uvl
uvl <tool> [args...] Run the tool through uvl
uvl --unmnt <dir> Unmount a virtualized dependency directory
uvl --stat Show current project mount status
uvl --list, -l List fused tools
uvl --has <tool> Check whether a tool is fused with uvl
uvl --version, -v Print version
Published wheels include the native engine, so installation does not need to compile the C code. Runtime mounting still needs Linux FUSE support and permission to mount filesystems.
If you build from source, install:
cmake- a C compiler such as
gccorclang pkg-config- FUSE 3 development headers
- OpenSSL development headers
- Python 3.8+ and
uvif you want to build the wheel locally
Platform Support
Published wheels:
- Linux x86_64
Runtime requirements:
- Linux kernel FUSE support
/dev/fuseaccessfusermount3or an equivalent FUSE unmount helper
Source builds work on the same Linux environment, but the runtime FUSE requirements still apply.
Build From Source
The repository has one native CLI binary built by CMake:
build/uvl
The binary handles the CLI, tool wrapping, object storage, and FUSE mount mode in a single executable. It re-executes itself internally for mount mode, so there is no separate mount binary to manage.
Use the Makefile wrapper for day-to-day commands:
make # configure CMake and build the native binary
make build # same as make
make check # build the native binary and run a CLI smoke check
make wheel # build a wheel with the bundled native binary
make clean # remove build outputs and Python bytecode
Register A Tool
Register the tool binary and the dependency directory it owns:
uvl --fuse bun --mnt node_modules
[UVL] [ INFO ] Fused `bun` with uvl.
[UVL] [ INFO ] Mount directory: `node_modules`
[UVL] [ INFO ] Store: ~/.uvl/store/bun
[UVL] [ INFO ] Run `uvl bun ...` to use it through uvl.
The same pattern works for uv:
uvl --fuse uv --mnt .venv
Useful management flags:
uvl --list # list registered tools from ~/.uvl/config.json
uvl --has uv # check whether a tool binary exists in PATH
uvl --fiss uv # remove a tool from ~/.uvl/config.json
uvl --stat # show current project mount status
uvl --unmnt .venv
Usage
After a tool is registered, run it through uvl whenever the dependency tree
may change.
Bun
❯ uvl bun install
bun install v1.2.10 (db2e7d7f)
+ typescript@5.9.3
+ @types/bun@1.3.13
5 packages installed [11.00ms]
[UVL] [ INFO ] Taking control of '<project>/node_modules'.
[UVL] [ INFO ] Mounting virtual filesystem with 635 files...
[UVL] [ INFO ] Successfully mounted virtual '<project>/node_modules'.
[UVL] [ INFO ] Deduplication saved 27.50 MB of physical disk space.
[UVL] [ INFO ] Virtualized 27.50 MB into ~/.uvl/store/bun.
❯ uvl bun add vite
bun add v1.2.10 (db2e7d7f)
installed vite@8.0.11 with binaries:
- vite
17 packages installed [1.88s]
[UVL] [ INFO ] Re-virtualizing '<project>/node_modules' after command completed.
[UVL] [ INFO ] Mounting virtual filesystem with 846 files...
[UVL] [ INFO ] Successfully remounted virtual '<project>/node_modules'.
[UVL] [ INFO ] Deduplication saved 26.39 MB of physical disk space.
[UVL] [ INFO ] Virtualized 93.64 MB into ~/.uvl/store/bun.
The directory still works as normal:
❯ bun run index.ts
Hello via Bun!
❯ uvl bun run index.ts
Hello via Bun!
Disk usage in the project directory stays near zero:
❯ du -sh node_modules
0 node_modules
Uv
❯ uv init app
Initialized project `app` at `<project-root>/app`
❯ cd app
❯ uvl uv sync
Using CPython 3.12.12
Creating virtual environment at: .venv
Resolved 1 package in 2ms
Audited in 0.00ms
[UVL] [ INFO ] Taking control of '<project>/.venv'.
[UVL] [ INFO ] Mounting virtual filesystem with 19 files...
[UVL] [ INFO ] Successfully mounted virtual '<project>/.venv'.
[UVL] [ INFO ] Deduplication saved 0.01 MB of physical disk space.
[UVL] [ INFO ] Virtualized 0.03 MB into ~/.uvl/store/uv.
Running through either command still works:
❯ uvl uv run main.py
Hello from app!
❯ uv run main.py
Hello from app!
Project Status
--stat shows every mounted tool in the current project. A project can track
multiple entries at once:
❯ uvl --stat
Project status:
manifest: <project>/.uvl
uv:
mount: .venv
store: ~/.uvl/store/uv
records: 46469
mounted: yes
bun:
mount: node_modules
store: ~/.uvl/store/bun
records: 22364
mounted: yes
Disk Usage
The point is to keep dependency trees mounted in place while the physical files live in the shared store:
find ~/Documents -type d -name node_modules -prune -exec du -sh {} +
0 ~/Documents/proj/app/node_modules
0 ~/Documents/ai/project-b/node_modules
find ~/Documents -type d -name .venv -prune -exec du -sh {} +
0 ~/Documents/proj/app/.venv
0 ~/Documents/ai/project-b/.venv
Those directories still work normally, but the bytes are stored once under
~/.uvl/store/<manager>.
Unmount
Mounted dependency directories are intentionally read-only. If you want to delete, inspect, or rebuild the directory directly, unmount it first:
uvl --unmnt .venv
After unmounting, the mount point is just a normal directory again.
How It Works
uvl --fuse <tool> --mnt <dir>saves a registration in~/.uvl/config.json.uvl --fiss <tool>removes the tool from~/.uvl/config.json.uvl <tool> ...resolves the real tool binary fromPATHand runs it with the same arguments.- If the registered entry directory exists,
uvlrestores the mounted view before the tool changes files. - Files are content-addressed by SHA-256 and stored under
~/.uvl/store/<tool>. - A binary project
.uvlmanifest stores every mounted tool and mount directory for fast loading. One project can track multiple entries such as.venvandnode_modulesat the same time. - A C FUSE daemon mounts a read-only virtual filesystem at the original dependency directory.
The goal is simple: tools keep their normal layout while projects stop holding duplicate physical dependency trees.
Shinapri
Metadata
Release files for uvl-fuse 0.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| uvl_fuse-0.0.4-py3-none-manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64 | Details for uvl_fuse-0.0.4-py3-none-manylinux_2_28_x86_64.whl |
Release files / uvl_fuse-0.0.4-py3-none-manylinux_2_28_x86_64.whl
| Download URL | uvl_fuse-0.0.4-py3-none-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
6e452fc9d2495ea16991a268c8ff850e70c3ef38a0bdf747d44655d78742fdac
|
|
BLAKE2b-256 checksum How to use checksums |
da79b11967b510d165a2f3dfa5f115c7170a574598ea4919f50a67fd52de169c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 8, 2026.
Transparency logSecurity for uvl-fuse 0.0.4
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.
Full provenance
All 1 file in this release has been uploaded with provenance metadata.
Attestation for uvl_fuse-0.0.4-py3-none-manylinux_2_28_x86_64.whl
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 May 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.