lib/mix/tasks/hf.login.ex

defmodule Mix.Tasks.Hf.Login do
  @shortdoc "Authenticate with HuggingFace and save token to disk"
  @moduledoc """
  Saves a HuggingFace API token to `~/.cache/huggingface/token`.

      $ mix hf.login --token hf_xxx

  ## Options

    * `--token` / `-t` — your HuggingFace API token (prompts if omitted)

  The token will be used by all `HuggingfaceClient` calls that don't
  specify an explicit `access_token:` option.
  """

  use Mix.Task

  @impl Mix.Task
  def run(args) do
    {opts, _, _} = OptionParser.parse(args, aliases: [t: :token], strict: [token: :string])

    token =
      opts[:token] ||
        (
          IO.write("Enter your HuggingFace token: ")
          IO.read(:line) |> String.trim()
        )

    case HuggingfaceClient.Config.save_token(token) do
      :ok ->
        Mix.shell().info("✓ Token saved to #{HuggingfaceClient.Config.hf_home()}/token")
        Mix.shell().info("  Verifying token...")

        case HuggingfaceClient.Hub.Auth.who_am_i(access_token: token) do
          {:ok, %{"name" => name}} ->
            Mix.shell().info("✓ Logged in as: #{name}")

          _ ->
            Mix.shell().error("  Warning: could not verify token (network issue?)")
        end

      err ->
        Mix.raise("Failed to save token: #{inspect(err)}")
    end
  end
end