FIELD NOTE / CLAUDE CODE

Claude Code · Remote Control · macOS

claude rc gives up after 10 minutes. launchd does not.

2026-10-01  ·  ~5 min read  ·  by Gal Tidhar

One of the best things in Claude Code is the one I almost never see people use: claude rc. Leave it running in a folder on your Mac, start a new session from the Claude app on your phone, and a real session starts on the Mac with your files, MCP servers and settings. Two things ruined it for me. It needs a terminal window left open forever, and close it once by accident and the Mac goes offline for your phone. And it dies: mine reconnected itself thirteen times over 2 days 20 hours, then printed Persistent errors for 10 minutes, giving up. and quit. There is no setting for either. A small launchd file fixes both: no window, and it comes back every time it exits.

claude rc log: thirteen reconnects over nearly three days, then Persistent errors for 10 minutes, giving up
2 days 20 hours, thirteen reconnects, one exit.

Two different Remote Controls

In part 1 I turned on remoteControlAtStartup: true, which connects every Claude Code session I open to claude.ai and the mobile app. That covers the sessions that already exist. It does not let me start a new session from the phone when nothing is open on the Mac.

That is what server mode is for: claude remote-control, or claude rc. It sits in a folder and waits. From the app you pick it and a fresh session spawns on your machine, in that folder, with your files, MCP servers and settings. It is the closest thing to a self-hosted Claude Code you can reach from anywhere.

What the docs say about giving up

The two modes handle a long outage differently, and the docs spell it out:

Server mode: Claude Code gives up after roughly 10 minutes and the claude remote-control process exits. Run claude remote-control again to start a new session.

Interactive session: keep working locally. Claude Code retries for as long as the outage lasts and reconnects on its own when the network returns.

So the interactive sessions are fine. The server is designed to exit, and the documented fix is a human typing the command again. I went looking for a keep-alive flag in claude rc --help and the settings reference. There is none.

My log had one more failure in it worth knowing about: RemoteIO: transport closed permanently (code 401). That one killed a single spawned session, not the server, and the server kept going. The one that matters is the last line.

The fix: let macOS restart it

macOS already has a process supervisor. launchd's KeepAlive restarts a job whenever it exits, for any reason, and RunAtLoad starts it at login. claude rc runs fine without a terminal attached (I checked before relying on it), so it can run as a background job with no wrapper script.

Run this once. Change WorkingDirectory to the folder you want new sessions to start in. I use the parent folder of all my projects, so a session started from the phone can work in any of them.

cat > ~/Library/LaunchAgents/com.me.claude-rc.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>com.me.claude-rc</string>
  <key>ProgramArguments</key><array>
    <string>$HOME/.local/bin/claude</string><string>remote-control</string>
  </array>
  <key>WorkingDirectory</key><string>$HOME/Projects</string>
  <key>EnvironmentVariables</key><dict>
    <key>PATH</key><string>$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
  </dict>
  <key>StandardInPath</key><string>/dev/null</string>
  <key>StandardErrorPath</key><string>/tmp/claude-rc.err</string>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
  <key>ThrottleInterval</key><integer>30</integer>
</dict></plist>
EOF
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.me.claude-rc.plist

What each part is for:

  • ProgramArguments needs the full path to claude, because launchd does not read your shell profile. Check yours with which claude.
  • PATH is set for the same reason, so the sessions it spawns can find git, node and friends.
  • StandardInPath /dev/null because there is no keyboard. Stdout is left out on purpose: claude rc redraws its status every few seconds and would fill a log file for no reason. Errors still go to /tmp/claude-rc.err.
  • ThrottleInterval 30 waits 30 seconds between restarts, so a real outage costs one attempt every 30 seconds instead of a tight loop.

Check that it really comes back

Do not trust a config you have not watched fail. Kill the process and see launchd start a new one:

launchctl print gui/$(id -u)/com.me.claude-rc | grep -E "state|pid|runs"
#   state = running   runs = 1   pid = 94945
kill 94945; sleep 35
launchctl print gui/$(id -u)/com.me.claude-rc | grep -E "state|pid|runs"
#   state = running   runs = 2   pid = 96157

New pid and runs = 2: launchd restarted it. And there is no terminal window anywhere: you can close every one of them.

Things to know

  1. Close the terminal one. If you also run claude rc by hand in the same folder, you get two servers.
  2. One job per folder. Need a second folder? Copy the plist with a new Label and WorkingDirectory. I started by writing a wrapper script that looped over a list of folders, and launchd kept exiting it silently. One plist per folder has nothing to debug.
  3. A restart is a new server. The server itself starts fresh; the docs say a stopped session can be picked up again for roughly 4 hours. If a spawned session crashes, the docs say to send it a message from the app and the server serves it again (Claude Code v2.1.238 or later).
  4. Turning it off: launchctl bootout gui/$(id -u)/com.me.claude-rc, then delete the plist so it does not come back at login.
  5. Linux: not covered by the Remote Control docs, but a systemd user unit with Restart=always is the standard equivalent.

Want this set up across a team?

I set up Claude Code for teams and small businesses through ZaZet Solutions: remote access, skills, background jobs like this one, and the boring parts that keep it running when nobody is watching.