DEV Community

Cover image for Keeping the working copy on my laptop while the agent runs on a server
Matteo Ricupero
Matteo Ricupero

Posted on Originally published at corami.dev

Keeping the working copy on my laptop while the agent runs on a server

A refactor runs on a server while I sit on a train. I open the preview on my phone, see the page the agent just changed, type one correction, put the phone away. Two hours later I open the laptop at my desk and the work is in my working tree: new files, half-edited ones, a failing test I still have to fix. Nothing was committed, pushed or pulled.

Why there are two copies

A coding agent needs a machine that stays on and I need the code on the computer in front of me. Every other answer moves the code somewhere: a cloud agent clones the repository into a VM and your working copy becomes a stale checkout; tmux on a rented box keeps the agent alive and leaves the project on the server.

Corami keeps a real copy of the project on both sides. It is a normal directory on the server and on the laptop, synced in both directions with Mutagen over Tailscale SSH.

Builds run where I am. xcodebuild, a flutter run on a phone plugged into the Mac, a dev server the browser on my desk talks to: those want local files, local caches and no network filesystem between them and the disk. A mount makes them crawl. A synced directory is a directory and they behave.

Uncommitted work travels. The sync carries what is on disk. I can leave a half-written migration and a debug print in a file, close the lid and the agent on the server works on that exact state. Its edits come back into the same folder, still uncommitted and I read them with git diff before deciding anything.

My editor keeps working. Rename a symbol across the tree, grep it, let the language server index it. All of that assumes local files and here the files are local.

The agent on the server, the build on the laptop

The harness stays yours: opencode, Claude Code, Codex, whatever you already use, installed on the server. Corami is the host; the harness is whatever you installed on the server.

A dev server started there gets a stable HTTPS address with corami serve 3000, reachable from the tailnet. On the train I open that address in the browser, see the change the agent just made and reply in the same conversation.

The build is the harder half, because flutter build needs the Mac. A client can now run commands for the server, behind an approval dialog that names the program and the project. Refusing leaves a note in the dialog instead of failing quietly. It is a permission gate, not a sandbox and I would not treat it as one.

Setting it up

On the server, over ssh as root (the setup creates the corami account):

curl -fsSL https://github.com/tapeo/corami/releases/latest/download/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Answer server. On the laptop the same script, answer client and the setup finds the server in your tailnet. Then:

corami project add ~/dev/myapp
Enter fullscreen mode Exit fullscreen mode

The project lands in ~/projects/myapp on the server; the folder on the laptop stays where it was and becomes the synced copy. There is no configuration file. Dependencies and build output (node_modules, build, Pods) are excluded and each machine regenerates them; everything else travels, keys and env files included, so a build or a preview on the server has what the laptop has. When both sides edit the same file and the merge cannot be done safely, the sync stops and reports which file and which two paths. Nothing is overwritten.

What breaks

Failures here cost work, so this list matters more than the features.

  • git: a rebase on one side while the agent writes on the other produces index.lock fights and half-applied states. One long git operation at a time.
  • Large binaries: it syncs a source tree, not a backup. Keep videos and datasets out.
  • Deleting the same file on both sides is the classic sync trap. Corami reports it as a conflict instead of guessing.
  • The toolchain: Node, pnpm, Flutter have to exist on the machines where they run. Corami does not install them.

What it is today

Early stage, macOS and Linux clients, one binary that is both the CLI and the daemon, every command speaking JSON so an agent can drive it. The server, the agent and the previews stay on the tailnet; nothing listens on the public internet.

The license is FSL-1.1-ALv2: source available, not OSI open source and each release becomes Apache 2.0 after two years.

If you run an agent on a remote machine already, I would like to know how you handle the build half: a mount, a second checkout or a sync like this one?

I built Corami, so weigh the recommendation accordingly.

Top comments (1)

Collapse
 
reidmarlow profile image
Reid Marlow •

The sharp edge with bidirectional directory sync like Mutagen comes from secondary build artifacts and watcher collisions. When a remote agent runs a test runner that leaves temporary fixtures or local sqlite state on the server, the reverse sync can pull those back into the local tree if the ignore rules miss an extension. Local editor formatters also fight inbound changes if a save event fires while the agent is halfway through a multi-file diff. Pausing sync across active tool executions usually saves more files than letting the watcher race the language server.