The AI Agent Skills Multi-Machine Sync Problem: A Deep-Dive Across 8 Ecosystems and 6 Strategies
When you open Claude Code on your MacBook, it knows about your custom skills. When you ssh into a cloud VM and run the same tool, those skills are gone. You re-install, re-configure, re-teach. Multiply that across three machines and five agent tools, and you have what I call the AI Agent Skills Multi-Machine Sync Problem.
This is not a hypothetical edge case. Anyone serious about AI-assisted development works across multiple machines — a primary workstation, perhaps a Linux desktop with GPUs for local models, cloud VMs for isolated experiments, and a laptop for meetings and travel. AI agents are increasingly personal tools: they accumulate context, learn your conventions, and grow custom skills over weeks of interaction. When half that context vanishes on machine B, the agent regresses to a generic assistant.
Over the past week, I redesigned the skills sync architecture for my Hermes Agent setup and did a deep comparative study of how the broader AI agent ecosystem handles this problem. This post covers both: the concrete solution I built, and the landscape across eight major agent ecosystems.
The Anatomy of the Problem
AI agent configuration breaks into three categories:
| Tier | What | Examples | Sync Difficulty |
|---|---|---|---|
| Built-in | Skills shipped with the agent distribution | Hermes built-in manifests, Claude Code's default tools | None — updated with the agent itself |
| Third-party | Community skills installed from hub/URL | hermes skills install --url, Claude Code community plugins |
Hard — files sit in local agent directories, not in git |
| Personal | Skills you authored or forked | Your custom blog deploy workflow, your specialized code reviewer | Medium — you control them, can put them in git |
Third-party skills are the crux. They're installed at agent runtime with commands like hermes skills install --url https://raw.githubusercontent.com/.../SKILL.md. The SKILL.md lands in ~/.hermes/skills/ — outside any git repo. On your other machine, the agent has no record this skill was ever installed.
Personal skills are easier in theory: you own them, so you can put them in a git repo. In practice, many people don't bother, and the skill degrades into a single-machine artifact.
The question is: what's the right architecture to keep all three tiers consistent across N machines, without duplicating files and without losing the ability to receive upstream updates?
How Eight Ecosystems Handle This
1. Claude Code (Anthropic)
Claude Code is the most prominent example of "no built-in sync, thriving community workaround."
Config lives in ~/.claude/ (settings.json, skills, commands, agents) plus project-local CLAUDE.md. There is no cloud account. When you run claude on a new machine, it starts with a blank slate.
The community has converged on a pattern: canonical git repo + symlinks. Five independent tools implement this identically:
- saddle (49 stars): canonical config → symlinks to Claude, Codex, Copilot, Cursor, Gemini, OpenCode
- dotai-cli (4 stars): unified
.ai/folder, symlinks to tool-specific paths - glooit (22 stars): rules/commands/skills/MCP sync across Claude, Cursor, Codex, OpenCode, RooCode
- skrills (61 stars): coordinates skills across Codex, Copilot, Claude
- agent-sync (3 stars): universal config sync for four tools
The symlink approach works: you maintain one source of truth, and tools see it where they expect. The downside is fragility — a tool that changes its expected path breaks every symlink. And API keys in settings.json are a constant security risk when sharing config repos.
Verdict: The community has solved it with symlink farms, but there's no standard. Five competing tools doing the same thing is a signal waiting for consolidation.
2. Cursor (Anysphere)
Cursor has two separate sync mechanisms, which is both its strength and confusion.
IDE settings (extensions, keybindings, themes, profiles) sync via Settings Sync — the same battle-tested system inherited from VS Code. This works well: sign in with a Microsoft/GitHub account, and your Cursor feels the same everywhere.
Project rules (.cursor/rules/*.mdc) have no cloud sync. They're project files, expected to be committed to git. This is a principled design choice — project rules belong to the project, not to your personal Cursor account. But it means there's no way to have "personal machine-specific project rules" that follow you across machines but not into the project repo.
Verdict: Hybrid approach — cloud for IDE, git for project. Clean separation, but no answer for the personal third-party skills problem.
3. GitHub Copilot
Copilot takes the most radical architectural approach: personal instructions don't live on your filesystem at all. They're stored server-side on GitHub, accessed when you sign in from any machine. Zero local config to sync.
Repository instructions (.github/copilot-instructions.md) live in the repo and sync via git like any project file.
This is elegant — but has tradeoffs. You can't version-control your personal instructions. You can't edit them offline. You can't programmatically generate them. And Copilot's terminal CLI mode has different config paths than its IDE extension.
Verdict: The most seamless cross-machine experience for a single tool. But it solves the problem by hiding it behind a server, not by giving you control.
4. VS Code (the foundation)
VS Code's Settings Sync is the most mature sync system in any developer tool. It syncs 7 categories of data (settings, keybindings, snippets, tasks, UI state, extensions, profiles), handles 3-way conflict resolution, maintains versioned backups for 30 days locally and 20 versions remotely, and even has an extension API (setKeysForSync) for extensions to opt into sync.
But crucially: it doesn't sync to remote windows (SSH, containers, WSL). And workspace-level settings are intentionally excluded — they're project-specific.
This is the gold standard for what "built-in sync" should look like — but it's IDE-scoped, not agent-scoped. No AI agent ecosystem has reached this level of sync maturity.
Verdict: Best-in-class sync, wrong scope for AI agent skills.
5. OpenCode & Codex CLI
Both are pure filesystem tools with no cloud account. Config lives in ~/.config/opencode/ and ~/.codex/ respectively. The community cross-tool tools (saddle, skrills, glooit) include them. No unique sync innovations.
Codex has an interesting enterprise feature — codex.yaml for organizational governance — but it's not a personal sync mechanism.
Verdict: Same as Claude Code: file-based, community-solved with symlinks.
6. Aider
Dead simple: one YAML file (~/.aider.conf.yml) plus environment variables. No built-in sync. Trivially managed by any dotfiles system (chezmoi, yadm, stow).
Verdict: The simplicity advantage — when your config is one YAML file, sync is almost free. But the tool is limited in scope compared to full agent ecosystems.
7. Windsurf / Cascade
Similar to Cursor: IDE settings via account sync, project rules (.windsurfrules) via git. Smaller community and fewer cross-tool integrations.
Verdict: Same hybrid model, less mature ecosystem.
8. Hermes Agent
Hermes has three layers by design, and each needs a different sync strategy:
- Layer 1 (Built-in): 89 skills shipped with Hermes releases. Updated via
hermes update. The bundled manifest (~/.hermes/skills/.bundled_manifest) tracks checksums. - Layer 2 (Third-party): Skills installed via
hermes skills install --urlorhermes skills tap. Land in~/.hermes/skills/but not tracked by any built-in sync. - Layer 3 (Personal): User-authored skills, supported by
external_dirsconfig that points to a git repo.
The critical insight is that Layer 2 and Layer 3 need fundamentally different sync strategies, and conflating them is the root cause of most sync failures.
The Hermes Solution: Manifest-Driven Sync
After analysis, I settled on a manifest-driven architecture for Hermes:
Layer 3: Personal Skills (git external_dirs)
Personal skills live in a dedicated git repository (github.com/guancyxx/skills), mounted via skills.external_dirs in Hermes config. The repo uses Hermes-native directory structure (category/skill-name/SKILL.md). On a new machine:
cd ~/.hermes
git clone https://github.com/guancyxx/skills.git personal-skills
# Config already points external_dirs at ~/.hermes/personal-skills
# Restart Hermes
The key design rule: zero overlap with Layer 1 or Layer 2. If a skill exists in both ~/.hermes/skills/ and the personal repo, Hermes silently picks one and the other is dead weight. The repo was cleaned from 176 skills down to 163, removing 15 built-in duplicates and 1 hub duplicate.
Layer 2: Third-party Skills (Manifest + Bootstrap)
This is the real innovation. Instead of syncing the installed skill files, we sync a manifest that records where each third-party skill came from.
The manifest lives in the personal-skills repo as skills-manifest.yaml:
url_installs:
- name: hermes-dojo
url: https://raw.githubusercontent.com/Yonkoo11/hermes-dojo/master/SKILL.md
- name: incident-commander
url: https://raw.githubusercontent.com/Lethe044/.../SKILL.md
- name: prism-3way
url: https://raw.githubusercontent.com/Cranot/.../SKILL.md
# ... 10 total
hub_taps:
- repo: tlehman/litprog-skill
path: skills/
tool_setup:
- name: browser-harness
install: uv tool install --editable ~/Developer/browser-harness
- name: opencli-setup
install: npm install -g @jackwener/opencli
A bootstrap script (scripts/sync-skills.sh) reads the manifest and reinstalls on the current machine:
#!/bin/bash
# On a new machine, after cloning the personal-skills repo:
cd ~/.hermes/personal-skills
scripts/sync-skills.sh
# Installs all 10 third-party skills + hub taps
# Restart Hermes
When you install a new third-party skill, the workflow is:
# 1. Install the skill
hermes skills install --url https://raw.githubusercontent.com/.../SKILL.md --yes
# 2. Add it to the manifest
# Edit skills-manifest.yaml, add under url_installs:
# - name: <skill-name>
# url: <URL>
# 3. Commit and push so other machines pick it up
cd ~/.hermes/personal-skills
git add skills-manifest.yaml
git commit -m "skill: add <name> to manifest"
git push origin master
On the other machine:
cd ~/.hermes/personal-skills
git pull origin master
scripts/sync-skills.sh
Why Not Just Symlinks?
The Claude Code ecosystem pattern — canonical repo + symlinks — seems simpler. Why not just symlink ~/.hermes/skills/ to a git repo?
Because Hermes's skill resolution is more complex than Claude Code's. Hermes has a bundled manifest, hub lock files, trust levels, scan verdicts, and a skills curator. Simply symlink-replacing the skills directory would break the hub/lock infrastructure and lose metadata that Hermes depends on.
The manifest approach separates state from sync:
- Hub metadata (trust levels, content hashes, install timestamps) stays local
- The manifest is the minimal shared surface — just "skill X came from URL Y"
- The bootstrap script reconstructs the full state from this shared surface
The Skill Graph Integration
This architecture is backed by three skills in the personal-skills repo:
- skill-creation-guide (Phase 5B): after creating/editing a personal skill, sync to the git repo
- hermes-install-skill-with-manifest-sync: after installing a third-party skill, add it to the manifest
- hermes-sync-personal-skills-from-github: the full 3-layer reference for multi-machine setup
Each trigger is clearly scoped:
| Action | Skill to Load |
|---|---|
| Create/edit own skill | skill-creation-guide |
| Install community skill | hermes-install-skill-with-manifest-sync |
| New machine setup | hermes-sync-personal-skills-from-github |
| Hermes update | Automatic (Layer 1) |
Results
After implementing:
Before:
personal-skills: 176 SKILL.md (15 built-in overlaps, 1 hub overlap)
skills/: 100 SKILL.md (89 built-in + 10 hub + 1 manual overlap)
After:
personal-skills: 163 SKILL.md (zero overlaps)
skills/: 97 SKILL.md (89 built-in + 10 hub, zero overlaps)
The layers are mathematically disjoint. No silent pick-one, no dead weight.
Six General Approaches Across the Ecosystem
Zooming out from individual tools, the broader configuration management landscape offers six patterns:
1. Manual Copy (The Baseline)
scp ~/.claude/ new-machine:~/.claude/
Pros: zero setup. Cons: drifts immediately, no history, no conflict resolution. This is what most developers do until they get burned.
2. Dotfiles with Git
Bare git repo or tools like chezmoi/yadm/stow that manage home directory configs.
chezmoi init --apply https://github.com/user/dotfiles
Strengths: mature ecosystem, battle-tested, handles secrets (chezmoi's age encryption), supports templates for machine-specific values.
Weaknesses: file-based — doesn't understand skill semantics. Manages bytes, not intent. If a tool moves its config directory, all dotfiles break.
This works well for tools with simple config (Aider's single YAML file) but strains for complex agent ecosystems with metadata files, lock files, and manifests.
3. Symlink Farms
Canonical repo with structured directories, symlinked to tool-expected paths.
~/canonical-config/
├── rules/my-rules.mdc → symlinked to ~/project/.cursor/rules/my-rules.mdc
├── skills/my-skill.md → symlinked to ~/.claude/skills/my-skill.md
└── commands/build.sh → symlinked to ~/.claude/commands/build.sh
The dominant Claude Code community pattern (saddle, dotai, glooit). GNU stow is the classic Unix tool that implements this generically.
Strengths: single source of truth, changes propagate instantly. The canonical repo is just a git repo.
Weaknesses: brittle — depends on tool-specific paths not changing. Doesn't handle tools that write metadata alongside config files. Symlinks confuse IDEs and backup tools. And at scale, managing which file goes where across 6+ tools becomes its own project.
4. Cloud-Hosted Config
Personal instructions stored server-side, synced on sign-in. The Copilot model.
Strengths: the best user experience — it "just works" across machines without any user intervention.
Weaknesses: vendor lock-in, no version control, no offline access, opaque. You can't git diff your instructions before a change. You can't git blame to see when a rule was added. And if the cloud service goes down, your agent reverts to defaults.
5. Manifest-Driven Bootstrap
A minimal shared record of "what was installed from where," with a script that reconstructs the full environment.
The approach I built for Hermes. Also the conceptual model behind tools like Nix and home-manager — but implemented with lightweight YAML and shell scripts rather than a functional DSL.
Strengths: separates state from sync, minimal shared surface, version-controllable, supports heterogeneous environments (different machines can have different subsets).
Weaknesses: requires discipline — you must remember to update the manifest after every install. The bootstrap script must be idempotent and handle partial failures gracefully. Tool-specific metadata (trust levels, content hashes) is lost between machines and must be reconstructed.
6. Declarative Configuration (Nix / home-manager)
Fully reproducible, deterministic environment generation.
# home-manager configuration
programs.hermes = {
enable = true;
skills = {
personal = [ ./skills/blog-build-deploy ./skills/code-review ];
third-party = [
{ name = "hermes-dojo"; url = "..."; }
];
};
};
Strengths: the endgame. Fully deterministic, reproducible across any machine, atomic upgrades, rollbacks. If you're already using NixOS or home-manager, this is the obvious choice.
Weaknesses: steepest learning curve in the ecosystem. Requires buying into the Nix ecosystem. Most AI agent users aren't Nix users. And many agent tools aren't packaged for Nix, adding overhead.
Decision Matrix
| Approach | Setup Cost | Drift Resistance | Cross-Tool | Cross-Machine | Secret Safety |
|---|---|---|---|---|---|
| Manual copy | Zero | None | None | Manual | Risky |
| Dotfiles (git) | Low | Medium | Low | Good | Moderate (chezmoi) |
| Symlink farms | Medium | Good | Good | Good | Risky |
| Cloud-hosted | Zero | Good | None | Excellent | High |
| Manifest bootstrap | Medium | Medium | Good | Good | High (manifest is secret-free) |
| Declarative (Nix) | High | Excellent | Excellent | Excellent | Excellent |
The Secret Problem
A cross-cutting concern that every approach must address: API keys and credentials.
Most agent tools store API keys in config files (settings.json, config.yaml, .env). When you sync these files across machines, you're syncing secrets. The solutions:
- Environment variables: set keys via
~/.zshrcsourced from a secrets manager. Config files reference env vars, not literal keys. - chezmoi encryption:
chezmoi add --encryptusesageto encrypt secrets at rest. - Manifest separation: the manifest records skills, not keys. The bootstrap script triggers installs but doesn't move secrets.
- Never commit API keys: this should be obvious by 2026, but Claude Code's settings.json is a recurring footgun.
The manifest approach has a natural advantage here: the manifest is secret-free by design. It records URLs and repo references, not credentials. The bootstrap script runs hermes skills install, which pulls skills from public URLs — no keys involved.
The State of the Art in 2026
The current landscape:
-
No AI agent ecosystem has a satisfying built-in sync story. VS Code's Settings Sync is the closest thing to "solved," but it's IDE-scoped. Among AI agents, Copilot's server-side approach is the most seamless user experience, but it trades control for convenience.
-
The community is independently converging on canonical-repo + symlinks. At least five separate projects implement this pattern for Claude Code. The convergence signal is strong — this is likely the "correct" pattern for filesystem-based tools. The fragmentation is in implementation, not architecture.
-
The gap is cross-tool + cross-machine simultaneously. Individual tools handle cross-machine poorly. Individual machines handle cross-tool poorly. No tool handles both well, and that's the real problem for users who run 3+ agents across 3+ machines.
-
Manifest-driven sync is a pragmatic middle ground. It separates the minimal shared surface (where did this come from?) from machine-local state (trust levels, update timestamps, checksums). It's compatible with git, doesn't require symlink fragility, and naturally avoids secret leakage.
-
Declarative approaches (Nix/home-manager) are the endgame but the adoption curve is too steep for mainstream AI agent users in 2026. As agent tooling matures and Nix packaging improves, this will likely become the standard answer — but we're 3-5 years away.
A Recommendation for Tool Builders
If you're building an AI agent tool and want to support multi-machine workflows, here's what I'd recommend based on this analysis:
-
Separate built-in, installed, and personal config into distinct directories with clear precedence rules. Hermes's three-layer model is a good reference.
-
Provide a manifest file that records all third-party installations — URL, timestamp, content hash, trust level. Make this file the sync surface.
-
Ship a bootstrap command like
hermes skills sync --manifest <path>that reads the manifest and reinstalls missing skills. Make it idempotent. -
Never sync credentials. Reference env vars in config, not literal keys. Your manifest should be safe to commit to a public repo.
-
Design for git-native workflows. If users can
git clone && ./bootstrap.shand have their agent ready, you've solved 80% of the problem.
The AI agent ecosystem is still in its "dotfiles era" — the period before a standard emerges, when every user invents their own sync strategy. VS Code's Settings Sync took years to mature into what it is today. Hopefully the agent ecosystem gets there faster, because the cost of fragmented context is higher for agents than for editors: an editor without your keybindings is annoying. An agent without your accumulated skills is lobotomized.