Current section
Files
Jump to
Current section
Files
lib/mix/tasks/claude.setup_token.ex
defmodule Mix.Tasks.Claude.SetupToken do
use Mix.Task
@shortdoc "Sets up Claude Code authentication token"
@moduledoc """
Sets up a long-lived authentication token for Claude Code SDK.
This task executes `claude setup-token` and stores the result
for automatic use by the SDK.
## Usage
$ mix claude.setup_token
## Requirements
- Claude Code CLI installed (`npm install -g @anthropic-ai/claude-code`)
- Active Claude subscription
- Interactive terminal access
## Options
- `--force` - Force token refresh even if valid token exists
- `--clear` - Clear existing authentication
## Examples
# Initial setup
$ mix claude.setup_token
# Force refresh
$ mix claude.setup_token --force
# Clear authentication
$ mix claude.setup_token --clear
"""
@impl Mix.Task
def run(args) do
# Start applications
Mix.Task.run("app.start")
# Start AuthManager manually if not in supervision tree
ensure_auth_manager_started()
# Parse options
{opts, _args, _invalid} =
OptionParser.parse(args,
switches: [force: :boolean, clear: :boolean]
)
cond do
opts[:clear] ->
clear_auth()
opts[:force] || !token_exists?() ->
setup_new_token()
true ->
Mix.shell().info("β
Valid token already exists. Use --force to refresh.")
show_status()
end
end
defp ensure_auth_manager_started do
# Check if AuthManager is already running
case Process.whereis(ClaudeAgentSDK.AuthManager) do
nil ->
# Start it manually
{:ok, _pid} = ClaudeAgentSDK.AuthManager.start_link()
:ok
_pid ->
# Already running
:ok
end
end
defp token_exists? do
case ClaudeAgentSDK.AuthManager.get_token() do
{:ok, _token} -> true
_ -> false
end
end
defp setup_new_token do
case ClaudeAgentSDK.AuthManager.setup_token() do
{:ok, token} ->
Mix.shell().info("β
Authentication successful!")
Mix.shell().info("")
Mix.shell().info("Token: #{String.slice(token, 0, 20)}...")
Mix.shell().info("")
# Show how to use the token
if String.starts_with?(token, "sk-ant-oat01-") do
Mix.shell().info("π‘ To use this token manually, set:")
Mix.shell().info(" export CLAUDE_AGENT_OAUTH_TOKEN=#{token}")
end
show_status()
{:error, :no_input} ->
Mix.shell().error("Cancelled.")
{:error, reason} ->
Mix.shell().error("Authentication failed: #{inspect(reason)}")
end
end
defp clear_auth do
Mix.shell().info("ποΈ Clearing authentication...")
:ok = ClaudeAgentSDK.AuthManager.clear_auth()
Mix.shell().info("β
Authentication cleared")
end
defp show_status do
status = ClaudeAgentSDK.AuthManager.status()
Mix.shell().info("")
Mix.shell().info("π Authentication Status:")
Mix.shell().info(" Provider: #{status.provider}")
Mix.shell().info(" Authenticated: #{status.authenticated}")
if status.expires_at do
Mix.shell().info(" Expires: #{status.expires_at}")
Mix.shell().info(" Time remaining: #{status.time_until_expiry_hours} hours")
end
Mix.shell().info("")
Mix.shell().info("β
Ready to use ClaudeAgentSDK.query/2")
end
end