```html

Bifurcating Claude API Authentication: Subscription CLI + Farm-Out Architecture for Cost Optimization

We recently restructured our Claude authentication layer to support two distinct execution paths: interactive subscription-based CLI work and programmatic API-key-driven farm-out tasks on EC2. This post details the technical decisions, implementation, and the infrastructure that now allows us to reduce API spend by an order of magnitude while maintaining reliability where it matters.

The Problem: API Cost Runaway

Our previous architecture exported a single ANTHROPIC_API_KEY globally in the shell environment, which meant every invocation of Claude—whether interactive development work, scheduled tasks, or delegated farm-out jobs—consumed the same expensive token pool. This created two problems:

  • Cost collision: Interactive work and programmatic automation competed for the same billing envelope, making it impossible to cap experimental spend.
  • Reliability mismatch: We couldn't afford to use cheaper models (Haiku) for atomic, well-scoped tasks without risking interactive work falling back to an underpowered endpoint.

At ~$1,500/month on the API token plan, we needed to drop to 1/10th or 1/20th of that spend. The leverage point was recognizing that not all work requires the subscription tier.

Technical Architecture: Two Paths

Path 1: Interactive CLI (Subscription)

The claude command invoked interactively should use the subscription billing plan. This work is exploratory, requires strong reasoning, and the user is actively waiting. The authentication mechanism here is the OAuth keychain token already stored by Claude Code:

  • Location: ~/.claude/credentials/Claude Code-credentials (managed by the Claude client)
  • Trigger: When ANTHROPIC_API_KEY is absent from the interactive shell, the Claude CLI automatically falls back to keychain-stored OAuth credentials.
  • Why this works: The keychain credential is tied to the user's claude.ai subscription account (account cb in this case) and carries the subscription billing context automatically.

Path 2: Programmatic Farm-Out (API Key + Haiku)

Automated tasks—lead responders, digest generation, daemon-driven workflows—should use a dedicated API key scoped to cheap models. These jobs are:

  • Broken down into small, well-defined tasks before delegation.
  • Fault-tolerant (failures can be retried with degraded output).
  • Frequently stateless or have bounded context windows.

The API key lives in a secure, repo-specific dotenv file instead of the global shell:

  • File: /Users/cb/Documents/repos/repos.env (git-ignored, never committed)
  • Convention: Programmatic scripts and farm-out wrappers explicitly source repos.env before invoking Claude.
  • Model constraint: Scripts using this path default to claude-3-5-haiku-latest unless overridden per-task.

Implementation Details

Shell Configuration Changes

The ~/.zshrc file was modified to remove the global ANTHROPIC_API_KEY export while preserving all other environment setup:

# BEFORE (problematic):
export ANTHROPIC_API_KEY="sk-ant-..."  # ← Causes CLI to ignore keychain

# AFTER (fixed):
# ANTHROPIC_API_KEY is NOT exported in .zshrc
# Interactive 'claude' command now uses keychain OAuth automatically
# Programmatic work sources repos.env on-demand

The .zshrc syntax was validated with zsh -n ~/.zshrc to ensure no breakage in the interactive shell. A utility function burst-valve was added to safely test the farm-out path without exposing credentials in command history.

Programmatic Script Changes

Two automation scripts were updated to source the API key only when needed:

  • gmb_lead_responder.py: Responds to Google My Business leads. Sources repos.env at runtime and uses the Anthropic Python SDK with explicit model selection.
  • carole_digest.py: Aggregates email and generates daily digests. Similar pattern: sources env, uses Haiku for text summarization tasks.

Both scripts were compile-checked and dry-run against live IMAP/Gmail credentials to confirm the credential loading mechanism works without breaking existing functionality.

EC2 Farm-Out Infrastructure

The EC2 Lightsail instance at 34.239.233.28 (internal hostname ip-172-26-6-34ubuntu) serves as the farm-out node for delegating work. The infrastructure details:

  • SSH access: Passwordless key-based auth using ~/.ssh/LightsailDefaultKey-us-west-2.pem. Connection verified with ssh -o BatchMode=yes probe.
  • Claude daemon: /usr/bin/claude binary present and running under systemd unit jada-agent.service (status: active).
  • Auth injection: The daemon does not read ANTHROPIC_API_KEY from the login shell. Instead, API credentials are passed per-invocation by the farm-out wrapper. This prevents credential leakage and allows model/key rotation without daemon restart.
  • EnvironmentFile pattern: Daemon configuration sources an EnvironmentFile for Fourthwall secrets and other deployment context, decoupling configuration from code.

Farm-Out Wrapper Design

A wrapper function (not yet committed, but tested) handles routing:

# Pseudo-code structure:
function farm_to_cheap_claude() {
  local task="$1"
  # Only invoke cheap claude if task is atomic and well-scoped
  ssh ubuntu@34.239.233.28 \
    "ANTHROPIC_API_KEY= claude  "
}

# Usage in main scripts:
if is_atomized_task; then
  farm_to_cheap_claude "$work"
else
  claude   # Uses subscription (interactive path)
fi

This pattern ensures that the EC2 daemon receives credentials per-call and can enforce model constraints without affecting the local interactive environment.

Key Design Decisions

  • Why not use forceLoginMethod? This setting is enterprise-only and silently ignored in user settings.json. The real lever is shell environment state.
  • Why keep the API key in repos.env? It's already the convention for sensitive deployment variables. Scripts that need it explicitly opt in by sourcing the file, reducing the attack surface compared to a global export.
  • Why Haiku for farm-out? For atomized tasks (single-turn classification, summarization, routing), Haiku's cost-to-performance ratio is optimal.