Skip to content

feat: phone-pickup Claude Code Remote Control for local folders on link - #138

Merged
Multipixelone merged 2 commits into
mainfrom
claude/multi-folder-local-access-8warrt
Jul 23, 2026
Merged

feat: phone-pickup Claude Code Remote Control for local folders on link#138
Multipixelone merged 2 commits into
mainfrom
claude/multi-folder-local-access-8warrt

Conversation

@Multipixelone

Copy link
Copy Markdown
Owner

What & why

Goal: keep Claude Code "always open" in several truly local project folders on link (the OpenClaw workspace + a fixed list) and pick any of them up from the phone — without pushing anything to GitHub.

The mechanism is Claude Code Remote Control (research preview; Pro/Max), not the cloud "Claude Code on the web" product. A Remote Control session runs on link against the real local filesystem; the phone's Claude app Code tab / claude.ai/code is just a window into it. The one catch that shapes the design: the local claude process must stay alive, so "always pick up from my phone" becomes "keep one process running per folder on link" — exactly what the existing openclaw-gateway user service already does.

Change

New auto-discovered module modules/link/claude-remote-control.nix:

  • One Restart=always systemd user service per folder (claude-rc-<name>), modelled on modules/link/openclaw.nix, WorkingDirectory rooted in that folder.
  • A writeShellApplication launcher that auto-detects the installed claude's Remote Control surface and picks the right invocation, so it's robust to version drift:
    • if the build exposes a remote-control subcommand (server mode) → use it (stays running headless, no PTY);
    • else fall back to the interactive --remote-control flag under a script PTY so it runs under systemd. (The claude build checked here — 2.1.218 — only has the flag, not the subcommand.)
  • Session labels come from CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX; the folder list is a clearly-marked folders attrset at the top of the file.

One-time setup that can't be codified in Nix

Remote Control state lives in ~/.claude and there is no settings.json key to enable it, so on link as tunnel:

  1. claude/login once (full-scope OAuth; setup-token / CLAUDE_CODE_OAUTH_TOKEN are rejected). Re-/login when the token expires.
  2. Run claude once inside each listed folder to accept workspace trust.
  3. loginctl enable-linger tunnel only if sessions must run while logged out (may already hold).

Pre-flight verified: nothing in this repo exports ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL into tunnel's env (the only Anthropic key is the standalone premtweet daemon secret), so the main Remote Control blocker is absent. The service also clears them defensively via UnsetEnvironment.

To confirm before merge

  • The folders list is seeded with openclaw and infra — confirm the real OpenClaw workspace path (its dev folder isn't referenced elsewhere in the repo; ~/Documents/Git/openclaw is a guess from the $PROJECTS_DIR convention) and add the rest of the fixed set.
  • On link, confirm which Remote Control surface this build has (claude remote-control --help) and, for server mode, whether --spawn same-dir is needed.

Verify

just rebuild                                    # on link (genswitch)
systemctl --user status claude-rc-openclaw
journalctl --user -u claude-rc-openclaw -f      # should register + show online

Then: Claude app → Code tab → the folder session appears (green dot) → open it → run pwd / a small edit → confirm it acts on link's local files. Repeat for a second folder to confirm they list separately.

Caveats

  • Running Remote Control under systemd isn't an officially documented pattern (docs treat it as a foreground process, no daemon mode); we supervise it ourselves, like openclaw-gateway.
  • While connected, the transcript is stored on Anthropic's servers (Remote Control routes phone↔machine via Anthropic's relay; the phone never connects directly to link).

Generated by Claude Code

Copy link
Copy Markdown
Owner Author

CI note: the Eval / get-check-names failure here is pre-existing on the base branch, not caused by this PR.

The job fails during nix eval while fetching a flake input, before any module in this diff is evaluated:

unpacking 'github:Multipixelone/prem-tweet/c75f964a5e348d35d9769e8d7f1cdc708c0e1989...' into the Git cache...
error: Failed to open archive (... unable to download
'https://api.github.com/repos/Multipixelone/prem-tweet/tarball/c75f964a...': HTTP error 404)

Evidence it predates this branch:

  • main @ 65845f33 (the exact commit this branch is based on) already has Eval = failure (2026-07-22), and the commit before it failed too — last green main eval was 17a1bb2f on 2026-07-08.
  • This PR adds a single file (modules/link/claude-remote-control.nix) and introduces no new flake input and no change to flake.lock, ssh.nix, or anything touching prem-tweet.

So this isn't fixable from within this PR — it needs the prem-tweet flake input pin/access sorted out on main (the pinned rev c75f964a 404s from the CI token). Once the base eval is green again, I'll re-run CI here. The per-check build jobs are continue-on-error and non-blocking regardless.


Generated by Claude Code

Add one Restart=always systemd user service per local project folder on
`link` (modelled on openclaw-gateway), each hosting a Claude Code Remote
Control session rooted in a real local folder. The phone's Claude app is a
window into these local sessions, so folders like the OpenClaw workspace are
always pickable from mobile without pushing anything to GitHub.

The launcher auto-detects the installed claude's Remote Control surface:
`claude remote-control` server mode when present, else the interactive
`--remote-control` flag under a `script` PTY so it runs headless.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KPtXx5e689U6QVbyzPgi13
@Multipixelone
Multipixelone force-pushed the claude/multi-folder-local-access-8warrt branch from fb92be7 to 195ec6e Compare July 23, 2026 22:35
~/Documents/Git/openclaw was a guess and does not exist on link, so the
unit would crash-loop. Use OPENCLAW_STATE_DIR (~/.openclaw) instead --
the same root openclaw-gateway runs in -- so the session sees the config
files alongside workspace/.
@Multipixelone
Multipixelone merged commit 520df97 into main Jul 23, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants