function cmd::add::run() {
  local name=""
  local type=""
  local subtype=""
  local rule=""
  local ip=""
  local tunnel=""
  local guest=false
  local presets=()
  local show_config=false
  local show_qr=false

  # Parse flags
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --name)         name="$2";           shift 2 ;;
      --type)         type="$2";           shift 2 ;;
      --subtype)      subtype="$2";        shift 2 ;;
      --rule)         rule="$2";           shift 2 ;;
      --ip)           ip="$2";             shift 2 ;;
      --preset)       presets+=("$2");     shift 2 ;;
      --guest)        guest=true;          shift   ;;
      --tunnel)       tunnel="$2";         shift 2 ;;
      --show-config)  show_config=true;    shift   ;;
      --show-qr)      show_qr=true;        shift   ;;
      --help)         cmd::add::help;      return  ;;
      *)
        log::error "Unknown flag: $1"
        cmd::add::help
        return 1
        ;;
    esac
  done

  # --guest shorthand
  if $guest; then
    type="guest"
  fi

  # Resolve guest subtype
  local effective_type="$type"
  if [[ "$type" == "guest" && -n "$subtype" ]]; then
    # Validate subtype
    local valid_subtypes="desktop laptop phone tablet"
    if ! echo "$valid_subtypes" | grep -qw "$subtype"; then
      log::error "Invalid subtype: ${subtype} (valid: desktop, laptop, phone, tablet)"
      return 1
    fi
    effective_type="guest-${subtype}"
  fi

  # Build full client name
  local full_name="${type}-${name}"

  # Validate
  cmd::add::validate "$name" "$type" "$ip" "$tunnel" || return 1

  # Resolve tunnel mode — flag > device default
  if [[ -z "$tunnel" ]]; then
    tunnel=$(config::default_tunnel_for "$type")
  fi

    # Determine rule — explicit flag > type default
  if [[ -z "$rule" ]]; then
    if config::is_guest_type "$type"; then
      rule="guest"
    else
      rule="user"
    fi
  fi

  # Validate rule if specified
  if ! rule::exists "$rule"; then
    log::error "Rule not found: ${rule}"
    return 1
  fi

  local allowed_ips
  allowed_ips=$(config::allowed_ips_for "$effective_type" "$tunnel") || return 1

  log::section "Adding client: ${full_name}"

  # Auto-assign IP if not provided
  if [[ -z "$ip" ]]; then
    ip=$(ip::next_for_type "$effective_type") || return 1
  fi

  log::wg_add "Name:   ${full_name}"
  log::wg_add "Type:   ${type}"
  log::wg_add "IP:     ${ip}"
  log::wg_add "Tunnel: ${tunnel} (${allowed_ips})"

  # Generate keys
  keys::generate_pair "$full_name" || return 1

  # Create client config
  peers::create_client_config "$full_name" "$effective_type" "$ip" "$allowed_ips" || return 1

  # Store subtype in meta
  if [[ -n "$subtype" ]]; then
    peers::set_meta "$full_name" "subtype" "$subtype"
  fi

  # Add peer to server config
  local public_key
  public_key=$(keys::public "$full_name") || return 1
  peers::add_to_server "$full_name" "$public_key" "$ip" || return 1

  log::wg_add "Rule:   ${rule:-none}"

  # Apply presets
  for preset in "${presets[@]}"; do
    fw::apply_preset "$preset" "${ip}" || return 1
  done

  # Apply rule
  if [[ -n "$rule" ]]; then
    rule::apply "$rule" "$ip" || return 1
  fi

  # Reload WireGuard
  peers::reload || return 1

  log::wg_success "Client added successfully: ${full_name} (${ip}) [${tunnel} tunnel]"

  # Show QR for mobile by default, config for desktop/laptop
  local display_type="${subtype:-$type}"
  
  if cmd::add::is_mobile "$display_type"; then
    keys::qr "$full_name"
  else
    log::section "Client Config"
    cat "$(ctx::clients)/${full_name}.conf"
  fi
}