Two machines, one mess

Give every kind of state one owner, and every concurrent agent its own workspace

Two machines, one mess

Last week in our community chat, one of our members described his new setup: he types into his agent on his Mac, and an agent on his Windows server does the work. A gateway connects the two. He had it running within a day. Then he hit the wall everybody hits, and he spotted it fast: "having project files and sessions on two machines is troublesome."

Another member replied that he'd already solved this for his own two-person operation with Dropbox. I suggested Tailscale and SSH. Somebody else is eyeing a NAS. Four operators, four answers, and all of us circling a problem that barely existed a year ago: the moment your agents outgrow one computer, where does their stuff live?

I put my agent to work researching what people are actually doing about this in 2026, because my gut said we weren't the first to hit it. We weren't. Anthropic's own issue tracker has a feature request asking for exactly our member's setup, "compile on Windows, edit on Mac" from a single prompt, and the bot auto-closed it after finding three duplicate requests. A Codex discussion with more than 60 votes complains that "threads and session context appear to be tied to the local environment." That is user demand, not a vendor commitment. Still: this is a real, mostly unsolved problem, and the vendors know people are hitting it.

The tempting answer is: get one always-on machine, point every other device at it, and stop copying files. That is the right answer for live agent sessions. It is not the whole answer for a fleet. Remote control lets you reach the same agent from two computers. It does not tell two agents how to share a codebase, a database, a Dropbox folder, or a set of customer records without stepping on each other.

The useful rule is narrower:

Give every kind of state one authority. Give every concurrent agent its own workspace. Use remote windows and explicit handoff seams instead of syncing live state.

"One home, many windows" still holds for sessions. It does not hold for source code, and it does not hold for every database.

The problem

You started with one machine. The projects lived in a folder, the session history lived somewhere you never had to think about, and everything just worked.

Then you added a second machine. Maybe an always-on server so agents keep working when the laptop sleeps. Maybe a desktop at the office and a laptop at home. Now every piece of agent state has two possible homes, and the two disagree within hours.

The mistake almost everyone makes, and I include myself here, is treating this as one folder-sync problem. It is five.

Documents and media are ordinary files: proposals, photos, PDFs, spreadsheets. These can live in Dropbox, Drive, or a NAS. They fork under concurrent writes, but they do not usually corrupt a database.

Source code already has a collaboration system. Git is built for many copies, as long as each worker has its own branch or worktree and you integrate through commits and review. A shared live checkout is still a mess even when every agent runs on the same machine.

Active workspaces are the uncommitted hour: dirty files, local config, generated build output. This is the kill zone. One operator running agents on different machines put it better than I could: "the last hour of uncommitted work stays invisible, and that hour is where agents do the most damage."

Session state is the agent's memory of what happened: transcripts, resume checkpoints, lock files, and little databases. This stuff fights being copied. Claude Code stores sessions as JSONL files keyed to your working directory. Hermes stores its canonical conversation history in a local SQLite database, plus config, skills, and credentials sitting next to it.

Live databases and secrets are the part that will actually take the business down. SQLite says using it over a network filesystem risks corruption, especially NFS. Write-ahead-log mode does not work over a network filesystem when processes sit on different hosts. Their page on remote databases adds the nasty part: the failures are "inevitable" but "not frequent or repeatable." The setup will pass every test, run fine for weeks, then eat something on a Tuesday. Copying a live SQLite file while a transaction is open can produce a corrupt backup. Secrets do not belong in any of those folders.

Many of the failure stories my agent found trace back to ignoring that split. One practitioner synced everything with Syncthing across two Windows machines with identical usernames and paths, and reported that "it does sync all files, but the conversation history doesn't open." Another got Dropbox working across three Macs, but only under monastic discipline: one machine at a time, fully exit the tool, wait for sync to finish, identical absolute paths everywhere. Read that rule list again. Every single rule is a thing an unattended agent will violate.

The rest of the wrecks were same-machine concurrency, not sync. Shared checkouts were one mixed-fleet operator's "single biggest source of chaos." Another post-mortem of a parallel-agent pileup ended with raced migrations, clobbered diffs, and poisoned caches: "none of these were the model being dumb. they were plumbing." Putting every agent on one hub does not fix that. It just moves the collision into one room.

How to identify it

You have this problem right now if any of these sound familiar:

  1. Files named like scar tissue. Anything containing conflicted copy or .sync-conflict in your project folders. Dropbox forks a file rather than merging it when two machines touch it, and their docs specifically call out auto-saving applications as a trigger. An agent is an auto-saving application with a work ethic. Syncthing does the same with .sync-conflict files, then syncs the conflict copies to every other machine.
  2. The agent on machine two has amnesia. You resume a session and it starts fresh, or the history sidebar is empty even though you can see the transcript files sitting right there. Path-keyed session storage means the files arrived but the meaning didn't.
  3. You've become the sync layer. You finish work on one machine, wait for a push or a sync, then walk to the other machine like a courier. The tooling was supposed to remove you from the loop. Instead you are the most reliable component in it.
  4. Two agents did conflicting work and neither noticed. The raced database migration, the clobbered refactor, the build that fails on a machine where nobody changed anything. This can happen on one hub with one shared checkout. Conflict-copy filenames will not catch it.

How to fix it

I went in assuming this was a file synchronization problem, and the job was picking the right sync tool. The strongest practitioners, and now the vendors themselves, have landed somewhere more specific for live sessions: stop moving the running work between machines. Give that session one home, and move the view to it.

That is still the right first move for transcripts and resume state. It is not a universal architecture. Source code wants copies. Documents can sync. Databases want an owner and a seam. Secrets want a vault, not a folder.

Here is the sorting rule I wish I'd started with:

Kind of state One authority How workers collaborate
Documents, photos, PDFs Dropbox, Drive, OneDrive, or a NAS folder Sync, one writer at a time, watch for conflict copies
Source code The Git remote Isolated clone or worktree per agent, then review and merge
Active workspace The machine running that agent Do not share a live checkout. Commit or snapshot before handoff
Agent sessions The gateway or host running the session Remote Control, a Hermes remote connection, or a vendor cloud window
File databases (SQLite) The process that owns the file Talk through a CLI, API, or MCP seam. Copy only cold snapshots
Postgres / MySQL The database server Isolated database or schema per agent
SaaS records (QuickBooks, Jobber, Shopify) The SaaS vendor Authenticated API, with writes gated
Secrets A secret manager or the host's credential store Inject at runtime. Never sync .env files

You do not pick one tool for the whole row. You pick the row, then the tool.

That gives three realistic operator paths, plus a fourth if you actually run software.

Path 1: cheap cloud or sync. Dropbox, Drive, OneDrive. This is the rung our member solved his two-person operation with, and for document-shaped files it genuinely holds. Lowest cost, lowest ceremony. Know the edges: conflicted copies under concurrent writes, almost no ignore-list, and keep it far away from live session directories and live databases. If you cannot name a single-writer rule, do not put agents in that folder.

Path 2: one remote execution home. The agent process, its session, and its active workspace stay on one always-on machine. Your laptop, phone, and office desktop are windows. Hermes Desktop's gateway registry can register a remote, SSH, or cloud backend; chats, sessions, and memory stay scoped to the gateway you opened. Registering the hub does not merge two machines' files. You still have to do the project work on the hub profile and stop doing it on the local one. Claude Code Remote Control is the same idea in fewer words: "Claude keeps running locally the entire time... The web and mobile interfaces are a window into that local session." Codex Cloud is a different shape: each task runs in an isolated cloud environment seeded from GitHub or GitLab, and durable work comes back as a diff or a pull request. That is not one persistent cloud workstation owning every file. The Git remote is the handoff.

SSH belongs here, with one distinction that ate a lot of setups. SSH into the machine and run the agent there: that is the hub. Mount the remote folder with SSHFS or Taildrive and run the agent on your laptop: that is still moving live files to the work, and SQLite's network-filesystem warning applies. Tailscale is excellent private plumbing when you need host-to-host reachability. It is not required for Claude Remote Control, Codex Cloud, or a Hermes messaging window on Telegram. Taildrop and Taildrive are still marked alpha, and Taildrive is a network filesystem, so do not park a live database on it.

Path 3: a NAS, later. When capacity, snapshots, and a file home that is not any of your laptops start to matter, a NAS earns its keep as backup target, media archive, and maybe a bare Git remote. Entry hardware is a few hundred dollars before drives, or TrueNAS on a box you already own. A NAS is not automatically "real backup." Snapshots on the same box do not protect you from theft, site loss, or ransomware. You still want a versioned copy somewhere else, and you still want to restore it once. Live worktrees belong on local disk. Live SQLite belongs on the machine that runs the process.

If you run software, add isolation. One hub with one shared checkout is how you get the plumbing failures above on a single computer. Claude Code now starts parallel sessions in git worktrees so one session's edits never touch another's files. Hermes has --worktree for the same reason. Codex Cloud already gives each task its own environment. The pattern is: one canonical repository, one worktree and branch per concurrent agent, one isolated runtime and development database, merge through review. Imagine a small inventory app whose book of record is a local SQLite file, and you want a second always-on machine to start helping. That second agent gets a clone or worktree, not the live database. For analysis it gets a snapshot or a read-only query seam. Code comes back through a pull request. The live file never rides Dropbox, Syncthing, SSHFS, or a NAS mount.

If you still need the same files in two places, climb by need. Git first, for committed code. Consumer sync for documents. Syncthing only for named folders with ignore patterns, file versioning, and a single-writer rule. The one detailed public blueprint, syncing 253,000 files across 30 project directories, keeps sessions machine-local on purpose.

The major harnesses now ship parts of the hub pattern. They do not reconcile two active copies of a project, isolate two agents on the same host, or migrate every local session. You still have to assign owners.

Below the line for Operators: a state inventory you can hand to your agent, the three paths built safely, software-fleet isolation, harness recipes, a backup routine that does not copy a live SQLite file, and an acceptance test that actually checks concurrency.

The playbook: one authority per store, one workspace per agent

The goal is not "one machine owns every file." The goal is: every mutable store has one owner, every concurrent agent has its own workspace, and you can lose a laptop without losing the business. Losing the hub still means downtime. A verified off-host backup is what limits the damage to the copy you actually tested.

1. Inventory the state

Make a five-column list before you install anything:

  1. Name of the store (the client folder, the git repo, the SQLite file, the QuickBooks company, the session directory).
  2. Kind of state, using the table above.
  3. Current machines that can write to it.
  4. The one authority you want.
  5. The handoff seam (Git PR, Dropbox folder with a single-writer rule, Remote Control, read-only API, snapshot copy).

If two agents can write the same row, you do not have an architecture yet. You have a race.

2. Architecture rules

  1. Sessions stay with the process that created them. Never sync a live session directory or a harness state database. Cold export is fine. Live copies are how you get path-keyed amnesia and corrupt SQLite.
  2. One worktree per concurrent agent. Shared checkouts are still chaos on a hub. Use claude --worktree, hermes --worktree, or git worktree add. Give each tree its own branch, ports, caches, and development database or schema. A shared checkout is allowed only under an explicit single-writer lock.
  3. Code leaves a workspace through Git. Documents leave through the document store. Database changes leave through migrations and review, not by copying the live file. Do not auto-push every dirty repo overnight. Alert on uncommitted or unpushed work; publish on purpose.
  4. Talk to live file databases through a seam. CLI over SSH, HTTP, or MCP. For read-only analysis, ship a snapshot taken with the database's own backup API, not a finder copy of a file that is still open.
  5. Remote access is authenticated. Claude Remote Control uses Anthropic's relay; you do not open an inbound port. Hermes remote HTTP still needs a session token or OAuth; SSH mode lets Desktop open the tunnel. Tailscale is optional private reachability, not a substitute for app auth, and default tailnet policy may let every device talk until you tighten grants.
  6. Backup is a separate failure domain. Git is not a backup of uncommitted work. Sync is not backup. NAS snapshots are not off-site backup. Use the harness's own backup command for session databases, encrypt the archive, keep a copy off the hub, and restore it once on a scratch machine.

3. Build the path you actually need

Path 1, documents. Put the client files in one named Dropbox or Drive folder. Write a one-line rule: only one agent (or one person) writes that folder at a time. Exclude anything your harness writes at runtime. Nightly, search that folder for conflicted copy. If the count is not zero, stop and merge by hand.

Path 2, hub. Pick one always-on machine. Install the harness there. Do the project work there.

Hermes: on the hub, start the headless backend with hermes serve. That is not the messaging gateway. On Desktop, open Settings → Gateways, add the hub by SSH (Desktop opens the tunnel) or by an authenticated Tailscale URL, hit Test, wait for "Reachable." Open the hub's profile for this project and stop using the local profile against a second copy of the files. Phone window: hermes gateway to Telegram or WhatsApp. Messaging docs.

Claude Code: enable Remote Control on the hub session. The session stays on the hub. If you run several brands and want one phone app, Happy wraps the existing command and does not move state.

Codex: connect the repo in Codex Cloud, run tasks in isolated environments, review the diff, open the PR. Local Codex threads can still stay on the machine that created them. Do not expect arbitrary local files or CLI history to appear in the cloud.

Windows hubs: use the harness's supported native Windows install or WSL2. If you choose WSL2, keep the working tree and session state inside the Linux filesystem, and confirm the background service survives logoff and reboot. WSL2 does not magically erase path problems.

Path 3, NAS. Point backups, media, and archives at it. Keep live worktrees on the hub disk. If you use it as a Git remote, clone from it; do not mount it as the working tree.

Software fleet, on any path above. For a second agent helping with a codebase that owns a local database:

  • Agent B gets git clone or git worktree add, on its own branch.
  • Agent B does not receive the live SQLite/Postgres file by mount or sync.
  • Agent B gets either a disposable development database, a dedicated schema, or a sanitized snapshot.
  • Fresh data, if needed, comes from a read-only command on the owning host.
  • Integration is a pull request plus tests on the hub. Production writes stay gated.

4. Backup, without copying a live database

Nightly, on the hub:

  • Hermes: hermes backup -o /path/hermes-backup.zip. That zip is built with SQLite's backup API and excludes live WAL sidecars on purpose. Copy the closed zip off-host. Restore with hermes import. For transcripts only, hermes sessions export backup.jsonl --redact.
  • Claude Code: archive closed session JSONL under ~/.claude/projects after the tool is idle. Claude Code defaults to 30-day local transcript retention; raise cleanupPeriodDays if you need them longer. That default is Claude's, not Hermes's or Codex's.
  • Codex: archive idle files under ~/.codex/sessions. Do not assume this captures cloud tasks; those live in the connected repo.
  • Git: alert on dirty worktrees and unpushed commits. Do not silently commit or push. Uncommitted work needs a filesystem snapshot or an explicit stash, because git push cannot see it.
  • Encrypt the off-host copy. Harness directories contain credentials, .env files, and customer transcripts.

Weekly: restore one backup onto a scratch profile or VM. Open the project. Resume or import one session. Run one known test. If you cannot, the backup is a decoration.

5. Acceptance test

  1. Lid test. Start a task from the laptop, close the lid, reattach from the phone. The task should still be on the hub. (Kills: laptop-as-courier.)
  2. Amnesia test. Resume yesterday's session from a different window. Full history should be there because you attached to the same host. (Kills: path-keyed session copies.)
  3. Isolation test. Start two agents on adjacent work. Separate worktrees, separate branches, separate dev databases. Merge through Git. Neither tree should see the other's dirty files. (Kills: shared-checkout plumbing.)
  4. Conflict scan. Search document-sync folders for conflicted copy and .sync-conflict. Code worktrees should not be in those folders at all.
  5. Fire drill. Restore onto a scratch machine. Confirm the project opens, one session is readable, and you can rebuild enough to work. Record the age of the copy you restored. A lost window should cost you nothing. A lost hub costs downtime plus whatever you had not yet backed up.

Hand this to your agent

Inventory every store I use with agents: documents, git repos, live workspaces, session directories, databases, SaaS, and secrets. For each, name one authority and one handoff seam. Do not sync live session directories or live SQLite files. Do not network-mount a live database. Concurrent agents get separate git worktrees and branches (claude --worktree, hermes --worktree, or git worktree add) plus isolated dev databases. Remote access uses the harness's own feature [Hermes: Settings → Gateways + hermes serve on the hub, messaging via hermes gateway / Claude Code: Remote Control / Codex: Cloud isolated environments + PRs]. Tailscale is optional private plumbing, not a replacement for app auth. Nightly: hermes backup (not a raw copy of ~/.hermes), idle session export for other harnesses, alert on dirty or unpushed git work, copy encrypted archives off-host. Do not auto-commit or auto-push. Finish with lid, amnesia, isolation, conflict-scan, and restore fire-drill tests. My hub is [OS/SPECS], harness is [HARNESS], clients are [DEVICES], and the stores are [LIST].

If your agent gets stuck or your setup fights back, hit reply with what happened. Member failure reports have already improved two of the specs in past issues, and I read every one.

What not to build

Skip the mesh where every machine runs every agent and they all stay in sync. That is where the failure stories come from. Skip network-mounting a live SQLite file, even on a tailnet. Skip copying state.db with rclone while the agent is running. Skip auto-pushing every dirty repo as if that were backup. Skip treating Codex Cloud as a second copy of your laptop. And skip building your own session-directory sync tool; the graveyard of 88-star GitHub repos attempting it is the warning, not the invitation.

One authority per store. One workspace per agent. Windows for sessions. Git for code. Snapshots for data. A backup you have actually restored.

Hit reply and tell me what's on your bench this week. I read every one.

Subscribe to Operators AI

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe