Skip to content

uvlink

uvlink is a CLI tool that moves heavy folders like Python's .venv and Node's node_modules out of your project into a local cache, and symlinks them back. It works for any folder you name. Perfect for developers who sync code to Dropbox, Google Drive, or iCloud. Only your source code syncs, not gigabytes of dependencies.

PyPI - Version PyPI - Downloads GitHub Actions - CI Tests GitHub - License

Cloud services like Dropbox, Google Drive, or iCloud often struggle with the thousands of small files found in Python virtual environments (.venv). This can lead to:

  • Slow Syncing: Endless "Syncing..." status.
  • High Bandwidth Usage: Uploading/downloading megabytes of dependencies unnecessarily.
  • Conflicts: Sync conflicts on binary files.

uvlink solves this by moving the heavy .venv directory to a local cache (outside the synced folder) and replacing it with a lightweight symlink. Your cloud service syncs the symlink (negligible size), while your tools (VS Code, terminal) follow the link seamlessly.

Important Note on Caching

Since v0.6.0, the cache directory includes the venv type in its folder name and stores the environment under a matching subdirectory (e.g. ~/.local/share/uvlink/cache/<project-name>-<hash>-.venv/.venv). Delete caches created with older versions and rerun uvlink link to migrate.

Windows Support

Windows support is considered beta as of v0.8.0. It uses directory junctions as a fallback when symlinks are not available, which does not require admin privileges or Developer Mode. Please report any issues you encounter on Windows!

Quick Start

For installation instructions, please refer to the Installation page.

Navigate to any Python project (which may be created by uv init for instance) and run uvlink link:

cd /path/to/your/project
uvlink link

The link command asks which directory to link:

? Which directory to link? (↑/↓, Enter)
 ❯ .venv
   node_modules
   type your own

Use the arrow keys to move and Enter to pick. Pressing Enter right away picks .venv, which is where uv sync installs by default. uvlink then creates a .venv symlink in your project pointing to a cached environment. When not run in a terminal (e.g. in a script), it uses .venv without asking.

You can also skip the menu by giving the name directly, for example:

uvlink link myenv

This creates a myenv symlink instead.

The cached environment is stored under $XDG_DATA_HOME/uvlink/cache/<project-name>-<hash>-<venv_name>/<venv_name> (or ~/.local/share/uvlink/cache/... if XDG_DATA_HOME is not set).

After linking, you can use the virtual environment just like you would with uv within the project directory:

source .venv/bin/activate   # Activate the environment
uv sync                     # Install dependencies into the cached .venv
uv run python script.py     # Run commands in the environment

Since .venv exists as a symlink in your project directory, all standard activation methods work. Your cloud service will ignore the heavy virtual environment files since they're stored in the cache.

List all cached environments:

uvlink ls

Shows all projects with cached environments and their link status. Projects where the symlink has been removed (e.g., via rm .venv) will show as "Not Linked" (❌). You can relink them by running uvlink link again in that project directory.

To only list projects under a path (recursively), give the path, for example uvlink ls . for the current directory.

Remove a symlink

To remove the symlink, just do normal rm:

rm .venv
This will remove the symlink .venv, and the unlinked cache can be further cleaned up by uvlink gc (garbage collection) command as following.

Clean up unlinked caches:

uvlink gc

Removes cached environments for projects that no longer have working symlinks (marked as "Not Linked" in uvlink ls), freeing up disk space.

Demo

Other Use Cases

In fact, since the minimal philosophy of uvlink is that it only creates symlinks and link them to the cache, it can be used for other use cases as well. For example, you can cache tmp, objs, ... etc as much as you want:

uvlink link .venv
uvlink link tmp
uvlink link objs
# ... etc
However, we only recommand using it for type of files that can be easily regenerated if lost, such as virtual environments, dependencies, intermediate build files, ... etc.