<?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: Sarower Morshed</title>
    <description>The latest articles on DEV Community by Sarower Morshed (@morsheded).</description>
    <link>https://dev.to/morsheded</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3955077%2F132c0f07-79e4-4800-a576-d45f47a09464.jpg</url>
      <title>DEV Community: Sarower Morshed</title>
      <link>https://dev.to/morsheded</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/morsheded"/>
    <language>en</language>
    <item>
      <title>I Shipped a Multi-Tenant Flutter SaaS Overnight — Without Writing a Single Line of App Code</title>
      <dc:creator>Sarower Morshed</dc:creator>
      <pubDate>Fri, 29 May 2026 22:12:27 +0000</pubDate>
      <link>https://dev.to/morsheded/i-shipped-a-multi-tenant-flutter-saas-overnight-without-writing-a-single-line-of-app-code-184g</link>
      <guid>https://dev.to/morsheded/i-shipped-a-multi-tenant-flutter-saas-overnight-without-writing-a-single-line-of-app-code-184g</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hermes-agent-2026-05-15"&gt;Hermes Agent Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What this post unpacks
&lt;/h2&gt;

&lt;p&gt;I shipped a multi-tenant Flutter SaaS — a futsal-pitch booking app with a consumer app, an operator admin console, QR check-in, walk-in POS, and a deployed Firebase backend — in one overnight sitting. The git timeline runs from &lt;strong&gt;19:38 to 03:09&lt;/strong&gt;. I never typed app code.&lt;/p&gt;

&lt;p&gt;I drove &lt;strong&gt;four (then five) Claude Code agents in parallel&lt;/strong&gt;, each in its own pane, each owning one directory of a shared monorepo. The conductor was &lt;strong&gt;&lt;a href="https://github.com/NousResearch/hermes-agent" rel="noopener noreferrer"&gt;Hermes Agent&lt;/a&gt;&lt;/strong&gt; (Nous Research, MIT). The visible substrate was &lt;strong&gt;&lt;a href="https://herdr.dev" rel="noopener noreferrer"&gt;Herdr&lt;/a&gt;&lt;/strong&gt;, a terminal multiplexer built for agents instead of humans.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;Write&lt;/strong&gt; category. So this is not a product tour. It is the orchestration teardown: the patterns that let N agents grind one repo at once without colliding, how they signal "done" without anyone polling, and how a fresh build lands on a phone seconds after it compiles. Every claim below traces to a commit, a file on disk, or a Hermes skill. Pointers at the bottom.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;The basic architecture diagram is given bellow, &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.amazonaws.com%2Fuploads%2Farticles%2F7us38scy5ctjivyst79f.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.amazonaws.com%2Fuploads%2Farticles%2F7us38scy5ctjivyst79f.png" alt="Architecture diagram" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four panes, one repo, one conductor. No agent touches another's directory.&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.amazonaws.com%2Fuploads%2Farticles%2F5xcju7qr6t5612dh73nq.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.amazonaws.com%2Fuploads%2Farticles%2F5xcju7qr6t5612dh73nq.png" alt="Four panel layout" width="800" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the magic of the markerfile for pingback loop.&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.amazonaws.com%2Fuploads%2Farticles%2F5fw015x70sft2gx0ku4w.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.amazonaws.com%2Fuploads%2Farticles%2F5fw015x70sft2gx0ku4w.png" alt="marker-file pingback loop" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concurrent commits, from &lt;code&gt;docs/timeline.md&lt;/code&gt; (the wiki pane logs every commit, which agent, why):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## 2026-05-30 02:43–02:44 — Email/Password + PRD-007/008 backend callables&lt;/span&gt;
   AGENT: backend claude (aa54dc9, 10dc2c6) + frontend claude (fc20bf2).
&lt;span class="gu"&gt;## 2026-05-30 00:21–00:28 — FirebaseApi wiring + multi-tenant data model&lt;/span&gt;
   AGENT: frontend claude (10beb79, 236fe01) + backend claude (dacb833)
          — landed concurrently with this docs upgrade.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The watcher catching an APK build and a "done" ping in the same window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;[03:06:10] APK INSTALL: app-arm64-v8a-release.apk -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Success
&lt;span class="go"&gt;[03:07:10] frontend-done: auth errors now show the real code, not generic text...
&lt;/span&gt;&lt;span class="gp"&gt;           APK rebuilt: /tmp/futsal-frontend-apk;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cold-launch-&amp;gt;/signin verified.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;App repo (public for the contest): &lt;code&gt;github.com/morsheded/futsal-booking&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hermes Agent (the orchestrator): &lt;code&gt;github.com/NousResearch/hermes-agent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The watcher daemon, redacted: &lt;code&gt;assets/futsal-watcher-redacted.sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My Tech Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Orchestration:&lt;/strong&gt; Hermes Agent (conductor) · Herdr (visible terminal substrate) · Claude Code CLI ×5 (the workers). &lt;strong&gt;App:&lt;/strong&gt; Flutter 3 / Dart 3 · Riverpod · go_router · Firebase (Auth + Firestore + Functions v2 &lt;code&gt;asia-south1&lt;/code&gt; node22 + Hosting + Storage). &lt;strong&gt;Delivery:&lt;/strong&gt; Tailscale (wireless &lt;code&gt;adb&lt;/code&gt;) · &lt;code&gt;mobile_scanner&lt;/code&gt; (web QR). &lt;strong&gt;Memory:&lt;/strong&gt; self-hosted Honcho (&lt;code&gt;localhost:8000&lt;/code&gt;, Ollama-backed, Colima + Docker).&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Hermes Agent
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Hermes orchestrates. It never writes app code.
&lt;/h3&gt;

&lt;p&gt;This is the whole mental model. Hermes does not implement features. Hermes writes a &lt;strong&gt;goal-file&lt;/strong&gt; per pane, dispatches it into a Claude Code instance, arms a watcher, reads the result marker, and reseeds the next goal. The Claude panes do every line of Dart and TypeScript.&lt;/p&gt;

&lt;p&gt;A real goal-file (&lt;code&gt;/tmp/goal-frontend.txt&lt;/code&gt;, trimmed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;GOAL: ship PRD-006 (auth routing fix + email/password) on the CLIENT FLUTTER APP only.
Your turf is &lt;span class="sb"&gt;`app/`&lt;/span&gt; and &lt;span class="sb"&gt;`packages/gameon_core/`&lt;/span&gt;.

READ FIRST:
&lt;span class="p"&gt;-&lt;/span&gt; docs/prd/PRD-006-auth-routing-fix-and-dual-login.md (your spec)
&lt;span class="p"&gt;-&lt;/span&gt; app/CLAUDE.md (rule 0: never &lt;span class="sb"&gt;`git add -A`&lt;/span&gt;)

PRECONDITION: backend claude is enabling Email/Password provider in Firebase Auth in
parallel. If sign-in fails with &lt;span class="sb"&gt;`operation-not-allowed`&lt;/span&gt;, the provider isn't on yet —
wait, retry. Do NOT mock; this is real Firebase.

WHEN DONE (truly idle, not between subtasks):
  echo "&lt;span class="nt"&gt;&amp;lt;one-line:&lt;/span&gt; &lt;span class="na"&gt;what&lt;/span&gt; &lt;span class="na"&gt;shipped&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="na"&gt;recommended&lt;/span&gt; &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;" &amp;gt; /tmp/futsal-frontend-done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal-file is self-contained: identity, turf, what to read, the cross-pane precondition, and the exit contract. Hermes is the only thing holding global state. Each pane holds only its lane.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Herdr is the substrate the human can watch.
&lt;/h3&gt;

&lt;p&gt;Unlike &lt;code&gt;tmux&lt;/code&gt;, Herdr is purpose-built for agents. Every pane is addressable by ID. Every pane reports a status (idle / working / blocked) into the status bar. Hermes pipes commands in from outside, and I watch the whole thing in real time in my own attached terminal. The &lt;code&gt;herdr-cli&lt;/code&gt; skill is how Hermes drives it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;herdr pane run &lt;span class="nv"&gt;$PANE&lt;/span&gt; &lt;span class="s2"&gt;"cd /path/to/project &amp;amp;&amp;amp; claude --dangerously-skip-permissions"&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;5                                  &lt;span class="c"&gt;# let the TUI draw&lt;/span&gt;
herdr agent send &lt;span class="nv"&gt;$PANE&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/goal-frontend.txt&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
herdr pane send-keys &lt;span class="nv"&gt;$PANE&lt;/span&gt; Enter         &lt;span class="c"&gt;# agent send does NOT submit — Enter is mandatory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That missing &lt;code&gt;Enter&lt;/code&gt; is the #1 "I sent it but Claude isn't doing anything" bug. It is in the skill in bold because it bit us twice.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Four panes, one git repo, zero collisions.
&lt;/h3&gt;

&lt;p&gt;Each pane owns a directory. That is the entire contract:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pane&lt;/th&gt;
&lt;th&gt;Owns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;frontend&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;app/&lt;/code&gt;, &lt;code&gt;pubspec.yaml&lt;/code&gt;, &lt;code&gt;pubspec.lock&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;backend&lt;/td&gt;
&lt;td&gt;&lt;code&gt;backend/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wiki&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;docs/&lt;/code&gt;, &lt;code&gt;wiki/&lt;/code&gt; (maintenance loop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;apps/admin/&lt;/code&gt;, &lt;code&gt;packages/gameon_core/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;e2e &lt;em&gt;(added when Playwright landed)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;e2e/&lt;/code&gt;, &lt;code&gt;.github/workflows/e2e.yml&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The hard rule, repeated verbatim as &lt;strong&gt;rule #0&lt;/strong&gt; in every pane's &lt;code&gt;CLAUDE.md&lt;/code&gt; (this is from &lt;code&gt;app/CLAUDE.md&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0. NEVER `git add -A` or `git add .` from repo root. This is a multi-agent monorepo
   with 3 other Claudes (backend, wiki, admin) writing to `main` in parallel + an
   auto-commit hook. Scope every commit to YOUR files only: `git add app/ pubspec.yaml
   pubspec.lock`. Before commit run `git status --short` and verify nothing outside your
   turf is staged. If you see foreign paths, that's another agent's WIP — leave it alone.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it matters: if agent A runs &lt;code&gt;git add -A&lt;/code&gt; while agent B has uncommitted WIP in &lt;code&gt;wiki/&lt;/code&gt;, A sweeps B's files into A's commit. Now history says &lt;code&gt;feat(backend): X&lt;/code&gt; but the diff contains wiki edits, and B comes back to a "clean" tree and gets confused. Stage explicit paths, never &lt;code&gt;-A&lt;/code&gt;, and the entire class of collision bugs disappears. The &lt;code&gt;multi-claude-monorepo-discipline&lt;/code&gt; skill is one page and that one rule is the whole cost of parallelism.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Marker-file pingback. No polling.
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Diagram: &lt;a href="https://excalidraw.com/#json=vGXkc2IUOCTXSuWqipQXW,Cl4svcA-vUTWSn8NaoEfPg" rel="noopener noreferrer"&gt;marker-file pingback loop&lt;/a&gt; (Excalidraw).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the signal layer. Reading a pane's TUI is noisy — ANSI redraws, partial output. So agents don't get polled. Each agent writes &lt;strong&gt;one line&lt;/strong&gt; to its own marker file the moment it goes idle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;what shipped + recommended next&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/futsal-frontend-done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hermes arms a background watcher that does nothing until the file exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Hermes runs this with background=true, notify_on_complete=true, timeout=86400&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /tmp/futsal-frontend-done &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;20&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nv"&gt;MSG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/futsal-frontend-done&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /tmp/futsal-frontend-done          &lt;span class="c"&gt;# delete immediately, so the next task can re-ping&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FRONTEND CLAUDE IDLE: &lt;/span&gt;&lt;span class="nv"&gt;$MSG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the marker appears the loop exits, &lt;code&gt;notify_on_complete=true&lt;/code&gt; fires the stdout back into the parent Hermes chat as a system message, and Hermes relays the one-liner to me. The signal is &lt;strong&gt;exactly what the agent decided was done&lt;/strong&gt; — it authored it. Zero polling, zero context churn. One unified watcher (&lt;code&gt;/tmp/futsal-watcher.sh&lt;/code&gt;) loops all five markers plus the APK marker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;f &lt;span class="k"&gt;in &lt;/span&gt;frontend backend admin e2e wiki&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;MF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/futsal-&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="nt"&gt;-done&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$MF&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;MSG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$MF&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$MF&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%H:%M:%S&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;-done: &lt;/span&gt;&lt;span class="nv"&gt;$MSG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOG&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Wireless APK delivery over Tailscale.
&lt;/h3&gt;

&lt;p&gt;My Samsung S24 Ultra lives on my tailnet at &lt;code&gt;100.101.80.104&lt;/code&gt;, with &lt;code&gt;adb&lt;/code&gt; pinned to port &lt;code&gt;5555&lt;/code&gt; once over USB (&lt;code&gt;adb tcpip 5555&lt;/code&gt;). When the frontend pane finishes a build it writes the &lt;code&gt;.apk&lt;/code&gt; path to a marker, and the same watcher installs it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /tmp/futsal-frontend-apk &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nv"&gt;APK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/futsal-frontend-apk&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /tmp/futsal-frontend-apk
  adb connect 100.101.80.104:5555 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
  adb &lt;span class="nt"&gt;-s&lt;/span&gt; 100.101.80.104:5555 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$APK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build finishes → phone has it in seconds. No USB cable, no Telegram (the bot caps uploads at 50MB; a debug APK is ~144MB anyway — release split-per-abi is ~18MB and fits, but the cable still beats the chat). The log shows the full loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;✓ Built build/app/outputs/flutter-apk/app-arm64-v8a-release.apk (18.2MB)
already connected to 100.101.80.104:5555
[20:26:57] installing app-arm64-v8a-release.apk to 100.101.80.104:5555...
Success
&lt;/span&gt;&lt;span class="gp"&gt;[20:27:13] ✓ batch #&lt;/span&gt;1 installed on phone &lt;span class="o"&gt;(&lt;/span&gt;17M&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. PRD-first venture culture.
&lt;/h3&gt;

&lt;p&gt;Nothing gets built without a written intent. Every feature has a numbered PRD in &lt;code&gt;docs/prd/&lt;/code&gt; (PRD-001 through PRD-009 shipped this run). Hermes writes the PRD &lt;em&gt;before&lt;/em&gt; dispatching any pane, and the PRD is the first thing the goal-file tells the agent to read. PRDs reference prior PRDs and ADRs, so the system stays coherent without anyone holding the design in their head. The &lt;code&gt;docs/&lt;/code&gt; tree is the authoritative spec; &lt;code&gt;wiki/&lt;/code&gt; is the auto-derived "what currently exists" view the wiki pane regenerates from git. The point, from the &lt;code&gt;venture-prd-workflow&lt;/code&gt; skill: &lt;strong&gt;the project must be rebuildable from &lt;code&gt;docs/&lt;/code&gt; alone — even after a full stack swap.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. The handoff: kill the pane before it hallucinates.
&lt;/h3&gt;

&lt;p&gt;This is the pattern almost nobody is running yet. Long-lived Claude panes degrade as their context window fills. My rule: after a major feature ships, when a pane crosses &lt;strong&gt;~300k tokens&lt;/strong&gt;, force the &lt;code&gt;mattpocock/handoff&lt;/code&gt; skill — compact the conversation into &lt;code&gt;/tmp/futsal-&amp;lt;pane&amp;gt;-handoff.md&lt;/code&gt;, then &lt;code&gt;/exit&lt;/code&gt;. Next time that pane is needed, relaunch a &lt;strong&gt;fresh&lt;/strong&gt; Claude and seed it with the handoff doc.&lt;/p&gt;

&lt;p&gt;The backend pane hit the threshold right after shipping the PRD-006/007/008 callables. Its handoff doc (&lt;code&gt;/tmp/futsal-backend-handoff.md&lt;/code&gt;, 64 lines) is a clean state transfer — current deployed state, source-of-truth file pointers, flagged decisions, gotchas, and the exact rule that protects it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Commit discipline (HARD RULE — see app/CLAUDE.md rule #0)&lt;/span&gt;
&lt;span class="sb"&gt;`main`&lt;/span&gt; is shared by 4 Claudes + an auto-commit hook. NEVER &lt;span class="sb"&gt;`git add -A`&lt;/span&gt;/&lt;span class="sb"&gt;`.`&lt;/span&gt;/&lt;span class="sb"&gt;`**`&lt;/span&gt;.
Stage explicit &lt;span class="sb"&gt;`backend/`&lt;/span&gt; paths only... If a collision happens anyway, don't rewrite
shared history — note it in /tmp/futsal-backend-done. (Last time &lt;span class="sb"&gt;`git add -A`&lt;/span&gt; swept the
wiki Claude's WIP into a backend commit — don't repeat.)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fresh pane seeded with this doc has the &lt;em&gt;facts&lt;/em&gt; without the &lt;em&gt;drift&lt;/em&gt; of a 300k-token conversation. Compaction-induced hallucination on long autonomous runs basically stops.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. The collision incident — the discipline rule self-correcting, on the record.
&lt;/h3&gt;

&lt;p&gt;Best part: I have the rule catching a real collision, captured live in an artifact. The admin pane went to commit and found the e2e pane's WIP already staged in the shared index. It didn't sweep it. It reported it in its own done-marker (&lt;code&gt;/tmp/futsal-watcher.log&lt;/code&gt;, &lt;code&gt;03:05:17&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[03:05:17] admin-done: ... commit 832f9cf scoped to apps/admin/ + packages/gameon_core/ ONLY.
  DEVIATIONS / NOTES:
  - MULTI-AGENT: the e2e claude's staged e2e/ files were already in the shared index
&lt;/span&gt;&lt;span class="gp"&gt;    when I went to commit;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;I git-restored them out so my commit stayed turf-only
&lt;span class="go"&gt;    (apps/admin + packages/gameon_core). e2e/ left untouched for the e2e claude.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent noticed foreign paths, &lt;code&gt;git restore&lt;/code&gt;'d them out, committed only its turf, and &lt;em&gt;narrated the whole thing&lt;/em&gt; so the conductor knew. That is the discipline rule working as a self-healing mechanism — not a guardrail that blocks, but a norm the agent reasons about out loud.&lt;/p&gt;

&lt;p&gt;(The repo's history also records the &lt;em&gt;other&lt;/em&gt; outcome — &lt;code&gt;dacb833&lt;/code&gt; in the timeline notes a wide &lt;code&gt;git add&lt;/code&gt; that swept the wiki pane's WIP, with a "history is not rewritten, noted here" entry. The rule postdates that commit. The collision happened once, got documented, became rule #0, and then &lt;em&gt;prevented its own recurrence&lt;/em&gt; at &lt;code&gt;03:05:17&lt;/code&gt;. That arc is the actual lesson.)&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Hermes is a fleet, not an agent.
&lt;/h3&gt;

&lt;p&gt;Last layer. The same Mac runs &lt;strong&gt;three Hermes profiles&lt;/strong&gt; — &lt;code&gt;default&lt;/code&gt; (the operator that ran this build), &lt;code&gt;nexus&lt;/code&gt; (homelab IT), &lt;code&gt;donna&lt;/code&gt; (Obsidian second-brain). Each is a full Hermes instance with its own skills, plugins, cron, and memory, and they share one self-hosted &lt;strong&gt;Honcho&lt;/strong&gt; memory layer (&lt;code&gt;localhost:8000&lt;/code&gt;, workspace &lt;code&gt;hermes&lt;/code&gt;, Ollama-backed via Colima + Docker). So the orchestration nests: Hermes drives a fleet of Claude panes for &lt;em&gt;coding&lt;/em&gt;, and Hermes itself runs as a fleet of profiles for &lt;em&gt;everything else&lt;/em&gt;. Same multi-agent shape, one level up.&lt;/p&gt;




&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The speed didn't come from a better model. It came from structure around the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One conductor that never codes&lt;/strong&gt; (Hermes) and many workers that only code (Claude panes).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One directory per agent + never &lt;code&gt;git add -A&lt;/code&gt;&lt;/strong&gt; — the cheapest possible collision defense.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent-authored marker files&lt;/strong&gt; instead of polling — the agent tells you it's done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PRD-first&lt;/strong&gt; so parallel agents converge instead of diverging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forced handoffs at ~300k tokens&lt;/strong&gt; so long runs don't rot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is model-specific or even Flutter-specific. It is a coordination protocol. Hermes is open source (&lt;a href="https://github.com/NousResearch/hermes-agent" rel="noopener noreferrer"&gt;NousResearch/hermes-agent&lt;/a&gt;, MIT) and so is the discipline. Steal the patterns.&lt;/p&gt;

</description>
      <category>hermesagentchallenge</category>
      <category>devchallenge</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
