//! A shadow of `pitchfork.usage.kdl` in usage'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 usage_derive::{Args, Cli, Subcommands, ValueEnum};

/// Activate pitchfork in your shell session
///
/// Generates shell code that enables automatic daemon management when changing directories. Required for auto-start/stop features in pitchfork.toml.
///
/// Supported shells: bash, zsh, fish
///
/// Add to your shell config:
///
///     bash (~/.bashrc):
///       eval "$(pitchfork activate bash)"
///
///     zsh (~/.zshrc):
///       eval "$(pitchfork activate zsh)"
///
///     fish (~/.config/fish/config.fish):
///       pitchfork activate fish | source
#[derive(Args)]
#[usage(effect = "read")]
pub struct ActivateArgs {
    /// Shell to activate (bash, zsh, fish)
    #[usage(arg, name = "SHELL", value_enum)]
    pub shell: ActivateShellValue,
}

#[derive(ValueEnum)]
pub enum ActivateShellValue {
    #[usage(name = "bash")]
    Bash,
    #[usage(name = "zsh")]
    Zsh,
    #[usage(name = "fish")]
    Fish,
}

/// Generate JSON documentation for the web API endpoints
#[derive(Args)]
#[usage(effect = "read")]
pub struct ApiSchemaArgs {}

/// Enable boot start for pitchfork supervisor
///
/// Registers pitchfork to start automatically when the system boots.
///
/// When run as root (or via sudo): creates a system-level entry
///
///     macOS: /Library/LaunchDaemons/pitchfork.plist
///     Linux: /etc/systemd/system/pitchfork.service
///
/// When run as a normal user: creates a user-level entry
///
///     macOS: ~/Library/LaunchAgents/pitchfork.plist
///     Linux: ~/.config/systemd/user/pitchfork.service
///
/// If you want the supervisor to run as root but keep state files and IPC sockets under a specific user's home directory, configure `settings.supervisor.user` in your pitchfork configuration.
#[derive(Args)]
#[usage(effect = "write")]
pub struct BootEnableArgs {}

/// Disable boot start for pitchfork supervisor
///
/// Removes the boot start registration. Pitchfork will no longer start automatically on system boot.
#[derive(Args)]
#[usage(effect = "write")]
pub struct BootDisableArgs {}

/// Check boot start status
///
/// Reports whether pitchfork is configured to start on system boot.
#[derive(Args)]
#[usage(effect = "read")]
pub struct BootStatusArgs {}

/// Enable or disable boot start
///
/// Manages whether pitchfork supervisor starts automatically when the system boots. Uses platform-specific mechanisms (launchd on macOS, systemd on Linux).
///
/// When run as root (or via sudo), registers a system-level entry that starts pitchfork for all users:
///
///     macOS: /Library/LaunchDaemons/pitchfork.plist
///     Linux: /etc/systemd/system/pitchfork.service
///
/// When run as a normal user, registers a user-level entry:
///
///     macOS: ~/Library/LaunchAgents/pitchfork.plist
///     Linux: ~/.config/systemd/user/pitchfork.service
///
/// To run the supervisor as root but keep state files and IPC sockets in a specific user's home directory, set `settings.supervisor.user` in the global pitchfork configuration (~/.config/pitchfork/config.toml or /etc/pitchfork/config.toml).
///
/// Subcommands:
///
///     enable    Register pitchfork to start on boot
///     disable   Remove pitchfork from boot startup
///     status    Check if boot start is currently enabled
///
/// Examples:
///
///     pitchfork boot enable           Start pitchfork on system boot (user-level)
///     sudo pitchfork boot enable      Start pitchfork on system boot (system-level)
///     pitchfork boot disable          Don't start pitchfork on boot
///     pitchfork boot status           Check boot start status
#[derive(Args)]
#[usage(effect = "read")]
pub struct BootArgs {
    #[usage(subcommand)]
    pub command: BootCommands,
}

#[derive(Subcommands)]
pub enum BootCommands {
    /// Enable boot start for pitchfork supervisor
    #[usage(name = "enable")]
    Enable(Box<BootEnableArgs>),
    /// Disable boot start for pitchfork supervisor
    #[usage(name = "disable")]
    Disable(Box<BootDisableArgs>),
    /// Check boot start status
    #[usage(name = "status")]
    Status(Box<BootStatusArgs>),
}

#[derive(Args)]
#[usage(effect = "read")]
pub struct CdArgs {
    #[usage(long = "shell-pid", value_name = "SHELL_PID")]
    pub shell_pid: ::std::string::String,
}

/// Removes stopped/failed daemons from `pitchfork list`
///
/// Cleans up the daemon list by removing entries for daemons that are no longer running. Does not affect running daemons or their configurations.
///
/// Use this to clear out old entries after stopping daemons manually or after daemons have failed.
///
/// Examples:
///
///     pitchfork clean                 Remove all stopped/failed entries
///     pitchfork clean my-worktree     Remove entries in one namespace
///     pitchfork clean --daemon api    Remove the local namespace's api entry
///     pitchfork clean --prune         Remove entries whose directories disappeared
///     pitchfork c                     Alias for 'clean'
#[derive(Args)]
#[usage(effect = "write")]
pub struct CleanArgs {
    /// Only clean these daemons (repeatable; bare names use the current namespace)
    #[usage(long = "daemon", value_name = "ID", var)]
    pub daemon: ::std::vec::Vec<::std::string::String>,
    /// Only clean registrations whose working directories no longer exist
    #[usage(long = "prune")]
    pub prune: bool,
    /// Only clean daemon registrations in these namespaces
    #[usage(arg, name = "NAMESPACE")]
    pub namespace: ::std::vec::Vec<::std::string::String>,
}

/// Add a new daemon to pitchfork.toml
///
/// Creates a new daemon configuration section in the pitchfork.toml file. The daemon will be added to the nearest pitchfork.toml found in the filesystem hierarchy starting from the current directory.
///
/// Examples:
///
///     pitchfork daemons add api bun run server
///                                      Add daemon using positional args
///     pitchfork daemons add api --run 'npm start'
///                                      Add daemon with explicit run command
///     pitchfork daemons add api -- bun run server
///                                      Add daemon with explicit args after --
///     pitchfork daemons add api --run 'npm start' --retry 3
///                                      Add with retry policy
///     pitchfork daemons add api --run 'npm start' --watch 'src/**/*.ts'
///                                      Add with file watching
///     pitchfork daemons add api --run 'npm start' --autostart --autostop
///                                      Add with auto start/stop hooks
///     pitchfork daemons add worker --run './worker' --depends api
///                                      Add with daemon dependency
///     pitchfork daemons add api --run 'npm start' --local
///                                    Add to pitchfork.local.toml instead
///     pitchfork daemons add api --run 'npm start' --global
///                                   Add to ~/.config/pitchfork/config.toml instead
///     pitchfork daemons add worker --run './worker' --cron-schedule '0 * * * *' --cron-immediate
///                                   Add cron daemon that triggers immediately
#[derive(Args)]
#[usage(effect = "write")]
pub struct DaemonsAddArgs {
    /// Command to run (can also use positional args)
    #[usage(long = "run", value_name = "RUN")]
    pub run: ::std::option::Option<::std::string::String>,
    /// Number of retry attempts on failure (use \"true\" for infinite)
    #[usage(long = "retry", value_name = "RETRY")]
    pub retry: ::std::option::Option<::std::string::String>,
    /// Glob patterns to watch for changes (can be specified multiple times)
    #[usage(long = "watch", value_name = "WATCH", var)]
    pub watch: ::std::vec::Vec<::std::string::String>,
    /// Working directory for the daemon
    #[usage(long = "dir", value_name = "DIR")]
    pub dir: ::std::option::Option<::std::string::String>,
    /// Environment variables in KEY=value format (can be specified multiple times)
    #[usage(long = "env", value_name = "ENV", var)]
    pub env: ::std::vec::Vec<::std::string::String>,
    /// Delay in seconds before considering daemon ready
    #[usage(long = "ready-delay", value_name = "READY_DELAY")]
    pub ready_delay: ::std::option::Option<::std::string::String>,
    /// Regex pattern to match in output for readiness
    #[usage(long = "ready-output", value_name = "READY_OUTPUT")]
    pub ready_output: ::std::option::Option<::std::string::String>,
    /// HTTP endpoint URL to poll for readiness
    #[usage(long = "ready-http", value_name = "READY_HTTP")]
    pub ready_http: ::std::option::Option<::std::string::String>,
    /// TCP port to check for readiness (a number or Tera template)
    #[usage(long = "ready-port", value_name = "READY_PORT")]
    pub ready_port: ::std::option::Option<::std::string::String>,
    /// Shell command to poll for readiness
    #[usage(long = "ready-cmd", value_name = "READY_CMD")]
    pub ready_cmd: ::std::option::Option<::std::string::String>,
    /// Ports the daemon is expected to bind to (can be specified multiple times or comma-separated)
    #[usage(
        long = "expected-port",
        delimiter = ',',
        value_name = "EXPECTED_PORT",
        var
    )]
    pub expected_port: ::std::vec::Vec<::std::string::String>,
    /// Automatically find an available port if the expected port is in use
    #[usage(long = "bump", value_optional, value_name = "BUMP")]
    pub bump: ::std::option::Option<::std::option::Option<::std::string::String>>,
    /// Daemon dependencies that must start first (can be specified multiple times)
    #[usage(long = "depends", value_name = "DEPENDS", var)]
    pub depends: ::std::vec::Vec<::std::string::String>,
    /// Start this daemon automatically on system boot
    #[usage(long = "boot-start")]
    pub boot_start: bool,
    /// Autostart the daemon when entering the directory
    #[usage(long = "autostart")]
    pub autostart: bool,
    /// Autostop the daemon when leaving the directory
    #[usage(long = "autostop")]
    pub autostop: bool,
    /// Command to run when daemon becomes ready
    #[usage(long = "on-ready", value_name = "ON_READY")]
    pub on_ready: ::std::option::Option<::std::string::String>,
    /// Command to run when daemon fails
    #[usage(long = "on-fail", value_name = "ON_FAIL")]
    pub on_fail: ::std::option::Option<::std::string::String>,
    /// Command to run before each retry attempt
    #[usage(long = "on-retry", value_name = "ON_RETRY")]
    pub on_retry: ::std::option::Option<::std::string::String>,
    /// Command to run when the daemon is explicitly stopped by pitchfork
    #[usage(long = "on-stop", value_name = "ON_STOP")]
    pub on_stop: ::std::option::Option<::std::string::String>,
    /// Command to run on any daemon termination (clean exit, crash, or stop)
    #[usage(long = "on-exit", value_name = "ON_EXIT")]
    pub on_exit: ::std::option::Option<::std::string::String>,
    /// Cron schedule expression (6 fields: second minute hour day month weekday)
    #[usage(long = "cron-schedule", value_name = "CRON_SCHEDULE")]
    pub cron_schedule: ::std::option::Option<::std::string::String>,
    /// Cron retrigger behavior: finish, always, success, fail
    #[usage(long = "cron-retrigger", value_name = "CRON_RETRIGGER")]
    pub cron_retrigger: ::std::option::Option<::std::string::String>,
    /// Trigger cron immediately on first check (default: deferred until next scheduled time)
    #[usage(long = "cron-immediate")]
    pub cron_immediate: bool,
    /// Write to pitchfork.local.toml instead of pitchfork.toml
    #[usage(long = "local")]
    pub local: bool,
    /// Write to pitchfork.toml explicitly (default if no flag specified)
    #[usage(long = "project")]
    pub project: bool,
    /// Write to the user-level global config (~/.config/pitchfork/config.toml)
    #[usage(long = "global")]
    pub global: bool,
    /// ID of the daemon to add (e.g., "api" or "namespace/api")
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
    /// Arguments to pass to the daemon (alternative to --run)
    #[usage(arg, name = "ARGS", double_dash = "automatic")]
    pub args: ::std::vec::Vec<::std::string::String>,
}

/// Remove a daemon from a pitchfork config file
#[derive(Args)]
#[usage(effect = "destructive")]
pub struct DaemonsRemoveArgs {
    /// Remove from pitchfork.local.toml instead of pitchfork.toml
    #[usage(long = "local")]
    pub local: bool,
    /// Remove from pitchfork.toml explicitly (default if no flag specified)
    #[usage(long = "project")]
    pub project: bool,
    /// Remove from the user-level global config (~/.config/pitchfork/config.toml)
    #[usage(long = "global")]
    pub global: bool,
    /// The ID of the daemon to remove (e.g., "api" or "namespace/api")
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
}

/// List configured daemons from all merged config files.
#[derive(Args)]
#[usage(effect = "read")]
pub struct DaemonsArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
    #[usage(subcommand)]
    pub command: ::std::option::Option<DaemonsCommands>,
}

#[derive(Subcommands)]
pub enum DaemonsCommands {
    /// Add a new daemon to pitchfork.toml
    #[usage(name = "add", alias = "a")]
    Add(Box<DaemonsAddArgs>),
    /// Remove a daemon from a pitchfork config file
    #[usage(name = "remove", alias = "rm")]
    Remove(Box<DaemonsRemoveArgs>),
}

/// Generates shell completion scripts
///
/// Creates self-contained tab-completion scripts for your shell.
///
/// Supported shells: bash, zsh, fish
///
/// Installation:
///
///     bash:
///       pitchfork completion bash > ~/.local/share/bash-completion/completions/pitchfork
///
///     zsh:
///       pitchfork completion zsh > ~/.zfunc/_pitchfork
///
///     fish:
///       pitchfork completion fish > ~/.config/fish/completions/pitchfork.fish
#[derive(Args)]
#[usage(effect = "read")]
pub struct CompletionArgs {
    /// Shell to generate completions for (bash, zsh, fish)
    #[usage(arg, name = "SHELL", value_enum)]
    pub shell: CompletionShellValue,
}

#[derive(ValueEnum)]
pub enum CompletionShellValue {
    #[usage(name = "bash")]
    Bash,
    #[usage(name = "zsh")]
    Zsh,
    #[usage(name = "fish")]
    Fish,
}

/// Prevent a daemon from restarting
///
/// Disables a daemon to prevent it from being started automatically or manually. The daemon will remain disabled until `pitchfork enable` is called. Useful for temporarily stopping a service without removing it from config.
///
/// Examples:
///
///     pitchfork disable api           Prevent daemon from starting
///     pitchfork d api                 Alias for 'disable'
///     pitchfork list                  Shows 'disabled' status in output
#[derive(Args)]
#[usage(effect = "write")]
pub struct DisableArgs {
    /// Name of the daemon to disable
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
}

/// Allow a daemon to start
///
/// Re-enables a previously disabled daemon, allowing it to be started manually or automatically. Use this after `pitchfork disable` to restore normal operation.
///
/// Examples:
///
///     pitchfork enable api            Enable a disabled daemon
///     pitchfork e api                 Alias for 'enable'
#[derive(Args)]
#[usage(effect = "write")]
pub struct EnableArgs {
    /// Name of the daemon to enable
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
}

/// List all daemons
///
/// Displays a table of all tracked daemons with their PIDs, status, whether they are disabled, and any error messages.
///
/// This command shows both: - Active daemons (currently running or stopped) - Available daemons (defined in config but not yet started)
///
/// Example:
///
///     pitchfork list
///     pitchfork ls                    Alias for 'list'
///     pitchfork list --hide-header    Output without column headers
///     pitchfork list --status running  Show only running daemons
///     pitchfork ls --status available --status stopped
///                                     Show daemons that are available OR stopped
///     pitchfork list --namespace frontend
///                                     Show only daemons in the 'frontend' namespace
///     pitchfork list --project        Show only the current project's daemons
///
/// Output:
///
///     Name    Status
///     api     running    https://api.localhost
///     worker  available
///     db      errored    exit code 127
#[derive(Args)]
#[usage(effect = "read")]
pub struct ListArgs {
    /// Hide the table header row
    #[usage(long = "hide-header")]
    pub hide_header: bool,
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
    /// Filter daemons by status (repeatable for OR logic)
    ///
    /// Values: running, stopped, waiting, stopping, failed, errored, available, disabled
    #[usage(long = "status", value_name = "STATUS", value_enum, var)]
    pub status: ::std::vec::Vec<ListStatusValue>,
    /// Only show daemons in this namespace (repeatable for OR logic)
    #[usage(long = "namespace", value_name = "NAMESPACE", var)]
    pub namespace: ::std::vec::Vec<::std::string::String>,
    /// Only show daemons in the current project's namespace
    ///
    /// The namespace is resolved from the current directory the same way short daemon IDs are: the nearest config file's namespace, falling back to 'global' when no config file is found.
    #[usage(long = "project")]
    pub project: bool,
}

#[derive(ValueEnum)]
pub enum ListStatusValue {
    #[usage(name = "running")]
    Running,
    #[usage(name = "stopped")]
    Stopped,
    #[usage(name = "waiting")]
    Waiting,
    #[usage(name = "stopping")]
    Stopping,
    #[usage(name = "failed")]
    Failed,
    #[usage(name = "errored")]
    Errored,
    #[usage(name = "available")]
    Available,
    #[usage(name = "disabled")]
    Disabled,
}

/// Reads a daemon's output on stdin and writes it to the log store
///
/// Spawned by the supervisor as a sibling of the daemon, holding the read end of the daemon's output pipe. Keeping the reader in its own process is what makes logging survive a supervisor crash: the pipe still has a reader, so the daemon is neither killed by SIGPIPE nor blocked, and no output is lost. Exits when the pipe reaches end of file, which happens once the daemon and every descendant holding the write end have gone.
#[derive(Args)]
#[usage(effect = "write")]
pub struct LogSinkArgs {
    /// Qualified id of the daemon whose output this is
    #[usage(long = "daemon-id", value_name = "DAEMON_ID")]
    pub daemon_id: ::std::string::String,
    /// Log format to parse lines with (`json`, `logfmt`, `auto`, or `text`)
    #[usage(long = "log-format", value_name = "LOG_FORMAT", default = "text")]
    pub log_format: ::std::option::Option<::std::string::String>,
    /// Regex whose first match means the daemon is ready
    ///
    /// Set for a daemon configured with `ready_output`. The supervisor cannot match it itself — this process holds the output — so the match is reported back over IPC.
    #[usage(long = "ready-pattern", value_name = "READY_PATTERN")]
    pub ready_pattern: ::std::option::Option<::std::string::String>,
    /// Token identifying the start attempt this sink belongs to
    ///
    /// Quoted back when reporting a match. The supervisor drops reports whose token is no longer current, so a sink still draining a failed attempt cannot mark that daemon's retry ready.
    #[usage(long = "relay-token", value_name = "RELAY_TOKEN", default = "0")]
    pub relay_token: ::std::option::Option<::std::string::String>,
    /// Report lines so the supervisor can fire the daemon's `on_output` hook
    ///
    /// Without `--output-filter` or `--output-regex` every line qualifies, which is what a hook with no pattern asks for.
    #[usage(long = "report-output")]
    pub report_output: bool,
    /// Only report lines containing this substring
    #[usage(long = "output-filter", value_name = "OUTPUT_FILTER")]
    pub output_filter: ::std::option::Option<::std::string::String>,
    /// Only report lines matching this regex
    #[usage(long = "output-regex", value_name = "OUTPUT_REGEX")]
    pub output_regex: ::std::option::Option<::std::string::String>,
    /// Shortest gap between reported lines, in milliseconds
    #[usage(
        long = "output-debounce-ms",
        value_name = "OUTPUT_DEBOUNCE_MS",
        default = "1000"
    )]
    pub output_debounce_ms: ::std::option::Option<::std::string::String>,
}

/// Displays logs for daemon(s)
///
/// Shows logs from managed daemons. Logs are stored in the pitchfork logs directory and include timestamps for filtering.
///
/// Examples:
///
///     pitchfork logs api              Show all logs for 'api' (paged if needed)
///     pitchfork logs api worker       Show logs for multiple daemons
///     pitchfork logs                  Show logs for all daemons
///     pitchfork logs api -n 50        Show last 50 lines
///     pitchfork logs api --follow     Follow logs in real-time
///     pitchfork logs api --since '2024-01-15 10:00:00'
///                                     Show logs since a specific time (forward)
///     pitchfork logs api --since '10:30:00'
///                                     Show logs since 10:30:00 today
///     pitchfork logs api --since '10:30' --until '12:00'
///                                     Show logs since 10:30:00 until 12:00:00 today
///     pitchfork logs api --since 5min Show logs from last 5 minutes
///     pitchfork logs api --raw        Output raw log lines without formatting
///     pitchfork logs api --raw -n 100 Output last 100 raw log lines
///     pitchfork logs api --clear      Delete logs for 'api'
///     pitchfork logs --clear          Delete logs for all daemons
#[derive(Args)]
#[usage(effect = "read")]
pub struct LogsArgs {
    /// Delete logs
    #[usage(long = "clear", short = 'c', effect = "destructive")]
    pub clear: bool,
    /// Show last N lines of logs
    ///
    /// Only applies when --since/--until is not used. Without this option, all logs are shown.
    #[usage(short = 'n', value_name = "N")]
    pub n: ::std::option::Option<::std::string::String>,
    /// Show logs in real-time
    #[usage(long = "tail", long = "follow", short = 't', short = 'f')]
    pub tail: bool,
    /// Show logs from this time
    ///
    /// Supports multiple formats: - Full datetime: "YYYY-MM-DD HH:MM:SS" or "YYYY-MM-DD HH:MM" - Time only: "HH:MM:SS" or "HH:MM" (uses today's date) - Relative time: "5min", "2h", "1d" (e.g., last 5 minutes)
    #[usage(long = "since", short = 's', value_name = "SINCE")]
    pub since: ::std::option::Option<::std::string::String>,
    /// Show logs until this time
    ///
    /// Supports multiple formats: - Full datetime: "YYYY-MM-DD HH:MM:SS" or "YYYY-MM-DD HH:MM" - Time only: "HH:MM:SS" or "HH:MM" (uses today's date)
    #[usage(long = "until", short = 'u', value_name = "UNTIL")]
    pub until: ::std::option::Option<::std::string::String>,
    /// Disable pager even in interactive terminal
    #[usage(long = "no-pager")]
    pub no_pager: bool,
    /// Output raw log lines without color or formatting
    #[usage(long = "raw")]
    pub raw: bool,
    /// Output in JSON format
    #[usage(long = "json", conflicts("--raw", "--tail"))]
    pub json: bool,
    /// Filter logs by case-insensitive substring (can be repeated)
    ///
    /// Multiple --grep options are combined with OR.
    #[usage(long = "grep", value_name = "GREP", var)]
    pub grep: ::std::vec::Vec<::std::string::String>,
    /// Filter logs by regular expression
    #[usage(long = "regex", value_name = "REGEX")]
    pub regex: ::std::option::Option<::std::string::String>,
    /// Make --grep matching case-sensitive
    #[usage(long = "case-sensitive")]
    pub case_sensitive: bool,
    /// Filter by minimum log level (error, warn, info, debug, trace)
    ///
    /// Shows entries at or above the given severity. For example, `--level warn` shows warn and error. Only effective for daemons with log_format json or logfmt.
    #[usage(long = "level", value_name = "LEVEL")]
    pub level: ::std::option::Option<::std::string::String>,
    /// Filter by structured field value (KEY=VALUE, can be repeated)
    ///
    /// Extracts the value from fields_json using json_extract($.KEY). Multiple --field options are combined with AND.
    #[usage(long = "field", value_name = "KEY=VALUE", var)]
    pub field: ::std::vec::Vec<::std::string::String>,
    /// Filter log entries with a jq expression
    ///
    /// Each log entry is serialized as a JSON object with fields: timestamp, daemon_id, message, level, msg, logger, fields. Entries for which the expression produces a truthy value are shown.
    #[usage(long = "jq", value_name = "EXPR")]
    pub jq: ::std::option::Option<::std::string::String>,
    /// Omit timestamps from log output
    #[usage(long = "no-timestamp")]
    pub no_timestamp: bool,
    /// Show only logs for the specified daemon(s)
    #[usage(arg, name = "ID")]
    pub id: ::std::vec::Vec<::std::string::String>,
}

/// Runs a Model Context Protocol (MCP) server over stdin/stdout
///
/// This command starts an MCP server that exposes pitchfork daemon management to AI assistants (Claude, Cursor, etc.) over stdin/stdout using JSON-RPC.
///
/// Typically used as a subprocess by an MCP-aware AI agent.
///
/// Examples:
///
///     # In claude_desktop_config.json or similar:
///     {
///         "mcpServers": {
///             "pitchfork": {
///                 "command": "pitchfork",
///                 "args": ["mcp"]
///             }
///         }
///     }
///
/// Tools provided:
///
///     pitchfork_status    List all daemons and their state
///     pitchfork_start     Start a named daemon
///     pitchfork_stop      Stop a named daemon
///     pitchfork_restart   Restart a named daemon
///     pitchfork_logs      Return recent log output for a daemon
#[derive(Args)]
#[usage(
    after_long_help = "Examples:\n\n    # Start the MCP server (used by AI assistant tools)\n    $ pitchfork mcp\n\n    # Claude Desktop configuration (claude_desktop_config.json):\n    {\n      \"mcpServers\": {\n        \"pitchfork\": {\n          \"command\": \"pitchfork\",\n          \"args\": [\"mcp\"]\n        }\n      }\n    }\n\n    # Interactive testing with JSON-RPC:\n    $ echo '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0\"}}}' | pitchfork mcp\n\n# Available tools:\n- pitchfork_status  - List all daemons and their state\n- pitchfork_start   - Start daemon(s) by name\n- pitchfork_stop    - Stop daemon(s) by name\n- pitchfork_restart - Restart daemon(s) by name\n- pitchfork_logs    - Return recent log output for daemon(s)\n"
)]
pub struct McpArgs {}

/// Install the proxy's self-signed TLS certificate into the system trust store
///
/// This command installs pitchfork's auto-generated TLS certificate into your system's trust store so that browsers and tools trust HTTPS proxy URLs without certificate warnings.
///
/// On macOS, this installs the certificate into the current user's login keychain. No `sudo` required.
///
/// On Linux, the appropriate CA certificate directory and update command are detected automatically based on the running distribution:
///   - Debian/Ubuntu: /usr/local/share/ca-certificates/ + update-ca-certificates
///   - RHEL/Fedora/CentOS: /etc/pki/ca-trust/source/anchors/ + update-ca-trust
///   - Arch Linux: /etc/ca-certificates/trust-source/anchors/ + trust extract-compat
///   - openSUSE: /etc/pki/trust/anchors/ + update-ca-certificates
///
/// This DOES require sudo on Linux.
///
/// Example:
///
/// ```text
/// pitchfork proxy trust
/// sudo pitchfork proxy trust    # Linux only
/// ```
#[derive(Args)]
#[usage(effect = "write")]
pub struct ProxyTrustArgs {
    /// Path to the certificate file to trust (defaults to pitchfork's auto-generated cert)
    #[usage(long = "cert", value_name = "CERT")]
    pub cert: ::std::option::Option<::std::string::String>,
}

/// Remove the proxy's TLS certificate from the system trust store
///
/// Removes the pitchfork CA certificate that was previously installed by `pitchfork proxy trust` or auto-trust.
///
/// On macOS, removes the certificate from the login keychain and system keychain. On Linux, removes the certificate from the distro-specific CA directory and runs the appropriate update command.
///
/// Example:
///
/// ```text
/// pitchfork proxy untrust
/// sudo pitchfork proxy untrust    # Linux only
/// ```
#[derive(Args)]
#[usage(effect = "write")]
pub struct ProxyUntrustArgs {
    /// Path to the certificate file (defaults to pitchfork's auto-generated cert)
    #[usage(long = "cert", value_name = "CERT")]
    pub cert: ::std::option::Option<::std::string::String>,
}

/// Show all registered slugs and their current state
///
/// Displays the proxy configuration and lists all slugs from the global config with their project directory, daemon name, and current status (running/stopped, port).
#[derive(Args)]
#[usage(effect = "read")]
pub struct ProxyStatusArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
}

/// Add a slug mapping to the global config
///
/// Registers a slug in ~/.config/pitchfork/config.toml that maps to a project directory and daemon name. The proxy uses this to route requests.
///
/// If --dir is not specified, uses the current directory. If --daemon is not specified, defaults to the slug name.
///
/// Example:
///
/// ```text
/// pitchfork proxy add api
/// pitchfork proxy add api --daemon server
/// pitchfork proxy add api --dir /home/user/my-api --daemon server
/// ```
#[derive(Args)]
#[usage(effect = "write")]
pub struct ProxyAddArgs {
    /// Project directory (defaults to current directory)
    #[usage(long = "dir", value_name = "DIR")]
    pub dir: ::std::option::Option<::std::string::String>,
    /// Daemon name within the project (defaults to slug name)
    #[usage(long = "daemon", value_name = "DAEMON")]
    pub daemon: ::std::option::Option<::std::string::String>,
    /// Namespace to associate with the slug. If not provided, derived from the project directory.
    #[usage(long = "namespace", value_name = "NAMESPACE")]
    pub namespace: ::std::option::Option<::std::string::String>,
    /// The slug name (used in proxy URLs, e.g. api → api.localhost)
    #[usage(arg, name = "SLUG")]
    pub slug: ::std::string::String,
}

/// Remove a slug mapping from the global config
///
/// Example:
///
/// ```text
/// pitchfork proxy remove api
/// ```
#[derive(Args)]
#[usage(effect = "destructive")]
pub struct ProxyRemoveArgs {
    /// The slug name to remove
    #[usage(arg, name = "SLUG")]
    pub slug: ::std::string::String,
}

/// Manage the pitchfork reverse proxy
///
/// The reverse proxy routes requests from stable slug-based URLs like `https://myapp.localhost` to the daemon's actual listening port (e.g. localhost:3000).
///
/// Slugs are defined in the global config (~/.config/pitchfork/config.toml) under [slugs]. Each slug maps to a project directory and daemon name.
///
/// Enable the proxy in your pitchfork.toml or settings:
///
///     [settings.proxy]
///     enable = true
///
/// Subcommands:
///
///     trust     Install the proxy's TLS certificate into the system trust store
///     untrust   Remove the proxy's TLS certificate from the system trust store
///     add       Add a slug mapping to the global config
///     remove    Remove a slug mapping from the global config
///     status    Show all registered slugs and their current state
#[derive(Args)]
#[usage(effect = "read")]
pub struct ProxyArgs {
    #[usage(subcommand)]
    pub command: ProxyCommands,
}

#[derive(Subcommands)]
pub enum ProxyCommands {
    /// Install the proxy's self-signed TLS certificate into the system trust store
    #[usage(name = "trust")]
    Trust(Box<ProxyTrustArgs>),
    /// Remove the proxy's TLS certificate from the system trust store
    #[usage(name = "untrust")]
    Untrust(Box<ProxyUntrustArgs>),
    /// Show all registered slugs and their current state
    #[usage(name = "status")]
    Status(Box<ProxyStatusArgs>),
    /// Add a slug mapping to the global config
    #[usage(name = "add")]
    Add(Box<ProxyAddArgs>),
    /// Remove a slug mapping from the global config
    #[usage(name = "remove", alias = "rm")]
    Remove(Box<ProxyRemoveArgs>),
}

/// Enter (or replace) a project session tied to a host process.
///
/// The host PID is required and is used by the supervisor to revoke the session automatically when the process dies (with a title match to guard against PID reuse).
///
/// On Windows, automatic revocation when the host process exits is not available (Git Bash PIDs are invisible to the process table); sessions must be ended with an explicit `project leave`.
#[derive(Args)]
#[usage(effect = "write")]
pub struct ProjectEnterArgs {
    /// Host process PID that owns the session. Required.
    #[usage(long = "pid", value_name = "PID")]
    pub pid: ::std::string::String,
    #[usage(
        help = "Project directory to associate with the session. Defaults to the current working directory and is canonicalized before tracking.",
        long_help = "Project directory to associate with the session. Defaults to the\ncurrent working directory and is canonicalized before tracking.",
        long = "directory",
        value_name = "DIRECTORY"
    )]
    pub directory: ::std::option::Option<::std::string::String>,
}

/// Leave a project session and evaluate its directory for autostop.
#[derive(Args)]
#[usage(effect = "write")]
pub struct ProjectLeaveArgs {
    /// Host process PID that owns the session.
    #[usage(long = "pid", value_name = "PID")]
    pub pid: ::std::string::String,
    #[usage(
        help = "Project directory the session was entered with. Defaults to the current working directory and is canonicalized before lookup. Must match the directory used at enter time.",
        long_help = "Project directory the session was entered with. Defaults to the\ncurrent working directory and is canonicalized before lookup. Must\nmatch the directory used at enter time.",
        long = "directory",
        value_name = "DIRECTORY"
    )]
    pub directory: ::std::option::Option<::std::string::String>,
}

#[derive(Args)]
#[usage(effect = "read")]
pub struct ProjectListArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
}

/// Project session management for IDE and workspace integrations.
#[derive(Args)]
#[usage(effect = "read")]
pub struct ProjectArgs {
    #[usage(subcommand)]
    pub command: ProjectCommands,
}

#[derive(Subcommands)]
pub enum ProjectCommands {
    /// Enter (or replace) a project session tied to a host process.
    #[usage(name = "enter")]
    Enter(Box<ProjectEnterArgs>),
    /// Leave a project session and evaluate its directory for autostop.
    #[usage(name = "leave")]
    Leave(Box<ProjectLeaveArgs>),
    /// List tracked project sessions.
    #[usage(
        name = "list",
        help = "List tracked project sessions.",
        long_help = "List tracked project sessions\n\nDisplays a table of active project sessions with their host PID, directory,\nliveness status, and recorded process title.\n\nExample:\n\n    pitchfork project list\n    pitchfork project list --json"
    )]
    List(Box<ProjectListArgs>),
}

/// Restarts a daemon (stops then starts it)
///
/// Equivalent to `start --force` - stops the daemon (SIGTERM) then starts it again from the pitchfork.toml configuration with dependency resolution.
///
/// Examples:
///
///     pitchfork restart api           Restart a single daemon
///     pitchfork restart api worker    Restart multiple daemons
///     pitchfork restart --group backend Restart all daemons in the 'backend' group
///     pitchfork restart --all         Restart all running daemons
///     pitchfork restart -l            Restart all local daemons in pitchfork.toml
///     pitchfork restart -g            Restart all global daemons in config.toml
///     pitchfork restart api --delay 5 Wait 5 seconds for daemon to be ready
#[derive(Args)]
pub struct RestartArgs {
    /// Restart all daemons in the named group
    #[usage(
        long = "group",
        conflicts("--local", "--global", "--all"),
        value_name = "GROUP"
    )]
    pub group: ::std::option::Option<::std::string::String>,
    /// Restart all running daemons
    #[usage(long = "all", short = 'a', conflicts("--local", "--global"))]
    pub all: bool,
    /// Restart all local daemons in pitchfork.toml
    #[usage(
        long = "local",
        long = "all-local",
        short = 'l',
        conflicts("--all", "--global")
    )]
    pub local: bool,
    /// Restart all global daemons in ~/.config/pitchfork/config.toml and /etc/pitchfork/config.toml
    #[usage(
        long = "global",
        long = "all-global",
        short = 'g',
        conflicts("--local", "--all")
    )]
    pub global: bool,
    /// Delay in seconds before considering daemon ready (default: 3 seconds)
    #[usage(long = "delay", value_name = "DELAY")]
    pub delay: ::std::option::Option<::std::string::String>,
    /// Wait until output matches this regex pattern before considering daemon ready
    #[usage(long = "output", value_name = "OUTPUT")]
    pub output: ::std::option::Option<::std::string::String>,
    /// Wait until HTTP endpoint returns 2xx status before considering daemon ready
    #[usage(long = "http", value_name = "HTTP")]
    pub http: ::std::option::Option<::std::string::String>,
    /// Wait until TCP port is listening before considering daemon ready
    #[usage(long = "port", value_name = "PORT")]
    pub port: ::std::option::Option<::std::string::String>,
    /// Shell command to poll for readiness (exit code 0 = ready)
    #[usage(long = "cmd", value_name = "CMD")]
    pub cmd: ::std::option::Option<::std::string::String>,
    /// Suppress startup log output
    #[usage(long = "quiet", short = 'q')]
    pub quiet: bool,
    /// ID of the daemon(s) to restart
    #[usage(arg, name = "ID", conflicts("--local", "--global", "--all"))]
    pub id: ::std::vec::Vec<::std::string::String>,
}

/// Runs a one-off daemon
///
/// Runs a command as a managed daemon without needing a pitchfork.toml. The daemon is tracked by pitchfork and can be monitored with `pitchfork status`.
///
/// Examples:
///
///     pitchfork run api -- npm run dev
///                                   Run npm as daemon named 'api'
///     pitchfork run api -f -- npm run dev
///                                   Force restart if 'api' is running
///     pitchfork run api --retry 3 -- ./server
///                                   Restart up to 3 times on failure
///     pitchfork run api -d 5 -- ./server
///                                   Wait 5 seconds for ready check
///     pitchfork run api -o 'Listening' -- ./server
///                                   Wait for output pattern before ready
///     pitchfork run api --http http://localhost:8080/health -- ./server
///                                   Wait for HTTP endpoint to return 2xx
///     pitchfork run api --port 8080 -- ./server
///                                   Wait for TCP port to be listening
#[derive(Args)]
pub struct RunArgs {
    /// Stop the daemon if it is already running
    #[usage(long = "force", short = 'f')]
    pub force: bool,
    /// Number of times to retry on error exit
    #[usage(long = "retry", value_name = "RETRY", default = "0")]
    pub retry: ::std::option::Option<::std::string::String>,
    /// Delay in seconds before considering daemon ready (default: 3 seconds)
    #[usage(long = "delay", short = 'd', value_name = "DELAY")]
    pub delay: ::std::option::Option<::std::string::String>,
    /// Wait until output matches this regex pattern before considering daemon ready
    #[usage(long = "output", short = 'o', value_name = "OUTPUT")]
    pub output: ::std::option::Option<::std::string::String>,
    /// Wait until HTTP endpoint returns 2xx status before considering daemon ready
    #[usage(long = "http", value_name = "HTTP")]
    pub http: ::std::option::Option<::std::string::String>,
    /// Wait until TCP port is listening before considering daemon ready
    #[usage(long = "port", value_name = "PORT")]
    pub port: ::std::option::Option<::std::string::String>,
    /// Port(s) the daemon is expected to bind to (can be specified multiple times or comma-separated)
    #[usage(
        long = "expected-port",
        delimiter = ',',
        value_name = "EXPECTED_PORT",
        var
    )]
    pub expected_port: ::std::vec::Vec<::std::string::String>,
    /// Automatically find an available port if the expected port is in use
    #[usage(long = "bump", value_optional, value_name = "BUMP")]
    pub bump: ::std::option::Option<::std::option::Option<::std::string::String>>,
    /// Shell command to poll for readiness (exit code 0 = ready)
    #[usage(long = "cmd", value_name = "CMD")]
    pub cmd: ::std::option::Option<::std::string::String>,
    /// Suppress startup log output
    #[usage(long = "quiet", short = 'q')]
    pub quiet: bool,
    /// Name of the daemon to run
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
    /// Command and arguments to run (after --)
    #[usage(arg, name = "RUN", double_dash = "required")]
    pub run: ::std::vec::Vec<::std::string::String>,
}

/// Generate JSON Schema for pitchfork.toml configuration
#[derive(Args)]
#[usage(effect = "read")]
pub struct SchemaArgs {}

/// List all available settings with types and defaults
#[derive(Args)]
#[usage(effect = "read")]
pub struct SettingsListArgs {
    /// Only show settings in a specific group (e.g., "general", "web", "supervisor")
    #[usage(long = "group", value_name = "GROUP")]
    pub group: ::std::option::Option<::std::string::String>,
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
}

/// Get the current value of a setting
#[derive(Args)]
#[usage(effect = "read")]
pub struct SettingsGetArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
    /// Setting key in dot notation (e.g., general.log_level, web.auto_start)
    #[usage(arg, name = "KEY")]
    pub key: ::std::string::String,
}

/// Set a setting value in a config file
#[derive(Args)]
#[usage(effect = "write")]
pub struct SettingsSetArgs {
    /// Write to the user-level global config (~/.config/pitchfork/config.toml)
    #[usage(long = "global")]
    pub global: bool,
    /// Write to the project-level pitchfork.local.toml (overrides pitchfork.toml)
    #[usage(long = "local")]
    pub local: bool,
    /// Write to the project-level pitchfork.toml (default if no flag specified)
    #[usage(long = "project")]
    pub project: bool,
    /// Setting key in dot notation (e.g., general.log_level, web.auto_start)
    #[usage(arg, name = "KEY")]
    pub key: ::std::string::String,
    /// Value to set (type must match the setting: string, integer, boolean, or duration)
    #[usage(arg, name = "VALUE")]
    pub value: ::std::string::String,
}

/// View and modify pitchfork settings
///
/// Settings can be configured in multiple ways (in order of precedence): 1. Environment variables (highest priority) 2. Project-level pitchfork.toml or pitchfork.local.toml in [settings] section 3. User-level ~/.config/pitchfork/config.toml in [settings] section 4. System-level /etc/pitchfork/config.toml in [settings] section 5. Built-in defaults (lowest priority)
///
/// Subcommands:
///
///     list    List all available settings with types and defaults
///     get     Get the current value of a setting
///     set     Set a setting value in a config file
///
/// Examples:
///
///     pitchfork settings                        Show all current settings
///     pitchfork settings list                   List all available settings
///     pitchfork settings get general.log_level  Get a specific setting
///     pitchfork settings set general.log_level debug
///     pitchfork settings set web.auto_start true --global
///     pitchfork settings set supervisor.stop_timeout 10s --local
///     pitchfork settings set supervisor.stop_timeout 10s --project
#[derive(Args)]
#[usage(effect = "read")]
pub struct SettingsArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
    #[usage(subcommand)]
    pub command: ::std::option::Option<SettingsCommands>,
}

#[derive(Subcommands)]
pub enum SettingsCommands {
    /// List all available settings with types and defaults
    #[usage(name = "list", alias = "ls")]
    List(Box<SettingsListArgs>),
    /// Get the current value of a setting
    #[usage(name = "get")]
    Get(Box<SettingsGetArgs>),
    /// Set a setting value in a config file
    #[usage(name = "set")]
    Set(Box<SettingsSetArgs>),
}

/// Show the companies sponsoring pitchfork and the jdx.dev open source tools
#[derive(Args)]
#[usage(effect = "read")]
pub struct SponsorsArgs {}

/// Starts a daemon from a pitchfork.toml file
///
/// Daemons are defined in pitchfork.toml with a `[daemons.<name>]` section. The command waits for the daemon to be ready before returning.
///
/// Examples:
///
///     pitchfork start api           Start a single daemon
///     pitchfork start api worker    Start multiple daemons
///     pitchfork start --group backend Start all daemons in the 'backend' group
///     pitchfork start -l            Start all local daemons in pitchfork.toml
///     pitchfork start -g            Start all global daemons in config.toml
///     pitchfork start -a            Start all daemons (local and global)
///     pitchfork start api -f        Restart daemon if already running
///     pitchfork start api --delay 5 Wait 5 seconds for daemon to be ready
///     pitchfork start api --output 'Listening on'
///                                   Wait for output pattern before ready
///     pitchfork start api --http http://localhost:8080/health
///                                   Wait for HTTP endpoint to return 2xx
///     pitchfork start api --port 8080
///                                   Wait for TCP port to be listening
#[derive(Args)]
pub struct StartArgs {
    /// Start all daemons in the named group
    #[usage(
        long = "group",
        conflicts("--local", "--global", "--all"),
        value_name = "GROUP"
    )]
    pub group: ::std::option::Option<::std::string::String>,
    /// Start all local daemons in pitchfork.toml
    #[usage(
        long = "local",
        long = "all-local",
        short = 'l',
        conflicts("--all", "--global")
    )]
    pub local: bool,
    /// Start all global daemons in ~/.config/pitchfork/config.toml and /etc/pitchfork/config.toml
    #[usage(
        long = "global",
        long = "all-global",
        short = 'g',
        conflicts("--local", "--all")
    )]
    pub global: bool,
    /// Start all daemons (both local and global)
    #[usage(long = "all", short = 'a', conflicts("--local", "--global"))]
    pub all: bool,
    #[usage(long = "shell-pid", hide, value_name = "SHELL_PID")]
    pub shell_pid: ::std::option::Option<::std::string::String>,
    /// Stop the daemon if it is already running
    #[usage(long = "force", short = 'f')]
    pub force: bool,
    /// Delay in seconds before considering daemon ready (default: 3 seconds)
    #[usage(long = "delay", value_name = "DELAY")]
    pub delay: ::std::option::Option<::std::string::String>,
    /// Wait until output matches this regex pattern before considering daemon ready
    #[usage(long = "output", value_name = "OUTPUT")]
    pub output: ::std::option::Option<::std::string::String>,
    /// Wait until HTTP endpoint returns 2xx status before considering daemon ready
    #[usage(long = "http", value_name = "HTTP")]
    pub http: ::std::option::Option<::std::string::String>,
    /// Wait until TCP port is listening before considering daemon ready
    #[usage(long = "port", value_name = "PORT")]
    pub port: ::std::option::Option<::std::string::String>,
    /// Shell command to poll for readiness (exit code 0 = ready)
    #[usage(long = "cmd", value_name = "CMD")]
    pub cmd: ::std::option::Option<::std::string::String>,
    /// Ports the daemon is expected to bind to (can be specified multiple times or comma-separated)
    #[usage(
        long = "expected-port",
        delimiter = ',',
        value_name = "EXPECTED_PORT",
        var
    )]
    pub expected_port: ::std::vec::Vec<::std::string::String>,
    /// Automatically find an available port if the expected port is in use
    #[usage(long = "bump", value_optional, value_name = "BUMP")]
    pub bump: ::std::option::Option<::std::option::Option<::std::string::String>>,
    /// Suppress startup log output
    #[usage(long = "quiet", short = 'q')]
    pub quiet: bool,
    /// ID of the daemon(s) in pitchfork.toml to start
    #[usage(arg, name = "ID", conflicts("--local", "--global", "--all"))]
    pub id: ::std::vec::Vec<::std::string::String>,
}

/// Display the status of a daemon
///
/// Shows detailed information about a single daemon including its PID and current status (running, stopped, failed, etc.).
///
/// Example:
///
///     pitchfork status api
///
/// Output:
///
///     Name: api
///     PID: 12345
///     Status: running
#[derive(Args)]
#[usage(effect = "read")]
pub struct StatusArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
    /// Name of the daemon to check
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
}

/// Sends a stop signal to a daemon
///
/// Uses a graceful shutdown strategy: 1. Send SIGTERM and wait up to ~3 seconds for the process to exit (fast 10ms checks initially, then 50ms) 2. If still running, send SIGKILL to force termination
///
/// Most processes will exit immediately after the first SIGTERM. The escalation ensures stubborn processes are eventually terminated while giving well-behaved processes time to clean up resources.
///
/// When using --all/--local/--global, daemons are stopped in reverse dependency order: dependents are stopped before the daemons they depend on.
///
/// Examples:
///
///     pitchfork stop api           Stop a single daemon
///     pitchfork stop api worker    Stop multiple daemons
///     pitchfork stop --group backend Stop all daemons in the 'backend' group
///     pitchfork stop --all         Stop all running daemons in dependency order
///     pitchfork stop -l            Stop all local daemons in pitchfork.toml
///     pitchfork stop -g            Stop all global daemons in config.toml
///     pitchfork kill api           Same as 'stop' (alias)
#[derive(Args)]
#[usage(effect = "write")]
pub struct StopArgs {
    /// Stop all daemons in the named group
    #[usage(
        long = "group",
        conflicts("--local", "--global", "--all"),
        value_name = "GROUP"
    )]
    pub group: ::std::option::Option<::std::string::String>,
    /// Stop all running daemons (in reverse dependency order)
    #[usage(long = "all", short = 'a', conflicts("--local", "--global"))]
    pub all: bool,
    /// Stop all local daemons in pitchfork.toml
    #[usage(
        long = "local",
        long = "all-local",
        short = 'l',
        conflicts("--all", "--global")
    )]
    pub local: bool,
    /// Stop all global daemons in ~/.config/pitchfork/config.toml and /etc/pitchfork/config.toml
    #[usage(
        long = "global",
        long = "all-global",
        short = 'g',
        conflicts("--local", "--all")
    )]
    pub global: bool,
    /// The name of the daemon(s) to stop
    #[usage(arg, name = "ID", conflicts("--local", "--global", "--all"))]
    pub id: ::std::vec::Vec<::std::string::String>,
}

/// Runs the internal pitchfork daemon in the foreground
#[derive(Args)]
pub struct SupervisorRunArgs {
    /// kill existing daemon
    #[usage(long = "force", short = 'f')]
    pub force: bool,
    /// run as boot start (auto-start boot_start daemons)
    #[usage(long = "boot")]
    pub boot: bool,
    /// Enable container/PID1 mode (reap zombies, forward signals)
    #[usage(long = "container", env = "PITCHFORK_CONTAINER")]
    pub container: bool,
    /// Enable web UI on specified port (tries up to 10 ports if in use)
    #[usage(long = "web-port", env = "PITCHFORK_WEB_PORT", value_name = "WEB_PORT")]
    pub web_port: ::std::option::Option<::std::string::String>,
    /// Serve web UI under a path prefix (e.g. "ps" serves at /ps/)
    #[usage(long = "web-path", env = "PITCHFORK_WEB_PATH", value_name = "WEB_PATH")]
    pub web_path: ::std::option::Option<::std::string::String>,
}

/// Starts the internal pitchfork daemon in the background
#[derive(Args)]
pub struct SupervisorStartArgs {
    /// kill existing daemon
    #[usage(long = "force", short = 'f')]
    pub force: bool,
}

/// Gets the status of the pitchfork daemon
#[derive(Args)]
#[usage(effect = "read")]
pub struct SupervisorStatusArgs {
    /// Output in JSON format
    #[usage(long = "json")]
    pub json: bool,
}

/// Stops the internal pitchfork daemon running in the background
#[derive(Args)]
#[usage(effect = "write")]
pub struct SupervisorStopArgs {}

/// Start, stop, and check the status of the pitchfork supervisor daemon
#[derive(Args)]
#[usage(effect = "read")]
pub struct SupervisorArgs {
    #[usage(subcommand)]
    pub command: SupervisorCommands,
}

#[derive(Subcommands)]
pub enum SupervisorCommands {
    /// Runs the internal pitchfork daemon in the foreground
    #[usage(name = "run")]
    Run(Box<SupervisorRunArgs>),
    /// Starts the internal pitchfork daemon in the background
    #[usage(name = "start")]
    Start(Box<SupervisorStartArgs>),
    /// Gets the status of the pitchfork daemon
    #[usage(name = "status")]
    Status(Box<SupervisorStatusArgs>),
    /// Stops the internal pitchfork daemon running in the background
    #[usage(name = "stop")]
    Stop(Box<SupervisorStopArgs>),
}

/// Launch the interactive TUI dashboard
///
/// Shows live daemon status with fuzzy search, sorting, batch operations, log viewing, and a config editor.
///
/// The dashboard can be scoped to one or more namespaces; the fuzzy search (`/`) then operates within the scoped set.
///
/// Example:
///
///     pitchfork tui
///     pitchfork tui --namespace frontend
///                                     Show only daemons in the 'frontend' namespace
///     pitchfork tui --project         Show only the current project's daemons
#[derive(Args)]
pub struct TuiArgs {
    /// Only show daemons in this namespace (repeatable for OR logic)
    #[usage(long = "namespace", value_name = "NAMESPACE", var)]
    pub namespace: ::std::vec::Vec<::std::string::String>,
    /// Only show daemons in the current project's namespace
    ///
    /// The namespace is resolved from the current directory the same way short daemon IDs are: the nearest config file's namespace, falling back to 'global' when no config file is found.
    #[usage(long = "project")]
    pub project: bool,
}

/// Generates a usage spec for the CLI
///
/// https://usage.jdx.dev
#[derive(Args)]
#[usage(effect = "read")]
pub struct UsageArgs {}

/// Wait for a daemon to stop, tailing the logs along the way
///
/// Blocks until the specified daemon stops running, while displaying its log output in real-time. Exits with the same status code as the daemon.
///
/// Useful in scripts that need to wait for a daemon to complete.
///
/// Examples:
///
///     pitchfork wait api              Wait for 'api' to stop
///     pitchfork w api                 Alias for 'wait'
///     pitchfork wait api && echo done Run command after daemon stops
#[derive(Args)]
#[usage(effect = "read")]
pub struct WaitArgs {
    /// The name of the daemon to wait for
    #[usage(arg, name = "ID")]
    pub id: ::std::string::String,
}

/// Daemons with DX
#[derive(Cli)]
#[usage(
    bin = "pitchfork",
    name = "pitchfork",
    version = "2.22.0",
    unknown_flags = "error",
    arg_required_else_help = true
)]
pub struct Cli {
    #[usage(subcommand)]
    pub command: Commands,
}

#[derive(Subcommands)]
pub enum Commands {
    /// Activate pitchfork in your shell session
    #[usage(name = "activate")]
    Activate(Box<ActivateArgs>),
    /// Generate JSON documentation for the web API endpoints
    #[usage(name = "api-schema", hide)]
    ApiSchema(Box<ApiSchemaArgs>),
    /// Enable or disable boot start
    #[usage(name = "boot")]
    Boot(Box<BootArgs>),
    #[usage(name = "cd", hide)]
    Cd(Box<CdArgs>),
    /// Removes stopped/failed daemons from `pitchfork list`
    #[usage(name = "clean", alias = "c")]
    Clean(Box<CleanArgs>),
    /// List configured daemons from all merged config files.
    #[usage(name = "daemons", alias = "daemon")]
    Daemons(Box<DaemonsArgs>),
    /// Generates shell completion scripts
    #[usage(name = "completion")]
    Completion(Box<CompletionArgs>),
    /// Prevent a daemon from restarting
    #[usage(name = "disable", alias = "d")]
    Disable(Box<DisableArgs>),
    /// Allow a daemon to start
    #[usage(name = "enable", alias = "e")]
    Enable(Box<EnableArgs>),
    /// List all daemons
    #[usage(name = "list", alias = "ls")]
    List(Box<ListArgs>),
    /// Reads a daemon's output on stdin and writes it to the log store
    #[usage(name = "log-sink", hide)]
    LogSink(Box<LogSinkArgs>),
    /// Displays logs for daemon(s)
    #[usage(name = "logs", alias = "l")]
    Logs(Box<LogsArgs>),
    /// Runs a Model Context Protocol (MCP) server over stdin/stdout
    #[usage(name = "mcp")]
    Mcp(Box<McpArgs>),
    /// Manage the pitchfork reverse proxy
    #[usage(name = "proxy")]
    Proxy(Box<ProxyArgs>),
    /// Project session management for IDE and workspace integrations.
    #[usage(name = "project")]
    Project(Box<ProjectArgs>),
    /// Restarts a daemon (stops then starts it)
    #[usage(name = "restart")]
    Restart(Box<RestartArgs>),
    /// Runs a one-off daemon
    #[usage(name = "run", alias = "r")]
    Run(Box<RunArgs>),
    /// Generate JSON Schema for pitchfork.toml configuration
    #[usage(name = "schema", hide)]
    Schema(Box<SchemaArgs>),
    /// View and modify pitchfork settings
    #[usage(name = "settings", alias = "setting")]
    Settings(Box<SettingsArgs>),
    /// Show the companies sponsoring pitchfork and the jdx.dev open source tools
    #[usage(name = "sponsors")]
    Sponsors(Box<SponsorsArgs>),
    /// Starts a daemon from a pitchfork.toml file
    #[usage(name = "start", alias = "s")]
    Start(Box<StartArgs>),
    /// Display the status of a daemon
    #[usage(name = "status", alias = "stat")]
    Status(Box<StatusArgs>),
    /// Sends a stop signal to a daemon
    #[usage(name = "stop", alias = "kill")]
    Stop(Box<StopArgs>),
    /// Start, stop, and check the status of the pitchfork supervisor daemon
    #[usage(name = "supervisor", alias = "sup")]
    Supervisor(Box<SupervisorArgs>),
    /// Launch the interactive TUI dashboard
    #[usage(name = "tui")]
    Tui(Box<TuiArgs>),
    /// Generates a usage spec for the CLI
    #[usage(name = "usage", hide)]
    Usage(Box<UsageArgs>),
    /// Wait for a daemon to stop, tailing the logs along the way
    #[usage(name = "wait", alias = "w")]
    Wait(Box<WaitArgs>),
}
