npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

claude-remote-sync

v0.2.1

Published

Run Claude Code on a trusted remote machine, kept in sync with your control machine via Mutagen.

Readme

claude-remote-sync

npm version npm downloads license

Command name: the CLI is invoked as claude-remote-sync, matching the npm package name — that's the command every example below uses. claude-remote (no -sync) still works today as a legacy alias so existing installs keep working unchanged, but it's deprecated and will be removed in a future release. New setups should use claude-remote-sync.

What this is

claude-remote-sync runs Claude Code (with --dangerously-skip-permissions) on a separate, fully-trusted machine — instead of on your own main machine — while making that remote session feel local. It keeps two things continuously synced between your control machine and the remote machine via Mutagen:

  • Claude Code's own config and session history (~/.claude)
  • Your active project's files

Then it drops you into a live Claude Code session on the remote over SSH + tmux, working on the synced copy of your project.

Why: --dangerously-skip-permissions gives Claude Code unrestricted filesystem/shell access with no confirmation prompts — safer to run against a separate machine's filesystem than the one you actually care about protecting. Continuous two-way sync is what makes that separate machine still feel like your own dev environment: same project files, same Claude session history, resumable from either side.

The remote machine doesn't need to be on the same local network as your control machine — any host you can SSH into works (LAN, a machine reachable over the internet, or one behind a VPN/Tailscale). See "How it works" below for what's actually required.

How it works

  Control machine                                  Remote (Linux / WSL2)
  ------------------------                         ------------------------

  ~/.claude               --- Mutagen sync --->     <homeMirrorPath>/.claude
  (config + history)          "claude-home"
                               (started once by
                                `claude-remote-sync setup`,
                                runs permanently)

  <active project>        --- Mutagen sync --->     <same absolute path>
                               "workspace"
                               (retargeted on every
                                `claude-remote-sync launch`)

  `claude-remote-sync launch` --- SSH + tmux --->    Claude Code running
  attaches here                                      inside the workspace

Two Mutagen sync sessions run independently of each other:

  1. claude-home — mirrors ~/.claude (Claude Code's config and session history) between the control machine and <homeMirrorPath>/.claude on the remote. Created once by claude-remote-sync setup and left running in the background from then on — it isn't tied to any particular project.
  2. workspace — mirrors your active project directory. Retargeted every time you run claude-remote-sync launch, either against the project set in config.yaml or a different one passed via CLAUDE_REMOTE_WORKSPACE.

Both sessions sync two-way. If the same file changes on both sides before a sync catches up, the remote's copy always wins — see "Operational rules" below for what that means in practice.

On top of sync, claude-remote-sync launch opens an SSH connection to the remote and attaches to a tmux session there, running Claude Code inside the synced workspace. Detaching (Ctrl-b d) leaves that tmux session — and Claude Code — running on the remote; running claude-remote-sync launch again reattaches to it instead of starting a new one.

Why paths have to line up: homeMirrorPath in config.yaml is set to mirror the control machine's own home directory path (e.g. /Users/pak), and your project lives at the same absolute path on both sides. This is what lets Claude Code resume a session that has history from the other machine — its own path-derived session keys only match up because the paths are identical, not just similarly structured.

Components

| Component | Runs on | Responsibility | |---|---|---| | claude-remote-sync CLI (aka claude-remote, deprecated) | Control machine | Everything you run — setup, launch, status, monitor, config. | | config.yaml | Control machine | Single source of truth: remote host/user/OS, path layout, sync ignore list, tmux session name, launch behavior. | | Mutagen | Control machine (daemon) + Remote (agent, auto-installed by Mutagen itself) | Owns both sync sessions described above. | | tmux, Node.js (via nvm), Claude Code CLI | Remote | Installed automatically by claude-remote-sync setup — nothing to install by hand beyond SSH access. |

Prerequisites

On the control machine (whatever machine you don't want --dangerously-skip-permissions running against directly):

  • Node.js >= 18 (to install/run the claude-remote-sync CLI itself)
  • Mutagen installed (e.g. brew install mutagen-io/mutagen/mutagen on macOS — see mutagen.io/documentation/introduction/installation for other platforms)
  • SSH key access to the remote already working — ssh <user>@<host> should need no password or prompt. This tool never generates or copies keys for you.

On the remote machine:

  • Linux (any apt-based distro) or Windows with WSL2 already installed (native Windows without WSL2 is not supported).
  • Reachable over SSH from the control machine.
  • On Windows specifically: the machine's SSH server must be configured so an incoming SSH connection lands inside WSL2, not native PowerShell/cmd.exe — the default OpenSSH Server on Windows drops you into PowerShell unless it's been set up to hand sessions to the Linux userspace. claude-remote-sync setup assumes this is already true; it does not check or configure it, and every remote command it runs expects a bash/Linux shell. Step-by-step: docs/remote-setup/windows-wsl2.md (Windows) or docs/remote-setup/linux.md (Linux).
  • tmux, Node.js, and the Claude Code CLI are not manual prerequisites — claude-remote-sync setup installs all three.

Setup

Install:

npm install -g claude-remote-sync

This installs the claude-remote-sync command (and, for backward compatibility, the deprecated claude-remote alias).

Create ~/.config/claude-remote/config.yaml (the config directory name is unchanged from before the claude-remote-sync command name existed, so upgrading an existing install doesn't move or lose your config):

mkdir -p ~/.config/claude-remote

with these fields:

remote:
  host: 192.168.1.50          # or a public hostname/IP — LAN is not required
  user: pak
  sshKeyPath: ~/.ssh/id_ed25519   # optional — falls back to ssh-agent/~/.ssh/config
  os: linux                   # or windows-wsl2 — checked against `uname -a` during setup
  homeMirrorPath: /Users/pak  # must match `echo $HOME` on THIS control machine

workspace:
  local: /path/to/your/project

sync:
  ignore: [node_modules, .venv, dist, build, __pycache__]

tmux:
  sessionName: claude-remote

launch:
  autoStartClaude: true
  claudeArgs: ["--dangerously-skip-permissions"]

Then run the one-time setup, which verifies SSH access and installs everything needed on the remote (tmux, Node.js, the Claude Code CLI), and starts the claude-home sync session:

claude-remote-sync setup

Daily use

claude-remote-sync launch
# or, to work on a different project without editing config.yaml:
CLAUDE_REMOTE_WORKSPACE=/path/to/other/repo claude-remote-sync launch

launch syncs the active workspace and drops you into a live Claude Code session on the remote, inside a tmux session. Detach with Ctrl-b d any time; running claude-remote-sync launch again reattaches to that same session instead of starting a new one.

If your workspace root is itself a folder of unrelated projects (e.g. CLAUDE_REMOTE_WORKSPACE=/Users/you/Projects, containing Deepsel/, Cookie/, ...), launch prompts you to pick which immediate subfolder Claude Code should actually cd into and start from — without narrowing what gets synced, which always stays the full workspace root. Picking a folder gets its own tmux session (so switching folders across launches never leaves you stuck in a stale cd), and Claude Code picks up that folder's own CLAUDE.md/.claude/ config and session history instead of the root's. The prompt is skipped (defaulting to the root) whenever CLAUDE_REMOTE_WORKSPACE is set, --yes is passed, or the workspace has no subfolders to choose from — use --folder <name> (or --folder root) to skip it explicitly and pick non-interactively.

Check sync/connectivity state without launching: claude-remote-sync status.

Command reference

claude-remote (no -sync) is a deprecated alias for every command below — identical behavior, kept only so existing installs don't break. Use claude-remote-sync.

  • --config <path> (global option, before the subcommand) — use a config file other than the default ~/.config/claude-remote/config.yaml.
  • claude-remote-sync setup — one-time: verify SSH access, install remote dependencies, start the ~/.claude sync session.
  • claude-remote-sync launch [-y|--yes] [-f|--folder <name>] — sync the active workspace and drop into a live Claude Code session on the remote. -y/--yes skips the concurrent-session confirmation prompt described below (see "Operational rules") — useful for scripting, but skips a real safety check, so don't reach for it out of habit. -f/--folder <name> launches directly in that immediate subfolder of the workspace root (or root for the root itself), skipping the interactive folder picker.
  • claude-remote-sync status — show SSH connectivity and both sync sessions' state.
  • claude-remote-sync monitor [--interval <seconds>] — live-stream a combined dashboard: both sessions' Mutagen sync status plus CPU/RAM/disk performance for the control machine and the remote, refreshed every --interval seconds (default 3). Ctrl+C stops watching, not the sync itself — it keeps running in Mutagen's background daemon either way.
  • claude-remote-sync config — print the fully resolved config (after any CLAUDE_REMOTE_WORKSPACE override) as JSON; useful for confirming which workspace/paths a command would actually use before running it.

Operational rules (read before your first real session)

  • Never run Claude Code on both the control machine and the remote at the same time. ~/.claude is synced continuously, not instantly — running both sides at once can clobber the control machine's session/memory state (the remote side wins on conflict). launch prompts you to confirm this before every session; don't reflexively pass --yes unless you've actually checked.
  • Avoid git write operations (commit, checkout, merge) on both sides at the same time, for the same reason — both sides have a live, bidirectionally-synced .git directory.
  • Conflicts, if they happen, default to "remote wins". Check claude-remote-sync status if something looks like it reverted unexpectedly.

Publishing

Published to npm as claude-remote-sync. Releases are built and published by .github/workflows/publish.yml, triggered by pushing a vX.Y.Z tag — nothing is ever published from a local machine.

One-time setup (do this once, before the first release):

  1. npm login locally and run npm publish --access public once by hand. npm's Trusted Publisher setting (used for every release after this) lives on a package's settings page, which only exists once the package has been published at least once.
  2. On npmjs.com: package page → Settings → Publishing access → add a Trusted Publisher — GitHub Actions, repo anhkhuong975/claude-remote, workflow file publish.yml, no environment.
  3. From then on, CI publishes via OIDC (no NPM_TOKEN secret needed, per the id-token: write permission in the workflow).

Every release after that:

npm version patch   # or minor / major — bumps package.json + creates a git tag
git push --follow-tags

The workflow verifies the pushed tag matches package.json's version, builds, and publishes with provenance.

Manual end-to-end verification checklist

This project has no automated tests and was implemented without a reachable SSH target available during initial development. The following still needs a real run against an actual remote machine before trusting this day-to-day:

  • [ ] After a fresh npm install -g claude-remote-sync: both which claude-remote-sync and which claude-remote resolve, and claude-remote --help / claude-remote-sync --help print identical output (the deprecated alias behaves identically to the primary command).
  • [ ] claude-remote-sync setup against a real, freshly-provisioned Linux or WSL2 machine: completes without error, leaves tmux, node, and claude installed, and mutagen sync list claude-remote-claude-home shows the session as Watching for changes.
  • [ ] Edit a file inside ~/.claude/projects/ on the control machine; confirm it appears on the remote within a few seconds (and vice versa).
  • [ ] claude-remote-sync launch: confirm it attaches to the correct tmux session, in the correct directory, with CLAUDE_CONFIG_DIR set correctly (echo $CLAUDE_CONFIG_DIR inside the session), and that Claude Code can resume a session that has history from the control machine.
  • [ ] Detach (Ctrl-b d), run claude-remote-sync launch again: confirm it reattaches to the same tmux session instead of creating a new one.
  • [ ] Against a workspace root with subfolders, plain claude-remote-sync launch (no --folder, no CLAUDE_REMOTE_WORKSPACE, no --yes): confirm the folder picker appears, and picking a subfolder cds into it on the remote with that subfolder's own CLAUDE.md/.claude/ config picked up. Launch into a second, different subfolder without killing the first tmux session; confirm tmux ls shows two distinct sessions, each still cd'd correctly into its own folder.
  • [ ] claude-remote-sync launch --folder <name>: confirm it skips the picker and launches directly in that folder; claude-remote-sync launch --folder <bogus-name> fails immediately with the valid-choices list, before attempting any SSH connection.
  • [ ] Edit a file in the workspace on the remote; confirm it propagates back to the control machine.
  • [ ] Conflict direction (highest-risk item — see the WHY-comment above createSession in src/sync.ts): pause or disconnect the workspace Mutagen session (mutagen sync pause <name>), edit the same file on both the control machine and the remote with different content, then resume/reconnect (mutagen sync resume <name>) and let it resolve. Confirm the remote's edit is the one that survives. If the control machine's edit survives instead, that confirms the Critical finding's risk materialized — --default-conflict-resolution=beta either isn't a real flag or doesn't override two-way-resolved's default, and the conflict-resolution flag needs fixing before this tool's "remote wins" claim can be trusted.
  • [ ] claude-remote-sync status: confirm both sessions show as syncing and SSH shows as reachable.
  • [ ] claude-remote-sync monitor: confirm both the Sync section and both Performance sections render without errors against a real remote, and the numbers roughly match what the control machine's own system monitor (Activity Monitor on macOS, Task Manager on Windows, htop on Linux) and htop on the remote report at the same moment.
  • [ ] While monitor is running, briefly disconnect the remote (e.g. disable Wi-Fi for a few seconds): confirm the remote Performance section shows the (stale — ...) marker instead of crashing the dashboard, and recovers automatically once connectivity returns.
  • [ ] Ctrl+C out of monitor, then check for leftover processes/sockets: ps aux | grep '[s]sh -f -N -M' should show nothing, and the control socket file (/tmp/claude-remote-ssh-*.sock) should be gone.