Claude Code Remote Control: resume your WSL sessions from your phone

Claude Code Remote Control: resume your WSL sessions from your phone

·7 min read·Updated on May 26, 2026

The problem: Claude Code sessions locked inside WSL

Claude Code sessions pile up in ~/.claude/projects/-home-kwuic-projects-*: history JSONLs, todos, sometimes hours of context per session. Step away from the desk and none of it is reachable.

Claude Desktop can't open WSL sessions, and neither can claude --resume <session-id> from a different filesystem. Each environment — native Windows, WSL, the Desktop app — is sealed in its own bubble.

The workarounds aren't better: Tailscale + SSH + a mobile client works, but typing code on a phone keyboard in a bare terminal isn't viable; GitHub Actions for delegating tasks is asynchronous, so there's no natural workflow.

The fix: claude remote-control

Since Claude Code 2.1.51:

claude remote-control

The binary opens a bridge between your local terminal and Anthropic's servers, and prints a QR code plus a claude.ai/code?environment=env_xxxxx URL. Scan it with the Claude app ("Code" tab) or open the URL anywhere. From then on, the session keeps running on your machine (files, MCP, git, WSL env untouched), with mobile and desktop synced in real time.

It's the inverse of a cloud editor like Cursor Web: the compute stays local, only the UI is remote. MCP secrets, credentials and private code never leave the machine.

The DISABLE_TELEMETRY gotcha

First launch:

❯ claude remote-control
Error: Remote Control is not yet enabled for your account.

On the $200/month Max plan. There's no toggle to hunt for in /config, claude.ai/settings or admin-settings: the feature is gated server-side through GrowthBook, Anthropic's feature flag system, via an internal flag named tengu_ccr_bridge.

The GitHub issues (#34528, #29569) and the community's minified binary analysis give the real cause. Somewhere in the claude binary, a Pv() function decides whether the client should query the feature flag service:

// Reconstructed from the minified code
function Pv() {
  return !!process.env.DISABLE_TELEMETRY || !!process.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
}

function qA(flagName, defaultValue) {
  if (!Pv()) {
    return fetchFromGrowthBook(flagName, defaultValue)
  }
  return defaultValue // ← always returns false for gated features
}

// Later:
const remoteControlEnabled = qA('tengu_ccr_bridge', false)

If DISABLE_TELEMETRY=1 is set (or its alias CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC), the client never even asks the server: it assumes every gated feature is false. Remote Control disappears, silently.

The design conflates two distinct things — "I don't want to send analytics" (a privacy preference) and "I'm a client that can't reach Anthropic" (Bedrock, Vertex, Foundry). Two endpoints, two use cases, gated by the same boolean. Several PRs are pushing to split them; until then, you need to know the trap.

What's safe vs what breaks

VariableEffectBreaks Remote Control?
DISABLE_TELEMETRYCuts Statsig + GrowthBookYes
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICAlias of the aboveYes
DISABLE_ERROR_REPORTINGCuts SentryNo ✅
DISABLE_NON_ESSENTIAL_MODEL_CALLSCuts Haiku calls (titles, etc.)No ✅
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEYCuts surveysNo ✅

Typical trap: DISABLE_NON_ESSENTIAL_MODEL_CALLS looks like CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, off by an underscore and three letters. They're two different variables with two different effects. It's DISABLE_TELEMETRY that breaks Remote Control, not the other.

The fix procedure

  1. Remove DISABLE_TELEMETRY (and CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC if present) from ~/.claude/settings.json:
{
  "env": {
    "DISABLE_ERROR_REPORTING": "1",
    "DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
    "CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY": "1"
  }
}
  1. Check it isn't in the shell either:
grep -i -E "DISABLE_TELEMETRY|NONESSENTIAL_TRAFFIC" ~/.bashrc ~/.zshrc ~/.profile ~/.config/fish/config.fish 2>/dev/null
  1. Close the terminal completely. The variable is still exported in the parent shell's env, so relaunching claude in the same window isn't enough. In an IDE integrated terminal, kill every instance to purge the inherited env.

  2. Refresh the feature-flag cache by re-authenticating:

claude
# in the session:
/logout
/login   # claude.ai OAuth, definitely NOT an API key
  1. Test with claude remote-control. If all is well:
Take this session with you and pick up right where you left off on any device.
Open the Code tab in the Claude mobile app, or visit claude.ai/code in a browser.

Enable Remote Control? (y/n)

Spawn mode: same-dir or worktree

On first launch:

Spawn mode for this project:
  [1] same-dir — sessions share the current directory (default)
  [2] worktree — each session gets an isolated git worktree

same-dir: every session launched from mobile works in the current directory. Simple, but two parallel sessions can step on each other's files.

worktree: each session gets its own isolated git worktree on a dedicated branch. Safe parallelism, with the overhead that comes with it (worktrees to clean up, branches to merge).

For serial writing, same-dir is plenty. To let mobile chew through tickets while you work on something else at the desk, worktree becomes relevant. You can switch mid-flight with the w key, or restart with --spawn=worktree.

Detached workflow with tmux

By default claude remote-control holds the terminal in the foreground: closing the window kills the session.

# Create a tmux session named "rc"
tmux new -s rc

# Inside tmux: start the remote
claude remote-control

# Detach (Ctrl+B then D): the terminal closes, the remote keeps running
# To come back later:
tmux attach -t rc

The remote then lives in the background as long as the machine is on. Three aliases in ~/.bashrc to avoid retyping:

alias rc-start='tmux new -d -s rc "claude remote-control"'
alias rc-attach='tmux attach -t rc'
alias rc-stop='tmux kill-session -t rc'

What works, what doesn't (yet)

Works:

  • Resuming any session launched from the remote, on mobile or desktop
  • Live file editing (changes appear on both screens)
  • Running bash commands, reading logs
  • Local MCP servers available (every one configured locally)
  • Push notifications when a long task finishes

Doesn't work (yet):

  • Resuming a prior session launched outside the remote. Old JSONLs in ~/.claude/projects/ stay invisible from mobile: only what you launch via remote-control is reachable.
  • Working without an internet connection (it's a cloud bridge).
  • Keeping the session if the machine shuts down or Windows pauses WSL2.

That last point is insidious: Windows 11 aggressively pauses WSL2 after a few minutes of inactivity. You think your session is alive while the Linux VM is frozen. Fix, in %UserProfile%\.wslconfig:

[wsl2]
vmIdleTimeout=-1

What to take away

One command, one QR code, and the phone becomes a clean Claude Code client — no SSH hacks, no Tailscale, and above all the code stays on the machine.

The DISABLE_TELEMETRY trap yields a general rule: on Claude Code, whenever a paid feature doesn't work, check your opt-out variables before blaming the vendor. For a minimal privacy opt-out that breaks nothing, DISABLE_ERROR_REPORTING + DISABLE_NON_ESSENTIAL_MODEL_CALLS + CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY cover the essentials without touching the GrowthBook flags.

ShareLinkedInXBluesky

Related articles