worktrunk 0.35.3

A CLI for Git worktree management, designed for parallel AI agent workflows
Documentation
use clap::Subcommand;

use super::config::ApprovalsCommand;

/// Run configured hooks
#[derive(Subcommand)]
pub enum HookCommand {
    /// Show configured hooks
    ///
    /// Lists user and project hooks. Project hooks show approval status (❓ = needs approval).
    Show {
        /// Hook type to show (default: all)
        #[arg(value_parser = ["pre-switch", "post-switch", "pre-start", "post-start", "pre-commit", "post-commit", "pre-merge", "post-merge", "pre-remove", "post-remove"])]
        hook_type: Option<String>,

        /// Show expanded commands with current variables
        #[arg(long)]
        expanded: bool,
    },

    /// Run pre-switch hooks
    ///
    /// Blocking — waits for completion before continuing.
    PreSwitch {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run post-switch hooks
    ///
    /// Background by default. Use `--foreground` to run in foreground for debugging.
    PostSwitch {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Run in foreground (block until complete)
        #[arg(long)]
        foreground: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run pre-start hooks
    ///
    /// Blocking — waits for completion before continuing.
    #[command(alias = "post-create")]
    PreStart {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run post-start hooks
    ///
    /// Background by default. Use `--foreground` to run in foreground for debugging.
    PostStart {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Run in foreground (block until complete)
        #[arg(long)]
        foreground: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run pre-commit hooks
    PreCommit {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run post-commit hooks
    ///
    /// Background by default. Use `--foreground` to run in foreground for debugging.
    PostCommit {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Run in foreground (block until complete)
        #[arg(long)]
        foreground: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run pre-merge hooks
    PreMerge {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run post-merge hooks
    ///
    /// Background by default. Use `--foreground` to run in foreground for debugging.
    PostMerge {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Run in foreground (block until complete)
        #[arg(long)]
        foreground: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run pre-remove hooks
    PreRemove {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Run post-remove hooks
    ///
    /// Background by default. Use `--foreground` to run in foreground for debugging.
    PostRemove {
        /// Filter by command name(s)
        ///
        /// Supports `user:name` or `project:name` to filter by source.
        /// `user:` alone runs all user hooks; `project:` alone runs all project hooks.
        #[arg(add = crate::completion::hook_command_name_completer())]
        name: Vec<String>,

        /// Skip approval prompts
        #[arg(short, long, help_heading = "Automation")]
        yes: bool,

        /// Show what would run without executing
        #[arg(long)]
        dry_run: bool,

        /// Run in foreground (block until complete)
        #[arg(long)]
        foreground: bool,

        /// Override built-in template variable (KEY=VALUE)
        #[arg(long = "var", value_name = "KEY=VALUE", value_parser = super::parse_key_val, action = clap::ArgAction::Append)]
        vars: Vec<(String, String)>,
    },

    /// Internal: run a serialized pipeline from stdin
    #[command(hide = true, name = "run-pipeline")]
    RunPipeline,

    /// Manage command approvals
    #[command(
        after_long_help = r#"Project hooks require approval on first run to prevent untrusted projects from running arbitrary commands.

## Examples

Pre-approve all commands for current project:
```console
$ wt hook approvals add
```

Clear approvals for current project:
```console
$ wt hook approvals clear
```

Clear global approvals:
```console
$ wt hook approvals clear --global
```

## How approvals work

Approved commands are saved to `~/.config/worktrunk/approvals.toml`. Re-approval is required when the command template changes or the project moves. Use `--yes` to bypass prompts in CI."#
    )]
    Approvals {
        #[command(subcommand)]
        action: ApprovalsCommand,
    },
}