<?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: Kaushik N</title>
    <description>The latest articles on DEV Community by Kaushik N (@mrtigafk).</description>
    <link>https://dev.to/mrtigafk</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%2F4128159%2F48f53769-7a84-4766-8dcb-7f6659e1f897.jpg</url>
      <title>DEV Community: Kaushik N</title>
      <link>https://dev.to/mrtigafk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrtigafk"/>
    <language>en</language>
    <item>
      <title>The cloud can have my code. It can't have my Claude.</title>
      <dc:creator>Kaushik N</dc:creator>
      <pubDate>Wed, 16 Sep 2026 13:46:01 +0000</pubDate>
      <link>https://dev.to/mrtigafk/the-cloud-can-have-my-code-it-cant-have-my-claude-1d4d</link>
      <guid>https://dev.to/mrtigafk/the-cloud-can-have-my-code-it-cant-have-my-claude-1d4d</guid>
      <description>&lt;p&gt;The Claude app can start a coding session from your phone. It spins up a cloud sandbox, clones your GitHub repo into it, and lets you work from anywhere. For a lot of people, that's everything they need.&lt;/p&gt;

&lt;p&gt;It wasn't enough for me, and the reason turned into a project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup that can't travel
&lt;/h2&gt;

&lt;p&gt;Over the last few months I've customised Claude Code heavily. None of it is exotic, but it adds up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hooks&lt;/strong&gt;: scripts that run automatically on events. Mine refuse a commit until the review steps have actually run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt;: written instructions for how I plan, review, test and ship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A global CLAUDE.md&lt;/strong&gt;: the rules I want followed in every project, rewritten every time something goes wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of that lives in my profile folder, not in any repository. I keep it out of GitHub on purpose, because it describes how I work and what I'm building.&lt;/p&gt;

&lt;p&gt;A cloud sandbox gets a clone of my repo and stock Claude Code. Same model, much worse assistant. That's the whole pitch in one line: &lt;strong&gt;the cloud can have my code, but it can't have my Claude.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude Code's Remote Control already lets me continue a session on my PC from my phone. But someone has to start that session at the desk first. I wanted to start one from my phone, in whichever project I pick, with my whole setup loaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Claude Remote is a Claude Code plugin. Fittingly, it installs into the same setup it exists to protect. You add its marketplace and install it from inside Claude Code, with no separate download and no cloning. If you want to change how it works, you fork it.&lt;/p&gt;

&lt;p&gt;Under the hood it's two small pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A Node agent&lt;/strong&gt; on my Windows PC. It has zero dependencies, runs as a scheduled task, and listens only on loopback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A PWA&lt;/strong&gt; on my phone. It lists my projects, starts a session when I tap one, and stops it when I tap stop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgke7hbh8wdimlm8ri4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgke7hbh8wdimlm8ri4r.png" alt=" " width="390" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The phone reaches the agent through &lt;code&gt;tailscale serve&lt;/code&gt;, so it only works inside my private Tailscale network. There are no open ports, and every API call needs a token issued by a passcode. When I tap a project, a PowerShell launcher changes into that folder, activates its environment, and runs Claude Code with Remote Control on. The session appears in the Claude app's Code tab, and I drive it from there.&lt;/p&gt;

&lt;p&gt;The PWA is deliberately not a terminal. It's a start button. The conversation happens in the Claude app, which already does that well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7d29ep50md5e8vh8x1eo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7d29ep50md5e8vh8x1eo.png" alt=" " width="390" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One touch I like: if the project has a &lt;code&gt;HANDOFF.md&lt;/code&gt;, a notes file I keep for where the work stands, the launcher passes a first prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read HANDOFF.md and give the opening report.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A session I start away from my desk opens by telling me where things are, instead of sitting silent waiting for input.&lt;/p&gt;

&lt;p&gt;That created its own problem. A session could now start itself and begin working with nobody watching. So the opening report has to end as a proposal and wait for my go. The first thing I hear from a session should never be work that's already underway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four bugs that passed every test
&lt;/h2&gt;

&lt;p&gt;The code was the easy part. What took the time was a series of bugs that looked fine from every angle a test could see.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. One flag silently broke Remote Control
&lt;/h3&gt;

&lt;p&gt;My desk setup launches Claude Code with a &lt;code&gt;--channels&lt;/code&gt; flag for a messaging plugin. I carried it over to the launcher.&lt;/p&gt;

&lt;p&gt;The session started perfectly. Right window title, interface drawn, ready to work. But Remote Control sat on "connecting" forever, and the session never appeared in the Code tab. From the phone, it looked like nothing had happened.&lt;/p&gt;

&lt;p&gt;Removing that one flag fixed it in seconds. Two experimental input channels were competing for the same session.&lt;/p&gt;

&lt;p&gt;No test could have caught this. The process was healthy, and the only symptom was a row missing from an app on my phone. It took a person looking at the screen. Now, any change to the launch arguments means checking the app again, by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. A reviewer's fix would have broken every Python project
&lt;/h3&gt;

&lt;p&gt;To activate a Python virtual environment, the launcher adds the venv's &lt;code&gt;Scripts&lt;/code&gt; folder to the front of &lt;code&gt;PATH&lt;/code&gt;. A review pointed out that a &lt;code&gt;;&lt;/code&gt; in the project path would split that entry, and suggested quoting it.&lt;/p&gt;

&lt;p&gt;Sensible advice, but wrong here. PowerShell's command resolution doesn't honour quotes inside a &lt;code&gt;PATH&lt;/code&gt; entry. With the quoted version, &lt;code&gt;python&lt;/code&gt; resolved to the system interpreter, while &lt;code&gt;VIRTUAL_ENV&lt;/code&gt; claimed the venv was active. Every venv project would have launched outside its venv, and nothing would have looked wrong.&lt;/p&gt;

&lt;p&gt;The whole test suite stayed green, because the tests used a synthetic venv. They proved &lt;code&gt;python.exe&lt;/code&gt; &lt;em&gt;existed&lt;/em&gt; in the right place, never that it &lt;em&gt;resolved&lt;/em&gt;. I only caught it by running the real launcher against a real venv and asking which &lt;code&gt;python&lt;/code&gt; came back.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;;&lt;/code&gt; in the path is now refused with a clear message instead of quoted around.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;conda activate&lt;/code&gt; failing doesn't throw
&lt;/h3&gt;

&lt;p&gt;For conda projects, the launcher reads the environment name from &lt;code&gt;environment.yml&lt;/code&gt; and runs &lt;code&gt;conda activate&lt;/code&gt;. I wrapped it in a try/catch.&lt;/p&gt;

&lt;p&gt;That catches nothing useful. In PowerShell, a native command exiting non-zero isn't an exception, even with &lt;code&gt;$ErrorActionPreference = 'Stop'&lt;/code&gt;. When the environment doesn't exist, which is the most likely failure, conda prints an error and carries on. A cloned repo naming an environment you don't have would have launched a healthy-looking session sitting in &lt;code&gt;base&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fix checks the result, not the exception. After activating, the launcher compares &lt;code&gt;CONDA_DEFAULT_ENV&lt;/code&gt; against the name it asked for, and refuses the launch if they differ. The try/catch stays too, because a &lt;em&gt;command-resolution&lt;/em&gt; failure does throw. That distinction is the entire guard.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Activating a venv let a repo choose which Claude to run
&lt;/h3&gt;

&lt;p&gt;Adding the venv's &lt;code&gt;Scripts&lt;/code&gt; folder to &lt;code&gt;PATH&lt;/code&gt; had a second consequence. The launcher started Claude Code by name, so the name was looked up through the new &lt;code&gt;PATH&lt;/code&gt;. A cloned repo carrying its own &lt;code&gt;claude.cmd&lt;/code&gt; in its venv would have had &lt;em&gt;that&lt;/em&gt; file run instead, with my full user permissions, the moment I tapped the project.&lt;/p&gt;

&lt;p&gt;The fix resolves Claude Code to an absolute path before the venv touches &lt;code&gt;PATH&lt;/code&gt;, so the project never gets a say in which executable starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The state I deleted
&lt;/h2&gt;

&lt;p&gt;Early on, a broken environment didn't stop the launch. The launcher recorded the error and started the session anyway, reasoning that a running session was better than none.&lt;/p&gt;

&lt;p&gt;That produced a session that was alive and wrong at the same time. I designed five different ways to show "running, but in the wrong environment" on a phone screen, and every one was confusing. A condition that persists doesn't fit in the same banner as a one-off message.&lt;/p&gt;

&lt;p&gt;In the end I deleted the state. A broken environment now stops the launch, and the phone shows why. A clear failure beats a session that quietly works in the wrong place.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took away
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Green tests prove what the tests can see.&lt;/strong&gt; Three of these four bugs lived at a layer the tests never touched: a phone screen, command resolution, an exit code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the real thing.&lt;/strong&gt; A synthetic fixture proves a file exists. Only the real launcher proves it works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alive but wrong is worse than failed.&lt;/strong&gt; If the tool can't do the job properly, it should say so and stop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude Remote is Windows only and not public yet. When it is, it will be a plugin you can install from inside Claude Code, and a repo you can fork if you want it to work differently. Until then, if you keep your Claude Code setup out of your repos too, I'd like to hear how you use it away from your desk.&lt;/p&gt;

&lt;p&gt;If you want to follow along, I'm on GitHub: &lt;a href="https://github.com/MrTig-afk" rel="noopener noreferrer"&gt;https://github.com/MrTig-afk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>microsoft</category>
      <category>powershell</category>
    </item>
  </channel>
</rss>
