Bifurcating Claude API Consumption: Subscription UI for Interactive Work, Cheap API for Farmed Tasks
The Problem
Running multiple Claude workflows—interactive development via claude.ai, programmatic API calls for CI/CD and tooling, and experimental batch work—creates a credential management nightmare. More critically, it creates a cost nightmare. When you're spending $1,500/month on Claude API tokens but need to cut that by 90%, you can't afford to run every workload at the same tier.
The conflict: your shell had ANTHROPIC_API_KEY globally exported, which meant claude command invocations (intended for the subscription web UI) were silently falling back to API key auth, burning tokens. Meanwhile, legitimate programmatic work needed the API key but couldn't distinguish between "use cheap Haiku for this atomized subtask" and "use the full model for this critical path."
The solution required surgical separation: keep the subscription token (OAuth via Claude Code credentials) active for interactive shell work, confine the API key to explicit farm-out paths, and route sufficiently-decomposed tasks to a cheaper inference tier running on an existing EC2 instance.
Authentication Architecture: The Current State
Before making changes, we mapped the actual auth mechanisms:
- Claude Code credentials store: OAuth token persisted in
~/.claude/code-credentials(macOS Keychain integration, account `cb`). This is already present and unused in your shell environment. - API key location:
~/projects/repos.env, exported globally in~/.zshrcviasource ~/projects/repos.env. - Claude CLI precedence: When
ANTHROPIC_API_KEYis in the environment, theclaudecommand uses API key auth exclusively, bypassing the stored OAuth token. - EC2 farm-out box: Lightsail instance at
34.239.233.28(Ubuntu, internal hostnameip-172-26-6-34), runningjada-agent.servicedaemon. SSH auth via~/.ssh/LightsailDefaultKey-us-west-2.pem, passwordless.
The jada-agent.service daemon accepts Claude API calls with model and key injected per-invocation, not baked into the login shell. This is critical: the farm-out wrapper must explicitly pass credentials.
The Fix: Three-Layer Shell Environment
Layer 1: Interactive Shell (No API Key)
Remove the global ANTHROPIC_API_KEY export from ~/.zshrc. The exact change:
# BEFORE (in ~/.zshrc)
source ~/projects/repos.env # exports ANTHROPIC_API_KEY globally
# AFTER (in ~/.zshrc)
# Do not source repos.env globally. Load it explicitly where needed.
With ANTHROPIC_API_KEY absent from the interactive shell environment, invoking claude will fall back to the keychain OAuth token—the intended behavior for subscription-tier interactive work.
Layer 2: Programmatic Scripts (Scoped API Key)
For scripts that genuinely need the API key—CI/CD pipelines, automation, background jobs—they explicitly source ~/projects/repos.env in their execution context. This is your existing convention, now enforced by necessity:
#!/bin/bash
# Example: ci-integration.sh
source ~/projects/repos.env # Loads ANTHROPIC_API_KEY locally only
# Now ANTHROPIC_API_KEY is available only within this script's subshell
claude API call here...
Scripts follow this pattern consistently. The API key is never ambient; it's explicitly loaded where it's consumed.
Layer 3: Farm-Out Wrapper (Cheap Tier on EC2)
For tasks that have been sufficiently decomposed into atomic pieces (unit tests, validation, synthesis of small documents, etc.), a wrapper function routes them to the cheaper Haiku tier running on the EC2 box:
#!/bin/bash
# Function to add to ~/.zshrc (after removing global repos.env)
claude-cheap() {
# Route to EC2 farm-out box for cheap inference
# Requires: SSH key at ~/.ssh/LightsailDefaultKey-us-west-2.pem
# EC2 box runs jada-agent.service (daemon injecting API key per call)
local prompt="$*"
# SSH to Lightsail instance, invoke claude on the box with Haiku model
ssh -i ~/.ssh/LightsailDefaultKey-us-west-2.pem \
ubuntu@34.239.233.28 \
"ANTHROPIC_MODEL=claude-3-5-haiku-20241022 \
/usr/bin/claude '$prompt'"
}
# Usage example:
# claude-cheap "Lint this Python function and report issues"
Why this architecture? Once a problem is broken down (by you, or by the subscription tier), verification, formatting, and validation can run on cheaper inference without quality loss. The Haiku model handles well-scoped tasks effectively and costs roughly 1/20th of Claude 3.5 Sonnet.
Infrastructure Details
- EC2 Instance: AWS Lightsail, Ubuntu 22.04 LTS,
34.239.233.28. - Service:
jada-agent.servicerunning as a systemd daemon. Status verified withssh ubuntu@34.239.233.28 systemctl status jada-agent.service. - Claude binary:
/usr/bin/claudepresent on the box. The daemon handles API key injection per-invocation (not stored in the box's shell environment). - SSH key:
~/.ssh/LightsailDefaultKey-us-west-2.pem(2048-bit RSA, Lightsail-generated). Passwordless auth verified viassh -iwithBatchMode yes. - Network: Lightsail firewall rules must allow inbound SSH on port 22 from your development machine's IP (or 0.0.0.0/0 if acceptable). Verify with
aws lightsail get-instance-access-details --instance-name farm-out-box --region us-west-2.
Cost Impact
The target: reduce API spend from ~$1,500/month to $75–150/month.
- Interactive work: Uses subscription tier (fixed $20/month). No token burn for
claudeshell invocations. - Critical programmatic work: Still uses API key with Sonnet tier where accuracy is essential. Estimated 20% of current API volume.
- Decomposed/atomized tasks: Route to Haiku via farm-out wrapper. Estimated 80% of current API volume, now at 1/20th cost. Savings: ~$1,200/month.
- EC2 Lightsail instance: ~$5/month for the small instance (minimal resource footprint for daemon).