[{"data":1,"prerenderedAt":1215},["ShallowReactive",2],{"page-\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002Fuv-tool-install-vs-pipx-for-clis\u002F":3,"content-directory":1065},{"id":4,"title":5,"body":6,"date":1050,"description":1051,"difficulty":1052,"draft":1053,"extension":1054,"meta":1055,"navigation":171,"path":1056,"seo":1057,"stem":1058,"tags":1059,"updated":1050,"__hash__":1064},"content\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002Fuv-tool-install-vs-pipx-for-clis\u002Findex.md","uv tool install vs pipx for CLIs",{"type":7,"value":8,"toc":1036},"minimark",[9,25,30,96,100,119,207,226,239,250,318,336,358,362,365,410,420,424,427,528,531,573,584,591,594,704,728,732,897,901,915,926,929,933,1002,1006,1032],[10,11,12,16,17,20,21,24],"p",{},[13,14,15],"code",{},"uv tool install"," and ",[13,18,19],{},"pipx install"," solve the same core problem: they put a Python command-line tool on your ",[13,22,23],{},"PATH"," without letting its dependencies collide with anything else on your machine. Each tool gets its own isolated virtual environment, and you type its name like any other program. The differences show up in speed, upgrade ergonomics, and how you run something just once. This guide puts the two side by side for the specific job of installing and living with globally available CLIs.",[26,27,29],"h2",{"id":28},"tldr","TL;DR",[31,32,33,52,60,72,86],"ul",{},[34,35,36,40,41,16,44,47,48,51],"li",{},[37,38,39],"strong",{},"Both give isolated global installs."," Each installed CLI lands in a dedicated virtual environment, so ",[13,42,43],{},"httpie",[13,45,46],{},"awscli"," never fight over ",[13,49,50],{},"requests"," versions.",[34,53,54,59],{},[37,55,56,58],{},[13,57,15],{}," is faster"," thanks to uv's Rust resolver and a shared global cache — repeat installs reuse already-downloaded wheels.",[34,61,62,71],{},[37,63,64,16,67,70],{},[13,65,66],{},"uvx",[13,68,69],{},"pipx run"," are the one-off runners."," Use them to execute a tool once without leaving anything installed.",[34,73,74,77,78,81,82,85],{},[37,75,76],{},"Upgrades differ:"," ",[13,79,80],{},"uv tool upgrade"," re-resolves against your constraints; ",[13,83,84],{},"pipx upgrade"," does the same for pipx-managed venvs. Both let you pin.",[34,87,88,91,92,95],{},[37,89,90],{},"Pick uv"," if you already use it for project work (one tool, one cache); ",[37,93,94],{},"pick pipx"," if you want a small, single-purpose installer that does nothing else.",[26,97,99],{"id":98},"both-give-you-isolated-global-installs","Both give you isolated global installs",[10,101,102,103,106,107,16,109,112,113,115,116,118],{},"The shared idea is worth stating plainly because it is the whole reason these tools exist. If you ",[13,104,105],{},"pip install httpie"," into your system Python, its pinned ",[13,108,50],{},[13,110,111],{},"pygments"," become global, and the next tool that wants a different ",[13,114,111],{}," breaks. Isolated installers avoid this by creating one virtual environment per tool and exposing only that tool's entry-point scripts on your ",[13,117,23],{},".",[120,121,126],"pre",{"className":122,"code":123,"language":124,"meta":125,"style":125},"language-bash shiki shiki-themes github-light github-dark","# pipx: one venv for black, another for httpie\n$ pipx install black\n$ pipx install httpie\n\n# uv: same model, different front door\n$ uv tool install black\n$ uv tool install httpie\n","bash","",[13,127,128,137,154,166,173,179,194],{"__ignoreMap":125},[129,130,133],"span",{"class":131,"line":132},"line",1,[129,134,136],{"class":135},"sJ8bj","# pipx: one venv for black, another for httpie\n",[129,138,140,144,148,151],{"class":131,"line":139},2,[129,141,143],{"class":142},"sScJk","$",[129,145,147],{"class":146},"sZZnC"," pipx",[129,149,150],{"class":146}," install",[129,152,153],{"class":146}," black\n",[129,155,157,159,161,163],{"class":131,"line":156},3,[129,158,143],{"class":142},[129,160,147],{"class":146},[129,162,150],{"class":146},[129,164,165],{"class":146}," httpie\n",[129,167,169],{"class":131,"line":168},4,[129,170,172],{"emptyLinePlaceholder":171},true,"\n",[129,174,176],{"class":131,"line":175},5,[129,177,178],{"class":135},"# uv: same model, different front door\n",[129,180,182,184,187,190,192],{"class":131,"line":181},6,[129,183,143],{"class":142},[129,185,186],{"class":146}," uv",[129,188,189],{"class":146}," tool",[129,191,150],{"class":146},[129,193,153],{"class":146},[129,195,197,199,201,203,205],{"class":131,"line":196},7,[129,198,143],{"class":142},[129,200,186],{"class":146},[129,202,189],{"class":146},[129,204,150],{"class":146},[129,206,165],{"class":146},[10,208,209,210,16,213,216,217,219,220,225],{},"After either pair of commands, ",[13,211,212],{},"black",[13,214,215],{},"http"," are on your ",[13,218,23],{},", backed by separate environments that can hold conflicting dependency trees without noticing each other. This is the same isolation principle covered in ",[221,222,224],"a",{"href":223},"\u002Fproject-setup-dependency-management\u002Fvirtual-environments-isolation-best-practices\u002Fmanaging-virtual-environments-for-cross-platform-clis\u002F","managing virtual environments for cross-platform CLIs"," — an installed tool is just a managed, named venv you never have to activate.",[26,227,229,231,232,234,235,231,237],{"id":228},"uv-tool-install-uvx-vs-pipx-install-pipx-run",[13,230,15],{}," \u002F ",[13,233,66],{}," vs ",[13,236,19],{},[13,238,69],{},[10,240,241,242,246,247,118],{},"Both tools split the world into two verbs: ",[243,244,245],"em",{},"install and keep"," versus ",[243,248,249],{},"run once",[120,251,253],{"className":122,"code":252,"language":124,"meta":125,"style":125},"# Keep it around (adds a command to your PATH)\n$ pipx install cowsay\n$ uv tool install cowsay\n\n# Run it once, throw the environment away afterwards\n$ pipx run cowsay \"hello\"\n$ uvx cowsay \"hello\"\n",[13,254,255,260,271,283,287,292,307],{"__ignoreMap":125},[129,256,257],{"class":131,"line":132},[129,258,259],{"class":135},"# Keep it around (adds a command to your PATH)\n",[129,261,262,264,266,268],{"class":131,"line":139},[129,263,143],{"class":142},[129,265,147],{"class":146},[129,267,150],{"class":146},[129,269,270],{"class":146}," cowsay\n",[129,272,273,275,277,279,281],{"class":131,"line":156},[129,274,143],{"class":142},[129,276,186],{"class":146},[129,278,189],{"class":146},[129,280,150],{"class":146},[129,282,270],{"class":146},[129,284,285],{"class":131,"line":168},[129,286,172],{"emptyLinePlaceholder":171},[129,288,289],{"class":131,"line":175},[129,290,291],{"class":135},"# Run it once, throw the environment away afterwards\n",[129,293,294,296,298,301,304],{"class":131,"line":181},[129,295,143],{"class":142},[129,297,147],{"class":146},[129,299,300],{"class":146}," run",[129,302,303],{"class":146}," cowsay",[129,305,306],{"class":146}," \"hello\"\n",[129,308,309,311,314,316],{"class":131,"line":196},[129,310,143],{"class":142},[129,312,313],{"class":146}," uvx",[129,315,303],{"class":146},[129,317,306],{"class":146},[10,319,320,322,323,326,327,329,330,332,333,335],{},[13,321,66],{}," is simply an alias for ",[13,324,325],{},"uv tool run",". It resolves the requested package, builds (or reuses a cached) ephemeral environment, runs the command, and leaves nothing on your ",[13,328,23],{},". ",[13,331,69],{}," behaves the same way and caches the temporary environment for a few days so a second ",[13,334,69],{}," of the same tool is quick.",[10,337,338,339,342,343,345,346,348,349,353,354,357],{},"The one-off runners are the right call for tools you touch rarely: a project scaffolder, a linter you only run in CI, a ",[13,340,341],{},"cookiecutter"," template. There is no reason to permanently install something you invoke twice a year — reach for ",[13,344,66],{}," or ",[13,347,69],{}," and skip the cleanup. The scaffolding workflow in ",[221,350,352],{"href":351},"\u002Fproject-setup-dependency-management\u002Fcli-project-scaffolding-with-cookiecutter\u002F","CLI project scaffolding with Cookiecutter"," is a textbook case: ",[13,355,356],{},"uvx cookiecutter gh:org\u002Ftemplate"," runs the generator without adding a command you will never use again.",[26,359,361],{"id":360},"speed-and-the-shared-cache","Speed and the shared cache",[10,363,364],{},"This is where uv pulls ahead. uv keeps a single global cache of downloaded and built wheels and resolves dependencies with a parallel Rust resolver. When you install a second tool that shares a dependency with the first, uv links the already-cached wheel instead of re-downloading it. Cold installs are fast; warm installs are close to instant.",[120,366,368],{"className":122,"code":367,"language":124,"meta":125,"style":125},"# First install populates the cache\n$ uv tool install rich-cli\n\n# A later install that shares 'rich' reuses cached wheels\n$ uv tool install textual\n",[13,369,370,375,388,392,397],{"__ignoreMap":125},[129,371,372],{"class":131,"line":132},[129,373,374],{"class":135},"# First install populates the cache\n",[129,376,377,379,381,383,385],{"class":131,"line":139},[129,378,143],{"class":142},[129,380,186],{"class":146},[129,382,189],{"class":146},[129,384,150],{"class":146},[129,386,387],{"class":146}," rich-cli\n",[129,389,390],{"class":131,"line":156},[129,391,172],{"emptyLinePlaceholder":171},[129,393,394],{"class":131,"line":168},[129,395,396],{"class":135},"# A later install that shares 'rich' reuses cached wheels\n",[129,398,399,401,403,405,407],{"class":131,"line":175},[129,400,143],{"class":142},[129,402,186],{"class":146},[129,404,189],{"class":146},[129,406,150],{"class":146},[129,408,409],{"class":146}," textual\n",[10,411,412,413,16,416,419],{},"pipx is a thin, pure-Python layer over ",[13,414,415],{},"venv",[13,417,418],{},"pip",". It is perfectly fast enough for interactive use, but it does not share a wheel cache across tool environments the way uv does, so each install does more independent work. If you install and reinstall many tools — for example, rebuilding a toolbox in a fresh container — the difference is noticeable.",[26,421,423],{"id":422},"upgrades-and-pinning","Upgrades and pinning",[10,425,426],{},"Both tools let you upgrade one CLI, upgrade everything, or pin to an exact version.",[120,428,430],{"className":122,"code":429,"language":124,"meta":125,"style":125},"# Upgrade a single tool\n$ pipx upgrade httpie\n$ uv tool upgrade httpie\n\n# Upgrade every installed tool\n$ pipx upgrade-all\n$ uv tool upgrade --all\n\n# Pin at install time\n$ pipx install 'httpie==3.2.2'\n$ uv tool install 'httpie==3.2.2'\n",[13,431,432,437,448,460,464,469,478,492,497,503,515],{"__ignoreMap":125},[129,433,434],{"class":131,"line":132},[129,435,436],{"class":135},"# Upgrade a single tool\n",[129,438,439,441,443,446],{"class":131,"line":139},[129,440,143],{"class":142},[129,442,147],{"class":146},[129,444,445],{"class":146}," upgrade",[129,447,165],{"class":146},[129,449,450,452,454,456,458],{"class":131,"line":156},[129,451,143],{"class":142},[129,453,186],{"class":146},[129,455,189],{"class":146},[129,457,445],{"class":146},[129,459,165],{"class":146},[129,461,462],{"class":131,"line":168},[129,463,172],{"emptyLinePlaceholder":171},[129,465,466],{"class":131,"line":175},[129,467,468],{"class":135},"# Upgrade every installed tool\n",[129,470,471,473,475],{"class":131,"line":181},[129,472,143],{"class":142},[129,474,147],{"class":146},[129,476,477],{"class":146}," upgrade-all\n",[129,479,480,482,484,486,488],{"class":131,"line":196},[129,481,143],{"class":142},[129,483,186],{"class":146},[129,485,189],{"class":146},[129,487,445],{"class":146},[129,489,491],{"class":490},"sj4cs"," --all\n",[129,493,495],{"class":131,"line":494},8,[129,496,172],{"emptyLinePlaceholder":171},[129,498,500],{"class":131,"line":499},9,[129,501,502],{"class":135},"# Pin at install time\n",[129,504,506,508,510,512],{"class":131,"line":505},10,[129,507,143],{"class":142},[129,509,147],{"class":146},[129,511,150],{"class":146},[129,513,514],{"class":146}," 'httpie==3.2.2'\n",[129,516,518,520,522,524,526],{"class":131,"line":517},11,[129,519,143],{"class":142},[129,521,186],{"class":146},[129,523,189],{"class":146},[129,525,150],{"class":146},[129,527,514],{"class":146},[10,529,530],{},"An upgrade re-resolves the tool's dependencies against its version constraints and rebuilds the environment. Pinning matters for reproducibility: if a CLI is part of your team's workflow, pin the version in your setup docs so everyone runs the same one. You can also inject extra packages into a tool's environment — useful when a CLI needs an optional plugin:",[120,532,534],{"className":122,"code":533,"language":124,"meta":125,"style":125},"# Add a plugin into an existing tool environment\n$ pipx inject mkdocs mkdocs-material\n$ uv tool install mkdocs --with mkdocs-material\n",[13,535,536,541,556],{"__ignoreMap":125},[129,537,538],{"class":131,"line":132},[129,539,540],{"class":135},"# Add a plugin into an existing tool environment\n",[129,542,543,545,547,550,553],{"class":131,"line":139},[129,544,143],{"class":142},[129,546,147],{"class":146},[129,548,549],{"class":146}," inject",[129,551,552],{"class":146}," mkdocs",[129,554,555],{"class":146}," mkdocs-material\n",[129,557,558,560,562,564,566,568,571],{"class":131,"line":156},[129,559,143],{"class":142},[129,561,186],{"class":146},[129,563,189],{"class":146},[129,565,150],{"class":146},[129,567,552],{"class":146},[129,569,570],{"class":490}," --with",[129,572,555],{"class":146},[10,574,575,576,579,580,583],{},"Note the small ergonomic difference: pipx ",[243,577,578],{},"injects"," into an already-installed tool as a separate step, while uv declares extras with ",[13,581,582],{},"--with"," at install time (re-running the install updates the set). Both end with the plugin importable inside the tool's isolated environment.",[26,585,587,590],{"id":586},"uv-tool-list-and-managing-whats-installed",[13,588,589],{},"uv tool list"," and managing what's installed",[10,592,593],{},"Listing and removing work the same way in both, which makes auditing your global toolbox easy.",[120,595,597],{"className":122,"code":596,"language":124,"meta":125,"style":125},"# What is installed, and which commands does each expose?\n$ uv tool list\nblack v24.10.0\n- black\n- blackd\nhttpie v3.2.4\n- http\n- https\n\n$ pipx list\n\n# Remove a tool and its environment\n$ uv tool uninstall black\n$ pipx uninstall black\n",[13,598,599,604,615,622,629,636,643,650,657,661,669,673,679,693],{"__ignoreMap":125},[129,600,601],{"class":131,"line":132},[129,602,603],{"class":135},"# What is installed, and which commands does each expose?\n",[129,605,606,608,610,612],{"class":131,"line":139},[129,607,143],{"class":142},[129,609,186],{"class":146},[129,611,189],{"class":146},[129,613,614],{"class":146}," list\n",[129,616,617,619],{"class":131,"line":156},[129,618,212],{"class":142},[129,620,621],{"class":146}," v24.10.0\n",[129,623,624,627],{"class":131,"line":168},[129,625,626],{"class":142},"-",[129,628,153],{"class":146},[129,630,631,633],{"class":131,"line":175},[129,632,626],{"class":142},[129,634,635],{"class":146}," blackd\n",[129,637,638,640],{"class":131,"line":181},[129,639,43],{"class":142},[129,641,642],{"class":146}," v3.2.4\n",[129,644,645,647],{"class":131,"line":196},[129,646,626],{"class":142},[129,648,649],{"class":146}," http\n",[129,651,652,654],{"class":131,"line":494},[129,653,626],{"class":142},[129,655,656],{"class":146}," https\n",[129,658,659],{"class":131,"line":499},[129,660,172],{"emptyLinePlaceholder":171},[129,662,663,665,667],{"class":131,"line":505},[129,664,143],{"class":142},[129,666,147],{"class":146},[129,668,614],{"class":146},[129,670,671],{"class":131,"line":517},[129,672,172],{"emptyLinePlaceholder":171},[129,674,676],{"class":131,"line":675},12,[129,677,678],{"class":135},"# Remove a tool and its environment\n",[129,680,682,684,686,688,691],{"class":131,"line":681},13,[129,683,143],{"class":142},[129,685,186],{"class":146},[129,687,189],{"class":146},[129,689,690],{"class":146}," uninstall",[129,692,153],{"class":146},[129,694,696,698,700,702],{"class":131,"line":695},14,[129,697,143],{"class":142},[129,699,147],{"class":146},[129,701,690],{"class":146},[129,703,153],{"class":146},[10,705,706,708,709,711,712,16,714,717,718,721,722,724,725,118],{},[13,707,589],{}," shows both the package version and every console script that package puts on your ",[13,710,23],{},", which is handy when a single distribution installs several commands (like ",[13,713,212],{},[13,715,716],{},"blackd","). One more uv-specific nicety: ",[13,719,720],{},"uv tool update-shell"," ensures the tool bin directory is on your ",[13,723,23],{},", the equivalent of pipx's ",[13,726,727],{},"pipx ensurepath",[26,729,731],{"id":730},"comparison-table","Comparison table",[733,734,735,755],"table",{},[736,737,738],"thead",{},[739,740,741,745,750],"tr",{},[742,743,744],"th",{},"Dimension",[742,746,747],{},[13,748,749],{},"uv tool",[742,751,752],{},[13,753,754],{},"pipx",[756,757,758,769,784,802,823,839,853,864,875,886],"tbody",{},[739,759,760,764,767],{},[761,762,763],"td",{},"Isolation model",[761,765,766],{},"One venv per tool",[761,768,766],{},[739,770,771,774,779],{},[761,772,773],{},"Install a tool",[761,775,776],{},[13,777,778],{},"uv tool install X",[761,780,781],{},[13,782,783],{},"pipx install X",[739,785,786,789,797],{},[761,787,788],{},"Run once, no install",[761,790,791,231,794],{},[13,792,793],{},"uvx X",[13,795,796],{},"uv tool run X",[761,798,799],{},[13,800,801],{},"pipx run X",[739,803,804,807,815],{},[761,805,806],{},"Upgrade one \u002F all",[761,808,809,231,812],{},[13,810,811],{},"uv tool upgrade X",[13,813,814],{},"--all",[761,816,817,231,820],{},[13,818,819],{},"pipx upgrade X",[13,821,822],{},"upgrade-all",[739,824,825,828,834],{},[761,826,827],{},"Add a plugin",[761,829,830,833],{},[13,831,832],{},"--with pkg"," at install",[761,835,836],{},[13,837,838],{},"pipx inject tool pkg",[739,840,841,844,848],{},[761,842,843],{},"List installed",[761,845,846],{},[13,847,589],{},[761,849,850],{},[13,851,852],{},"pipx list",[739,854,855,858,861],{},[761,856,857],{},"Shared wheel cache",[761,859,860],{},"Yes (global)",[761,862,863],{},"No",[739,865,866,869,872],{},[761,867,868],{},"Resolver",[761,870,871],{},"Rust, parallel",[761,873,874],{},"pip (pure Python)",[739,876,877,880,883],{},[761,878,879],{},"Scope of the tool",[761,881,882],{},"Full project + package manager",[761,884,885],{},"Install\u002Frun CLIs only",[739,887,888,891,894],{},[761,889,890],{},"Runtime dependency",[761,892,893],{},"Single static uv binary",[761,895,896],{},"Python + pip",[26,898,900],{"id":899},"when-each-wins","When each wins",[10,902,903,909,910,914],{},[37,904,905,906,908],{},"Reach for ",[13,907,749],{}," when"," you already use uv for project dependency management. Keeping one binary, one cache, and one mental model for both your projects and your global tools is a real simplification — the same uv you use in ",[221,911,913],{"href":912},"\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002F","uv for Python CLI dependency management"," also installs finished CLIs. It is also the fastest option for cold environments like CI runners and Docker images.",[10,916,917,921,922,118],{},[37,918,905,919,908],{},[13,920,754],{}," you want a small, focused, well-established tool that does exactly one thing. pipx has been the community standard for global CLI installs for years, it is packaged in most distributions, and it carries no expectation that you adopt a whole project workflow. If uv is not already in your stack, pipx is the lower-commitment choice. The end-to-end distribution story — building the tool and telling users to install it with pipx — lives in ",[221,923,925],{"href":924},"\u002Fproject-setup-dependency-management\u002Fpackaging-python-clis-for-distribution\u002Finstalling-and-distributing-clis-with-pipx\u002F","installing and distributing CLIs with pipx",[10,927,928],{},"For most teams the honest answer is \"whichever you already have.\" Both deliver the same isolation guarantee; the deciding factor is how much other tooling you want to standardize on.",[26,930,932],{"id":931},"production-notes","Production notes",[31,934,935,952,965,981,993],{},[34,936,937,940,941,944,945,16,948,951],{},[37,938,939],{},"Publishing advice should name a runnable installer."," When you document install steps for ",[243,942,943],{},"your"," CLI, offer both ",[13,946,947],{},"pipx install yourcli",[13,949,950],{},"uv tool install yourcli"," — users have one or the other, rarely both.",[34,953,954,957,958,345,961,964],{},[37,955,956],{},"CI: prefer the one-off runner."," In CI you usually want ",[13,959,960],{},"uvx ruff check",[13,962,963],{},"pipx run ruff check"," rather than a persistent install; the ephemeral environment is cached and there is no global state to clean up.",[34,966,967,972,973,975,976,345,978,980],{},[37,968,969,971],{},[13,970,23],{}," setup is a first-run gotcha."," Both tools install scripts into a bin directory that may not be on a fresh machine's ",[13,974,23],{},". Run ",[13,977,720],{},[13,979,727],{}," once and restart the shell.",[34,982,983,986,987,989,990,992],{},[37,984,985],{},"Pin tools your team depends on."," An unpinned ",[13,988,15],{},"\u002F",[13,991,19],{}," floats to the latest release; pin the version in onboarding docs to avoid \"works on my laptop\" drift.",[34,994,995,77,998,1001],{},[37,996,997],{},"Python version.",[13,999,1000],{},"uv tool install --python 3.12 X"," lets uv fetch and use a specific interpreter for the tool's environment; pipx relies on a Python already present on the system.",[26,1003,1005],{"id":1004},"related","Related",[31,1007,1008,1013,1019,1025],{},[34,1009,1010,1012],{},[221,1011,913],{"href":912}," — the parent guide covering uv end to end for CLI projects.",[34,1014,1015,1018],{},[221,1016,1017],{"href":924},"Installing and distributing CLIs with pipx"," — how to package a CLI so users can install it with pipx or uv.",[34,1020,1021,1024],{},[221,1022,1023],{"href":223},"Managing virtual environments for cross-platform CLIs"," — the isolation model that global tool installs are built on.",[34,1026,1027,1031],{},[221,1028,1030],{"href":1029},"\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002Fuv-init-vs-poetry-init-for-cli-tools\u002F","uv init vs poetry init for CLI tools"," — choosing a project bootstrapper before you ship the tool.",[1033,1034,1035],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":125,"searchDepth":139,"depth":139,"links":1037},[1038,1039,1040,1042,1043,1044,1046,1047,1048,1049],{"id":28,"depth":139,"text":29},{"id":98,"depth":139,"text":99},{"id":228,"depth":139,"text":1041},"uv tool install \u002F uvx vs pipx install \u002F pipx run",{"id":360,"depth":139,"text":361},{"id":422,"depth":139,"text":423},{"id":586,"depth":139,"text":1045},"uv tool list and managing what's installed",{"id":730,"depth":139,"text":731},{"id":899,"depth":139,"text":900},{"id":931,"depth":139,"text":932},{"id":1004,"depth":139,"text":1005},"2026-07-05","Compare uv tool install and pipx for installing Python CLIs globally: isolation, speed, upgrades, and when uvx or pipx run fits a one-off tool.","intermediate",false,"md",{},"\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002Fuv-tool-install-vs-pipx-for-clis",{"title":5,"description":1051},"project-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002Fuv-tool-install-vs-pipx-for-clis\u002Findex",[1060,754,1061,1062,1063],"uv","cli","packaging","distribution","hG8at5-bMoXI_3iTifAFGA40K1yF00vWqYGi0MNrPCs",[1066,1069,1072,1075,1078,1081,1084,1087,1090,1093,1096,1099,1102,1105,1108,1111,1114,1117,1120,1122,1125,1128,1131,1134,1137,1140,1143,1146,1149,1152,1155,1158,1161,1164,1167,1170,1173,1176,1179,1182,1185,1188,1191,1194,1197,1200,1203,1206,1208,1209,1212],{"path":1067,"title":1068},"\u002Fabout","About Python CLI Toolcraft",{"path":1070,"title":1071},"\u002Fadvanced-input-parsing-user-experience\u002Fadvanced-argument-validation-strategies","Advanced Argument Validation Strategies",{"path":1073,"title":1074},"\u002Fadvanced-input-parsing-user-experience\u002Fadvanced-argument-validation-strategies\u002Fparsing-nested-json-arguments-in-python-clis","Parsing Nested JSON Args in Python CLIs",{"path":1076,"title":1077},"\u002Fadvanced-input-parsing-user-experience\u002Ferror-handling-and-exit-codes\u002Fchoosing-exit-codes-for-cli-tools","Choosing Exit Codes for CLI Tools",{"path":1079,"title":1080},"\u002Fadvanced-input-parsing-user-experience\u002Ferror-handling-and-exit-codes\u002Ffriendly-error-messages-and-tracebacks","Friendly Error Messages and Tracebacks",{"path":1082,"title":1083},"\u002Fadvanced-input-parsing-user-experience\u002Ferror-handling-and-exit-codes","Error Handling and Exit Codes for CLIs",{"path":1085,"title":1086},"\u002Fadvanced-input-parsing-user-experience\u002Fhandling-configuration-files-env-vars\u002Fconfig-precedence-flags-env-files-defaults","Config Precedence: Flags, Env, Files, Defaults",{"path":1088,"title":1089},"\u002Fadvanced-input-parsing-user-experience\u002Fhandling-configuration-files-env-vars","Handling Config Files and Env Vars in CLIs",{"path":1091,"title":1092},"\u002Fadvanced-input-parsing-user-experience\u002Fhandling-configuration-files-env-vars\u002Floading-yaml-configs-safely-in-cli-apps","Loading YAML configs safely in CLI apps",{"path":1094,"title":1095},"\u002Fadvanced-input-parsing-user-experience","Advanced Input Parsing for Python CLIs",{"path":1097,"title":1098},"\u002Fadvanced-input-parsing-user-experience\u002Finteractive-terminal-ui-with-rich\u002Fadding-progress-bars-and-spinners-to-python-clis","Progress Bars and Spinners for Python CLIs",{"path":1100,"title":1101},"\u002Fadvanced-input-parsing-user-experience\u002Finteractive-terminal-ui-with-rich","Interactive Terminal UI with Rich",{"path":1103,"title":1104},"\u002Fadvanced-input-parsing-user-experience\u002Fshell-completion-for-python-clis\u002Fenabling-tab-completion-in-click-and-typer","Enabling Tab Completion in Click and Typer",{"path":1106,"title":1107},"\u002Fadvanced-input-parsing-user-experience\u002Fshell-completion-for-python-clis","Shell Completion for Python CLIs",{"path":1109,"title":1110},"\u002Fadvanced-input-parsing-user-experience\u002Fshell-completion-for-python-clis\u002Finstalling-shell-completion-for-bash-zsh-fish","Installing Shell Completion for bash, zsh, fish",{"path":1112,"title":1113},"\u002Fadvanced-input-parsing-user-experience\u002Fstructured-logging-for-cli-apps\u002Fadding-verbose-and-quiet-logging-flags","Adding Verbose and Quiet Logging Flags",{"path":1115,"title":1116},"\u002Fadvanced-input-parsing-user-experience\u002Fstructured-logging-for-cli-apps","Structured Logging for CLI Apps",{"path":1118,"title":1119},"\u002Fadvanced-input-parsing-user-experience\u002Fstructured-logging-for-cli-apps\u002Fstructured-json-logging-in-python-clis","Structured JSON Logging in Python CLIs",{"path":989,"title":1121},"Python CLI Toolcraft",{"path":1123,"title":1124},"\u002Fmodern-python-cli-frameworks-architecture\u002Fcli-startup-performance-and-lazy-loading","CLI Startup Performance and Lazy Loading",{"path":1126,"title":1127},"\u002Fmodern-python-cli-frameworks-architecture\u002Fcli-startup-performance-and-lazy-loading\u002Flazy-loading-subcommands-for-faster-startup","Lazy Loading Subcommands for Faster Startup",{"path":1129,"title":1130},"\u002Fmodern-python-cli-frameworks-architecture\u002Fcli-startup-performance-and-lazy-loading\u002Fprofiling-python-cli-startup-time","Profiling Python CLI Startup Time",{"path":1132,"title":1133},"\u002Fmodern-python-cli-frameworks-architecture\u002Fcommand-line-parsing-with-argparse\u002Fargparse-subparsers-for-subcommands","argparse Subparsers for Subcommands",{"path":1135,"title":1136},"\u002Fmodern-python-cli-frameworks-architecture\u002Fcommand-line-parsing-with-argparse","Command-Line Parsing with argparse",{"path":1138,"title":1139},"\u002Fmodern-python-cli-frameworks-architecture\u002Fcommand-line-parsing-with-argparse\u002Fmigrating-from-argparse-to-typer","Migrating from argparse to Typer",{"path":1141,"title":1142},"\u002Fmodern-python-cli-frameworks-architecture","Python CLI Frameworks and Architecture",{"path":1144,"title":1145},"\u002Fmodern-python-cli-frameworks-architecture\u002Fplugin-architectures-for-extensible-clis","Plugin Architectures for Extensible CLIs",{"path":1147,"title":1148},"\u002Fmodern-python-cli-frameworks-architecture\u002Fstructuring-multi-command-python-clis\u002Fbest-practices-for-python-cli-entry-points","Best practices for Python CLI entry points",{"path":1150,"title":1151},"\u002Fmodern-python-cli-frameworks-architecture\u002Fstructuring-multi-command-python-clis\u002Fhow-to-structure-a-large-python-cli-project","Structuring a Large Python CLI Project",{"path":1153,"title":1154},"\u002Fmodern-python-cli-frameworks-architecture\u002Fstructuring-multi-command-python-clis","Structuring Multi-Command Python CLIs",{"path":1156,"title":1157},"\u002Fmodern-python-cli-frameworks-architecture\u002Fstructuring-multi-command-python-clis\u002Fsharing-state-with-click-context-objects","Sharing State with Click Context Objects",{"path":1159,"title":1160},"\u002Fmodern-python-cli-frameworks-architecture\u002Ftyper-vs-click-when-to-use-each\u002Fbuilding-a-cli-with-subcommands-in-click","Building a CLI with subcommands in Click",{"path":1162,"title":1163},"\u002Fmodern-python-cli-frameworks-architecture\u002Ftyper-vs-click-when-to-use-each","Typer vs Click: When to Use Each",{"path":1165,"title":1166},"\u002Fmodern-python-cli-frameworks-architecture\u002Ftyper-vs-click-when-to-use-each\u002Ftyper-callback-functions-explained","Typer callback functions explained",{"path":1168,"title":1169},"\u002Fproject-setup-dependency-management\u002Fcli-project-scaffolding-with-cookiecutter","CLI Project Scaffolding with Cookiecutter",{"path":1171,"title":1172},"\u002Fproject-setup-dependency-management","Project Setup & Dependency Management",{"path":1174,"title":1175},"\u002Fproject-setup-dependency-management\u002Fmanaging-cli-versioning-changelogs\u002Fautomating-changelogs-with-conventional-commits","Automating Changelogs with Conventional Commits",{"path":1177,"title":1178},"\u002Fproject-setup-dependency-management\u002Fmanaging-cli-versioning-changelogs","Managing CLI Versioning & Changelogs",{"path":1180,"title":1181},"\u002Fproject-setup-dependency-management\u002Fpackaging-python-clis-for-distribution\u002Fbuilding-wheels-and-sdists-for-python-clis","Building Wheels and sdists for Python CLIs",{"path":1183,"title":1184},"\u002Fproject-setup-dependency-management\u002Fpackaging-python-clis-for-distribution","Packaging Python CLIs for Distribution",{"path":1186,"title":1187},"\u002Fproject-setup-dependency-management\u002Fpackaging-python-clis-for-distribution\u002Finstalling-and-distributing-clis-with-pipx","Installing and Distributing CLIs with pipx",{"path":1189,"title":1190},"\u002Fproject-setup-dependency-management\u002Fpackaging-python-clis-for-distribution\u002Fpublishing-a-python-cli-to-pypi","Publishing a Python CLI to PyPI",{"path":1192,"title":1193},"\u002Fproject-setup-dependency-management\u002Fpoetry-workflows-for-cli-development","Poetry Workflows for CLI Development",{"path":1195,"title":1196},"\u002Fproject-setup-dependency-management\u002Fpoetry-workflows-for-cli-development\u002Fpoetry-entry-points-and-scripts-for-clis","Poetry Entry Points and Scripts for CLIs",{"path":1198,"title":1199},"\u002Fproject-setup-dependency-management\u002Fpre-commit-hooks-for-cli-projects","Pre-commit Hooks for CLI Projects",{"path":1201,"title":1202},"\u002Fproject-setup-dependency-management\u002Fpre-commit-hooks-for-cli-projects\u002Fsetting-up-pre-commit-for-python-cli-repos","Setting up pre-commit for Python CLI repos",{"path":1204,"title":1205},"\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management","uv for Python CLI Dependency Management",{"path":1207,"title":1030},"\u002Fproject-setup-dependency-management\u002Fuv-for-python-cli-dependency-management\u002Fuv-init-vs-poetry-init-for-cli-tools",{"path":1056,"title":5},{"path":1210,"title":1211},"\u002Fproject-setup-dependency-management\u002Fvirtual-environments-isolation-best-practices","Python CLI Env Isolation Best Practices",{"path":1213,"title":1214},"\u002Fproject-setup-dependency-management\u002Fvirtual-environments-isolation-best-practices\u002Fmanaging-virtual-environments-for-cross-platform-clis","Managing Python CLI Virtual Environments",1783281867200]