Context
Relates to #423 (PEP 723 support).
uv has become the de-facto fast Python package/venv manager and overlaps heavily with what fades does. This issue does two things:
- Documents a feature-by-feature comparison of every fades command/feature against its
uv equivalent.
- Proposes a concrete first step: use
uv as an optional backend (create the venv + install deps with uv instead of pip/venv when uv is available), keeping all the rest of fades' behaviour unchanged.
The comparison is meant to inform a future decision about fades' direction. For now the only proposed action is the optional-backend work below.
fades → uv feature comparison
Docs read: uv latest (scripts, run, CLI reference) and fades master README/CLI.
CLI options
| fades option |
What it does |
uv equivalent |
Same? |
fades script.py |
Run script in managed venv |
uv run script.py |
✅ |
#!/usr/bin/env fades |
Self-executing script |
#!/usr/bin/env -S uv run --script |
✅ |
fades http://.../script.py |
Run script from pastebin/URL |
uv run https://.../script.py |
✅ (fades also resolves pastebin/gist/linkode share pages) |
import x # fades |
Mark dep via import comment |
❌ none — uv uses PEP 723 or --with |
❌ fades-only |
| docstring deps |
Deps in docstring after fades line |
❌ none |
❌ fades-only |
-d, --dependency |
Add dep on CLI (repeatable) |
uv run --with PKG |
✅ |
-r, --requirement |
Install from requirements file(s) |
uv run --with-requirements req.txt |
✅ |
-p, --python |
Pick interpreter |
uv run --python 3.11 (also auto-downloads) |
✅ (uv superset) |
-i, --ipython |
Use IPython REPL |
uv run --with ipython ipython |
⚠️ manual, not a flag |
-a, --autoimport |
Auto-import deps in REPL |
❌ none |
❌ fades-only |
| (no script) |
Open REPL in the env |
uv run python |
✅ |
--system-site-packages |
Venv sees system packages |
uv venv --system-site-packages (create-time only) |
⚠️ partial |
-x, --exec |
Run any installed executable in venv |
uv run <exe> / uvx <exe> |
✅ |
-m, --module |
Run module |
uv run -m module |
✅ |
--check-updates / -U |
Re-resolve to newest |
uv run --refresh / --upgrade |
✅ |
--freeze FILE |
Dump pip freeze of env |
uv lock --script (.py.lock) / uv export |
⚠️ different format |
--no-precheck-availability |
Skip PyPI existence check |
n/a (uv resolves directly) |
— |
--avoid-pip-upgrade |
Don't auto-upgrade pip |
n/a (no pip) |
— |
--pip-options |
Pass-through pip args |
native flags only; no generic passthrough |
⚠️ partial |
--python-options |
Pass-through python args |
uv run python <opts> |
✅ |
--virtualenv-options |
Pass-through virtualenv args |
limited uv venv flags |
⚠️ partial |
-v/--verbose, -q/--quiet |
Verbosity |
uv -v / uv -q |
✅ |
-V, --version |
Version + system info |
uv version |
✅ |
Repository / source support
| fades feature |
uv equivalent |
Same? |
pypi::pkg |
default PyPI |
✅ |
vcs::git+https://... |
--with "pkg @ git+https://..." |
✅ |
file:///local/project |
--with /local/path |
✅ |
| alternate index |
uv run --index URL |
✅ |
Venv lifecycle / maintenance
| fades feature |
uv equivalent |
Same? |
--get-venv-dir / --where |
❌ envs live opaquely in uv cache |
❌ fades-only |
--rm UUID |
uv cache clean / prune (no per-UUID removal) |
⚠️ partial |
--clean-unused-venvs=N |
uv cache prune (no day-based policy) |
⚠️ partial |
| per-depset venv reuse |
automatic (keyed on resolved depset) |
✅ |
Configuration
| fades feature |
uv equivalent |
Same? |
.ini at system/user/project, merged |
uv.toml / [tool.uv] + env vars, layered |
✅ (different format) |
| config-injected global deps into every env |
❌ none |
❌ fades-only |
Genuine fades-only features (uv can't replicate today)
# fades import-comment & docstring dependency marking (fades' signature feature).
--autoimport into the REPL.
--where/--get-venv-dir and --rm UUID (per-venv management by UUID).
--clean-unused-venvs=N day-based GC.
- Config-injected global dependencies.
How the comparison shifts once fades supports PEP 723 (#423)
Once #423 lands, fades will read # /// script ... /// blocks. This narrows the gap meaningfully:
- Interoperability: fades and uv (and pipx/pip-run) could run each other's scripts. The
# fades comment convention stays as the fades-native way; PEP 723 becomes the portable way.
- Dependency declaration moves from "fades-only" toward "✅ same standard" — the biggest semantic difference between the tools largely disappears.
- What remains distinctly fades: the
# fades comment style, --autoimport, explicit per-UUID venv management (--where/--rm), day-based venv GC, and config-injected global deps.
So post-#423 the two tools converge on the input format but still differ on venv management philosophy (fades exposes/manages individual venvs by UUID; uv hides them in a cache).
Proposal: use uv as an optional backend
Add uv as an optional dependency. When uv is present on the system, fades uses it for the parts where it's strictly better; when it's absent, fades behaves exactly as today.
Concretely:
- Venv creation: use
uv venv instead of the venv/virtualenv path.
- Dependency installation: use
uv pip install (or uv add) instead of pip.
- Everything else stays fades: dependency parsing (
# fades comments, docstring, -d/-r), venv indexing by UUID, reuse logic, --where/--rm/--clean-unused-venvs, config files, REPL/--autoimport, etc.
This gives fades users uv's speed and built-in Python provisioning without changing fades' UX or losing any of its unique features, and it's a low-risk, incremental step.
Open questions to resolve before implementing:
- Detection & opt-out: auto-detect
uv on PATH, with a config flag / env var to force on/off?
- Does
uv's venv layout stay compatible with fades' UUID indexing and reuse-by-hash logic?
- How to map
--pip-options / --virtualenv-options onto uv invocations.
--freeze semantics when using uv.
Scope of this issue
This issue is for documenting the comparison and discussing the optional-backend approach. No implementation is proposed here yet beyond the outline above — the broader question of fades' long-term direction vs. uv is intentionally left for a future decision.
Context
Relates to #423 (PEP 723 support).
uvhas become the de-facto fast Python package/venv manager and overlaps heavily with what fades does. This issue does two things:uvequivalent.uvas an optional backend (create the venv + install deps withuvinstead ofpip/venvwhenuvis available), keeping all the rest of fades' behaviour unchanged.The comparison is meant to inform a future decision about fades' direction. For now the only proposed action is the optional-backend work below.
fades → uv feature comparison
Docs read: uv latest (scripts, run, CLI reference) and fades
masterREADME/CLI.CLI options
fades script.pyuv run script.py#!/usr/bin/env fades#!/usr/bin/env -S uv run --scriptfades http://.../script.pyuv run https://.../script.pyimport x # fades--withfadesline-d, --dependencyuv run --with PKG-r, --requirementuv run --with-requirements req.txt-p, --pythonuv run --python 3.11(also auto-downloads)-i, --ipythonuv run --with ipython ipython-a, --autoimportuv run python--system-site-packagesuv venv --system-site-packages(create-time only)-x, --execuv run <exe>/uvx <exe>-m, --moduleuv run -m module--check-updates/-Uuv run --refresh/--upgrade--freeze FILEpip freezeof envuv lock --script(.py.lock) /uv export--no-precheck-availability--avoid-pip-upgrade--pip-options--python-optionsuv run python <opts>--virtualenv-optionsuv venvflags-v/--verbose,-q/--quietuv -v/uv -q-V, --versionuv versionRepository / source support
pypi::pkgvcs::git+https://...--with "pkg @ git+https://..."file:///local/project--with /local/pathuv run --index URLVenv lifecycle / maintenance
--get-venv-dir/--where--rm UUIDuv cache clean/prune(no per-UUID removal)--clean-unused-venvs=Nuv cache prune(no day-based policy)Configuration
.iniat system/user/project, mergeduv.toml/[tool.uv]+ env vars, layeredGenuine fades-only features (uv can't replicate today)
# fadesimport-comment & docstring dependency marking (fades' signature feature).--autoimportinto the REPL.--where/--get-venv-dirand--rm UUID(per-venv management by UUID).--clean-unused-venvs=Nday-based GC.How the comparison shifts once fades supports PEP 723 (#423)
Once #423 lands, fades will read
# /// script ... ///blocks. This narrows the gap meaningfully:# fadescomment convention stays as the fades-native way; PEP 723 becomes the portable way.# fadescomment style,--autoimport, explicit per-UUID venv management (--where/--rm), day-based venv GC, and config-injected global deps.So post-#423 the two tools converge on the input format but still differ on venv management philosophy (fades exposes/manages individual venvs by UUID; uv hides them in a cache).
Proposal: use
uvas an optional backendAdd
uvas an optional dependency. Whenuvis present on the system, fades uses it for the parts where it's strictly better; when it's absent, fades behaves exactly as today.Concretely:
uv venvinstead of thevenv/virtualenvpath.uv pip install(oruv add) instead ofpip.# fadescomments, docstring,-d/-r), venv indexing by UUID, reuse logic,--where/--rm/--clean-unused-venvs, config files, REPL/--autoimport, etc.This gives fades users uv's speed and built-in Python provisioning without changing fades' UX or losing any of its unique features, and it's a low-risk, incremental step.
Open questions to resolve before implementing:
uvonPATH, with a config flag / env var to force on/off?uv's venv layout stay compatible with fades' UUID indexing and reuse-by-hash logic?--pip-options/--virtualenv-optionsontouvinvocations.--freezesemantics when usinguv.Scope of this issue
This issue is for documenting the comparison and discussing the optional-backend approach. No implementation is proposed here yet beyond the outline above — the broader question of fades' long-term direction vs. uv is intentionally left for a future decision.