Skip to main content

uv_cli/
lib.rs

1use std::ffi::OsString;
2use std::ops::{Deref, DerefMut};
3use std::path::{Path, PathBuf};
4use std::str::FromStr;
5
6use anyhow::{Result, anyhow};
7use clap::builder::styling::{AnsiColor, Effects, Style};
8use clap::builder::{PossibleValue, Styles, TypedValueParser};
9use clap::error::ErrorKind;
10use clap::{Args, Parser, Subcommand};
11use clap::{ValueEnum, ValueHint};
12
13use uv_audit::VulnerabilityServiceFormat;
14use uv_auth::Service;
15use uv_cache::CacheArgs;
16use uv_configuration::RequirementsInput;
17use uv_configuration::{
18    AddBoundsKind, AnnotationStyle, AuditOutputFormat, AuthorFrom, ColorChoice,
19    ExcludeNewerPackageEntry, ExportFormat, ForkStrategy, IndexStrategy, KeyringProviderType,
20    ListFormat, PackageNameSpecifier, PipCompileFormat, PipInstallFormat, PrereleaseMode,
21    PrereleasePackageEntry, ProjectBuildBackend, PythonListFormat, ResolutionMode, SyncFormat,
22    TargetTriple, TreeFormat, TrustedHost, TrustedPublishing, VersionBump, VersionBumpSpec,
23    VersionControlSystem, VersionFormat,
24};
25use uv_distribution_types::{
26    ConfigSettingEntry, ConfigSettingPackageEntry, ExcludeNewerOverride, Index, IndexName,
27    IndexSourceError, IndexUrl, Origin, PipExtraIndex, PipFindLinks, PipIndex,
28};
29use uv_normalize::{ExtraName, GroupName, PackageName, PipGroupName};
30use uv_pep508::{MarkerTree, Requirement, VerbatimUrl};
31use uv_preview::{MaybePreviewFeature, PreviewFeature};
32use uv_pypi_types::VerbatimParsedUrl;
33use uv_python_types::{PythonDownloads, PythonPreference, PythonVersion};
34use uv_redacted::DisplaySafeUrl;
35use uv_settings::PythonInstallMirrors;
36use uv_static::EnvVars;
37use uv_torch::TorchMode;
38use uv_warnings::warn_user_once;
39
40pub mod comma;
41pub mod compat;
42pub mod options;
43pub mod settings;
44pub mod version;
45
46#[derive(Debug, Default, Clone, Copy, clap::ValueEnum)]
47pub enum CacheSizeOutputFormat {
48    /// Display a human-readable size in terminals and raw bytes otherwise.
49    #[default]
50    Auto,
51    /// Display the cache size in a human-readable format.
52    Human,
53    /// Display the cache size in raw bytes.
54    Machine,
55}
56
57fn extra_name_with_clap_error(arg: &str) -> Result<ExtraName> {
58    ExtraName::from_str(arg).map_err(|_err| {
59        anyhow!(
60            "Extra names must start and end with a letter or digit and may only \
61            contain -, _, ., and alphanumeric characters"
62        )
63    })
64}
65
66// Configures Clap v3-style help menu colors
67const STYLES: Styles = Styles::styled()
68    .header(AnsiColor::Green.on_default().effects(Effects::BOLD))
69    .usage(AnsiColor::Green.on_default().effects(Effects::BOLD))
70    .literal(AnsiColor::Cyan.on_default().effects(Effects::BOLD))
71    .placeholder(AnsiColor::Cyan.on_default());
72
73#[derive(Parser)]
74#[command(name = "uv", author, long_version = crate::version::uv_self_version())]
75#[command(about = "An extremely fast Python package manager.")]
76#[command(
77    after_help = "Use `uv help` for more details.",
78    after_long_help = "",
79    disable_help_flag = true,
80    disable_help_subcommand = true,
81    disable_version_flag = true
82)]
83#[command(styles=STYLES)]
84pub struct Cli {
85    #[command(subcommand)]
86    pub command: Box<Commands>,
87
88    #[command(flatten)]
89    pub top_level: TopLevelArgs,
90}
91
92#[derive(Parser)]
93#[command(disable_help_flag = true, disable_version_flag = true)]
94pub struct TopLevelArgs {
95    #[command(flatten)]
96    pub cache_args: Box<CacheArgs>,
97
98    #[command(flatten)]
99    pub global_args: Box<GlobalArgs>,
100
101    /// The path to a `uv.toml` file to use for configuration.
102    ///
103    /// While uv configuration can be included in a `pyproject.toml` file, it is
104    /// not allowed in this context.
105    #[arg(
106        global = true,
107        long,
108        env = EnvVars::UV_CONFIG_FILE,
109        help_heading = "Global options",
110        value_hint = ValueHint::FilePath,
111    )]
112    pub config_file: Option<PathBuf>,
113
114    /// Avoid discovering configuration files (`pyproject.toml`, `uv.toml`).
115    ///
116    /// Normally, configuration files are discovered in the current directory,
117    /// parent directories, or user configuration directories.
118    #[arg(global = true, long, env = EnvVars::UV_NO_CONFIG, value_parser = clap::builder::BoolishValueParser::new(), help_heading = "Global options")]
119    pub no_config: bool,
120
121    /// Display the concise help for this command.
122    #[arg(global = true, short, long, action = clap::ArgAction::HelpShort, help_heading = "Global options")]
123    help: Option<bool>,
124
125    /// Display the uv version.
126    #[arg(short = 'V', long, action = clap::ArgAction::Version)]
127    version: Option<bool>,
128}
129
130#[derive(Parser, Debug, Clone)]
131#[command(next_help_heading = "Global options", next_display_order = 1000)]
132pub struct GlobalArgs {
133    #[arg(
134        global = true,
135        long,
136        help_heading = "Python options",
137        display_order = 700,
138        env = EnvVars::UV_PYTHON_PREFERENCE,
139        hide = true
140    )]
141    pub python_preference: Option<PythonPreference>,
142
143    /// Require use of uv-managed Python versions [env: UV_MANAGED_PYTHON=]
144    ///
145    /// By default, uv prefers using Python versions it manages. However, it will use system Python
146    /// versions if a uv-managed Python is not installed. This option disables use of system Python
147    /// versions.
148    #[arg(
149        global = true,
150        long,
151        help_heading = "Python options",
152        overrides_with = "no_managed_python"
153    )]
154    pub managed_python: bool,
155
156    /// Disable use of uv-managed Python versions [env: UV_NO_MANAGED_PYTHON=]
157    ///
158    /// Instead, uv will search for a suitable Python version on the system.
159    #[arg(
160        global = true,
161        long,
162        help_heading = "Python options",
163        overrides_with = "managed_python"
164    )]
165    pub no_managed_python: bool,
166
167    #[expect(clippy::doc_markdown)]
168    /// Allow automatically downloading Python when required. [env: "UV_PYTHON_DOWNLOADS=auto"]
169    #[arg(global = true, long, help_heading = "Python options", hide = true)]
170    pub allow_python_downloads: bool,
171
172    #[expect(clippy::doc_markdown)]
173    /// Disable automatic downloads of Python. [env: "UV_PYTHON_DOWNLOADS=never"]
174    #[arg(global = true, long, help_heading = "Python options")]
175    pub no_python_downloads: bool,
176
177    /// Deprecated option for configuring automatic Python downloads.
178    #[arg(global = true, long, hide = true)]
179    pub python_fetch: Option<PythonDownloads>,
180
181    /// Use quiet output.
182    ///
183    /// Repeating this option, e.g., `-qq`, will enable a silent mode in which
184    /// uv will write no output to stdout.
185    #[arg(global = true, action = clap::ArgAction::Count, long, short, conflicts_with = "verbose")]
186    pub quiet: u8,
187
188    /// Use verbose output.
189    ///
190    /// You can configure fine-grained logging using the `RUST_LOG` environment variable.
191    /// (<https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives>)
192    #[arg(global = true, action = clap::ArgAction::Count, long, short, conflicts_with = "quiet")]
193    pub verbose: u8,
194
195    /// Disable colors.
196    ///
197    /// Provided for compatibility with `pip`, use `--color` instead.
198    #[arg(global = true, long, hide = true, conflicts_with = "color")]
199    pub no_color: bool,
200
201    /// Control the use of color in output.
202    ///
203    /// By default, uv will automatically detect support for colors when writing to a terminal.
204    #[arg(
205        global = true,
206        long,
207        value_enum,
208        conflicts_with = "no_color",
209        value_name = "COLOR_CHOICE"
210    )]
211    pub color: Option<ColorChoice>,
212
213    /// (Deprecated: use `--system-certs` instead.) Whether to load TLS certificates from the
214    /// platform's native certificate store [env: UV_NATIVE_TLS=]
215    ///
216    /// By default, uv uses bundled Mozilla root certificates. When enabled, this flag loads
217    /// certificates from the platform's native certificate store instead.
218    ///
219    /// This is equivalent to `--system-certs`.
220    #[arg(global = true, long, value_parser = clap::builder::BoolishValueParser::new(), overrides_with_all = ["no_native_tls", "system_certs", "no_system_certs"], hide = true)]
221    pub native_tls: bool,
222
223    #[arg(global = true, long, overrides_with_all = ["native_tls", "system_certs", "no_system_certs"], hide = true)]
224    pub no_native_tls: bool,
225
226    /// Whether to load TLS certificates from the platform's native certificate store [env: UV_SYSTEM_CERTS=]
227    ///
228    /// By default, uv uses bundled Mozilla root certificates, which improves portability and
229    /// performance (especially on macOS).
230    ///
231    /// However, in some cases, you may want to use the platform's native certificate store,
232    /// especially if you're relying on a corporate trust root (e.g., for a mandatory proxy) that's
233    /// included in your system's certificate store.
234    #[arg(global = true, long, value_parser = clap::builder::BoolishValueParser::new(), overrides_with_all = ["no_system_certs", "native_tls", "no_native_tls"])]
235    pub system_certs: bool,
236
237    #[arg(global = true, long, overrides_with_all = ["system_certs", "native_tls", "no_native_tls"], hide = true)]
238    pub no_system_certs: bool,
239
240    /// Disable network access [env: UV_OFFLINE=]
241    ///
242    /// When disabled, uv will only use locally cached data and locally available files.
243    #[arg(global = true, long, overrides_with("no_offline"))]
244    pub offline: bool,
245
246    #[arg(global = true, long, overrides_with("offline"), hide = true)]
247    pub no_offline: bool,
248
249    /// Allow insecure connections to a host.
250    ///
251    /// Can be provided multiple times.
252    ///
253    /// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
254    /// `localhost:8080`), or a URL (e.g., `https://localhost`).
255    ///
256    /// WARNING: Hosts included in this list will not be verified against the system's certificate
257    /// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
258    /// bypasses SSL verification and could expose you to MITM attacks.
259    #[arg(
260        global = true,
261        long,
262        alias = "trusted-host",
263        env = EnvVars::UV_INSECURE_HOST,
264        value_delimiter = ' ',
265        value_parser = parse_insecure_host,
266        value_hint = ValueHint::Url,
267    )]
268    pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
269
270    /// Whether to enable all experimental preview features [env: UV_PREVIEW=]
271    ///
272    /// Preview features may change without warning.
273    #[arg(global = true, long, hide = true, value_parser = clap::builder::BoolishValueParser::new(), overrides_with("no_preview"))]
274    pub preview: bool,
275
276    #[arg(global = true, long, overrides_with("preview"), hide = true)]
277    pub no_preview: bool,
278
279    /// Enable experimental preview features.
280    ///
281    /// Preview features may change without warning.
282    ///
283    /// Use comma-separated values or pass multiple times to enable multiple features.
284    #[arg(
285        global = true,
286        long = "preview-features",
287        env = EnvVars::UV_PREVIEW_FEATURES,
288        value_delimiter = ',',
289        hide = true,
290        alias = "preview-feature",
291    )]
292    pub preview_features: Vec<MaybePreviewFeature>,
293
294    /// Avoid discovering a `pyproject.toml` or `uv.toml` file [env: UV_ISOLATED=]
295    ///
296    /// Normally, configuration files are discovered in the current directory,
297    /// parent directories, or user configuration directories.
298    ///
299    /// This option is deprecated in favor of `--no-config`.
300    #[arg(global = true, long, hide = true, value_parser = clap::builder::BoolishValueParser::new())]
301    pub isolated: bool,
302
303    /// Show the resolved settings for the current command.
304    ///
305    /// This option is used for debugging and development purposes.
306    #[arg(global = true, long, hide = true)]
307    pub show_settings: bool,
308
309    /// Hide all progress outputs [env: UV_NO_PROGRESS=]
310    ///
311    /// For example, spinners or progress bars.
312    #[arg(global = true, long, value_parser = clap::builder::BoolishValueParser::new())]
313    pub no_progress: bool,
314
315    /// Skip writing `uv` installer metadata files (e.g., `INSTALLER`, `REQUESTED`, and
316    /// `direct_url.json`) to site-packages `.dist-info` directories [env: UV_NO_INSTALLER_METADATA=]
317    #[arg(global = true, long, hide = true, value_parser = clap::builder::BoolishValueParser::new())]
318    pub no_installer_metadata: bool,
319
320    /// Change to the given directory prior to running the command.
321    ///
322    /// Relative paths are resolved with the given directory as the base.
323    ///
324    /// See `--project` to only change the project root directory.
325    #[arg(global = true, long, env = EnvVars::UV_WORKING_DIR, value_hint = ValueHint::DirPath)]
326    pub directory: Option<PathBuf>,
327
328    /// Discover a project in the given directory.
329    ///
330    /// All `pyproject.toml`, `uv.toml`, and `.python-version` files will be discovered by walking
331    /// up the directory tree from the project root, as will the project's virtual environment
332    /// (`.venv`).
333    ///
334    /// Other command-line arguments (such as relative paths) will be resolved relative
335    /// to the current working directory.
336    ///
337    /// See `--directory` to change the working directory entirely.
338    ///
339    /// This setting has no effect when used in the `uv pip` interface.
340    #[arg(global = true, long, env = EnvVars::UV_PROJECT, value_hint = ValueHint::DirPath)]
341    pub project: Option<PathBuf>,
342}
343
344#[derive(Subcommand)]
345pub enum Commands {
346    /// Manage authentication.
347    #[command(
348        after_help = "Use `uv help auth` for more details.",
349        after_long_help = ""
350    )]
351    Auth(AuthNamespace),
352
353    /// Manage Python projects.
354    #[command(flatten)]
355    Project(Box<ProjectCommand>),
356
357    /// Run and install commands provided by Python packages.
358    #[command(
359        after_help = "Use `uv help tool` for more details.",
360        after_long_help = ""
361    )]
362    Tool(ToolNamespace),
363
364    /// Manage Python versions and installations
365    ///
366    /// Generally, uv first searches for Python in a virtual environment, either active or in a
367    /// `.venv` directory in the current working directory or any parent directory. If a virtual
368    /// environment is not required, uv will then search for a Python interpreter. Python
369    /// interpreters are found by searching for Python executables in the `PATH` environment
370    /// variable.
371    ///
372    /// On Windows, the registry is also searched for Python executables.
373    ///
374    /// By default, uv will download Python if a version cannot be found. This behavior can be
375    /// disabled with the `--no-python-downloads` flag or the `python-downloads` setting.
376    ///
377    /// The `--python` option allows requesting a different interpreter.
378    ///
379    /// The following Python version request formats are supported:
380    ///
381    /// - `<version>` e.g. `3`, `3.12`, `3.12.3`
382    /// - `<version-specifier>` e.g. `>=3.12,<3.13`
383    /// - `<version><short-variant>` (e.g., `3.13t`, `3.12.0d`)
384    /// - `<version>+<variant>` (e.g., `3.13+freethreaded`, `3.12.0+debug`)
385    /// - `<implementation>` e.g. `cpython` or `cp`
386    /// - `<implementation>@<version>` e.g. `cpython@3.12`
387    /// - `<implementation><version>` e.g. `cpython3.12` or `cp312`
388    /// - `<implementation><version-specifier>` e.g. `cpython>=3.12,<3.13`
389    /// - `<implementation>-<version>-<os>-<arch>-<libc>` e.g. `cpython-3.12.3-macos-aarch64-none`
390    ///
391    /// Additionally, a specific system Python interpreter can often be requested with:
392    ///
393    /// - `<executable-path>` e.g. `/opt/homebrew/bin/python3`
394    /// - `<executable-name>` e.g. `mypython3`
395    /// - `<install-dir>` e.g. `/some/environment/`
396    ///
397    /// When the `--python` option is used, normal discovery rules apply but discovered interpreters
398    /// are checked for compatibility with the request, e.g., if `pypy` is requested, uv will first
399    /// check if the virtual environment contains a PyPy interpreter then check if each executable
400    /// in the path is a PyPy interpreter.
401    ///
402    /// uv supports discovering CPython, PyPy, and GraalPy interpreters. Unsupported interpreters
403    /// will be skipped during discovery. If an unsupported interpreter implementation is requested,
404    /// uv will exit with an error.
405    #[clap(verbatim_doc_comment)]
406    #[command(
407        after_help = "Use `uv help python` for more details.",
408        after_long_help = ""
409    )]
410    Python(PythonNamespace),
411    /// Manage Python packages with a pip-compatible interface.
412    #[command(
413        after_help = "Use `uv help pip` for more details.",
414        after_long_help = ""
415    )]
416    Pip(PipNamespace),
417    /// Create a virtual environment.
418    ///
419    /// By default, creates a virtual environment named `.venv` in the working
420    /// directory. An alternative path may be provided positionally.
421    ///
422    /// If in a project, the default environment name can be changed with
423    /// the `UV_PROJECT_ENVIRONMENT` environment variable; this only applies
424    /// when run from the project root directory.
425    ///
426    /// If a virtual environment exists at the target path, it will be removed
427    /// and a new, empty virtual environment will be created.
428    ///
429    /// When using uv, the virtual environment does not need to be activated. uv
430    /// will find a virtual environment (named `.venv`) in the working directory
431    /// or any parent directories.
432    #[command(
433        alias = "virtualenv",
434        alias = "v",
435        after_help = "Use `uv help venv` for more details.",
436        after_long_help = ""
437    )]
438    Venv(VenvArgs),
439    /// Build Python packages into source distributions and wheels.
440    ///
441    /// `uv build` accepts a path to a directory or source distribution,
442    /// which defaults to the current working directory.
443    ///
444    /// By default, if passed a directory, `uv build` will build a source
445    /// distribution ("sdist") from the source directory, and a binary
446    /// distribution ("wheel") from the source distribution.
447    ///
448    /// `uv build --sdist` can be used to build only the source distribution,
449    /// `uv build --wheel` can be used to build only the binary distribution,
450    /// and `uv build --sdist --wheel` can be used to build both distributions
451    /// from source.
452    ///
453    /// If passed a source distribution, `uv build --wheel` will build a wheel
454    /// from the source distribution.
455    #[command(
456        after_help = "Use `uv help build` for more details.",
457        after_long_help = ""
458    )]
459    Build(BuildArgs),
460    /// Upload distributions to an index.
461    Publish(PublishArgs),
462    /// Inspect uv workspaces.
463    #[command(
464        after_help = "Use `uv help workspace` for more details.",
465        after_long_help = ""
466    )]
467    Workspace(WorkspaceNamespace),
468    /// The implementation of the build backend.
469    ///
470    /// These commands are not directly exposed to the user, instead users invoke their build
471    /// frontend (PEP 517) which calls the Python shims which calls back into uv with this method.
472    #[command(hide = true)]
473    BuildBackend {
474        #[command(subcommand)]
475        command: BuildBackendCommand,
476    },
477    /// Manage uv's cache.
478    #[command(
479        after_help = "Use `uv help cache` for more details.",
480        after_long_help = ""
481    )]
482    Cache(CacheNamespace),
483    /// Manage the uv executable.
484    #[command(name = "self")]
485    Self_(SelfNamespace),
486    /// Clear the cache, removing all entries or those linked to specific packages.
487    #[command(hide = true)]
488    Clean(CleanArgs),
489    /// Generate shell completion
490    #[command(alias = "--generate-shell-completion", hide = true)]
491    GenerateShellCompletion(GenerateShellCompletionArgs),
492    /// Display documentation for a command.
493    // To avoid showing the global options when displaying help for the help command, we are
494    // responsible for maintaining the options using the `after_help`.
495    #[command(help_template = "\
496{about-with-newline}
497{usage-heading} {usage}{after-help}
498",
499        after_help = format!("\
500{heading}Options:{heading:#}
501  {option}--no-pager{option:#} Disable pager when printing help
502",
503            heading = Style::new().bold().underline(),
504            option = Style::new().bold(),
505        ),
506    )]
507    Help(HelpArgs),
508}
509
510#[derive(Args, Debug)]
511pub struct HelpArgs {
512    /// Disable pager when printing help
513    #[arg(long)]
514    pub no_pager: bool,
515
516    #[arg(value_hint = ValueHint::Other)]
517    pub command: Option<Vec<String>>,
518}
519
520#[derive(Args)]
521#[command(group = clap::ArgGroup::new("operation"))]
522pub struct VersionArgs {
523    /// Set the project version to this value
524    ///
525    /// To update the project using semantic versioning components instead, use `--bump`.
526    #[arg(group = "operation", value_hint = ValueHint::Other)]
527    value: Option<String>,
528
529    /// Update the project version using the given semantics
530    ///
531    /// This flag can be passed multiple times.
532    #[arg(group = "operation", long, value_name = "BUMP[=VALUE]", value_parser = VersionBumpSpecValueParser)]
533    bump: Vec<VersionBumpSpec>,
534
535    /// Don't write a new version to the `pyproject.toml`
536    ///
537    /// Instead, the version will be displayed.
538    #[arg(long)]
539    dry_run: bool,
540
541    /// Only show the version
542    ///
543    /// By default, uv will show the project name before the version.
544    #[arg(long)]
545    short: bool,
546
547    /// The format of the output
548    #[arg(long, value_enum, default_value = "text")]
549    output_format: VersionFormat,
550
551    /// Avoid syncing the virtual environment after re-locking the project [env: UV_NO_SYNC=]
552    #[arg(long)]
553    no_sync: bool,
554
555    /// Prefer the active virtual environment over the project's virtual environment.
556    ///
557    /// If the project virtual environment is active or no virtual environment is active, this has
558    /// no effect.
559    #[arg(long, overrides_with = "no_active")]
560    active: bool,
561
562    /// Prefer project's virtual environment over an active environment.
563    ///
564    /// This is the default behavior.
565    #[arg(long, overrides_with = "active", hide = true)]
566    no_active: bool,
567
568    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
569    ///
570    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
571    /// uv will exit with an error.
572    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
573    locked: bool,
574
575    /// Disable locked mode, overriding `UV_LOCKED`.
576    #[arg(long, overrides_with = "locked", hide = true)]
577    no_locked: bool,
578
579    /// Update the version without re-locking the project [env: UV_FROZEN=]
580    ///
581    /// The project environment will not be synced.
582    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
583    frozen: bool,
584
585    /// Disable frozen mode, overriding `UV_FROZEN`.
586    #[arg(long, overrides_with = "frozen", hide = true)]
587    no_frozen: bool,
588
589    #[command(flatten)]
590    installer: ResolverInstallerArgs,
591
592    #[command(flatten)]
593    build: BuildOptionsArgs,
594
595    #[command(flatten)]
596    refresh: RefreshArgs,
597
598    /// Update the version of a specific package in the workspace.
599    #[arg(long, conflicts_with = "isolated", value_hint = ValueHint::Other)]
600    package: Option<PackageName>,
601
602    /// The Python interpreter to use for resolving and syncing.
603    ///
604    /// See `uv help python` for details on Python discovery and supported request formats.
605    #[arg(
606        long,
607        short,
608        env = EnvVars::UV_PYTHON,
609        verbatim_doc_comment,
610        help_heading = "Python options",
611        value_hint = ValueHint::Other,
612    )]
613    python: Option<Maybe<String>>,
614}
615
616#[derive(Clone, Debug)]
617struct VersionBumpSpecValueParser;
618
619impl TypedValueParser for VersionBumpSpecValueParser {
620    type Value = VersionBumpSpec;
621
622    fn parse_ref(
623        &self,
624        command: &clap::Command,
625        _arg: Option<&clap::Arg>,
626        value: &std::ffi::OsStr,
627    ) -> Result<Self::Value, clap::Error> {
628        let raw = value.to_str().ok_or_else(|| {
629            command.clone().error(
630                ErrorKind::InvalidUtf8,
631                "`--bump` values must be valid UTF-8",
632            )
633        })?;
634
635        VersionBumpSpec::from_str(raw)
636            .map_err(|message| command.clone().error(ErrorKind::InvalidValue, message))
637    }
638
639    fn possible_values(&self) -> Option<Box<dyn Iterator<Item = PossibleValue> + '_>> {
640        Some(Box::new(
641            VersionBump::value_variants()
642                .iter()
643                .filter_map(ValueEnum::to_possible_value),
644        ))
645    }
646}
647
648#[derive(Args)]
649pub struct SelfNamespace {
650    #[command(subcommand)]
651    pub command: SelfCommand,
652}
653
654#[derive(Subcommand)]
655pub enum SelfCommand {
656    /// Update uv.
657    Update(SelfUpdateArgs),
658    /// Display uv's version
659    Version {
660        /// Only print the version
661        #[arg(long)]
662        short: bool,
663        #[arg(long, value_enum, default_value = "text")]
664        output_format: VersionFormat,
665    },
666}
667
668#[derive(Args, Debug)]
669pub struct SelfUpdateArgs {
670    /// Update to the specified version. If not provided, uv will update to the latest version.
671    #[arg(value_hint = ValueHint::Other)]
672    pub target_version: Option<String>,
673
674    /// A GitHub token for authentication.
675    /// A token is not required but can be used to reduce the chance of encountering rate limits.
676    #[arg(long, env = EnvVars::UV_GITHUB_TOKEN, value_hint = ValueHint::Other)]
677    pub token: Option<String>,
678
679    /// Run without performing the update.
680    #[arg(long)]
681    pub dry_run: bool,
682}
683
684#[derive(Args)]
685pub struct CacheNamespace {
686    #[command(subcommand)]
687    pub command: CacheCommand,
688}
689
690#[derive(Subcommand)]
691pub enum CacheCommand {
692    /// Clear the cache, removing all entries or those linked to specific packages.
693    #[command(alias = "clear")]
694    Clean(CleanArgs),
695    /// Prune dangling cache entries and cached environments.
696    Prune(PruneArgs),
697    /// Show the cache directory.
698    ///
699    /// By default, the cache is stored in `$XDG_CACHE_HOME/uv` or `$HOME/.cache/uv` on Unix and
700    /// `%LOCALAPPDATA%\uv\cache` on Windows.
701    ///
702    /// When `--no-cache` is used, the cache is stored in a temporary directory and discarded when
703    /// the process exits.
704    ///
705    /// An alternative cache directory may be specified via the `cache-dir` setting, the
706    /// `--cache-dir` option, or the `$UV_CACHE_DIR` environment variable.
707    ///
708    /// Note that it is important for performance for the cache directory to be located on the same
709    /// file system as the Python environment uv is operating on.
710    Dir,
711    /// Show the cache size.
712    ///
713    /// Displays the total size of the cache directory. This includes all downloaded and built
714    /// wheels, source distributions, and other cached data. By default, displays a human-readable
715    /// size when the output is a terminal and raw bytes otherwise.
716    Size(SizeArgs),
717}
718
719#[derive(Args, Debug)]
720pub struct CleanArgs {
721    /// The packages to remove from the cache.
722    #[arg(value_hint = ValueHint::Other)]
723    pub package: Vec<PackageName>,
724
725    /// Force removal of the cache, ignoring in-use checks.
726    ///
727    /// By default, `uv cache clean` will block until no process is reading the cache. When
728    /// `--force` is used, `uv cache clean` will proceed without taking a lock.
729    #[arg(long)]
730    pub force: bool,
731}
732
733#[derive(Args, Debug)]
734pub struct PruneArgs {
735    /// Optimize the cache for persistence in a continuous integration environment, like GitHub
736    /// Actions.
737    ///
738    /// By default, uv caches both the wheels that it builds from source and the pre-built wheels
739    /// that it downloads directly, to enable high-performance package installation. In some
740    /// scenarios, though, persisting pre-built wheels may be undesirable. For example, in GitHub
741    /// Actions, it's faster to omit pre-built wheels from the cache and instead have re-download
742    /// them on each run. However, it typically _is_ faster to cache wheels that are built from
743    /// source, since the wheel building process can be expensive, especially for extension
744    /// modules.
745    ///
746    /// In `--ci` mode, uv will prune any pre-built wheels from the cache, but retain any wheels
747    /// that were built from source.
748    #[arg(long)]
749    pub ci: bool,
750
751    /// Force removal of the cache, ignoring in-use checks.
752    ///
753    /// By default, `uv cache prune` will block until no process is reading the cache. When
754    /// `--force` is used, `uv cache prune` will proceed without taking a lock.
755    #[arg(long)]
756    pub force: bool,
757}
758
759#[derive(Args, Debug)]
760pub struct SizeArgs {
761    /// Select the output format.
762    #[arg(long, value_enum, default_value_t = CacheSizeOutputFormat::default())]
763    pub output_format: CacheSizeOutputFormat,
764
765    /// Display the cache size in human-readable format (e.g., `1.2GiB` instead of raw bytes).
766    #[arg(
767        long = "human",
768        short = 'H',
769        alias = "human-readable",
770        conflicts_with = "output_format"
771    )]
772    pub human: bool,
773}
774
775#[derive(Args)]
776pub struct PipNamespace {
777    #[command(subcommand)]
778    pub command: PipCommand,
779
780    /// Path to a PEM-encoded CA certificate bundle.
781    ///
782    /// If provided, this overrides the default certificate source.
783    #[arg(global = true, long, value_name = "FILE", value_hint = ValueHint::FilePath)]
784    pub cert: Option<PathBuf>,
785}
786
787#[derive(Subcommand)]
788pub enum PipCommand {
789    /// Compile a `requirements.in` file to a `requirements.txt` or `pylock.toml` file.
790    #[command(
791        after_help = "Use `uv help pip compile` for more details.",
792        after_long_help = ""
793    )]
794    Compile(PipCompileArgs),
795    /// Sync an environment with a `requirements.txt` or `pylock.toml` file.
796    ///
797    /// When syncing an environment, any packages not listed in the `requirements.txt` or
798    /// `pylock.toml` file will be removed. To retain extraneous packages, use `uv pip install`
799    /// instead.
800    ///
801    /// The input file is presumed to be the output of a `pip compile` or `uv export` operation,
802    /// in which it will include all transitive dependencies. If transitive dependencies are not
803    /// present in the file, they will not be installed. Use `--strict` to warn if any transitive
804    /// dependencies are missing.
805    #[command(
806        after_help = "Use `uv help pip sync` for more details.",
807        after_long_help = ""
808    )]
809    Sync(Box<PipSyncArgs>),
810    /// Install packages into an environment.
811    #[command(
812        after_help = "Use `uv help pip install` for more details.",
813        after_long_help = ""
814    )]
815    Install(PipInstallArgs),
816    /// Uninstall packages from an environment.
817    #[command(
818        after_help = "Use `uv help pip uninstall` for more details.",
819        after_long_help = ""
820    )]
821    Uninstall(PipUninstallArgs),
822    /// List, in requirements format, packages installed in an environment.
823    #[command(
824        after_help = "Use `uv help pip freeze` for more details.",
825        after_long_help = ""
826    )]
827    Freeze(PipFreezeArgs),
828    /// List, in tabular format, packages installed in an environment.
829    #[command(
830        after_help = "Use `uv help pip list` for more details.",
831        after_long_help = "",
832        alias = "ls"
833    )]
834    List(PipListArgs),
835    /// Show information about one or more installed packages.
836    #[command(
837        after_help = "Use `uv help pip show` for more details.",
838        after_long_help = ""
839    )]
840    Show(PipShowArgs),
841    /// Display the dependency tree for an environment.
842    #[command(
843        after_help = "Use `uv help pip tree` for more details.",
844        after_long_help = ""
845    )]
846    Tree(PipTreeArgs),
847    /// Verify installed packages have compatible dependencies.
848    #[command(
849        after_help = "Use `uv help pip check` for more details.",
850        after_long_help = ""
851    )]
852    Check(PipCheckArgs),
853    /// Display debug information (unsupported)
854    #[command(hide = true)]
855    Debug(PipDebugArgs),
856}
857
858#[derive(Subcommand)]
859pub enum ProjectCommand {
860    /// Run a command or script.
861    ///
862    /// Ensures that the command runs in a Python environment.
863    ///
864    /// When used with a file ending in `.py` or an HTTP(S) URL, the file will be treated as a
865    /// script and run with a Python interpreter, i.e., `uv run file.py` is equivalent to `uv run
866    /// python file.py`. For URLs, the script is temporarily downloaded before execution. If the
867    /// script contains inline dependency metadata, it will be installed into an isolated, ephemeral
868    /// environment. When used with `-`, the input will be read from stdin, and treated as a Python
869    /// script.
870    ///
871    /// When used in a project, the project environment will be created and updated before invoking
872    /// the command.
873    ///
874    /// When used outside a project, if a virtual environment can be found in the current directory
875    /// or a parent directory, the command will be run in that environment. Otherwise, the command
876    /// will be run in the environment of the discovered interpreter.
877    ///
878    /// When running a script, the project or workspace is discovered from the script's directory.
879    /// Otherwise, the project or workspace is discovered from the current working directory.
880    ///
881    /// Arguments following the command (or script) are not interpreted as arguments to uv. All
882    /// options to uv must be provided before the command, e.g., `uv run --verbose foo`. A `--` can
883    /// be used to separate the command from uv options for clarity, e.g., `uv run --python 3.12 --
884    /// python`.
885    #[command(
886        after_help = "Use `uv help run` for more details.",
887        after_long_help = ""
888    )]
889    Run(RunArgs),
890    /// Create a new project.
891    ///
892    /// Follows the `pyproject.toml` specification.
893    ///
894    /// If a `pyproject.toml` already exists at the target, uv will exit with an error.
895    ///
896    /// If a `pyproject.toml` is found in any of the parent directories of the target path, the
897    /// project will be added as a workspace member of the parent.
898    ///
899    /// Some project state is not created until needed, e.g., the project virtual environment
900    /// (`.venv`) and lockfile (`uv.lock`) are lazily created during the first sync.
901    Init(InitArgs),
902    /// Add dependencies to the project.
903    ///
904    /// Dependencies are added to the project's `pyproject.toml` file.
905    ///
906    /// If a given dependency exists already, it will be updated to the new version specifier unless
907    /// it includes markers that differ from the existing specifier in which case another entry for
908    /// the dependency will be added.
909    ///
910    /// The lockfile and project environment will be updated to reflect the added dependencies. To
911    /// skip updating the lockfile, use `--frozen`. To skip updating the environment, use
912    /// `--no-sync`.
913    ///
914    /// If any of the requested dependencies cannot be found, uv will exit with an error, unless the
915    /// `--frozen` flag is provided, in which case uv will add the dependencies verbatim without
916    /// checking that they exist or are compatible with the project.
917    ///
918    /// uv will search for a project in the current directory or any parent directory. If a project
919    /// cannot be found, uv will exit with an error.
920    #[command(
921        after_help = "Use `uv help add` for more details.",
922        after_long_help = ""
923    )]
924    Add(AddArgs),
925    /// Remove dependencies from the project.
926    ///
927    /// Dependencies are removed from the project's `pyproject.toml` file.
928    ///
929    /// If multiple entries exist for a given dependency, i.e., each with different markers, all of
930    /// the entries will be removed.
931    ///
932    /// The lockfile and project environment will be updated to reflect the removed dependencies. To
933    /// skip updating the lockfile, use `--frozen`. To skip updating the environment, use
934    /// `--no-sync`.
935    ///
936    /// If any of the requested dependencies are not present in the project, uv will exit with an
937    /// error.
938    ///
939    /// If a package has been manually installed in the environment, i.e., with `uv pip install`, it
940    /// will not be removed by `uv remove`.
941    ///
942    /// uv will search for a project in the current directory or any parent directory. If a project
943    /// cannot be found, uv will exit with an error.
944    #[command(
945        after_help = "Use `uv help remove` for more details.",
946        after_long_help = ""
947    )]
948    Remove(RemoveArgs),
949    /// Read or update the project's version.
950    Version(VersionArgs),
951    /// Update the project's environment.
952    ///
953    /// Syncing ensures that all project dependencies are installed and up-to-date with the
954    /// lockfile.
955    ///
956    /// By default, an exact sync is performed: uv removes packages that are not declared as
957    /// dependencies of the project. Use the `--inexact` flag to keep extraneous packages. Note that
958    /// if an extraneous package conflicts with a project dependency, it will still be removed.
959    /// Additionally, if `--no-build-isolation` is used, uv will not remove extraneous packages to
960    /// avoid removing possible build dependencies.
961    ///
962    /// If the project virtual environment (`.venv`) does not exist, it will be created.
963    ///
964    /// The project is re-locked before syncing unless the `--locked` or `--frozen` flag is
965    /// provided.
966    ///
967    /// uv will search for a project in the current directory or any parent directory. If a project
968    /// cannot be found, uv will exit with an error.
969    ///
970    /// Note that, when installing from a lockfile, uv will not provide warnings for yanked package
971    /// versions.
972    #[command(
973        after_help = "Use `uv help sync` for more details.",
974        after_long_help = ""
975    )]
976    Sync(SyncArgs),
977    /// Update the project's lockfile.
978    ///
979    /// If the project lockfile (`uv.lock`) does not exist, it will be created. If a lockfile is
980    /// present, its contents will be used as preferences for the resolution.
981    ///
982    /// If there are no changes to the project's dependencies, locking will have no effect unless
983    /// the `--upgrade` flag is provided.
984    #[command(
985        after_help = "Use `uv help lock` for more details.",
986        after_long_help = ""
987    )]
988    Lock(LockArgs),
989    /// Upgrade a dependency in the project.
990    #[command(hide = true)]
991    Upgrade(UpgradeArgs),
992    /// Export the project's lockfile to an alternate format.
993    ///
994    /// At present, `requirements.txt`, `pylock.toml` (PEP 751) and CycloneDX v1.5 JSON output
995    /// formats are supported.
996    ///
997    /// The project is re-locked before exporting unless the `--locked` or `--frozen` flag is
998    /// provided.
999    ///
1000    /// uv will search for a project in the current directory or any parent directory. If a project
1001    /// cannot be found, uv will exit with an error.
1002    ///
1003    /// If operating in a workspace, the root will be exported by default; however, specific
1004    /// members can be selected using the `--package` option.
1005    #[command(
1006        after_help = "Use `uv help export` for more details.",
1007        after_long_help = ""
1008    )]
1009    Export(ExportArgs),
1010    /// Display the project's dependency tree.
1011    Tree(TreeArgs),
1012    /// Format Python code in the project.
1013    ///
1014    /// Formats Python code using the Ruff formatter. By default, all Python files in the project
1015    /// are formatted. This command has the same behavior as running `ruff format` in the project
1016    /// root.
1017    ///
1018    /// To check if files are formatted without modifying them, use `--check`. To see a diff of
1019    /// formatting changes, use `--diff`.
1020    ///
1021    /// Additional arguments can be passed to Ruff after `--`.
1022    #[command(
1023        after_help = "Use `uv help format` for more details.",
1024        after_long_help = ""
1025    )]
1026    Format(FormatArgs),
1027    /// Run checks on the project.
1028    ///
1029    /// Currently, this type checks Python code using ty. By default, all Python files in the
1030    /// project are checked.
1031    ///
1032    /// To apply safe fixes to type-checking errors, use `--fix`.
1033    #[command(
1034        after_help = "Use `uv help check` for more details.",
1035        after_long_help = ""
1036    )]
1037    Check(CheckArgs),
1038    /// Audit the project's dependencies.
1039    ///
1040    /// Dependencies are audited for known vulnerabilities, as well as 'adverse' statuses such as
1041    /// deprecation and quarantine.
1042    ///
1043    /// By default, all extras and dependency groups within the project are audited, regardless of
1044    /// `tool.uv.default-groups`. To omit all dependency groups, use `--no-default-groups`. To exclude
1045    /// individual extras or groups, use `--no-extra` or `--no-group`.
1046    ///
1047    /// Auditing requires network access and cannot be performed in offline mode.
1048    #[command(
1049        after_help = "Use `uv help audit` for more details.",
1050        after_long_help = ""
1051    )]
1052    Audit(AuditArgs),
1053}
1054
1055/// A re-implementation of [`Option`], used to avoid `clap`'s automatic `Option` flattening.
1056#[derive(Debug, Clone)]
1057pub enum Maybe<T> {
1058    Some(T),
1059    None,
1060}
1061
1062impl<T> Maybe<T> {
1063    fn into_option(self) -> Option<T> {
1064        match self {
1065            Self::Some(value) => Some(value),
1066            Self::None => None,
1067        }
1068    }
1069
1070    fn is_some(&self) -> bool {
1071        matches!(self, Self::Some(_))
1072    }
1073}
1074
1075impl<T> FromStr for Maybe<T>
1076where
1077    T: FromStr,
1078{
1079    type Err = T::Err;
1080
1081    fn from_str(input: &str) -> Result<Self, Self::Err> {
1082        if input.is_empty() {
1083            Ok(Self::None)
1084        } else {
1085            input.parse().map(Self::Some)
1086        }
1087    }
1088}
1089
1090/// Parse an `--index-url` argument into an [`PipIndex`], mapping the empty string to `None`.
1091fn parse_index_url(input: &str) -> Result<Maybe<PipIndex>, String> {
1092    if input.is_empty() {
1093        Ok(Maybe::None)
1094    } else {
1095        IndexUrl::from_str(input)
1096            .map(Index::from_index_url)
1097            .map(|index| Index {
1098                origin: Some(Origin::Cli),
1099                ..index
1100            })
1101            .map(PipIndex::from)
1102            .map(Maybe::Some)
1103            .map_err(|err| err.to_string())
1104    }
1105}
1106
1107/// Parse an `--extra-index-url` argument into an [`PipExtraIndex`], mapping the empty string to `None`.
1108fn parse_extra_index_url(input: &str) -> Result<Maybe<PipExtraIndex>, String> {
1109    if input.is_empty() {
1110        Ok(Maybe::None)
1111    } else {
1112        IndexUrl::from_str(input)
1113            .map(Index::from_extra_index_url)
1114            .map(|index| Index {
1115                origin: Some(Origin::Cli),
1116                ..index
1117            })
1118            .map(PipExtraIndex::from)
1119            .map(Maybe::Some)
1120            .map_err(|err| err.to_string())
1121    }
1122}
1123
1124/// Parse a `--find-links` argument into an [`PipFindLinks`], mapping the empty string to `None`.
1125fn parse_find_links(input: &str) -> Result<Maybe<PipFindLinks>, String> {
1126    if input.is_empty() {
1127        Ok(Maybe::None)
1128    } else {
1129        IndexUrl::from_str(input)
1130            .map(Index::from_find_links)
1131            .map(|index| Index {
1132                origin: Some(Origin::Cli),
1133                ..index
1134            })
1135            .map(PipFindLinks::from)
1136            .map(Maybe::Some)
1137            .map_err(|err| err.to_string())
1138    }
1139}
1140
1141/// An unresolved index passed by the user by its name.
1142#[derive(Debug, Clone, PartialEq, Eq)]
1143pub struct UnresolvedIndex {
1144    name: IndexName,
1145    default: bool,
1146}
1147
1148impl UnresolvedIndex {
1149    /// Resolve an index name against the effective filesystem configuration.
1150    fn resolve(self, indexes: &[Index], preview_enabled: bool) -> Result<Index> {
1151        let Self { name, default } = self;
1152        let path_exists = Path::new(name.as_ref()).exists();
1153
1154        // Outside preview, an existing path retains its current interpretation.
1155        if preview_enabled || !path_exists {
1156            if let Some(index) = indexes
1157                .iter()
1158                .find(|index| index.name.as_ref() == Some(&name))
1159            {
1160                if !preview_enabled {
1161                    warn_user_once!(
1162                        "Referencing an index by name is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
1163                        PreviewFeature::IndexByName
1164                    );
1165                }
1166
1167                let mut index = index.clone();
1168                // Keep relative paths anchored to their configuration file without marking them
1169                // as absolute when CLI settings are rebased or written back to a project.
1170                if let IndexUrl::Path(url) = index.url()
1171                    && url.prefers_relative()
1172                {
1173                    index.url = IndexUrl::from(VerbatimUrl::from_url(index.raw_url().clone()));
1174                }
1175
1176                return Ok(Index {
1177                    default,
1178                    explicit: false,
1179                    origin: Some(Origin::Cli),
1180                    ..index
1181                });
1182            }
1183
1184            if preview_enabled && !path_exists {
1185                return Err(anyhow!("Could not find an index named `{name}`"));
1186            }
1187        }
1188
1189        Ok(Index {
1190            default,
1191            origin: Some(Origin::Cli),
1192            ..Index::from_str(name.as_ref())?
1193        })
1194    }
1195}
1196
1197/// A potentially unresolved index.
1198#[expect(clippy::large_enum_variant)]
1199#[derive(Debug, Clone, PartialEq, Eq)]
1200pub enum IndexArg {
1201    /// A usable index with a URL.
1202    Resolved(Index),
1203    /// An unresolved index specification.
1204    Unresolved(UnresolvedIndex),
1205}
1206
1207impl IndexArg {
1208    fn new(value: &str, default: bool) -> Result<Self, IndexSourceError> {
1209        if let Ok(name) = IndexName::from_str(value) {
1210            return Ok(Self::Unresolved(UnresolvedIndex { name, default }));
1211        }
1212
1213        let index = Index::from_str(value)?;
1214        Ok(Self::Resolved(Index {
1215            default,
1216            origin: Some(Origin::Cli),
1217            ..index
1218        }))
1219    }
1220
1221    /// Parse an index passed via `--index`.
1222    fn from_index(value: &str) -> Result<Self, IndexSourceError> {
1223        Self::new(value, false)
1224    }
1225
1226    /// Parse an index passed via `--default-index`.
1227    fn from_default_index(value: &str) -> Result<Self, IndexSourceError> {
1228        Self::new(value, true)
1229    }
1230
1231    /// Resolve the argument against indexes from the effective configuration.
1232    fn resolve(self, indexes: &[Index]) -> Result<Index> {
1233        let index = match self {
1234            Self::Resolved(index) => index,
1235            Self::Unresolved(index) => {
1236                index.resolve(indexes, uv_preview::is_enabled(PreviewFeature::IndexByName))?
1237            }
1238        };
1239
1240        index.url().warn_on_disambiguated_relative_path();
1241
1242        Ok(index)
1243    }
1244}
1245
1246/// Parse an `--index` argument into a [`Vec<IndexArg>`], mapping the empty string to an empty Vec.
1247///
1248/// This function splits the input on all whitespace characters rather than a single delimiter,
1249/// which is necessary to parse environment variables like `PIP_EXTRA_INDEX_URL`.
1250/// The standard `clap::Args` `value_delimiter` only supports single-character delimiters.
1251fn parse_indices(input: &str) -> Result<Vec<Maybe<IndexArg>>, String> {
1252    if input.trim().is_empty() {
1253        return Ok(Vec::new());
1254    }
1255    let mut indices = Vec::new();
1256    for token in input.split_whitespace() {
1257        match IndexArg::from_index(token) {
1258            Ok(index) => indices.push(Maybe::Some(index)),
1259            Err(e) => return Err(e.to_string()),
1260        }
1261    }
1262    Ok(indices)
1263}
1264
1265/// Parse a `--default-index` argument into an [`IndexArg`], mapping the empty string to `None`.
1266fn parse_default_index(input: &str) -> Result<Maybe<IndexArg>, String> {
1267    if input.is_empty() {
1268        Ok(Maybe::None)
1269    } else {
1270        match IndexArg::from_default_index(input) {
1271            Ok(index) => Ok(Maybe::Some(index)),
1272            Err(err) => Err(err.to_string()),
1273        }
1274    }
1275}
1276
1277/// Parse a string into a [`TrustedHost`], mapping the empty string to `None`.
1278fn parse_insecure_host(input: &str) -> Result<Maybe<TrustedHost>, String> {
1279    if input.is_empty() {
1280        Ok(Maybe::None)
1281    } else {
1282        match TrustedHost::from_str(input) {
1283            Ok(host) => Ok(Maybe::Some(host)),
1284            Err(err) => Err(err.to_string()),
1285        }
1286    }
1287}
1288
1289/// Parse a string into a [`PathBuf`]. The string can represent a file, either as a path or a
1290/// `file://` URL.
1291fn parse_file_path(input: &str) -> Result<PathBuf, String> {
1292    if input.starts_with("file://") {
1293        let url = match url::Url::from_str(input) {
1294            Ok(url) => url,
1295            Err(err) => return Err(err.to_string()),
1296        };
1297        url.to_file_path()
1298            .map_err(|()| "invalid file URL".to_string())
1299    } else {
1300        Ok(PathBuf::from(input))
1301    }
1302}
1303
1304/// Arguments for constraining, overriding, and excluding dependencies with requirements files.
1305#[derive(Args)]
1306#[group(skip)]
1307pub struct DependencyConstraintsArgs {
1308    /// Constrain versions using the given requirements files.
1309    ///
1310    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
1311    /// requirement that's installed. However, including a package in a constraints file will _not_
1312    /// trigger the installation of that package.
1313    ///
1314    /// This is equivalent to pip's `--constraint` option.
1315    #[arg(
1316        long,
1317        short,
1318        alias = "constraint",
1319        env = EnvVars::UV_CONSTRAINT,
1320        value_delimiter = ' ',
1321        value_hint = ValueHint::FilePath,
1322    )]
1323    constraints: Vec<Maybe<RequirementsInput>>,
1324
1325    /// Override versions using the given requirements files.
1326    ///
1327    /// Overrides files are `requirements.txt`-like files that force a specific version of a
1328    /// requirement to be installed, regardless of the requirements declared by any constituent
1329    /// package, and regardless of whether this would be considered an invalid resolution.
1330    ///
1331    /// While constraints are _additive_, in that they're combined with the requirements of the
1332    /// constituent packages, overrides are _absolute_, in that they completely replace the
1333    /// requirements of the constituent packages.
1334    #[arg(
1335        long,
1336        alias = "override",
1337        env = EnvVars::UV_OVERRIDE,
1338        value_delimiter = ' ',
1339        value_hint = ValueHint::FilePath,
1340    )]
1341    overrides: Vec<Maybe<RequirementsInput>>,
1342
1343    /// Exclude packages from resolution using the given requirements files.
1344    ///
1345    /// Excludes files are `requirements.txt`-like files that specify packages to exclude
1346    /// from the resolution. When a package is excluded, it will be omitted from the
1347    /// dependency list entirely and its own dependencies will be ignored during the resolution
1348    /// phase. Excludes are unconditional in that requirement specifiers and markers are ignored;
1349    /// any package listed in the provided file will be omitted from all resolved environments.
1350    #[arg(
1351        long,
1352        alias = "exclude",
1353        env = EnvVars::UV_EXCLUDE,
1354        value_delimiter = ' ',
1355        value_hint = ValueHint::FilePath,
1356    )]
1357    excludes: Vec<Maybe<RequirementsInput>>,
1358
1359    /// Constrain build dependencies using the given requirements files when building source
1360    /// distributions.
1361    ///
1362    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
1363    /// requirement that's installed. However, including a package in a constraints file will _not_
1364    /// trigger the installation of that package.
1365    #[arg(
1366        long,
1367        short,
1368        alias = "build-constraint",
1369        env = EnvVars::UV_BUILD_CONSTRAINT,
1370        value_delimiter = ' ',
1371        value_hint = ValueHint::FilePath,
1372    )]
1373    build_constraints: Vec<Maybe<RequirementsInput>>,
1374}
1375
1376#[derive(Args)]
1377#[command(group = clap::ArgGroup::new("sources").required(true).multiple(true))]
1378pub struct PipCompileArgs {
1379    /// Include the packages listed in the given files.
1380    ///
1381    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
1382    /// `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg`.
1383    ///
1384    /// If a `pyproject.toml`, `setup.py`, or `setup.cfg` file is provided, uv will extract the
1385    /// requirements for the relevant project.
1386    ///
1387    /// If `-` is provided, then requirements will be read from stdin.
1388    ///
1389    /// The order of the requirements files and the requirements in them is used to determine
1390    /// priority during resolution.
1391    #[arg(group = "sources", value_hint = ValueHint::FilePath)]
1392    pub src_file: Vec<RequirementsInput>,
1393
1394    #[command(flatten)]
1395    pub constraints: DependencyConstraintsArgs,
1396
1397    /// Include optional dependencies from the specified extra name; may be provided more than once.
1398    ///
1399    /// Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
1400    #[arg(long, value_delimiter = ',', conflicts_with = "all_extras", value_parser = extra_name_with_clap_error)]
1401    pub extra: Option<Vec<ExtraName>>,
1402
1403    /// Include all optional dependencies.
1404    ///
1405    /// Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
1406    #[arg(long, conflicts_with = "extra")]
1407    pub all_extras: bool,
1408
1409    #[arg(long, overrides_with("all_extras"), hide = true)]
1410    pub no_all_extras: bool,
1411
1412    /// Install the specified dependency group from a `pyproject.toml`.
1413    ///
1414    /// If no path is provided, the `pyproject.toml` in the working directory is used.
1415    ///
1416    /// May be provided multiple times.
1417    #[arg(long, group = "sources")]
1418    pub group: Vec<PipGroupName>,
1419
1420    #[command(flatten)]
1421    pub resolver: ResolverArgs,
1422
1423    #[command(flatten)]
1424    pub refresh: RefreshArgs,
1425
1426    /// Ignore package dependencies, instead only add those packages explicitly listed
1427    /// on the command line to the resulting requirements file.
1428    #[arg(long)]
1429    pub no_deps: bool,
1430
1431    #[arg(long, overrides_with("no_deps"), hide = true)]
1432    pub deps: bool,
1433
1434    /// Write the compiled requirements to the given `requirements.txt` or `pylock.toml` file.
1435    ///
1436    /// If the file already exists, the existing versions will be preferred when resolving
1437    /// dependencies, unless `--upgrade` is also specified.
1438    #[arg(long, short, value_hint = ValueHint::FilePath)]
1439    pub output_file: Option<PathBuf>,
1440
1441    /// The format in which the resolution should be output.
1442    ///
1443    /// Supports both `requirements.txt` and `pylock.toml` (PEP 751) output formats.
1444    ///
1445    /// uv will infer the output format from the file extension of the output file, if
1446    /// provided. Otherwise, defaults to `requirements.txt`.
1447    #[arg(long, value_enum)]
1448    pub format: Option<PipCompileFormat>,
1449
1450    /// Include extras in the output file.
1451    ///
1452    /// By default, uv strips extras, as any packages pulled in by the extras are already included
1453    /// as dependencies in the output file directly. Further, output files generated with
1454    /// `--no-strip-extras` cannot be used as constraints files in `install` and `sync` invocations.
1455    #[arg(long, overrides_with("strip_extras"))]
1456    pub no_strip_extras: bool,
1457
1458    #[arg(long, overrides_with("no_strip_extras"), hide = true)]
1459    pub strip_extras: bool,
1460
1461    /// Include environment markers in the output file.
1462    ///
1463    /// By default, uv strips environment markers, as the resolution generated by `compile` is
1464    /// only guaranteed to be correct for the target environment.
1465    #[arg(long, overrides_with("strip_markers"))]
1466    pub no_strip_markers: bool,
1467
1468    #[arg(long, overrides_with("no_strip_markers"), hide = true)]
1469    pub strip_markers: bool,
1470
1471    /// Exclude comment annotations indicating the source of each package.
1472    #[arg(long, overrides_with("annotate"))]
1473    pub no_annotate: bool,
1474
1475    #[arg(long, overrides_with("no_annotate"), hide = true)]
1476    pub annotate: bool,
1477
1478    /// Exclude the comment header at the top of the generated output file.
1479    #[arg(long, overrides_with("header"))]
1480    pub no_header: bool,
1481
1482    #[arg(long, overrides_with("no_header"), hide = true)]
1483    pub header: bool,
1484
1485    /// The style of the annotation comments included in the output file, used to indicate the
1486    /// source of each package.
1487    ///
1488    /// Defaults to `split`.
1489    #[arg(long, value_enum)]
1490    pub annotation_style: Option<AnnotationStyle>,
1491
1492    /// The header comment to include at the top of the output file generated by `uv pip compile`.
1493    ///
1494    /// Used to reflect custom build scripts and commands that wrap `uv pip compile`.
1495    #[arg(long, env = EnvVars::UV_CUSTOM_COMPILE_COMMAND, value_hint = ValueHint::Other)]
1496    pub custom_compile_command: Option<String>,
1497
1498    /// The Python interpreter to use during resolution.
1499    ///
1500    /// A Python interpreter is required for building source distributions to determine package
1501    /// metadata when there are not wheels.
1502    ///
1503    /// The interpreter is also used to determine the default minimum Python version, unless
1504    /// `--python-version` is provided.
1505    ///
1506    /// This option respects `UV_PYTHON`, but when set via environment variable, it is overridden
1507    /// by `--python-version`.
1508    ///
1509    /// See `uv help python` for details on Python discovery and supported request formats.
1510    #[arg(
1511        long,
1512        short,
1513        verbatim_doc_comment,
1514        help_heading = "Python options",
1515        value_hint = ValueHint::Other,
1516    )]
1517    pub python: Option<Maybe<String>>,
1518
1519    /// Install packages into the system Python environment.
1520    ///
1521    /// By default, uv uses the virtual environment in the current working directory or any parent
1522    /// directory, falling back to searching for a Python executable in `PATH`. The `--system`
1523    /// option instructs uv to avoid using a virtual environment Python and restrict its search to
1524    /// the system path.
1525    #[arg(
1526        long,
1527        env = EnvVars::UV_SYSTEM_PYTHON,
1528        value_parser = clap::builder::BoolishValueParser::new(),
1529        overrides_with("no_system")
1530    )]
1531    pub system: bool,
1532
1533    #[arg(long, overrides_with("system"), hide = true)]
1534    pub no_system: bool,
1535
1536    /// Include distribution hashes in the output file.
1537    #[arg(long, overrides_with("no_generate_hashes"))]
1538    pub generate_hashes: bool,
1539
1540    #[arg(long, overrides_with("generate_hashes"), hide = true)]
1541    pub no_generate_hashes: bool,
1542
1543    /// Don't build source distributions.
1544    ///
1545    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
1546    /// operations that require building a source distribution will exit with an error. uv may
1547    /// still build editable requirements, and their build backends may run arbitrary Python code.
1548    ///
1549    /// Alias for `--only-binary :all:`.
1550    #[arg(
1551        long,
1552        conflicts_with = "no_binary",
1553        conflicts_with = "only_binary",
1554        overrides_with("build")
1555    )]
1556    pub no_build: bool,
1557
1558    #[arg(
1559        long,
1560        conflicts_with = "no_binary",
1561        conflicts_with = "only_binary",
1562        overrides_with("no_build"),
1563        hide = true
1564    )]
1565    pub build: bool,
1566
1567    /// Don't install pre-built wheels.
1568    ///
1569    /// The given packages will be built and installed from source. The resolver will still use
1570    /// pre-built wheels to extract package metadata, if available.
1571    ///
1572    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`.
1573    /// Clear previously specified packages with `:none:`.
1574    #[arg(long, value_delimiter = ',', conflicts_with = "no_build")]
1575    pub no_binary: Option<Vec<PackageNameSpecifier>>,
1576
1577    /// Only use pre-built wheels; don't build source distributions.
1578    ///
1579    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
1580    /// operations that require building a source distribution for the given packages will exit
1581    /// with an error. uv may still build editable requirements, and their build backends may run
1582    /// arbitrary Python code.
1583    ///
1584    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`.
1585    /// Clear previously specified packages with `:none:`.
1586    #[arg(long, value_delimiter = ',', conflicts_with = "no_build")]
1587    pub only_binary: Option<Vec<PackageNameSpecifier>>,
1588
1589    /// The Python version to use for resolution.
1590    ///
1591    /// For example, `3.8` or `3.8.17`.
1592    ///
1593    /// Defaults to the version of the Python interpreter used for resolution.
1594    ///
1595    /// Defines the minimum Python version that must be supported by the
1596    /// resolved requirements.
1597    ///
1598    /// If a patch version is omitted, the minimum patch version is assumed. For
1599    /// example, `3.8` is mapped to `3.8.0`.
1600    #[arg(long, help_heading = "Python options")]
1601    pub python_version: Option<PythonVersion>,
1602
1603    /// The platform for which requirements should be resolved.
1604    ///
1605    /// Represented as a "target triple", a string that describes the target platform in terms of
1606    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
1607    /// `aarch64-apple-darwin`.
1608    ///
1609    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
1610    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
1611    ///
1612    /// When targeting iOS, the default minimum version is `13.0`. Use
1613    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
1614    ///
1615    /// When targeting Android, the default minimum Android API level is `24`. Use
1616    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
1617    #[arg(long)]
1618    pub python_platform: Option<TargetTriple>,
1619
1620    /// Perform a universal resolution, attempting to generate a single `requirements.txt` output
1621    /// file that is compatible with all operating systems, architectures, and Python
1622    /// implementations.
1623    ///
1624    /// In universal mode, the current Python version (or user-provided `--python-version`) will be
1625    /// treated as a lower bound. For example, `--universal --python-version 3.7` would produce a
1626    /// universal resolution for Python 3.7 and later.
1627    ///
1628    /// Implies `--no-strip-markers`.
1629    #[arg(
1630        long,
1631        overrides_with("no_universal"),
1632        conflicts_with("python_platform"),
1633        conflicts_with("strip_markers")
1634    )]
1635    pub universal: bool,
1636
1637    #[arg(long, overrides_with("universal"), hide = true)]
1638    pub no_universal: bool,
1639
1640    /// Specify a package to omit from the output resolution. Its dependencies will still be
1641    /// included in the resolution. Equivalent to pip-compile's `--unsafe-package` option.
1642    #[arg(long, alias = "unsafe-package", value_delimiter = ',', value_hint = ValueHint::Other)]
1643    pub no_emit_package: Option<Vec<PackageName>>,
1644
1645    /// Include `--index-url` and `--extra-index-url` entries in the generated output file.
1646    #[arg(long, overrides_with("no_emit_index_url"))]
1647    pub emit_index_url: bool,
1648
1649    #[arg(long, overrides_with("emit_index_url"), hide = true)]
1650    pub no_emit_index_url: bool,
1651
1652    /// Include `--find-links` entries in the generated output file.
1653    #[arg(long, overrides_with("no_emit_find_links"))]
1654    pub emit_find_links: bool,
1655
1656    #[arg(long, overrides_with("emit_find_links"), hide = true)]
1657    pub no_emit_find_links: bool,
1658
1659    /// Include `--no-binary` and `--only-binary` entries in the generated output file.
1660    #[arg(long, overrides_with("no_emit_build_options"))]
1661    pub emit_build_options: bool,
1662
1663    #[arg(long, overrides_with("emit_build_options"), hide = true)]
1664    pub no_emit_build_options: bool,
1665
1666    /// Whether to emit a marker string indicating when it is known that the
1667    /// resulting set of pinned dependencies is valid.
1668    ///
1669    /// The pinned dependencies may be valid even when the marker expression is
1670    /// false, but when the expression is true, the requirements are known to
1671    /// be correct.
1672    #[arg(long, overrides_with("no_emit_marker_expression"), hide = true)]
1673    pub emit_marker_expression: bool,
1674
1675    #[arg(long, overrides_with("emit_marker_expression"), hide = true)]
1676    pub no_emit_marker_expression: bool,
1677
1678    /// Include comment annotations indicating the index used to resolve each package (e.g.,
1679    /// `# from https://pypi.org/simple`).
1680    #[arg(long, overrides_with("no_emit_index_annotation"))]
1681    pub emit_index_annotation: bool,
1682
1683    #[arg(long, overrides_with("emit_index_annotation"), hide = true)]
1684    pub no_emit_index_annotation: bool,
1685
1686    /// The backend to use when fetching packages in the PyTorch ecosystem (e.g., `cpu`, `cu126`, or `auto`).
1687    ///
1688    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
1689    /// and will instead use the defined backend.
1690    ///
1691    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
1692    /// uv will use the PyTorch index for CUDA 12.6.
1693    ///
1694    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
1695    /// installed CUDA drivers.
1696    ///
1697    /// This option is in preview and may change in any future release.
1698    #[arg(long, value_enum, env = EnvVars::UV_TORCH_BACKEND)]
1699    pub torch_backend: Option<TorchMode>,
1700
1701    #[command(flatten)]
1702    pub compat_args: compat::PipCompileCompatArgs,
1703}
1704
1705#[derive(Args)]
1706pub struct PipSyncArgs {
1707    /// Include the packages listed in the given files.
1708    ///
1709    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
1710    /// `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg`.
1711    ///
1712    /// If a `pyproject.toml`, `setup.py`, or `setup.cfg` file is provided, uv will
1713    /// extract the requirements for the relevant project.
1714    ///
1715    /// If `-` is provided, then requirements will be read from stdin.
1716    #[arg(required(true), value_hint = ValueHint::FilePath)]
1717    pub src_file: Vec<RequirementsInput>,
1718
1719    /// Constrain versions using the given requirements files.
1720    ///
1721    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
1722    /// requirement that's installed. However, including a package in a constraints file will _not_
1723    /// trigger the installation of that package.
1724    ///
1725    /// This is equivalent to pip's `--constraint` option.
1726    #[arg(
1727        long,
1728        short,
1729        alias = "constraint",
1730        env = EnvVars::UV_CONSTRAINT,
1731        value_delimiter = ' ',
1732        value_hint = ValueHint::FilePath,
1733    )]
1734    pub constraints: Vec<Maybe<RequirementsInput>>,
1735
1736    /// Constrain build dependencies using the given requirements files when building source
1737    /// distributions.
1738    ///
1739    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
1740    /// requirement that's installed. However, including a package in a constraints file will _not_
1741    /// trigger the installation of that package.
1742    #[arg(
1743        long,
1744        short,
1745        alias = "build-constraint",
1746        env = EnvVars::UV_BUILD_CONSTRAINT,
1747        value_delimiter = ' ',
1748        value_hint = ValueHint::FilePath,
1749    )]
1750    pub build_constraints: Vec<Maybe<RequirementsInput>>,
1751
1752    /// Include optional dependencies from the specified extra name; may be provided more than once.
1753    ///
1754    /// Only applies to `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
1755    #[arg(long, value_delimiter = ',', conflicts_with = "all_extras", value_parser = extra_name_with_clap_error)]
1756    pub extra: Option<Vec<ExtraName>>,
1757
1758    /// Include all optional dependencies.
1759    ///
1760    /// Only applies to `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
1761    #[arg(long, conflicts_with = "extra", overrides_with = "no_all_extras")]
1762    pub all_extras: bool,
1763
1764    #[arg(long, overrides_with("all_extras"), hide = true)]
1765    pub no_all_extras: bool,
1766
1767    /// Install the specified dependency group from a `pylock.toml` or `pyproject.toml`.
1768    ///
1769    /// If no path is provided, the `pylock.toml` or `pyproject.toml` in the working directory is
1770    /// used.
1771    ///
1772    /// May be provided multiple times.
1773    #[arg(long, group = "sources")]
1774    pub group: Vec<PipGroupName>,
1775
1776    #[command(flatten)]
1777    pub installer: InstallerArgs,
1778
1779    #[command(flatten)]
1780    pub refresh: RefreshArgs,
1781
1782    #[command(flatten)]
1783    pub hash_checking: HashCheckingArgs,
1784
1785    /// The Python interpreter into which packages should be installed.
1786    ///
1787    /// By default, syncing requires a virtual environment. A path to an alternative Python can be
1788    /// provided, but it is only recommended in continuous integration (CI) environments and should
1789    /// be used with caution, as it can modify the system Python installation.
1790    ///
1791    /// See `uv help python` for details on Python discovery and supported request formats.
1792    #[arg(
1793        long,
1794        short,
1795        env = EnvVars::UV_PYTHON,
1796        verbatim_doc_comment,
1797        help_heading = "Python options",
1798        value_hint = ValueHint::Other,
1799    )]
1800    pub python: Option<Maybe<String>>,
1801
1802    /// Install packages into the system Python environment.
1803    ///
1804    /// By default, uv installs into the virtual environment in the current working directory or any
1805    /// parent directory. The `--system` option instructs uv to instead use the first Python found
1806    /// in the system `PATH`.
1807    ///
1808    /// WARNING: `--system` is intended for use in continuous integration (CI) environments and
1809    /// should be used with caution, as it can modify the system Python installation.
1810    #[arg(
1811        long,
1812        env = EnvVars::UV_SYSTEM_PYTHON,
1813        value_parser = clap::builder::BoolishValueParser::new(),
1814        overrides_with("no_system")
1815    )]
1816    pub system: bool,
1817
1818    #[arg(long, overrides_with("system"), hide = true)]
1819    pub no_system: bool,
1820
1821    /// Allow uv to modify an `EXTERNALLY-MANAGED` Python installation.
1822    ///
1823    /// WARNING: `--break-system-packages` is intended for use in continuous integration (CI)
1824    /// environments, when installing into Python installations that are managed by an external
1825    /// package manager, like `apt`. It should be used with caution, as such Python installations
1826    /// explicitly recommend against modifications by other package managers (like uv or `pip`).
1827    #[arg(
1828        long,
1829        env = EnvVars::UV_BREAK_SYSTEM_PACKAGES,
1830        value_parser = clap::builder::BoolishValueParser::new(),
1831        overrides_with("no_break_system_packages")
1832    )]
1833    pub break_system_packages: bool,
1834
1835    #[arg(long, overrides_with("break_system_packages"))]
1836    pub no_break_system_packages: bool,
1837
1838    /// Install packages into the specified directory, rather than into the virtual or system Python
1839    /// environment. The packages will be installed at the top-level of the directory.
1840    ///
1841    /// Unlike other install operations, this command does not require discovery of an existing Python
1842    /// environment and only searches for a Python interpreter to use for package resolution.
1843    /// If a suitable Python interpreter cannot be found, uv will install one.
1844    /// To disable this, add `--no-python-downloads`.
1845    #[arg(short = 't', long, conflicts_with = "prefix", value_hint = ValueHint::DirPath)]
1846    pub target: Option<PathBuf>,
1847
1848    /// Install packages into `lib`, `bin`, and other top-level folders under the specified
1849    /// directory, as if a virtual environment were present at that location.
1850    ///
1851    /// In general, prefer the use of `--python` to install into an alternate environment, as
1852    /// scripts and other artifacts installed via `--prefix` will reference the installing
1853    /// interpreter, rather than any interpreter added to the `--prefix` directory, rendering them
1854    /// non-portable.
1855    ///
1856    /// Unlike other install operations, this command does not require discovery of an existing Python
1857    /// environment and only searches for a Python interpreter to use for package resolution.
1858    /// If a suitable Python interpreter cannot be found, uv will install one.
1859    /// To disable this, add `--no-python-downloads`.
1860    #[arg(long, conflicts_with = "target", value_hint = ValueHint::DirPath)]
1861    pub prefix: Option<PathBuf>,
1862
1863    /// Don't build source distributions.
1864    ///
1865    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
1866    /// operations that require building a source distribution will exit with an error. uv may
1867    /// still build editable requirements, and their build backends may run arbitrary Python code.
1868    ///
1869    /// Alias for `--only-binary :all:`.
1870    #[arg(
1871        long,
1872        conflicts_with = "no_binary",
1873        conflicts_with = "only_binary",
1874        overrides_with("build")
1875    )]
1876    pub no_build: bool,
1877
1878    #[arg(
1879        long,
1880        conflicts_with = "no_binary",
1881        conflicts_with = "only_binary",
1882        overrides_with("no_build"),
1883        hide = true
1884    )]
1885    pub build: bool,
1886
1887    /// Don't install pre-built wheels.
1888    ///
1889    /// The given packages will be built and installed from source. The resolver will still use
1890    /// pre-built wheels to extract package metadata, if available.
1891    ///
1892    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`. Clear
1893    /// previously specified packages with `:none:`.
1894    #[arg(long, value_delimiter = ',', conflicts_with = "no_build")]
1895    pub no_binary: Option<Vec<PackageNameSpecifier>>,
1896
1897    /// Only use pre-built wheels; don't build source distributions.
1898    ///
1899    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
1900    /// operations that require building a source distribution for the given packages will exit
1901    /// with an error. uv may still build editable requirements, and their build backends may run
1902    /// arbitrary Python code.
1903    ///
1904    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`. Clear
1905    /// previously specified packages with `:none:`.
1906    #[arg(long, value_delimiter = ',', conflicts_with = "no_build")]
1907    pub only_binary: Option<Vec<PackageNameSpecifier>>,
1908
1909    /// Allow sync of empty requirements, which will clear the environment of all packages.
1910    #[arg(long, overrides_with("no_allow_empty_requirements"))]
1911    pub allow_empty_requirements: bool,
1912
1913    #[arg(long, overrides_with("allow_empty_requirements"))]
1914    pub no_allow_empty_requirements: bool,
1915
1916    /// The minimum Python version that should be supported by the requirements (e.g., `3.7` or
1917    /// `3.7.9`).
1918    ///
1919    /// If a patch version is omitted, the minimum patch version is assumed. For example, `3.7` is
1920    /// mapped to `3.7.0`.
1921    #[arg(long)]
1922    pub python_version: Option<PythonVersion>,
1923
1924    /// The platform for which requirements should be installed.
1925    ///
1926    /// Represented as a "target triple", a string that describes the target platform in terms of
1927    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
1928    /// `aarch64-apple-darwin`.
1929    ///
1930    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
1931    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
1932    ///
1933    /// When targeting iOS, the default minimum version is `13.0`. Use
1934    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
1935    ///
1936    /// When targeting Android, the default minimum Android API level is `24`. Use
1937    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
1938    ///
1939    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
1940    /// platform; as a result, the installed distributions may not be compatible with the _current_
1941    /// platform. Conversely, any distributions that are built from source may be incompatible with
1942    /// the _target_ platform, as they will be built for the _current_ platform. The
1943    /// `--python-platform` option is intended for advanced use cases.
1944    #[arg(long)]
1945    pub python_platform: Option<TargetTriple>,
1946
1947    /// Validate the Python environment after completing the installation, to detect packages with
1948    /// missing dependencies or other issues.
1949    #[arg(long, overrides_with("no_strict"))]
1950    pub strict: bool,
1951
1952    #[arg(long, overrides_with("strict"), hide = true)]
1953    pub no_strict: bool,
1954
1955    /// Perform a dry run, i.e., don't actually install anything but resolve the dependencies and
1956    /// print the resulting plan.
1957    #[arg(long)]
1958    pub dry_run: bool,
1959
1960    /// Check whether the environment matches the requirements without modifying it.
1961    ///
1962    /// Resolve and report any necessary changes, exiting with code 1 if changes are needed.
1963    #[arg(long, conflicts_with = "dry_run")]
1964    pub check: bool,
1965
1966    /// Select the output format.
1967    ///
1968    /// JSON output is written to stdout; diagnostic messages are written to stderr.
1969    /// The JSON schema is experimental and may change without warning.
1970    #[arg(long, value_enum, default_value_t = PipInstallFormat::default())]
1971    pub output_format: PipInstallFormat,
1972
1973    /// The backend to use when fetching packages in the PyTorch ecosystem (e.g., `cpu`, `cu126`, or `auto`).
1974    ///
1975    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
1976    /// and will instead use the defined backend.
1977    ///
1978    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
1979    /// uv will use the PyTorch index for CUDA 12.6.
1980    ///
1981    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
1982    /// installed CUDA drivers.
1983    ///
1984    /// This option is in preview and may change in any future release.
1985    #[arg(long, value_enum, env = EnvVars::UV_TORCH_BACKEND)]
1986    pub torch_backend: Option<TorchMode>,
1987
1988    #[command(flatten)]
1989    pub compat_args: compat::PipSyncCompatArgs,
1990}
1991
1992#[derive(Args)]
1993#[command(group = clap::ArgGroup::new("sources").required(true).multiple(true))]
1994pub struct PipInstallArgs {
1995    /// Install all listed packages.
1996    ///
1997    /// The order of the packages is used to determine priority during resolution.
1998    #[arg(group = "sources", value_hint = ValueHint::Other)]
1999    pub package: Vec<String>,
2000
2001    /// Install the packages listed in the given files.
2002    ///
2003    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
2004    /// `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg`.
2005    ///
2006    /// If a `pyproject.toml`, `setup.py`, or `setup.cfg` file is provided, uv will extract the
2007    /// requirements for the relevant project.
2008    ///
2009    /// If `-` is provided, then requirements will be read from stdin.
2010    #[arg(
2011        long,
2012        short,
2013        alias = "requirement",
2014        group = "sources",
2015        value_hint = ValueHint::FilePath,
2016    )]
2017    pub requirements: Vec<RequirementsInput>,
2018
2019    /// Install the editable package based on the provided local file path.
2020    #[arg(long, short, group = "sources")]
2021    pub editable: Vec<String>,
2022
2023    /// Install any editable dependencies as non-editable [env: UV_NO_EDITABLE=]
2024    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
2025    pub no_editable: bool,
2026
2027    /// Install the specified editable packages as non-editable.
2028    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other)]
2029    pub no_editable_package: Vec<PackageName>,
2030
2031    #[command(flatten)]
2032    pub constraints: DependencyConstraintsArgs,
2033
2034    /// Include optional dependencies from the specified extra name; may be provided more than once.
2035    ///
2036    /// Only applies to `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
2037    #[arg(long, value_delimiter = ',', conflicts_with = "all_extras", value_parser = extra_name_with_clap_error)]
2038    pub extra: Option<Vec<ExtraName>>,
2039
2040    /// Include all optional dependencies.
2041    ///
2042    /// Only applies to `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
2043    #[arg(long, conflicts_with = "extra", overrides_with = "no_all_extras")]
2044    pub all_extras: bool,
2045
2046    #[arg(long, overrides_with("all_extras"), hide = true)]
2047    pub no_all_extras: bool,
2048
2049    /// Install the specified dependency group from a `pylock.toml` or `pyproject.toml`.
2050    ///
2051    /// If no path is provided, the `pylock.toml` or `pyproject.toml` in the working directory is
2052    /// used.
2053    ///
2054    /// May be provided multiple times.
2055    #[arg(long, group = "sources")]
2056    pub group: Vec<PipGroupName>,
2057
2058    #[command(flatten)]
2059    pub installer: ResolverInstallerArgs,
2060
2061    #[command(flatten)]
2062    pub refresh: RefreshArgs,
2063
2064    /// Ignore package dependencies, instead only installing those packages explicitly listed
2065    /// on the command line or in the requirements files.
2066    #[arg(long, overrides_with("deps"))]
2067    pub no_deps: bool,
2068
2069    #[arg(long, overrides_with("no_deps"), hide = true)]
2070    pub deps: bool,
2071
2072    #[command(flatten)]
2073    pub hash_checking: HashCheckingArgs,
2074
2075    /// The Python interpreter into which packages should be installed.
2076    ///
2077    /// By default, installation requires a virtual environment. A path to an alternative Python can
2078    /// be provided, but it is only recommended in continuous integration (CI) environments and
2079    /// should be used with caution, as it can modify the system Python installation.
2080    ///
2081    /// See `uv help python` for details on Python discovery and supported request formats.
2082    #[arg(
2083        long,
2084        short,
2085        env = EnvVars::UV_PYTHON,
2086        verbatim_doc_comment,
2087        help_heading = "Python options",
2088        value_hint = ValueHint::Other,
2089    )]
2090    pub python: Option<Maybe<String>>,
2091
2092    /// Install packages into the system Python environment.
2093    ///
2094    /// By default, uv installs into the virtual environment in the current working directory or any
2095    /// parent directory. The `--system` option instructs uv to instead use the first Python found
2096    /// in the system `PATH`.
2097    ///
2098    /// WARNING: `--system` is intended for use in continuous integration (CI) environments and
2099    /// should be used with caution, as it can modify the system Python installation.
2100    #[arg(
2101        long,
2102        env = EnvVars::UV_SYSTEM_PYTHON,
2103        value_parser = clap::builder::BoolishValueParser::new(),
2104        overrides_with("no_system")
2105    )]
2106    pub system: bool,
2107
2108    #[arg(long, overrides_with("system"), hide = true)]
2109    pub no_system: bool,
2110
2111    /// Allow uv to modify an `EXTERNALLY-MANAGED` Python installation.
2112    ///
2113    /// WARNING: `--break-system-packages` is intended for use in continuous integration (CI)
2114    /// environments, when installing into Python installations that are managed by an external
2115    /// package manager, like `apt`. It should be used with caution, as such Python installations
2116    /// explicitly recommend against modifications by other package managers (like uv or `pip`).
2117    #[arg(
2118        long,
2119        env = EnvVars::UV_BREAK_SYSTEM_PACKAGES,
2120        value_parser = clap::builder::BoolishValueParser::new(),
2121        overrides_with("no_break_system_packages")
2122    )]
2123    pub break_system_packages: bool,
2124
2125    #[arg(long, overrides_with("break_system_packages"))]
2126    pub no_break_system_packages: bool,
2127
2128    /// Install packages into the specified directory, rather than into the virtual or system Python
2129    /// environment. The packages will be installed at the top-level of the directory.
2130    ///
2131    /// Unlike other install operations, this command does not require discovery of an existing Python
2132    /// environment and only searches for a Python interpreter to use for package resolution.
2133    /// If a suitable Python interpreter cannot be found, uv will install one.
2134    /// To disable this, add `--no-python-downloads`.
2135    #[arg(short = 't', long, conflicts_with = "prefix", value_hint = ValueHint::DirPath)]
2136    pub target: Option<PathBuf>,
2137
2138    /// Install packages into `lib`, `bin`, and other top-level folders under the specified
2139    /// directory, as if a virtual environment were present at that location.
2140    ///
2141    /// In general, prefer the use of `--python` to install into an alternate environment, as
2142    /// scripts and other artifacts installed via `--prefix` will reference the installing
2143    /// interpreter, rather than any interpreter added to the `--prefix` directory, rendering them
2144    /// non-portable.
2145    ///
2146    /// Unlike other install operations, this command does not require discovery of an existing Python
2147    /// environment and only searches for a Python interpreter to use for package resolution.
2148    /// If a suitable Python interpreter cannot be found, uv will install one.
2149    /// To disable this, add `--no-python-downloads`.
2150    #[arg(long, conflicts_with = "target", value_hint = ValueHint::DirPath)]
2151    pub prefix: Option<PathBuf>,
2152
2153    /// Don't build source distributions.
2154    ///
2155    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
2156    /// operations that require building a source distribution will exit with an error. uv may
2157    /// still build editable requirements, and their build backends may run arbitrary Python code.
2158    ///
2159    /// Alias for `--only-binary :all:`.
2160    #[arg(
2161        long,
2162        conflicts_with = "no_binary",
2163        conflicts_with = "only_binary",
2164        overrides_with("build")
2165    )]
2166    pub no_build: bool,
2167
2168    #[arg(
2169        long,
2170        conflicts_with = "no_binary",
2171        conflicts_with = "only_binary",
2172        overrides_with("no_build"),
2173        hide = true
2174    )]
2175    pub build: bool,
2176
2177    /// Don't install pre-built wheels.
2178    ///
2179    /// The given packages will be built and installed from source. The resolver will still use
2180    /// pre-built wheels to extract package metadata, if available.
2181    ///
2182    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`. Clear
2183    /// previously specified packages with `:none:`.
2184    #[arg(long, value_delimiter = ',', conflicts_with = "no_build")]
2185    pub no_binary: Option<Vec<PackageNameSpecifier>>,
2186
2187    /// Only use pre-built wheels; don't build source distributions.
2188    ///
2189    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
2190    /// operations that require building a source distribution for the given packages will exit
2191    /// with an error. uv may still build editable requirements, and their build backends may run
2192    /// arbitrary Python code.
2193    ///
2194    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`. Clear
2195    /// previously specified packages with `:none:`.
2196    #[arg(long, value_delimiter = ',', conflicts_with = "no_build")]
2197    pub only_binary: Option<Vec<PackageNameSpecifier>>,
2198
2199    /// The minimum Python version that should be supported by the requirements (e.g., `3.7` or
2200    /// `3.7.9`).
2201    ///
2202    /// If a patch version is omitted, the minimum patch version is assumed. For example, `3.7` is
2203    /// mapped to `3.7.0`.
2204    #[arg(long)]
2205    pub python_version: Option<PythonVersion>,
2206
2207    /// The platform for which requirements should be installed.
2208    ///
2209    /// Represented as a "target triple", a string that describes the target platform in terms of
2210    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
2211    /// `aarch64-apple-darwin`.
2212    ///
2213    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
2214    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
2215    ///
2216    /// When targeting iOS, the default minimum version is `13.0`. Use
2217    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
2218    ///
2219    /// When targeting Android, the default minimum Android API level is `24`. Use
2220    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
2221    ///
2222    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
2223    /// platform; as a result, the installed distributions may not be compatible with the _current_
2224    /// platform. Conversely, any distributions that are built from source may be incompatible with
2225    /// the _target_ platform, as they will be built for the _current_ platform. The
2226    /// `--python-platform` option is intended for advanced use cases.
2227    #[arg(long)]
2228    pub python_platform: Option<TargetTriple>,
2229
2230    /// Do not remove extraneous packages present in the environment.
2231    #[arg(long, overrides_with("exact"), alias = "no-exact", hide = true)]
2232    pub inexact: bool,
2233
2234    /// Perform an exact sync, removing extraneous packages.
2235    ///
2236    /// By default, installing will make the minimum necessary changes to satisfy the requirements.
2237    /// When enabled, uv will update the environment to exactly match the requirements, removing
2238    /// packages that are not included in the requirements.
2239    #[arg(long, overrides_with("inexact"))]
2240    pub exact: bool,
2241
2242    /// Validate the Python environment after completing the installation, to detect packages with
2243    /// missing dependencies or other issues.
2244    #[arg(long, overrides_with("no_strict"))]
2245    pub strict: bool,
2246
2247    #[arg(long, overrides_with("strict"), hide = true)]
2248    pub no_strict: bool,
2249
2250    /// Perform a dry run, i.e., don't actually install anything but resolve the dependencies and
2251    /// print the resulting plan.
2252    #[arg(long)]
2253    pub dry_run: bool,
2254
2255    /// Check whether the environment satisfies the requirements without modifying it.
2256    ///
2257    /// Resolve and report any necessary changes, exiting with code 1 if changes are needed.
2258    #[arg(long, conflicts_with = "dry_run")]
2259    pub check: bool,
2260
2261    /// Select the output format.
2262    ///
2263    /// JSON output is written to stdout; diagnostic messages are written to stderr.
2264    /// The JSON schema is experimental and may change without warning.
2265    #[arg(long, value_enum, default_value_t = PipInstallFormat::default())]
2266    pub output_format: PipInstallFormat,
2267
2268    /// The backend to use when fetching packages in the PyTorch ecosystem (e.g., `cpu`, `cu126`, or `auto`)
2269    ///
2270    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
2271    /// and will instead use the defined backend.
2272    ///
2273    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
2274    /// uv will use the PyTorch index for CUDA 12.6.
2275    ///
2276    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
2277    /// installed CUDA drivers.
2278    ///
2279    /// This option is in preview and may change in any future release.
2280    #[arg(long, value_enum, env = EnvVars::UV_TORCH_BACKEND)]
2281    pub torch_backend: Option<TorchMode>,
2282
2283    #[command(flatten)]
2284    pub compat_args: compat::PipInstallCompatArgs,
2285}
2286
2287#[derive(Args)]
2288#[command(group = clap::ArgGroup::new("sources").required(true).multiple(true))]
2289pub struct PipUninstallArgs {
2290    /// Uninstall all listed packages.
2291    #[arg(group = "sources", value_hint = ValueHint::Other)]
2292    pub package: Vec<String>,
2293
2294    /// Uninstall the packages listed in the given files.
2295    ///
2296    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
2297    /// `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg`.
2298    #[arg(long, short, alias = "requirement", group = "sources", value_hint = ValueHint::FilePath)]
2299    pub requirements: Vec<RequirementsInput>,
2300
2301    /// The Python interpreter from which packages should be uninstalled.
2302    ///
2303    /// By default, uninstallation requires a virtual environment. A path to an alternative Python
2304    /// can be provided, but it is only recommended in continuous integration (CI) environments and
2305    /// should be used with caution, as it can modify the system Python installation.
2306    ///
2307    /// See `uv help python` for details on Python discovery and supported request formats.
2308    #[arg(
2309        long,
2310        short,
2311        env = EnvVars::UV_PYTHON,
2312        verbatim_doc_comment,
2313        help_heading = "Python options",
2314        value_hint = ValueHint::Other,
2315    )]
2316    pub python: Option<Maybe<String>>,
2317
2318    /// Attempt to use `keyring` for authentication for remote requirements files.
2319    ///
2320    /// At present, only `--keyring-provider subprocess` is supported, which configures uv to use
2321    /// the `keyring` CLI to handle authentication.
2322    ///
2323    /// Defaults to `disabled`.
2324    #[arg(long, value_enum, env = EnvVars::UV_KEYRING_PROVIDER)]
2325    pub keyring_provider: Option<KeyringProviderType>,
2326
2327    /// Use the system Python to uninstall packages.
2328    ///
2329    /// By default, uv uninstalls from the virtual environment in the current working directory or
2330    /// any parent directory. The `--system` option instructs uv to instead use the first Python
2331    /// found in the system `PATH`.
2332    ///
2333    /// WARNING: `--system` is intended for use in continuous integration (CI) environments and
2334    /// should be used with caution, as it can modify the system Python installation.
2335    #[arg(
2336        long,
2337        env = EnvVars::UV_SYSTEM_PYTHON,
2338        value_parser = clap::builder::BoolishValueParser::new(),
2339        overrides_with("no_system")
2340    )]
2341    pub system: bool,
2342
2343    #[arg(long, overrides_with("system"), hide = true)]
2344    pub no_system: bool,
2345
2346    /// Allow uv to modify an `EXTERNALLY-MANAGED` Python installation.
2347    ///
2348    /// WARNING: `--break-system-packages` is intended for use in continuous integration (CI)
2349    /// environments, when installing into Python installations that are managed by an external
2350    /// package manager, like `apt`. It should be used with caution, as such Python installations
2351    /// explicitly recommend against modifications by other package managers (like uv or `pip`).
2352    #[arg(
2353        long,
2354        env = EnvVars::UV_BREAK_SYSTEM_PACKAGES,
2355        value_parser = clap::builder::BoolishValueParser::new(),
2356        overrides_with("no_break_system_packages")
2357    )]
2358    pub break_system_packages: bool,
2359
2360    #[arg(long, overrides_with("break_system_packages"))]
2361    pub no_break_system_packages: bool,
2362
2363    /// Uninstall packages from the specified `--target` directory.
2364    #[arg(short = 't', long, conflicts_with = "prefix", value_hint = ValueHint::DirPath)]
2365    pub target: Option<PathBuf>,
2366
2367    /// Uninstall packages from the specified `--prefix` directory.
2368    #[arg(long, conflicts_with = "target", value_hint = ValueHint::DirPath)]
2369    pub prefix: Option<PathBuf>,
2370
2371    /// Perform a dry run, i.e., don't actually uninstall anything but print the resulting plan.
2372    #[arg(long)]
2373    pub dry_run: bool,
2374
2375    #[command(flatten)]
2376    pub compat_args: compat::PipUninstallCompatArgs,
2377}
2378
2379#[derive(Args)]
2380pub struct PipFreezeArgs {
2381    /// Exclude any editable packages from output.
2382    #[arg(long)]
2383    exclude_editable: bool,
2384
2385    /// Exclude the specified package(s) from the output.
2386    #[arg(long)]
2387    r#exclude: Vec<PackageName>,
2388
2389    /// Validate the Python environment, to detect packages with missing dependencies and other
2390    /// issues.
2391    #[arg(long, overrides_with("no_strict"))]
2392    strict: bool,
2393
2394    #[arg(long, overrides_with("strict"), hide = true)]
2395    no_strict: bool,
2396
2397    /// The Python interpreter for which packages should be listed.
2398    ///
2399    /// By default, uv lists packages in a virtual environment but will show packages in a system
2400    /// Python environment if no virtual environment is found.
2401    ///
2402    /// See `uv help python` for details on Python discovery and supported request formats.
2403    #[arg(
2404        long,
2405        short,
2406        env = EnvVars::UV_PYTHON,
2407        verbatim_doc_comment,
2408        help_heading = "Python options",
2409        value_hint = ValueHint::Other,
2410    )]
2411    python: Option<Maybe<String>>,
2412
2413    /// Restrict to the specified installation path for listing packages (can be used multiple times).
2414    #[arg(long("path"), value_parser = parse_file_path, value_hint = ValueHint::DirPath)]
2415    paths: Option<Vec<PathBuf>>,
2416
2417    /// List packages in the system Python environment.
2418    ///
2419    /// Disables discovery of virtual environments.
2420    ///
2421    /// See `uv help python` for details on Python discovery.
2422    #[arg(
2423        long,
2424        env = EnvVars::UV_SYSTEM_PYTHON,
2425        value_parser = clap::builder::BoolishValueParser::new(),
2426        overrides_with("no_system")
2427    )]
2428    system: bool,
2429
2430    #[arg(long, overrides_with("system"), hide = true)]
2431    no_system: bool,
2432
2433    /// List packages from the specified `--target` directory.
2434    #[arg(short = 't', long, conflicts_with_all = ["prefix", "paths"], value_hint = ValueHint::DirPath)]
2435    target: Option<PathBuf>,
2436
2437    /// List packages from the specified `--prefix` directory.
2438    #[arg(long, conflicts_with_all = ["target", "paths"], value_hint = ValueHint::DirPath)]
2439    prefix: Option<PathBuf>,
2440
2441    #[command(flatten)]
2442    compat_args: compat::PipGlobalCompatArgs,
2443}
2444
2445#[derive(Args)]
2446pub struct PipListArgs {
2447    /// Only include editable projects.
2448    #[arg(short, long)]
2449    pub editable: bool,
2450
2451    /// Exclude any editable packages from output.
2452    #[arg(long, conflicts_with = "editable")]
2453    pub exclude_editable: bool,
2454
2455    /// Exclude the specified package(s) from the output.
2456    #[arg(long, value_hint = ValueHint::Other)]
2457    pub r#exclude: Vec<PackageName>,
2458
2459    /// Select the output format.
2460    #[arg(long, value_enum, default_value_t = ListFormat::default())]
2461    pub format: ListFormat,
2462
2463    /// List outdated packages.
2464    ///
2465    /// The latest version of each package will be shown alongside the installed version. Up-to-date
2466    /// packages will be omitted from the output.
2467    #[arg(long, overrides_with("no_outdated"))]
2468    pub outdated: bool,
2469
2470    #[arg(long, overrides_with("outdated"), hide = true)]
2471    pub no_outdated: bool,
2472
2473    /// Validate the Python environment, to detect packages with missing dependencies and other
2474    /// issues.
2475    #[arg(long, overrides_with("no_strict"))]
2476    pub strict: bool,
2477
2478    #[arg(long, overrides_with("strict"), hide = true)]
2479    pub no_strict: bool,
2480
2481    #[command(flatten)]
2482    pub fetch: FetchArgs,
2483
2484    /// The Python interpreter for which packages should be listed.
2485    ///
2486    /// By default, uv lists packages in a virtual environment but will show packages in a system
2487    /// Python environment if no virtual environment is found.
2488    ///
2489    /// See `uv help python` for details on Python discovery and supported request formats.
2490    #[arg(
2491        long,
2492        short,
2493        env = EnvVars::UV_PYTHON,
2494        verbatim_doc_comment,
2495        help_heading = "Python options",
2496        value_hint = ValueHint::Other,
2497    )]
2498    pub python: Option<Maybe<String>>,
2499
2500    /// List packages in the system Python environment.
2501    ///
2502    /// Disables discovery of virtual environments.
2503    ///
2504    /// See `uv help python` for details on Python discovery.
2505    #[arg(
2506        long,
2507        env = EnvVars::UV_SYSTEM_PYTHON,
2508        value_parser = clap::builder::BoolishValueParser::new(),
2509        overrides_with("no_system")
2510    )]
2511    pub system: bool,
2512
2513    #[arg(long, overrides_with("system"), hide = true)]
2514    pub no_system: bool,
2515
2516    /// List packages from the specified `--target` directory.
2517    #[arg(short = 't', long, conflicts_with = "prefix", value_hint = ValueHint::DirPath)]
2518    pub target: Option<PathBuf>,
2519
2520    /// List packages from the specified `--prefix` directory.
2521    #[arg(long, conflicts_with = "target", value_hint = ValueHint::DirPath)]
2522    pub prefix: Option<PathBuf>,
2523
2524    #[command(flatten)]
2525    pub compat_args: compat::PipListCompatArgs,
2526}
2527
2528#[derive(Args)]
2529pub struct PipCheckArgs {
2530    /// The Python interpreter for which packages should be checked.
2531    ///
2532    /// By default, uv checks packages in a virtual environment but will check packages in a system
2533    /// Python environment if no virtual environment is found.
2534    ///
2535    /// See `uv help python` for details on Python discovery and supported request formats.
2536    #[arg(
2537        long,
2538        short,
2539        env = EnvVars::UV_PYTHON,
2540        verbatim_doc_comment,
2541        help_heading = "Python options",
2542        value_hint = ValueHint::Other,
2543    )]
2544    python: Option<Maybe<String>>,
2545
2546    /// Check packages in the system Python environment.
2547    ///
2548    /// Disables discovery of virtual environments.
2549    ///
2550    /// See `uv help python` for details on Python discovery.
2551    #[arg(
2552        long,
2553        env = EnvVars::UV_SYSTEM_PYTHON,
2554        value_parser = clap::builder::BoolishValueParser::new(),
2555        overrides_with("no_system")
2556    )]
2557    system: bool,
2558
2559    #[arg(long, overrides_with("system"), hide = true)]
2560    no_system: bool,
2561
2562    /// The Python version against which packages should be checked.
2563    ///
2564    /// By default, the installed packages are checked against the version of the current
2565    /// interpreter.
2566    #[arg(long)]
2567    python_version: Option<PythonVersion>,
2568
2569    /// The platform for which packages should be checked.
2570    ///
2571    /// By default, the installed packages are checked against the platform of the current
2572    /// interpreter.
2573    ///
2574    /// Represented as a "target triple", a string that describes the target platform in terms of
2575    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
2576    /// `aarch64-apple-darwin`.
2577    ///
2578    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
2579    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
2580    ///
2581    /// When targeting iOS, the default minimum version is `13.0`. Use
2582    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
2583    ///
2584    /// When targeting Android, the default minimum Android API level is `24`. Use
2585    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
2586    #[arg(long)]
2587    python_platform: Option<TargetTriple>,
2588}
2589
2590#[derive(Args)]
2591pub struct PipShowArgs {
2592    /// The package(s) to display.
2593    #[arg(value_hint = ValueHint::Other)]
2594    package: Vec<PackageName>,
2595
2596    /// Validate the Python environment, to detect packages with missing dependencies and other
2597    /// issues.
2598    #[arg(long, overrides_with("no_strict"))]
2599    strict: bool,
2600
2601    #[arg(long, overrides_with("strict"), hide = true)]
2602    no_strict: bool,
2603
2604    /// Show the full list of installed files for each package.
2605    #[arg(short, long)]
2606    files: bool,
2607
2608    /// The Python interpreter to find the package in.
2609    ///
2610    /// By default, uv looks for packages in a virtual environment but will look for packages in a
2611    /// system Python environment if no virtual environment is found.
2612    ///
2613    /// See `uv help python` for details on Python discovery and supported request formats.
2614    #[arg(
2615        long,
2616        short,
2617        env = EnvVars::UV_PYTHON,
2618        verbatim_doc_comment,
2619        help_heading = "Python options",
2620        value_hint = ValueHint::Other,
2621    )]
2622    python: Option<Maybe<String>>,
2623
2624    /// Show a package in the system Python environment.
2625    ///
2626    /// Disables discovery of virtual environments.
2627    ///
2628    /// See `uv help python` for details on Python discovery.
2629    #[arg(
2630        long,
2631        env = EnvVars::UV_SYSTEM_PYTHON,
2632        value_parser = clap::builder::BoolishValueParser::new(),
2633        overrides_with("no_system")
2634    )]
2635    system: bool,
2636
2637    #[arg(long, overrides_with("system"), hide = true)]
2638    no_system: bool,
2639
2640    /// Show a package from the specified `--target` directory.
2641    #[arg(short = 't', long, conflicts_with = "prefix", value_hint = ValueHint::DirPath)]
2642    target: Option<PathBuf>,
2643
2644    /// Show a package from the specified `--prefix` directory.
2645    #[arg(long, conflicts_with = "target", value_hint = ValueHint::DirPath)]
2646    prefix: Option<PathBuf>,
2647
2648    #[command(flatten)]
2649    compat_args: compat::PipGlobalCompatArgs,
2650}
2651
2652#[derive(Args)]
2653pub struct PipTreeArgs {
2654    /// Show the version constraint(s) imposed on each package.
2655    #[arg(long)]
2656    show_version_specifiers: bool,
2657
2658    #[command(flatten)]
2659    tree: DisplayTreeArgs,
2660
2661    /// Validate the Python environment, to detect packages with missing dependencies and other
2662    /// issues.
2663    #[arg(long, overrides_with("no_strict"))]
2664    strict: bool,
2665
2666    #[arg(long, overrides_with("strict"), hide = true)]
2667    no_strict: bool,
2668
2669    #[command(flatten)]
2670    fetch: FetchArgs,
2671
2672    /// The Python interpreter for which packages should be listed.
2673    ///
2674    /// By default, uv lists packages in a virtual environment but will show packages in a system
2675    /// Python environment if no virtual environment is found.
2676    ///
2677    /// See `uv help python` for details on Python discovery and supported request formats.
2678    #[arg(
2679        long,
2680        short,
2681        env = EnvVars::UV_PYTHON,
2682        verbatim_doc_comment,
2683        help_heading = "Python options",
2684        value_hint = ValueHint::Other,
2685    )]
2686    python: Option<Maybe<String>>,
2687
2688    /// List packages in the system Python environment.
2689    ///
2690    /// Disables discovery of virtual environments.
2691    ///
2692    /// See `uv help python` for details on Python discovery.
2693    #[arg(
2694        long,
2695        env = EnvVars::UV_SYSTEM_PYTHON,
2696        value_parser = clap::builder::BoolishValueParser::new(),
2697        overrides_with("no_system")
2698    )]
2699    system: bool,
2700
2701    #[arg(long, overrides_with("system"), hide = true)]
2702    no_system: bool,
2703
2704    #[command(flatten)]
2705    compat_args: compat::PipGlobalCompatArgs,
2706}
2707
2708#[derive(Args)]
2709pub struct PipDebugArgs {
2710    #[arg(long, hide = true)]
2711    platform: Option<String>,
2712
2713    #[arg(long, hide = true)]
2714    python_version: Option<String>,
2715
2716    #[arg(long, hide = true)]
2717    implementation: Option<String>,
2718
2719    #[arg(long, hide = true)]
2720    abi: Option<String>,
2721}
2722
2723#[derive(Args)]
2724pub struct BuildArgs {
2725    /// Skip checking if build dependencies are satisfied when building without isolation.
2726    ///
2727    /// Only affects builds with the `build-dependency-check` preview feature enabled. By
2728    /// default, that feature checks declared, backend-reported, and transitive build requirements
2729    /// in the selected environment before building. Isolated builds install their requirements.
2730    #[arg(long, hide = true)]
2731    skip_dependency_check: bool,
2732
2733    /// The directory from which distributions should be built, or a source
2734    /// distribution archive to build into a wheel.
2735    ///
2736    /// Defaults to the current working directory.
2737    #[arg(value_parser = parse_file_path, value_hint = ValueHint::DirPath)]
2738    src: Option<PathBuf>,
2739
2740    /// Build a specific package in the workspace.
2741    ///
2742    /// The workspace will be discovered from the provided source directory, or the current
2743    /// directory if no source directory is provided.
2744    ///
2745    /// If the workspace member does not exist, uv will exit with an error.
2746    #[arg(long, conflicts_with("all_packages"), value_hint = ValueHint::Other)]
2747    package: Option<PackageName>,
2748
2749    /// Builds all packages in the workspace.
2750    ///
2751    /// The workspace will be discovered from the provided source directory, or the current
2752    /// directory if no source directory is provided.
2753    ///
2754    /// If the workspace member does not exist, uv will exit with an error.
2755    #[arg(long, alias = "all", conflicts_with("package"))]
2756    all_packages: bool,
2757
2758    /// The output directory to which distributions should be written.
2759    ///
2760    /// Defaults to the `dist` subdirectory within the source directory, or the
2761    /// directory containing the source distribution archive.
2762    #[arg(long, short, value_parser = parse_file_path, value_hint = ValueHint::DirPath)]
2763    out_dir: Option<PathBuf>,
2764
2765    /// Build a source distribution ("sdist") from the given directory.
2766    #[arg(long)]
2767    sdist: bool,
2768
2769    /// Build a binary distribution ("wheel") from the given directory.
2770    #[arg(long)]
2771    wheel: bool,
2772
2773    /// When using the uv build backend, list the files that would be included when building.
2774    ///
2775    /// Skips building the actual distribution, except when the source distribution is needed to
2776    /// build the wheel. The file list is collected directly without a PEP 517 environment. It only
2777    /// works with the uv build backend, there is no PEP 517 file list build hook.
2778    ///
2779    /// This option can be combined with `--sdist` and `--wheel` for inspecting different build
2780    /// paths.
2781    // Hidden while in preview.
2782    #[arg(long, hide = true)]
2783    list: bool,
2784
2785    #[arg(long, overrides_with("no_build_logs"), hide = true)]
2786    build_logs: bool,
2787
2788    /// Hide logs from the build backend.
2789    #[arg(long, overrides_with("build_logs"))]
2790    no_build_logs: bool,
2791
2792    /// Always build through PEP 517, don't use the fast path for the uv build backend.
2793    ///
2794    /// By default, uv won't create a PEP 517 build environment for packages using the uv build
2795    /// backend, but use a fast path that calls into the build backend directly. This option forces
2796    /// always using PEP 517.
2797    #[arg(long, conflicts_with = "list")]
2798    force_pep517: bool,
2799
2800    /// Clear the output directory before the build, removing stale artifacts.
2801    #[arg(long)]
2802    clear: bool,
2803
2804    #[arg(long, overrides_with("no_create_gitignore"), hide = true)]
2805    create_gitignore: bool,
2806
2807    /// Do not create a `.gitignore` file in the output directory.
2808    ///
2809    /// By default, uv creates a `.gitignore` file in the output directory to exclude build
2810    /// artifacts from version control. When this flag is used, the file will be omitted.
2811    #[arg(long, overrides_with("create_gitignore"))]
2812    no_create_gitignore: bool,
2813
2814    /// Constrain build dependencies using the given requirements files when building distributions.
2815    ///
2816    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
2817    /// build dependency that's installed. However, including a package in a constraints file will
2818    /// _not_ trigger the inclusion of that package on its own.
2819    #[arg(
2820        long,
2821        short,
2822        alias = "build-constraint",
2823        env = EnvVars::UV_BUILD_CONSTRAINT,
2824        value_delimiter = ' ',
2825        value_hint = ValueHint::FilePath,
2826    )]
2827    build_constraints: Vec<Maybe<RequirementsInput>>,
2828
2829    #[command(flatten)]
2830    hash_checking: HashCheckingArgs,
2831
2832    /// The Python interpreter to use for the build environment.
2833    ///
2834    /// By default, builds are executed in isolated virtual environments. The discovered interpreter
2835    /// will be used to create those environments, and will be symlinked or copied in depending on
2836    /// the platform.
2837    ///
2838    /// See `uv help python` to view supported request formats.
2839    #[arg(
2840        long,
2841        short,
2842        env = EnvVars::UV_PYTHON,
2843        verbatim_doc_comment,
2844        help_heading = "Python options",
2845        value_hint = ValueHint::Other,
2846    )]
2847    python: Option<Maybe<String>>,
2848
2849    #[command(flatten)]
2850    resolver: ResolverArgs,
2851
2852    #[command(flatten)]
2853    build: BuildOptionsArgs,
2854
2855    #[command(flatten)]
2856    refresh: RefreshArgs,
2857}
2858
2859#[derive(Args)]
2860pub struct VenvArgs {
2861    /// The Python interpreter to use for the virtual environment.
2862    ///
2863    /// During virtual environment creation, uv will not look for Python interpreters in virtual
2864    /// environments.
2865    ///
2866    /// See `uv help python` for details on Python discovery and supported request formats.
2867    #[arg(
2868        long,
2869        short,
2870        env = EnvVars::UV_PYTHON,
2871        verbatim_doc_comment,
2872        help_heading = "Python options",
2873        value_hint = ValueHint::Other,
2874    )]
2875    pub python: Option<Maybe<String>>,
2876
2877    /// Ignore virtual environments when searching for the Python interpreter.
2878    ///
2879    /// This is the default behavior and has no effect.
2880    #[arg(
2881        long,
2882        env = EnvVars::UV_SYSTEM_PYTHON,
2883        value_parser = clap::builder::BoolishValueParser::new(),
2884        overrides_with("no_system"),
2885        hide = true,
2886    )]
2887    pub system: bool,
2888
2889    /// This flag is included for compatibility only, it has no effect.
2890    ///
2891    /// uv will never search for interpreters in virtual environments when creating a virtual
2892    /// environment.
2893    #[arg(long, overrides_with("system"), hide = true)]
2894    pub no_system: bool,
2895
2896    /// Avoid discovering a project or workspace.
2897    ///
2898    /// By default, uv searches for projects in the current directory or any parent directory to
2899    /// determine the default path of the virtual environment and check for Python version
2900    /// constraints, if any.
2901    #[arg(
2902        long,
2903        alias = "no-workspace",
2904        env = EnvVars::UV_NO_PROJECT,
2905        value_parser = clap::builder::BoolishValueParser::new()
2906    )]
2907    pub no_project: bool,
2908
2909    /// Install seed packages (one or more of: `pip`, `setuptools`, and `wheel`) into the virtual
2910    /// environment [env: UV_VENV_SEED=]
2911    ///
2912    /// Note that `setuptools` and `wheel` are not included in Python 3.12+ environments.
2913    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
2914    pub seed: bool,
2915
2916    /// Remove any existing files or directories at the target path [env: UV_VENV_CLEAR=]
2917    ///
2918    /// By default, `uv venv` will exit with an error if the given path is non-empty. The
2919    /// `--clear` option will instead clear a non-empty path before creating a new virtual
2920    /// environment.
2921    #[clap(long, short, overrides_with = "allow_existing", value_parser = clap::builder::BoolishValueParser::new())]
2922    pub clear: bool,
2923
2924    /// Allow `--clear` to remove a non-virtual environment directory.
2925    ///
2926    /// This will remove all files and directories at the target path.
2927    #[arg(long)]
2928    pub force: bool,
2929
2930    /// Fail without prompting if any existing files or directories are present at the target path.
2931    ///
2932    /// By default, when a TTY is available, `uv venv` will prompt to clear a non-empty directory.
2933    /// When `--no-clear` is used, the command will exit with an error instead of prompting.
2934    #[clap(
2935        long,
2936        overrides_with = "clear",
2937        conflicts_with = "allow_existing",
2938        hide = true
2939    )]
2940    pub no_clear: bool,
2941
2942    /// Preserve any existing files or directories at the target path.
2943    ///
2944    /// By default, `uv venv` will exit with an error if the given path is non-empty. The
2945    /// `--allow-existing` option will instead write to the given path, regardless of its contents,
2946    /// and without clearing it beforehand.
2947    ///
2948    /// WARNING: This option can lead to unexpected behavior if the existing virtual environment and
2949    /// the newly-created virtual environment are linked to different Python interpreters.
2950    #[clap(long, overrides_with = "clear")]
2951    pub allow_existing: bool,
2952
2953    /// The path to the virtual environment to create.
2954    ///
2955    /// Default to `.venv` in the working directory.
2956    ///
2957    /// Relative paths are resolved relative to the working directory.
2958    #[arg(value_hint = ValueHint::DirPath)]
2959    pub path: Option<PathBuf>,
2960
2961    /// Provide an alternative prompt prefix for the virtual environment.
2962    ///
2963    /// By default, the prompt is dependent on whether a path was provided to `uv venv`. If provided
2964    /// (e.g, `uv venv project`), the prompt is set to the directory name. If not provided
2965    /// (`uv venv`), the prompt is set to the current directory's name.
2966    ///
2967    /// If "." is provided, the current directory name will be used regardless of whether a path was
2968    /// provided to `uv venv`.
2969    #[arg(long, verbatim_doc_comment, value_hint = ValueHint::Other)]
2970    pub prompt: Option<String>,
2971
2972    /// Give the virtual environment access to the system site packages directory.
2973    ///
2974    /// Unlike `pip`, when a virtual environment is created with `--system-site-packages`, uv will
2975    /// _not_ take system site packages into account when running commands like `uv pip list` or `uv
2976    /// pip install`. The `--system-site-packages` flag will provide the virtual environment with
2977    /// access to the system site packages directory at runtime, but will not affect the behavior of
2978    /// uv commands.
2979    #[arg(long)]
2980    pub system_site_packages: bool,
2981
2982    /// Make the virtual environment relocatable [env: UV_VENV_RELOCATABLE=]
2983    ///
2984    /// A relocatable virtual environment can be moved around and redistributed without invalidating
2985    /// its associated entrypoint and activation scripts.
2986    ///
2987    /// Note that this can only be guaranteed for standard `console_scripts` and `gui_scripts`.
2988    /// Other scripts may be adjusted if they ship with a generic `#!python[w]` shebang, and
2989    /// binaries are left as-is.
2990    ///
2991    /// As a result of making the environment relocatable (by way of writing relative, rather than
2992    /// absolute paths), the entrypoints and scripts themselves will _not_ be relocatable. In other
2993    /// words, copying those entrypoints and scripts to a location outside the environment will not
2994    /// work, as they reference paths relative to the environment itself.
2995    #[expect(clippy::doc_markdown)]
2996    #[arg(long, overrides_with("no_relocatable"))]
2997    pub relocatable: bool,
2998
2999    /// Don't make the virtual environment relocatable.
3000    ///
3001    /// Disables the default relocatable behavior when the `relocatable-envs-default` preview
3002    /// feature is enabled.
3003    #[arg(long, overrides_with("relocatable"), hide = true)]
3004    pub no_relocatable: bool,
3005
3006    #[command(flatten)]
3007    pub index_args: IndexArgs,
3008
3009    #[command(flatten)]
3010    pub registry_client: RegistryClientArgs,
3011
3012    #[command(flatten)]
3013    pub exclude_newer: PackageExcludeNewerArgs,
3014
3015    /// The method to use when installing packages from the global cache.
3016    ///
3017    /// This option is only used for installing seed packages.
3018    ///
3019    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
3020    /// Windows.
3021    ///
3022    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
3023    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
3024    /// will break all installed packages by way of removing the underlying source files. Use
3025    /// symlinks with caution.
3026    #[arg(long, value_enum, env = EnvVars::UV_LINK_MODE)]
3027    pub link_mode: Option<uv_install_wheel::LinkMode>,
3028
3029    #[command(flatten)]
3030    pub refresh: RefreshArgs,
3031
3032    #[command(flatten)]
3033    pub compat_args: compat::VenvCompatArgs,
3034}
3035
3036#[derive(Parser, Debug, Clone)]
3037pub enum ExternalCommand {
3038    #[command(external_subcommand)]
3039    Cmd(Vec<OsString>),
3040}
3041
3042impl Deref for ExternalCommand {
3043    type Target = Vec<OsString>;
3044
3045    fn deref(&self) -> &Self::Target {
3046        match self {
3047            Self::Cmd(cmd) => cmd,
3048        }
3049    }
3050}
3051
3052impl DerefMut for ExternalCommand {
3053    fn deref_mut(&mut self) -> &mut Self::Target {
3054        match self {
3055            Self::Cmd(cmd) => cmd,
3056        }
3057    }
3058}
3059
3060#[derive(Args)]
3061pub struct InitArgs {
3062    /// The path to use for the project/script.
3063    ///
3064    /// Defaults to the current working directory when initializing an app or library; required when
3065    /// initializing a script. Accepts relative and absolute paths.
3066    ///
3067    /// If a `pyproject.toml` is found in any of the parent directories of the target path, the
3068    /// project will be added as a workspace member of the parent, unless `--no-workspace` is
3069    /// provided.
3070    #[arg(required_if_eq("script", "true"), value_hint = ValueHint::DirPath)]
3071    path: Option<PathBuf>,
3072
3073    /// The name of the project.
3074    ///
3075    /// Defaults to the name of the directory.
3076    #[arg(long, conflicts_with = "script", value_hint = ValueHint::Other)]
3077    name: Option<PackageName>,
3078
3079    /// Only create a `pyproject.toml`.
3080    ///
3081    /// Disables creating extra files like `README.md`, the `src/` tree, `.python-version` files,
3082    /// etc.
3083    ///
3084    /// A `[build-system]` table is only created with `--package` or `--build-backend`.
3085    ///
3086    /// When combined with `--script`, the script will only contain the inline metadata header.
3087    #[arg(long)]
3088    bare: bool,
3089
3090    /// Create a virtual project, rather than a package.
3091    ///
3092    /// This option is deprecated and will be removed in a future release.
3093    #[arg(long, hide = true, conflicts_with = "package")]
3094    r#virtual: bool,
3095
3096    /// Set up the project to be built as a Python package.
3097    ///
3098    /// Defines a `[build-system]` for the project.
3099    ///
3100    /// This is the default behavior.
3101    #[arg(long, overrides_with = "no_package")]
3102    r#package: bool,
3103
3104    /// Do not set up the project to be built as a Python package.
3105    ///
3106    /// This option creates the project structure as a flat directory that is not importable as a
3107    /// module and has no `[build-system]` entry. It can be used for applications that are not
3108    /// expected to be distributed as a package.
3109    #[arg(long, overrides_with = "package", conflicts_with_all = ["lib", "build_backend"])]
3110    r#no_package: bool,
3111
3112    /// Create a project for an application.
3113    ///
3114    /// This project kind is for web servers, scripts, and command-line interfaces.
3115    ///
3116    /// Applications are packaged by default. Use `--no-package` to create an unpackaged application.
3117    #[arg(long, alias = "application", conflicts_with_all = ["lib", "script"])]
3118    r#app: bool,
3119
3120    /// Create a project for a library.
3121    ///
3122    /// A library is a project that is intended to be built and distributed as a Python package.
3123    #[arg(long, alias = "library", conflicts_with_all=["app", "script"])]
3124    r#lib: bool,
3125
3126    /// Create a script.
3127    ///
3128    /// A script is a standalone file with embedded metadata enumerating its dependencies, along
3129    /// with any Python version requirements, as defined in the PEP 723 specification.
3130    ///
3131    /// PEP 723 scripts can be executed directly with `uv run`.
3132    ///
3133    /// By default, adds a requirement on the system Python version; use `--python` to specify an
3134    /// alternative Python version requirement.
3135    #[arg(long, conflicts_with_all=["app", "lib", "package", "build_backend", "description"])]
3136    r#script: bool,
3137
3138    /// Set the project description.
3139    #[arg(long, conflicts_with = "script", overrides_with = "no_description", value_hint = ValueHint::Other)]
3140    description: Option<String>,
3141
3142    /// Disable the description for the project.
3143    #[arg(long, conflicts_with = "script", overrides_with = "description")]
3144    no_description: bool,
3145
3146    /// Initialize a version control system for the project.
3147    ///
3148    /// By default, uv will initialize a Git repository (`git`). Use `--vcs none` to explicitly
3149    /// avoid initializing a version control system.
3150    #[arg(long, value_enum, conflicts_with = "script")]
3151    vcs: Option<VersionControlSystem>,
3152
3153    /// Initialize a build-backend of choice for the project.
3154    ///
3155    /// Implicitly sets `--package`.
3156    #[arg(long, value_enum, conflicts_with_all=["script", "no_package"], env = EnvVars::UV_INIT_BUILD_BACKEND)]
3157    build_backend: Option<ProjectBuildBackend>,
3158
3159    /// Invalid option name for build backend.
3160    #[arg(
3161        long,
3162        required(false),
3163        action(clap::ArgAction::SetTrue),
3164        value_parser=clap::builder::UnknownArgumentValueParser::suggest_arg("--build-backend"),
3165        hide(true)
3166    )]
3167    backend: Option<String>,
3168
3169    /// Do not create a `README.md` file.
3170    #[arg(long)]
3171    no_readme: bool,
3172
3173    /// Fill in the `authors` field in the `pyproject.toml`.
3174    ///
3175    /// By default, uv will attempt to infer the author information from some sources (e.g., Git)
3176    /// (`auto`). Use `--author-from git` to only infer from Git configuration. Use `--author-from
3177    /// none` to avoid inferring the author information.
3178    #[arg(long, value_enum)]
3179    author_from: Option<AuthorFrom>,
3180
3181    /// Do not create a `.python-version` file for the project.
3182    ///
3183    /// By default, uv will create a `.python-version` file containing the minor version of the
3184    /// discovered Python interpreter, which will cause subsequent uv commands to use that version.
3185    #[arg(long)]
3186    no_pin_python: bool,
3187
3188    /// Create a `.python-version` file for the project.
3189    ///
3190    /// This is the default.
3191    #[arg(long, hide = true)]
3192    pin_python: bool,
3193
3194    /// Avoid discovering a workspace and create a standalone project.
3195    ///
3196    /// By default, uv searches for workspaces in the current directory or any parent directory.
3197    #[arg(long, alias = "no-project")]
3198    no_workspace: bool,
3199
3200    /// The Python interpreter to use to determine the minimum supported Python version.
3201    ///
3202    /// See `uv help python` to view supported request formats.
3203    #[arg(
3204        long,
3205        short,
3206        env = EnvVars::UV_PYTHON,
3207        verbatim_doc_comment,
3208        help_heading = "Python options",
3209        value_hint = ValueHint::Other,
3210    )]
3211    python: Option<Maybe<String>>,
3212}
3213
3214#[derive(Args)]
3215pub struct RunArgs {
3216    /// Include optional dependencies from the specified extra name.
3217    ///
3218    /// May be provided more than once.
3219    ///
3220    /// This option is only available when running in a project.
3221    #[arg(
3222        long,
3223        conflicts_with = "all_extras",
3224        conflicts_with = "only_group",
3225        value_delimiter = ',',
3226        value_parser = extra_name_with_clap_error,
3227        value_hint = ValueHint::Other,
3228    )]
3229    pub extra: Option<Vec<ExtraName>>,
3230
3231    /// Include all optional dependencies.
3232    ///
3233    /// This option is only available when running in a project.
3234    #[arg(long, conflicts_with = "extra", conflicts_with = "only_group")]
3235    pub all_extras: bool,
3236
3237    /// Exclude the specified optional dependencies, if `--all-extras` is supplied.
3238    ///
3239    /// May be provided multiple times.
3240    #[arg(long, value_hint = ValueHint::Other)]
3241    pub no_extra: Vec<ExtraName>,
3242
3243    #[arg(long, overrides_with("all_extras"), hide = true)]
3244    pub no_all_extras: bool,
3245
3246    #[command(flatten)]
3247    pub dependency_groups: ProjectDependencyGroupsArgs,
3248
3249    /// Run a Python module.
3250    ///
3251    /// Equivalent to `python -m <module>`.
3252    #[arg(short, long, conflicts_with_all = ["script", "gui_script"])]
3253    pub module: bool,
3254
3255    /// Install any non-editable dependencies, including the project and any workspace members, as
3256    /// editable.
3257    #[arg(long, overrides_with = "no_editable", hide = true)]
3258    pub editable: bool,
3259
3260    /// Install any editable dependencies, including the project and any workspace members, as
3261    /// non-editable [env: UV_NO_EDITABLE=]
3262    #[arg(long, overrides_with = "editable", value_parser = clap::builder::BoolishValueParser::new())]
3263    pub no_editable: bool,
3264
3265    /// Install the specified editable packages as non-editable.
3266    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other)]
3267    pub no_editable_package: Vec<PackageName>,
3268
3269    /// Do not remove extraneous packages present in the environment.
3270    #[arg(long, overrides_with("exact"), alias = "no-exact", hide = true)]
3271    pub inexact: bool,
3272
3273    /// Perform an exact sync, removing extraneous packages.
3274    ///
3275    /// When enabled, uv will remove any extraneous packages from the environment. By default, `uv
3276    /// run` will make the minimum necessary changes to satisfy the requirements.
3277    #[arg(long, overrides_with("inexact"))]
3278    pub exact: bool,
3279
3280    /// Load environment variables from a `.env` file.
3281    ///
3282    /// Can be provided multiple times, with subsequent files overriding values defined in previous
3283    /// files.
3284    #[arg(long, env = EnvVars::UV_ENV_FILE, value_hint = ValueHint::FilePath)]
3285    pub env_file: Vec<String>,
3286
3287    /// Avoid reading environment variables from a `.env` file [env: UV_NO_ENV_FILE=]
3288    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
3289    pub no_env_file: bool,
3290
3291    /// The command to run.
3292    ///
3293    /// If the path to a Python script (i.e., ending in `.py`), it will be
3294    /// executed with the Python interpreter.
3295    #[command(subcommand)]
3296    pub command: Option<ExternalCommand>,
3297
3298    /// Run with the given packages installed.
3299    ///
3300    /// When used in a project, these dependencies will be layered on top of the project environment
3301    /// in a separate, ephemeral environment. These dependencies are allowed to conflict with those
3302    /// specified by the project.
3303    #[arg(short = 'w', long, value_hint = ValueHint::Other)]
3304    pub with: Vec<comma::CommaSeparatedRequirements>,
3305
3306    /// Run with the given packages installed in editable mode.
3307    ///
3308    /// When used in a project, these dependencies will be layered on top of the project environment
3309    /// in a separate, ephemeral environment. These dependencies are allowed to conflict with those
3310    /// specified by the project.
3311    #[arg(long, value_hint = ValueHint::DirPath)]
3312    pub with_editable: Vec<comma::CommaSeparatedRequirements>,
3313
3314    /// Run with the packages listed in the given files.
3315    ///
3316    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
3317    /// and `pylock.toml`.
3318    ///
3319    /// The same environment semantics as `--with` apply.
3320    ///
3321    /// Using `pyproject.toml`, `setup.py`, or `setup.cfg` files is not allowed.
3322    #[arg(long, value_delimiter = ',', value_hint = ValueHint::FilePath)]
3323    pub with_requirements: Vec<Maybe<RequirementsInput>>,
3324
3325    /// Run the command in an isolated virtual environment [env: UV_ISOLATED=]
3326    ///
3327    /// Usually, the project environment is reused for performance. This option forces a fresh
3328    /// environment to be used for the project, enforcing strict isolation between dependencies and
3329    /// declaration of requirements.
3330    ///
3331    /// An editable installation is still used for the project.
3332    ///
3333    /// When used with `--with` or `--with-requirements`, the additional dependencies will still be
3334    /// layered in a second environment.
3335    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
3336    pub isolated: bool,
3337
3338    /// Prefer the active virtual environment over the project's virtual environment.
3339    ///
3340    /// If the project virtual environment is active or no virtual environment is active, this has
3341    /// no effect.
3342    #[arg(long, overrides_with = "no_active")]
3343    pub active: bool,
3344
3345    /// Prefer project's virtual environment over an active environment.
3346    ///
3347    /// This is the default behavior.
3348    #[arg(long, overrides_with = "active", hide = true)]
3349    pub no_active: bool,
3350
3351    /// Avoid syncing the virtual environment [env: UV_NO_SYNC=]
3352    ///
3353    /// Implies `--frozen`, as the project dependencies will be ignored (i.e., the lockfile will not
3354    /// be updated, since the environment will not be synced regardless).
3355    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
3356    pub no_sync: bool,
3357
3358    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
3359    ///
3360    /// Requires that the lockfile is up-to-date. If the lockfile is missing or
3361    /// needs to be updated, uv will exit with an error.
3362    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
3363    pub locked: bool,
3364
3365    /// Disable locked mode, overriding `UV_LOCKED`.
3366    #[arg(long, overrides_with = "locked", hide = true)]
3367    pub no_locked: bool,
3368
3369    /// Run without updating the `uv.lock` file [env: UV_FROZEN=]
3370    ///
3371    /// Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the
3372    /// source of truth. If the lockfile is missing, uv will exit with an error. If the
3373    /// `pyproject.toml` includes changes to dependencies that have not been included in the
3374    /// lockfile yet, they will not be present in the environment.
3375    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
3376    pub frozen: bool,
3377
3378    /// Disable frozen mode, overriding `UV_FROZEN`.
3379    #[arg(long, overrides_with = "frozen", hide = true)]
3380    pub no_frozen: bool,
3381
3382    /// Run the given path as a Python script.
3383    ///
3384    /// Using `--script` will attempt to parse the path as a PEP 723 script,
3385    /// irrespective of its extension.
3386    #[arg(long, short, conflicts_with_all = ["module", "gui_script"])]
3387    pub script: bool,
3388
3389    /// Run the given path as a Python GUI script.
3390    ///
3391    /// Using `--gui-script` will attempt to parse the path as a PEP 723 script and run it with
3392    /// `pythonw.exe`, irrespective of its extension. Only available on Windows.
3393    #[arg(long, conflicts_with_all = ["script", "module"])]
3394    pub gui_script: bool,
3395
3396    #[command(flatten)]
3397    pub installer: ResolverInstallerArgs,
3398
3399    #[command(flatten)]
3400    pub build: BuildOptionsArgs,
3401
3402    #[command(flatten)]
3403    pub refresh: RefreshArgs,
3404
3405    /// Run the command with all workspace members installed.
3406    ///
3407    /// The workspace's environment (`.venv`) is updated to include all workspace members.
3408    ///
3409    /// Any extras or groups specified via `--extra`, `--group`, or related options will be applied
3410    /// to all workspace members.
3411    #[arg(long, conflicts_with = "package")]
3412    pub all_packages: bool,
3413
3414    /// Run the command in a specific package in the workspace.
3415    ///
3416    /// If the workspace member does not exist, uv will exit with an error.
3417    #[arg(long, conflicts_with = "all_packages", value_hint = ValueHint::Other)]
3418    pub package: Option<PackageName>,
3419
3420    /// Avoid discovering the project or workspace.
3421    ///
3422    /// Instead of searching for projects in the current directory and parent directories, run in an
3423    /// isolated, ephemeral environment populated by the `--with` requirements.
3424    ///
3425    /// If a virtual environment is active or found in a current or parent directory, it will be
3426    /// used as if there was no project or workspace.
3427    #[arg(
3428        long,
3429        alias = "no_workspace",
3430        env = EnvVars::UV_NO_PROJECT,
3431        value_parser = clap::builder::BoolishValueParser::new(),
3432        conflicts_with = "package"
3433    )]
3434    pub no_project: bool,
3435
3436    /// The Python interpreter to use for the run environment.
3437    ///
3438    /// If the interpreter request is satisfied by a discovered environment, the environment will be
3439    /// used.
3440    ///
3441    /// See `uv help python` to view supported request formats.
3442    #[arg(
3443        long,
3444        short,
3445        env = EnvVars::UV_PYTHON,
3446        verbatim_doc_comment,
3447        help_heading = "Python options",
3448        value_hint = ValueHint::Other,
3449    )]
3450    pub python: Option<Maybe<String>>,
3451
3452    /// Whether to show resolver and installer output from any environment modifications [env:
3453    /// UV_SHOW_RESOLUTION=]
3454    ///
3455    /// By default, environment modifications are omitted, but enabled under `--verbose`.
3456    #[arg(long, value_parser = clap::builder::BoolishValueParser::new(), hide = true)]
3457    pub show_resolution: bool,
3458
3459    /// Number of times that `uv run` will allow recursive invocations.
3460    ///
3461    /// The current recursion depth is tracked by environment variable. If environment variables are
3462    /// cleared, uv will fail to detect the recursion depth.
3463    ///
3464    /// If uv reaches the maximum recursion depth, it will exit with an error.
3465    #[arg(long, hide = true, env = EnvVars::UV_RUN_MAX_RECURSION_DEPTH)]
3466    pub max_recursion_depth: Option<u32>,
3467
3468    /// The platform for which requirements should be installed.
3469    ///
3470    /// Represented as a "target triple", a string that describes the target platform in terms of
3471    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
3472    /// `aarch64-apple-darwin`.
3473    ///
3474    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
3475    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
3476    ///
3477    /// When targeting iOS, the default minimum version is `13.0`. Use
3478    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
3479    ///
3480    /// When targeting Android, the default minimum Android API level is `24`. Use
3481    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
3482    ///
3483    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
3484    /// platform; as a result, the installed distributions may not be compatible with the _current_
3485    /// platform. Conversely, any distributions that are built from source may be incompatible with
3486    /// the _target_ platform, as they will be built for the _current_ platform. The
3487    /// `--python-platform` option is intended for advanced use cases.
3488    #[arg(long)]
3489    pub python_platform: Option<TargetTriple>,
3490}
3491
3492#[derive(Args)]
3493pub struct SyncArgs {
3494    /// Include optional dependencies from the specified extra name.
3495    ///
3496    /// May be provided more than once.
3497    ///
3498    /// When multiple extras or groups are specified that appear in `tool.uv.conflicts`, uv will
3499    /// report an error.
3500    ///
3501    /// Note that all optional dependencies are always included in the resolution; this option only
3502    /// affects the selection of packages to install.
3503    #[arg(
3504        long,
3505        conflicts_with = "all_extras",
3506        conflicts_with = "only_group",
3507        value_delimiter = ',',
3508        value_parser = extra_name_with_clap_error,
3509        value_hint = ValueHint::Other,
3510    )]
3511    pub extra: Option<Vec<ExtraName>>,
3512
3513    /// Select the output format.
3514    ///
3515    /// JSON output is written to stdout; diagnostic messages are written to stderr.
3516    /// The JSON schema is experimental and may change without warning.
3517    #[arg(long, value_enum, default_value_t = SyncFormat::default())]
3518    pub output_format: SyncFormat,
3519
3520    /// Include all optional dependencies.
3521    ///
3522    /// When two or more extras are declared as conflicting in `tool.uv.conflicts`, using this flag
3523    /// will always result in an error.
3524    ///
3525    /// Note that all optional dependencies are always included in the resolution; this option only
3526    /// affects the selection of packages to install.
3527    #[arg(long, conflicts_with = "extra", conflicts_with = "only_group")]
3528    pub all_extras: bool,
3529
3530    /// Exclude the specified optional dependencies, if `--all-extras` is supplied.
3531    ///
3532    /// May be provided multiple times.
3533    #[arg(long, value_hint = ValueHint::Other)]
3534    pub no_extra: Vec<ExtraName>,
3535
3536    #[arg(long, overrides_with("all_extras"), hide = true)]
3537    pub no_all_extras: bool,
3538
3539    #[command(flatten)]
3540    pub dependency_groups: ConflictCheckedDependencyGroupsArgs,
3541
3542    /// Install any non-editable dependencies, including the project and any workspace members, as
3543    /// editable.
3544    #[arg(long, overrides_with = "no_editable", hide = true)]
3545    pub editable: bool,
3546
3547    /// Install any editable dependencies, including the project and any workspace members, as
3548    /// non-editable [env: UV_NO_EDITABLE=]
3549    #[arg(long, overrides_with = "editable", value_parser = clap::builder::BoolishValueParser::new())]
3550    pub no_editable: bool,
3551
3552    /// Install the specified editable packages as non-editable.
3553    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other)]
3554    pub no_editable_package: Vec<PackageName>,
3555
3556    /// Do not remove extraneous packages present in the environment.
3557    ///
3558    /// When enabled, uv will make the minimum necessary changes to satisfy the requirements.
3559    /// By default, syncing will remove any extraneous packages from the environment
3560    #[arg(long, overrides_with("exact"), alias = "no-exact")]
3561    pub inexact: bool,
3562
3563    /// Perform an exact sync, removing extraneous packages.
3564    #[arg(long, overrides_with("inexact"), hide = true)]
3565    pub exact: bool,
3566
3567    /// Sync dependencies to the active virtual environment.
3568    ///
3569    /// Instead of creating or updating the virtual environment for the project or script, the
3570    /// active virtual environment will be preferred, if the `VIRTUAL_ENV` environment variable is
3571    /// set.
3572    #[arg(long, overrides_with = "no_active")]
3573    pub active: bool,
3574
3575    /// Prefer project's virtual environment over an active environment.
3576    ///
3577    /// This is the default behavior.
3578    #[arg(long, overrides_with = "active", hide = true)]
3579    pub no_active: bool,
3580
3581    /// Do not install the current project [env: UV_NO_INSTALL_PROJECT=]
3582    ///
3583    /// By default, the current project is installed into the environment with all of its
3584    /// dependencies. The `--no-install-project` option allows the project to be excluded, but all
3585    /// of its dependencies are still installed. This is particularly useful in situations like
3586    /// building Docker images where installing the project separately from its dependencies allows
3587    /// optimal layer caching.
3588    ///
3589    /// The inverse `--only-install-project` can be used to install _only_ the project itself,
3590    /// excluding all dependencies.
3591    #[arg(long, conflicts_with = "only_install_project")]
3592    pub no_install_project: bool,
3593
3594    /// Only install the current project.
3595    #[arg(long, conflicts_with = "no_install_project", hide = true)]
3596    pub only_install_project: bool,
3597
3598    /// Do not install any workspace members, including the root project [env: UV_NO_INSTALL_WORKSPACE=]
3599    ///
3600    /// By default, all workspace members and their dependencies are installed into the
3601    /// environment. The `--no-install-workspace` option allows exclusion of all the workspace
3602    /// members while retaining their dependencies. This is particularly useful in situations like
3603    /// building Docker images where installing the workspace separately from its dependencies
3604    /// allows optimal layer caching.
3605    ///
3606    /// The inverse `--only-install-workspace` can be used to install _only_ workspace members,
3607    /// excluding all other dependencies.
3608    #[arg(long, conflicts_with = "only_install_workspace")]
3609    pub no_install_workspace: bool,
3610
3611    /// Only install workspace members, including the root project.
3612    #[arg(long, conflicts_with = "no_install_workspace", hide = true)]
3613    pub only_install_workspace: bool,
3614
3615    /// Do not install local path dependencies [env: UV_NO_INSTALL_LOCAL=]
3616    ///
3617    /// Skips the current project, workspace members, and any other local (path or editable)
3618    /// packages. Only remote/indexed dependencies are installed. Useful in Docker builds to cache
3619    /// heavy third-party dependencies first and layer local packages separately.
3620    ///
3621    /// The inverse `--only-install-local` can be used to install _only_ local packages, excluding
3622    /// all remote dependencies.
3623    #[arg(long, conflicts_with = "only_install_local")]
3624    pub no_install_local: bool,
3625
3626    /// Only install local path dependencies
3627    #[arg(long, conflicts_with = "no_install_local", hide = true)]
3628    pub only_install_local: bool,
3629
3630    /// Do not install the given package(s).
3631    ///
3632    /// By default, all of the project's dependencies are installed into the environment. The
3633    /// `--no-install-package` option allows exclusion of specific packages. Note this can result
3634    /// in a broken environment, and should be used with caution.
3635    ///
3636    /// The inverse `--only-install-package` can be used to install _only_ the specified packages,
3637    /// excluding all others.
3638    #[arg(long, conflicts_with = "only_install_package", value_hint = ValueHint::Other)]
3639    pub no_install_package: Vec<PackageName>,
3640
3641    /// Only install the given package(s).
3642    #[arg(long, conflicts_with = "no_install_package", hide = true, value_hint = ValueHint::Other)]
3643    pub only_install_package: Vec<PackageName>,
3644
3645    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
3646    ///
3647    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
3648    /// uv will exit with an error.
3649    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
3650    pub locked: bool,
3651
3652    /// Disable locked mode, overriding `UV_LOCKED`.
3653    #[arg(long, overrides_with = "locked", hide = true)]
3654    pub no_locked: bool,
3655
3656    /// Sync without updating the `uv.lock` file [env: UV_FROZEN=]
3657    ///
3658    /// Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the
3659    /// source of truth. If the lockfile is missing, uv will exit with an error. If the
3660    /// `pyproject.toml` includes changes to dependencies that have not been included in the
3661    /// lockfile yet, they will not be present in the environment.
3662    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
3663    pub frozen: bool,
3664
3665    /// Disable frozen mode, overriding `UV_FROZEN`.
3666    #[arg(long, overrides_with = "frozen", hide = true)]
3667    pub no_frozen: bool,
3668
3669    /// Perform a dry run, without writing the lockfile or modifying the project environment.
3670    ///
3671    /// In dry-run mode, uv will resolve the project's dependencies and report on the resulting
3672    /// changes to both the lockfile and the project environment, but will not modify either.
3673    #[arg(long)]
3674    pub dry_run: bool,
3675
3676    #[command(flatten)]
3677    pub installer: ResolverInstallerArgs,
3678
3679    #[command(flatten)]
3680    pub build: BuildOptionsArgs,
3681
3682    #[command(flatten)]
3683    pub refresh: RefreshArgs,
3684
3685    /// Sync all packages in the workspace.
3686    ///
3687    /// The workspace's environment (`.venv`) is updated to include all workspace members.
3688    ///
3689    /// Any extras or groups specified via `--extra`, `--group`, or related options will be applied
3690    /// to all workspace members.
3691    #[arg(long, conflicts_with = "package")]
3692    pub all_packages: bool,
3693
3694    /// Sync for specific packages in the workspace.
3695    ///
3696    /// The workspace's environment (`.venv`) is updated to reflect the subset of dependencies
3697    /// declared by the specified workspace member packages.
3698    ///
3699    /// If any workspace member does not exist, uv will exit with an error.
3700    #[arg(long, conflicts_with = "all_packages", value_hint = ValueHint::Other)]
3701    pub package: Vec<PackageName>,
3702
3703    /// Sync the environment for a Python script, rather than the current project.
3704    ///
3705    /// If provided, uv will sync the dependencies based on the script's inline metadata table, in
3706    /// adherence with PEP 723.
3707    #[arg(
3708        long,
3709        conflicts_with = "all_packages",
3710        conflicts_with = "package",
3711        conflicts_with = "no_install_project",
3712        conflicts_with = "no_install_workspace",
3713        conflicts_with = "no_install_local",
3714        conflicts_with = "extra",
3715        conflicts_with = "all_extras",
3716        conflicts_with = "no_extra",
3717        conflicts_with = "no_all_extras",
3718        conflicts_with = "dev",
3719        conflicts_with = "no_dev",
3720        conflicts_with = "only_dev",
3721        conflicts_with = "group",
3722        conflicts_with = "no_group",
3723        conflicts_with = "no_default_groups",
3724        conflicts_with = "only_group",
3725        conflicts_with = "all_groups",
3726        value_hint = ValueHint::FilePath,
3727    )]
3728    pub script: Option<PathBuf>,
3729
3730    /// The Python interpreter to use for the project environment.
3731    ///
3732    /// By default, the first interpreter that meets the project's `requires-python` constraint is
3733    /// used.
3734    ///
3735    /// If a Python interpreter in a virtual environment is provided, the packages will not be
3736    /// synced to the given environment. The interpreter will be used to create a virtual
3737    /// environment in the project.
3738    ///
3739    /// See `uv help python` for details on Python discovery and supported request formats.
3740    #[arg(
3741        long,
3742        short,
3743        env = EnvVars::UV_PYTHON,
3744        verbatim_doc_comment,
3745        help_heading = "Python options",
3746        value_hint = ValueHint::Other,
3747    )]
3748    pub python: Option<Maybe<String>>,
3749
3750    /// The platform for which requirements should be installed.
3751    ///
3752    /// Represented as a "target triple", a string that describes the target platform in terms of
3753    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
3754    /// `aarch64-apple-darwin`.
3755    ///
3756    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
3757    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
3758    ///
3759    /// When targeting iOS, the default minimum version is `13.0`. Use
3760    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
3761    ///
3762    /// When targeting Android, the default minimum Android API level is `24`. Use
3763    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
3764    ///
3765    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
3766    /// platform; as a result, the installed distributions may not be compatible with the _current_
3767    /// platform. Conversely, any distributions that are built from source may be incompatible with
3768    /// the _target_ platform, as they will be built for the _current_ platform. The
3769    /// `--python-platform` option is intended for advanced use cases.
3770    #[arg(long)]
3771    pub python_platform: Option<TargetTriple>,
3772
3773    /// Check if the Python environment is synchronized with the project.
3774    ///
3775    /// If the environment is not up to date, uv will exit with an error.
3776    #[arg(long, overrides_with("no_check"))]
3777    pub check: bool,
3778
3779    #[arg(long, overrides_with("check"), hide = true)]
3780    pub no_check: bool,
3781}
3782
3783#[derive(Args)]
3784pub struct LockArgs {
3785    /// Check if the lockfile is up-to-date.
3786    ///
3787    /// Asserts that the `uv.lock` would remain unchanged after a resolution. If the lockfile is
3788    /// missing or needs to be updated, uv will exit with an error.
3789    ///
3790    /// Equivalent to `--locked`.
3791    #[arg(long, value_parser = clap::builder::BoolishValueParser::new(), conflicts_with_all = ["check_exists", "upgrade"], overrides_with_all = ["check", "no_locked"])]
3792    pub check: bool,
3793
3794    /// Check if the lockfile is up-to-date [env: UV_LOCKED=]
3795    ///
3796    /// Asserts that the `uv.lock` would remain unchanged after a resolution. If the lockfile is
3797    /// missing or needs to be updated, uv will exit with an error.
3798    ///
3799    /// Equivalent to `--check`.
3800    #[arg(long, conflicts_with_all = ["check_exists", "upgrade"], hide = true, overrides_with = "no_locked")]
3801    pub locked: bool,
3802
3803    /// Disable locked mode, overriding `UV_LOCKED`.
3804    #[arg(long, overrides_with_all = ["locked", "check"], hide = true)]
3805    pub no_locked: bool,
3806
3807    /// Assert that a `uv.lock` exists without checking if it is up-to-date [env: UV_FROZEN=]
3808    ///
3809    /// Equivalent to `--frozen`.
3810    #[arg(long, conflicts_with_all = ["check", "locked"], overrides_with = "no_frozen")]
3811    pub check_exists: bool,
3812
3813    /// Equivalent to `--check-exists`.
3814    #[arg(long, hide = true, conflicts_with_all = ["check_exists", "check", "locked", "dry_run"], overrides_with = "no_frozen")]
3815    pub frozen: bool,
3816
3817    /// Disable frozen mode, overriding `UV_FROZEN`.
3818    #[arg(long, overrides_with_all = ["frozen", "check_exists"], hide = true)]
3819    pub no_frozen: bool,
3820
3821    /// Perform a dry run, without writing the lockfile.
3822    ///
3823    /// In dry-run mode, uv will resolve the project's dependencies and report on the resulting
3824    /// changes, but will not write the lockfile to disk.
3825    #[arg(
3826        long,
3827        conflicts_with = "check_exists",
3828        conflicts_with = "check",
3829        conflicts_with = "locked"
3830    )]
3831    pub dry_run: bool,
3832
3833    /// Lock the specified Python script, rather than the current project.
3834    ///
3835    /// If provided, uv will lock the script (based on its inline metadata table, in adherence with
3836    /// PEP 723) to a `.lock` file adjacent to the script itself.
3837    #[arg(long, value_hint = ValueHint::FilePath)]
3838    pub script: Option<PathBuf>,
3839
3840    #[command(flatten)]
3841    pub resolver: ResolverArgs,
3842
3843    #[command(flatten)]
3844    pub build: BuildOptionsArgs,
3845
3846    #[command(flatten)]
3847    pub refresh: RefreshArgs,
3848
3849    /// The Python interpreter to use during resolution.
3850    ///
3851    /// A Python interpreter is required for building source distributions to determine package
3852    /// metadata when there are not wheels.
3853    ///
3854    /// The interpreter is also used as the fallback value for the minimum Python version if
3855    /// `requires-python` is not set.
3856    ///
3857    /// See `uv help python` for details on Python discovery and supported request formats.
3858    #[arg(
3859        long,
3860        short,
3861        env = EnvVars::UV_PYTHON,
3862        verbatim_doc_comment,
3863        help_heading = "Python options",
3864        value_hint = ValueHint::Other,
3865    )]
3866    pub python: Option<Maybe<String>>,
3867}
3868
3869#[derive(Args)]
3870pub struct UpgradeArgs {
3871    /// The packages to upgrade.
3872    #[arg(value_hint = ValueHint::Other)]
3873    packages: Vec<PackageName>,
3874
3875    /// Exclude the named package from upgrades.
3876    #[arg(long, value_hint = ValueHint::Other)]
3877    exclude: Vec<PackageName>,
3878
3879    #[command(flatten)]
3880    index_args: IndexArgs,
3881
3882    #[command(flatten)]
3883    registry_client: RegistryClientArgs,
3884}
3885
3886#[derive(Args)]
3887#[command(group = clap::ArgGroup::new("sources").required(true).multiple(true))]
3888pub struct AddArgs {
3889    /// The packages to add, as PEP 508 requirements (e.g., `ruff==0.5.0`).
3890    #[arg(group = "sources", value_hint = ValueHint::Other)]
3891    pub packages: Vec<String>,
3892
3893    /// Add the packages listed in the given files.
3894    ///
3895    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
3896    /// `pylock.toml`, `pyproject.toml`, `setup.py`, and `setup.cfg`.
3897    #[arg(
3898        long,
3899        short,
3900        alias = "requirement",
3901        group = "sources",
3902        value_hint = ValueHint::FilePath,
3903    )]
3904    pub requirements: Vec<RequirementsInput>,
3905
3906    /// Constrain versions using the given requirements files.
3907    ///
3908    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
3909    /// requirement that's installed. The constraints will _not_ be added to the project's
3910    /// `pyproject.toml` file, but _will_ be respected during dependency resolution.
3911    ///
3912    /// This is equivalent to pip's `--constraint` option.
3913    #[arg(
3914        long,
3915        short,
3916        alias = "constraint",
3917        env = EnvVars::UV_CONSTRAINT,
3918        value_delimiter = ' ',
3919        value_hint = ValueHint::FilePath,
3920    )]
3921    pub constraints: Vec<Maybe<RequirementsInput>>,
3922
3923    /// Apply this marker to all added packages.
3924    #[arg(long, short, value_parser = MarkerTree::from_str, value_hint = ValueHint::Other)]
3925    pub marker: Option<MarkerTree>,
3926
3927    /// Add the requirements to the development dependency group [env: UV_DEV=]
3928    ///
3929    /// This option is an alias for `--group dev`.
3930    #[arg(
3931        long,
3932        conflicts_with("optional"),
3933        conflicts_with("group"),
3934        conflicts_with("script"),
3935        value_parser = clap::builder::BoolishValueParser::new()
3936    )]
3937    pub dev: bool,
3938
3939    /// Add the requirements to the package's optional dependencies for the specified extra.
3940    ///
3941    /// The group may then be activated when installing the project with the `--extra` flag.
3942    ///
3943    /// To enable an optional extra for this requirement instead, see `--extra`.
3944    #[arg(long, conflicts_with("dev"), conflicts_with("group"), value_hint = ValueHint::Other)]
3945    pub optional: Option<ExtraName>,
3946
3947    /// Add the requirements to the specified dependency group.
3948    ///
3949    /// These requirements will not be included in the published metadata for the project.
3950    #[arg(
3951        long,
3952        conflicts_with("dev"),
3953        conflicts_with("optional"),
3954        conflicts_with("script"),
3955        value_hint = ValueHint::Other,
3956    )]
3957    pub group: Option<GroupName>,
3958
3959    /// Add the requirements as editable.
3960    #[arg(long, overrides_with = "no_editable")]
3961    pub editable: bool,
3962
3963    /// Don't add the requirements as editable [env: UV_NO_EDITABLE=]
3964    #[arg(long, overrides_with = "editable", hide = true, value_parser = clap::builder::BoolishValueParser::new())]
3965    pub no_editable: bool,
3966
3967    /// Don't add the specified requirements as editable.
3968    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other, hide = true)]
3969    pub no_editable_package: Vec<PackageName>,
3970
3971    /// Add a dependency as provided.
3972    ///
3973    /// By default, uv will use the `tool.uv.sources` section to record source information for Git,
3974    /// local, editable, and direct URL requirements. When `--raw` is provided, uv will add source
3975    /// requirements to `project.dependencies`, rather than `tool.uv.sources`.
3976    ///
3977    /// Additionally, by default, uv will add bounds to your dependency, e.g., `foo>=1.0.0`. When
3978    /// `--raw` is provided, uv will add the dependency without bounds.
3979    #[arg(
3980        long,
3981        conflicts_with = "editable",
3982        conflicts_with = "no_editable",
3983        conflicts_with = "rev",
3984        conflicts_with = "tag",
3985        conflicts_with = "branch",
3986        alias = "raw-sources"
3987    )]
3988    pub raw: bool,
3989
3990    /// The kind of version specifier to use when adding dependencies.
3991    ///
3992    /// When adding a dependency to the project, if no constraint or URL is provided, a constraint
3993    /// is added based on the latest compatible version of the package. By default, a lower bound
3994    /// constraint is used, e.g., `>=1.2.3`.
3995    ///
3996    /// When `--frozen` is provided, no resolution is performed, and dependencies are always added
3997    /// without constraints.
3998    ///
3999    /// This option is in preview and may change in any future release.
4000    #[arg(long, value_enum)]
4001    pub bounds: Option<AddBoundsKind>,
4002
4003    /// Commit to use when adding a dependency from Git.
4004    #[arg(long, group = "git-ref", action = clap::ArgAction::Set, value_hint = ValueHint::Other)]
4005    pub rev: Option<String>,
4006
4007    /// Tag to use when adding a dependency from Git.
4008    #[arg(long, group = "git-ref", action = clap::ArgAction::Set, value_hint = ValueHint::Other)]
4009    pub tag: Option<String>,
4010
4011    /// Branch to use when adding a dependency from Git.
4012    #[arg(long, group = "git-ref", action = clap::ArgAction::Set, value_hint = ValueHint::Other)]
4013    pub branch: Option<String>,
4014
4015    /// Whether to use Git LFS when adding a dependency from Git.
4016    #[arg(long)]
4017    pub lfs: bool,
4018
4019    /// Extras to enable for the dependency.
4020    ///
4021    /// May be provided more than once.
4022    ///
4023    /// To add this dependency to an optional extra instead, see `--optional`.
4024    #[arg(long, value_hint = ValueHint::Other)]
4025    pub extra: Option<Vec<ExtraName>>,
4026
4027    /// Avoid syncing the virtual environment [env: UV_NO_SYNC=]
4028    #[arg(long)]
4029    pub no_sync: bool,
4030
4031    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
4032    ///
4033    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
4034    /// uv will exit with an error.
4035    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
4036    pub locked: bool,
4037
4038    /// Disable locked mode, overriding `UV_LOCKED`.
4039    #[arg(long, overrides_with = "locked", hide = true)]
4040    pub no_locked: bool,
4041
4042    /// Add dependencies without re-locking the project [env: UV_FROZEN=]
4043    ///
4044    /// The project environment will not be synced.
4045    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
4046    pub frozen: bool,
4047
4048    /// Disable frozen mode, overriding `UV_FROZEN`.
4049    #[arg(long, overrides_with = "frozen", hide = true)]
4050    pub no_frozen: bool,
4051
4052    /// Prefer the active virtual environment over the project's virtual environment.
4053    ///
4054    /// If the project virtual environment is active or no virtual environment is active, this has
4055    /// no effect.
4056    #[arg(long, overrides_with = "no_active")]
4057    pub active: bool,
4058
4059    /// Prefer project's virtual environment over an active environment.
4060    ///
4061    /// This is the default behavior.
4062    #[arg(long, overrides_with = "active", hide = true)]
4063    pub no_active: bool,
4064
4065    #[command(flatten)]
4066    pub installer: ResolverInstallerArgs,
4067
4068    #[command(flatten)]
4069    pub build: BuildOptionsArgs,
4070
4071    #[command(flatten)]
4072    pub refresh: RefreshArgs,
4073
4074    /// Add the dependency to a specific package in the workspace.
4075    #[arg(long, conflicts_with = "isolated", value_hint = ValueHint::Other)]
4076    pub package: Option<PackageName>,
4077
4078    /// Add the dependency to the specified Python script, rather than to a project.
4079    ///
4080    /// If provided, uv will add the dependency to the script's inline metadata table, in adherence
4081    /// with PEP 723. If no such inline metadata table is present, a new one will be created and
4082    /// added to the script. When executed via `uv run`, uv will create a temporary environment for
4083    /// the script with all inline dependencies installed.
4084    #[arg(
4085        long,
4086        conflicts_with = "dev",
4087        conflicts_with = "optional",
4088        conflicts_with = "package",
4089        conflicts_with = "workspace",
4090        value_hint = ValueHint::FilePath,
4091    )]
4092    pub script: Option<PathBuf>,
4093
4094    /// The Python interpreter to use for resolving and syncing.
4095    ///
4096    /// See `uv help python` for details on Python discovery and supported request formats.
4097    #[arg(
4098        long,
4099        short,
4100        env = EnvVars::UV_PYTHON,
4101        verbatim_doc_comment,
4102        help_heading = "Python options",
4103        value_hint = ValueHint::Other,
4104    )]
4105    pub python: Option<Maybe<String>>,
4106
4107    /// Add the dependency as a workspace member.
4108    ///
4109    /// By default, uv will add path dependencies that are within the workspace directory
4110    /// as workspace members. When used with a path dependency, the package will be added
4111    /// to the workspace's `members` list in the root `pyproject.toml` file.
4112    #[arg(long, overrides_with = "no_workspace")]
4113    pub workspace: bool,
4114
4115    /// Don't add the dependency as a workspace member.
4116    ///
4117    /// By default, when adding a dependency that's a local path and is within the workspace
4118    /// directory, uv will add it as a workspace member; pass `--no-workspace` to add the package
4119    /// as direct path dependency instead.
4120    #[arg(long, overrides_with = "workspace")]
4121    pub no_workspace: bool,
4122
4123    /// Do not install the current project [env: UV_NO_INSTALL_PROJECT=]
4124    ///
4125    /// By default, the current project is installed into the environment with all of its
4126    /// dependencies. The `--no-install-project` option allows the project to be excluded, but all of
4127    /// its dependencies are still installed. This is particularly useful in situations like building
4128    /// Docker images where installing the project separately from its dependencies allows optimal
4129    /// layer caching.
4130    ///
4131    /// The inverse `--only-install-project` can be used to install _only_ the project itself,
4132    /// excluding all dependencies.
4133    #[arg(
4134        long,
4135        conflicts_with = "frozen",
4136        conflicts_with = "no_sync",
4137        conflicts_with = "only_install_project"
4138    )]
4139    pub no_install_project: bool,
4140
4141    /// Only install the current project.
4142    #[arg(
4143        long,
4144        conflicts_with = "frozen",
4145        conflicts_with = "no_sync",
4146        conflicts_with = "no_install_project",
4147        hide = true
4148    )]
4149    pub only_install_project: bool,
4150
4151    /// Do not install any workspace members, including the current project [env: UV_NO_INSTALL_WORKSPACE=]
4152    ///
4153    /// By default, all workspace members and their dependencies are installed into the
4154    /// environment. The `--no-install-workspace` option allows exclusion of all the workspace
4155    /// members while retaining their dependencies. This is particularly useful in situations like
4156    /// building Docker images where installing the workspace separately from its dependencies
4157    /// allows optimal layer caching.
4158    ///
4159    /// The inverse `--only-install-workspace` can be used to install _only_ workspace members,
4160    /// excluding all other dependencies.
4161    #[arg(
4162        long,
4163        conflicts_with = "frozen",
4164        conflicts_with = "no_sync",
4165        conflicts_with = "only_install_workspace"
4166    )]
4167    pub no_install_workspace: bool,
4168
4169    /// Only install workspace members, including the current project.
4170    #[arg(
4171        long,
4172        conflicts_with = "frozen",
4173        conflicts_with = "no_sync",
4174        conflicts_with = "no_install_workspace",
4175        hide = true
4176    )]
4177    pub only_install_workspace: bool,
4178
4179    /// Do not install local path dependencies [env: UV_NO_INSTALL_LOCAL=]
4180    ///
4181    /// Skips the current project, workspace members, and any other local (path or editable)
4182    /// packages. Only remote/indexed dependencies are installed. Useful in Docker builds to cache
4183    /// heavy third-party dependencies first and layer local packages separately.
4184    ///
4185    /// The inverse `--only-install-local` can be used to install _only_ local packages, excluding
4186    /// all remote dependencies.
4187    #[arg(
4188        long,
4189        conflicts_with = "frozen",
4190        conflicts_with = "no_sync",
4191        conflicts_with = "only_install_local"
4192    )]
4193    pub no_install_local: bool,
4194
4195    /// Only install local path dependencies
4196    #[arg(
4197        long,
4198        conflicts_with = "frozen",
4199        conflicts_with = "no_sync",
4200        conflicts_with = "no_install_local",
4201        hide = true
4202    )]
4203    pub only_install_local: bool,
4204
4205    /// Do not install the given package(s).
4206    ///
4207    /// By default, all project's dependencies are installed into the environment. The
4208    /// `--no-install-package` option allows exclusion of specific packages. Note this can result
4209    /// in a broken environment, and should be used with caution.
4210    ///
4211    /// The inverse `--only-install-package` can be used to install _only_ the specified packages,
4212    /// excluding all others.
4213    #[arg(
4214        long,
4215        conflicts_with = "frozen",
4216        conflicts_with = "no_sync",
4217        conflicts_with = "only_install_package",
4218        value_hint = ValueHint::Other,
4219    )]
4220    pub no_install_package: Vec<PackageName>,
4221
4222    /// Only install the given package(s).
4223    #[arg(
4224        long,
4225        conflicts_with = "frozen",
4226        conflicts_with = "no_sync",
4227        conflicts_with = "no_install_package",
4228        hide = true,
4229        value_hint = ValueHint::Other,
4230    )]
4231    pub only_install_package: Vec<PackageName>,
4232}
4233
4234#[derive(Args)]
4235pub struct RemoveArgs {
4236    /// The names of the dependencies to remove (e.g., `ruff`).
4237    #[arg(required = true, value_hint = ValueHint::Other)]
4238    pub packages: Vec<Requirement<VerbatimParsedUrl>>,
4239
4240    /// Remove the packages from the development dependency group [env: UV_DEV=]
4241    ///
4242    /// This option is an alias for `--group dev`.
4243    #[arg(
4244        long,
4245        conflicts_with("optional"),
4246        conflicts_with("group"),
4247        conflicts_with("script"),
4248        value_parser = clap::builder::BoolishValueParser::new()
4249    )]
4250    pub dev: bool,
4251
4252    /// Remove the packages from the project's optional dependencies for the specified extra.
4253    #[arg(
4254        long,
4255        conflicts_with("dev"),
4256        conflicts_with("group"),
4257        conflicts_with("script"),
4258        value_hint = ValueHint::Other,
4259    )]
4260    pub optional: Option<ExtraName>,
4261
4262    /// Remove the packages from the specified dependency group.
4263    #[arg(
4264        long,
4265        conflicts_with("dev"),
4266        conflicts_with("optional"),
4267        conflicts_with("script"),
4268        value_hint = ValueHint::Other,
4269    )]
4270    pub group: Option<GroupName>,
4271
4272    /// Avoid syncing the virtual environment after re-locking the project [env: UV_NO_SYNC=]
4273    #[arg(long)]
4274    pub no_sync: bool,
4275
4276    /// Prefer the active virtual environment over the project's virtual environment.
4277    ///
4278    /// If the project virtual environment is active or no virtual environment is active, this has
4279    /// no effect.
4280    #[arg(long, overrides_with = "no_active")]
4281    pub active: bool,
4282
4283    /// Prefer project's virtual environment over an active environment.
4284    ///
4285    /// This is the default behavior.
4286    #[arg(long, overrides_with = "active", hide = true)]
4287    pub no_active: bool,
4288
4289    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
4290    ///
4291    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
4292    /// uv will exit with an error.
4293    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
4294    pub locked: bool,
4295
4296    /// Disable locked mode, overriding `UV_LOCKED`.
4297    #[arg(long, overrides_with = "locked", hide = true)]
4298    pub no_locked: bool,
4299
4300    /// Remove dependencies without re-locking the project [env: UV_FROZEN=]
4301    ///
4302    /// The project environment will not be synced.
4303    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
4304    pub frozen: bool,
4305
4306    /// Disable frozen mode, overriding `UV_FROZEN`.
4307    #[arg(long, overrides_with = "frozen", hide = true)]
4308    pub no_frozen: bool,
4309
4310    #[command(flatten)]
4311    pub installer: ResolverInstallerArgs,
4312
4313    #[command(flatten)]
4314    pub build: BuildOptionsArgs,
4315
4316    #[command(flatten)]
4317    pub refresh: RefreshArgs,
4318
4319    /// Remove the dependencies from a specific package in the workspace.
4320    #[arg(long, conflicts_with = "isolated", value_hint = ValueHint::Other)]
4321    pub package: Option<PackageName>,
4322
4323    /// Remove the dependency from the specified Python script, rather than from a project.
4324    ///
4325    /// If provided, uv will remove the dependency from the script's inline metadata table, in
4326    /// adherence with PEP 723.
4327    #[arg(long, value_hint = ValueHint::FilePath)]
4328    pub script: Option<PathBuf>,
4329
4330    /// The Python interpreter to use for resolving and syncing.
4331    ///
4332    /// See `uv help python` for details on Python discovery and supported request formats.
4333    #[arg(
4334        long,
4335        short,
4336        env = EnvVars::UV_PYTHON,
4337        verbatim_doc_comment,
4338        help_heading = "Python options",
4339        value_hint = ValueHint::Other,
4340    )]
4341    pub python: Option<Maybe<String>>,
4342}
4343
4344#[derive(Args)]
4345pub struct TreeArgs {
4346    /// Show a platform-independent dependency tree.
4347    ///
4348    /// Shows resolved package versions for all Python versions and platforms, rather than filtering
4349    /// to those that are relevant for the current environment.
4350    ///
4351    /// Multiple versions may be shown for a each package.
4352    #[arg(long)]
4353    pub universal: bool,
4354
4355    /// The format in which to display the dependency graph.
4356    #[arg(long, value_enum, default_value_t = TreeFormat::default())]
4357    pub format: TreeFormat,
4358
4359    #[command(flatten)]
4360    pub tree: DisplayTreeArgs,
4361
4362    #[command(flatten)]
4363    pub dependency_groups: ProjectDependencyGroupsArgs,
4364
4365    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
4366    ///
4367    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
4368    /// uv will exit with an error.
4369    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
4370    pub locked: bool,
4371
4372    /// Disable locked mode, overriding `UV_LOCKED`.
4373    #[arg(long, overrides_with = "locked", hide = true)]
4374    pub no_locked: bool,
4375
4376    /// Display the requirements without locking the project [env: UV_FROZEN=]
4377    ///
4378    /// If the lockfile is missing, uv will exit with an error.
4379    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
4380    pub frozen: bool,
4381
4382    /// Disable frozen mode, overriding `UV_FROZEN`.
4383    #[arg(long, overrides_with = "frozen", hide = true)]
4384    pub no_frozen: bool,
4385
4386    #[command(flatten)]
4387    pub build: BuildOptionsArgs,
4388
4389    #[command(flatten)]
4390    pub resolver: ResolverArgs,
4391
4392    /// Show the dependency tree the specified PEP 723 Python script, rather than the current
4393    /// project.
4394    ///
4395    /// If provided, uv will resolve the dependencies based on its inline metadata table, in
4396    /// adherence with PEP 723.
4397    #[arg(long, value_hint = ValueHint::FilePath)]
4398    pub script: Option<PathBuf>,
4399
4400    /// The Python version to use when filtering the tree.
4401    ///
4402    /// For example, pass `--python-version 3.10` to display the dependencies that would be included
4403    /// when installing on Python 3.10.
4404    ///
4405    /// Defaults to the version of the discovered Python interpreter.
4406    #[arg(long, conflicts_with = "universal")]
4407    pub python_version: Option<PythonVersion>,
4408
4409    /// The platform to use when filtering the tree.
4410    ///
4411    /// For example, pass `--platform windows` to display the dependencies that would be included
4412    /// when installing on Windows.
4413    ///
4414    /// Represented as a "target triple", a string that describes the target platform in terms of
4415    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
4416    /// `aarch64-apple-darwin`.
4417    #[arg(long, conflicts_with = "universal")]
4418    pub python_platform: Option<TargetTriple>,
4419
4420    /// The Python interpreter to use for locking and filtering.
4421    ///
4422    /// By default, the tree is filtered to match the platform as reported by the Python
4423    /// interpreter. Use `--universal` to display the tree for all platforms, or use
4424    /// `--python-version` or `--python-platform` to override a subset of markers.
4425    ///
4426    /// See `uv help python` for details on Python discovery and supported request formats.
4427    #[arg(
4428        long,
4429        short,
4430        env = EnvVars::UV_PYTHON,
4431        verbatim_doc_comment,
4432        help_heading = "Python options",
4433        value_hint = ValueHint::Other,
4434    )]
4435    pub python: Option<Maybe<String>>,
4436}
4437
4438#[derive(Args)]
4439pub struct ExportArgs {
4440    /// The format to which `uv.lock` should be exported.
4441    ///
4442    /// Supports `requirements.txt`, `pylock.toml` (PEP 751) and CycloneDX v1.5 JSON output formats.
4443    ///
4444    /// uv will infer the output format from the file extension of the output file, if
4445    /// provided. Otherwise, defaults to `requirements.txt`.
4446    #[arg(long, value_enum)]
4447    pub format: Option<ExportFormat>,
4448
4449    /// Export the entire workspace.
4450    ///
4451    /// The dependencies for all workspace members will be included in the exported requirements
4452    /// file.
4453    ///
4454    /// Any extras or groups specified via `--extra`, `--group`, or related options will be applied
4455    /// to all workspace members.
4456    #[arg(long, conflicts_with = "package")]
4457    pub all_packages: bool,
4458
4459    /// Export the dependencies for specific packages in the workspace.
4460    ///
4461    /// If any workspace member does not exist, uv will exit with an error.
4462    #[arg(long, conflicts_with = "all_packages", value_hint = ValueHint::Other)]
4463    pub package: Vec<PackageName>,
4464
4465    /// Prune the given package from the dependency tree.
4466    ///
4467    /// Pruned packages will be excluded from the exported requirements file, as will any
4468    /// dependencies that are no longer required after the pruned package is removed.
4469    #[arg(long, conflicts_with = "all_packages", value_name = "PACKAGE")]
4470    pub prune: Vec<PackageName>,
4471
4472    /// Include optional dependencies from the specified extra name.
4473    ///
4474    /// May be provided more than once.
4475    #[arg(long, value_delimiter = ',', conflicts_with = "all_extras", conflicts_with = "only_group", value_parser = extra_name_with_clap_error)]
4476    pub extra: Option<Vec<ExtraName>>,
4477
4478    /// Include all optional dependencies.
4479    #[arg(long, conflicts_with = "extra", conflicts_with = "only_group")]
4480    pub all_extras: bool,
4481
4482    /// Exclude the specified optional dependencies, if `--all-extras` is supplied.
4483    ///
4484    /// May be provided multiple times.
4485    #[arg(long)]
4486    pub no_extra: Vec<ExtraName>,
4487
4488    #[arg(long, overrides_with("all_extras"), hide = true)]
4489    pub no_all_extras: bool,
4490
4491    #[command(flatten)]
4492    pub dependency_groups: ProjectDependencyGroupsArgs,
4493
4494    /// Exclude comment annotations indicating the source of each package.
4495    #[arg(long, overrides_with("annotate"))]
4496    pub no_annotate: bool,
4497
4498    #[arg(long, overrides_with("no_annotate"), hide = true)]
4499    pub annotate: bool,
4500
4501    /// Exclude the comment header at the top of the generated output file.
4502    #[arg(long, overrides_with("header"))]
4503    pub no_header: bool,
4504
4505    #[arg(long, overrides_with("no_header"), hide = true)]
4506    pub header: bool,
4507
4508    /// Include `--index-url` and `--extra-index-url` entries in the generated output file.
4509    #[arg(long, overrides_with("no_emit_index_url"))]
4510    pub emit_index_url: bool,
4511
4512    #[arg(long, overrides_with("emit_index_url"), hide = true)]
4513    pub no_emit_index_url: bool,
4514
4515    /// Include `--find-links` entries in the generated output file.
4516    #[arg(long, overrides_with("no_emit_find_links"))]
4517    pub emit_find_links: bool,
4518
4519    #[arg(long, overrides_with("emit_find_links"), hide = true)]
4520    pub no_emit_find_links: bool,
4521
4522    /// Export any non-editable dependencies, including the project and any workspace members, as
4523    /// editable.
4524    #[arg(long, overrides_with = "no_editable", hide = true)]
4525    pub editable: bool,
4526
4527    /// Export any editable dependencies, including the project and any workspace members, as
4528    /// non-editable [env: UV_NO_EDITABLE=]
4529    #[arg(long, overrides_with = "editable", value_parser = clap::builder::BoolishValueParser::new())]
4530    pub no_editable: bool,
4531
4532    /// Export the specified editable packages as non-editable.
4533    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other)]
4534    pub no_editable_package: Vec<PackageName>,
4535
4536    /// Include hashes for all dependencies.
4537    #[arg(long, overrides_with("no_hashes"), hide = true)]
4538    pub hashes: bool,
4539
4540    /// Omit hashes in the generated output.
4541    #[arg(long, overrides_with("hashes"))]
4542    pub no_hashes: bool,
4543
4544    /// Write the exported requirements to the given file.
4545    #[arg(long, short, value_hint = ValueHint::FilePath)]
4546    pub output_file: Option<PathBuf>,
4547
4548    /// Export multiple selections from a TOML manifest containing `[[export]]` entries.
4549    ///
4550    /// Each entry specifies an `output-file` and its own package, extra, and group selections.
4551    /// Output paths are relative to the manifest.
4552    #[arg(long, hide = true, value_hint = ValueHint::FilePath, conflicts_with_all = [
4553        "output_file", "script", "package", "all_packages", "extra", "all_extras", "no_extra",
4554        "no_all_extras", "group", "no_group", "only_group", "all_groups", "no_default_groups",
4555        "dev", "no_dev", "only_dev",
4556    ])]
4557    pub batch: Option<PathBuf>,
4558
4559    /// Do not emit the current project.
4560    ///
4561    /// By default, the current project is included in the exported requirements file with all of
4562    /// its dependencies. The `--no-emit-project` option allows the project to be excluded, but all
4563    /// of its dependencies to remain included.
4564    ///
4565    /// The inverse `--only-emit-project` can be used to emit _only_ the project itself, excluding
4566    /// all dependencies.
4567    #[arg(
4568        long,
4569        alias = "no-install-project",
4570        conflicts_with = "only_emit_project"
4571    )]
4572    pub no_emit_project: bool,
4573
4574    /// Only emit the current project.
4575    #[arg(
4576        long,
4577        alias = "only-install-project",
4578        conflicts_with = "no_emit_project",
4579        hide = true
4580    )]
4581    pub only_emit_project: bool,
4582
4583    /// Do not emit any workspace members, including the root project.
4584    ///
4585    /// By default, all workspace members and their dependencies are included in the exported
4586    /// requirements file, with all of their dependencies. The `--no-emit-workspace` option allows
4587    /// exclusion of all the workspace members while retaining their dependencies.
4588    ///
4589    /// The inverse `--only-emit-workspace` can be used to emit _only_ workspace members, excluding
4590    /// all other dependencies.
4591    #[arg(
4592        long,
4593        alias = "no-install-workspace",
4594        conflicts_with = "only_emit_workspace"
4595    )]
4596    pub no_emit_workspace: bool,
4597
4598    /// Only emit workspace members, including the root project.
4599    #[arg(
4600        long,
4601        alias = "only-install-workspace",
4602        conflicts_with = "no_emit_workspace",
4603        hide = true
4604    )]
4605    pub only_emit_workspace: bool,
4606
4607    /// Do not include local path dependencies in the exported requirements.
4608    ///
4609    /// Omits the current project, workspace members, and any other local (path or editable)
4610    /// packages from the export. Only remote/indexed dependencies are written. Useful for Docker
4611    /// and CI flows that want to export and cache third-party dependencies first.
4612    ///
4613    /// The inverse `--only-emit-local` can be used to emit _only_ local packages, excluding all
4614    /// remote dependencies.
4615    #[arg(long, alias = "no-install-local", conflicts_with = "only_emit_local")]
4616    pub no_emit_local: bool,
4617
4618    /// Only include local path dependencies in the exported requirements.
4619    #[arg(
4620        long,
4621        alias = "only-install-local",
4622        conflicts_with = "no_emit_local",
4623        hide = true
4624    )]
4625    pub only_emit_local: bool,
4626
4627    /// Do not emit the given package(s).
4628    ///
4629    /// By default, all project's dependencies are included in the exported requirements
4630    /// file. The `--no-emit-package` option allows exclusion of specific packages.
4631    ///
4632    /// The inverse `--only-emit-package` can be used to emit _only_ the specified packages,
4633    /// excluding all others.
4634    #[arg(
4635        long,
4636        alias = "no-install-package",
4637        conflicts_with = "only_emit_package",
4638        value_delimiter = ',',
4639        value_hint = ValueHint::Other,
4640    )]
4641    pub no_emit_package: Vec<PackageName>,
4642
4643    /// Only emit the given package(s).
4644    #[arg(
4645        long,
4646        alias = "only-install-package",
4647        conflicts_with = "no_emit_package",
4648        hide = true,
4649        value_delimiter = ',',
4650        value_hint = ValueHint::Other,
4651    )]
4652    pub only_emit_package: Vec<PackageName>,
4653
4654    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
4655    ///
4656    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
4657    /// uv will exit with an error.
4658    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
4659    pub locked: bool,
4660
4661    /// Disable locked mode, overriding `UV_LOCKED`.
4662    #[arg(long, overrides_with = "locked", hide = true)]
4663    pub no_locked: bool,
4664
4665    /// Do not update the `uv.lock` before exporting [env: UV_FROZEN=]
4666    ///
4667    /// If a `uv.lock` does not exist, uv will exit with an error.
4668    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
4669    pub frozen: bool,
4670
4671    /// Disable frozen mode, overriding `UV_FROZEN`.
4672    #[arg(long, overrides_with = "frozen", hide = true)]
4673    pub no_frozen: bool,
4674
4675    #[command(flatten)]
4676    pub resolver: ResolverArgs,
4677
4678    #[command(flatten)]
4679    pub build: BuildOptionsArgs,
4680
4681    #[command(flatten)]
4682    pub refresh: RefreshArgs,
4683
4684    /// Export the dependencies for the specified PEP 723 Python script, rather than the current
4685    /// project.
4686    ///
4687    /// If provided, uv will resolve the dependencies based on its inline metadata table, in
4688    /// adherence with PEP 723.
4689    #[arg(
4690        long,
4691        conflicts_with_all = ["all_packages", "package", "no_emit_project", "no_emit_workspace"],
4692        value_hint = ValueHint::FilePath,
4693    )]
4694    pub script: Option<PathBuf>,
4695
4696    /// The Python interpreter to use during resolution.
4697    ///
4698    /// A Python interpreter is required for building source distributions to determine package
4699    /// metadata when there are not wheels.
4700    ///
4701    /// The interpreter is also used as the fallback value for the minimum Python version if
4702    /// `requires-python` is not set.
4703    ///
4704    /// See `uv help python` for details on Python discovery and supported request formats.
4705    #[arg(
4706        long,
4707        short,
4708        env = EnvVars::UV_PYTHON,
4709        verbatim_doc_comment,
4710        help_heading = "Python options",
4711        value_hint = ValueHint::Other,
4712    )]
4713    pub python: Option<Maybe<String>>,
4714}
4715
4716#[derive(Args)]
4717pub struct FormatArgs {
4718    /// Check if files are formatted without applying changes.
4719    #[arg(long)]
4720    check: bool,
4721
4722    /// Show a diff of formatting changes without applying them.
4723    ///
4724    /// Implies `--check`.
4725    #[arg(long)]
4726    diff: bool,
4727
4728    /// The version of Ruff to use for formatting.
4729    ///
4730    /// Accepts either a version (e.g., `0.8.2`) which will be treated as an exact pin,
4731    /// a version specifier (e.g., `>=0.8.0`), or `latest` to use the latest available version.
4732    ///
4733    /// By default, a constrained version range of Ruff will be used (e.g., `>=0.15,<0.16`).
4734    #[arg(long, value_hint = ValueHint::Other)]
4735    version: Option<String>,
4736
4737    /// Limit candidate Ruff versions to those released prior to the given date.
4738    ///
4739    /// Accepts a superset of [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) (e.g.,
4740    /// `2006-12-02T02:07:43Z`) or local date in the same format (e.g. `2006-12-02`), as well as
4741    /// durations relative to "now" (e.g., `-1 week`).
4742    ///
4743    /// Use `false` to disable `exclude-newer`.
4744    #[arg(long, env = EnvVars::UV_EXCLUDE_NEWER, value_hint = ValueHint::Other)]
4745    exclude_newer: Option<ExcludeNewerOverride>,
4746
4747    /// Additional arguments to pass to Ruff.
4748    ///
4749    /// For example, use `uv format -- --line-length 100` to set the line length or
4750    /// `uv format -- src/module/foo.py` to format a specific file.
4751    #[arg(last = true, value_hint = ValueHint::Other)]
4752    extra_args: Vec<String>,
4753
4754    /// Avoid discovering a project or workspace.
4755    ///
4756    /// Instead of running the formatter in the context of the current project, run it in the
4757    /// context of the current directory. This is useful when the current directory is not a
4758    /// project.
4759    #[arg(
4760        long,
4761        env = EnvVars::UV_NO_PROJECT,
4762        value_parser = clap::builder::BoolishValueParser::new()
4763    )]
4764    no_project: bool,
4765
4766    /// Display the version of Ruff that will be used for formatting.
4767    ///
4768    /// This is useful for verifying which version was resolved when using version constraints
4769    /// (e.g., `--version ">=0.8.0"`) or `--version latest`.
4770    #[arg(long, hide = true)]
4771    show_version: bool,
4772}
4773
4774#[derive(Args)]
4775pub struct CheckArgs {
4776    /// Apply safe fixes to resolve type-checking errors.
4777    #[arg(long)]
4778    pub fix: bool,
4779
4780    /// Check all packages in the workspace.
4781    ///
4782    /// The workspace's environment is synchronized to include all workspace members, and files in
4783    /// every member are checked.
4784    #[arg(long, conflicts_with_all = ["package", "script", "no_project"])]
4785    pub all_packages: bool,
4786
4787    /// Check specific packages in the workspace.
4788    ///
4789    /// The workspace's environment is synchronized to include the selected members and their
4790    /// dependencies. Only files owned by the selected members are checked.
4791    #[arg(
4792        long,
4793        conflicts_with_all = ["all_packages", "script", "no_project"],
4794        value_hint = ValueHint::Other
4795    )]
4796    pub package: Vec<PackageName>,
4797
4798    /// Run checks for the specified PEP 723 Python script, rather than the current project.
4799    ///
4800    /// If provided, uv will use the dependencies based on the script's inline metadata table, in
4801    /// adherence with PEP 723.
4802    #[arg(
4803        long,
4804        conflicts_with = "extra",
4805        conflicts_with = "all_extras",
4806        conflicts_with = "no_extra",
4807        conflicts_with = "no_all_extras",
4808        conflicts_with = "dev",
4809        conflicts_with = "no_dev",
4810        conflicts_with = "only_dev",
4811        conflicts_with = "group",
4812        conflicts_with = "no_group",
4813        conflicts_with = "no_default_groups",
4814        conflicts_with = "only_group",
4815        conflicts_with = "all_groups",
4816        conflicts_with = "no_project",
4817        conflicts_with = "all_packages",
4818        conflicts_with = "package",
4819        value_hint = ValueHint::FilePath,
4820    )]
4821    pub script: Option<PathBuf>,
4822
4823    /// Include optional dependencies from the specified extra name.
4824    ///
4825    /// May be provided more than once.
4826    ///
4827    /// When multiple extras or groups are specified that appear in `tool.uv.conflicts`, uv will
4828    /// report an error.
4829    ///
4830    /// Note that all optional dependencies are always included in the resolution; this option only
4831    /// affects the selection of packages to install.
4832    #[arg(
4833        long,
4834        conflicts_with = "all_extras",
4835        conflicts_with = "only_group",
4836        value_delimiter = ',',
4837        value_parser = extra_name_with_clap_error,
4838        value_hint = ValueHint::Other,
4839    )]
4840    pub extra: Option<Vec<ExtraName>>,
4841
4842    /// Include all optional dependencies.
4843    ///
4844    /// When two or more extras are declared as conflicting in `tool.uv.conflicts`, using this flag
4845    /// will always result in an error.
4846    ///
4847    /// Note that all optional dependencies are always included in the resolution; this option only
4848    /// affects the selection of packages to install.
4849    #[arg(long, conflicts_with = "extra", conflicts_with = "only_group")]
4850    pub all_extras: bool,
4851
4852    /// Exclude the specified optional dependencies, if `--all-extras` is supplied.
4853    ///
4854    /// May be provided multiple times.
4855    #[arg(long, value_hint = ValueHint::Other)]
4856    pub no_extra: Vec<ExtraName>,
4857
4858    #[arg(long, overrides_with("all_extras"), hide = true)]
4859    pub no_all_extras: bool,
4860
4861    #[command(flatten)]
4862    pub dependency_groups: ConflictCheckedDependencyGroupsArgs,
4863
4864    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
4865    ///
4866    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
4867    /// uv will exit with an error.
4868    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
4869    pub locked: bool,
4870
4871    /// Disable locked mode, overriding `UV_LOCKED`.
4872    #[arg(long, overrides_with = "locked", hide = true)]
4873    pub no_locked: bool,
4874
4875    /// Sync without updating the `uv.lock` file [env: UV_FROZEN=]
4876    ///
4877    /// Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the
4878    /// source of truth. If the lockfile is missing, uv will exit with an error. If the
4879    /// `pyproject.toml` includes changes to dependencies that have not been included in the
4880    /// lockfile yet, they will not be present in the environment.
4881    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
4882    pub frozen: bool,
4883
4884    /// Disable frozen mode, overriding `UV_FROZEN`.
4885    #[arg(long, overrides_with = "frozen", hide = true)]
4886    pub no_frozen: bool,
4887
4888    /// Avoid syncing the virtual environment [env: UV_NO_SYNC=]
4889    #[arg(long)]
4890    pub no_sync: bool,
4891
4892    /// Do not install the current project [env: UV_NO_INSTALL_PROJECT=]
4893    ///
4894    /// By default, the current project is installed into the environment with all of its
4895    /// dependencies. The `--no-install-project` option excludes the project itself while still
4896    /// installing its dependencies, which is useful when the project can be type-checked from its
4897    /// source tree without building native extensions.
4898    #[arg(long, conflicts_with_all = ["no_sync", "script", "no_project"])]
4899    pub no_install_project: bool,
4900
4901    /// Run checks without mutating project state [env: UV_ISOLATED=]
4902    ///
4903    /// Uses a temporary virtual environment and leaves existing environments and the project
4904    /// lockfile unchanged. Declared project requirements are resolved and installed into the
4905    /// temporary environment.
4906    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
4907    pub isolated: bool,
4908
4909    /// The Python interpreter to use for the project environment.
4910    ///
4911    /// By default, the first interpreter that meets the project's
4912    /// `requires-python` constraint is used.
4913    ///
4914    /// See `uv python` for more details on Python discovery and requests.
4915    #[arg(
4916        long,
4917        short,
4918        env = EnvVars::UV_PYTHON,
4919        value_hint = ValueHint::Other,
4920    )]
4921    pub python: Option<Maybe<String>>,
4922
4923    /// The version of ty to use for type checking.
4924    ///
4925    /// Accepts either a version (e.g., `0.0.1`) which will be treated as an exact pin,
4926    /// a version specifier (e.g., `>=0.0.1`), or `latest` to use the latest available version.
4927    ///
4928    /// By default, the exact version resolved in `uv.lock` will be used when `ty` is a project
4929    /// dependency or a dependency in the project's `dev` group. Otherwise, a constrained version
4930    /// range of ty will be used (e.g., `>=0.0,<0.1`).
4931    #[arg(long, value_hint = ValueHint::Other)]
4932    pub ty_version: Option<String>,
4933
4934    /// Display the version of ty that will be used for type checking.
4935    #[arg(long, hide = true)]
4936    pub show_version: bool,
4937
4938    /// Display the ty command that will be used for type checking.
4939    #[arg(long, hide = true)]
4940    pub show_command: bool,
4941
4942    /// Avoid discovering a project or workspace.
4943    ///
4944    /// Instead of running checks in the context of the current project, run them in the context of
4945    /// the current directory. This is useful when the current directory is not a project.
4946    #[arg(
4947        long,
4948        env = EnvVars::UV_NO_PROJECT,
4949        value_parser = clap::builder::BoolishValueParser::new()
4950    )]
4951    pub no_project: bool,
4952
4953    #[command(flatten)]
4954    pub installer: ResolverInstallerArgs,
4955
4956    #[command(flatten)]
4957    pub build: BuildOptionsArgs,
4958
4959    #[command(flatten)]
4960    pub refresh: RefreshArgs,
4961}
4962
4963#[derive(Args)]
4964#[group(skip)]
4965pub struct AuditCommonArgs {
4966    // Hide the unsupported global offline option.
4967    #[arg(long, hide = true, overrides_with("no_offline"))]
4968    offline: bool,
4969
4970    /// Select the output format.
4971    #[arg(long, value_enum, default_value_t = AuditOutputFormat::default())]
4972    output_format: AuditOutputFormat,
4973
4974    /// Ignore a vulnerability by ID.
4975    ///
4976    /// Vulnerabilities matching any of the provided IDs (including aliases) will be excluded from
4977    /// the audit results.
4978    ///
4979    /// May be provided multiple times.
4980    #[arg(long)]
4981    ignore: Vec<String>,
4982
4983    /// Ignore a vulnerability by ID, but only while no fix is available.
4984    ///
4985    /// Vulnerabilities matching any of the provided IDs (including aliases) will be excluded from
4986    /// the audit results as long as they have no known fix versions. Once a fix version becomes
4987    /// available, the vulnerability will be reported again.
4988    ///
4989    /// May be provided multiple times.
4990    #[arg(long)]
4991    ignore_until_fixed: Vec<String>,
4992
4993    /// The service format to use for vulnerability lookups.
4994    ///
4995    /// Each service format has a default URL, which can be
4996    /// changed with `--service-url`. The defaults are:
4997    ///
4998    /// * OSV: <https://api.osv.dev/>
4999    #[arg(long, value_enum, default_value = "osv")]
5000    service_format: VulnerabilityServiceFormat,
5001
5002    /// The URL to vulnerability service API endpoint.
5003    ///
5004    /// If not provided, the default URL for the selected service will be used.
5005    ///
5006    /// The service needs to use the OSV protocol, unless a different
5007    /// format was requested by `--service-format`.
5008    #[arg(long, value_hint = ValueHint::Url)]
5009    service_url: Option<DisplaySafeUrl>,
5010}
5011
5012#[derive(Args)]
5013pub struct AuditArgs {
5014    /// Don't audit the specified optional dependencies.
5015    ///
5016    /// May be provided multiple times.
5017    #[arg(long, value_hint = ValueHint::Other)]
5018    pub no_extra: Vec<ExtraName>,
5019
5020    /// Don't audit the development dependency group [env: UV_NO_DEV=]
5021    ///
5022    /// This option is an alias of `--no-group dev`.
5023    /// See `--no-default-groups` to exclude all dependency groups instead.
5024    ///
5025    /// This option is only available when running in a project.
5026    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
5027    pub no_dev: bool,
5028
5029    /// Don't audit the specified dependency group [env: `UV_NO_GROUP`=]
5030    ///
5031    /// May be provided multiple times.
5032    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other)]
5033    pub no_group: Vec<GroupName>,
5034
5035    /// Don't audit dependency groups unless explicitly requested.
5036    ///
5037    /// By default, `uv audit` includes all dependency groups, regardless of `tool.uv.default-groups`.
5038    /// Groups can still be selected with `--only-group` or `--only-dev`.
5039    #[arg(long, env = EnvVars::UV_NO_DEFAULT_GROUPS, value_parser = clap::builder::BoolishValueParser::new())]
5040    pub no_default_groups: bool,
5041
5042    /// Only audit dependencies from the specified dependency group.
5043    ///
5044    /// The project and its dependencies will be omitted.
5045    ///
5046    /// May be provided multiple times. Implies `--no-default-groups`.
5047    #[arg(long, value_hint = ValueHint::Other)]
5048    pub only_group: Vec<GroupName>,
5049
5050    /// Only audit the development dependency group.
5051    ///
5052    /// The project and its dependencies will be omitted.
5053    ///
5054    /// This option is an alias for `--only-group dev`. Implies `--no-default-groups`.
5055    #[arg(long, conflicts_with_all = ["no_dev"])]
5056    pub only_dev: bool,
5057
5058    /// Assert that the `uv.lock` will remain unchanged [env: UV_LOCKED=]
5059    ///
5060    /// Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated,
5061    /// uv will exit with an error.
5062    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
5063    pub locked: bool,
5064
5065    /// Disable locked mode, overriding `UV_LOCKED`.
5066    #[arg(long, overrides_with = "locked", hide = true)]
5067    pub no_locked: bool,
5068
5069    /// Audit the requirements without locking the project [env: UV_FROZEN=]
5070    ///
5071    /// If the lockfile is missing, uv will exit with an error.
5072    #[arg(long, conflicts_with_all = ["locked", "upgrade", "no_sources"], overrides_with = "no_frozen")]
5073    pub frozen: bool,
5074
5075    /// Disable frozen mode, overriding `UV_FROZEN`.
5076    #[arg(long, overrides_with = "frozen", hide = true)]
5077    pub no_frozen: bool,
5078
5079    #[command(flatten)]
5080    pub audit: AuditCommonArgs,
5081
5082    #[command(flatten)]
5083    pub build: BuildOptionsArgs,
5084
5085    #[command(flatten)]
5086    pub resolver: ResolverArgs,
5087
5088    /// Audit the specified PEP 723 Python script, rather than the current
5089    /// project.
5090    ///
5091    /// The specified script must be locked, i.e. with `uv lock --script <script>`
5092    /// before it can be audited.
5093    #[arg(long, value_hint = ValueHint::FilePath)]
5094    pub script: Option<PathBuf>,
5095
5096    /// The Python version to use when auditing.
5097    ///
5098    /// For example, pass `--python-version 3.10` to audit the dependencies that would be included
5099    /// when installing on Python 3.10.
5100    ///
5101    /// Defaults to the version of the discovered Python interpreter.
5102    #[arg(long)]
5103    pub python_version: Option<PythonVersion>,
5104
5105    /// The platform to use when auditing.
5106    ///
5107    /// For example, pass `--platform windows` to audit the dependencies that would be included
5108    /// when installing on Windows.
5109    ///
5110    /// Represented as a "target triple", a string that describes the target platform in terms of
5111    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
5112    /// `aarch64-apple-darwin`.
5113    #[arg(long)]
5114    pub python_platform: Option<TargetTriple>,
5115}
5116
5117#[derive(Args)]
5118pub struct AuthNamespace {
5119    #[command(subcommand)]
5120    pub command: AuthCommand,
5121}
5122
5123#[derive(Subcommand)]
5124pub enum AuthCommand {
5125    /// Login to a service
5126    Login(AuthLoginArgs),
5127    /// Logout of a service
5128    Logout(AuthLogoutArgs),
5129    /// Show the authentication token for a service
5130    Token(AuthTokenArgs),
5131    /// Show the path to the uv credentials directory.
5132    ///
5133    /// By default, credentials are stored in the uv data directory at
5134    /// `$XDG_DATA_HOME/uv/credentials` or `$HOME/.local/share/uv/credentials` on Unix and
5135    /// `%APPDATA%\uv\data\credentials` on Windows.
5136    ///
5137    /// The credentials directory may be overridden with `$UV_CREDENTIALS_DIR`.
5138    ///
5139    /// Credentials are only stored in this directory when the plaintext backend is used, as
5140    /// opposed to the native backend, which uses the system keyring.
5141    Dir,
5142    /// Act as a credential helper for external tools.
5143    ///
5144    /// Implements the Bazel credential helper protocol to provide credentials
5145    /// to external tools via JSON over stdin/stdout.
5146    ///
5147    /// This command is typically invoked by external tools.
5148    #[command(hide = true)]
5149    Helper(AuthHelperArgs),
5150}
5151
5152#[derive(Args)]
5153pub struct ToolNamespace {
5154    #[command(subcommand)]
5155    pub command: ToolCommand,
5156}
5157
5158#[derive(Subcommand)]
5159pub enum ToolCommand {
5160    /// Run a command provided by a Python package.
5161    ///
5162    /// By default, the package to install is assumed to match the command name.
5163    ///
5164    /// The name of the command can include an exact version in the format `<package>@<version>`,
5165    /// e.g., `uv tool run ruff@0.3.0`. If more complex version specification is desired or if the
5166    /// command is provided by a different package, use `--from`.
5167    ///
5168    /// `uvx` can be used to invoke Python, e.g., with `uvx python` or `uvx python@<version>`. A
5169    /// Python interpreter will be started in an isolated virtual environment.
5170    ///
5171    /// If the tool was previously installed, i.e., via `uv tool install`, the installed version
5172    /// will be used unless a version is requested or the `--isolated` flag is used.
5173    ///
5174    /// `uvx` is provided as a convenient alias for `uv tool run`, their behavior is identical.
5175    ///
5176    /// If no command is provided, the installed tools are displayed.
5177    ///
5178    /// Packages are installed into an ephemeral virtual environment in the uv cache directory.
5179    #[command(
5180        after_help = "Use `uvx` as a shortcut for `uv tool run`.\n\n\
5181        Use `uv help tool run` for more details.",
5182        after_long_help = ""
5183    )]
5184    Run(ToolRunArgs),
5185    /// Hidden alias for `uv tool run` for the `uvx` command
5186    #[command(
5187        hide = true,
5188        override_usage = "uvx [OPTIONS] [COMMAND]",
5189        about = "Run a command provided by a Python package.",
5190        after_help = "Use `uv help tool run` for more details.",
5191        after_long_help = "",
5192        display_name = "uvx",
5193        long_version = crate::version::uv_self_version()
5194    )]
5195    Uvx(UvxArgs),
5196    /// Install commands provided by a Python package.
5197    ///
5198    /// Packages are installed into an isolated virtual environment in the uv tools directory. The
5199    /// executables are linked the tool executable directory, which is determined according to the
5200    /// XDG standard and can be retrieved with `uv tool dir --bin`.
5201    ///
5202    /// If the tool was previously installed, the existing tool will generally be replaced.
5203    Install(ToolInstallArgs),
5204    /// Upgrade installed tools.
5205    ///
5206    /// If a tool was installed with version constraints, they will be respected on upgrade — to
5207    /// upgrade a tool beyond the originally provided constraints, use `uv tool install` again.
5208    ///
5209    /// If a tool was installed with specific settings, they will be respected on upgraded. For
5210    /// example, if `--prereleases allow` was provided during installation, it will continue to be
5211    /// respected in upgrades.
5212    #[command(alias = "update")]
5213    Upgrade(ToolUpgradeArgs),
5214    /// List installed tools.
5215    #[command(alias = "ls")]
5216    List(ToolListArgs),
5217    /// Audit installed tools and their dependencies.
5218    ///
5219    /// Auditing requires network access and cannot be performed in offline mode.
5220    Audit(ToolAuditArgs),
5221    /// Uninstall a tool.
5222    Uninstall(ToolUninstallArgs),
5223    /// Ensure that the tool executable directory is on the `PATH`.
5224    ///
5225    /// If the tool executable directory is not present on the `PATH`, uv will attempt to add it to
5226    /// the relevant shell configuration files.
5227    ///
5228    /// If the shell configuration files already include a blurb to add the executable directory to
5229    /// the path, but the directory is not present on the `PATH`, uv will exit with an error.
5230    ///
5231    /// The tool executable directory is determined according to the XDG standard and can be
5232    /// retrieved with `uv tool dir --bin`.
5233    #[command(alias = "ensurepath")]
5234    UpdateShell,
5235    /// Show the path to the uv tools directory.
5236    ///
5237    /// The tools directory is used to store environments and metadata for installed tools.
5238    ///
5239    /// By default, tools are stored in the uv data directory at `$XDG_DATA_HOME/uv/tools` or
5240    /// `$HOME/.local/share/uv/tools` on Unix and `%APPDATA%\uv\data\tools` on Windows.
5241    ///
5242    /// The tool installation directory may be overridden with `$UV_TOOL_DIR`.
5243    ///
5244    /// To instead view the directory uv installs executables into, use the `--bin` flag.
5245    Dir(ToolDirArgs),
5246}
5247
5248#[derive(Args)]
5249pub struct ToolRunArgs {
5250    /// The command to run.
5251    ///
5252    /// WARNING: The documentation for [`Self::command`] is not included in help output
5253    #[command(subcommand)]
5254    pub command: Option<ExternalCommand>,
5255
5256    /// Use the given package to provide the command.
5257    ///
5258    /// By default, the package name is assumed to match the command name.
5259    #[arg(long, value_hint = ValueHint::Other)]
5260    pub from: Option<String>,
5261
5262    /// Run with the given packages installed.
5263    #[arg(short = 'w', long, value_hint = ValueHint::Other)]
5264    pub with: Vec<comma::CommaSeparatedRequirements>,
5265
5266    /// Run with the given packages installed in editable mode
5267    ///
5268    /// When used in a project, these dependencies will be layered on top of the uv tool's
5269    /// environment in a separate, ephemeral environment. These dependencies are allowed to conflict
5270    /// with those specified.
5271    #[arg(long, value_hint = ValueHint::DirPath)]
5272    pub with_editable: Vec<comma::CommaSeparatedRequirements>,
5273
5274    /// Run with the packages listed in the given files.
5275    ///
5276    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
5277    /// and `pylock.toml`.
5278    #[arg(
5279        long,
5280        value_delimiter = ',',
5281        value_hint = ValueHint::FilePath,
5282    )]
5283    pub with_requirements: Vec<Maybe<RequirementsInput>>,
5284
5285    /// Constrain versions using the given requirements files.
5286    ///
5287    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
5288    /// requirement that's installed. However, including a package in a constraints file will _not_
5289    /// trigger the installation of that package.
5290    ///
5291    /// This is equivalent to pip's `--constraint` option.
5292    #[arg(
5293        long,
5294        short,
5295        alias = "constraint",
5296        env = EnvVars::UV_CONSTRAINT,
5297        value_delimiter = ' ',
5298        value_hint = ValueHint::FilePath,
5299    )]
5300    pub constraints: Vec<Maybe<RequirementsInput>>,
5301
5302    /// Constrain build dependencies using the given requirements files when building source
5303    /// distributions.
5304    ///
5305    /// Constraints files are `requirements.txt`-like files that only control the _version_ of a
5306    /// requirement that's installed. However, including a package in a constraints file will _not_
5307    /// trigger the installation of that package.
5308    #[arg(
5309        long,
5310        short,
5311        alias = "build-constraint",
5312        env = EnvVars::UV_BUILD_CONSTRAINT,
5313        value_delimiter = ' ',
5314        value_hint = ValueHint::FilePath,
5315    )]
5316    pub build_constraints: Vec<Maybe<RequirementsInput>>,
5317
5318    /// Override versions using the given requirements files.
5319    ///
5320    /// Overrides files are `requirements.txt`-like files that force a specific version of a
5321    /// requirement to be installed, regardless of the requirements declared by any constituent
5322    /// package, and regardless of whether this would be considered an invalid resolution.
5323    ///
5324    /// While constraints are _additive_, in that they're combined with the requirements of the
5325    /// constituent packages, overrides are _absolute_, in that they completely replace the
5326    /// requirements of the constituent packages.
5327    #[arg(
5328        long,
5329        alias = "override",
5330        env = EnvVars::UV_OVERRIDE,
5331        value_delimiter = ' ',
5332        value_hint = ValueHint::FilePath,
5333    )]
5334    pub overrides: Vec<Maybe<RequirementsInput>>,
5335
5336    /// Run the tool in an isolated virtual environment, ignoring any already-installed tools [env:
5337    /// UV_ISOLATED=]
5338    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
5339    pub isolated: bool,
5340
5341    /// Load environment variables from a `.env` file.
5342    ///
5343    /// Can be provided multiple times, with subsequent files overriding values defined in previous
5344    /// files.
5345    #[arg(long, value_delimiter = ' ', env = EnvVars::UV_ENV_FILE, value_hint = ValueHint::FilePath)]
5346    pub env_file: Vec<PathBuf>,
5347
5348    /// Avoid reading environment variables from a `.env` file [env: UV_NO_ENV_FILE=]
5349    #[arg(long, value_parser = clap::builder::BoolishValueParser::new())]
5350    pub no_env_file: bool,
5351
5352    #[command(flatten)]
5353    pub installer: ResolverInstallerArgs,
5354
5355    #[command(flatten)]
5356    pub build: BuildOptionsArgs,
5357
5358    #[command(flatten)]
5359    pub refresh: RefreshArgs,
5360
5361    /// Whether to use Git LFS when adding a dependency from Git.
5362    #[arg(long)]
5363    pub lfs: bool,
5364
5365    /// The Python interpreter to use to build the run environment.
5366    ///
5367    /// See `uv help python` for details on Python discovery and supported request formats.
5368    #[arg(
5369        long,
5370        short,
5371        env = EnvVars::UV_PYTHON,
5372        verbatim_doc_comment,
5373        help_heading = "Python options",
5374        value_hint = ValueHint::Other,
5375    )]
5376    pub python: Option<Maybe<String>>,
5377
5378    /// Whether to show resolver and installer output from any environment modifications [env:
5379    /// UV_SHOW_RESOLUTION=]
5380    ///
5381    /// By default, environment modifications are omitted, but enabled under `--verbose`.
5382    #[arg(long, value_parser = clap::builder::BoolishValueParser::new(), hide = true)]
5383    pub show_resolution: bool,
5384
5385    /// The platform for which requirements should be installed.
5386    ///
5387    /// Represented as a "target triple", a string that describes the target platform in terms of
5388    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
5389    /// `aarch64-apple-darwin`.
5390    ///
5391    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
5392    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
5393    ///
5394    /// When targeting iOS, the default minimum version is `13.0`. Use
5395    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
5396    ///
5397    /// When targeting Android, the default minimum Android API level is `24`. Use
5398    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
5399    ///
5400    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
5401    /// platform; as a result, the installed distributions may not be compatible with the _current_
5402    /// platform. Conversely, any distributions that are built from source may be incompatible with
5403    /// the _target_ platform, as they will be built for the _current_ platform. The
5404    /// `--python-platform` option is intended for advanced use cases.
5405    #[arg(long)]
5406    pub python_platform: Option<TargetTriple>,
5407
5408    /// The backend to use when fetching packages in the PyTorch ecosystem (e.g., `cpu`, `cu126`, or `auto`)
5409    ///
5410    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
5411    /// and will instead use the defined backend.
5412    ///
5413    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
5414    /// uv will use the PyTorch index for CUDA 12.6.
5415    ///
5416    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
5417    /// installed CUDA drivers.
5418    ///
5419    /// This option is in preview and may change in any future release.
5420    #[arg(long, value_enum, env = EnvVars::UV_TORCH_BACKEND)]
5421    pub torch_backend: Option<TorchMode>,
5422
5423    #[arg(long, hide = true)]
5424    pub generate_shell_completion: Option<clap_complete_command::Shell>,
5425}
5426
5427#[derive(Args)]
5428pub struct UvxArgs {
5429    #[command(flatten)]
5430    pub tool_run: ToolRunArgs,
5431
5432    /// Display the uvx version.
5433    #[arg(short = 'V', long, action = clap::ArgAction::Version)]
5434    pub version: Option<bool>,
5435}
5436
5437#[derive(Args)]
5438pub struct ToolInstallArgs {
5439    /// The package to install commands from.
5440    #[arg(value_hint = ValueHint::Other)]
5441    package: String,
5442
5443    /// The package to install commands from.
5444    ///
5445    /// This option is provided for parity with `uv tool run`, but is redundant with `package`.
5446    #[arg(long, hide = true, value_hint = ValueHint::Other)]
5447    from: Option<String>,
5448
5449    /// Include the following additional requirements.
5450    #[arg(short = 'w', long, value_hint = ValueHint::Other)]
5451    with: Vec<comma::CommaSeparatedRequirements>,
5452
5453    /// Run with the packages listed in the given files.
5454    ///
5455    /// The following formats are supported: `requirements.txt`, `.py` files with inline metadata,
5456    /// and `pylock.toml`.
5457    #[arg(long, value_delimiter = ',', value_hint = ValueHint::FilePath)]
5458    with_requirements: Vec<Maybe<RequirementsInput>>,
5459
5460    /// Install the target package in editable mode, such that changes in the package's source
5461    /// directory are reflected without reinstallation.
5462    #[arg(short, long)]
5463    editable: bool,
5464
5465    /// Include the given packages in editable mode.
5466    #[arg(long, value_hint = ValueHint::DirPath)]
5467    with_editable: Vec<comma::CommaSeparatedRequirements>,
5468
5469    /// Install executables from the following packages.
5470    #[arg(long, value_hint = ValueHint::Other)]
5471    with_executables_from: Vec<comma::CommaSeparatedRequirements>,
5472
5473    #[command(flatten)]
5474    constraints: DependencyConstraintsArgs,
5475
5476    #[command(flatten)]
5477    installer: ResolverInstallerArgs,
5478
5479    #[command(flatten)]
5480    build: BuildOptionsArgs,
5481
5482    #[command(flatten)]
5483    refresh: RefreshArgs,
5484
5485    /// Force installation of the tool.
5486    ///
5487    /// Will recreate any existing environment for the tool and replace any existing entry points
5488    /// with the same name in the executable directory.
5489    #[arg(long)]
5490    force: bool,
5491
5492    /// Whether to use Git LFS when adding a dependency from Git.
5493    #[arg(long)]
5494    lfs: bool,
5495
5496    /// The Python interpreter to use to build the tool environment.
5497    ///
5498    /// See `uv help python` for details on Python discovery and supported request formats.
5499    #[arg(
5500        long,
5501        short,
5502        env = EnvVars::UV_PYTHON,
5503        verbatim_doc_comment,
5504        help_heading = "Python options",
5505        value_hint = ValueHint::Other,
5506    )]
5507    python: Option<Maybe<String>>,
5508
5509    /// The platform for which requirements should be installed.
5510    ///
5511    /// Represented as a "target triple", a string that describes the target platform in terms of
5512    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
5513    /// `aarch64-apple-darwin`.
5514    ///
5515    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
5516    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
5517    ///
5518    /// When targeting iOS, the default minimum version is `13.0`. Use
5519    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
5520    ///
5521    /// When targeting Android, the default minimum Android API level is `24`. Use
5522    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
5523    ///
5524    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
5525    /// platform; as a result, the installed distributions may not be compatible with the _current_
5526    /// platform. Conversely, any distributions that are built from source may be incompatible with
5527    /// the _target_ platform, as they will be built for the _current_ platform. The
5528    /// `--python-platform` option is intended for advanced use cases.
5529    #[arg(long)]
5530    python_platform: Option<TargetTriple>,
5531
5532    /// The backend to use when fetching packages in the PyTorch ecosystem (e.g., `cpu`, `cu126`, or `auto`)
5533    ///
5534    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
5535    /// and will instead use the defined backend.
5536    ///
5537    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
5538    /// uv will use the PyTorch index for CUDA 12.6.
5539    ///
5540    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
5541    /// installed CUDA drivers.
5542    ///
5543    /// This option is in preview and may change in any future release.
5544    #[arg(long, value_enum, env = EnvVars::UV_TORCH_BACKEND)]
5545    torch_backend: Option<TorchMode>,
5546}
5547
5548#[derive(Args)]
5549pub struct ToolListArgs {
5550    /// Whether to display the path to each tool environment and installed executable.
5551    #[arg(long)]
5552    show_paths: bool,
5553
5554    /// Whether to display the version specifier(s) used to install each tool.
5555    #[arg(long)]
5556    show_version_specifiers: bool,
5557
5558    /// Whether to display the additional requirements installed with each tool.
5559    #[arg(long)]
5560    show_with: bool,
5561
5562    /// Whether to display the extra requirements installed with each tool.
5563    #[arg(long)]
5564    show_extras: bool,
5565
5566    /// Whether to display the Python version associated with each tool.
5567    #[arg(long)]
5568    show_python: bool,
5569
5570    /// List outdated tools.
5571    ///
5572    /// The latest version of each tool will be shown alongside the installed version. Up-to-date
5573    /// tools will be omitted from the output.
5574    #[arg(long, overrides_with("no_outdated"))]
5575    outdated: bool,
5576
5577    #[arg(long, overrides_with("outdated"), hide = true)]
5578    no_outdated: bool,
5579
5580    #[command(flatten)]
5581    exclude_newer: PackageExcludeNewerArgs,
5582
5583    // Hide unused global Python options.
5584    #[arg(long, hide = true)]
5585    python_preference: Option<PythonPreference>,
5586
5587    #[arg(long, hide = true)]
5588    no_python_downloads: bool,
5589}
5590
5591#[derive(Args)]
5592pub struct ToolAuditArgs {
5593    /// The names of the installed tools to audit.
5594    #[arg(required = true, value_hint = ValueHint::Other)]
5595    name: Vec<PackageName>,
5596
5597    /// Audit all installed tools.
5598    #[arg(long, conflicts_with("name"))]
5599    all: bool,
5600
5601    #[command(flatten)]
5602    audit: AuditCommonArgs,
5603}
5604
5605#[derive(Args)]
5606pub struct ToolDirArgs {
5607    /// Show the directory into which `uv tool` will install executables.
5608    ///
5609    /// By default, `uv tool dir` shows the directory into which the tool Python environments
5610    /// themselves are installed, rather than the directory containing the linked executables.
5611    ///
5612    /// The tool executable directory is determined according to the XDG standard and is derived
5613    /// from the following environment variables, in order of preference:
5614    ///
5615    /// - `$UV_TOOL_BIN_DIR`
5616    /// - `$XDG_BIN_HOME`
5617    /// - `$XDG_DATA_HOME/../bin`
5618    /// - `$HOME/.local/bin`
5619    #[arg(long, verbatim_doc_comment)]
5620    bin: bool,
5621}
5622
5623#[derive(Args)]
5624pub struct ToolUninstallArgs {
5625    /// The name of the tool to uninstall.
5626    #[arg(required = true, value_hint = ValueHint::Other)]
5627    name: Vec<PackageName>,
5628
5629    /// Uninstall all tools.
5630    #[arg(long, conflicts_with("name"))]
5631    all: bool,
5632}
5633
5634#[derive(Args)]
5635pub struct ToolUpgradeArgs {
5636    /// The name of the tool to upgrade, along with an optional version specifier.
5637    #[arg(required = true, value_hint = ValueHint::Other)]
5638    name: Vec<String>,
5639
5640    /// Upgrade all tools.
5641    #[arg(long, conflicts_with("name"))]
5642    all: bool,
5643
5644    /// Upgrade a tool, and specify it to use the given Python interpreter to build its environment.
5645    /// Use with `--all` to apply to all tools.
5646    ///
5647    /// See `uv help python` for details on Python discovery and supported request formats.
5648    #[arg(
5649        long,
5650        short,
5651        env = EnvVars::UV_PYTHON,
5652        verbatim_doc_comment,
5653        help_heading = "Python options",
5654        value_hint = ValueHint::Other,
5655    )]
5656    python: Option<Maybe<String>>,
5657
5658    /// The platform for which requirements should be installed.
5659    ///
5660    /// Represented as a "target triple", a string that describes the target platform in terms of
5661    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
5662    /// `aarch64-apple-darwin`.
5663    ///
5664    /// When targeting macOS (Darwin), the default minimum version is `13.0`. Use
5665    /// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
5666    ///
5667    /// When targeting iOS, the default minimum version is `13.0`. Use
5668    /// `IPHONEOS_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `14.0`.
5669    ///
5670    /// When targeting Android, the default minimum Android API level is `24`. Use
5671    /// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
5672    ///
5673    /// WARNING: When specified, uv will select wheels that are compatible with the _target_
5674    /// platform; as a result, the installed distributions may not be compatible with the _current_
5675    /// platform. Conversely, any distributions that are built from source may be incompatible with
5676    /// the _target_ platform, as they will be built for the _current_ platform. The
5677    /// `--python-platform` option is intended for advanced use cases.
5678    #[arg(long)]
5679    python_platform: Option<TargetTriple>,
5680
5681    // The following is equivalent to flattening `ResolverInstallerArgs`, with the `--upgrade`,
5682    // `--upgrade-package`, and `--upgrade-group` options hidden, and the `--no-upgrade` option
5683    // removed.
5684    /// Allow package upgrades, ignoring pinned versions in any existing output file. Implies
5685    /// `--refresh`.
5686    #[arg(hide = true, long, short = 'U', help_heading = "Resolver options")]
5687    upgrade: bool,
5688
5689    /// Allow upgrades for a specific package, ignoring pinned versions in any existing output
5690    /// file. Implies `--refresh-package`.
5691    #[arg(hide = true, long, short = 'P', help_heading = "Resolver options")]
5692    upgrade_package: Vec<Requirement<VerbatimParsedUrl>>,
5693
5694    /// Allow upgrades for all packages in a dependency group, ignoring pinned versions in any
5695    /// existing output file.
5696    #[arg(hide = true, long, help_heading = "Resolver options")]
5697    upgrade_group: Vec<GroupName>,
5698
5699    #[command(flatten)]
5700    index_args: IndexArgs,
5701
5702    #[command(flatten)]
5703    reinstall: ReinstallArgs,
5704
5705    #[command(flatten)]
5706    registry_client: RegistryClientArgs,
5707
5708    #[command(flatten)]
5709    version_selection: VersionSelectionArgs,
5710
5711    /// Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs.
5712    #[arg(
5713        long,
5714        short = 'C',
5715        alias = "config-settings",
5716        help_heading = "Build options"
5717    )]
5718    config_setting: Option<Vec<ConfigSettingEntry>>,
5719
5720    /// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
5721    #[arg(
5722        long,
5723        alias = "config-settings-package",
5724        help_heading = "Build options"
5725    )]
5726    config_setting_package: Option<Vec<ConfigSettingPackageEntry>>,
5727
5728    #[command(flatten)]
5729    build_isolation: PackageBuildIsolationArgs,
5730
5731    #[command(flatten)]
5732    exclude_newer: PackageExcludeNewerArgs,
5733
5734    /// The method to use when installing packages from the global cache.
5735    ///
5736    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
5737    /// Windows.
5738    ///
5739    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
5740    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
5741    /// will break all installed packages by way of removing the underlying source files. Use
5742    /// symlinks with caution.
5743    #[arg(
5744        long,
5745        value_enum,
5746        env = EnvVars::UV_LINK_MODE,
5747        help_heading = "Installer options"
5748    )]
5749    link_mode: Option<uv_install_wheel::LinkMode>,
5750
5751    #[command(flatten)]
5752    compile_bytecode: CompileBytecodeArgs,
5753
5754    #[command(flatten)]
5755    sources: SourcesArgs,
5756
5757    #[command(flatten)]
5758    build: BuildOptionsArgs,
5759}
5760
5761#[derive(Args)]
5762pub struct PythonNamespace {
5763    #[command(subcommand)]
5764    pub command: PythonCommand,
5765}
5766
5767#[derive(Subcommand)]
5768pub enum PythonCommand {
5769    /// List the available Python installations.
5770    ///
5771    /// By default, installed Python versions and the downloads for latest available patch version
5772    /// of each supported Python major version are shown.
5773    ///
5774    /// Use `--managed-python` to view only managed Python versions.
5775    ///
5776    /// Use `--no-managed-python` to omit managed Python versions.
5777    ///
5778    /// Use `--all-versions` to view all available patch versions.
5779    ///
5780    /// Use `--only-installed` to omit available downloads.
5781    #[command(alias = "ls")]
5782    List(PythonListArgs),
5783
5784    /// Download and install Python versions.
5785    ///
5786    /// Supports CPython and PyPy. CPython distributions are downloaded from the Astral
5787    /// `python-build-standalone` project. PyPy distributions are downloaded from `python.org`. The
5788    /// available Python versions are bundled with each uv release. To install new Python versions,
5789    /// you may need upgrade uv.
5790    ///
5791    /// Python versions are installed into the uv Python directory, which can be retrieved with `uv
5792    /// python dir`.
5793    ///
5794    /// By default, Python executables are added to a directory on the path with a minor version
5795    /// suffix, e.g., `python3.13`. To install `python3` and `python`, use the `--default` flag. Use
5796    /// `uv python dir --bin` to see the target directory.
5797    ///
5798    /// Multiple Python versions may be requested.
5799    ///
5800    /// See `uv help python` to view supported request formats.
5801    Install(PythonInstallArgs),
5802
5803    /// Upgrade installed Python versions.
5804    ///
5805    /// Upgrades versions to the latest supported patch release.
5806    ///
5807    /// A target Python minor version to upgrade may be provided, e.g., `3.13`. Multiple versions
5808    /// may be provided to perform more than one upgrade.
5809    ///
5810    /// If no target version is provided, then uv will upgrade all managed CPython versions.
5811    ///
5812    /// During an upgrade, uv will not uninstall outdated patch versions.
5813    ///
5814    /// When an upgrade is performed, virtual environments created by uv will automatically
5815    /// use the new version. However, if the virtual environment was created before the
5816    /// upgrade functionality was added, it will continue to use the old Python version; to enable
5817    /// upgrades, the environment must be recreated.
5818    ///
5819    /// Upgrades are not yet supported for alternative implementations, like PyPy.
5820    Upgrade(PythonUpgradeArgs),
5821
5822    /// Search for a Python installation.
5823    ///
5824    /// Displays the path to the Python executable.
5825    ///
5826    /// See `uv help python` to view supported request formats and details on discovery behavior.
5827    Find(PythonFindArgs),
5828
5829    /// Pin to a specific Python version.
5830    ///
5831    /// Writes the pinned Python version to a `.python-version` file, which is used by other uv
5832    /// commands to determine the required Python version.
5833    ///
5834    /// If no version is provided, uv will look for an existing `.python-version` file and display
5835    /// the currently pinned version. If no `.python-version` file is found, uv will exit with an
5836    /// error.
5837    ///
5838    /// See `uv help python` to view supported request formats.
5839    Pin(PythonPinArgs),
5840
5841    /// Show the uv Python installation directory.
5842    ///
5843    /// By default, Python installations are stored in the uv data directory at
5844    /// `$XDG_DATA_HOME/uv/python` or `$HOME/.local/share/uv/python` on Unix and
5845    /// `%APPDATA%\uv\data\python` on Windows.
5846    ///
5847    /// The Python installation directory may be overridden with `$UV_PYTHON_INSTALL_DIR`.
5848    ///
5849    /// To view the directory where uv installs Python executables instead, use the `--bin` flag.
5850    /// The Python executable directory may be overridden with `$UV_PYTHON_BIN_DIR`.
5851    Dir(PythonDirArgs),
5852
5853    /// Uninstall Python versions.
5854    Uninstall(PythonUninstallArgs),
5855
5856    /// Ensure that the Python executable directory is on the `PATH`.
5857    ///
5858    /// If the Python executable directory is not present on the `PATH`, uv will attempt to add it to
5859    /// the relevant shell configuration files.
5860    ///
5861    /// If the shell configuration files already include a blurb to add the executable directory to
5862    /// the path, but the directory is not present on the `PATH`, uv will exit with an error.
5863    ///
5864    /// The Python executable directory is determined according to the XDG standard and can be
5865    /// retrieved with `uv python dir --bin`.
5866    #[command(alias = "ensurepath")]
5867    UpdateShell,
5868}
5869
5870#[derive(Args)]
5871pub struct PythonListArgs {
5872    /// A Python request to filter by.
5873    ///
5874    /// See `uv help python` to view supported request formats.
5875    request: Option<String>,
5876
5877    /// List all Python versions, including old patch versions.
5878    ///
5879    /// By default, only the latest patch version is shown for each minor version.
5880    #[arg(long)]
5881    all_versions: bool,
5882
5883    /// List Python downloads for all platforms.
5884    ///
5885    /// By default, only downloads for the current platform are shown.
5886    #[arg(long)]
5887    all_platforms: bool,
5888
5889    /// List Python downloads for all architectures.
5890    ///
5891    /// By default, only downloads for the current architecture are shown.
5892    #[arg(long, alias = "all_architectures")]
5893    all_arches: bool,
5894
5895    /// Only show installed Python versions.
5896    ///
5897    /// By default, installed distributions and available downloads for the current platform are shown.
5898    #[arg(long, conflicts_with("only_downloads"))]
5899    only_installed: bool,
5900
5901    /// Only show available Python downloads.
5902    ///
5903    /// By default, installed distributions and available downloads for the current platform are shown.
5904    #[arg(long, conflicts_with("only_installed"))]
5905    only_downloads: bool,
5906
5907    /// Show the URLs of available Python downloads.
5908    ///
5909    /// By default, these display as `<download available>`.
5910    #[arg(long)]
5911    show_urls: bool,
5912
5913    /// Select the output format.
5914    #[arg(long, value_enum, default_value_t = PythonListFormat::default())]
5915    output_format: PythonListFormat,
5916
5917    /// URL pointing to JSON of custom Python installations.
5918    #[arg(long, value_hint = ValueHint::Other)]
5919    python_downloads_json_url: Option<String>,
5920}
5921
5922#[derive(Args)]
5923pub struct PythonDirArgs {
5924    /// Show the directory into which `uv python` will install Python executables.
5925    ///
5926    /// The Python executable directory is determined according to the XDG standard and is derived
5927    /// from the following environment variables, in order of preference:
5928    ///
5929    /// - `$UV_PYTHON_BIN_DIR`
5930    /// - `$XDG_BIN_HOME`
5931    /// - `$XDG_DATA_HOME/../bin`
5932    /// - `$HOME/.local/bin`
5933    #[arg(long, verbatim_doc_comment)]
5934    bin: bool,
5935}
5936
5937#[derive(Args)]
5938pub struct PythonInstallCompileBytecodeArgs {
5939    /// Compile Python's standard library to bytecode after installation.
5940    ///
5941    /// By default, uv does not compile Python (`.py`) files to bytecode (`__pycache__/*.pyc`);
5942    /// instead, compilation is performed lazily the first time a module is imported. For use-cases
5943    /// in which start time is important, such as CLI applications and Docker containers, this
5944    /// option can be enabled to trade longer installation times and some additional disk space for
5945    /// faster start times.
5946    ///
5947    /// When enabled, uv will process the Python version's `stdlib` directory. It will ignore any
5948    /// compilation errors.
5949    #[arg(
5950        long,
5951        alias = "compile",
5952        overrides_with("no_compile_bytecode"),
5953        env = EnvVars::UV_COMPILE_BYTECODE,
5954        value_parser = clap::builder::BoolishValueParser::new(),
5955    )]
5956    compile_bytecode: bool,
5957
5958    #[arg(
5959        long,
5960        alias = "no-compile",
5961        overrides_with("compile_bytecode"),
5962        hide = true
5963    )]
5964    no_compile_bytecode: bool,
5965}
5966
5967#[derive(Args)]
5968pub struct PythonInstallArgs {
5969    /// The directory to store the Python installation in.
5970    ///
5971    /// If provided, `UV_PYTHON_INSTALL_DIR` will need to be set for subsequent operations for uv to
5972    /// discover the Python installation.
5973    ///
5974    /// See `uv python dir` to view the current Python installation directory. Defaults to
5975    /// `~/.local/share/uv/python`.
5976    #[arg(long, short, env = EnvVars::UV_PYTHON_INSTALL_DIR, value_hint = ValueHint::DirPath)]
5977    install_dir: Option<PathBuf>,
5978
5979    /// Install a Python executable into the `bin` directory.
5980    ///
5981    /// This is the default behavior. If this flag is provided explicitly, uv will error if the
5982    /// executable cannot be installed.
5983    ///
5984    /// This can also be set with `UV_PYTHON_INSTALL_BIN=1`.
5985    ///
5986    /// See `UV_PYTHON_BIN_DIR` to customize the target directory.
5987    #[arg(long, overrides_with("no_bin"), hide = true)]
5988    bin: bool,
5989
5990    /// Do not install a Python executable into the `bin` directory.
5991    ///
5992    /// This can also be set with `UV_PYTHON_INSTALL_BIN=0`.
5993    #[arg(long, overrides_with("bin"), conflicts_with("default"))]
5994    no_bin: bool,
5995
5996    /// Register the Python installation in the Windows registry.
5997    ///
5998    /// This is the default behavior on Windows. If this flag is provided explicitly, uv will error if the
5999    /// registry entry cannot be created.
6000    ///
6001    /// This can also be set with `UV_PYTHON_INSTALL_REGISTRY=1`.
6002    #[arg(long, overrides_with("no_registry"), hide = true)]
6003    registry: bool,
6004
6005    /// Do not register the Python installation in the Windows registry.
6006    ///
6007    /// This can also be set with `UV_PYTHON_INSTALL_REGISTRY=0`.
6008    #[arg(long, overrides_with("registry"))]
6009    no_registry: bool,
6010
6011    /// The Python version(s) to install.
6012    ///
6013    /// If not provided, the requested Python version(s) will be read from the `UV_PYTHON`
6014    /// environment variable then `.python-versions` or `.python-version` files. If none of the
6015    /// above are present, uv will check if it has installed any Python versions. If not, it will
6016    /// install the latest stable version of Python.
6017    ///
6018    /// See `uv help python` to view supported request formats.
6019    #[arg(env = EnvVars::UV_PYTHON)]
6020    targets: Vec<String>,
6021
6022    /// Set the URL to use as the source for downloading Python installations.
6023    ///
6024    /// The provided URL will replace
6025    /// `https://github.com/astral-sh/python-build-standalone/releases/download` in, e.g.,
6026    /// `https://github.com/astral-sh/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz`.
6027    ///
6028    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6029    #[arg(long, value_hint = ValueHint::Url)]
6030    mirror: Option<String>,
6031
6032    /// Set the URL to use as the source for downloading PyPy installations.
6033    ///
6034    /// The provided URL will replace `https://downloads.python.org/pypy` in, e.g.,
6035    /// `https://downloads.python.org/pypy/pypy3.8-v7.3.7-osx64.tar.bz2`.
6036    ///
6037    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6038    #[arg(long, value_hint = ValueHint::Url)]
6039    pypy_mirror: Option<String>,
6040
6041    /// Set the URL to use as the source for downloading GraalPy installations.
6042    ///
6043    /// The provided URL will replace `https://github.com/oracle/graalpython/releases/download` in, e.g.,
6044    /// `https://github.com/oracle/graalpython/releases/download/graal-24.2.2/graalpy-24.2.2-macos-aarch64.tar.gz`.
6045    ///
6046    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6047    #[arg(long, value_hint = ValueHint::Url)]
6048    graalpy_mirror: Option<String>,
6049
6050    /// Set the URL to use as the source for downloading Pyodide installations.
6051    ///
6052    /// The provided URL will replace `https://github.com/pyodide/pyodide/releases/download` in, e.g.,
6053    /// `https://github.com/pyodide/pyodide/releases/download/0.29.5/xbuildenv-0.29.5.tar.gz`.
6054    ///
6055    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6056    #[arg(long, value_hint = ValueHint::Url)]
6057    pyodide_mirror: Option<String>,
6058
6059    /// URL pointing to JSON of custom Python installations.
6060    #[arg(long, value_hint = ValueHint::Other)]
6061    python_downloads_json_url: Option<String>,
6062
6063    /// Reinstall the requested Python version, if it's already installed.
6064    ///
6065    /// If a minor version is requested, all matching installed patch versions are reinstalled.
6066    ///
6067    /// By default, uv will exit successfully if the version is already
6068    /// installed.
6069    #[arg(long, short)]
6070    reinstall: bool,
6071
6072    /// Replace existing Python executables during installation.
6073    ///
6074    /// By default, uv will refuse to replace executables that it does not manage.
6075    ///
6076    /// Implies `--reinstall`.
6077    #[arg(long, short)]
6078    force: bool,
6079
6080    /// Upgrade existing Python installations to the latest patch version.
6081    ///
6082    /// By default, uv will not upgrade already-installed Python versions to newer patch releases.
6083    /// With `--upgrade`, uv will upgrade to the latest available patch version for the specified
6084    /// minor version(s).
6085    ///
6086    /// If the requested versions are not yet installed, uv will install them.
6087    ///
6088    /// This option is only supported for minor version requests, e.g., `3.12`; uv will exit with an
6089    /// error if a patch version, e.g., `3.12.2`, is requested.
6090    #[arg(long, short = 'U')]
6091    upgrade: bool,
6092
6093    /// Use as the default Python version.
6094    ///
6095    /// By default, only a `python{major}.{minor}` executable is installed, e.g., `python3.10`. When
6096    /// the `--default` flag is used, `python{major}`, e.g., `python3`, and `python` executables are
6097    /// also installed.
6098    ///
6099    /// Alternative Python variants will still include their tag. For example, installing
6100    /// 3.13+freethreaded with `--default` will include `python3t` and `pythont` instead of
6101    /// `python3` and `python`.
6102    ///
6103    /// If multiple Python versions are requested, uv will exit with an error.
6104    #[arg(long, conflicts_with("no_bin"))]
6105    default: bool,
6106
6107    #[command(flatten)]
6108    compile_bytecode: PythonInstallCompileBytecodeArgs,
6109}
6110
6111impl PythonInstallArgs {
6112    #[must_use]
6113    fn install_mirrors(&self) -> PythonInstallMirrors {
6114        PythonInstallMirrors {
6115            python_install_mirror: self.mirror.clone(),
6116            pypy_install_mirror: self.pypy_mirror.clone(),
6117            graalpy_install_mirror: self.graalpy_mirror.clone(),
6118            pyodide_install_mirror: self.pyodide_mirror.clone(),
6119            python_downloads_json_url: self.python_downloads_json_url.clone(),
6120        }
6121    }
6122}
6123
6124#[derive(Args)]
6125pub struct PythonUpgradeArgs {
6126    /// The directory Python installations are stored in.
6127    ///
6128    /// If provided, `UV_PYTHON_INSTALL_DIR` will need to be set for subsequent operations for uv to
6129    /// discover the Python installation.
6130    ///
6131    /// See `uv python dir` to view the current Python installation directory. Defaults to
6132    /// `~/.local/share/uv/python`.
6133    #[arg(long, short, env = EnvVars::UV_PYTHON_INSTALL_DIR, value_hint = ValueHint::DirPath)]
6134    install_dir: Option<PathBuf>,
6135
6136    /// The Python minor version(s) to upgrade.
6137    ///
6138    /// If no target version is provided, then uv will upgrade all managed CPython versions.
6139    #[arg(env = EnvVars::UV_PYTHON)]
6140    targets: Vec<String>,
6141
6142    /// Set the URL to use as the source for downloading Python installations.
6143    ///
6144    /// The provided URL will replace
6145    /// `https://github.com/astral-sh/python-build-standalone/releases/download` in, e.g.,
6146    /// `https://github.com/astral-sh/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz`.
6147    ///
6148    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6149    #[arg(long, value_hint = ValueHint::Url)]
6150    mirror: Option<String>,
6151
6152    /// Set the URL to use as the source for downloading PyPy installations.
6153    ///
6154    /// The provided URL will replace `https://downloads.python.org/pypy` in, e.g.,
6155    /// `https://downloads.python.org/pypy/pypy3.8-v7.3.7-osx64.tar.bz2`.
6156    ///
6157    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6158    #[arg(long, value_hint = ValueHint::Url)]
6159    pypy_mirror: Option<String>,
6160
6161    /// Set the URL to use as the source for downloading GraalPy installations.
6162    ///
6163    /// The provided URL will replace `https://github.com/oracle/graalpython/releases/download` in, e.g.,
6164    /// `https://github.com/oracle/graalpython/releases/download/graal-24.2.2/graalpy-24.2.2-macos-aarch64.tar.gz`.
6165    ///
6166    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6167    #[arg(long, value_hint = ValueHint::Url)]
6168    graalpy_mirror: Option<String>,
6169
6170    /// Set the URL to use as the source for downloading Pyodide installations.
6171    ///
6172    /// The provided URL will replace `https://github.com/pyodide/pyodide/releases/download` in, e.g.,
6173    /// `https://github.com/pyodide/pyodide/releases/download/0.29.5/xbuildenv-0.29.5.tar.gz`.
6174    ///
6175    /// Distributions can be read from a local directory by using the `file://` URL scheme.
6176    #[arg(long, value_hint = ValueHint::Url)]
6177    pyodide_mirror: Option<String>,
6178
6179    /// Reinstall the latest Python patch, if it's already installed.
6180    ///
6181    /// By default, uv will exit successfully if the latest patch is already
6182    /// installed.
6183    #[arg(long, short)]
6184    reinstall: bool,
6185
6186    /// URL pointing to JSON of custom Python installations.
6187    #[arg(long, value_hint = ValueHint::Other)]
6188    python_downloads_json_url: Option<String>,
6189
6190    #[command(flatten)]
6191    compile_bytecode: PythonInstallCompileBytecodeArgs,
6192}
6193
6194impl PythonUpgradeArgs {
6195    #[must_use]
6196    fn install_mirrors(&self) -> PythonInstallMirrors {
6197        PythonInstallMirrors {
6198            python_install_mirror: self.mirror.clone(),
6199            pypy_install_mirror: self.pypy_mirror.clone(),
6200            graalpy_install_mirror: self.graalpy_mirror.clone(),
6201            pyodide_install_mirror: self.pyodide_mirror.clone(),
6202            python_downloads_json_url: self.python_downloads_json_url.clone(),
6203        }
6204    }
6205}
6206
6207#[derive(Args)]
6208pub struct PythonUninstallArgs {
6209    /// The directory where the Python was installed.
6210    #[arg(long, short, env = EnvVars::UV_PYTHON_INSTALL_DIR, value_hint = ValueHint::DirPath)]
6211    install_dir: Option<PathBuf>,
6212
6213    /// The Python version(s) to uninstall.
6214    ///
6215    /// See `uv help python` to view supported request formats.
6216    #[arg(required = true)]
6217    targets: Vec<String>,
6218
6219    /// Uninstall all managed Python versions.
6220    #[arg(long, conflicts_with("targets"))]
6221    all: bool,
6222}
6223
6224#[derive(Args)]
6225pub struct PythonFindArgs {
6226    /// The Python request.
6227    ///
6228    /// See `uv help python` to view supported request formats.
6229    pub request: Option<String>,
6230
6231    /// Avoid discovering a project or workspace.
6232    ///
6233    /// Otherwise, when no request is provided, the Python requirement of a project in the current
6234    /// directory or parent directories will be used.
6235    #[arg(
6236        long,
6237        alias = "no_workspace",
6238        env = EnvVars::UV_NO_PROJECT,
6239        value_parser = clap::builder::BoolishValueParser::new()
6240    )]
6241    pub no_project: bool,
6242
6243    /// Only find system Python interpreters.
6244    ///
6245    /// By default, uv will report the first Python interpreter it would use, including those in an
6246    /// active virtual environment or a virtual environment in the current working directory or any
6247    /// parent directory.
6248    ///
6249    /// The `--system` option instructs uv to skip virtual environment Python interpreters and
6250    /// restrict its search to the system path.
6251    #[arg(
6252        long,
6253        env = EnvVars::UV_SYSTEM_PYTHON,
6254        value_parser = clap::builder::BoolishValueParser::new(),
6255        overrides_with("no_system")
6256    )]
6257    pub system: bool,
6258
6259    #[arg(long, overrides_with("system"), hide = true)]
6260    pub no_system: bool,
6261
6262    /// Find the environment for a Python script, rather than the current project.
6263    #[arg(
6264        long,
6265        conflicts_with = "request",
6266        conflicts_with = "no_project",
6267        conflicts_with = "system",
6268        conflicts_with = "no_system",
6269        value_hint = ValueHint::FilePath,
6270    )]
6271    pub script: Option<PathBuf>,
6272
6273    /// Show the Python version that would be used instead of the path to the interpreter.
6274    #[arg(long)]
6275    pub show_version: bool,
6276
6277    /// Resolve symlinks in the output path.
6278    ///
6279    /// When enabled, the output path will be canonicalized, resolving any symlinks.
6280    #[arg(long)]
6281    pub resolve_links: bool,
6282
6283    /// URL pointing to JSON of custom Python installations.
6284    #[arg(long, value_hint = ValueHint::Other)]
6285    pub python_downloads_json_url: Option<String>,
6286}
6287
6288#[derive(Args)]
6289pub struct PythonPinArgs {
6290    /// The Python version request.
6291    ///
6292    /// uv supports more formats than other tools that read `.python-version` files, i.e., `pyenv`.
6293    /// If compatibility with those tools is needed, only use version numbers instead of complex
6294    /// requests such as `cpython@3.10`.
6295    ///
6296    /// If no request is provided, the currently pinned version will be shown.
6297    ///
6298    /// See `uv help python` to view supported request formats.
6299    request: Option<String>,
6300
6301    /// Write the resolved Python interpreter path instead of the request.
6302    ///
6303    /// Ensures that the exact same interpreter is used.
6304    ///
6305    /// This option is usually not safe to use when committing the `.python-version` file to version
6306    /// control.
6307    #[arg(long, overrides_with("resolved"))]
6308    resolved: bool,
6309
6310    #[arg(long, overrides_with("no_resolved"), hide = true)]
6311    no_resolved: bool,
6312
6313    /// Avoid validating the Python pin is compatible with the project or workspace.
6314    ///
6315    /// By default, a project or workspace is discovered in the current directory or any parent
6316    /// directory. If a workspace is found, the Python pin is validated against the workspace's
6317    /// `requires-python` constraint.
6318    #[arg(
6319        long,
6320        alias = "no-workspace",
6321        env = EnvVars::UV_NO_PROJECT,
6322        value_parser = clap::builder::BoolishValueParser::new()
6323    )]
6324    no_project: bool,
6325
6326    /// Update the global Python version pin.
6327    ///
6328    /// Writes the pinned Python version to a `.python-version` file in the uv user configuration
6329    /// directory: `XDG_CONFIG_HOME/uv` on Linux/macOS and `%APPDATA%/uv` on Windows.
6330    ///
6331    /// When a local Python version pin is not found in the working directory or an ancestor
6332    /// directory, this version will be used instead.
6333    #[arg(long)]
6334    global: bool,
6335
6336    /// Remove the Python version pin.
6337    #[arg(long, conflicts_with = "request", conflicts_with = "resolved")]
6338    rm: bool,
6339
6340    /// URL pointing to JSON of custom Python installations.
6341    #[arg(long, value_hint = ValueHint::Other)]
6342    python_downloads_json_url: Option<String>,
6343}
6344
6345#[derive(Args)]
6346pub struct AuthLogoutArgs {
6347    /// The domain or URL of the service to logout from.
6348    service: Service,
6349
6350    /// The username to logout.
6351    #[arg(long, short, value_hint = ValueHint::Other)]
6352    username: Option<String>,
6353
6354    #[arg(
6355        long,
6356        value_enum,
6357        env = EnvVars::UV_KEYRING_PROVIDER,
6358        hide = true,
6359    )]
6360    keyring_provider: Option<KeyringProviderType>,
6361}
6362
6363#[derive(Args)]
6364pub struct AuthLoginArgs {
6365    /// The domain or URL of the service to log into.
6366    #[arg(value_hint = ValueHint::Url)]
6367    service: Service,
6368
6369    /// The username to use for the service.
6370    #[arg(long, short, conflicts_with = "token", value_hint = ValueHint::Other)]
6371    username: Option<String>,
6372
6373    /// The password to use for the service.
6374    ///
6375    /// Use `-` to read the password from stdin.
6376    #[arg(long, conflicts_with = "token", value_hint = ValueHint::Other)]
6377    password: Option<String>,
6378
6379    /// The token to use for the service.
6380    ///
6381    /// The username will be set to `__token__`.
6382    ///
6383    /// Use `-` to read the token from stdin.
6384    #[arg(long, short, conflicts_with = "username", conflicts_with = "password", value_hint = ValueHint::Other)]
6385    token: Option<String>,
6386
6387    #[arg(
6388        long,
6389        value_enum,
6390        env = EnvVars::UV_KEYRING_PROVIDER,
6391        hide = true,
6392    )]
6393    keyring_provider: Option<KeyringProviderType>,
6394}
6395
6396#[derive(Args)]
6397pub struct AuthTokenArgs {
6398    /// The domain or URL of the service to lookup.
6399    #[arg(value_hint = ValueHint::Url)]
6400    service: Service,
6401
6402    /// The username to lookup.
6403    #[arg(long, short, value_hint = ValueHint::Other)]
6404    username: Option<String>,
6405
6406    #[arg(
6407        long,
6408        value_enum,
6409        env = EnvVars::UV_KEYRING_PROVIDER,
6410        hide = true,
6411    )]
6412    keyring_provider: Option<KeyringProviderType>,
6413}
6414
6415#[derive(Args)]
6416pub struct AuthHelperArgs {
6417    #[command(subcommand)]
6418    pub command: AuthHelperCommand,
6419
6420    /// The credential helper protocol to use
6421    #[arg(long, value_enum, required = true)]
6422    pub protocol: AuthHelperProtocol,
6423}
6424
6425/// Credential helper protocols supported by uv
6426#[derive(Debug, Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
6427pub enum AuthHelperProtocol {
6428    /// Bazel credential helper protocol as described in [the
6429    /// spec](https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md)
6430    Bazel,
6431}
6432
6433#[derive(Subcommand)]
6434pub enum AuthHelperCommand {
6435    /// Retrieve credentials for a URI
6436    Get,
6437}
6438
6439#[derive(Args)]
6440pub struct GenerateShellCompletionArgs {
6441    /// The shell to generate the completion script for
6442    pub shell: clap_complete_command::Shell,
6443
6444    // Hide unused global options.
6445    #[arg(long, short, hide = true)]
6446    pub no_cache: bool,
6447    #[arg(long, hide = true)]
6448    pub cache_dir: Option<PathBuf>,
6449
6450    #[arg(long, hide = true)]
6451    pub python_preference: Option<PythonPreference>,
6452    #[arg(long, hide = true)]
6453    pub no_python_downloads: bool,
6454
6455    #[arg(long, short, action = clap::ArgAction::Count, conflicts_with = "verbose", hide = true)]
6456    pub quiet: u8,
6457    #[arg(long, short, action = clap::ArgAction::Count, conflicts_with = "quiet", hide = true)]
6458    pub verbose: u8,
6459    #[arg(long, conflicts_with = "no_color", hide = true)]
6460    pub color: Option<ColorChoice>,
6461    #[arg(long, hide = true)]
6462    pub native_tls: bool,
6463    #[arg(long, hide = true)]
6464    pub offline: bool,
6465    #[arg(long, hide = true)]
6466    pub no_progress: bool,
6467    #[arg(long, hide = true)]
6468    pub config_file: Option<PathBuf>,
6469    #[arg(long, hide = true)]
6470    pub no_config: bool,
6471    #[arg(long, short, action = clap::ArgAction::HelpShort, hide = true)]
6472    pub help: Option<bool>,
6473    #[arg(short = 'V', long, hide = true)]
6474    pub version: bool,
6475}
6476
6477#[derive(Args)]
6478pub struct IndexArgs {
6479    /// The indexes to use when resolving dependencies, in addition to the default index.
6480    ///
6481    /// Accepts either a repository compliant with PEP 503 (the simple repository API), or a local
6482    /// directory laid out in the same format.
6483    ///
6484    /// All indexes provided via this flag take priority over the index specified by
6485    /// `--default-index` (which defaults to PyPI). When multiple `--index` flags are provided,
6486    /// earlier values take priority.
6487    ///
6488    /// Indexes configured in `uv.toml` or `pyproject.toml` may be selected by name. Enable the
6489    /// `index-by-name` preview feature to prefer index names over relative paths.
6490    ///
6491    /// Relative paths can be disambiguated from index names with `./` or `../` on Unix or `.\\`,
6492    /// `..\\`, `./` or `../` on Windows.
6493    //
6494    // The nested Vec structure (`Vec<Vec<Maybe<IndexArg>>>`) is required for clap's
6495    // value parsing mechanism, which processes one value at a time, in order to handle
6496    // `UV_INDEX` the same way pip handles `PIP_EXTRA_INDEX_URL`.
6497    #[arg(
6498        long,
6499        env = EnvVars::UV_INDEX,
6500        hide_env_values = true,
6501        value_parser = parse_indices,
6502        help_heading = "Index options"
6503    )]
6504    index: Option<Vec<Vec<Maybe<IndexArg>>>>,
6505
6506    /// The default package index (by default: <https://pypi.org/simple>).
6507    ///
6508    /// Accepts either a repository compliant with PEP 503 (the simple repository API), or a local
6509    /// directory laid out in the same format.
6510    ///
6511    /// The index given by this flag is given lower priority than all other indexes specified via
6512    /// the `--index` flag.
6513    ///
6514    /// Indexes configured in `uv.toml` or `pyproject.toml` may be selected by name. Enable the
6515    /// `index-by-name` preview feature to prefer index names over relative paths.
6516    #[arg(
6517        long,
6518        env = EnvVars::UV_DEFAULT_INDEX,
6519        hide_env_values = true,
6520        value_parser = parse_default_index,
6521        help_heading = "Index options"
6522    )]
6523    default_index: Option<Maybe<IndexArg>>,
6524
6525    /// (Deprecated: use `--default-index` instead) The URL of the Python package index (by default:
6526    /// <https://pypi.org/simple>).
6527    ///
6528    /// Accepts either a repository compliant with PEP 503 (the simple repository API), or a local
6529    /// directory laid out in the same format.
6530    ///
6531    /// The index given by this flag is given lower priority than all other indexes specified via
6532    /// the `--extra-index-url` flag.
6533    #[arg(
6534        long,
6535        short,
6536        env = EnvVars::UV_INDEX_URL,
6537        hide_env_values = true,
6538        value_parser = parse_index_url,
6539        help_heading = "Index options"
6540    )]
6541    index_url: Option<Maybe<PipIndex>>,
6542
6543    /// (Deprecated: use `--index` instead) Extra URLs of package indexes to use, in addition to
6544    /// `--index-url`.
6545    ///
6546    /// Accepts either a repository compliant with PEP 503 (the simple repository API), or a local
6547    /// directory laid out in the same format.
6548    ///
6549    /// All indexes provided via this flag take priority over the index specified by `--index-url`
6550    /// (which defaults to PyPI). When multiple `--extra-index-url` flags are provided, earlier
6551    /// values take priority.
6552    #[arg(
6553        long,
6554        env = EnvVars::UV_EXTRA_INDEX_URL,
6555        hide_env_values = true,
6556        value_delimiter = ' ',
6557        value_parser = parse_extra_index_url,
6558        help_heading = "Index options"
6559    )]
6560    extra_index_url: Option<Vec<Maybe<PipExtraIndex>>>,
6561
6562    /// Locations to search for candidate distributions, in addition to those found in the registry
6563    /// indexes.
6564    ///
6565    /// If a path, the target must be a directory that contains packages as wheel files (`.whl`) or
6566    /// source distributions (e.g., `.tar.gz` or `.zip`) at the top level.
6567    ///
6568    /// If a URL, the page must contain a flat list of links to package files adhering to the
6569    /// formats described above.
6570    #[arg(
6571        long,
6572        short,
6573        env = EnvVars::UV_FIND_LINKS,
6574        hide_env_values = true,
6575        value_delimiter = ',',
6576        value_parser = parse_find_links,
6577        help_heading = "Index options"
6578    )]
6579    find_links: Option<Vec<Maybe<PipFindLinks>>>,
6580
6581    /// Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those
6582    /// provided via `--find-links`.
6583    #[arg(long, help_heading = "Index options")]
6584    no_index: bool,
6585}
6586
6587/// Arguments that configure the package registry client.
6588#[derive(Args)]
6589#[group(skip)]
6590pub struct RegistryClientArgs {
6591    /// The strategy to use when resolving against multiple index URLs.
6592    ///
6593    /// By default, uv will stop at the first index on which a given package is available, and limit
6594    /// resolutions to those present on that first index (`first-index`). This prevents "dependency
6595    /// confusion" attacks, whereby an attacker can upload a malicious package under the same name
6596    /// to an alternate index.
6597    #[arg(
6598        long,
6599        value_enum,
6600        env = EnvVars::UV_INDEX_STRATEGY,
6601        help_heading = "Index options"
6602    )]
6603    index_strategy: Option<IndexStrategy>,
6604
6605    /// Attempt to use `keyring` for authentication for index URLs.
6606    ///
6607    /// At present, only `--keyring-provider subprocess` is supported, which configures uv to use
6608    /// the `keyring` CLI to handle authentication.
6609    ///
6610    /// Defaults to `disabled`.
6611    #[arg(
6612        long,
6613        value_enum,
6614        env = EnvVars::UV_KEYRING_PROVIDER,
6615        help_heading = "Index options"
6616    )]
6617    keyring_provider: Option<KeyringProviderType>,
6618}
6619
6620/// Arguments that control dependency sources.
6621#[derive(Args)]
6622#[group(skip)]
6623pub struct SourcesArgs {
6624    /// Ignore the `tool.uv.sources` table when resolving dependencies. Used to lock against the
6625    /// standards-compliant, publishable package metadata, as opposed to using any workspace, Git,
6626    /// URL, or local path sources.
6627    #[arg(
6628        long,
6629        env = EnvVars::UV_NO_SOURCES,
6630        value_parser = clap::builder::BoolishValueParser::new(),
6631        help_heading = "Resolver options",
6632    )]
6633    no_sources: bool,
6634
6635    /// Don't use sources from the `tool.uv.sources` table for the specified packages [env: `UV_NO_SOURCES_PACKAGE`=]
6636    #[arg(long, help_heading = "Resolver options", value_delimiter = ' ')]
6637    no_sources_package: Vec<PackageName>,
6638}
6639
6640/// Arguments that configure package version selection.
6641#[derive(Args)]
6642#[group(skip)]
6643pub struct VersionSelectionArgs {
6644    /// The strategy to use when selecting between the different compatible versions for a given
6645    /// package requirement.
6646    ///
6647    /// By default, uv will use the latest compatible version of each package (`highest`).
6648    #[arg(
6649        long,
6650        value_enum,
6651        env = EnvVars::UV_RESOLUTION,
6652        help_heading = "Resolver options"
6653    )]
6654    resolution: Option<ResolutionMode>,
6655
6656    /// The strategy to use when considering pre-release versions.
6657    ///
6658    /// By default, uv will prefer stable candidates, falling back to pre-releases only after every
6659    /// stable candidate that satisfies the active constraints is rejected
6660    /// (`if-necessary`).
6661    #[arg(
6662        long,
6663        value_enum,
6664        env = EnvVars::UV_PRERELEASE,
6665        help_heading = "Resolver options"
6666    )]
6667    prerelease: Option<PrereleaseMode>,
6668
6669    /// The strategy to use when considering pre-release versions for a specific package.
6670    ///
6671    /// Accepts package-mode pairs in the format `PACKAGE=MODE`, where `MODE` is any value
6672    /// accepted by `--prerelease`.
6673    ///
6674    /// May be provided multiple times for different packages.
6675    #[arg(long, help_heading = "Resolver options", value_hint = ValueHint::Other)]
6676    prerelease_package: Option<Vec<PrereleasePackageEntry>>,
6677
6678    #[arg(long, hide = true, help_heading = "Resolver options")]
6679    pre: bool,
6680
6681    /// The strategy to use when selecting multiple versions of a given package across Python
6682    /// versions and platforms.
6683    ///
6684    /// By default, uv will optimize for selecting the latest version of each package for each
6685    /// supported Python version (`requires-python`), while minimizing the number of selected
6686    /// versions across platforms.
6687    ///
6688    /// Under `fewest`, uv will minimize the number of selected versions for each package,
6689    /// preferring older versions that are compatible with a wider range of supported Python
6690    /// versions or platforms.
6691    #[arg(
6692        long,
6693        value_enum,
6694        env = EnvVars::UV_FORK_STRATEGY,
6695        help_heading = "Resolver options"
6696    )]
6697    fork_strategy: Option<ForkStrategy>,
6698}
6699
6700/// Arguments that select dependency groups in a project or workspace.
6701#[derive(Args)]
6702#[group(skip)]
6703pub struct ProjectDependencyGroupsArgs<const CHECKS_CONFLICTS: bool = false> {
6704    /// Include the development dependency group [env: UV_DEV=]
6705    ///
6706    /// Development dependencies are defined via `dependency-groups.dev` or
6707    /// `tool.uv.dev-dependencies` in a `pyproject.toml`.
6708    ///
6709    /// This option is an alias for `--group dev`.
6710    ///
6711    /// This option is only available when running in a project.
6712    #[arg(long, overrides_with("no_dev"), hide = true, value_parser = clap::builder::BoolishValueParser::new())]
6713    dev: bool,
6714
6715    /// Disable the development dependency group [env: UV_NO_DEV=]
6716    ///
6717    /// This option is an alias of `--no-group dev`.
6718    /// See `--no-default-groups` to disable all default groups instead.
6719    ///
6720    /// This option is only available when running in a project.
6721    #[arg(long, overrides_with("dev"), value_parser = clap::builder::BoolishValueParser::new())]
6722    no_dev: bool,
6723
6724    /// Only include the development dependency group.
6725    ///
6726    /// The project and its dependencies will be omitted.
6727    ///
6728    /// This option is an alias for `--only-group dev`. Implies `--no-default-groups`.
6729    #[arg(long, conflicts_with_all = ["group", "all_groups", "no_dev"])]
6730    only_dev: bool,
6731
6732    /// Include dependencies from the specified dependency group.
6733    ///
6734    /// May be provided multiple times.
6735    #[arg(
6736        long,
6737        conflicts_with_all = ["only_group", "only_dev"],
6738        value_hint = ValueHint::Other,
6739        long_help = if CHECKS_CONFLICTS {
6740            concat!(
6741                "Include dependencies from the specified dependency group.\n\n",
6742                "When multiple extras or groups are specified that appear in ",
6743                "`tool.uv.conflicts`, uv will report an error.\n\n",
6744                "May be provided multiple times."
6745            )
6746        } else {
6747            concat!(
6748                "Include dependencies from the specified dependency group.\n\n",
6749                "May be provided multiple times."
6750            )
6751        }
6752    )]
6753    group: Vec<GroupName>,
6754
6755    /// Disable the specified dependency group [env: `UV_NO_GROUP`=]
6756    ///
6757    /// This option always takes precedence over default groups,
6758    /// `--all-groups`, and `--group`.
6759    ///
6760    /// May be provided multiple times.
6761    #[arg(long, value_delimiter = ' ', value_hint = ValueHint::Other)]
6762    no_group: Vec<GroupName>,
6763
6764    /// Ignore the default dependency groups.
6765    ///
6766    /// uv includes the groups defined in `tool.uv.default-groups` by default.
6767    /// This disables that option, however, specific groups can still be included with `--group`.
6768    #[arg(long, env = EnvVars::UV_NO_DEFAULT_GROUPS, value_parser = clap::builder::BoolishValueParser::new())]
6769    no_default_groups: bool,
6770
6771    /// Only include dependencies from the specified dependency group.
6772    ///
6773    /// The project and its dependencies will be omitted.
6774    ///
6775    /// May be provided multiple times. Implies `--no-default-groups`.
6776    #[arg(long, conflicts_with_all = ["group", "dev", "all_groups"], value_hint = ValueHint::Other)]
6777    only_group: Vec<GroupName>,
6778
6779    /// Include dependencies from all dependency groups.
6780    ///
6781    /// `--no-group` can be used to exclude specific groups.
6782    #[arg(long, conflicts_with_all = ["only_group", "only_dev"])]
6783    all_groups: bool,
6784}
6785
6786/// Dependency-group arguments for commands that reject conflicting extras or groups.
6787pub type ConflictCheckedDependencyGroupsArgs = ProjectDependencyGroupsArgs<true>;
6788
6789/// Arguments that configure requirement hash checking.
6790#[derive(Args)]
6791#[group(skip)]
6792pub struct HashCheckingArgs {
6793    /// Require a matching hash for each requirement.
6794    ///
6795    /// By default, uv will verify any available hashes in the requirements file, but will not
6796    /// require that all requirements have an associated hash.
6797    ///
6798    /// When `--require-hashes` is enabled, _all_ requirements must include a hash or set of hashes,
6799    /// and _all_ requirements must either be pinned to exact versions (e.g., `==1.0.0`), or be
6800    /// specified via direct URL.
6801    ///
6802    /// Hash-checking mode introduces a number of additional constraints:
6803    ///
6804    /// - Git dependencies are not supported.
6805    /// - Editable installations are not supported.
6806    /// - Local dependencies are not supported, unless they point to a specific wheel (`.whl`) or
6807    ///   source archive (`.zip`, `.tar.gz`), as opposed to a directory.
6808    #[arg(
6809        long,
6810        env = EnvVars::UV_REQUIRE_HASHES,
6811        value_parser = clap::builder::BoolishValueParser::new(),
6812        overrides_with("no_require_hashes"),
6813    )]
6814    require_hashes: bool,
6815
6816    #[arg(long, overrides_with("require_hashes"), hide = true)]
6817    no_require_hashes: bool,
6818
6819    #[arg(long, overrides_with("no_verify_hashes"), hide = true)]
6820    verify_hashes: bool,
6821
6822    /// Disable validation of hashes in the requirements file.
6823    ///
6824    /// By default, uv will verify any available hashes in the requirements file, but will not
6825    /// require that all requirements have an associated hash. To enforce hash validation, use
6826    /// `--require-hashes`.
6827    #[arg(
6828        long,
6829        env = EnvVars::UV_NO_VERIFY_HASHES,
6830        value_parser = clap::builder::BoolishValueParser::new(),
6831        overrides_with("verify_hashes"),
6832    )]
6833    no_verify_hashes: bool,
6834}
6835
6836/// Arguments that filter packages by upload date.
6837#[derive(Args)]
6838#[group(skip)]
6839pub struct ExcludeNewerArgs {
6840    /// Limit candidate packages to those that were uploaded prior to the given date.
6841    ///
6842    /// The date is compared against the upload time of each individual distribution artifact
6843    /// (i.e., when each file was uploaded to the package index), not the release date of the
6844    /// package version.
6845    ///
6846    /// Accepts RFC 3339 timestamps (e.g., `2006-12-02T02:07:43Z`), local dates in the same format
6847    /// (e.g., `2006-12-02`) resolved based on your system's configured time zone, a "friendly"
6848    /// duration (e.g., `24 hours`, `1 week`, `30 days`), or an ISO 8601 duration (e.g., `PT24H`,
6849    /// `P7D`, `P30D`).
6850    ///
6851    /// Durations do not respect semantics of the local time zone and are always resolved to a fixed
6852    /// number of seconds assuming that a day is 24 hours (e.g., DST transitions are ignored).
6853    /// Calendar units such as months and years are not allowed.
6854    ///
6855    /// Use `false` to disable `exclude-newer`.
6856    #[arg(
6857        long,
6858        env = EnvVars::UV_EXCLUDE_NEWER,
6859        help_heading = "Resolver options",
6860        value_hint = ValueHint::Other,
6861    )]
6862    exclude_newer: Option<ExcludeNewerOverride>,
6863}
6864
6865/// Arguments that filter packages by global and package-specific upload dates.
6866#[derive(Args)]
6867#[group(skip)]
6868pub struct PackageExcludeNewerArgs {
6869    #[command(flatten)]
6870    exclude_newer: ExcludeNewerArgs,
6871
6872    /// Limit candidate packages for specific packages to those that were uploaded prior to the
6873    /// given date.
6874    ///
6875    /// Accepts package-date pairs in the format `PACKAGE=DATE`, where `DATE` is an RFC 3339
6876    /// timestamp (e.g., `2006-12-02T02:07:43Z`), a local date in the same format (e.g.,
6877    /// `2006-12-02`) resolved based on your system's configured time zone, a "friendly" duration
6878    /// (e.g., `24 hours`, `1 week`, `30 days`), or an ISO 8601 duration (e.g., `PT24H`, `P7D`,
6879    /// `P30D`).
6880    ///
6881    /// Durations do not respect semantics of the local time zone and are always resolved to a fixed
6882    /// number of seconds assuming that a day is 24 hours (e.g., DST transitions are ignored).
6883    /// Calendar units such as months and years are not allowed.
6884    ///
6885    /// Can be provided multiple times for different packages.
6886    #[arg(long, help_heading = "Resolver options", value_hint = ValueHint::Other)]
6887    exclude_newer_package: Option<Vec<ExcludeNewerPackageEntry>>,
6888}
6889
6890#[derive(Args)]
6891pub struct RefreshArgs {
6892    /// Refresh all cached data.
6893    #[arg(long, overrides_with("no_refresh"), help_heading = "Cache options")]
6894    refresh: bool,
6895
6896    #[arg(
6897        long,
6898        overrides_with("refresh"),
6899        hide = true,
6900        help_heading = "Cache options"
6901    )]
6902    no_refresh: bool,
6903
6904    /// Refresh cached data for a specific package.
6905    #[arg(long, help_heading = "Cache options", value_hint = ValueHint::Other)]
6906    refresh_package: Vec<PackageName>,
6907}
6908
6909#[derive(Args)]
6910pub struct BuildOptionsArgs {
6911    /// Don't build source distributions.
6912    ///
6913    /// When enabled, uv will reuse cached wheels from previously built source distributions, but
6914    /// operations that require building a source distribution will exit with an error. First-party
6915    /// packages, such as projects in the workspace, will still be built. uv will also still build
6916    /// editable requirements, and their build backends may run arbitrary Python code.
6917    #[arg(
6918        long,
6919        env = EnvVars::UV_NO_BUILD,
6920        overrides_with("build"),
6921        value_parser = clap::builder::BoolishValueParser::new(),
6922        help_heading = "Build options",
6923    )]
6924    no_build: bool,
6925
6926    #[arg(
6927        long,
6928        overrides_with("no_build"),
6929        hide = true,
6930        help_heading = "Build options"
6931    )]
6932    build: bool,
6933
6934    /// Don't build source distributions for a specific package [env: `UV_NO_BUILD_PACKAGE`=]
6935    ///
6936    /// First-party packages, such as projects in the workspace, will still be built.
6937    #[arg(
6938        long,
6939        help_heading = "Build options",
6940        value_delimiter = ' ',
6941        value_hint = ValueHint::Other,
6942    )]
6943    no_build_package: Vec<PackageName>,
6944
6945    /// Don't install pre-built wheels.
6946    ///
6947    /// The given packages will be built and installed from source. The resolver will still use
6948    /// pre-built wheels to extract package metadata, if available.
6949    #[arg(
6950        long,
6951        env = EnvVars::UV_NO_BINARY,
6952        overrides_with("binary"),
6953        value_parser = clap::builder::BoolishValueParser::new(),
6954        help_heading = "Build options"
6955    )]
6956    no_binary: bool,
6957
6958    #[arg(
6959        long,
6960        overrides_with("no_binary"),
6961        hide = true,
6962        help_heading = "Build options"
6963    )]
6964    binary: bool,
6965
6966    /// Don't install pre-built wheels for a specific package [env: `UV_NO_BINARY_PACKAGE`=]
6967    #[arg(
6968        long,
6969        help_heading = "Build options",
6970        value_delimiter = ' ',
6971        value_hint = ValueHint::Other,
6972    )]
6973    no_binary_package: Vec<PackageName>,
6974}
6975
6976/// Arguments that configure build isolation for source distributions.
6977#[derive(Args)]
6978#[group(skip)]
6979pub struct BuildIsolationArgs {
6980    /// Disable isolation when building source distributions.
6981    ///
6982    /// Assumes that build dependencies specified by PEP 518 are already installed.
6983    #[arg(
6984        long,
6985        overrides_with("build_isolation"),
6986        help_heading = "Build options",
6987        env = EnvVars::UV_NO_BUILD_ISOLATION,
6988        value_parser = clap::builder::BoolishValueParser::new(),
6989    )]
6990    no_build_isolation: bool,
6991
6992    #[arg(
6993        long,
6994        overrides_with("no_build_isolation"),
6995        hide = true,
6996        help_heading = "Build options"
6997    )]
6998    build_isolation: bool,
6999}
7000
7001/// Arguments that configure global and package-specific build isolation.
7002#[derive(Args)]
7003#[group(skip)]
7004pub struct PackageBuildIsolationArgs {
7005    #[command(flatten)]
7006    build_isolation: BuildIsolationArgs,
7007
7008    /// Disable isolation when building source distributions for a specific package.
7009    ///
7010    /// Assumes that the packages' build dependencies specified by PEP 518 are already installed.
7011    #[arg(long, help_heading = "Build options", value_hint = ValueHint::Other)]
7012    no_build_isolation_package: Vec<PackageName>,
7013}
7014
7015#[derive(Args)]
7016#[group(skip)]
7017pub struct ReinstallArgs {
7018    /// Reinstall all packages, regardless of whether they're already installed. Implies
7019    /// `--refresh`.
7020    #[arg(
7021        long,
7022        alias = "force-reinstall",
7023        overrides_with("no_reinstall"),
7024        help_heading = "Installer options"
7025    )]
7026    reinstall: bool,
7027
7028    #[arg(
7029        long,
7030        overrides_with("reinstall"),
7031        hide = true,
7032        help_heading = "Installer options"
7033    )]
7034    no_reinstall: bool,
7035
7036    /// Reinstall a specific package, regardless of whether it's already installed. Implies
7037    /// `--refresh-package`.
7038    #[arg(long, help_heading = "Installer options", value_hint = ValueHint::Other)]
7039    reinstall_package: Vec<PackageName>,
7040}
7041
7042#[derive(Args)]
7043#[group(skip)]
7044pub struct CompileBytecodeArgs {
7045    /// Compile Python files to bytecode after installation.
7046    ///
7047    /// By default, uv does not compile Python (`.py`) files to bytecode (`__pycache__/*.pyc`);
7048    /// instead, compilation is performed lazily the first time a module is imported. For use-cases
7049    /// in which start time is critical, such as CLI applications and Docker containers, this option
7050    /// can be enabled to trade longer installation times for faster start times.
7051    ///
7052    /// When enabled, install operations (e.g., `uv pip install`) will compile installed or
7053    /// reinstalled Python files. Commands that perform a sync operation (e.g., `uv sync` or `uv
7054    /// run`) will process the entire site-packages directory including packages that are not being
7055    /// modified.
7056    #[arg(
7057        long,
7058        alias = "compile",
7059        overrides_with("no_compile_bytecode"),
7060        help_heading = "Installer options",
7061        env = EnvVars::UV_COMPILE_BYTECODE,
7062        value_parser = clap::builder::BoolishValueParser::new(),
7063    )]
7064    compile_bytecode: bool,
7065
7066    #[arg(
7067        long,
7068        alias = "no-compile",
7069        overrides_with("compile_bytecode"),
7070        hide = true,
7071        help_heading = "Installer options"
7072    )]
7073    no_compile_bytecode: bool,
7074}
7075
7076/// Arguments that are used by commands that need to install (but not resolve) packages.
7077#[derive(Args)]
7078pub struct InstallerArgs {
7079    #[command(flatten)]
7080    index_args: IndexArgs,
7081
7082    #[command(flatten)]
7083    reinstall: ReinstallArgs,
7084
7085    #[command(flatten)]
7086    registry_client: RegistryClientArgs,
7087
7088    /// Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs.
7089    #[arg(
7090        long,
7091        short = 'C',
7092        alias = "config-settings",
7093        help_heading = "Build options"
7094    )]
7095    config_setting: Option<Vec<ConfigSettingEntry>>,
7096
7097    /// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
7098    #[arg(
7099        long,
7100        alias = "config-settings-package",
7101        help_heading = "Build options"
7102    )]
7103    config_settings_package: Option<Vec<ConfigSettingPackageEntry>>,
7104
7105    #[command(flatten)]
7106    build_isolation: BuildIsolationArgs,
7107
7108    #[command(flatten)]
7109    exclude_newer: PackageExcludeNewerArgs,
7110
7111    /// The method to use when installing packages from the global cache.
7112    ///
7113    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
7114    /// Windows.
7115    ///
7116    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
7117    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
7118    /// will break all installed packages by way of removing the underlying source files. Use
7119    /// symlinks with caution.
7120    #[arg(
7121        long,
7122        value_enum,
7123        env = EnvVars::UV_LINK_MODE,
7124        help_heading = "Installer options"
7125    )]
7126    link_mode: Option<uv_install_wheel::LinkMode>,
7127
7128    #[command(flatten)]
7129    compile_bytecode: CompileBytecodeArgs,
7130
7131    #[command(flatten)]
7132    sources: SourcesArgs,
7133}
7134
7135/// Arguments that are used by commands that need to resolve (but not install) packages.
7136#[derive(Args)]
7137pub struct ResolverArgs {
7138    #[command(flatten)]
7139    index_args: IndexArgs,
7140
7141    /// Allow package upgrades, ignoring pinned versions in any existing output file. Implies
7142    /// `--refresh`.
7143    #[arg(
7144        long,
7145        short = 'U',
7146        overrides_with("no_upgrade"),
7147        help_heading = "Resolver options"
7148    )]
7149    upgrade: bool,
7150
7151    #[arg(
7152        long,
7153        overrides_with("upgrade"),
7154        hide = true,
7155        help_heading = "Resolver options"
7156    )]
7157    no_upgrade: bool,
7158
7159    /// Allow upgrades for a specific package, ignoring pinned versions in any existing output
7160    /// file. Implies `--refresh-package`.
7161    #[arg(long, short = 'P', help_heading = "Resolver options")]
7162    upgrade_package: Vec<Requirement<VerbatimParsedUrl>>,
7163
7164    /// Allow upgrades for all packages in a dependency group, ignoring pinned versions in any
7165    /// existing output file.
7166    #[arg(long, help_heading = "Resolver options")]
7167    upgrade_group: Vec<GroupName>,
7168
7169    #[command(flatten)]
7170    registry_client: RegistryClientArgs,
7171
7172    #[command(flatten)]
7173    version_selection: VersionSelectionArgs,
7174
7175    /// Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs.
7176    #[arg(
7177        long,
7178        short = 'C',
7179        alias = "config-settings",
7180        help_heading = "Build options"
7181    )]
7182    config_setting: Option<Vec<ConfigSettingEntry>>,
7183
7184    /// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
7185    #[arg(
7186        long,
7187        alias = "config-settings-package",
7188        help_heading = "Build options"
7189    )]
7190    config_settings_package: Option<Vec<ConfigSettingPackageEntry>>,
7191
7192    #[command(flatten)]
7193    build_isolation: PackageBuildIsolationArgs,
7194
7195    #[command(flatten)]
7196    exclude_newer: PackageExcludeNewerArgs,
7197
7198    /// The method to use when installing packages from the global cache.
7199    ///
7200    /// This option is only used when building source distributions.
7201    ///
7202    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
7203    /// Windows.
7204    ///
7205    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
7206    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
7207    /// will break all installed packages by way of removing the underlying source files. Use
7208    /// symlinks with caution.
7209    #[arg(
7210        long,
7211        value_enum,
7212        env = EnvVars::UV_LINK_MODE,
7213        help_heading = "Installer options"
7214    )]
7215    link_mode: Option<uv_install_wheel::LinkMode>,
7216
7217    #[command(flatten)]
7218    sources: SourcesArgs,
7219}
7220
7221/// Arguments that are used by commands that need to resolve and install packages.
7222#[derive(Args)]
7223pub struct ResolverInstallerArgs {
7224    #[command(flatten)]
7225    index_args: IndexArgs,
7226
7227    /// Allow package upgrades, ignoring pinned versions in any existing output file. Implies
7228    /// `--refresh`.
7229    #[arg(
7230        long,
7231        short = 'U',
7232        overrides_with("no_upgrade"),
7233        help_heading = "Resolver options"
7234    )]
7235    upgrade: bool,
7236
7237    #[arg(
7238        long,
7239        overrides_with("upgrade"),
7240        hide = true,
7241        help_heading = "Resolver options"
7242    )]
7243    no_upgrade: bool,
7244
7245    /// Allow upgrades for a specific package, ignoring pinned versions in any existing output file.
7246    /// Implies `--refresh-package`.
7247    #[arg(long, short = 'P', help_heading = "Resolver options", value_hint = ValueHint::Other)]
7248    upgrade_package: Vec<Requirement<VerbatimParsedUrl>>,
7249
7250    /// Allow upgrades for all packages in a dependency group, ignoring pinned versions in any
7251    /// existing output file.
7252    #[arg(long, help_heading = "Resolver options")]
7253    upgrade_group: Vec<GroupName>,
7254
7255    #[command(flatten)]
7256    reinstall: ReinstallArgs,
7257
7258    #[command(flatten)]
7259    registry_client: RegistryClientArgs,
7260
7261    #[command(flatten)]
7262    version_selection: VersionSelectionArgs,
7263
7264    /// Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs.
7265    #[arg(
7266        long,
7267        short = 'C',
7268        alias = "config-settings",
7269        help_heading = "Build options",
7270        value_hint = ValueHint::Other,
7271    )]
7272    config_setting: Option<Vec<ConfigSettingEntry>>,
7273
7274    /// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
7275    #[arg(
7276        long,
7277        alias = "config-settings-package",
7278        help_heading = "Build options",
7279        value_hint = ValueHint::Other,
7280    )]
7281    config_settings_package: Option<Vec<ConfigSettingPackageEntry>>,
7282
7283    #[command(flatten)]
7284    build_isolation: PackageBuildIsolationArgs,
7285
7286    #[command(flatten)]
7287    exclude_newer: PackageExcludeNewerArgs,
7288
7289    /// The method to use when installing packages from the global cache.
7290    ///
7291    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
7292    /// Windows.
7293    ///
7294    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
7295    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
7296    /// will break all installed packages by way of removing the underlying source files. Use
7297    /// symlinks with caution.
7298    #[arg(
7299        long,
7300        value_enum,
7301        env = EnvVars::UV_LINK_MODE,
7302        help_heading = "Installer options"
7303    )]
7304    link_mode: Option<uv_install_wheel::LinkMode>,
7305
7306    #[command(flatten)]
7307    compile_bytecode: CompileBytecodeArgs,
7308
7309    #[command(flatten)]
7310    sources: SourcesArgs,
7311}
7312
7313/// Arguments that are used by commands that need to fetch from the Simple API.
7314#[derive(Args)]
7315pub struct FetchArgs {
7316    #[command(flatten)]
7317    index_args: IndexArgs,
7318
7319    #[command(flatten)]
7320    registry_client: RegistryClientArgs,
7321
7322    #[command(flatten)]
7323    exclude_newer: PackageExcludeNewerArgs,
7324}
7325
7326#[derive(Args)]
7327pub struct DisplayTreeArgs {
7328    /// Maximum display depth of the dependency tree
7329    #[arg(long, short, default_value_t = 255)]
7330    depth: u8,
7331
7332    /// Prune the given package from the display of the dependency tree.
7333    #[arg(long, value_hint = ValueHint::Other)]
7334    prune: Vec<PackageName>,
7335
7336    /// Display only the specified packages.
7337    #[arg(long, value_hint = ValueHint::Other)]
7338    package: Vec<PackageName>,
7339
7340    /// Do not de-duplicate repeated dependencies. Usually, when a package has already displayed its
7341    /// dependencies, further occurrences will not re-display its dependencies, and will include a
7342    /// (*) to indicate it has already been shown. This flag will cause those duplicates to be
7343    /// repeated.
7344    #[arg(long)]
7345    no_dedupe: bool,
7346
7347    /// Show the reverse dependencies for the given package. This flag will invert the tree and
7348    /// display the packages that depend on the given package.
7349    #[arg(long, alias = "reverse")]
7350    invert: bool,
7351
7352    /// Show the latest available version of each package in the tree.
7353    #[arg(long)]
7354    outdated: bool,
7355
7356    /// Show compressed wheel sizes for packages in the tree.
7357    #[arg(long)]
7358    show_sizes: bool,
7359}
7360
7361#[derive(Args, Debug)]
7362pub struct PublishArgs {
7363    // Hide the unsupported global offline option.
7364    #[arg(long, hide = true, overrides_with("no_offline"))]
7365    pub offline: bool,
7366
7367    /// Paths to the files to upload. Accepts glob expressions.
7368    ///
7369    /// Defaults to the `dist` directory. Selects only wheels and source distributions
7370    /// and their attestations, while ignoring other files.
7371    #[arg(default_value = "dist/*", value_hint = ValueHint::FilePath)]
7372    pub files: Vec<String>,
7373
7374    /// The name of an index in the configuration to use for publishing.
7375    ///
7376    /// The index must have a `publish-url` setting, for example:
7377    ///
7378    /// ```toml
7379    /// [[tool.uv.index]]
7380    /// name = "pypi"
7381    /// url = "https://pypi.org/simple"
7382    /// publish-url = "https://upload.pypi.org/legacy/"
7383    /// ```
7384    ///
7385    /// The index `url` will be used to check for existing files to skip duplicate uploads.
7386    ///
7387    /// With these settings, the following two calls are equivalent:
7388    ///
7389    /// ```shell
7390    /// uv publish --index pypi
7391    /// uv publish --publish-url https://upload.pypi.org/legacy/ --check-url https://pypi.org/simple
7392    /// ```
7393    #[arg(
7394        long,
7395        verbatim_doc_comment,
7396        env = EnvVars::UV_PUBLISH_INDEX,
7397        conflicts_with = "publish_url",
7398        conflicts_with = "check_url",
7399        value_hint = ValueHint::Other,
7400    )]
7401    pub index: Option<String>,
7402
7403    /// The username for the upload.
7404    #[arg(
7405        short,
7406        long,
7407        env = EnvVars::UV_PUBLISH_USERNAME,
7408        hide_env_values = true,
7409        value_hint = ValueHint::Other
7410    )]
7411    pub username: Option<String>,
7412
7413    /// The password for the upload.
7414    #[arg(
7415        short,
7416        long,
7417        env = EnvVars::UV_PUBLISH_PASSWORD,
7418        hide_env_values = true,
7419        value_hint = ValueHint::Other
7420    )]
7421    pub password: Option<String>,
7422
7423    /// The token for the upload.
7424    ///
7425    /// Using a token is equivalent to passing `__token__` as `--username` and the token as
7426    /// `--password` password.
7427    #[arg(
7428        short,
7429        long,
7430        env = EnvVars::UV_PUBLISH_TOKEN,
7431        hide_env_values = true,
7432        conflicts_with = "username",
7433        conflicts_with = "password",
7434        value_hint = ValueHint::Other,
7435    )]
7436    pub token: Option<String>,
7437
7438    /// Configure trusted publishing.
7439    ///
7440    /// By default, uv checks for trusted publishing when running in a supported environment, but
7441    /// ignores it if it isn't configured.
7442    ///
7443    /// uv's supported environments for trusted publishing include GitHub Actions and GitLab CI/CD.
7444    #[arg(long)]
7445    pub trusted_publishing: Option<TrustedPublishing>,
7446
7447    /// Attempt to use `keyring` for authentication for remote requirements files.
7448    ///
7449    /// At present, only `--keyring-provider subprocess` is supported, which configures uv to use
7450    /// the `keyring` CLI to handle authentication.
7451    ///
7452    /// Defaults to `disabled`.
7453    #[arg(long, value_enum, env = EnvVars::UV_KEYRING_PROVIDER)]
7454    pub keyring_provider: Option<KeyringProviderType>,
7455
7456    /// The URL of the upload endpoint (not the index URL).
7457    ///
7458    /// Note that there are typically different URLs for index access (e.g., `https:://.../simple`)
7459    /// and index upload.
7460    ///
7461    /// Defaults to PyPI's publish URL (<https://upload.pypi.org/legacy/>).
7462    #[arg(long, env = EnvVars::UV_PUBLISH_URL, hide_env_values = true)]
7463    pub publish_url: Option<DisplaySafeUrl>,
7464
7465    /// Check an index URL for existing files to skip duplicate uploads.
7466    ///
7467    /// This option allows retrying publishing that failed after only some, but not all files have
7468    /// been uploaded, and handles errors due to parallel uploads of the same file.
7469    ///
7470    /// Before uploading, the index is checked. If the exact same file already exists in the index,
7471    /// the file will not be uploaded. If an error occurred during the upload, the index is checked
7472    /// again, to handle cases where the identical file was uploaded twice in parallel.
7473    ///
7474    /// The exact behavior will vary based on the index. When uploading to PyPI, uploading the same
7475    /// file succeeds even without `--check-url`, while most other indexes error.
7476    ///
7477    /// The index must provide one of the supported hashes (SHA-256, SHA-384, or SHA-512).
7478    #[arg(long, env = EnvVars::UV_PUBLISH_CHECK_URL, hide_env_values = true)]
7479    pub check_url: Option<IndexUrl>,
7480
7481    #[arg(long, hide = true)]
7482    pub skip_existing: bool,
7483
7484    /// Perform a dry run without uploading files.
7485    ///
7486    /// The command checks the distribution metadata locally, and checks for existing files if
7487    /// `--check-url` or `--index` is provided, but will not upload any files.
7488    #[arg(long)]
7489    pub dry_run: bool,
7490
7491    /// Do not upload attestations for the published files.
7492    ///
7493    /// By default, uv attempts to upload matching PEP 740 attestations with each distribution
7494    /// that is published.
7495    #[arg(long, env = EnvVars::UV_PUBLISH_NO_ATTESTATIONS)]
7496    pub no_attestations: bool,
7497}
7498
7499#[derive(Args)]
7500pub struct WorkspaceNamespace {
7501    #[command(subcommand)]
7502    pub command: WorkspaceCommand,
7503}
7504
7505#[derive(Subcommand)]
7506pub enum WorkspaceCommand {
7507    /// View metadata about the current workspace.
7508    ///
7509    /// The output of this command is not yet stable.
7510    Metadata(Box<MetadataArgs>),
7511    /// Display the path of a workspace member.
7512    ///
7513    /// By default, the path to the workspace root directory is displayed.
7514    /// The `--package` option can be used to display the path to a workspace member instead.
7515    ///
7516    /// If used outside of a workspace, i.e., if a `pyproject.toml` cannot be found, uv will exit with an error.
7517    Dir(WorkspaceDirArgs),
7518    /// List the members of a workspace.
7519    ///
7520    /// Displays newline separated names of workspace members.
7521    List(WorkspaceListArgs),
7522}
7523#[derive(Args)]
7524pub struct MetadataArgs {
7525    /// View metadata for the specified PEP 723 Python script, rather than the current workspace.
7526    ///
7527    /// If provided, uv will resolve the dependencies based on the script's inline metadata table,
7528    /// in adherence with PEP 723.
7529    #[arg(long, value_hint = ValueHint::FilePath)]
7530    pub script: Option<PathBuf>,
7531
7532    /// Check if the lockfile is up-to-date [env: UV_LOCKED=]
7533    ///
7534    /// Asserts that the `uv.lock` would remain unchanged after a resolution. If the lockfile is
7535    /// missing or needs to be updated, uv will exit with an error.
7536    #[arg(long, conflicts_with_all = ["frozen", "upgrade"], overrides_with = "no_locked")]
7537    pub locked: bool,
7538
7539    /// Disable locked mode, overriding `UV_LOCKED`.
7540    #[arg(long, overrides_with = "locked", hide = true)]
7541    pub no_locked: bool,
7542
7543    /// Assert that a `uv.lock` exists without checking if it is up-to-date [env: UV_FROZEN=]
7544    #[arg(long, conflicts_with_all = ["locked"], overrides_with = "no_frozen")]
7545    pub frozen: bool,
7546
7547    /// Disable frozen mode, overriding `UV_FROZEN`.
7548    #[arg(long, overrides_with = "frozen", hide = true)]
7549    pub no_frozen: bool,
7550
7551    #[command(flatten)]
7552    pub resolver: ResolverArgs,
7553
7554    #[command(flatten)]
7555    pub build: BuildOptionsArgs,
7556
7557    #[command(flatten)]
7558    pub refresh: RefreshArgs,
7559
7560    /// Sync the environment to include module ownership metadata in the output.
7561    ///
7562    /// This adds a mapping from importable module names to references to the package nodes
7563    /// that provide them. By default, the environment is synced in inexact mode.
7564    ///
7565    /// This also allows creating or updating the lockfile, unless `--locked` or `--frozen` is
7566    /// provided. For scripts, the lockfile is only updated if it already exists.
7567    #[arg(long)]
7568    pub sync: bool,
7569
7570    /// Perform an exact sync, removing extraneous packages.
7571    ///
7572    /// By default, synchronization preserves packages that are not part of the selected
7573    /// resolution. When enabled, uv removes those packages from the environment.
7574    #[arg(long, requires = "sync")]
7575    pub exact: bool,
7576
7577    /// Sync dependencies to the active virtual environment.
7578    ///
7579    /// Instead of creating or updating the virtual environment for the project or script, the
7580    /// active virtual environment will be preferred, if the `VIRTUAL_ENV` environment variable is
7581    /// set.
7582    #[arg(long)]
7583    pub active: bool,
7584
7585    /// The Python interpreter to use during resolution.
7586    ///
7587    /// A Python interpreter is required for building source distributions to determine package
7588    /// metadata when there are not wheels.
7589    ///
7590    /// The interpreter is also used as the fallback value for the minimum Python version if
7591    /// `requires-python` is not set.
7592    ///
7593    /// See `uv help python` for details on Python discovery and supported request formats.
7594    #[arg(
7595        long,
7596        short,
7597        env = EnvVars::UV_PYTHON,
7598        verbatim_doc_comment,
7599        help_heading = "Python options",
7600        value_hint = ValueHint::Other,
7601    )]
7602    pub python: Option<Maybe<String>>,
7603}
7604
7605#[derive(Args, Debug)]
7606pub struct WorkspaceDirArgs {
7607    /// Display the path to a specific package in the workspace.
7608    #[arg(long, value_hint = ValueHint::Other)]
7609    pub package: Option<PackageName>,
7610}
7611
7612#[derive(Args, Debug)]
7613pub struct WorkspaceListArgs {
7614    /// Show paths instead of names.
7615    #[arg(long)]
7616    pub paths: bool,
7617
7618    /// List all standalone scripts with inline metadata in the workspace.
7619    #[arg(long)]
7620    pub scripts: bool,
7621}
7622
7623/// See [PEP 517](https://peps.python.org/pep-0517/) and
7624/// [PEP 660](https://peps.python.org/pep-0660/) for specifications of the parameters.
7625#[derive(Subcommand)]
7626pub enum BuildBackendCommand {
7627    /// PEP 517 hook `build_sdist`.
7628    BuildSdist { sdist_directory: PathBuf },
7629    /// PEP 517 hook `build_wheel`.
7630    BuildWheel {
7631        wheel_directory: PathBuf,
7632        #[arg(long)]
7633        metadata_directory: Option<PathBuf>,
7634    },
7635    /// PEP 660 hook `build_editable`.
7636    BuildEditable {
7637        wheel_directory: PathBuf,
7638        #[arg(long)]
7639        metadata_directory: Option<PathBuf>,
7640    },
7641    /// PEP 517 hook `get_requires_for_build_sdist`.
7642    GetRequiresForBuildSdist,
7643    /// PEP 517 hook `get_requires_for_build_wheel`.
7644    GetRequiresForBuildWheel,
7645    /// PEP 517 hook `prepare_metadata_for_build_wheel`.
7646    PrepareMetadataForBuildWheel { wheel_directory: PathBuf },
7647    /// PEP 660 hook `get_requires_for_build_editable`.
7648    GetRequiresForBuildEditable,
7649    /// PEP 660 hook `prepare_metadata_for_build_editable`.
7650    PrepareMetadataForBuildEditable { wheel_directory: PathBuf },
7651}
7652
7653#[cfg(test)]
7654mod tests {
7655    use clap::{CommandFactory, Parser};
7656
7657    use super::{AuthCommand, Cli, Commands};
7658
7659    #[test]
7660    fn auth_keyring_provider_hidden_from_help() {
7661        let mut command = Cli::command();
7662        let auth = command
7663            .find_subcommand_mut("auth")
7664            .expect("auth subcommand should exist");
7665
7666        let login_help = auth
7667            .find_subcommand_mut("login")
7668            .expect("auth login subcommand should exist")
7669            .render_help()
7670            .to_string();
7671        assert!(!login_help.contains("--keyring-provider"));
7672
7673        let logout_help = auth
7674            .find_subcommand_mut("logout")
7675            .expect("auth logout subcommand should exist")
7676            .render_help()
7677            .to_string();
7678        assert!(!logout_help.contains("--keyring-provider"));
7679
7680        let token_help = auth
7681            .find_subcommand_mut("token")
7682            .expect("auth token subcommand should exist")
7683            .render_help()
7684            .to_string();
7685        assert!(!token_help.contains("--keyring-provider"));
7686    }
7687
7688    #[test]
7689    fn auth_login_logout_still_accept_keyring_provider() {
7690        let login = Cli::try_parse_from([
7691            "uv",
7692            "auth",
7693            "login",
7694            "https://example.com",
7695            "--username",
7696            "user",
7697            "--password",
7698            "password",
7699            "--keyring-provider",
7700            "disabled",
7701        ])
7702        .expect("auth login should accept hidden keyring provider");
7703
7704        assert!(matches!(
7705            *login.command,
7706            Commands::Auth(ref auth)
7707                if matches!(auth.command, AuthCommand::Login(ref login) if login.keyring_provider.is_some())
7708        ));
7709
7710        let logout = Cli::try_parse_from([
7711            "uv",
7712            "auth",
7713            "logout",
7714            "https://example.com",
7715            "--keyring-provider",
7716            "disabled",
7717        ])
7718        .expect("auth logout should accept hidden keyring provider");
7719
7720        assert!(matches!(
7721            *logout.command,
7722            Commands::Auth(ref auth)
7723                if matches!(auth.command, AuthCommand::Logout(ref logout) if logout.keyring_provider.is_some())
7724        ));
7725    }
7726}