<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matteo Ricupero</title>
    <description>The latest articles on DEV Community by Matteo Ricupero (@matteoricupero).</description>
    <link>https://dev.to/matteoricupero</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4196862%2F05705cd5-a1bc-427b-8ed1-62192790e4e2.jpg</url>
      <title>DEV Community: Matteo Ricupero</title>
      <link>https://dev.to/matteoricupero</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matteoricupero"/>
    <language>en</language>
    <item>
      <title>Keeping the working copy on my laptop while the agent runs on a server</title>
      <dc:creator>Matteo Ricupero</dc:creator>
      <pubDate>Tue, 20 Oct 2026 20:49:20 +0000</pubDate>
      <link>https://dev.to/matteoricupero/keeping-the-working-copy-on-my-laptop-while-the-agent-runs-on-a-server-3p3l</link>
      <guid>https://dev.to/matteoricupero/keeping-the-working-copy-on-my-laptop-while-the-agent-runs-on-a-server-3p3l</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why there are two copies
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://mutagen.io/" rel="noopener noreferrer"&gt;Mutagen&lt;/a&gt; over Tailscale SSH.&lt;/p&gt;

&lt;p&gt;Builds run where I am. &lt;code&gt;xcodebuild&lt;/code&gt;, a &lt;code&gt;flutter run&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;git diff&lt;/code&gt; before deciding anything.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent on the server, the build on the laptop
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;A dev server started there gets a stable HTTPS address with &lt;code&gt;corami serve 3000&lt;/code&gt;, 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.&lt;/p&gt;

&lt;p&gt;The build is the harder half, because &lt;code&gt;flutter build&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting it up
&lt;/h2&gt;

&lt;p&gt;On the server, over ssh as root (the setup creates the &lt;code&gt;corami&lt;/code&gt; account):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://github.com/tapeo/corami/releases/latest/download/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer &lt;code&gt;server&lt;/code&gt;. On the laptop the same script, answer &lt;code&gt;client&lt;/code&gt; and the setup finds the server in your tailnet. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;corami project add ~/dev/myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project lands in &lt;code&gt;~/projects/myapp&lt;/code&gt; 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 (&lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;Pods&lt;/code&gt;) 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What breaks
&lt;/h2&gt;

&lt;p&gt;Failures here cost work, so this list matters more than the features.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What it is today
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;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?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Site: &lt;a href="https://corami.dev" rel="noopener noreferrer"&gt;https://corami.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/tapeo/corami" rel="noopener noreferrer"&gt;https://github.com/tapeo/corami&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Quickstart: &lt;a href="https://github.com/tapeo/corami/blob/main/docs/quickstart.md" rel="noopener noreferrer"&gt;https://github.com/tapeo/corami/blob/main/docs/quickstart.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built Corami, so weigh the recommendation accordingly.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>selfhosted</category>
      <category>tailscale</category>
    </item>
  </channel>
</rss>
