[FEATURE] Bandwidth-aware mode for metered connections (mobile hotspot, cellular tethering)
Preflight Checklist
- [x] I have searched existing requests
- [x] This is a single feature request
Problem Statement
Claude Code on a mobile hotspot or cellular tether can silently consume hundreds of MB to over 1 GB per hour of upload on a sustained interactive session. The current architecture has no awareness of metered connections, no visibility into per-turn bandwidth cost, and no built-in mitigations. For users on pay-per-GB plans or limited tethering allowances, this turns a normal coding session into an expensive incident before they realize what happened.
This issue is about the user-experience gap, not a single underlying cause. Existing related issues each address one technical sliver:
- #55087 — proposes a relay-mode architecture (large change, long horizon)
- #52056 — long sessions are forced because no persistent context exists
- #45067 — ~100 MB GCS download on every startup with no opt-out
- #44319 — tool output compression hooks
- #33464 — native compression for CLAUDE.md / instruction files
- #47059 — HTTP/2 keepalive issues on CGNAT (which mobile hotspots commonly use)
None of these surface the immediate practical question a user on a hotspot needs answered: "How much data is this session about to use, and how do I keep it small?"
Real-World Reproduction
A user on iPhone hotspot (CGNAT, ~10% packet loss typical for cellular) running a normal multi-turn session:
- Interface counters (
netstat -ibnonen0): ~300 KB/s sustained upload during burst windows, ~1 GB/hour projection - Per-process attribution (
nettop): theclaudeprocess accounts for ~95% of all upload traffic measured over multiple 30-second windows - TCP retransmit ratio (
nettop -m tcp): ~10% — every 1 MB of payload becomes ~1.1 MB on the wire - macOS bandwidth meters (Bandwidth+, Activity Monitor) misattribute most of this to "System" because the traffic flows through
nsurlsessiondand similar Apple daemons thatnettopcannot resolve to a process — the user has no idea Claude Code is the source until they investigate at the interface layer
After ~1 hour of moderate interactive use (no large repos cloned, no MCP-heavy workflows): >200 MB uploaded to Anthropic API endpoints.
Why This Is Worse Than It Looks
Three multiplicative effects compound:
- Full context retransmission per turn. Every user message ships the entire conversation history plus all prior tool results. Prompt caching helps the server but the client still uploads cache breakpoints + new tokens each turn. A long session therefore gets more expensive per turn as it grows, not less.
- Tool results dominate the upload. A single
Bash/Read/Grepproducing 20-50 KB of output is sent verbatim back to the API. In a debugging session, dozens of these accumulate. The user wrote a 50-character prompt and triggered a 500 KB upload.
- Lossy connection amplifies everything. On a typical cellular tether with 5-15% packet loss, TCP retransmits add 10-20% raw bytes on top of payload. The interface meter reads higher than the API actually received.
What's Missing
There is no in-product way to:
- See how much data this session has uploaded, broken down by user message vs. tool results vs. context replays
- Get a warning before a turn that will upload >X MB (e.g., before pasting a large file, before a
Grepreturns 500 results) - Toggle a "metered connection mode" that automatically: truncates large tool results client-side before upload, defers non-essential network traffic (auto-update GCS pull #45067, telemetry, plugin marketplace sync), and surfaces a confirmation prompt for high-cost actions
- Read the /cost panel as bytes-on-wire, not just tokens. Tokens are a poor proxy for bandwidth because tool output bytes ≠ tokens, and retransmits don't appear in token counts at all.
Proposed Solution
A first-class "metered mode" with three layers:
1. Visibility (ship first, low effort):
- Extend
/costand/usageto show bytes uploaded/downloaded per session, with a per-turn breakdown - Statusline integration:
↑ 47.2 MB this sessionnext to token count - Pre-turn estimate: when a tool result exceeds a threshold, show "About to upload 380 KB to API — continue? [y/N]" gated behind a setting
2. Mitigations (medium effort):
--meteredCLI flag and"meteredMode": trueinsettings.jsonthat:- Skips the GCS auto-update download (#45067)
- Pauses plugin marketplace sync
- Truncates tool outputs above a configurable byte limit (with a "view full" inline option that uploads on demand)
- Disables non-essential telemetry/analytics pings
- Surfaces an explicit "this connection looks metered, enable metered mode?" prompt when iOS/macOS reports the network as Low Data Mode or expensive (
NWPathMonitor.isExpensiveon Apple platforms) - Honor OS-level Low Data Mode on macOS automatically when detected
3. Architectural (long-term, overlaps with #55087):
- Tool output compression at the transport layer (gzip/zstd), independent of the model — many tool results are highly compressible (logs, file contents, JSON)
- Local tool-output caching: if
Readproduces the same content twice in a session, reference by hash instead of re-uploading
Why Now
Mobile-tethered development is increasingly common (remote work, travel, areas with unreliable home internet). Claude Code is otherwise an excellent fit for these scenarios — small terminal footprint, no GUI overhead. Bandwidth is the one thing making it actively dangerous on a metered link, and the fix is largely product-surface work, not a fundamental rearchitecture.
The relay-mode proposal in #55087 solves this elegantly but is a major undertaking. Visibility and metered-mode toggles can ship in days and would prevent the worst user surprises while the bigger architectural work is considered.
Concrete Reproduction Snippet
For maintainers who want to verify on their own setup:
# Before starting a Claude session
B1=$(netstat -ibn | awk '/^en0 / {print $10; exit}')
# Run a typical interactive session: a few prompts, some tool calls,
# a couple of file Reads, ~30 minutes of normal back-and-forth.
B2=$(netstat -ibn | awk '/^en0 / {print $10; exit}')
echo "Uploaded: $(( (B2 - B1) / 1024 / 1024 )) MB"
Pair with nettop -P -x -L 1 -s 1 -m tcp and grep for the claude PID to confirm attribution. Per-process upload should match the interface delta within 10-20% (the rest is OS overhead + retransmits).
Environment
- macOS 26.4 (Tahoe), arm64
- Claude Code: latest release at time of report
- Connection: iPhone Personal Hotspot (cellular)
- Observed across multiple sessions over several days
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗