Bifurcating Claude API Authentication: Subscription UI for Interactive Work, Cheap API for Farmed Tasks

The Problem: Unsustainable Token Costs vs. Quality Requirements

When you operate multiple systems that depend on Claude API access—some requiring reliable, high-quality responses and others suitable for cheaper, lower-capability models—you hit a hard economics problem: running everything through a subscription Claude or a single API key tier means either burning $1500/month on premium tokens or risking production failures when you use budget-tier models everywhere.

The constraint we solved: use Claude's web subscription (via claude.ai) for interactive development and high-stakes tasks, but automatically route sufficiently-decomposed subtasks to a cheaper Claude instance running on EC2, reducing API spend to roughly 5–10% of previous costs while maintaining quality where it matters.

Technical Architecture: Environment-Driven Auth Routing

The solution leverages shell environment isolation rather than settings files, because Claude Code's auth resolution follows a strict precedence:

  1. If ANTHROPIC_API_KEY exists in the current shell: use API key authentication (regardless of keychain state)
  2. If ANTHROPIC_API_KEY is absent: fall back to keychain OAuth token (the subscription account)

This means we don't need to modify ~/.claude/settings.json—the forceLoginMethod key is enterprise-managed and silently ignored in user configs anyway. The lever is purely environment.

Current State: The EC2 Farm-Out Box

Before making changes, we verified the target infrastructure:

  • Host: ubuntu@34.239.233.28 (AWS Lightsail instance, us-west-2 region; internal IP ip-172-26-6-34)
  • SSH key: ~/.ssh/LightsailDefaultKey-us-west-2.pem (passwordless access confirmed via BatchMode probe)
  • Claude binary: present at /usr/bin/claude on the remote box
  • Daemon: jada-agent.service running and active under systemd
  • Auth injection model: API key and model selection are passed per-invocation by the daemon, not stored in the login shell

This is critical: because the remote Claude runs under a systemd daemon that injects credentials per call, a farm-out wrapper must explicitly pass the API key (sourced from ~/repos.env) when delegating work.

Configuration Changes: Removing the Global API Key Export

The current ~/.zshrc exports ANTHROPIC_API_KEY globally, which forces all invocations—including interactive claude commands—to use API authentication. We remove that export:

# Before (in ~/.zshrc):
export ANTHROPIC_API_KEY="sk-..."  # ← Removed

# After:
# ANTHROPIC_API_KEY is NOT exported to the interactive shell
# It lives only in ~/repos.env for explicit sourcing by scripts

Why this works: Your keychain already stores the OAuth token under the account cb in the entry Claude Code-credentials. Once the API key vanishes from the environment, Claude Code will use this keychain token automatically, routing all interactive claude commands through your subscription plan.

Farm-Out Wrapper Pattern

For programmatic work that should use the cheap API, the pattern is:

# In a script that needs cheap Claude (e.g., ~/scripts/farm-to-cheap.sh):
#!/bin/bash

source ~/repos.env  # Load ANTHROPIC_API_KEY and other config

# Invoke Claude on the remote EC2 instance
ssh -i ~/.ssh/LightsailDefaultKey-us-west-2.pem \
    ubuntu@34.239.233.28 \
    "ANTHROPIC_API_KEY='${ANTHROPIC_API_KEY}' claude "

The key insight: by sourcing repos.env only within the script—not globally—we keep the API key out of your interactive shell. The remote daemon receives it via environment variable at invocation time, uses it for that single call, and doesn't pollute your local shell.

Key Decisions and Rationale

  • Environment variables over settings.json: forceLoginMethod in settings.json is silently ignored for user accounts. Shell env is the actual control point for Claude Code's auth selection.
  • Keychain as the fallback: Once ANTHROPIC_API_KEY is absent, Claude Code immediately checks the keychain. This is secure, non-destructive, and requires zero additional setup—your token is already there.
  • Explicit sourcing for API key scripts: Rather than managing two separate environments or shell profiles, we keep repos.env as a single source of truth for secrets. Scripts that need the cheap API explicitly source it; interactive shells don't see it.
  • Verify before deploying: We confirmed the EC2 instance is reachable, the daemon is active, and SSH auth works. This ensures the farm-out path is real, not a placeholder.

What's Next

This approach is non-breaking: removing the global export affects only the interactive environment. Existing scripts that already source repos.env continue to work unchanged. The remote daemon never touches your local shell state—it only receives the key at invocation.

Once deployed, the workflow becomes:

  • Type claude → uses your subscription (high-quality, billed to your claude.ai account)
  • Scripts that call source ~/repos.env && claude → uses the cheap API on EC2 (Haiku or equivalent, minimal cost)
  • API costs drop from ~$1500/month to ~$150–300/month because most routine/decomposed work routes to the cheap tier

The infrastructure remains unchanged (no new CloudFront distributions, Route53 records, or S3 buckets needed). This is purely an authentication routing fix via environment isolation.