Virtual dependency directories for package managers, backed by a shared FUSE store.
Project description
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/fustion 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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uvl_fuse-0.0.3-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: uvl_fuse-0.0.3-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 1.8 MB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
051d44a3dd5cd7b77c785f8e79d0ad0db9478dab6867ea3a37b8f4ca94bbd8ee
|
|
| MD5 |
d54e617e2b113ce08b0168ea644f74dd
|
|
| BLAKE2b-256 |
9147022f0703fe6a7746306815d1fe6a5ac02a1a043d2f35b7f7daccb3bcecb5
|
Provenance
The following attestation bundles were made for uvl_fuse-0.0.3-py3-none-manylinux_2_28_x86_64.whl:
Publisher:
wheel.yml on ShinapriLN/uvl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvl_fuse-0.0.3-py3-none-manylinux_2_28_x86_64.whl -
Subject digest:
051d44a3dd5cd7b77c785f8e79d0ad0db9478dab6867ea3a37b8f4ca94bbd8ee - Sigstore transparency entry: 1476823692
- Sigstore integration time:
-
Permalink:
ShinapriLN/uvl@aff812cf7330fff55f04ee688d6a1ccbf7d19e43 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/ShinapriLN
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheel.yml@aff812cf7330fff55f04ee688d6a1ccbf7d19e43 -
Trigger Event:
push
-
Statement type: