<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>letsautom8 · lab notes</title>
  <link>https://letsautom8.dev/</link>
  <atom:link href="https://letsautom8.dev/feed.xml" rel="self" type="application/rss+xml"/>
  <description>Marlon Cruz&#39;s engineering lab: AI agents, automation pipelines and the tools that run his own work, written up as experiments.</description>
  <language>en-nz</language><lastBuildDate>Sun, 11 Oct 2026 20:00:00 +0000</lastBuildDate>
  <item>
    <title>One session per project: how my Claude Code agents stay on the job</title>
    <link>https://letsautom8.dev/posts/one-session-per-project/</link>
    <guid isPermaLink="true">https://letsautom8.dev/posts/one-session-per-project/</guid>
    <pubDate>Sun, 11 Oct 2026 20:00:00 +0000</pubDate>
    <description>&lt;p&gt;I run a lot of small projects: websites, a trading-engine fork, a content publisher, the home lab itself. For a while each one meant opening a terminal, starting Claude Code, re-explaining where we were, and remembering to come back. The context lived in my head, which is exactly the place I&#39;m trying to get it out of.&lt;/p&gt;
&lt;p&gt;So now every project has &lt;strong&gt;one master session&lt;/strong&gt;: a Claude Code session that belongs to that project, remembers it, and can be woken from anywhere, including my phone.&lt;/p&gt;
&lt;h2&gt;The whole interface is a text file&lt;/h2&gt;
&lt;p&gt;To wake a project&#39;s session, or give it a task, something drops a file into a requests folder:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;folder=letsautom8
---prompt---
Work on letsautom8#4: shape the site as an engineering blog.
Follow &amp;quot;Working an issue&amp;quot;. Report on the issue, not here.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A small launcher, a launchd agent on my Mac, notices the file and does one thing: it &lt;em&gt;ensures&lt;/em&gt; the session. If the project&#39;s session is running, the prompt is delivered to it. If it isn&#39;t (never started, crashed, Mac rebooted), it&#39;s started first and then gets the prompt. A status file comes back with the result and a snapshot of the screen.&lt;/p&gt;
&lt;p&gt;That&#39;s deliberately boring. Anything that can write a file can drive it: me from a terminal, a script, a scheduled job, or another agent.&lt;/p&gt;
&lt;h2&gt;One conversation per project, pinned&lt;/h2&gt;
&lt;p&gt;The important word is &lt;em&gt;master&lt;/em&gt;. Each project has one Claude Code conversation, pinned by its ID. When the session has to be restarted, the launcher resumes that exact conversation rather than starting fresh. There are no hand-over notes and no &amp;quot;here&#39;s where we were&amp;quot; summaries: the session simply carries on.&lt;/p&gt;
&lt;p&gt;Sessions run in tmux, one window per project, with remote control switched on, so each one also shows up in the Claude app on my phone. I can read along or nudge it while I&#39;m away from the desk.&lt;/p&gt;
&lt;p&gt;A few rules keep this sane:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;An allowlist.&lt;/strong&gt; Only listed project folders can be started, and the list says which ones may run unattended and which must ask before acting. Anything near live money or a client&#39;s tenant always asks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One process per conversation.&lt;/strong&gt; Two Claude processes on the same conversation step on each other. So nothing else is allowed to start a session in a project the launcher manages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stopping isn&#39;t forgetting.&lt;/strong&gt; &lt;code&gt;action=stop&lt;/code&gt; ends the process but keeps the master; the next request resumes it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The trap: macOS Local Network privacy&lt;/h2&gt;
&lt;p&gt;The first version worked perfectly in testing and then couldn&#39;t reach anything on my LAN.&lt;/p&gt;
&lt;p&gt;macOS asks for Local Network permission per &lt;em&gt;app that started the process&lt;/em&gt;, not per user. A tmux server started by launchd isn&#39;t an app you can grant anything to, so every session inside it silently lost access to machines on the home network. You get &amp;quot;No route to host&amp;quot;, which looks like a network fault, but it isn&#39;t one.&lt;/p&gt;
&lt;p&gt;The fix was to make sure the tmux server is always born from Terminal, which does have the permission. When no tmux server is running, the launcher opens a tiny bootstrap script in Terminal. That script starts the server with a keep-alive session, and every session started afterwards inherits Terminal&#39;s exemption.&lt;/p&gt;
&lt;div class=&quot;lesson&quot;&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; when an automated process can&#39;t reach the network but the same command works in your terminal, check who the process&#39;s ancestor is before you debug the network.&lt;/div&gt;
&lt;h2&gt;Letting an agent hand out work, carefully&lt;/h2&gt;
&lt;p&gt;The next step was letting my chief-of-staff agent (it triages my notes and tickets) hand issues to these sessions itself. That&#39;s powerful and slightly alarming, so its requests are marked as coming from it and get extra rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A cap on busy sessions.&lt;/strong&gt; Its requests wait in the queue while two sessions are already busy. My own requests are never held.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A pause switch.&lt;/strong&gt; Creating a &lt;code&gt;PAUSE&lt;/code&gt; file holds all of its requests until I delete it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only ready work.&lt;/strong&gt; It hands over only issues with no open decision, nothing blocking them, and no other session already working on them. Production work also needs an explicit &amp;quot;go&amp;quot; from me on the issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The sessions themselves follow one shared rule set: one issue per session, mark it &lt;em&gt;Doing&lt;/em&gt; while working, ask me only for real decisions, and report on the issue, not in a chat I&#39;ll never scroll back through.&lt;/p&gt;
&lt;h2&gt;What changed&lt;/h2&gt;
&lt;p&gt;The work now lives in tickets and the sessions live in tmux, which leaves me the decisions. When I say &amp;quot;send that to its session&amp;quot; to my lab connector by voice, a request file gets written, a session wakes up with its whole history, and the result appears on the issue.&lt;/p&gt;
&lt;p&gt;That connector, which lets Claude&#39;s phone app see and act on the lab, gets its own write-up.&lt;/p&gt;
</description>
  </item>
  <item>
    <title>Welcome to the lab</title>
    <link>https://letsautom8.dev/posts/welcome-to-the-lab/</link>
    <guid isPermaLink="true">https://letsautom8.dev/posts/welcome-to-the-lab/</guid>
    <pubDate>Sun, 11 Oct 2026 07:00:00 +0000</pubDate>
    <description>&lt;p&gt;This site is my lab notebook.&lt;/p&gt;
&lt;p&gt;I&#39;m an automation engineer. I come from test automation, and these days most of what I build is AI agents and the pipelines around them. Outside of that I keep a small home lab where I try things on my own work first: agents that run my tasks, sessions that pick up tickets by themselves, a connector that lets me run the lab by voice from the car.&lt;/p&gt;
&lt;p&gt;Some of it works. Some of it breaks in instructive ways. Both are worth writing down.&lt;/p&gt;
&lt;h2&gt;What you&#39;ll find here&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Write-ups of how things work.&lt;/strong&gt; The architecture, the moving parts, the trade-offs, and the trap I fell into along the way.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Experiments in progress.&lt;/strong&gt; Things marked &lt;em&gt;running&lt;/em&gt; aren&#39;t finished, and may change or get abandoned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The occasional post-mortem.&lt;/strong&gt; When something fails properly, I&#39;d rather explain why than quietly delete it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What you won&#39;t find&lt;/h2&gt;
&lt;p&gt;Live details. Write-ups describe how something is built, never where it runs: no hostnames, keys or client data. Posts about trading software are about the engineering only, never returns or &amp;quot;this strategy makes X%&amp;quot;. None of it is financial advice.&lt;/p&gt;
&lt;h2&gt;The format isn&#39;t fixed&lt;/h2&gt;
&lt;p&gt;I haven&#39;t settled on a format, and I don&#39;t want to guess. If a kind of post is useful to you (deep dives, short notes, videos), tell me and I&#39;ll do more of it. The contact section is at the bottom of every page.&lt;/p&gt;
</description>
  </item>
</channel>
</rss>
