Skip to main content

uv_cli/
lib.rs

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