#compdef dalfox

autoload -U is-at-least

_dalfox() {
    typeset -A opt_args
    typeset -a _arguments_options
    local ret=1

    if is-at-least 5.2; then
        _arguments_options=(-s -S -C)
    else
        _arguments_options=(-s -C)
    fi

    local context curcontext="$curcontext" state line
    _arguments "${_arguments_options[@]}" : \
'--config=[Path to a config file (TOML or JSON). Overrides default search path]:FILE:_default' \
'--debug[Enable debug logging (show DBG lines)]' \
'--no-color[Disable colored output (also respects NO_COLOR env var)]' \
'-S[Silence all logs except POC output to STDOUT]' \
'--silence[Silence all logs except POC output to STDOUT]' \
'-h[Print help]' \
'--help[Print help]' \
'-V[Print version]' \
'--version[Print version]' \
'::targets -- Targets (when no subcommand is provided, defaults to scan):_default' \
":: :_dalfox_commands" \
"*::: :->dalfox" \
&& ret=0
    case $state in
    (dalfox)
        words=($line[2] "${words[@]}")
        (( CURRENT += 1 ))
        curcontext="${curcontext%:*:*}:dalfox-command-$line[2]:"
        case $line[2] in
            (scan)
_arguments "${_arguments_options[@]}" : \
'-i+[Input type\: auto, url, file, pipe, raw-http, har]:INPUT_TYPE:_default' \
'--input-type=[Input type\: auto, url, file, pipe, raw-http, har]:INPUT_TYPE:_default' \
'--dedup-urls=[Target deduplication \[default\: exact\]\: exact (drop byte-identical URL+method), signature (also collapse URLs that differ only in parameter values — keys on method+host+path+parameter names), off (scan every input line)]:MODE:(exact signature off)' \
'-f+[Output format\: json, jsonl, plain, markdown, sarif, toml]:FORMAT:(plain json jsonl markdown sarif toml)' \
'--format=[Output format\: json, jsonl, plain, markdown, sarif, toml]:FORMAT:(plain json jsonl markdown sarif toml)' \
'-o+[Write output to a file. Example\: -o '\''output.txt'\'']:OUTPUT:_default' \
'--output=[Write output to a file. Example\: -o '\''output.txt'\'']:OUTPUT:_default' \
'--poc-type=[POC output type\: plain, curl, httpie, http-request]:POC_TYPE:(plain curl httpie http-request)' \
'--limit=[Limit the number of results to display (must be >=1). Example\: --limit 10]:LIMIT:_default' \
'--limit-result-type=[Filter which finding types count toward --limit\: all (default), v (vulnerable), r (reflected), a (AST DOM XSS), i (informational). Example\: --limit-result-type v]:LIMIT_RESULT_TYPE:(all v r a i V R A I)' \
'*--only-poc=[Filter output to show only specific finding types (comma-separated). Options\: v (vulnerable), r (reflected), a (AST DOM XSS), i (informational). Example\: --only-poc "v,r"]:ONLY_POC:(v r a i V R A I)' \
'--state-file=[Record which targets finished to PATH and skip them when the same scan is re-run, so an interrupted mass scan resumes instead of restarting. Only fully completed targets are skipped; ones cut short by Ctrl-C or --scan-timeout are retried. Example\: --state-file scan.state]:PATH:_default' \
'--baseline=[Diff against a previous dalfox JSON/JSONL report and report only findings new since it. The baseline is an ordinary \`--format json --output\` report. Example\: --baseline baseline.json]:BASELINE:_default' \
'--baseline-mode=[What --baseline does with already-known findings \[default\: filter\]\: filter (drop them, so the exit code gates on new findings only) or annotate (keep them and mark each \`new\`). Example\: --baseline-mode annotate]:MODE:(filter annotate)' \
'*-p+[Specify parameter names to analyze (e.g., -p sort -p id\:query). Types\: query, body, json, cookie, header]:PARAM:_default' \
'*--param=[Specify parameter names to analyze (e.g., -p sort -p id\:query). Types\: query, body, json, cookie, header]:PARAM:_default' \
'-d+[HTTP request body data]:DATA:_default' \
'--data=[HTTP request body data]:DATA:_default' \
'*-H+[HTTP headers (can be specified multiple times)]:HEADERS:_default' \
'*--headers=[HTTP headers (can be specified multiple times)]:HEADERS:_default' \
'*--cookies=[Cookies (can be specified multiple times)]:COOKIES:_default' \
'-X+[Override the HTTP method. Example\: -X '\''PUT'\'' (default "GET")]:METHOD:_default' \
'--method=[Override the HTTP method. Example\: -X '\''PUT'\'' (default "GET")]:METHOD:_default' \
'--user-agent=[Set a custom User-Agent header. Example\: --user-agent '\''Mozilla/5.0'\'']:USER_AGENT:_default' \
'--cookie-from-raw=[Load cookies from a raw HTTP request file. Example\: --cookie-from-raw '\''request.txt'\'']:COOKIE_FROM_RAW:_default' \
'--session-check=[Regex that must keep matching the response body for the session to be considered alive (e.g. --session-check '\''Sign out'\''). Authoritative\: when set, the built-in heuristics (401/403, login redirect, appearing login form) are not consulted. Without it, session monitoring still runs automatically whenever credentials are supplied via --cookies, --cookie-from-raw, or a Cookie/Authorization header]:REGEX:_default' \
'--session-check-url=[Probe this URL instead of the scan target when re-validating the session. Useful when the target itself is public but the app exposes a cheap authenticated endpoint. Example\: --session-check-url '\''https\://app/me'\'']:URL:_default' \
'--on-session-loss=[What to do when the session is detected as lost \[default\: abort\]\: abort stops the affected target and skips the rest of that host; continue keeps scanning. Either way the target is reported as \`incomplete\` / SESSION_LOST instead of a misleading "clean"]:POLICY:(abort continue)' \
'*--include-url=[Include only URLs matching these patterns (regex, can be specified multiple times)]:INCLUDE_URL:_default' \
'*--exclude-url=[Exclude URLs matching these patterns (regex, can be specified multiple times)]:EXCLUDE_URL:_default' \
'*--ignore-param=[Ignore specific parameters during scanning (can be specified multiple times)]:IGNORE_PARAM:_default' \
'*--out-of-scope=[Exclude targets whose domain matches these patterns (supports wildcards, e.g. *.dev.example.com)]:OUT_OF_SCOPE:_default' \
'--out-of-scope-file=[Load out-of-scope domains from a file (one per line, supports wildcards)]:OUT_OF_SCOPE_FILE:_default' \
'-W+[Dictionary analysis with wordlist file path]:MINING_DICT_WORD:_default' \
'--mining-dict-word=[Dictionary analysis with wordlist file path]:MINING_DICT_WORD:_default' \
'*--remote-wordlists=[Fetch remote parameter wordlists from providers (comma-separated). Options\: burp, assetnote]:REMOTE_WORDLISTS:_default' \
'--timeout=[Per-request timeout in seconds (network only; does not bound total scan time)]:TIMEOUT:_default' \
'--scan-timeout=[Hard wall-clock cap per target for the payload-injection (scan) stage in seconds. When set, dalfox stops a target'\''s payload-injection stage once this budget is exceeded — useful when many sequential phases each pay the per-request \`--timeout\` cost against a partially-hung endpoint. Scope note\: this caps ONLY the injection stage. The earlier preflight and parameter-analysis (discovery + mining) phases are bounded separately by \`--timeout\` × request-count, NOT by this wall-clock cap, so a slow target can overshoot this budget during analysis. 0 disables (default)]:SCAN_TIMEOUT:_default' \
'--delay=[Delay in milliseconds]:DELAY:_default' \
'-r+[Cap the global outbound request rate in requests/second, shared across all workers and targets (0 = unlimited). Unlike --delay (which only spaces a single worker'\''s requests), this bounds the total in-flight burst from workers × concurrent targets — friendlier to shared-IP / edge WAF thresholds. Example\: --rate-limit 20]:RATE_LIMIT:_default' \
'--rate-limit=[Cap the global outbound request rate in requests/second, shared across all workers and targets (0 = unlimited). Unlike --delay (which only spaces a single worker'\''s requests), this bounds the total in-flight burst from workers × concurrent targets — friendlier to shared-IP / edge WAF thresholds. Example\: --rate-limit 20]:RATE_LIMIT:_default' \
'--rl=[Cap the global outbound request rate in requests/second, shared across all workers and targets (0 = unlimited). Unlike --delay (which only spaces a single worker'\''s requests), this bounds the total in-flight burst from workers × concurrent targets — friendlier to shared-IP / edge WAF thresholds. Example\: --rate-limit 20]:RATE_LIMIT:_default' \
'--retries=[Retry failed requests on HTTP 5xx and transient transport errors (timeouts, connection resets) up to this many times (0 = off). HTTP 429 is always retried regardless of this value. Example\: --retries 2]:RETRIES:_default' \
'--retry-delay=[Base delay (ms) for the exponential backoff between retries (--retries). Doubles each attempt and is capped internally; a server Retry-After header takes precedence on 429. Example\: --retry-delay 500]:RETRY_DELAY:_default' \
'--proxy=[Proxy URL (e.g., http\://localhost\:8080, socks5\://localhost\:9050)]:PROXY:_default' \
'--insecure=[Skip TLS/SSL certificate verification, accepting self-signed, expired, or hostname-mismatched certs. Enabled by default for scanner use; pass \`--insecure=false\` to enforce certificate validation. Example\: --insecure=false]::INSECURE:(true false)' \
'*--ignore-return=[Ignore specific HTTP status codes during scanning (comma-separated). Example\: --ignore-return 302,403,404]:IGNORE_RETURN:_default' \
'--workers=[Number of concurrent workers]:WORKERS:_default' \
'--max-concurrent-targets=[Maximum number of concurrent targets to scan]:MAX_CONCURRENT_TARGETS:_default' \
'--max-targets-per-host=[Maximum number of targets per host]:MAX_TARGETS_PER_HOST:_default' \
'*-e+[Specify payload encoders to use (comma-separated). Options\: none, url, 2url, 3url, 4url, html, htmlpad, base64, unicode, zwsp. Default\: url,html]:ENCODERS:(none url 2url 3url 4url html htmlpad base64 unicode zwsp)' \
'*--encoders=[Specify payload encoders to use (comma-separated). Options\: none, url, 2url, 3url, 4url, html, htmlpad, base64, unicode, zwsp. Default\: url,html]:ENCODERS:(none url 2url 3url 4url html htmlpad base64 unicode zwsp)' \
'*--remote-payloads=[Fetch remote XSS payloads from providers (comma-separated). Options\: portswigger, payloadbox]:REMOTE_PAYLOADS:_default' \
'--custom-blind-xss-payload=[Load custom blind XSS payloads from a file. Example\: --custom-blind-xss-payload '\''payloads.txt'\'']:CUSTOM_BLIND_XSS_PAYLOAD:_default' \
'-b+[Blind XSS callback URL. Example\: -b '\''https\://example.com/callback'\'']:BLIND_CALLBACK_URL:_default' \
'--blind=[Blind XSS callback URL. Example\: -b '\''https\://example.com/callback'\'']:BLIND_CALLBACK_URL:_default' \
'*--blind-oob=[Enable OOB blind XSS via interactsh. Optional comma-separated server domains (default\: public servers). Example\: --blind-oob=oast.fun,oast.me]::BLIND_OOB:_default' \
'--blind-oob-secret=[Auth token (secret) for a self-hosted interactsh server; sent as the Authorization header on register/poll/deregister]:BLIND_OOB_SECRET:_default' \
'--blind-oob-wait=[Seconds to keep polling for OOB callbacks after all payloads are sent (default 30; 0 = no extra end-of-scan wait)]:BLIND_OOB_WAIT:_default' \
'--custom-payload=[Load custom payloads from a file. Example\: --custom-payload '\''payloads.txt'\'']:CUSTOM_PAYLOAD:_default' \
'--custom-alert-value=[Custom value for alert/prompt/confirm in payloads. Default\: "1". Example\: --custom-alert-value '\''document.domain'\'']:CUSTOM_ALERT_VALUE:_default' \
'--custom-alert-type=[Custom alert function type. Options\: none (keep original), str (wrap value in quotes). Default\: "none"]:CUSTOM_ALERT_TYPE:(none str)' \
'--inject-marker=[Custom injection point marker. Replace this string with payloads in URL/headers/body. Example\: --inject-marker '\''FUZZ'\'' with URL '\''http\://example.com/?q=FUZZ'\'']:INJECT_MARKER:_default' \
'--max-payloads-per-param=[Cap the number of base payloads tested per parameter (reflection set and DOM-verification set are each capped independently). 0 (default) applies a built-in safety cap of 3000 per set unless --deep-scan is set; pass an explicit value to override, or --deep-scan for a truly unlimited run. Bounds the request fan-out on large attack surfaces and on endpoints that reflect every payload (self-/canonical-link echoes) without verifying. Note\: the cap applies to the base catalog; WAF-bypass mutation/encoder expansion and a small set of shared CSP-bypass / tech-specific payloads are added afterwards (and never trimmed), so the actual per-parameter total can exceed this value — substantially so when a WAF bypass strategy is active. Use --deep-scan only to lift the built-in default cap]:MAX_PAYLOADS_PER_PARAM:_default' \
'--sxss-url=[URL to check for Stored XSS reflection. When omitted with --sxss, auto-detects from form discovery context]:SXSS_URL:_default' \
'--sxss-method=[HTTP method for checking Stored XSS (default "GET")]:SXSS_METHOD:_default' \
'--sxss-retries=[Number of times to re-check the Stored XSS URL to handle slow session/content propagation. Each retry waits 500ms * attempt_index]:SXSS_RETRIES:_default' \
'--waf-bypass=[WAF bypass mode\: auto (detect+bypass), force (use --force-waf), off (detect-only; no payload mutations). Default\: auto]:WAF_BYPASS:(auto force off)' \
'--force-waf=[Force a specific WAF type for bypass strategies (e.g., cloudflare, akamai, modsecurity)]:FORCE_WAF:_default' \
'--waf-min-confidence=[Discard WAF fingerprints below this confidence (0.0–1.0). Default (0.3) filters weak signals like \`Server\: Google Frontend\` (0.15 — emitted by every Google-hosted property regardless of Cloud Armor) and generic "Request blocked" body markers. Real WAF signatures (Cloudflare 0.9+, AWS WAF 0.95) are kept. Pass \`--waf-min-confidence 0.0\` to keep every match]:WAF_MIN_CONFIDENCE:_default' \
'--config=[Path to a config file (TOML or JSON). Overrides default search path]:FILE:_default' \
'--include-request[Include HTTP request information in output]' \
'--include-response[Include HTTP response information in output]' \
'--include-all[Include both HTTP request and response information in output (equivalent to --include-request --include-response)]' \
'--no-color[Disable colored output (also respects NO_COLOR env var)]' \
'-S[Silence all logs except POC output to STDOUT]' \
'--silence[Silence all logs except POC output to STDOUT]' \
'--dry-run[Dry-run mode\: parse targets, run parameter discovery, and report what would be scanned without sending attack payloads. Outputs target count, discovered parameters, and estimated request count]' \
'--stream-findings[Emit each finding (POC + Issue / Payload / Line) the moment it is verified, instead of waiting for end-of-scan. Useful for long scans where you want immediate feedback; off by default so the default flow shows findings after \`WRN XSS found N XSS\`]' \
'--only-discovery[Only perform parameter discovery (skip XSS scanning)]' \
'--skip-discovery[Skip all discovery checks]' \
'--skip-reflection-header[Skip header-based reflection checks]' \
'--skip-reflection-cookie[Skip cookie-based reflection checks]' \
'--skip-reflection-path[Skip path-based reflection checks]' \
'--skip-mining[Skip all mining]' \
'--skip-mining-dict[Skip dictionary-based mining]' \
'--skip-mining-dom[Skip mining parameter names from HTML input id/name attributes. Does NOT disable DOM-XSS static analysis of inline scripts (the \`\[A\]\` findings) — use --skip-ast-analysis for that]' \
'-F[Follow HTTP redirects. Example\: -F]' \
'--follow-redirects[Follow HTTP redirects. Example\: -F]' \
'--only-custom-payload[Only test custom payloads. Example\: --only-custom-payload --custom-payload=p.txt]' \
'--skip-xss-scanning[Skip XSS scanning entirely]' \
'--deep-scan[Perform deep scanning - test all payloads even after finding XSS]' \
'--sxss[Enable Stored XSS mode]' \
'--skip-ast-analysis[Skip AST-based DOM XSS detection — the source→sink analysis of JavaScript in responses that emits \[A\] findings. This is the flag that silences them; --skip-mining-dom does not]' \
'--analyze-external-js[Fetch and AST-analyze same-origin external <script src> bundles for DOM-XSS (off by default to preserve request budget)]' \
'--hpp[Enable HTTP Parameter Pollution (HPP) — duplicate query params to bypass WAF]' \
'--detect-outdated-libs[Also report outdated / known-vulnerable JS libraries (informational, CWE-1104). Off by default\: dalfox focuses on verified XSS; this is an opt-in retire.js-style add-on that inspects <script> tags (0 extra requests)]' \
'--skip-waf-probe[Skip WAF fingerprinting probes (header-only detection, no provocation request)]' \
'--waf-evasion[Adaptive WAF evasion\: when a WAF is detected, randomize inter-request timing (jitter) and escalate a cooldown pause on clusters of blocked responses, instead of the old blunt workers=1/delay=3000 preset. Pairs well with --rate-limit. The per-WAF pacing hint is applied automatically on detection even without this flag]' \
'--debug[Enable debug logging (show DBG lines)]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
'*::targets -- Targets (URLs or file paths):_default' \
&& ret=0
;;
(server)
_arguments "${_arguments_options[@]}" : \
'-p+[Port to run the server on]:PORT:_default' \
'--port=[Port to run the server on]:PORT:_default' \
'-H+[Host to bind the server to]:HOST:_default' \
'--host=[Host to bind the server to]:HOST:_default' \
'--api-key=[API key required in X-API-KEY header (or set via DALFOX_API_KEY). Leave empty to disable auth]:API_KEY:_default' \
'--log-file=[Path to a log file to also write logs (plain text, no ANSI colors)]:LOG_FILE:_default' \
'--rate-limit=[Server-wide cap on each scan'\''s outbound request rate (requests/second; 0 or unset = unlimited). Applied to every submitted scan\: a request'\''s own \`rate_limit\` may be lower but cannot exceed or disable this cap]:RATE_LIMIT:_default' \
'--scan-timeout=[Server-wide cap on each scan'\''s total wall-clock runtime, in seconds (0 or unset = unbounded). Applied to every submitted scan\: a request'\''s own scan_timeout may be shorter but cannot exceed or disable this cap. Bounds long/deep scans so a single target can'\''t pin a worker indefinitely]:SCAN_TIMEOUT:_default' \
'--max-concurrent-scans=[Maximum number of concurrently active (queued + running) scans. Once the cap is hit, new submissions get HTTP 503 until a slot frees. 0 disables the cap (unbounded). Bounds memory + the blocking-pool against a flood of submissions]:MAX_CONCURRENT_SCANS:_default' \
'--allowed-hosts=[Comma-separated hostnames accepted in the request \`Host\` header, on top of the bind host, \`localhost\`, and any IP literal (which cannot be rebound). Requests naming anything else are refused, which is what a DNS rebinding attack looks like. Set this when a reverse proxy forwards a public hostname to this server]:ALLOWED_HOSTS:_default' \
'--max-retained-scans=[Maximum number of finished (done/error/cancelled) scans kept in memory. Once exceeded, the oldest finished scans are dropped to make room; scans still queued or running are never dropped. 0 disables the cap. This bounds memory independently of \`--max-concurrent-scans\`, which only counts active scans, so a flood of quick scans could otherwise retain their results (including response bodies) until the retention TTL]:MAX_RETAINED_SCANS:_default' \
'--max-body-bytes=[Maximum accepted request-body size (bytes) for POST /scan and /preflight. Replaces axum'\''s implicit 2 MiB default with an explicit, documented bound]:MAX_BODY_BYTES:_default' \
'--allowed-origins=[Comma-separated list of allowed origins for CORS. Supports\:   - "*" wildcard (match all)   - exact origins (http\://localhost\:3000)   - "regex\:<pattern>" for regex]:ALLOWED_ORIGINS:_default' \
'--callback-param-name=[JSONP callback parameter name (default\: callback)]:CALLBACK_PARAM_NAME:_default' \
'--cors-allow-methods=[CORS allow methods (comma-separated). Default\: GET,POST,OPTIONS,PUT,PATCH,DELETE]:CORS_ALLOW_METHODS:_default' \
'--cors-allow-headers=[CORS allow headers (comma-separated). Default\: Content-Type,X-API-KEY,Authorization]:CORS_ALLOW_HEADERS:_default' \
'--config=[Path to a config file (TOML or JSON). Overrides default search path]:FILE:_default' \
'--jsonp[Allow JSONP responses (wrap JSON in callback())]' \
'--debug[Enable debug logging (show DBG lines)]' \
'--no-color[Disable colored output (also respects NO_COLOR env var)]' \
'-S[Silence all logs except POC output to STDOUT]' \
'--silence[Silence all logs except POC output to STDOUT]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
&& ret=0
;;
(payload)
_arguments "${_arguments_options[@]}" : \
'--config=[Path to a config file (TOML or JSON). Overrides default search path]:FILE:_default' \
'--json[Print payloads as a JSON array]' \
'--debug[Enable debug logging (show DBG lines)]' \
'--no-color[Disable colored output (also respects NO_COLOR env var)]' \
'-S[Silence all logs except POC output to STDOUT]' \
'--silence[Silence all logs except POC output to STDOUT]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
'::selector -- Payload selector
Available selectors\:
  - javascript
  - event-handlers
  - useful-tags
  - payloadbox
  - portswigger
  - uri-scheme
  - special-chars
  - functions
  - awesome-alert
  - dom-clobbering
  - mxss
  - blind
  - all:_default' \
&& ret=0
;;
(mcp)
_arguments "${_arguments_options[@]}" : \
'--config=[Path to a config file (TOML or JSON). Overrides default search path]:FILE:_default' \
'--debug[Enable debug logging (show DBG lines)]' \
'--no-color[Disable colored output (also respects NO_COLOR env var)]' \
'-S[Silence all logs except POC output to STDOUT]' \
'--silence[Silence all logs except POC output to STDOUT]' \
'-h[Print help]' \
'--help[Print help]' \
&& ret=0
;;
(completion)
_arguments "${_arguments_options[@]}" : \
'--config=[Path to a config file (TOML or JSON). Overrides default search path]:FILE:_default' \
'--debug[Enable debug logging (show DBG lines)]' \
'--no-color[Disable colored output (also respects NO_COLOR env var)]' \
'-S[Silence all logs except POC output to STDOUT]' \
'--silence[Silence all logs except POC output to STDOUT]' \
'-h[Print help]' \
'--help[Print help]' \
':shell -- Shell to generate completions for:(bash elvish fish powershell zsh)' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" : \
":: :_dalfox__subcmd__help_commands" \
"*::: :->help" \
&& ret=0

    case $state in
    (help)
        words=($line[1] "${words[@]}")
        (( CURRENT += 1 ))
        curcontext="${curcontext%:*:*}:dalfox-help-command-$line[1]:"
        case $line[1] in
            (scan)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(server)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(payload)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(mcp)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(completion)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
        esac
    ;;
esac
;;
        esac
    ;;
esac
}

(( $+functions[_dalfox_commands] )) ||
_dalfox_commands() {
    local commands; commands=(
'scan:Scan targets for XSS' \
'server:Run API/server mode' \
'payload:Manage or enumerate payloads' \
'mcp:Run MCP stdio server (Model Context Protocol) exposing Dalfox tools' \
'completion:Generate shell completion scripts' \
'help:Print this message or the help of the given subcommand(s)' \
    )
    _describe -t commands 'dalfox commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__completion_commands] )) ||
_dalfox__subcmd__completion_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox completion commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help_commands] )) ||
_dalfox__subcmd__help_commands() {
    local commands; commands=(
'scan:Scan targets for XSS' \
'server:Run API/server mode' \
'payload:Manage or enumerate payloads' \
'mcp:Run MCP stdio server (Model Context Protocol) exposing Dalfox tools' \
'completion:Generate shell completion scripts' \
'help:Print this message or the help of the given subcommand(s)' \
    )
    _describe -t commands 'dalfox help commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help__subcmd__completion_commands] )) ||
_dalfox__subcmd__help__subcmd__completion_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox help completion commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help__subcmd__help_commands] )) ||
_dalfox__subcmd__help__subcmd__help_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox help help commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help__subcmd__mcp_commands] )) ||
_dalfox__subcmd__help__subcmd__mcp_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox help mcp commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help__subcmd__payload_commands] )) ||
_dalfox__subcmd__help__subcmd__payload_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox help payload commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help__subcmd__scan_commands] )) ||
_dalfox__subcmd__help__subcmd__scan_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox help scan commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__help__subcmd__server_commands] )) ||
_dalfox__subcmd__help__subcmd__server_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox help server commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__mcp_commands] )) ||
_dalfox__subcmd__mcp_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox mcp commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__payload_commands] )) ||
_dalfox__subcmd__payload_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox payload commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__scan_commands] )) ||
_dalfox__subcmd__scan_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox scan commands' commands "$@"
}
(( $+functions[_dalfox__subcmd__server_commands] )) ||
_dalfox__subcmd__server_commands() {
    local commands; commands=()
    _describe -t commands 'dalfox server commands' commands "$@"
}

if [ "$funcstack[1]" = "_dalfox" ]; then
    _dalfox "$@"
else
    compdef _dalfox dalfox
fi
