//! A shadow of `mise.usage.kdl` in argh's vocabulary, generated by
//! `cargo run -p xtask -- gen-shadow`.
//!
//! Do not edit: regenerate it. It exists to be compiled and parsed against, so
//! that the parser can be measured at a real CLI's scale rather than a toy one.
#![allow(dead_code, unused_imports)]

use argh::FromArgs;

/// initializes mise in the current shell session
#[derive(FromArgs)]
#[argh(subcommand, name = "activate")]
pub struct ActivateArgs {
    /// suppress non-error messages
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// shell type to generate the script for
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// do not automatically call hook-env
    #[argh(switch, long = "no-hook-env")]
    pub no_hook_env: bool,
    /// use shims instead of modifying PATH
    #[argh(switch, long = "shims")]
    pub shims: bool,
    /// show "mise: <TOOL>@<VERSION>" message when changing directories
    #[argh(switch, long = "status")]
    pub status: bool,
    /// shell type to generate the script for
    #[argh(positional)]
    pub shell_type: Option<String>,
}

/// show an alias for a tool
#[derive(FromArgs)]
#[argh(subcommand, name = "get")]
pub struct ToolAliasGetArgs {
    /// the tool to show the alias for
    #[argh(positional)]
    pub tool: String,
    /// the alias to show
    #[argh(positional)]
    pub alias: String,
}

/// list tool version aliases
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct ToolAliasLsArgs {
    /// don't show table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// show aliases for <TOOL>
    #[argh(positional)]
    pub tool: Option<String>,
}

/// add/update an alias for a tool/backend
#[derive(FromArgs)]
#[argh(subcommand, name = "set")]
pub struct ToolAliasSetArgs {
    /// the tool/backend to set the alias for
    #[argh(positional)]
    pub tool: String,
    /// the alias to set
    #[argh(positional)]
    pub alias: String,
    /// the value to set the alias to
    #[argh(positional)]
    pub value: Option<String>,
}

/// clears an alias for a tool/backend
#[derive(FromArgs)]
#[argh(subcommand, name = "unset")]
pub struct ToolAliasUnsetArgs {
    /// the tool/backend to remove the alias from
    #[argh(positional)]
    pub tool: String,
    /// the alias to remove
    #[argh(positional)]
    pub alias: Option<String>,
}

/// manage tool version aliases.
#[derive(FromArgs)]
#[argh(subcommand, name = "tool-alias")]
pub struct ToolAliasArgs {
    /// filter aliases by tool
    #[argh(option, long = "tool", short = 'p')]
    pub tool: Option<String>,
    /// don't show table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<ToolAliasCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum ToolAliasCommands {
    /// show an alias for a tool
    Get(ToolAliasGetArgs),
    /// list tool version aliases
    Ls(ToolAliasLsArgs),
    /// add/update an alias for a tool/backend
    Set(ToolAliasSetArgs),
    /// clears an alias for a tool/backend
    Unset(ToolAliasUnsetArgs),
}

/// internal] simulates asdf for plugins that call "asdf" internally
#[derive(FromArgs)]
#[argh(subcommand, name = "asdf")]
pub struct AsdfArgs {
    /// all arguments
    #[argh(positional)]
    pub args: Vec<String>,
}

/// list built-in backends
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct BackendsLsArgs {}

/// manage backends
#[derive(FromArgs)]
#[argh(subcommand, name = "backends")]
pub struct BackendsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<BackendsCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BackendsCommands {
    /// list built-in backends
    Ls(BackendsLsArgs),
}

/// list all the active runtime bin paths
#[derive(FromArgs)]
#[argh(subcommand, name = "bin-paths")]
pub struct BinPathsArgs {
    /// output executable names instead of bin directories
    #[argh(switch, long = "bin-names")]
    pub bin_names: bool,
    /// output executable entries in JSON format (implies --bin-names)
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// tool(s) to look up
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "__apply-account-plan")]
pub struct BootstrapApplyAccountPlanArgs {}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "__apply-service-plan")]
pub struct BootstrapApplyServicePlanArgs {}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "__apply-firewall-plan")]
pub struct BootstrapApplyFirewallPlanArgs {}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "__apply-system-plan")]
pub struct BootstrapApplySystemPlanArgs {}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "__inspect-system-files")]
pub struct BootstrapInspectSystemFilesArgs {}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "__inspect-firewall-plan")]
pub struct BootstrapInspectFirewallPlanArgs {}

/// apply configured Linux users and groups
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapAccountsApplyArgs {
    /// print what would change without changing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// show configured Linux user and group state
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapAccountsStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 when any account is not converged
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage Linux users and groups from `[bootstrap.users]` and `[bootstrap.groups]`
#[derive(FromArgs)]
#[argh(subcommand, name = "accounts")]
pub struct BootstrapAccountsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapAccountsCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapAccountsCommands {
    /// apply configured Linux users and groups
    Apply(BootstrapAccountsApplyArgs),
    /// show configured Linux user and group state
    Status(BootstrapAccountsStatusArgs),
}

/// apply configured Docker Compose project state
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapComposeApplyArgs {
    /// print what would change without changing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// show configured Docker Compose project state
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapComposeStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 when any Compose project is not converged
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage Docker Compose projects from `[bootstrap.compose]`
#[derive(FromArgs)]
#[argh(subcommand, name = "compose")]
pub struct BootstrapComposeArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapComposeCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapComposeCommands {
    /// apply configured Docker Compose project state
    Apply(BootstrapComposeApplyArgs),
    /// show configured Docker Compose project state
    Status(BootstrapComposeStatusArgs),
}

/// add or update dotfiles in `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "add")]
pub struct BootstrapDotfilesAddArgs {
    /// overwrite existing sources without prompting
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// write to the global config
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// write to the local config instead of the global config
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// dotfile mode to write
    #[argh(option, long = "mode", short = 'm')]
    pub mode: Option<String>,
    /// print the config/source updates without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// add the entry without applying it
    #[argh(switch, long = "no-apply")]
    pub no_apply: bool,
    /// write to this config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// source path to use for a single target
    #[argh(option, long = "source", short = 's')]
    pub source: Option<String>,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// targets to add or update
    #[argh(positional)]
    pub target: Vec<String>,
}

/// apply dotfiles from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapDotfilesApplyArgs {
    /// overwrite existing files that conflict with whole-file dotfile entries
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// print the actions that would run without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// only apply these targets
    #[argh(positional)]
    pub target: Vec<String>,
}

/// edit a managed dotfile source
#[derive(FromArgs)]
#[argh(subcommand, name = "edit")]
pub struct BootstrapDotfilesEditArgs {
    /// apply this target after the editor exits
    #[argh(switch, long = "apply")]
    pub apply: bool,
    /// dotfile mode to use if the target is not yet managed
    #[argh(option, long = "mode", short = 'm')]
    pub mode: Option<String>,
    /// source path to use if the target is not yet managed
    #[argh(option, long = "source", short = 's')]
    pub source: Option<String>,
    /// skip the confirmation prompt when adding an unmanaged target
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// target to edit
    #[argh(positional)]
    pub target: String,
}

/// show the status of dotfiles from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapDotfilesStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured dotfiles are not in their desired
    #[argh(switch, long = "missing")]
    pub missing: bool,
    /// only show these targets
    #[argh(positional)]
    pub target: Vec<String>,
}

/// remove dotfiles applied from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "unapply")]
pub struct BootstrapDotfilesUnapplyArgs {
    /// remove modified or otherwise ambiguous managed files and lines
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// print the actions that would run without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// only unapply these targets
    #[argh(positional)]
    pub target: Vec<String>,
}

/// manage dotfiles from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "dotfiles")]
pub struct BootstrapDotfilesArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapDotfilesCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapDotfilesCommands {
    /// add or update dotfiles in `[dotfiles]`
    Add(BootstrapDotfilesAddArgs),
    /// apply dotfiles from `[dotfiles]`
    Apply(BootstrapDotfilesApplyArgs),
    /// edit a managed dotfile source
    Edit(BootstrapDotfilesEditArgs),
    /// show the status of dotfiles from `[dotfiles]`
    Status(BootstrapDotfilesStatusArgs),
    /// remove dotfiles applied from `[dotfiles]`
    Unapply(BootstrapDotfilesUnapplyArgs),
}

/// apply configured privileged files and directories
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapFilesApplyArgs {
    /// print what would change without changing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// prompt securely for missing bootstrap secret inputs
    #[argh(switch, long = "prompt-secrets")]
    pub prompt_secrets: bool,
}

/// show configured privileged file and directory state
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapFilesStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 when any resource is not converged
    #[argh(switch, long = "missing")]
    pub missing: bool,
    /// prompt securely for missing bootstrap secret inputs
    #[argh(switch, long = "prompt-secrets")]
    pub prompt_secrets: bool,
}

/// manage privileged files and directories from `[bootstrap.files]` and `[bootstrap.directories]`
#[derive(FromArgs)]
#[argh(subcommand, name = "files")]
pub struct BootstrapFilesArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapFilesCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapFilesCommands {
    /// apply configured privileged files and directories
    Apply(BootstrapFilesApplyArgs),
    /// show configured privileged file and directory state
    Status(BootstrapFilesStatusArgs),
}

/// apply the configured Linux host firewall
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapFirewallApplyArgs {
    /// print what would change without changing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// show configured Linux host firewall state
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapFirewallStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 when the firewall is not converged
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage the Linux host firewall from `[bootstrap.linux.firewall]`
#[derive(FromArgs)]
#[argh(subcommand, name = "firewall")]
pub struct BootstrapFirewallArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapFirewallCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapFirewallCommands {
    /// apply the configured Linux host firewall
    Apply(BootstrapFirewallApplyArgs),
    /// show configured Linux host firewall state
    Status(BootstrapFirewallStatusArgs),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapLaunchdApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapLaunchdStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured LaunchAgent is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage macOS LaunchAgents from `[bootstrap.macos.launchd.agents]`
#[derive(FromArgs)]
#[argh(subcommand, name = "launchd")]
pub struct BootstrapLaunchdArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapLaunchdCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapLaunchdCommands {
    /// apply
    Apply(BootstrapLaunchdApplyArgs),
    /// status
    Status(BootstrapLaunchdStatusArgs),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapLinuxSystemdUnitsApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapLinuxSystemdUnitsStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured systemd user service is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage systemd user services from `[bootstrap.linux.systemd.units]`
#[derive(FromArgs)]
#[argh(subcommand, name = "systemd-units")]
pub struct BootstrapLinuxSystemdUnitsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapLinuxSystemdUnitsCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapLinuxSystemdUnitsCommands {
    /// apply
    Apply(BootstrapLinuxSystemdUnitsApplyArgs),
    /// status
    Status(BootstrapLinuxSystemdUnitsStatusArgs),
}

/// manage Linux bootstrap config from `[bootstrap.linux]`
#[derive(FromArgs)]
#[argh(subcommand, name = "linux")]
pub struct BootstrapLinuxArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapLinuxCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapLinuxCommands {
    /// manage systemd user services from `[bootstrap.linux.systemd.units]`
    SystemdUnits(BootstrapLinuxSystemdUnitsArgs),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapMacosDefaultsApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapMacosDefaultsStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured defaults are not in their desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage macOS defaults from `[bootstrap.macos.defaults]`
#[derive(FromArgs)]
#[argh(subcommand, name = "defaults")]
pub struct BootstrapMacosDefaultsArgs2 {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapMacosDefaultsCommands2,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapMacosDefaultsCommands2 {
    /// apply
    Apply(BootstrapMacosDefaultsApplyArgs),
    /// status
    Status(BootstrapMacosDefaultsStatusArgs),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapMacosLaunchdAgentsApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapMacosLaunchdAgentsStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured LaunchAgent is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage macOS LaunchAgents from `[bootstrap.macos.launchd.agents]`
#[derive(FromArgs)]
#[argh(subcommand, name = "launchd-agents")]
pub struct BootstrapMacosLaunchdAgentsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapMacosLaunchdAgentsCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapMacosLaunchdAgentsCommands {
    /// apply
    Apply(BootstrapMacosLaunchdAgentsApplyArgs),
    /// status
    Status(BootstrapMacosLaunchdAgentsStatusArgs),
}

/// manage macOS bootstrap config from `[bootstrap.macos]`
#[derive(FromArgs)]
#[argh(subcommand, name = "macos")]
pub struct BootstrapMacosArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapMacosCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapMacosCommands {
    /// manage macOS defaults from `[bootstrap.macos.defaults]`
    Defaults(BootstrapMacosDefaultsArgs2),
    /// manage macOS LaunchAgents from `[bootstrap.macos.launchd.agents]`
    LaunchdAgents(BootstrapMacosLaunchdAgentsArgs),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapMacosDefaultsApplyArgs2 {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapMacosDefaultsStatusArgs2 {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured defaults are not in their desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage macOS defaults from `[bootstrap.macos.defaults]`
#[derive(FromArgs)]
#[argh(subcommand, name = "macos-defaults")]
pub struct BootstrapMacosDefaultsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapMacosDefaultsCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapMacosDefaultsCommands {
    /// apply
    Apply(BootstrapMacosDefaultsApplyArgs2),
    /// status
    Status(BootstrapMacosDefaultsStatusArgs2),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapMiseShellActivateApplyArgs {
    /// print the actions that would run without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapMiseShellActivateStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured shell activation is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage mise shell activation from `[bootstrap.mise_shell_activate]`
#[derive(FromArgs)]
#[argh(subcommand, name = "mise-shell-activate")]
pub struct BootstrapMiseShellActivateArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapMiseShellActivateCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapMiseShellActivateCommands {
    /// apply
    Apply(BootstrapMiseShellActivateApplyArgs),
    /// status
    Status(BootstrapMiseShellActivateStatusArgs),
}

/// apply system packages from `[bootstrap.packages]`
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapPackagesApplyArgs {
    /// only install packages for this built-in or plugin manager
    #[argh(option, long = "manager", short = 'm')]
    pub manager: Option<String>,
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// refresh package manager metadata first (apk: `--update-cache`, apt: `apt-get update`)
    #[argh(switch, long = "update")]
    pub update: bool,
    /// packages in `manager:package` form; defaults to everything configured in [bootstrap.packages]
    #[argh(positional)]
    pub package: Vec<String>,
}

/// add a Homebrew tap URL to [bootstrap.brew.taps]
#[derive(FromArgs)]
#[argh(subcommand, name = "tap")]
pub struct BootstrapPackagesBrewTapArgs {
    /// write to the local config instead of the global config
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// print the config change without writing it
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// write to this config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// tap name, e.g. `owner/repo`
    #[argh(positional)]
    pub tap: String,
    /// gitHub URL for the tap. Defaults to https://github.com/<owner>/homebrew-<repo>.git
    #[argh(positional)]
    pub url: Option<String>,
}

/// remove Homebrew tap URLs from [bootstrap.brew.taps]
#[derive(FromArgs)]
#[argh(subcommand, name = "untap")]
pub struct BootstrapPackagesBrewUntapArgs {
    /// write to the local config instead of the global config
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// print the config change without writing it
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// write to this config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// tap name(s), e.g. `owner/repo`
    #[argh(positional)]
    pub taps: Vec<String>,
}

/// manage Homebrew taps used by bootstrap packages
#[derive(FromArgs)]
#[argh(subcommand, name = "brew")]
pub struct BootstrapPackagesBrewArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapPackagesBrewCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapPackagesBrewCommands {
    /// add a Homebrew tap URL to [bootstrap.brew.taps]
    Tap(BootstrapPackagesBrewTapArgs),
    /// remove Homebrew tap URLs from [bootstrap.brew.taps]
    Untap(BootstrapPackagesBrewUntapArgs),
}

/// import installed system packages into `[bootstrap.packages]`
#[derive(FromArgs)]
#[argh(subcommand, name = "import")]
pub struct BootstrapPackagesImportArgs {
    /// write to the config file for this environment (mise.<ENV>.toml)
    #[argh(option, long = "env", short = 'e')]
    pub env: Option<String>,
    /// write to the global config (~/.config/mise/config.toml)
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// only import packages for this manager. Currently only `brew` is supported.
    #[argh(option, long = "manager", short = 'm')]
    pub manager: Option<String>,
    /// import every linked formula, including dependencies
    #[argh(switch, long = "all")]
    pub all: bool,
    /// print the config change without writing config
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// write to this config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
}

/// prune installed system packages no longer declared in `[bootstrap.packages]`
#[derive(FromArgs)]
#[argh(subcommand, name = "prune")]
pub struct BootstrapPackagesPruneArgs {
    /// only prune packages for this manager
    #[argh(option, long = "manager", short = 'm')]
    pub manager: Option<String>,
    /// print what would be removed without deleting anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// show the status of system packages from `[bootstrap.packages]`
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapPackagesStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured packages are not in their desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// upgrade installed bootstrap packages from `[bootstrap.packages]`
#[derive(FromArgs)]
#[argh(subcommand, name = "upgrade")]
pub struct BootstrapPackagesUpgradeArgs {
    /// only upgrade packages for this built-in or plugin manager
    #[argh(option, long = "manager", short = 'm')]
    pub manager: Option<String>,
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// packages in `manager:package` form; defaults to everything configured in [bootstrap.packages]
    #[argh(positional)]
    pub package: Vec<String>,
}

/// add bootstrap packages to [bootstrap.packages] and install them
#[derive(FromArgs)]
#[argh(subcommand, name = "use")]
pub struct BootstrapPackagesUseArgs {
    /// write to the config file for this environment (mise.<ENV>.toml)
    #[argh(option, long = "env", short = 'e')]
    pub env: Option<String>,
    /// write to the global config (~/.config/mise/config.toml) instead of the local one
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// print the commands that would run without writing config or installing
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// write to this config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// packages in `manager:package[@version]` form
    #[argh(positional)]
    pub package: Vec<String>,
}

/// manage bootstrap system packages from `[bootstrap.packages]`
#[derive(FromArgs)]
#[argh(subcommand, name = "packages")]
pub struct BootstrapPackagesArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapPackagesCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapPackagesCommands {
    /// apply system packages from `[bootstrap.packages]`
    Apply(BootstrapPackagesApplyArgs),
    /// manage Homebrew taps used by bootstrap packages
    Brew(BootstrapPackagesBrewArgs),
    /// import installed system packages into `[bootstrap.packages]`
    Import(BootstrapPackagesImportArgs),
    /// prune installed system packages no longer declared in `[bootstrap.packages]`
    Prune(BootstrapPackagesPruneArgs),
    /// show the status of system packages from `[bootstrap.packages]`
    Status(BootstrapPackagesStatusArgs),
    /// upgrade installed bootstrap packages from `[bootstrap.packages]`
    Upgrade(BootstrapPackagesUpgradeArgs),
    /// add bootstrap packages to [bootstrap.packages] and install them
    Use(BootstrapPackagesUseArgs),
}

/// show the changes declarative bootstrap resources would make
#[derive(FromArgs)]
#[argh(subcommand, name = "plan")]
pub struct BootstrapPlanArgs {
    /// output a stable machine-readable plan in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit 2 when the plan contains changes, 0 when unchanged, and 1 on errors
    #[argh(switch, long = "detailed-exitcode")]
    pub detailed_exitcode: bool,
    /// prompt securely for missing bootstrap secret inputs
    #[argh(switch, long = "prompt-secrets")]
    pub prompt_secrets: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapPluginsApplyArgs {
    /// print what would happen without installing plugins
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapPluginsStatusArgs {
    /// exit with code 1 if a declared plugin is missing
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage package manager plugins declared in `[bootstrap.plugins]`
#[derive(FromArgs)]
#[argh(subcommand, name = "plugins")]
pub struct BootstrapPluginsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapPluginsCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapPluginsCommands {
    /// apply
    Apply(BootstrapPluginsApplyArgs),
    /// status
    Status(BootstrapPluginsStatusArgs),
}

/// bootstrap one or more machines over OpenSSH
#[derive(FromArgs)]
#[argh(subcommand, name = "remote")]
pub struct BootstrapRemoteArgs {
    /// select every configured inventory host
    #[argh(switch, long = "all")]
    pub all: bool,
    /// explicit remote shell command that installs mise and places it on PATH
    #[argh(option, long = "bootstrap-command")]
    pub bootstrap_command: Option<String>,
    /// sSH connection timeout in seconds
    #[argh(option, long = "connect-timeout")]
    pub connect_timeout: Option<String>,
    /// dereference one source-relative symbolic link; repeat for multiple links
    #[argh(option, long = "copy-link")]
    pub copy_link: Vec<String>,
    /// dereference every symbolic link in the source archive
    #[argh(switch, long = "copy-links")]
    pub copy_links: bool,
    /// additional archive pattern to exclude; repeat for multiple patterns
    #[argh(option, long = "exclude")]
    pub exclude: Vec<String>,
    /// stop after the first failed target
    #[argh(switch, long = "fail-fast")]
    pub fail_fast: bool,
    /// allow remote dotfile conflicts to be replaced
    #[argh(switch, long = "force-dotfiles")]
    pub force_dotfiles: bool,
    /// ad-hoc SSH destination (`[user@]host`); repeat for multiple hosts
    #[argh(option, long = "host")]
    pub host: Vec<String>,
    /// sSH identity file override
    #[argh(option, long = "identity-file", short = 'i')]
    pub identity_file: Option<String>,
    /// print the remote bootstrap changes without applying them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// keep the remote staging directory for debugging
    #[argh(switch, long = "keep-staging")]
    pub keep_staging: bool,
    /// local mise binary to upload (escape hatch for custom architectures)
    #[argh(option, long = "mise-bin")]
    pub mise_bin: Option<String>,
    /// run only one or more remote bootstrap parts
    #[argh(option, long = "only")]
    pub only: Vec<String>,
    /// sSH port override
    #[argh(option, long = "port")]
    pub port: Option<String>,
    /// prompt securely for missing secret inputs on the remote host
    #[argh(switch, long = "prompt-secrets")]
    pub prompt_secrets: bool,
    /// config environments to load on the remote host; repeat or delimit with commas (for example, ci,dotfiles)
    #[argh(option, long = "remote-env")]
    pub remote_env: Vec<String>,
    /// existing mise executable name or path; relative paths use the staged project
    #[argh(option, long = "remote-mise")]
    pub remote_mise: Option<String>,
    /// skip one or more remote bootstrap parts
    #[argh(option, long = "skip")]
    pub skip: Vec<String>,
    /// local directory archived and sent to each target
    #[argh(option, long = "source")]
    pub source: Option<String>,
    /// openSSH `-o` option; repeat for multiple options
    #[argh(option, long = "ssh-option")]
    pub ssh_option: Vec<String>,
    /// select configured hosts with this tag; repeat to match any tag
    #[argh(option, long = "tag")]
    pub tag: Vec<String>,
    /// refresh package manager metadata and update configured repos remotely
    #[argh(switch, long = "update")]
    pub update: bool,
    /// skip remote confirmation prompts
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// inventory host names from `[bootstrap.remote.hosts]`
    #[argh(positional)]
    pub target: Vec<String>,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapReposApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "exec")]
pub struct BootstrapReposExecArgs {
    /// continue running in other repos after a command fails
    #[argh(switch, long = "continue-on-error", short = 'c')]
    pub continue_on_error: bool,
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// run only in matching configured or expanded paths
    #[argh(positional)]
    pub path: String,
    /// command and arguments to run in each repo
    #[argh(positional)]
    pub command: Vec<String>,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapReposStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured repo is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "update")]
pub struct BootstrapReposUpdateArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// update only matching configured or expanded paths
    #[argh(positional)]
    pub path: Vec<String>,
}

/// manage git repo checkouts from `[bootstrap.repos]`
#[derive(FromArgs)]
#[argh(subcommand, name = "repos")]
pub struct BootstrapReposArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapReposCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapReposCommands {
    /// apply
    Apply(BootstrapReposApplyArgs),
    /// exec
    Exec(BootstrapReposExecArgs),
    /// status
    Status(BootstrapReposStatusArgs),
    /// update
    Update(BootstrapReposUpdateArgs),
}

/// show whether declared bootstrap secret inputs are available
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapSecretsStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if a declared secret input is unavailable
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// inspect bootstrap secret inputs without revealing their values
#[derive(FromArgs)]
#[argh(subcommand, name = "secrets")]
pub struct BootstrapSecretsArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapSecretsCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapSecretsCommands {
    /// show whether declared bootstrap secret inputs are available
    Status(BootstrapSecretsStatusArgs),
}

/// apply configured Linux system service state
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapServicesApplyArgs {
    /// print what would change without changing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// show configured Linux system service state
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapServicesStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 when any service is not converged
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage Linux system services from `[bootstrap.services]`
#[derive(FromArgs)]
#[argh(subcommand, name = "services")]
pub struct BootstrapServicesArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapServicesCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapServicesCommands {
    /// apply configured Linux system service state
    Apply(BootstrapServicesApplyArgs),
    /// show configured Linux system service state
    Status(BootstrapServicesStatusArgs),
}

/// show the aggregate bootstrap status
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured bootstrap state is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
    /// prompt securely for missing bootstrap secret inputs
    #[argh(switch, long = "prompt-secrets")]
    pub prompt_secrets: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapSystemdApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapSystemdStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured systemd user service is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage systemd user services from `[bootstrap.linux.systemd.units]`
#[derive(FromArgs)]
#[argh(subcommand, name = "systemd")]
pub struct BootstrapSystemdArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapSystemdCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapSystemdCommands {
    /// apply
    Apply(BootstrapSystemdApplyArgs),
    /// status
    Status(BootstrapSystemdStatusArgs),
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct BootstrapUserApplyArgs {
    /// print the commands that would run without running them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
}

/// mise
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct BootstrapUserStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured user setting is not in its desired state
    #[argh(switch, long = "missing")]
    pub missing: bool,
}

/// manage current-user bootstrap settings from `[bootstrap.user]`
#[derive(FromArgs)]
#[argh(subcommand, name = "user")]
pub struct BootstrapUserArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: BootstrapUserCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapUserCommands {
    /// apply
    Apply(BootstrapUserApplyArgs),
    /// status
    Status(BootstrapUserStatusArgs),
}

/// set up a machine for the current config in one command
#[derive(FromArgs)]
#[argh(subcommand, name = "bootstrap")]
pub struct BootstrapArgs {
    /// print what would happen without installing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip confirmation prompts
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// overwrite existing files that conflict with whole-file dotfile entries
    #[argh(switch, long = "force-dotfiles")]
    pub force_dotfiles: bool,
    /// run only one or more bootstrap parts
    #[argh(option, long = "only")]
    pub only: Vec<String>,
    /// prompt securely for missing bootstrap secret inputs
    #[argh(switch, long = "prompt-secrets")]
    pub prompt_secrets: bool,
    /// skip one or more bootstrap parts
    #[argh(option, long = "skip")]
    pub skip: Vec<String>,
    /// refresh package manager metadata and update configured repos
    #[argh(switch, long = "update")]
    pub update: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<BootstrapCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum BootstrapCommands {
    /// apply-account-plan
    ApplyAccountPlan(BootstrapApplyAccountPlanArgs),
    /// apply-service-plan
    ApplyServicePlan(BootstrapApplyServicePlanArgs),
    /// apply-firewall-plan
    ApplyFirewallPlan(BootstrapApplyFirewallPlanArgs),
    /// apply-system-plan
    ApplySystemPlan(BootstrapApplySystemPlanArgs),
    /// inspect-system-files
    InspectSystemFiles(BootstrapInspectSystemFilesArgs),
    /// inspect-firewall-plan
    InspectFirewallPlan(BootstrapInspectFirewallPlanArgs),
    /// manage Linux users and groups from `[bootstrap.users]` and `[bootstrap.groups]`
    Accounts(BootstrapAccountsArgs),
    /// manage Docker Compose projects from `[bootstrap.compose]`
    Compose(BootstrapComposeArgs),
    /// manage dotfiles from `[dotfiles]`
    Dotfiles(BootstrapDotfilesArgs),
    /// manage privileged files and directories from `[bootstrap.files]` and `[bootstrap.directories]`
    Files(BootstrapFilesArgs),
    /// manage the Linux host firewall from `[bootstrap.linux.firewall]`
    Firewall(BootstrapFirewallArgs),
    /// manage macOS LaunchAgents from `[bootstrap.macos.launchd.agents]`
    Launchd(BootstrapLaunchdArgs),
    /// manage Linux bootstrap config from `[bootstrap.linux]`
    Linux(BootstrapLinuxArgs),
    /// manage macOS bootstrap config from `[bootstrap.macos]`
    Macos(BootstrapMacosArgs),
    /// manage macOS defaults from `[bootstrap.macos.defaults]`
    MacosDefaults(BootstrapMacosDefaultsArgs),
    /// manage mise shell activation from `[bootstrap.mise_shell_activate]`
    MiseShellActivate(BootstrapMiseShellActivateArgs),
    /// manage bootstrap system packages from `[bootstrap.packages]`
    Packages(BootstrapPackagesArgs),
    /// show the changes declarative bootstrap resources would make
    Plan(BootstrapPlanArgs),
    /// manage package manager plugins declared in `[bootstrap.plugins]`
    Plugins(BootstrapPluginsArgs),
    /// bootstrap one or more machines over OpenSSH
    Remote(BootstrapRemoteArgs),
    /// manage git repo checkouts from `[bootstrap.repos]`
    Repos(BootstrapReposArgs),
    /// inspect bootstrap secret inputs without revealing their values
    Secrets(BootstrapSecretsArgs),
    /// manage Linux system services from `[bootstrap.services]`
    Services(BootstrapServicesArgs),
    /// show the aggregate bootstrap status
    Status(BootstrapStatusArgs),
    /// manage systemd user services from `[bootstrap.linux.systemd.units]`
    Systemd(BootstrapSystemdArgs),
    /// manage current-user bootstrap settings from `[bootstrap.user]`
    User(BootstrapUserArgs),
}

/// deletes all cache files in mise
#[derive(FromArgs)]
#[argh(subcommand, name = "clear")]
pub struct CacheClearArgs {
    /// mark all cache files as old
    #[argh(switch, long = "outdate")]
    pub outdate: bool,
    /// clear output cache entries for a task name or pattern
    #[argh(option, long = "task")]
    pub task: Option<String>,
    /// tool(s) to clear cache for e.g.: node, python
    #[argh(positional)]
    pub tool: Vec<String>,
}

/// show the cache directory path
#[derive(FromArgs)]
#[argh(subcommand, name = "path")]
pub struct CachePathArgs {}

/// removes stale mise cache files
#[derive(FromArgs)]
#[argh(subcommand, name = "prune")]
pub struct CachePruneArgs {
    /// show pruned files
    #[argh(switch, long = "verbose", short = 'v')]
    pub verbose: u8,
    /// just show what would be pruned
    #[argh(switch, long = "dry-run")]
    pub dry_run: bool,
    /// tool(s) to prune cache for e.g.: node, python
    #[argh(positional)]
    pub tool: Vec<String>,
}

/// inspect output cache entries for a task
#[derive(FromArgs)]
#[argh(subcommand, name = "task")]
pub struct CacheTaskArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// task name or pattern to inspect
    #[argh(positional)]
    pub task: String,
}

/// manage the mise cache
#[derive(FromArgs)]
#[argh(subcommand, name = "cache")]
pub struct CacheArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<CacheCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum CacheCommands {
    /// deletes all cache files in mise
    Clear(CacheClearArgs),
    /// show the cache directory path
    Path(CachePathArgs),
    /// removes stale mise cache files
    Prune(CachePruneArgs),
    /// inspect output cache entries for a task
    Task(CacheTaskArgs),
}

/// generate shell completions
#[derive(FromArgs)]
#[argh(subcommand, name = "completion")]
pub struct CompletionArgs {
    /// shell type to generate completions for
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// include the bash completion library in the bash completion script
    #[argh(switch, long = "include-bash-completion-lib")]
    pub include_bash_completion_lib: bool,
    /// always use usage for completions.
    #[argh(switch, long = "usage")]
    pub usage: bool,
    /// shell type to generate completions for
    #[argh(positional)]
    pub shell_2: Option<String>,
}

/// display the value of a setting in a mise.toml file
#[derive(FromArgs)]
#[argh(subcommand, name = "get")]
pub struct ConfigGetArgs {
    /// the path to the mise.toml file to read
    #[argh(option, long = "file", short = 'f')]
    pub file: Option<String>,
    /// the path of the config to display
    #[argh(positional)]
    pub key: Option<String>,
}

/// list config files currently in use
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct ConfigLsArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// do not print table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// list all tracked config files
    #[argh(switch, long = "tracked-configs")]
    pub tracked_configs: bool,
}

/// set the value of a setting in a mise.toml file
#[derive(FromArgs)]
#[argh(subcommand, name = "set")]
pub struct ConfigSetArgs {
    /// the path to the mise.toml file to edit
    #[argh(option, long = "file", short = 'f')]
    pub file: Option<String>,
    /// type_
    #[argh(option, long = "type", short = 't')]
    pub type_: Option<String>,
    /// the path of the config to display
    #[argh(positional)]
    pub key: String,
    /// the value to set the key to (optional if provided as KEY=VALUE)
    #[argh(positional)]
    pub value: Option<String>,
}

/// manage config files
#[derive(FromArgs)]
#[argh(subcommand, name = "config")]
pub struct ConfigArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// do not print table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// list all tracked config files
    #[argh(switch, long = "tracked-configs")]
    pub tracked_configs: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<ConfigCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum ConfigCommands {
    /// display the value of a setting in a mise.toml file
    Get(ConfigGetArgs),
    /// list config files currently in use
    Ls(ConfigLsArgs),
    /// set the value of a setting in a mise.toml file
    Set(ConfigSetArgs),
}

/// shows current active and installed runtime versions
#[derive(FromArgs)]
#[argh(subcommand, name = "current")]
pub struct CurrentArgs {
    /// plugin to show versions of e.g.: ruby, node, cargo:eza, npm:prettier, etc.
    #[argh(positional)]
    pub plugin: Option<String>,
}

/// disable mise for current shell session
#[derive(FromArgs)]
#[argh(subcommand, name = "deactivate")]
pub struct DeactivateArgs {}

/// output direnv function to use mise inside direnv
#[derive(FromArgs)]
#[argh(subcommand, name = "activate")]
pub struct DirenvActivateArgs {}

/// internal] This is an internal command that writes an envrc file
#[derive(FromArgs)]
#[argh(subcommand, name = "envrc")]
pub struct DirenvEnvrcArgs {}

/// internal] This is an internal command that writes an envrc file
#[derive(FromArgs)]
#[argh(subcommand, name = "exec")]
pub struct DirenvExecArgs {}

/// output direnv function to use mise inside direnv
#[derive(FromArgs)]
#[argh(subcommand, name = "direnv")]
pub struct DirenvArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<DirenvCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum DirenvCommands {
    /// output direnv function to use mise inside direnv
    Activate(DirenvActivateArgs),
    /// internal] This is an internal command that writes an envrc file
    Envrc(DirenvEnvrcArgs),
    /// internal] This is an internal command that writes an envrc file
    Exec(DirenvExecArgs),
}

/// add or update dotfiles in `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "add")]
pub struct DotfilesAddArgs {
    /// overwrite existing sources without prompting
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// write to the global config
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// write to the local config instead of the global config
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// dotfile mode to write
    #[argh(option, long = "mode", short = 'm')]
    pub mode: Option<String>,
    /// print the config/source updates without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// add the entry without applying it
    #[argh(switch, long = "no-apply")]
    pub no_apply: bool,
    /// write to this config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// source path to use for a single target
    #[argh(option, long = "source", short = 's')]
    pub source: Option<String>,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// targets to add or update
    #[argh(positional)]
    pub target: Vec<String>,
}

/// apply dotfiles from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "apply")]
pub struct DotfilesApplyArgs {
    /// overwrite existing files that conflict with whole-file dotfile entries
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// print the actions that would run without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// only apply these targets
    #[argh(positional)]
    pub target: Vec<String>,
}

/// edit a managed dotfile source
#[derive(FromArgs)]
#[argh(subcommand, name = "edit")]
pub struct DotfilesEditArgs {
    /// apply this target after the editor exits
    #[argh(switch, long = "apply")]
    pub apply: bool,
    /// dotfile mode to use if the target is not yet managed
    #[argh(option, long = "mode", short = 'm')]
    pub mode: Option<String>,
    /// source path to use if the target is not yet managed
    #[argh(option, long = "source", short = 's')]
    pub source: Option<String>,
    /// skip the confirmation prompt when adding an unmanaged target
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// target to edit
    #[argh(positional)]
    pub target: String,
}

/// show the status of dotfiles from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "status")]
pub struct DotfilesStatusArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// exit with code 1 if any configured dotfiles are not in their desired
    #[argh(switch, long = "missing")]
    pub missing: bool,
    /// only show these targets
    #[argh(positional)]
    pub target: Vec<String>,
}

/// remove dotfiles applied from `[dotfiles]`
#[derive(FromArgs)]
#[argh(subcommand, name = "unapply")]
pub struct DotfilesUnapplyArgs {
    /// remove modified or otherwise ambiguous managed files and lines
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// print the actions that would run without writing anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// skip the confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// only unapply these targets
    #[argh(positional)]
    pub target: Vec<String>,
}

/// manage dotfiles from `[dotfiles]` (deprecated)
#[derive(FromArgs)]
#[argh(subcommand, name = "dotfiles")]
pub struct DotfilesArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: DotfilesCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum DotfilesCommands {
    /// add or update dotfiles in `[dotfiles]`
    Add(DotfilesAddArgs),
    /// apply dotfiles from `[dotfiles]`
    Apply(DotfilesApplyArgs),
    /// edit a managed dotfile source
    Edit(DotfilesEditArgs),
    /// show the status of dotfiles from `[dotfiles]`
    Status(DotfilesStatusArgs),
    /// remove dotfiles applied from `[dotfiles]`
    Unapply(DotfilesUnapplyArgs),
}

/// print the current PATH entries mise is providing
#[derive(FromArgs)]
#[argh(subcommand, name = "path")]
pub struct DoctorPathArgs {
    /// print all entries including those not provided by mise
    #[argh(switch, long = "full", short = 'f')]
    pub full: bool,
}

/// check mise installation for possible problems
#[derive(FromArgs)]
#[argh(subcommand, name = "doctor")]
pub struct DoctorArgs {
    /// json
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<DoctorCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum DoctorCommands {
    /// print the current PATH entries mise is providing
    Path(DoctorPathArgs),
}

/// starts a new shell with the mise environment built from the current configuration
#[derive(FromArgs)]
#[argh(subcommand, name = "en")]
pub struct EnArgs {
    /// shell to start
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// directory to start the shell in
    #[argh(positional)]
    pub dir: Option<String>,
}

/// exports env vars to activate mise a single time
#[derive(FromArgs)]
#[argh(subcommand, name = "env")]
pub struct EnvArgs {
    /// output in dotenv format
    #[argh(switch, long = "dotenv", short = 'D')]
    pub dotenv: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// shell type to generate environment variables for
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// output in JSON format with additional information (source, tool)
    #[argh(switch, long = "json-extended")]
    pub json_extended: bool,
    /// only show redacted environment variables
    #[argh(switch, long = "redacted")]
    pub redacted: bool,
    /// only show values of environment variables
    #[argh(switch, long = "values")]
    pub values: bool,
    /// tool(s) to use
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// execute a command with tool(s) set
#[derive(FromArgs)]
#[argh(subcommand, name = "exec")]
pub struct ExecArgs {
    /// command string to execute
    #[argh(option, long = "command", short = 'c')]
    pub command: Option<String>,
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// allow specific env var through (implies --deny-env for everything else)
    #[argh(option, long = "allow-env")]
    pub allow_env: Vec<String>,
    /// allow network to specific host (implies --deny-net for everything else)
    #[argh(option, long = "allow-net")]
    pub allow_net: Vec<String>,
    /// allow reads from specific path (implies --deny-read for everything else)
    #[argh(option, long = "allow-read")]
    pub allow_read: Vec<String>,
    /// allow writes to specific path (implies --deny-write for everything else)
    #[argh(option, long = "allow-write")]
    pub allow_write: Vec<String>,
    /// block reads, writes, network, and env vars
    #[argh(switch, long = "deny-all")]
    pub deny_all: bool,
    /// block env var inheritance (only PATH, HOME, USER, SHELL, TERM, LANG pass through)
    #[argh(switch, long = "deny-env")]
    pub deny_env: bool,
    /// block all network access
    #[argh(switch, long = "deny-net")]
    pub deny_net: bool,
    /// block filesystem reads (system libs and tool dirs still accessible)
    #[argh(switch, long = "deny-read")]
    pub deny_read: bool,
    /// block all filesystem writes
    #[argh(switch, long = "deny-write")]
    pub deny_write: bool,
    /// bypass the environment cache and recompute the environment
    #[argh(switch, long = "fresh-env")]
    pub fresh_env: bool,
    /// skip automatic dependency preparation
    #[argh(switch, long = "no-deps")]
    pub no_deps: bool,
    /// connect backend install command stdin/stdout/stderr directly to the terminal Implies --jobs=1
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// tool(s) to start e.g.: node@20 python@3.10
    #[argh(positional)]
    pub tool_version: String,
    /// command string to execute (same as --command)
    #[argh(positional)]
    pub command_2: Vec<String>,
}

/// formats mise.toml
#[derive(FromArgs)]
#[argh(subcommand, name = "fmt")]
pub struct FmtArgs {
    /// format all files from the current directory
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// check if the configs are formatted, no formatting is done
    #[argh(switch, long = "check", short = 'c')]
    pub check: bool,
    /// read config from stdin and write its formatted version into stdout
    #[argh(switch, long = "stdin", short = 's')]
    pub stdin: bool,
}

/// generate a script to download+execute mise
#[derive(FromArgs)]
#[argh(subcommand, name = "bootstrap")]
pub struct GenerateBootstrapArgs {
    /// sandboxes mise internal directories like MISE_DATA_DIR and MISE_CACHE_DIR into a `.mise` directory in the project
    #[argh(switch, long = "localize", short = 'l')]
    pub localize: bool,
    /// specify mise version to fetch
    #[argh(option, long = "version", short = 'V')]
    pub version: Option<String>,
    /// instead of outputting the script to stdout, write to a file and make it executable
    #[argh(option, long = "write", short = 'w')]
    pub write: Option<String>,
    /// directory to put localized data into
    #[argh(option, long = "localized-dir")]
    pub localized_dir: Option<String>,
    /// also write a Windows launcher, `<WRITE>.cmd`
    #[argh(switch, long = "windows")]
    pub windows: bool,
}

/// generate a mise.toml file
#[derive(FromArgs)]
#[argh(subcommand, name = "config")]
pub struct GenerateConfigArgs {
    /// generate the global config file (~/.config/mise/config.toml)
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// show what would be generated without writing to file
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// path to a .tool-versions file to import tools from
    #[argh(option, long = "tool-versions", short = 't')]
    pub tool_versions: Option<String>,
    /// path to the config file to create
    #[argh(positional)]
    pub path: Option<String>,
}

/// generate a devcontainer to execute mise
#[derive(FromArgs)]
#[argh(subcommand, name = "devcontainer")]
pub struct GenerateDevcontainerArgs {
    /// the image to use for the devcontainer
    #[argh(option, long = "image", short = 'i')]
    pub image: Option<String>,
    /// bind the mise-data-volume to the devcontainer
    #[argh(switch, long = "mount-mise-data", short = 'm')]
    pub mount_mise_data: bool,
    /// the name of the devcontainer
    #[argh(option, long = "name", short = 'n')]
    pub name: Option<String>,
    /// write to .devcontainer/devcontainer.json
    #[argh(switch, long = "write", short = 'w')]
    pub write: bool,
}

/// generate a git pre-commit hook
#[derive(FromArgs)]
#[argh(subcommand, name = "git-pre-commit")]
pub struct GenerateGitPreCommitArgs {
    /// the task to run when the pre-commit hook is triggered
    #[argh(option, long = "task", short = 't')]
    pub task: Option<String>,
    /// write to .git/hooks/pre-commit and make it executable
    #[argh(switch, long = "write", short = 'w')]
    pub write: bool,
    /// which hook to generate (saves to .git/hooks/$hook)
    #[argh(option, long = "hook")]
    pub hook: Option<String>,
    /// mise flags to embed in the generated hook, given after `--`
    #[argh(positional)]
    pub mise_arg: Vec<String>,
}

/// generate a GitHub Action workflow file
#[derive(FromArgs)]
#[argh(subcommand, name = "github-action")]
pub struct GenerateGithubActionArgs {
    /// the task to run when the workflow is triggered
    #[argh(option, long = "task", short = 't')]
    pub task: Option<String>,
    /// write to .github/workflows/$name.yml
    #[argh(switch, long = "write", short = 'w')]
    pub write: bool,
    /// the name of the workflow to generate
    #[argh(option, long = "name")]
    pub name: Option<String>,
}

/// generate documentation for tasks in a project
#[derive(FromArgs)]
#[argh(subcommand, name = "task-docs")]
pub struct GenerateTaskDocsArgs {
    /// inserts the documentation into an existing file
    #[argh(switch, long = "inject", short = 'i')]
    pub inject: bool,
    /// write only an index of tasks, intended for use with `--multi`
    #[argh(switch, long = "index", short = 'I')]
    pub index: bool,
    /// render each task as a separate document, requires `--output` to be a directory
    #[argh(switch, long = "multi", short = 'm')]
    pub multi: bool,
    /// writes the generated docs to a file/directory
    #[argh(option, long = "output", short = 'o')]
    pub output: Option<String>,
    /// root directory to search for tasks
    #[argh(option, long = "root", short = 'r')]
    pub root: Option<String>,
    /// style
    #[argh(option, long = "style", short = 's')]
    pub style: Option<String>,
}

/// generates shims to run mise tasks
#[derive(FromArgs)]
#[argh(subcommand, name = "task-stubs")]
pub struct GenerateTaskStubsArgs {
    /// directory to create task stubs inside of
    #[argh(option, long = "dir", short = 'd')]
    pub dir: Option<String>,
    /// path to a mise bin to use when running the task stub.
    #[argh(option, long = "mise-bin", short = 'm')]
    pub mise_bin: Option<String>,
}

/// generate a tool stub for HTTP-based tools
#[derive(FromArgs)]
#[argh(subcommand, name = "tool-stub")]
pub struct GenerateToolStubArgs {
    /// binary path within the extracted archive
    #[argh(option, long = "bin", short = 'b')]
    pub bin: Option<String>,
    /// wrap stub in a bootstrap script that installs mise if not already present
    #[argh(switch, long = "bootstrap")]
    pub bootstrap: bool,
    /// specify mise version for the bootstrap script
    #[argh(option, long = "bootstrap-version")]
    pub bootstrap_version: Option<String>,
    /// checksum algorithm to use when downloading artifacts
    #[argh(option, long = "checksum-algorithm")]
    pub checksum_algorithm: Option<String>,
    /// fetch checksums and sizes for an existing tool stub file
    #[argh(switch, long = "fetch")]
    pub fetch: bool,
    /// hTTP backend type to use
    #[argh(option, long = "http")]
    pub http: Option<String>,
    /// resolve and embed lockfile data (exact version + platform URLs/checksums) into an existing stub file for reproducible installs without runtime API calls
    #[argh(switch, long = "lock")]
    pub lock: bool,
    /// platform-specific binary paths in the format platform:path
    #[argh(option, long = "platform-bin")]
    pub platform_bin: Vec<String>,
    /// platform-specific URLs in the format platform:url or just url (auto-detect platform)
    #[argh(option, long = "platform-url")]
    pub platform_url: Vec<String>,
    /// skip downloading for checksum and binary path detection (faster but less informative)
    #[argh(switch, long = "skip-download")]
    pub skip_download: bool,
    /// uRL for downloading the tool
    #[argh(option, long = "url", short = 'u')]
    pub url: Option<String>,
    /// version of the tool
    #[argh(option, long = "version")]
    pub version: Option<String>,
    /// output file path for the tool stub
    #[argh(positional)]
    pub output: String,
}

/// generate files for various tools/services
#[derive(FromArgs)]
#[argh(subcommand, name = "generate")]
pub struct GenerateArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: GenerateCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum GenerateCommands {
    /// generate a script to download+execute mise
    Bootstrap(GenerateBootstrapArgs),
    /// generate a mise.toml file
    Config(GenerateConfigArgs),
    /// generate a devcontainer to execute mise
    Devcontainer(GenerateDevcontainerArgs),
    /// generate a git pre-commit hook
    GitPreCommit(GenerateGitPreCommitArgs),
    /// generate a GitHub Action workflow file
    GithubAction(GenerateGithubActionArgs),
    /// generate documentation for tasks in a project
    TaskDocs(GenerateTaskDocsArgs),
    /// generates shims to run mise tasks
    TaskStubs(GenerateTaskStubsArgs),
    /// generate a tool stub for HTTP-based tools
    ToolStub(GenerateToolStubArgs),
}

/// display the GitHub token mise will use for a given host
#[derive(FromArgs)]
#[argh(subcommand, name = "token")]
pub struct GithubTokenArgs {
    /// force native GitHub OAuth device flow instead of normal token resolution
    #[argh(switch, long = "oauth")]
    pub oauth: bool,
    /// print only the token value
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// mint a fresh OAuth token even if the cached one has not expired, via the refresh-token grant or a new device-code flow
    #[argh(switch, long = "refresh")]
    pub refresh: bool,
    /// show the full unmasked token
    #[argh(switch, long = "unmask")]
    pub unmask: bool,
    /// gitHub hostname
    #[argh(positional)]
    pub host: Option<String>,
}

/// gitHub related commands
#[derive(FromArgs)]
#[argh(subcommand, name = "github")]
pub struct GithubArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: GithubCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum GithubCommands {
    /// display the GitHub token mise will use for a given host
    Token(GithubTokenArgs),
}

/// sets/gets the global tool version(s)
#[derive(FromArgs)]
#[argh(subcommand, name = "global")]
pub struct GlobalArgs {
    /// save fuzzy version to `~/.tool-versions`
    #[argh(switch, long = "fuzzy")]
    pub fuzzy: bool,
    /// get the path of the global config file
    #[argh(switch, long = "path")]
    pub path: bool,
    /// save exact version to `~/.tool-versions`
    #[argh(switch, long = "pin")]
    pub pin: bool,
    /// remove the tool(s) from ~/.tool-versions
    #[argh(option, long = "remove")]
    pub remove: Vec<String>,
    /// tool(s) to add to .tool-versions
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// internal] called by activate hook to update env vars directory change
#[derive(FromArgs)]
#[argh(subcommand, name = "hook-env")]
pub struct HookEnvArgs {
    /// skip early exit check
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// hide warnings such as when a tool is not installed
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// shell type to generate script for
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// reason for calling hook-env (e.g., "precmd", "chpwd")
    #[argh(option, long = "reason")]
    pub reason: Option<String>,
    /// show "mise: <TOOL>@<VERSION>" message when changing directories
    #[argh(switch, long = "status")]
    pub status: bool,
}

/// internal] called by shell when a command is not found
#[derive(FromArgs)]
#[argh(subcommand, name = "hook-not-found")]
pub struct HookNotFoundArgs {
    /// shell type to generate script for
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// attempted bin to run
    #[argh(positional)]
    pub bin: String,
}

/// removes mise CLI and all related data
#[derive(FromArgs)]
#[argh(subcommand, name = "implode")]
pub struct ImplodeArgs {
    /// list directories that would be removed without actually removing them
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// also remove config directory
    #[argh(switch, long = "config")]
    pub config: bool,
}

/// edit mise.toml interactively
#[derive(FromArgs)]
#[argh(subcommand, name = "edit")]
pub struct EditArgs {
    /// edit the global config file (~/.config/mise/config.toml)
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// show what would be generated without writing to file
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// path to a .tool-versions file to import tools from
    #[argh(option, long = "tool-versions", short = 't')]
    pub tool_versions: Option<String>,
    /// path to the config file to create
    #[argh(positional)]
    pub path: Option<String>,
}

/// install a tool version
#[derive(FromArgs)]
#[argh(subcommand, name = "install")]
pub struct InstallArgs {
    /// force reinstall even if already installed
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// show what would be installed without actually installing
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// show installation output
    #[argh(switch, long = "verbose", short = 'v')]
    pub verbose: u8,
    /// like --dry-run but exits with code 1 if there are tools to install
    #[argh(switch, long = "dry-run-code")]
    pub dry_run_code: bool,
    /// also install tools required by tasks in the current scope
    #[argh(switch, long = "include-task-tools")]
    pub include_task_tools: bool,
    /// only install versions released before this date or older than this duration
    #[argh(option, long = "minimum-release-age")]
    pub minimum_release_age: Option<String>,
    /// install tools from every [monorepo].config_roots config root
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// connect backend install command stdin/stdout/stderr directly to the terminal Implies --jobs=1
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// install tool(s) to a shared directory
    #[argh(option, long = "shared")]
    pub shared: Option<String>,
    /// install tool(s) to the system-wide shared directory
    #[argh(switch, long = "system")]
    pub system: bool,
    /// tool(s) to install e.g.: node@20
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// install a tool version to a specific path
#[derive(FromArgs)]
#[argh(subcommand, name = "install-into")]
pub struct InstallIntoArgs {
    /// tool to install e.g.: node@20
    #[argh(positional)]
    pub tool_version: String,
    /// path to install the tool into
    #[argh(positional)]
    pub path: String,
}

/// gets the latest available version for a plugin
#[derive(FromArgs)]
#[argh(subcommand, name = "latest")]
pub struct LatestArgs {
    /// show latest installed instead of available version
    #[argh(switch, long = "installed", short = 'i')]
    pub installed: bool,
    /// only consider versions released before this date or older than this duration
    #[argh(option, long = "minimum-release-age")]
    pub minimum_release_age: Option<String>,
    /// tool to get the latest version of
    #[argh(positional)]
    pub tool_version: String,
    /// the version prefix to use when querying the latest version same as the first argument after the "@" used for asdf compatibility
    #[argh(positional)]
    pub asdf_version: Option<String>,
}

/// symlinks a tool version into mise
#[derive(FromArgs)]
#[argh(subcommand, name = "link")]
pub struct LinkArgs {
    /// overwrite an existing tool version if it exists
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// tool name and version to create a symlink for
    #[argh(positional)]
    pub tool_version: String,
    /// the local path to the tool version
    #[argh(positional)]
    pub path: String,
}

/// sets/gets tool version in local .tool-versions or mise.toml
#[derive(FromArgs)]
#[argh(subcommand, name = "local")]
pub struct LocalArgs {
    /// recurse up to find a .tool-versions file rather than using the current directory only
    #[argh(switch, long = "parent", short = 'p')]
    pub parent: bool,
    /// save fuzzy version to `.tool-versions` e.g.: `mise local --fuzzy node@20` will save `node 20` to .tool-versions This is the default behavior unless MISE_ASDF_COMPAT=1
    #[argh(switch, long = "fuzzy")]
    pub fuzzy: bool,
    /// get the path of the config file
    #[argh(switch, long = "path")]
    pub path: bool,
    /// save exact version to `.tool-versions`
    #[argh(switch, long = "pin")]
    pub pin: bool,
    /// remove the tool(s) from .tool-versions
    #[argh(option, long = "remove")]
    pub remove: Vec<String>,
    /// tool(s) to add to .tool-versions/mise.toml
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// update lockfile checksums and URLs for all specified platforms
#[derive(FromArgs)]
#[argh(subcommand, name = "lock")]
pub struct LockArgs {
    /// target only global config lockfiles (~/.config/mise/mise.lock and system config)
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// show what would be updated without making changes
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// comma-separated list of platforms to target
    #[argh(option, long = "platform", short = 'p')]
    pub platform: Vec<String>,
    /// re-resolve fuzzy version selectors against the latest available versions
    #[argh(switch, long = "bump")]
    pub bump: bool,
    /// output version changes as JSON
    #[argh(switch, long = "json")]
    pub json: bool,
    /// update mise.local.lock instead of mise.lock
    #[argh(switch, long = "local")]
    pub local: bool,
    /// only lock versions released before this age or date
    #[argh(option, long = "minimum-release-age")]
    pub minimum_release_age: Option<String>,
    /// tool(s) to update in lockfile
    #[argh(positional)]
    pub tool: Vec<String>,
}

/// list installed and active tool versions
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct LsArgs {
    /// only show tool versions currently specified in a mise.toml
    #[argh(switch, long = "current", short = 'c')]
    pub current: bool,
    /// only show tool versions currently specified in the global mise.toml
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// only show tool versions that are installed (Hides tools defined in mise.toml but not installed)
    #[argh(switch, long = "installed", short = 'i')]
    pub installed: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// only show tool versions currently specified in the local mise.toml
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// display missing tool versions
    #[argh(switch, long = "missing", short = 'm')]
    pub missing: bool,
    /// don't fetch information such as outdated versions
    #[argh(switch, long = "offline", short = 'o')]
    pub offline: bool,
    /// plugin
    #[argh(option, long = "plugin", short = 'p')]
    pub plugin: Option<String>,
    /// display all tracked config sources for tools
    #[argh(switch, long = "all-sources")]
    pub all_sources: bool,
    /// list tools from every [monorepo].config_roots config root
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// don't display headers
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// display whether a version is outdated
    #[argh(switch, long = "outdated")]
    pub outdated: bool,
    /// display versions matching this prefix
    #[argh(option, long = "prefix")]
    pub prefix: Option<String>,
    /// list only tools that can be pruned with `mise prune`
    #[argh(switch, long = "prunable")]
    pub prunable: bool,
    /// only show tool versions from [TOOL]
    #[argh(positional)]
    pub installed_tool: Vec<String>,
}

/// list runtime versions available for install.
#[derive(FromArgs)]
#[argh(subcommand, name = "ls-remote")]
pub struct LsRemoteArgs {
    /// show all installed plugins and versions
    #[argh(switch, long = "all")]
    pub all: bool,
    /// only show versions released before this age or date
    #[argh(option, long = "minimum-release-age")]
    pub minimum_release_age: Option<String>,
    /// output in JSON format (includes version metadata like created_at timestamps when available)
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// disable checking the mise-versions host
    #[argh(switch, long = "no-versions-host")]
    pub no_versions_host: bool,
    /// include pre-release versions in the output for backends that report
    #[argh(switch, long = "prerelease")]
    pub prerelease: bool,
    /// fail if release metadata fetches fail
    #[argh(switch, long = "strict-metadata")]
    pub strict_metadata: bool,
    /// tool to get versions for
    #[argh(positional)]
    pub tool_version: String,
    /// the version prefix to use when querying the latest version
    #[argh(positional)]
    pub prefix: Option<String>,
}

/// run Model Context Protocol (MCP) server
#[derive(FromArgs)]
#[argh(subcommand, name = "mcp")]
pub struct McpArgs {}

/// experimental] Build an OCI image from the current mise.toml
#[derive(FromArgs)]
#[argh(subcommand, name = "build")]
pub struct OciBuildArgs {
    /// copy a host file, directory, or symlink into the image (repeatable, HOST:IMAGE)
    #[argh(option, long = "copy")]
    pub copy: Vec<String>,
    /// output directory for the OCI image layout
    #[argh(option, long = "output", short = 'o')]
    pub output: Option<String>,
    /// base image reference (overrides [oci].from and the oci.default_from setting)
    #[argh(option, long = "from")]
    pub from: Option<String>,
    /// also include tools from the global / system config (default: project-only)
    #[argh(switch, long = "include-global")]
    pub include_global: bool,
    /// tag to record in the image index (the org.opencontainers.image.ref.name annotation)
    #[argh(option, long = "tag", short = 't')]
    pub tag: Option<String>,
    /// where to place tool installs inside the image (default: /mise)
    #[argh(option, long = "mount-point")]
    pub mount_point: Option<String>,
    /// do not embed the currently-running mise binary at /usr/local/bin/mise
    #[argh(switch, long = "no-mise")]
    pub no_mise: bool,
    /// uID[:GID] to assign to every tar entry in generated layers
    #[argh(option, long = "owner")]
    pub owner: Option<String>,
}

/// experimental] Build an OCI image and push it to a registry
#[derive(FromArgs)]
#[argh(subcommand, name = "push")]
pub struct OciPushArgs {
    /// reuse unchanged tool layers from this image instead of the destination ref
    #[argh(option, long = "cache-from")]
    pub cache_from: Option<String>,
    /// base image for the build (ignored with --image-dir)
    #[argh(option, long = "from")]
    pub from: Option<String>,
    /// push an already-built OCI image layout (skip the build step)
    #[argh(option, long = "image-dir")]
    pub image_dir: Option<String>,
    /// also include tools from the global / system config (default: project-only)
    #[argh(switch, long = "include-global")]
    pub include_global: bool,
    /// override in-image mount point (ignored with --image-dir)
    #[argh(option, long = "mount-point")]
    pub mount_point: Option<String>,
    /// don't reuse tool layers from the previously pushed image
    #[argh(switch, long = "no-cache")]
    pub no_cache: bool,
    /// don't embed the mise binary (ignored with --image-dir)
    #[argh(switch, long = "no-mise")]
    pub no_mise: bool,
    /// uID[:GID] to assign to every tar entry when building (conflicts with --image-dir)
    #[argh(option, long = "owner")]
    pub owner: Option<String>,
    /// maintain the tag as a multi-arch image index
    #[argh(switch, long = "update-index")]
    pub update_index: bool,
    /// destination registry reference (e.g. `ghcr.io/me/devenv:latest`)
    #[argh(positional)]
    pub ref_: String,
}

/// experimental] Build an OCI image from the current mise.toml and run a command in it
#[derive(FromArgs)]
#[argh(subcommand, name = "run")]
pub struct OciRunArgs {
    /// container engine to use (`auto`, `podman`, or `docker`)
    #[argh(option, long = "engine")]
    pub engine: Option<String>,
    /// base image reference for the build (ignored with --image-dir)
    #[argh(option, long = "from")]
    pub from: Option<String>,
    /// use an already-built OCI image layout instead of building fresh
    #[argh(option, long = "image-dir")]
    pub image_dir: Option<String>,
    /// also include tools from the global / system config (default: project-only)
    #[argh(switch, long = "include-global")]
    pub include_global: bool,
    /// keep the loaded image in the engine's storage after the run
    #[argh(switch, long = "keep")]
    pub keep: bool,
    /// override in-image mount point (ignored with --image-dir)
    #[argh(option, long = "mount-point")]
    pub mount_point: Option<String>,
    /// don't embed the mise binary (ignored with --image-dir)
    #[argh(switch, long = "no-mise")]
    pub no_mise: bool,
    /// uID[:GID] to assign to every tar entry when building (conflicts with --image-dir)
    #[argh(option, long = "owner")]
    pub owner: Option<String>,
    /// bind-mount a host path (repeatable, `HOST:CONTAINER[:MODE]`)
    #[argh(option, long = "volume")]
    pub volume: Vec<String>,
    /// set environment variable in the container (repeatable, `KEY=VAL`)
    #[argh(option, long = "env", short = 'e')]
    pub env: Vec<String>,
    /// run interactively (pass `-i` to the engine)
    #[argh(switch, long = "interactive", short = 'i')]
    pub interactive: bool,
    /// allocate a TTY (pass `-t` to the engine)
    #[argh(switch, long = "tty", short = 't')]
    pub tty: bool,
    /// working directory inside the container
    #[argh(option, long = "workdir", short = 'w')]
    pub workdir: Option<String>,
    /// command and arguments to run inside the container (after `--`)
    #[argh(positional)]
    pub cmd: Vec<String>,
}

/// experimental] Build OCI container images from a mise.toml
#[derive(FromArgs)]
#[argh(subcommand, name = "oci")]
pub struct OciArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: OciCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum OciCommands {
    /// experimental] Build an OCI image from the current mise.toml
    Build(OciBuildArgs),
    /// experimental] Build an OCI image and push it to a registry
    Push(OciPushArgs),
    /// experimental] Build an OCI image from the current mise.toml and run a command in it
    Run(OciRunArgs),
}

/// shows outdated tool versions
#[derive(FromArgs)]
#[argh(subcommand, name = "outdated")]
pub struct OutdatedArgs {
    /// compares against the latest versions available, not what matches the current config
    #[argh(switch, long = "bump", short = 'b')]
    pub bump: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// deprecated shorthand for --bump
    #[argh(switch, short = 'l')]
    pub l: bool,
    /// show outdated tools including installed-but-inactive tools not present in the current config
    #[argh(switch, long = "inactive")]
    pub inactive: bool,
    /// only show outdated tools defined in local config files
    #[argh(switch, long = "local")]
    pub local: bool,
    /// placeholder for future monorepo outdated checks; `mise outdated --monorepo` is not implemented yet.
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// don't show table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// tool(s) to show outdated versions for
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// show the individuals supporting mise as Patron-tier members
#[derive(FromArgs)]
#[argh(subcommand, name = "patrons")]
pub struct PatronsArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// bypass the local cache and re-fetch
    #[argh(switch, long = "refresh")]
    pub refresh: bool,
}

/// install a plugin
#[derive(FromArgs)]
#[argh(subcommand, name = "install")]
pub struct PluginsInstallArgs {
    /// install all missing plugins
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// reinstall even if plugin exists
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// show installation output
    #[argh(switch, long = "verbose", short = 'v')]
    pub verbose: u8,
    /// the name of the plugin to install
    #[argh(positional)]
    pub new_plugin: String,
    /// the git url of the plugin
    #[argh(positional)]
    pub git_url: String,
    /// rest
    #[argh(positional)]
    pub rest: Vec<String>,
}

/// symlinks a plugin into mise
#[derive(FromArgs)]
#[argh(subcommand, name = "link")]
pub struct PluginsLinkArgs {
    /// overwrite existing plugin
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// the name of the plugin
    #[argh(positional)]
    pub name: String,
    /// the local path to the plugin
    #[argh(positional)]
    pub dir: Option<String>,
}

/// list installed plugins
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct PluginsLsArgs {
    /// list all available remote plugins
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// the built-in plugins only
    #[argh(switch, long = "core", short = 'c')]
    pub core: bool,
    /// show plugins with available updates
    #[argh(switch, long = "outdated", short = 'o')]
    pub outdated: bool,
    /// show the git url for each plugin
    #[argh(switch, long = "urls", short = 'u')]
    pub urls: bool,
    /// show the git refs for each plugin
    #[argh(switch, long = "refs")]
    pub refs: bool,
    /// list installed plugins
    #[argh(switch, long = "user")]
    pub user: bool,
}

/// list all available remote plugins
#[derive(FromArgs)]
#[argh(subcommand, name = "ls-remote")]
pub struct PluginsLsRemoteArgs {
    /// show the git url for each plugin e.g.: https://github.com/mise-plugins/mise-poetry.git
    #[argh(switch, long = "urls", short = 'u')]
    pub urls: bool,
    /// only show the name of each plugin by default it will show a "*" next to installed plugins
    #[argh(switch, long = "only-names")]
    pub only_names: bool,
}

/// removes a plugin
#[derive(FromArgs)]
#[argh(subcommand, name = "uninstall")]
pub struct PluginsUninstallArgs {
    /// remove all plugins
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// also remove the plugin's installs, downloads, and cache
    #[argh(switch, long = "purge", short = 'p')]
    pub purge: bool,
    /// plugin(s) to remove
    #[argh(positional)]
    pub plugin: Vec<String>,
}

/// updates a plugin to the latest version
#[derive(FromArgs)]
#[argh(subcommand, name = "update")]
pub struct PluginsUpdateArgs {
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// plugin(s) to update
    #[argh(positional)]
    pub plugin: Vec<String>,
}

/// manage plugins
#[derive(FromArgs)]
#[argh(subcommand, name = "plugins")]
pub struct PluginsArgs {
    /// list all available remote plugins
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// the built-in plugins only
    #[argh(switch, long = "core", short = 'c')]
    pub core: bool,
    /// show the git url for each plugin
    #[argh(switch, long = "urls", short = 'u')]
    pub urls: bool,
    /// show the git refs for each plugin
    #[argh(switch, long = "refs")]
    pub refs: bool,
    /// list installed plugins
    #[argh(switch, long = "user")]
    pub user: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<PluginsCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum PluginsCommands {
    /// install a plugin
    Install(PluginsInstallArgs),
    /// symlinks a plugin into mise
    Link(PluginsLinkArgs),
    /// list installed plugins
    Ls(PluginsLsArgs),
    /// list all available remote plugins
    LsRemote(PluginsLsRemoteArgs),
    /// removes a plugin
    Uninstall(PluginsUninstallArgs),
    /// updates a plugin to the latest version
    Update(PluginsUpdateArgs),
}

/// add a dependency
#[derive(FromArgs)]
#[argh(subcommand, name = "add")]
pub struct DepsAddArgs {
    /// add as a development dependency
    #[argh(switch, long = "dev", short = 'D')]
    pub dev: bool,
    /// package(s) to add (e.g., npm:react, npm:@types/react@19)
    #[argh(positional)]
    pub packages: Vec<String>,
}

/// install all project dependencies
#[derive(FromArgs)]
#[argh(subcommand, name = "install")]
pub struct DepsInstallArgs {
    /// show why a provider is fresh or stale (requires a provider argument)
    #[argh(switch, long = "explain")]
    pub explain: bool,
    /// force run all deps steps even if outputs are fresh
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// only check if deps install is needed, don't run commands
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// show what deps providers are available
    #[argh(switch, long = "list")]
    pub list: bool,
    /// install dependencies from every [monorepo].config_roots config root
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// run specific deps rule(s) only
    #[argh(option, long = "only")]
    pub only: Vec<String>,
    /// skip specific deps rule(s)
    #[argh(option, long = "skip")]
    pub skip: Vec<String>,
    /// provider to operate on (runs only this provider, or use with --explain)
    #[argh(positional)]
    pub provider: Option<String>,
}

/// remove a dependency
#[derive(FromArgs)]
#[argh(subcommand, name = "remove")]
pub struct DepsRemoveArgs {
    /// package(s) to remove (e.g., npm:lodash)
    #[argh(positional)]
    pub packages: Vec<String>,
}

/// experimental] Manage project dependencies
#[derive(FromArgs)]
#[argh(subcommand, name = "deps")]
pub struct DepsArgs {
    /// show why a provider is fresh or stale (requires a provider argument)
    #[argh(switch, long = "explain")]
    pub explain: bool,
    /// force run all deps steps even if outputs are fresh
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// only check if deps install is needed, don't run commands
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// show what deps providers are available
    #[argh(switch, long = "list")]
    pub list: bool,
    /// install dependencies from every [monorepo].config_roots config root
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// run specific deps rule(s) only
    #[argh(option, long = "only")]
    pub only: Vec<String>,
    /// skip specific deps rule(s)
    #[argh(option, long = "skip")]
    pub skip: Vec<String>,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<DepsCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum DepsCommands {
    /// add a dependency
    Add(DepsAddArgs),
    /// install all project dependencies
    Install(DepsInstallArgs),
    /// remove a dependency
    Remove(DepsRemoveArgs),
}

/// delete unused versions of tools
#[derive(FromArgs)]
#[argh(subcommand, name = "prune")]
pub struct PruneArgs {
    /// do not actually delete anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// prune only tracked and trusted configuration links that point to nonexistent configurations
    #[argh(switch, long = "configs")]
    pub configs: bool,
    /// like --dry-run but exits with code 1 if there are tools to prune
    #[argh(switch, long = "dry-run-code")]
    pub dry_run_code: bool,
    /// placeholder for future monorepo pruning; `mise prune --monorepo` is not implemented yet.
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// prune only unused versions of tools
    #[argh(switch, long = "tools")]
    pub tools: bool,
    /// prune only these tools
    #[argh(positional)]
    pub installed_tool: Vec<String>,
}

/// list available tools to install
#[derive(FromArgs)]
#[argh(subcommand, name = "registry")]
pub struct RegistryArgs {
    /// show only tools for this backend
    #[argh(option, long = "backend", short = 'b')]
    pub backend: Option<String>,
    /// print all tools with descriptions for shell completions
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// hide aliased tools
    #[argh(switch, long = "hide-aliased")]
    pub hide_aliased: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// include security features for each tool's backends in JSON output.
    #[argh(switch, long = "security")]
    pub security: bool,
    /// show only the specified tool's full name
    #[argh(positional)]
    pub name: Option<String>,
}

/// internal command to generate markdown from help
#[derive(FromArgs)]
#[argh(subcommand, name = "render-help")]
pub struct RenderHelpArgs {}

/// creates new shims based on bin paths from currently installed tools.
#[derive(FromArgs)]
#[argh(subcommand, name = "reshim")]
pub struct ReshimArgs {
    /// removes all shims before reshimming
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// tool
    #[argh(positional)]
    pub tool: String,
    /// version
    #[argh(positional)]
    pub version: Option<String>,
}

/// run task(s)
#[derive(FromArgs)]
#[argh(subcommand, name = "run")]
pub struct RunArgs {
    /// run matching tasks only for projects affected by Git changes
    #[argh(switch, long = "affected")]
    pub affected: bool,
    /// git base revision for --affected
    #[argh(option, long = "affected-base")]
    pub affected_base: Option<String>,
    /// explain why projects and tasks were selected by --affected
    #[argh(switch, long = "affected-explain")]
    pub affected_explain: bool,
    /// git head revision for --affected
    #[argh(option, long = "affected-head")]
    pub affected_head: Option<String>,
    /// output affected projects and tasks as JSON without running tasks
    #[argh(switch, long = "affected-json")]
    pub affected_json: bool,
    /// open the interactive selector with all tasks from the entire monorepo
    #[argh(switch, long = "all")]
    pub all: bool,
    /// continue running tasks even if one fails
    #[argh(switch, long = "continue-on-error", short = 'c')]
    pub continue_on_error: bool,
    /// change to this directory before executing the command
    #[argh(option, long = "cd", short = 'C')]
    pub cd: Option<String>,
    /// force the tasks to run even if outputs are up to date
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// number of tasks to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// don't actually run the task(s), just print them in order of execution
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// change how tasks information is output when running tasks
    #[argh(option, long = "output", short = 'o')]
    pub output: Option<String>,
    /// don't show extra output
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// read/write directly to stdin/stdout/stderr instead of by line
    #[argh(switch, long = "raw", short = 'r')]
    pub raw: bool,
    /// shell to use to run toml tasks
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// don't show any output except for errors
    #[argh(switch, long = "silent", short = 'S')]
    pub silent: bool,
    /// tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10
    #[argh(option, long = "tool", short = 't')]
    pub tool: Vec<String>,
    /// allow specific env var through (implies --deny-env for everything else)
    #[argh(option, long = "allow-env")]
    pub allow_env: Vec<String>,
    /// allow network to specific host (implies --deny-net for everything else)
    #[argh(option, long = "allow-net")]
    pub allow_net: Vec<String>,
    /// allow reads from specific path (implies --deny-read for everything else)
    #[argh(option, long = "allow-read")]
    pub allow_read: Vec<String>,
    /// allow writes to specific path (implies --deny-write for everything else)
    #[argh(option, long = "allow-write")]
    pub allow_write: Vec<String>,
    /// block reads, writes, network, and env vars
    #[argh(switch, long = "deny-all")]
    pub deny_all: bool,
    /// block env var inheritance (only PATH, HOME, USER, SHELL, TERM, LANG pass through)
    #[argh(switch, long = "deny-env")]
    pub deny_env: bool,
    /// block all network access
    #[argh(switch, long = "deny-net")]
    pub deny_net: bool,
    /// block filesystem reads (system libs and tool dirs still accessible)
    #[argh(switch, long = "deny-read")]
    pub deny_read: bool,
    /// block all filesystem writes
    #[argh(switch, long = "deny-write")]
    pub deny_write: bool,
    /// bypass the environment cache and recompute the environment
    #[argh(switch, long = "fresh-env")]
    pub fresh_env: bool,
    /// do not use cache on remote tasks
    #[argh(switch, long = "no-cache")]
    pub no_cache: bool,
    /// skip automatic dependency preparation
    #[argh(switch, long = "no-deps")]
    pub no_deps: bool,
    /// hides elapsed time after each task completes
    #[argh(switch, long = "no-timings")]
    pub no_timings: bool,
    /// run only the specified tasks skipping all dependencies
    #[argh(switch, long = "skip-deps")]
    pub skip_deps: bool,
    /// skip installing tools before running tasks
    #[argh(switch, long = "skip-tools")]
    pub skip_tools: bool,
    /// set task output cache access for this run
    #[argh(option, long = "task-cache")]
    pub task_cache: Option<String>,
    /// explain the inputs that produced each task's output cache key
    #[argh(switch, long = "task-cache-explain")]
    pub task_cache_explain: bool,
    /// output cache-key input details as JSON Lines without running tasks
    #[argh(switch, long = "task-cache-explain-json")]
    pub task_cache_explain_json: bool,
    /// report task output cache hits, restored bytes, and time saved
    #[argh(switch, long = "task-cache-stats")]
    pub task_cache_stats: bool,
    /// timeout for the task to complete
    #[argh(option, long = "timeout")]
    pub timeout: Option<String>,
    /// shows elapsed time after each task completes
    #[argh(switch, long = "timings")]
    pub timings: bool,
}

/// search for tools in the registry
#[derive(FromArgs)]
#[argh(subcommand, name = "search")]
pub struct SearchArgs {
    /// show interactive search
    #[argh(switch, long = "interactive", short = 'i')]
    pub interactive: bool,
    /// match type: equal, contains, or fuzzy
    #[argh(option, long = "match-type", short = 'm')]
    pub match_type: Option<String>,
    /// don't display headers
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// the tool to search for
    #[argh(positional)]
    pub name: Option<String>,
}

/// updates mise itself.
#[derive(FromArgs)]
#[argh(subcommand, name = "self-update")]
pub struct SelfUpdateArgs {
    /// update even if already up to date
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// skip confirmation prompt
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// disable auto-updating plugins
    #[argh(switch, long = "no-plugins")]
    pub no_plugins: bool,
    /// update to a specific version
    #[argh(positional)]
    pub version: Option<String>,
}

/// set environment variables in mise.toml
#[derive(FromArgs)]
#[argh(subcommand, name = "set")]
pub struct SetArgs {
    /// create/modify an environment-specific config file like .mise.<env>.toml
    #[argh(option, long = "env", short = 'E')]
    pub env: Option<String>,
    /// set the environment variable in the global config file
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// experimental] Encrypt the value with age before storing
    #[argh(switch, long = "age-encrypt")]
    pub age_encrypt: bool,
    /// experimental] Age identity file for encryption
    #[argh(option, long = "age-key-file")]
    pub age_key_file: Option<String>,
    /// experimental] Age recipient (x25519 public key) for encryption
    #[argh(option, long = "age-recipient")]
    pub age_recipient: Vec<String>,
    /// experimental] SSH recipient (public key or path) for age encryption
    #[argh(option, long = "age-ssh-recipient")]
    pub age_ssh_recipient: Vec<String>,
    /// render completions
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// the TOML file to update
    #[argh(option, long = "file")]
    pub file: Option<String>,
    /// show raw values instead of redacting secrets
    #[argh(switch, long = "no-redact")]
    pub no_redact: bool,
    /// prompt for environment variable values
    #[argh(switch, long = "prompt")]
    pub prompt: bool,
    /// remove the environment variable from config file
    #[argh(option, long = "remove")]
    pub remove: Vec<String>,
    /// read the value from stdin (for multiline input)
    #[argh(switch, long = "stdin")]
    pub stdin: bool,
    /// environment variable(s) to set
    #[argh(positional)]
    pub env_var: Vec<String>,
}

/// adds a setting to the configuration file
#[derive(FromArgs)]
#[argh(subcommand, name = "add")]
pub struct SettingsAddArgs {
    /// use the local config file instead of the global one
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// the setting to set
    #[argh(positional)]
    pub setting: String,
    /// the value to set (optional if provided as KEY=VALUE)
    #[argh(positional)]
    pub value: Option<String>,
}

/// show a current setting
#[derive(FromArgs)]
#[argh(subcommand, name = "get")]
pub struct SettingsGetArgs {
    /// use the local config file instead of the global one
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// the setting to show
    #[argh(positional)]
    pub setting: String,
}

/// show current settings
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct SettingsLsArgs {
    /// list all settings
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// use the local config file instead of the global one
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// output in TOML format
    #[argh(switch, long = "toml", short = 'T')]
    pub toml: bool,
    /// print all settings with descriptions for shell completions
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// output in JSON format with sources
    #[argh(switch, long = "json-extended")]
    pub json_extended: bool,
    /// name of setting
    #[argh(positional)]
    pub setting: Option<String>,
}

/// add/update a setting
#[derive(FromArgs)]
#[argh(subcommand, name = "set")]
pub struct SettingsSetArgs {
    /// use the local config file instead of the global one
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// the setting to set
    #[argh(positional)]
    pub setting: String,
    /// the value to set (optional if provided as KEY=VALUE)
    #[argh(positional)]
    pub value: Option<String>,
}

/// clears a setting
#[derive(FromArgs)]
#[argh(subcommand, name = "unset")]
pub struct SettingsUnsetArgs {
    /// use the local config file instead of the global one
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// the setting to remove
    #[argh(positional)]
    pub key: String,
}

/// manage settings
#[derive(FromArgs)]
#[argh(subcommand, name = "settings")]
pub struct SettingsArgs {
    /// list all settings
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// use the local config file instead of the global one
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// output in TOML format
    #[argh(switch, long = "toml", short = 'T')]
    pub toml: bool,
    /// print all settings with descriptions for shell completions
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// output in JSON format with sources
    #[argh(switch, long = "json-extended")]
    pub json_extended: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<SettingsCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum SettingsCommands {
    /// adds a setting to the configuration file
    Add(SettingsAddArgs),
    /// show a current setting
    Get(SettingsGetArgs),
    /// show current settings
    Ls(SettingsLsArgs),
    /// add/update a setting
    Set(SettingsSetArgs),
    /// clears a setting
    Unset(SettingsUnsetArgs),
}

/// sets a tool version for the current session.
#[derive(FromArgs)]
#[argh(subcommand, name = "shell")]
pub struct ShellArgs {
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// removes a previously set version
    #[argh(switch, long = "unset", short = 'u')]
    pub unset: bool,
    /// connect backend install command stdin/stdout/stderr directly to the terminal Implies --jobs=1
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// tool(s) to use
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// show the command for a shell alias
#[derive(FromArgs)]
#[argh(subcommand, name = "get")]
pub struct ShellAliasGetArgs {
    /// the alias to show
    #[argh(positional)]
    pub shell_alias: String,
}

/// list shell aliases
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct ShellAliasLsArgs {
    /// don't show table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
}

/// add/update a shell alias
#[derive(FromArgs)]
#[argh(subcommand, name = "set")]
pub struct ShellAliasSetArgs {
    /// the alias name
    #[argh(positional)]
    pub shell_alias: String,
    /// the command to run (optional if provided as ALIAS=COMMAND)
    #[argh(positional)]
    pub command: Option<String>,
}

/// removes a shell alias
#[derive(FromArgs)]
#[argh(subcommand, name = "unset")]
pub struct ShellAliasUnsetArgs {
    /// the alias to remove
    #[argh(positional)]
    pub shell_alias: String,
}

/// manage shell aliases.
#[derive(FromArgs)]
#[argh(subcommand, name = "shell-alias")]
pub struct ShellAliasArgs {
    /// don't show table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<ShellAliasCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum ShellAliasCommands {
    /// show the command for a shell alias
    Get(ShellAliasGetArgs),
    /// list shell aliases
    Ls(ShellAliasLsArgs),
    /// add/update a shell alias
    Set(ShellAliasSetArgs),
    /// removes a shell alias
    Unset(ShellAliasUnsetArgs),
}

/// show the companies sponsoring mise and the jdx.dev open source tools
#[derive(FromArgs)]
#[argh(subcommand, name = "sponsors")]
pub struct SponsorsArgs {}

/// symlinks all tool versions from an external tool into mise
#[derive(FromArgs)]
#[argh(subcommand, name = "node")]
pub struct SyncNodeArgs {
    /// get tool versions from Homebrew
    #[argh(switch, long = "brew")]
    pub brew: bool,
    /// get tool versions from nodenv
    #[argh(switch, long = "nodenv")]
    pub nodenv: bool,
    /// get tool versions from nvm
    #[argh(switch, long = "nvm")]
    pub nvm: bool,
}

/// symlinks all tool versions from an external tool into mise
#[derive(FromArgs)]
#[argh(subcommand, name = "python")]
pub struct SyncPythonArgs {
    /// get tool versions from pyenv
    #[argh(switch, long = "pyenv")]
    pub pyenv: bool,
    /// sync tool versions with uv (2-way sync)
    #[argh(switch, long = "uv")]
    pub uv: bool,
}

/// symlinks all ruby tool versions from an external tool into mise
#[derive(FromArgs)]
#[argh(subcommand, name = "ruby")]
pub struct SyncRubyArgs {
    /// get tool versions from Homebrew
    #[argh(switch, long = "brew")]
    pub brew: bool,
}

/// synchronize tools from other version managers with mise
#[derive(FromArgs)]
#[argh(subcommand, name = "sync")]
pub struct SyncArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: SyncCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum SyncCommands {
    /// symlinks all tool versions from an external tool into mise
    Node(SyncNodeArgs),
    /// symlinks all tool versions from an external tool into mise
    Python(SyncPythonArgs),
    /// symlinks all ruby tool versions from an external tool into mise
    Ruby(SyncRubyArgs),
}

/// create a new task
#[derive(FromArgs)]
#[argh(subcommand, name = "add")]
pub struct TasksAddArgs {
    /// other names for the task
    #[argh(option, long = "alias", short = 'a')]
    pub alias: Vec<String>,
    /// add dependencies to the task
    #[argh(option, long = "depends", short = 'd')]
    pub depends: Vec<String>,
    /// run the task in a specific directory
    #[argh(option, long = "dir", short = 'D')]
    pub dir: Option<String>,
    /// create a file task instead of a toml task
    #[argh(switch, long = "file", short = 'f')]
    pub file: bool,
    /// hide the task from `mise tasks` and completions
    #[argh(switch, long = "hide", short = 'H')]
    pub hide: bool,
    /// do not print the command before running
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// directly connect stdin/stdout/stderr
    #[argh(switch, long = "raw", short = 'r')]
    pub raw: bool,
    /// glob patterns of files this task uses as input
    #[argh(option, long = "sources", short = 's')]
    pub sources: Vec<String>,
    /// wait for these tasks to complete if they are to run
    #[argh(option, long = "wait-for", short = 'w')]
    pub wait_for: Vec<String>,
    /// dependencies to run after the task runs
    #[argh(option, long = "depends-post")]
    pub depends_post: Vec<String>,
    /// description of the task
    #[argh(option, long = "description")]
    pub description: Option<String>,
    /// glob patterns of files this task creates, to skip if they are not modified
    #[argh(option, long = "outputs")]
    pub outputs: Vec<String>,
    /// command to run on windows
    #[argh(option, long = "run-windows")]
    pub run_windows: Option<String>,
    /// run the task in a specific shell
    #[argh(option, long = "shell")]
    pub shell: Option<String>,
    /// do not print the command or its output
    #[argh(switch, long = "silent")]
    pub silent: bool,
    /// tasks name to add
    #[argh(positional)]
    pub task: String,
    /// run
    #[argh(positional)]
    pub run: Vec<String>,
}

/// display a tree visualization of a dependency graph
#[derive(FromArgs)]
#[argh(subcommand, name = "deps")]
pub struct TasksDepsArgs {
    /// collapse repeated dependencies after their first occurrence
    #[argh(switch, long = "compact")]
    pub compact: bool,
    /// display dependencies in DOT format
    #[argh(switch, long = "dot")]
    pub dot: bool,
    /// show hidden tasks
    #[argh(switch, long = "hidden")]
    pub hidden: bool,
    /// tasks to show dependencies for
    #[argh(positional)]
    pub tasks: Vec<String>,
}

/// edit a task with $EDITOR
#[derive(FromArgs)]
#[argh(subcommand, name = "edit")]
pub struct TasksEditArgs {
    /// display the path to the task instead of editing it
    #[argh(switch, long = "path", short = 'p')]
    pub path: bool,
    /// task to edit
    #[argh(positional)]
    pub task: String,
}

/// experimental] Inspect the workspace project graph
#[derive(FromArgs)]
#[argh(subcommand, name = "graph")]
pub struct TasksGraphArgs {
    /// output the project graph as JSON
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// explain provider attribution for inferred projects and tasks
    #[argh(switch, long = "explain")]
    pub explain: bool,
    /// do not print table headers
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
}

/// get information about a task
#[derive(FromArgs)]
#[argh(subcommand, name = "info")]
pub struct TasksInfoArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// name of the task to get information about
    #[argh(positional)]
    pub task: String,
}

/// list available tasks to execute
#[derive(FromArgs)]
#[argh(subcommand, name = "ls")]
pub struct TasksLsArgs {
    /// only show global tasks
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// only show non-global tasks
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// show all columns
    #[argh(switch, long = "extended", short = 'x')]
    pub extended: bool,
    /// load all tasks from the entire monorepo, including sibling directories.
    #[argh(switch, long = "all")]
    pub all: bool,
    /// display tasks for usage completion
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// show hidden tasks
    #[argh(switch, long = "hidden")]
    pub hidden: bool,
    /// only show task names, one per line. Useful for piping to fzf and similar tools.
    #[argh(switch, long = "name-only")]
    pub name_only: bool,
    /// do not print table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// sort by column. Default is name.
    #[argh(option, long = "sort")]
    pub sort: Option<String>,
    /// sort order. Default is asc.
    #[argh(option, long = "sort-order")]
    pub sort_order: Option<String>,
    /// usage
    #[argh(switch, long = "usage")]
    pub usage: bool,
}

/// run task(s)
#[derive(FromArgs)]
#[argh(subcommand, name = "run")]
pub struct TasksRunArgs {
    /// run matching tasks only for projects affected by Git changes
    #[argh(switch, long = "affected")]
    pub affected: bool,
    /// git base revision for --affected
    #[argh(option, long = "affected-base")]
    pub affected_base: Option<String>,
    /// explain why projects and tasks were selected by --affected
    #[argh(switch, long = "affected-explain")]
    pub affected_explain: bool,
    /// git head revision for --affected
    #[argh(option, long = "affected-head")]
    pub affected_head: Option<String>,
    /// output affected projects and tasks as JSON without running tasks
    #[argh(switch, long = "affected-json")]
    pub affected_json: bool,
    /// open the interactive selector with all tasks from the entire monorepo
    #[argh(switch, long = "all")]
    pub all: bool,
    /// continue running tasks even if one fails
    #[argh(switch, long = "continue-on-error", short = 'c')]
    pub continue_on_error: bool,
    /// change to this directory before executing the command
    #[argh(option, long = "cd", short = 'C')]
    pub cd: Option<String>,
    /// force the tasks to run even if outputs are up to date
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// number of tasks to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// don't actually run the task(s), just print them in order of execution
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// change how tasks information is output when running tasks
    #[argh(option, long = "output", short = 'o')]
    pub output: Option<String>,
    /// don't show extra output
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// read/write directly to stdin/stdout/stderr instead of by line
    #[argh(switch, long = "raw", short = 'r')]
    pub raw: bool,
    /// shell to use to run toml tasks
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// don't show any output except for errors
    #[argh(switch, long = "silent", short = 'S')]
    pub silent: bool,
    /// tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10
    #[argh(option, long = "tool", short = 't')]
    pub tool: Vec<String>,
    /// allow specific env var through (implies --deny-env for everything else)
    #[argh(option, long = "allow-env")]
    pub allow_env: Vec<String>,
    /// allow network to specific host (implies --deny-net for everything else)
    #[argh(option, long = "allow-net")]
    pub allow_net: Vec<String>,
    /// allow reads from specific path (implies --deny-read for everything else)
    #[argh(option, long = "allow-read")]
    pub allow_read: Vec<String>,
    /// allow writes to specific path (implies --deny-write for everything else)
    #[argh(option, long = "allow-write")]
    pub allow_write: Vec<String>,
    /// block reads, writes, network, and env vars
    #[argh(switch, long = "deny-all")]
    pub deny_all: bool,
    /// block env var inheritance (only PATH, HOME, USER, SHELL, TERM, LANG pass through)
    #[argh(switch, long = "deny-env")]
    pub deny_env: bool,
    /// block all network access
    #[argh(switch, long = "deny-net")]
    pub deny_net: bool,
    /// block filesystem reads (system libs and tool dirs still accessible)
    #[argh(switch, long = "deny-read")]
    pub deny_read: bool,
    /// block all filesystem writes
    #[argh(switch, long = "deny-write")]
    pub deny_write: bool,
    /// bypass the environment cache and recompute the environment
    #[argh(switch, long = "fresh-env")]
    pub fresh_env: bool,
    /// do not use cache on remote tasks
    #[argh(switch, long = "no-cache")]
    pub no_cache: bool,
    /// skip automatic dependency preparation
    #[argh(switch, long = "no-deps")]
    pub no_deps: bool,
    /// hides elapsed time after each task completes
    #[argh(switch, long = "no-timings")]
    pub no_timings: bool,
    /// run only the specified tasks skipping all dependencies
    #[argh(switch, long = "skip-deps")]
    pub skip_deps: bool,
    /// skip installing tools before running tasks
    #[argh(switch, long = "skip-tools")]
    pub skip_tools: bool,
    /// set task output cache access for this run
    #[argh(option, long = "task-cache")]
    pub task_cache: Option<String>,
    /// explain the inputs that produced each task's output cache key
    #[argh(switch, long = "task-cache-explain")]
    pub task_cache_explain: bool,
    /// output cache-key input details as JSON Lines without running tasks
    #[argh(switch, long = "task-cache-explain-json")]
    pub task_cache_explain_json: bool,
    /// report task output cache hits, restored bytes, and time saved
    #[argh(switch, long = "task-cache-stats")]
    pub task_cache_stats: bool,
    /// timeout for the task to complete
    #[argh(option, long = "timeout")]
    pub timeout: Option<String>,
    /// shows elapsed time after each task completes
    #[argh(switch, long = "timings")]
    pub timings: bool,
    /// tasks to run
    #[argh(positional)]
    pub task: String,
    /// arguments to pass to the tasks. Use ":::" to separate tasks.
    #[argh(positional)]
    pub args: String,
    /// arguments to pass to the tasks. Use ":::" to separate tasks.
    #[argh(positional)]
    pub args_last: Vec<String>,
}

/// validate tasks for common errors and issues
#[derive(FromArgs)]
#[argh(subcommand, name = "validate")]
pub struct TasksValidateArgs {
    /// only show errors (skip warnings)
    #[argh(switch, long = "errors-only")]
    pub errors_only: bool,
    /// output validation results in JSON format
    #[argh(switch, long = "json")]
    pub json: bool,
    /// tasks to validate
    #[argh(positional)]
    pub tasks: Vec<String>,
}

/// manage tasks
#[derive(FromArgs)]
#[argh(subcommand, name = "tasks")]
pub struct TasksArgs {
    /// only show global tasks
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// only show non-global tasks
    #[argh(switch, long = "local", short = 'l')]
    pub local: bool,
    /// show all columns
    #[argh(switch, long = "extended", short = 'x')]
    pub extended: bool,
    /// load all tasks from the entire monorepo, including sibling directories.
    #[argh(switch, long = "all")]
    pub all: bool,
    /// display tasks for usage completion
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// show hidden tasks
    #[argh(switch, long = "hidden")]
    pub hidden: bool,
    /// only show task names, one per line. Useful for piping to fzf and similar tools.
    #[argh(switch, long = "name-only")]
    pub name_only: bool,
    /// do not print table header
    #[argh(switch, long = "no-header")]
    pub no_header: bool,
    /// sort by column. Default is name.
    #[argh(option, long = "sort")]
    pub sort: Option<String>,
    /// sort order. Default is asc.
    #[argh(option, long = "sort-order")]
    pub sort_order: Option<String>,
    /// usage
    #[argh(switch, long = "usage")]
    pub usage: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<TasksCommands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum TasksCommands {
    /// create a new task
    Add(TasksAddArgs),
    /// display a tree visualization of a dependency graph
    Deps(TasksDepsArgs),
    /// edit a task with $EDITOR
    Edit(TasksEditArgs),
    /// experimental] Inspect the workspace project graph
    Graph(TasksGraphArgs),
    /// get information about a task
    Info(TasksInfoArgs),
    /// list available tasks to execute
    Ls(TasksLsArgs),
    /// run task(s)
    Run(TasksRunArgs),
    /// validate tasks for common errors and issues
    Validate(TasksValidateArgs),
}

/// test a tool installs and executes
#[derive(FromArgs)]
#[argh(subcommand, name = "test-tool")]
pub struct TestToolArgs {
    /// test every tool specified in registry/
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// number of tool tests to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// test all tools specified in config files
    #[argh(switch, long = "all-config")]
    pub all_config: bool,
    /// also test tools not defined in registry/, guessing how to test it
    #[argh(switch, long = "include-non-defined")]
    pub include_non_defined: bool,
    /// connect backend install command stdin/stdout/stderr directly to the terminal Implies --jobs=1
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// tool(s) to test
    #[argh(positional)]
    pub tools: Vec<String>,
}

/// forgejo token
#[derive(FromArgs)]
#[argh(subcommand, name = "forgejo")]
pub struct TokenForgejoArgs {
    /// show the full unmasked token
    #[argh(switch, long = "unmask")]
    pub unmask: bool,
    /// forgejo hostname
    #[argh(positional)]
    pub host: Option<String>,
}

/// gitHub token
#[derive(FromArgs)]
#[argh(subcommand, name = "github")]
pub struct TokenGithubArgs {
    /// resolve only via the native GitHub OAuth source (cache, refresh, or device-code flow), bypassing other token sources
    #[argh(switch, long = "oauth")]
    pub oauth: bool,
    /// print only the token value
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// mint a fresh OAuth token even if the cached one has not expired, via the refresh-token grant or a new device-code flow. Use after changing the GitHub App's installations or permissions: cached tokens keep their original access until they expire
    #[argh(switch, long = "refresh")]
    pub refresh: bool,
    /// show the full unmasked token
    #[argh(switch, long = "unmask")]
    pub unmask: bool,
    /// gitHub hostname
    #[argh(positional)]
    pub host: Option<String>,
}

/// gitLab token
#[derive(FromArgs)]
#[argh(subcommand, name = "gitlab")]
pub struct TokenGitlabArgs {
    /// show the full unmasked token
    #[argh(switch, long = "unmask")]
    pub unmask: bool,
    /// gitLab hostname
    #[argh(positional)]
    pub host: Option<String>,
}

/// display git provider tokens mise will use
#[derive(FromArgs)]
#[argh(subcommand, name = "token")]
pub struct TokenArgs {
    #[argh(subcommand)]
    /// subcommand
    pub command: TokenCommands,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum TokenCommands {
    /// forgejo token
    Forgejo(TokenForgejoArgs),
    /// gitHub token
    Github(TokenGithubArgs),
    /// gitLab token
    Gitlab(TokenGitlabArgs),
}

/// gets information about a tool
#[derive(FromArgs)]
#[argh(subcommand, name = "tool")]
pub struct ToolArgs {
    /// output in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
    /// only show active versions
    #[argh(switch, long = "active")]
    pub active: bool,
    /// only show backend field
    #[argh(switch, long = "backend")]
    pub backend: bool,
    /// only show config source
    #[argh(switch, long = "config-source")]
    pub config_source: bool,
    /// only show description field
    #[argh(switch, long = "description")]
    pub description: bool,
    /// only show installed versions
    #[argh(switch, long = "installed")]
    pub installed: bool,
    /// only show requested versions
    #[argh(switch, long = "requested")]
    pub requested: bool,
    /// only show tool options
    #[argh(switch, long = "tool-options")]
    pub tool_options: bool,
    /// tool name to get information about
    #[argh(positional)]
    pub tool: String,
}

/// execute a tool stub
#[derive(FromArgs)]
#[argh(subcommand, name = "tool-stub")]
pub struct ToolStubArgs {
    /// path to the TOML tool stub file to execute
    #[argh(positional)]
    pub file: String,
    /// arguments to pass to the tool
    #[argh(positional)]
    pub args: Vec<String>,
}

/// marks a config file as trusted
#[derive(FromArgs)]
#[argh(subcommand, name = "trust")]
pub struct TrustArgs {
    /// trust all config files in the current directory, its parents, and its subdirectories
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// do not trust this config and ignore it in the future
    #[argh(switch, long = "ignore")]
    pub ignore: bool,
    /// show the trusted status of config files from the current directory and its parents.
    #[argh(switch, long = "show")]
    pub show: bool,
    /// remove explicit trust for this config
    #[argh(switch, long = "untrust")]
    pub untrust: bool,
    /// the config file whose trust status to change
    #[argh(positional)]
    pub config_file: Option<String>,
}

/// removes installed tool versions
#[derive(FromArgs)]
#[argh(subcommand, name = "uninstall")]
pub struct UninstallArgs {
    /// delete all installed versions
    #[argh(switch, long = "all", short = 'a')]
    pub all: bool,
    /// do not actually delete anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// like --dry-run but exits with code 1 if there are tools to uninstall
    #[argh(switch, long = "dry-run-code")]
    pub dry_run_code: bool,
    /// tool(s) to remove
    #[argh(positional)]
    pub installed_tool_version: Vec<String>,
}

/// remove environment variable(s) from the config file.
#[derive(FromArgs)]
#[argh(subcommand, name = "unset")]
pub struct UnsetArgs {
    /// specify a file to use instead of `mise.toml`
    #[argh(option, long = "file", short = 'f')]
    pub file: Option<String>,
    /// use the global config file
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// environment variable(s) to remove
    #[argh(positional)]
    pub env_key: Vec<String>,
}

/// remove explicit trust for a config
#[derive(FromArgs)]
#[argh(subcommand, name = "untrust")]
pub struct UntrustArgs {
    /// the config file to untrust
    #[argh(positional)]
    pub config_file: Option<String>,
}

/// removes installed tool versions from mise.toml
#[derive(FromArgs)]
#[argh(subcommand, name = "unuse")]
pub struct UnuseArgs {
    /// create/modify an environment-specific config file like .mise.<env>.toml
    #[argh(option, long = "env", short = 'e')]
    pub env: Option<String>,
    /// use the global config file (`~/.config/mise/config.toml`) instead of the local one
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// specify a path to a config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// do not also prune the installed version
    #[argh(switch, long = "no-prune")]
    pub no_prune: bool,
    /// tool(s) to remove
    #[argh(positional)]
    pub installed_tool_version: Vec<String>,
}

/// upgrades outdated tools
#[derive(FromArgs)]
#[argh(subcommand, name = "upgrade")]
pub struct UpgradeArgs {
    /// upgrades to the latest version available, bumping the version in mise.toml
    #[argh(switch, long = "bump", short = 'b')]
    pub bump: bool,
    /// display multiselect menu to choose which tools to upgrade
    #[argh(switch, long = "interactive", short = 'i')]
    pub interactive: bool,
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// deprecated shorthand for --bump
    #[argh(switch, short = 'l')]
    pub l: bool,
    /// just print what would be done, don't actually do it
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// tool(s) to exclude from upgrading
    #[argh(option, long = "exclude", short = 'x')]
    pub exclude: Vec<String>,
    /// like --dry-run but exits with code 1 if there are outdated tools
    #[argh(switch, long = "dry-run-code")]
    pub dry_run_code: bool,
    /// upgrade all tools, including installed-but-inactive tools not present in the current config
    #[argh(switch, long = "inactive")]
    pub inactive: bool,
    /// only upgrade tools defined in local config files
    #[argh(switch, long = "local")]
    pub local: bool,
    /// only upgrade to versions released before this date or older than this duration
    #[argh(option, long = "minimum-release-age")]
    pub minimum_release_age: Option<String>,
    /// placeholder for future monorepo upgrades; `mise upgrade --monorepo` is not implemented yet.
    #[argh(switch, long = "monorepo")]
    pub monorepo: bool,
    /// do not uninstall the versions that were upgraded away from
    #[argh(switch, long = "no-prune")]
    pub no_prune: bool,
    /// uninstall the versions that were upgraded away from
    #[argh(switch, long = "prune")]
    pub prune: bool,
    /// connect backend install command stdin/stdout/stderr directly to the terminal Implies --jobs=1
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// tool(s) to upgrade
    #[argh(positional)]
    pub installed_tool_version: Vec<String>,
}

/// generate a usage CLI spec
#[derive(FromArgs)]
#[argh(subcommand, name = "usage")]
pub struct UsageArgs {}

/// installs a tool and adds the version to mise.toml.
#[derive(FromArgs)]
#[argh(subcommand, name = "use")]
pub struct UseArgs {
    /// create/modify an environment-specific config file like .mise.<env>.toml
    #[argh(option, long = "env", short = 'e')]
    pub env: Option<String>,
    /// force reinstall even if already installed
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// use the global config file (`~/.config/mise/config.toml`) instead of the local one
    #[argh(switch, long = "global", short = 'g')]
    pub global: bool,
    /// number of jobs to run in parallel
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// perform a dry run, showing what would be installed and modified without making changes
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// specify a path to a config file or directory
    #[argh(option, long = "path", short = 'p')]
    pub path: Option<String>,
    /// like --dry-run but exits with code 1 if there are changes to make
    #[argh(switch, long = "dry-run-code")]
    pub dry_run_code: bool,
    /// save fuzzy version to config file
    #[argh(switch, long = "fuzzy")]
    pub fuzzy: bool,
    /// only install versions released before this date or older than this duration
    #[argh(option, long = "minimum-release-age")]
    pub minimum_release_age: Option<String>,
    /// save the resolved concrete version to the config file
    #[argh(switch, long = "pin")]
    pub pin: bool,
    /// connect backend install command stdin/stdout/stderr directly to the terminal Implies `--jobs=1`
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// remove the tool(s) from config file
    #[argh(option, long = "remove")]
    pub remove: Vec<String>,
    /// tool(s) to add to config file
    #[argh(positional)]
    pub tool_version: Vec<String>,
}

/// display the version of mise
#[derive(FromArgs)]
#[argh(subcommand, name = "version")]
pub struct VersionArgs {
    /// print the version information in JSON format
    #[argh(switch, long = "json", short = 'J')]
    pub json: bool,
}

/// run task(s) and watch for changes to rerun it
#[derive(FromArgs)]
#[argh(subcommand, name = "watch")]
pub struct WatchArgs {
    /// tasks to run
    #[argh(option, long = "task-flag", short = 't')]
    pub task_flag: Vec<String>,
    /// files to watch
    #[argh(option, long = "glob", short = 'g')]
    pub glob: Vec<String>,
    /// run only the specified tasks skipping all dependencies
    #[argh(switch, long = "skip-deps")]
    pub skip_deps: bool,
    /// watch a specific file or directory
    #[argh(option, long = "watch", short = 'w')]
    pub watch: Vec<String>,
    /// watch a specific directory, non-recursively
    #[argh(option, long = "watch-non-recursive", short = 'W')]
    pub watch_non_recursive: Vec<String>,
    /// watch files and directories from a file
    #[argh(option, long = "watch-file", short = 'F')]
    pub watch_file: Option<String>,
    /// clear screen before running command
    #[argh(option, long = "clear", short = 'c')]
    pub clear: Option<String>,
    /// what to do when receiving events while the command is running
    #[argh(option, long = "on-busy-update", short = 'o')]
    pub on_busy_update: Option<String>,
    /// restart the process if it's still running
    #[argh(switch, long = "restart", short = 'r')]
    pub restart: bool,
    /// send a signal to the process when it's still running
    #[argh(option, long = "signal", short = 's')]
    pub signal: Option<String>,
    /// signal to send to stop the command
    #[argh(option, long = "stop-signal")]
    pub stop_signal: Option<String>,
    /// time to wait for the command to exit gracefully
    #[argh(option, long = "stop-timeout")]
    pub stop_timeout: Option<String>,
    /// translate signals from the OS to signals to send to the command
    #[argh(option, long = "map-signal")]
    pub map_signal: Vec<String>,
    /// time to wait for new events before taking action
    #[argh(option, long = "debounce", short = 'd')]
    pub debounce: Option<String>,
    /// exit when stdin closes
    #[argh(switch, long = "stdin-quit")]
    pub stdin_quit: bool,
    /// don't load gitignores
    #[argh(switch, long = "no-vcs-ignore")]
    pub no_vcs_ignore: bool,
    /// don't load project-local ignores
    #[argh(switch, long = "no-project-ignore")]
    pub no_project_ignore: bool,
    /// don't load global ignores
    #[argh(switch, long = "no-global-ignore")]
    pub no_global_ignore: bool,
    /// don't use internal default ignores
    #[argh(switch, long = "no-default-ignore")]
    pub no_default_ignore: bool,
    /// don't discover ignore files at all
    #[argh(switch, long = "no-discover-ignore")]
    pub no_discover_ignore: bool,
    /// don't ignore anything at all
    #[argh(switch, long = "ignore-nothing")]
    pub ignore_nothing: bool,
    /// wait until first change before running command
    #[argh(switch, long = "postpone", short = 'p')]
    pub postpone: bool,
    /// sleep before running the command
    #[argh(option, long = "delay-run")]
    pub delay_run: Option<String>,
    /// poll for filesystem changes
    #[argh(option, long = "poll")]
    pub poll: Option<String>,
    /// use a different shell
    #[argh(option, long = "shell")]
    pub shell: Option<String>,
    /// shorthand for '--shell=none'
    #[argh(switch, short = 'n')]
    pub n: bool,
    /// configure event emission
    #[argh(option, long = "emit-events-to")]
    pub emit_events_to: Option<String>,
    /// only emit events to stdout, run no commands.
    #[argh(switch, long = "only-emit-events")]
    pub only_emit_events: bool,
    /// add env vars to the command
    #[argh(option, long = "env", short = 'E')]
    pub env: Vec<String>,
    /// configure how the process is wrapped
    #[argh(option, long = "wrap-process")]
    pub wrap_process: Option<String>,
    /// alert when commands start and end
    #[argh(switch, long = "notify", short = 'N')]
    pub notify: bool,
    /// when to use terminal colours
    #[argh(option, long = "color")]
    pub color: Option<String>,
    /// print how long the command took to run
    #[argh(switch, long = "timings")]
    pub timings: bool,
    /// don't print starting and stopping messages
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// ring the terminal bell on command completion
    #[argh(switch, long = "bell")]
    pub bell: bool,
    /// set the project origin
    #[argh(option, long = "project-origin")]
    pub project_origin: Option<String>,
    /// set the working directory
    #[argh(option, long = "workdir")]
    pub workdir: Option<String>,
    /// filename extensions to filter to
    #[argh(option, long = "exts", short = 'e')]
    pub exts: Vec<String>,
    /// filename patterns to filter to
    #[argh(option, long = "filter", short = 'f')]
    pub filter: Vec<String>,
    /// files to load filters from
    #[argh(option, long = "filter-file")]
    pub filter_file: Vec<String>,
    /// experimental] Filter programs.
    #[argh(option, long = "filter-prog", short = 'J')]
    pub filter_prog: Vec<String>,
    /// filename patterns to filter out
    #[argh(option, long = "ignore", short = 'i')]
    pub ignore: Vec<String>,
    /// files to load ignores from
    #[argh(option, long = "ignore-file")]
    pub ignore_file: Vec<String>,
    /// filesystem events to filter to
    #[argh(option, long = "fs-events")]
    pub fs_events: Vec<String>,
    /// don't emit fs events for metadata changes
    #[argh(switch, long = "no-meta")]
    pub no_meta: bool,
    /// print events that trigger actions
    #[argh(switch, long = "print-events")]
    pub print_events: bool,
    /// show the manual page
    #[argh(switch, long = "manual")]
    pub manual: bool,
    /// tasks to run
    #[argh(positional)]
    pub task: String,
    /// task and arguments to run
    #[argh(positional)]
    pub args: Vec<String>,
}

/// display the installation path for a tool
#[derive(FromArgs)]
#[argh(subcommand, name = "where")]
pub struct WhereArgs {
    /// tool(s) to look up
    #[argh(positional)]
    pub tool_version: String,
    /// the version prefix to use when querying the latest version
    #[argh(positional)]
    pub asdf_version: Option<String>,
}

/// shows the path that a tool's bin points to.
#[derive(FromArgs)]
#[argh(subcommand, name = "which")]
pub struct WhichArgs {
    /// use a specific tool@version
    #[argh(option, long = "tool", short = 't')]
    pub tool: Option<String>,
    /// complete
    #[argh(switch, long = "complete")]
    pub complete: bool,
    /// show the plugin name instead of the path
    #[argh(switch, long = "plugin")]
    pub plugin: bool,
    /// show the version instead of the path
    #[argh(switch, long = "version")]
    pub version: bool,
    /// the bin to look up
    #[argh(positional)]
    pub bin_name: Option<String>,
}

/// mise
#[derive(FromArgs)]
pub struct Cli {
    /// continue running tasks even if one fails
    #[argh(switch, long = "continue-on-error", short = 'c')]
    pub continue_on_error: bool,
    /// change directory before running command
    #[argh(option, long = "cd", short = 'C')]
    pub cd: Option<String>,
    /// set the environment for loading `mise.<ENV>.toml`
    #[argh(option, long = "env", short = 'E')]
    pub env: Vec<String>,
    /// force the operation
    #[argh(switch, long = "force", short = 'f')]
    pub force: bool,
    /// how many jobs to run in parallel; values below 1 are treated as 1 [default: 8]
    #[argh(option, long = "jobs", short = 'j')]
    pub jobs: Option<String>,
    /// dry run, don't actually do anything
    #[argh(switch, long = "dry-run", short = 'n')]
    pub dry_run: bool,
    /// set the profile (environment)
    #[argh(option, long = "profile", short = 'P')]
    pub profile: Vec<String>,
    /// suppress non-error messages
    #[argh(switch, long = "quiet", short = 'q')]
    pub quiet: bool,
    /// shell
    #[argh(option, long = "shell", short = 's')]
    pub shell: Option<String>,
    /// tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10
    #[argh(option, long = "tool", short = 't')]
    pub tool: Vec<String>,
    /// show extra output (use -vv for even more)
    #[argh(switch, long = "verbose", short = 'v')]
    pub verbose: u8,
    /// version
    #[argh(switch, long = "version", short = 'V')]
    pub version: bool,
    /// answer yes to all confirmation prompts
    #[argh(switch, long = "yes", short = 'y')]
    pub yes: bool,
    /// sets log level to debug
    #[argh(switch, long = "debug")]
    pub debug: bool,
    /// log_level
    #[argh(option, long = "log-level")]
    pub log_level: Option<String>,
    /// do not load any config files
    #[argh(switch, long = "no-config")]
    pub no_config: bool,
    /// do not load environment variables from config files
    #[argh(switch, long = "no-env")]
    pub no_env: bool,
    /// do not execute hooks from config files
    #[argh(switch, long = "no-hooks")]
    pub no_hooks: bool,
    /// hides elapsed time after each task completes
    #[argh(switch, long = "no-timings")]
    pub no_timings: bool,
    /// output
    #[argh(option, long = "output")]
    pub output: Option<String>,
    /// read/write directly to stdin/stdout/stderr instead of by line
    #[argh(switch, long = "raw")]
    pub raw: bool,
    /// require lockfile URLs to be present during installation
    #[argh(switch, long = "locked")]
    pub locked: bool,
    /// suppress all task output and mise non-error messages
    #[argh(switch, long = "silent")]
    pub silent: bool,
    /// shows elapsed time after each task completes
    #[argh(switch, long = "timings")]
    pub timings: bool,
    /// sets log level to trace
    #[argh(switch, long = "trace")]
    pub trace: bool,
    #[argh(subcommand)]
    /// subcommand
    pub command: Option<Commands>,
}

#[derive(FromArgs)]
#[argh(subcommand)]
pub enum Commands {
    /// initializes mise in the current shell session
    Activate(ActivateArgs),
    /// manage tool version aliases.
    ToolAlias(ToolAliasArgs),
    /// internal] simulates asdf for plugins that call "asdf" internally
    Asdf(AsdfArgs),
    /// manage backends
    Backends(BackendsArgs),
    /// list all the active runtime bin paths
    BinPaths(BinPathsArgs),
    /// set up a machine for the current config in one command
    Bootstrap(BootstrapArgs),
    /// manage the mise cache
    Cache(CacheArgs),
    /// generate shell completions
    Completion(CompletionArgs),
    /// manage config files
    Config(ConfigArgs),
    /// shows current active and installed runtime versions
    Current(CurrentArgs),
    /// disable mise for current shell session
    Deactivate(DeactivateArgs),
    /// output direnv function to use mise inside direnv
    Direnv(DirenvArgs),
    /// manage dotfiles from `[dotfiles]` (deprecated)
    Dotfiles(DotfilesArgs),
    /// check mise installation for possible problems
    Doctor(DoctorArgs),
    /// starts a new shell with the mise environment built from the current configuration
    En(EnArgs),
    /// exports env vars to activate mise a single time
    Env(EnvArgs),
    /// execute a command with tool(s) set
    Exec(ExecArgs),
    /// formats mise.toml
    Fmt(FmtArgs),
    /// generate files for various tools/services
    Generate(GenerateArgs),
    /// gitHub related commands
    Github(GithubArgs),
    /// sets/gets the global tool version(s)
    Global(GlobalArgs),
    /// internal] called by activate hook to update env vars directory change
    HookEnv(HookEnvArgs),
    /// internal] called by shell when a command is not found
    HookNotFound(HookNotFoundArgs),
    /// removes mise CLI and all related data
    Implode(ImplodeArgs),
    /// edit mise.toml interactively
    Edit(EditArgs),
    /// install a tool version
    Install(InstallArgs),
    /// install a tool version to a specific path
    InstallInto(InstallIntoArgs),
    /// gets the latest available version for a plugin
    Latest(LatestArgs),
    /// symlinks a tool version into mise
    Link(LinkArgs),
    /// sets/gets tool version in local .tool-versions or mise.toml
    Local(LocalArgs),
    /// update lockfile checksums and URLs for all specified platforms
    Lock(LockArgs),
    /// list installed and active tool versions
    Ls(LsArgs),
    /// list runtime versions available for install.
    LsRemote(LsRemoteArgs),
    /// run Model Context Protocol (MCP) server
    Mcp(McpArgs),
    /// experimental] Build OCI container images from a mise.toml
    Oci(OciArgs),
    /// shows outdated tool versions
    Outdated(OutdatedArgs),
    /// show the individuals supporting mise as Patron-tier members
    Patrons(PatronsArgs),
    /// manage plugins
    Plugins(PluginsArgs),
    /// experimental] Manage project dependencies
    Deps(DepsArgs),
    /// delete unused versions of tools
    Prune(PruneArgs),
    /// list available tools to install
    Registry(RegistryArgs),
    /// internal command to generate markdown from help
    RenderHelp(RenderHelpArgs),
    /// creates new shims based on bin paths from currently installed tools.
    Reshim(ReshimArgs),
    /// run task(s)
    Run(RunArgs),
    /// search for tools in the registry
    Search(SearchArgs),
    /// updates mise itself.
    SelfUpdate(SelfUpdateArgs),
    /// set environment variables in mise.toml
    Set(SetArgs),
    /// manage settings
    Settings(SettingsArgs),
    /// sets a tool version for the current session.
    Shell(ShellArgs),
    /// manage shell aliases.
    ShellAlias(ShellAliasArgs),
    /// show the companies sponsoring mise and the jdx.dev open source tools
    Sponsors(SponsorsArgs),
    /// synchronize tools from other version managers with mise
    Sync(SyncArgs),
    /// manage tasks
    Tasks(TasksArgs),
    /// test a tool installs and executes
    TestTool(TestToolArgs),
    /// display git provider tokens mise will use
    Token(TokenArgs),
    /// gets information about a tool
    Tool(ToolArgs),
    /// execute a tool stub
    ToolStub(ToolStubArgs),
    /// marks a config file as trusted
    Trust(TrustArgs),
    /// removes installed tool versions
    Uninstall(UninstallArgs),
    /// remove environment variable(s) from the config file.
    Unset(UnsetArgs),
    /// remove explicit trust for a config
    Untrust(UntrustArgs),
    /// removes installed tool versions from mise.toml
    Unuse(UnuseArgs),
    /// upgrades outdated tools
    Upgrade(UpgradeArgs),
    /// generate a usage CLI spec
    Usage(UsageArgs),
    /// installs a tool and adds the version to mise.toml.
    Use(UseArgs),
    /// display the version of mise
    Version(VersionArgs),
    /// run task(s) and watch for changes to rerun it
    Watch(WatchArgs),
    /// display the installation path for a tool
    Where(WhereArgs),
    /// shows the path that a tool's bin points to.
    Which(WhichArgs),
}
