<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Engineering Management on Steve Sun</title><link>https://sund.site/en/tags/engineering-management/</link><description>Recent content in Engineering Management on Steve Sun</description><generator>Hugo</generator><language>en</language><copyright>© 2013-2026, Steve Sun</copyright><lastBuildDate>Sun, 07 Jun 2026 10:00:00 +0800</lastBuildDate><follow_challenge><feedId>41397727810093074</feedId><userId>56666701051455488</userId></follow_challenge><atom:link href="https://sund.site/en/tags/engineering-management/index.xml" rel="self" type="application/rss+xml"/><item><title>How I Use Hermes Agent to Write Code</title><link>https://sund.site/en/posts/2026/how-i-use-hermes-agent/</link><pubDate>Sun, 07 Jun 2026 10:00:00 +0800</pubDate><guid>https://sund.site/en/posts/2026/how-i-use-hermes-agent/</guid><description>&lt;p&gt;&lt;figure
 class="image-caption"
&gt;
 
 &lt;img src="https://raw.githubusercontent.com/stevedsun/blog-img/main/how-i-use-hermes-agent-header-900x383.png" alt="" loading="lazy" /&gt;
 
 &lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I run two Hermes Agents in parallel.&lt;/p&gt;
&lt;p&gt;One is called Super Juaner and handles daily conversation and information retrieval. The other is called Code Juaner and works exclusively on software engineering. Two independent Telegram bots, independent configurations, independent session databases.&lt;/p&gt;
&lt;p&gt;Running two Agents separately is for context and environment isolation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core discipline: Code Juaner never writes code.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All coding is delegated to Codex CLI for execution. Code Juaner only does the Product Owner work: writing requirement definitions, making architecture decisions, and accepting deliverables. Codex is the implementer: reads the spec, writes code, runs tests.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Role&lt;/th&gt;
 &lt;th&gt;Output&lt;/th&gt;
 &lt;th&gt;Responsibility&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Code Juaner (Hermes PO)&lt;/td&gt;
 &lt;td&gt;Feature doc + acceptance&lt;/td&gt;
 &lt;td&gt;Requirement definition, architecture decisions, quality control&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Codex CLI (Implementer)&lt;/td&gt;
 &lt;td&gt;Code + tests&lt;/td&gt;
 &lt;td&gt;Technical solution, coding implementation, self-testing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The flow is simple. The user says &amp;ldquo;I need a feature.&amp;rdquo; Code Juaner writes a feature doc containing only the requirement description and verifiable acceptance criteria. Every acceptance criterion must be verifiable—&amp;ldquo;clicking changes the URL to /zh/monaco&amp;rdquo; rather than &amp;ldquo;navigation is correct.&amp;rdquo; Then Codex reads the doc, plan mode produces a technical spec, and build mode implements plus tests. Code Juaner accepts each criterion one by one; if all pass, deploy; if there are issues, summarize and send back.&lt;/p&gt;
&lt;p&gt;Code Juaner never reads code files, never finishes reading code to tell Codex how to write. For project-level questions, delegate to Codex plan mode for investigation. Codex timeout means reporting back directly and waiting for next instructions.&lt;/p&gt;
&lt;p&gt;The acceptance standard is that &lt;code&gt;npm run build&lt;/code&gt; passing is only the minimum bar. For behavior changes, walk through the full user path in the browser before marking complete.&lt;/p&gt;
&lt;h2 id="the-three-layer-gate"&gt;The Three-Layer Gate&lt;/h2&gt;
&lt;p&gt;Discipline sounds simple but is easy to forget in practice. The model drifts in long conversations—after thirty turns, it may think it can write code and start modifying files directly. I built three layers of defense.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 1: System prompt (hardest, unbypassable)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Locked in &lt;code&gt;config.yaml&lt;/code&gt;: all coding must be delegated to Codex CLI for execution, never write code yourself, report and wait after Codex fails. Injected every turn, can&amp;rsquo;t be avoided.&lt;/p&gt;
&lt;p&gt;The system prompt&amp;rsquo;s lifecycle in Hermes is longer than SOUL.md; it doesn&amp;rsquo;t reset between conversations, so it better prevents forgetting after long conversations. Even if the model starts drifting after dozens of turns, this terminal instruction is still there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: SOUL.md + personality (loaded at session start)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SOUL.md defines personality and creed: terse, conclusion-first, type-safety &amp;gt; runtime correctness &amp;gt; performance optimization. But its effective range is the start of each conversation, weaker than the system prompt.&lt;/p&gt;
&lt;p&gt;SOUL loads a &lt;code&gt;development-workflow&lt;/code&gt; skill I co-developed with Super Juaner, which defines pre-checks when picking up code: must load the workflow skill first before making decisions, don&amp;rsquo;t skip. This file hosts my entire coding discipline as an initial activation guide.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 3: Plugin gate (physical interception, unbypassable)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Two plugins intercept Code Juaner&amp;rsquo;s source code read/write. &lt;code&gt;write-code-gate&lt;/code&gt; blocks &lt;code&gt;write_file&lt;/code&gt; and &lt;code&gt;patch&lt;/code&gt; on source files like &lt;code&gt;.ts&lt;/code&gt;, &lt;code&gt;.tsx&lt;/code&gt;, &lt;code&gt;.py&lt;/code&gt; and returns refusal. &lt;code&gt;read-code-gate&lt;/code&gt; blocks &lt;code&gt;read_file&lt;/code&gt; and &lt;code&gt;search_files&lt;/code&gt; on source files. Non-source files like &lt;code&gt;.md&lt;/code&gt;, &lt;code&gt;.yaml&lt;/code&gt;, &lt;code&gt;.toml&lt;/code&gt; pass through.&lt;/p&gt;
&lt;p&gt;The blocked extensions cover 30+ common languages. Exempt paths include &lt;code&gt;.hermes/&lt;/code&gt;, &lt;code&gt;node_modules/&lt;/code&gt;, &lt;code&gt;.next/&lt;/code&gt; and other non-project directories.&lt;/p&gt;
&lt;p&gt;Plugins are loaded via Hermes&amp;rsquo;s &lt;code&gt;pre_tool_call&lt;/code&gt; hook, take effect at session start, and remain available after gateway restarts.&lt;/p&gt;
&lt;p&gt;The three layers increase in hardness from outside to inside; when rules conflict, the hardest layer wins. The system prompt is a sticky note; the plugin is a locked door.&lt;/p&gt;
&lt;p&gt;These practices aren&amp;rsquo;t new. Most of them are decades of accumulated software engineering—separation of roles, clear responsibilities, acceptance-first—just wearing a new skin in the AI era and landing in a new way.&lt;/p&gt;
&lt;h2 id="dual-track-workflow"&gt;Dual-Track Workflow&lt;/h2&gt;
&lt;p&gt;Take different tracks based on task nature.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track A: New project or feature from zero to one&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Full pipeline: Feature Doc → Plan → Build → Verify → Fix (loop).&lt;/p&gt;
&lt;p&gt;Phase one: Code Juaner writes the feature doc. Phase two: Codex plan produces the technical spec, including file list, implementation plan, data structures, and test cases. Phase three: Codex build reads the spec, implements all files, runs tests. Phase four: Code Juaner accepts each criterion.&lt;/p&gt;
&lt;p&gt;Acceptance walks through five layers: data layer (type definitions, state management), logic layer (hooks, reducers), presentation layer (component rendering, interaction binding), config layer (static config, data loading), browser verification (route checks, localStorage confirmation, screenshot comparison).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track B: Bug fixes or feature modifications&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Most projects go through Track B. Skipping the feature doc only applies to single-file, pure styling, copy changes, or minor config tweaks. Multi-file changes, those involving data persistence, state machines, or new components must write a feature doc plus spec before dispatching Codex.&lt;/p&gt;
&lt;p&gt;When delegating to Codex, give only the goal and acceptance criteria, not the implementation plan. Codex reads the code and designs by itself.&lt;/p&gt;
&lt;h2 id="preview-tunnel"&gt;Preview Tunnel&lt;/h2&gt;
&lt;p&gt;In-progress websites need to be previewed on mobile. I use Cloudflare Tunnel to expose the local Next.js dev server to the public internet; Cloudflare assigns a temporary &lt;code&gt;trycloudflare.com&lt;/code&gt; domain, open it in a mobile browser to preview.&lt;/p&gt;
&lt;p&gt;Early on I stopped and restarted the tunnel after every change, which triggered Cloudflare rate limits. Each stop and restart assigned a new URL, requiring me to reopen it on the phone—annoying.&lt;/p&gt;
&lt;p&gt;Later I wrote a &lt;code&gt;tunnel-manager.sh&lt;/code&gt; script. The first start runs &lt;code&gt;cloudflared&lt;/code&gt; as a background daemon; subsequent builds only restart the next server, not touching the tunnel. The tunnel daemon is reused across preview sessions; it only rebuilds on machine restart or &lt;code&gt;cloudflared&lt;/code&gt; crash. The same URL persists through the entire development cycle, eliminating a lot of repetitive operations.&lt;/p&gt;
&lt;h2 id="git-plus-vercel-deployment"&gt;Git plus Vercel Deployment&lt;/h2&gt;
&lt;p&gt;Hit one silent pitfall: Vercel&amp;rsquo;s GitHub integration checks whether the commit author email is a real GitHub account email. When it doesn&amp;rsquo;t match, the CLI reports &amp;ldquo;Your deployment failed&amp;rdquo; and &lt;code&gt;vercel inspect&lt;/code&gt; shows &lt;code&gt;Builds: [0ms]&lt;/code&gt;—the build never started, no logs at all.&lt;/p&gt;
&lt;p&gt;Fix: use the system git identity for commit, and rebase to reset the author if there&amp;rsquo;s a mismatch.&lt;/p&gt;
&lt;p&gt;Deployment uses Vercel CLI with &lt;code&gt;--no-wait&lt;/code&gt; to avoid timeout blocking. GitHub Actions&amp;rsquo; &lt;code&gt;deploy.yml&lt;/code&gt; triggers automatically on push to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
&lt;h2 id="some-reflections"&gt;Some Reflections&lt;/h2&gt;
&lt;p&gt;After all those specific practices, let me share some thoughts.&lt;/p&gt;
&lt;p&gt;AI writing code has developed too fast. At the start of the year I was still manually writing every line; by mid-year I already had a pipeline that can independently complete features, acceptance, and deployment. What I do has shifted from writing code to defining rules, setting boundaries, and accepting results.&lt;/p&gt;
&lt;p&gt;The engineer&amp;rsquo;s role is changing. You used to be a bricklayer, placing bricks one by one. Now you&amp;rsquo;re a rancher: set up the fences, put out enough feed, and let the herd graze and grow. The software industry is shifting from construction to animal husbandry.&lt;/p&gt;
&lt;p&gt;This trend will only accelerate. Better models mean simpler harnesses, cheaper execution costs. You don&amp;rsquo;t need to be the best programmer—you need to be the best rule-maker. Define clearly what&amp;rsquo;s allowed, what&amp;rsquo;s not allowed, and what counts as done—leave the rest to the agent.&lt;/p&gt;
&lt;p&gt;The time I spend defining boundaries has a much higher return than the time I spend on actual coding. That&amp;rsquo;s the most surprising discovery.&lt;/p&gt;</description></item></channel></rss>