| name | sync-environments |
| description | Use when the user wants to sync packages, dotfiles, or configuration from a primary desktop/workstation to a secondary laptop (or any base→remote pair) over SSH. Compares environment snapshots, applies hardware-aware judgement (don't push heavy models/apps to weaker hardware), and produces an incremental, actionable install/remove/sync plan rather than a perfect clone. |
Sync Environments
Hardware-aware, incremental synchronisation of two Ubuntu/Debian-family systems — a base (the more capable machine the user is sitting at) and a remote (a less capable machine, typically a laptop, reachable over SSH via the alias laptop, configurable).
This skill is the brain behind the /sync-os command. It can also be invoked directly when the user says things like "sync my laptop", "compare my desktop and laptop packages", or "what should I install on the laptop".
Operating Principles
Hardware Capability Awareness
The base environment is significantly more powerful than the remote. Do not recommend syncing packages that would not run effectively on the remote. Example: if the base has Ollama with a large model that would not perform well on a 4–8 GB-RAM laptop, do not suggest ollama pull for that model on the remote.
Incremental Sync, Not Replication
This skill runs periodically. The remote will lag behind the base — sometimes significantly. The goal is not a carbon copy. Provide an incremental sync of the key packages and configs the user needs so that when they travel, they have their familiar tools without weeks of catch-up installs.
Removal Logic
If a package is on the remote but not on the base, infer that the user no longer finds it valuable on their primary machine, and propose it as a candidate for removal from the remote.
Workflow
-
Locate the script. The bundled scripts/sync-agent.sh (in this plugin) gathers the snapshots. Resolve its absolute path via ${CLAUDE_PLUGIN_ROOT}/scripts/sync-agent.sh if available, otherwise from the plugin install directory.
-
Confirm the SSH alias. Default is laptop. Ask the user once if it's something else (e.g. nuc, travel-laptop) and pass it via the env var SYNC_REMOTE_HOST (the script falls back to laptop).
-
Choose a profiles directory. Default is ${CLAUDE_USER_DATA:-$HOME/.claude/data}/os-sync-agent/profiles. Override with SYNC_PROFILES_DIR=... for one-off comparisons. Never write profiles into the plugin install dir — that's read-only.
-
Gather profiles. Invoke the script in one of these modes:
--gather-profiles — both base and remote
--gather-base / --gather-remote — one side only
--full — gather both then analyse (default)
--sync — analyse already-gathered profiles
-
Read the snapshots. For each side (base/, remote/):
dpkg-packages.txt, apt-packages.txt — system packages
snap-packages.txt, flatpak-packages.txt — sandboxed apps
pip-packages.txt, conda-envs.txt — Python
ollama-models.txt — local LLMs
system-info.txt, cpu-info.txt, memory-info.txt — hardware
dotfiles/ — .bashrc, .zshrc, .profile, .gitconfig, .vimrc, .tmux.conf
-
Compare and categorise. Identify:
- Install on remote — present on base, missing on remote, and appropriate for the remote's hardware.
- Remove from remote — present on remote, absent from base.
- Dotfile drift — diffs in tracked dotfiles worth syncing.
- Skipped — items deliberately not synced, with one-line reasoning (e.g. "Ollama llama3:70b — exceeds 16 GB laptop RAM").
-
Bucket recommendations by safety:
- Essential CLI tools — safe to sync
- Development tools — usually safe
- Resource-intensive applications — evaluate against
cpu-info.txt / memory-info.txt
- Large models/data — usually skip for the laptop
Output Format
Always produce four sections, in this order, with copy-pasteable commands:
Packages to Install on Laptop
sudo apt install <package1> <package2>
sudo snap install <package>
flatpak install -y <ref>
pip install <package>
Packages to Remove from Laptop
sudo apt remove <package>
sudo snap remove <package>
Dotfiles to Sync
scp ~/.gitconfig laptop:~/.gitconfig
diff <(ssh laptop 'cat ~/.bashrc') ~/.bashrc
Skipped Items (with reasoning)
<item> — <one-line reason>
Decision Guidelines
- Default to caution. When unsure whether something belongs on the laptop, ask the user before adding it to the install list.
- Don't issue destructive commands. Show the
apt remove lines but let the user execute them — don't shell out automatically.
- Don't trust empty profiles. If
system-profiles/remote/ is missing or laptop was unreachable during gather, say so explicitly and offer to run --gather-remote first.
Common Failure Modes
- Laptop unreachable —
ssh -o ConnectTimeout=5 -o BatchMode=yes laptop fails. Tell the user, suggest checking ~/.ssh/config for the laptop Host entry and that the laptop is on the LAN/VPN.
- No
claude CLI — the script's --sync mode shells out to claude. If running from inside Claude Code, prefer reading the profiles directly and producing the analysis yourself rather than re-invoking the CLI.
- Profiles dir on a read-only path — fall back to
$HOME/.claude/data/os-sync-agent/profiles.
Notes
The original system prompt is preserved at system-prompt.md in the plugin root for reference. This skill supersedes it but stays consistent with its philosophy.