<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet href="/feed_style.xsl" type="text/xsl"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="https://www.rssboard.org/media-rss"><channel><title>Software Factory on DazzLog</title><link>https://blog.dazzlog.de/tags/software-factory/</link><description>Recent content in Software Factory on DazzLog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>dazz - [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).</copyright><lastBuildDate>Wed, 02 Sep 2026 17:00:00 +0200</lastBuildDate><atom:link href="https://blog.dazzlog.de/tags/software-factory/index.xml" rel="self" type="application/rss+xml"/><icon>https://blog.dazzlog.de/logo.svg</icon><item><title>8 Stages to a Software Factory, and Where I Am Now</title><link>https://blog.dazzlog.de/posts/2026-09-02_eight-stages-to-a-software-factory/</link><pubDate>Wed, 02 Sep 2026 17:00:00 +0200</pubDate><guid>https://blog.dazzlog.de/posts/2026-09-02_eight-stages-to-a-software-factory/</guid><description><![CDATA[<div class="details admonition tldr open">
  <div class="details-summary admonition-title">
    <i class="icon ">&#xf259;</i> TL;DR<i class="details-icon fas fa-angle-right fa-fw"></i>
  </div>
  <div class="details-content">
    <div class="admonition-content">I thought I already had an advanced agent setup. What I actually had was a group of capable workers with me acting as scheduler, state machine, and safety net. DazzHub and Orca moved parts of that setup towards Stage 7, but the interesting work was not better prompting. It was isolation, state, gates, and limited permissions.</div>
  </div>
</div>
<p>A few weeks ago, I still started every coding agent myself. I opened a terminal, explained the task, watched it work, ran the tests, and decided what happened next. The agent wrote much of the code, but I remained the scheduler, the state machine, and the audit log.</p>
<p>That setup felt advanced compared with autocomplete. Then I read Upsun&rsquo;s article about <a href="https://upsun.com/blog/8-stages-ai-engineering-maturity/">the eight stages of AI engineering maturity</a>. It gave me an uncomfortable way to describe what I had built: I had several capable workers and no factory.</p>
<p>I used DazzHub, my Symfony application for discovering and processing technical videos, to find out what a software factory actually needs. Orca became the place where the agents run. What happened next was much less about clever prompts than I expected. Most of the work was state, isolation, gates, and deciding which decisions an agent may make.</p>
<h2 id="the-eight-stages">The Eight Stages</h2>
<p>The maturity model names these stages:</p>
<ol>
<li><strong>The Vacuum</strong>: developers already use AI, while the organization has made no real decision about it.</li>
<li><strong>The Drift</strong>: individual developers build private prompts, skills, and habits. Their results start to diverge.</li>
<li><strong>The Islands</strong>: whole teams develop different capabilities. One team has shared context and tooling; another does not.</li>
<li><strong>The Standardization Bet</strong>: context files, skills, security rules, approved tools, and training become shared assets.</li>
<li><strong>The Workflow Redesign</strong>: teams change the work itself. Specs become inputs, CI gates agent output, and review focuses on intent and risk.</li>
<li><strong>The Operating System</strong>: agents become part of how the team allocates work. Shared context, tests, budgets, isolation, and coordination become infrastructure.</li>
<li><strong>The Bright Factory</strong>: agents write and ship whole units of work while humans supervise. Much of this still runs interactively on a developer machine.</li>
<li><strong>The Autonomous Factory</strong>: agents run on shared infrastructure, pick up recurring work on schedules, leave central traces, pass automated evals, and escalate failures.</li>
</ol>
<p>I do not read this as a score. My setup occupies more than one stage at once. DazzHub has repository-owned skills and a formal workflow, which puts parts of it at Stage 6. An agent can take a Ready issue through an isolated worktree, implementation, CI, push, and pull request with little line-by-line authorship from me. That reaches into Stage 7. I still approve merges, and until recently I started every coding run myself.</p>
<div class="details admonition info open">
  <div class="details-summary admonition-title">
    <i class="icon ">&#xf05a;</i> The stages are not a score<i class="details-icon fas fa-angle-right fa-fw"></i>
  </div>
  <div class="details-content">
    <div class="admonition-content">A project can be at several stages at the same time. I use the model to find the next missing control, not to award my setup a bigger number.</div>
  </div>
</div>
<p>So I stopped asking, “Which stage am I?” The more useful question was: which missing part still requires my attention?</p>
<h2 id="my-starting-point-was-already-an-island">My Starting Point Was Already an Island</h2>
<p>I had accumulated a good personal setup around Claude Code. DazzHub had an <code>AGENTS.md</code>, project commands, architecture rules, and tests. I knew which prompts worked because I had discovered their failure modes one at a time.</p>
<p>That is exactly the Stage 2 trap. The setup worked because I remembered it.</p>
<p>If an agent tried to run a Doctrine migration, I knew why that was dangerous. If it injected a repository into a controller, I knew which project convention it had missed. If two sessions worked in the same checkout, I knew to stop one before they damaged each other&rsquo;s diff. None of that knowledge formed a system until I moved it into repository-owned rules and executable checks.</p>
<p>My first step toward a factory was therefore boring: make the repository explain itself.</p>
<p>DazzHub now carries skills for issue handling, pull requests, fleet operations, backlog grooming, architecture, verification, dependency updates, and naming. A normative workflow document defines which actor may move a card between <code>Backlog</code>, <code>Ready</code>, <code>In progress</code>, <code>Blocked</code>, <code>In review</code>, and <code>Done</code>. When a skill disagrees with that document, the skill is wrong.</p>
<p>This distinction matters because prompts are suggestions to a model. A state transition is a rule I need on every run.</p>
<h2 id="orca-gave-the-agents-a-place-to-work">Orca Gave the Agents a Place to Work</h2>
<p>The maturity model describes Stage 7 agents running from terminals on laptops. I wanted to remove my laptop from the execution path early, so I installed Orca on a dedicated Ubuntu VM called <code>dazztronic-box</code>.</p>
<p>I chose Ubuntu even though my desktop runs NixOS. Orca ships Linux builds as an Electron AppImage and updates often. More important, agents install tools at runtime: npm packages with native builds, Python tools, downloaded binaries. I am willing to debug Nix store paths on my own desktop. I do not want an unattended run to fail overnight because a downloaded binary expects an FHS system.</p>
<p>The VM has two users with real roles:</p>
<ul>
<li><code>dazz</code> operates the machine and has sudo.</li>
<li><code>dazztronic</code> runs Orca, the coding agents, rootless Docker, repositories, and a restricted GitHub identity.</li>
</ul>
<p>Orca runs Claude Code, Pi, and Codex as children of the runner. Giving Orca a third Unix user would only duplicate credentials while requiring the same repository access. The useful boundary is the runner account.</p>
<div class="details admonition warning open">
  <div class="details-summary admonition-title">
    <i class="icon ">&#xf071;</i> The real security boundary<i class="details-icon fas fa-angle-right fa-fw"></i>
  </div>
  <div class="details-content">
    <div class="admonition-content">Anything the <code>dazztronic</code> account can do, an agent may eventually do too. I try not to confuse separate agent sessions with separate security boundaries.</div>
  </div>
</div>
<p>With Orca, I found several pieces that map directly onto the factory problem.</p>
<h3 id="remote-runtime">Remote runtime</h3>
<p><code>orca serve</code> keeps the runtime on the VM. I can connect from my NixOS desktop or my phone, while the repositories, credentials, containers, and sessions stay on the server. Closing my laptop no longer kills the place where the work happens.</p>
<h3 id="worktrees-as-first-class-workspaces">Worktrees as first-class workspaces</h3>
<p>Orca can create a worktree and open it as a tracked workspace. Each issue gets its own branch, checkout, terminal, and agent session. DazzHub&rsquo;s factory CLI now prefers <code>orca worktree create</code> when the Orca runtime is reachable and falls back to <code>git worktree add</code> when it is not.</p>
<p>That sounds like convenience until two agents edit the same checkout. Isolation is a prerequisite for parallel work, not a UI feature.</p>
<h3 id="several-agents-in-one-runtime">Several agents in one runtime</h3>
<p>Claude Code, Pi, and Codex can live on the same box. I do not need to pretend they are interchangeable. Claude currently does most execution, Pi has been useful as an independent reviewer, and Codex is present but still lacks a fully verified login and tracing path. The runtime lets me assign different jobs without moving the repository or copying context between machines.</p>
<h3 id="orchestration">Orchestration</h3>
<p>Orca sessions can start workers in child worktrees and keep the coordinator separate from the implementation context. This is close to the shape I want: one session reasons about the queue and delegates bounded units of work; worker sessions operate in isolated checkouts.</p>
<p>The important discovery was that orchestration alone does not create governance. A coordinator can start five workers just as easily as one. DazzHub still needs the board claim, WIP rules, verification gate, and merge policy around it.</p>
<h3 id="scheduled-automations-with-prechecks">Scheduled automations with prechecks</h3>
<p>Orca automations supplied the first unattended actor in the workflow. An hourly backlog groomer checks whether the board has capacity before it starts a model session. A full board exits at the precheck, records a skipped run, and spends no tokens.</p>
<p>When there is capacity, the groomer reads <code>Backlog</code>, verifies one issue against the code, and either promotes a complete spec to <code>Ready</code>, asks one concrete question, or marks a thin issue for refinement. It never writes code and never touches a card outside <code>Backlog</code>.</p>
<div class="details admonition tip open">
  <div class="details-summary admonition-title">
    <i class="icon ">&#xf400;</i> I learned<i class="details-icon fas fa-angle-right fa-fw"></i>
  </div>
  <div class="details-content">
    <div class="admonition-content">The useful unit is not “an autonomous agent.” It is an actor allowed to make one kind of decision under conditions I can check.</div>
  </div>
</div>
<p>That narrow permission was my first practical lesson in autonomy. Small permissions are easier to trust, test, and take away again.</p>
<h2 id="the-first-factory-pieces">The First Factory Pieces</h2>
<p>The repository now contains a small Deno CLI under <code>factory/</code>. It grew from repeated shell fragments in Markdown that had no tests. The CLI handles board reads and writes, journal entries, and worktree lifecycle. Its exit codes are contracts because both skills and Orca prechecks branch on them.</p>
<p>The issue flow looks like this:</p>
<ol>
<li>A complete card reaches <code>Ready</code>.</li>
<li>An agent claims it before analysis, so another run cannot take the same work.</li>
<li>The factory creates an isolated worktree.</li>
<li>The agent changes only the requested scope.</li>
<li>The full local gate runs: PHPUnit, PHPStan, CS Fixer, and Deptrac.</li>
<li>A focused architecture review checks what those tools cannot see.</li>
<li>A green run pushes a feature branch and opens a pull request.</li>
<li>GitHub Actions runs the same gate again.</li>
<li>I review and approve before the agent may merge.</li>
</ol>
<p>Failures also have a path. A red gate gets up to three bounded attempts with wider context. After that, the card moves to <code>Blocked</code>, gets a reason label, returns to me, and keeps its worktree for inspection. An environmental failure can resume only after the run repeats the exact check named in the block comment.</p>
<p>I used to treat a failed agent session as a conversation that went badly. Now it becomes state another session can inspect. For me, that is a much bigger improvement than another clever prompt.</p>
<h2 id="where-this-leaves-me">Where This Leaves Me</h2>
<p>DazzHub sits around Stage 6 with working parts of Stage 7. Agents can deliver complete issues, and Orca already supplies shared runtime, worktree isolation, coordination, remote access, and scheduled automations. The backlog can refill itself under a WIP cap.</p>
<p>The queue still does not drain itself. A human starts the coding run on a <code>Ready</code> card. I still approve every merge. The workflow records failure states, but it does not yet have the immutable envelope that should carry attempts, touched paths, gate results, and rejection history through every phase.</p>
<p>Those gaps are useful. They tell me where to work next without pretending that “more autonomy” is one feature.</p>
<p>The next post in this series follows the less tidy part: using the setup on real DazzHub issues, finding where the Markdown rules drifted, and turning repeated mistakes into a tested factory CLI.</p>
]]></description><media:thumbnail url="https://blog.dazzlog.de/8-stage-software-factory.png"/></item><item><title>Orca Is My Agent Development Environment Now</title><link>https://blog.dazzlog.de/posts/2026-08-23_orca-is-my-agent-development-environment/</link><pubDate>Sun, 23 Aug 2026 17:00:00 +0200</pubDate><guid>https://blog.dazzlog.de/posts/2026-08-23_orca-is-my-agent-development-environment/</guid><description><![CDATA[<p>I used to open an IDE, open a terminal, find the right file, make a change, and run the tests myself.</p>
<p>That is still a perfectly reasonable way to develop software. It is also no longer the way I want to work.</p>
<p>At the beginning of August, I moved my development into <a href="https://herdr.dev/">Herdr</a>. Herdr gave me the first important step away from an IDE: one terminal interface for several agents and projects. I could send an agent to work, switch to another project instead of watching it, and see when the first agent had finished.</p>
<p><img src="ide.jpg" alt="ide.jpg"></p>
<p>That already matched the way I wanted to work. An IDE assumes that I operate Git, the file browser, the terminal, and the editor. Once a coding agent operates those tools, my job moves up a level. I describe the work, give the agent the project context, inspect the result, and decide what happens next.</p>
<p>Herdr brought the pieces together for me. I did not use it for long, because I found <a href="https://onorca.dev/">Orca</a> soon afterwards and was stunned by how much more it brought around the same agent-management idea.</p>
<h2 id="from-herdr-to-orca">From Herdr to Orca</h2>
<p>I had already stopped waiting beside a single coding agent. Herdr let me manage several agents and projects from one place. Orca kept that model and added workspaces, Git worktrees, orchestration, skills, automation, remote clients, and a server runtime.</p>
<p>I installed Orca on my computer first. During installation and setup it changed enough on my system that I reconsidered where any of my AI development should run. Coding agents install tools, create worktrees, start containers, store credentials, and leave session data behind. I no longer wanted all of that mixed into my personal workstation.</p>
<p><img src="herdr.jpg" alt="herdr.jpg"></p>
<p>Orca&rsquo;s documentation described several remote-server setups. I could have rented a virtual server. Instead, I already had a powerful AI computer sitting on my desk, so I created an Ubuntu VM on it and moved Orca, the agents, the repositories, and Docker into that VM.</p>
<p>That decision made Orca much more than the richer successor to the setup I had in Herdr. The agents now had a permanent place to work, independent of the computer I happened to be using.</p>
<h2 id="what-orca-adds-to-coding-agents">What Orca adds to coding agents</h2>
<p>Orca does not replace GitHub, Git, Docker, Claude Code, Pi, or Codex. It puts them into an environment where several agent sessions can work at once and where I can manage them as work rather than as disconnected command lines.</p>
<p>The parts I use most are these:</p>
<ul>
<li>workspaces and Git worktrees for isolated tasks;</li>
<li>terminals that belong to those workspaces;</li>
<li>several agents and models in one runtime;</li>
<li>orchestration, where a coordinator can start worker sessions;</li>
<li>skills and project context that tell an agent how this repository works;</li>
<li>remote access from a desktop or phone;</li>
<li>a headless server mode that keeps the work alive when my computer is closed;</li>
<li>automations that can run recurring, narrowly scoped actions;</li>
<li>session history and runtime state that make it possible to inspect what happened.</li>
</ul>
<p>The important feature is not any one item in that list. It is that Orca treats agent work as something that has a lifecycle.</p>
<p><img src="orca-ade.jpg" alt="orca-ade.jpg"></p>
<h2 id="worktrees-are-not-a-detail">Worktrees are not a detail</h2>
<p>DazzHub is the project where I am testing this way of working. It is a Symfony application that discovers YouTube videos, scores them with AI, fetches transcripts, and turns them into searchable knowledge and Markdown blog posts. It has PostgreSQL with pgvector, Neo4j, asynchronous workers, external services, and a serious test and architecture toolchain.</p>
<p>It is also exactly the kind of existing project where two agents must not casually share a checkout.</p>
<p>For an issue, I create an Orca worktree. The issue gets its own branch, directory, terminal, and agent session. The agent can inspect the project, edit files, run the checks, commit, push, and open a pull request without writing into the checkout where another task is running.</p>
<p>The isolation is more important than the interface. Two agents editing the same working tree can make both sessions appear productive while producing a diff nobody can explain. A separate worktree turns that into two inspectable pieces of work.</p>
<p>In practice, my flow looks roughly like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>orca worktree create --name <span style="color:#f1fa8c">&#34;152-embedding-agent-to-domain-service&#34;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --repo path:/srv/workspaces/dazzhub <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --base-branch main --issue <span style="color:#bd93f9">152</span> --activate --json
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>orca terminal create --worktree <span style="color:#f1fa8c">&#34;path:</span><span style="color:#8be9fd;font-style:italic">$WORKTREE</span><span style="color:#f1fa8c">&#34;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --title <span style="color:#f1fa8c">&#34;pi gpt-5.6-sol DAZ-152&#34;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --command <span style="color:#f1fa8c">&#34;pi --skill </span><span style="color:#8be9fd;font-style:italic">$WORKTREE</span><span style="color:#f1fa8c">/.claude/skills --model gpt-5.6-sol&#34;</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --json
</span></span></code></pre></div><p>The exact commands are wrapped by DazzHub&rsquo;s factory tooling now, but the shape matters: create an isolated place first, then start the worker inside it.</p>
<h2 id="i-do-not-use-one-agent-for-everything">I do not use one agent for everything</h2>
<p>Claude Code is still part of my daily work. Pi runs alongside it and is especially useful when I want a different agent implementation, model, or an independent review. Codex is installed as a third option and I am wiring it into the same conventions gradually rather than pretending that installation means integration.</p>
<p>They share a machine, but they do not share identical behavior.</p>
<p>Claude Code and Pi have different session formats, different startup behavior, and different ways of loading project context. Pi does not automatically discover DazzHub&rsquo;s <code>.claude/skills</code> directory, so I pass it explicitly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pi --skill /srv/workspaces/dazzhub/.claude/skills <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>   --model gpt-5.6-sol
</span></span></code></pre></div><p>That command is not decoration. Without the skill directory, Pi can write technically plausible code while missing the repository&rsquo;s rules about architecture, tests, migrations, naming, worktrees, and verification.</p>
<p>The agents run as the server user, with the permissions of that user. Pi has no permission system that makes an unattended run safe by itself. The containment is provided by the machine: the runner has no sudo, Docker is rootless, and the repositories and credentials belong to that runner. This is an operational boundary, not a magic property of the model.</p>
<h2 id="the-repository-is-part-of-the-agent">The repository is part of the agent</h2>
<p>The biggest mistake would be to think that Orca makes prompts unnecessary. It makes the surrounding system more important.</p>
<p>DazzHub has an <code>AGENTS.md</code>, project rules, architecture documentation, workflow documentation, skills, tests, Make targets, and a small factory CLI. Those files explain how the project is supposed to be changed. The agent is not just given an issue; it is given the local way of working.</p>
<p>The skills describe roles rather than one giant super-prompt:</p>
<ul>
<li>an issue worker claims a ready card and takes it through implementation and verification;</li>
<li>a fleet skill owns worktrees and isolated checks;</li>
<li>a pull-request skill handles review feedback and merge policy;</li>
<li>a verifier compares a pull request with its acceptance criteria;</li>
<li>a backlog groomer decides whether one Backlog card is specified enough to become Ready;</li>
<li>a board walker dispatches eligible Ready cards to implementers;</li>
<li>dependency and infrastructure skills handle their narrower kinds of change.</li>
</ul>
<p>The skills do not replace deterministic checks. They tell the agent what to do. The factory CLI and CI enforce the parts that should not depend on the model remembering them.</p>
<p>That distinction has become central to my system: a prompt may propose a transition, but it must not be the authority that silently performs every transition.</p>
<h2 id="how-i-give-the-system-work">How I give the system work</h2>
<p>My source of work is the GitHub Project board. The board has states such as <code>Backlog</code>, <code>Ready</code>, <code>In progress</code>, <code>Blocked</code>, <code>In review</code>, and <code>Done</code>. The workflow document defines which actor may move a card and which transitions are forbidden.</p>
<p>I do not throw a pile of vague ideas at an agent and hope that it turns them into good work. I refine the issue until it has a clear scope, acceptance criteria, and enough information for an implementer to start without inventing the product decision.</p>
<p>The current factory separates intake from execution.</p>
<p>The backlog groomer reads the board and the code, then performs at most one useful action: promote one fully specified card to <code>Ready</code>, ask one question that blocks it, or report that there is nothing it can responsibly promote. It does not write code.</p>
<p>The board walker reads <code>Ready</code>, claims an eligible card, creates its worktree, starts the implementer, and records the dispatch only after the terminal is actually running. It does not merge, review, or follow the worker. That is deliberate. Small permissions are easier to reason about than a general-purpose autonomous manager.</p>
<p>A precheck keeps a full queue from starting another model session. A skipped automation run is normal. It means there was no work the actor was allowed to take, so no session and no tokens were spent.</p>
<p>The implementer then follows the DazzHub path:</p>
<ol>
<li>claim one issue;</li>
<li>inspect the repository and the acceptance criteria;</li>
<li>change only the requested scope;</li>
<li>run CS Fixer, Deptrac, PHPUnit, and PHPStan through the project gate;</li>
<li>correct failures or stop with a precise blocked reason;</li>
<li>push the branch and open a pull request;</li>
<li>wait for review and approval before merging.</li>
</ol>
<p>I do not want an agent to merge merely because the tests are green. CI tells me that the tested constraints pass. It does not make the product decision for me.</p>
<h2 id="orca-lets-me-orchestrate-instead-of-babysit">Orca lets me orchestrate instead of babysit</h2>
<p>There are two ways I use multiple sessions.</p>
<p>Sometimes I start several independent issue workers. Each one has its own worktree and its own terminal. That is the simple form of parallelism: several pieces of work move at the same time, and I can inspect each result separately.</p>
<p>The other form is a coordinator session. A coordinator receives the larger task, breaks it into bounded work, and starts worker sessions in child worktrees. The coordinator can keep the overall plan while each worker gets a narrower context.</p>
<p>This is where Orca feels very different from a normal IDE. An IDE can open five terminals. Orca gives me a place for a group of agents whose relationships are part of the runtime.</p>
<p>It also makes the limits visible. Parallelism is not automatically good. Agents can still collide conceptually, use the same external resources, exhaust API limits, or create more review work than I can handle. Worktree isolation prevents one class of damage; it does not remove the need for a queue, a WIP cap, or human judgment.</p>
<h2 id="building-the-remote-orca-server">Building the remote Orca server</h2>
<p>I set up an Ubuntu VM called <code>dazztronic-box</code> and installed Orca&rsquo;s Linux AppImage there. My desktop runs NixOS, but I chose Ubuntu for the agent server. Orca ships frequently as an Electron AppImage, and agents install software at runtime: npm packages, Python tools, downloaded binaries, and native dependencies. Ubuntu gives those tools the conventional Linux environment they expect.</p>
<p>The VM runs with four cores, 16 GB of RAM, and a 100 GB disk on the AI computer already sitting on my desk. It uses VMware NAT and connects to my devices through Tailscale, so I did not need to rent another server or expose Orca directly to the internet.</p>
<p>Permissions and Docker caused the predictable trouble. The less predictable part was making Orca, rootless Docker, systemd, and a headless login session agree about the runner&rsquo;s environment. Once I had cleared those hurdles, all AI development could happen inside the VM instead of altering my workstation.</p>
<p>I use two Unix roles:</p>
<ul>
<li><code>dazz</code> is the operator and has sudo for the machine setup;</li>
<li><code>dazztronic</code> is the runner and owns Orca, the repositories, the agents, Docker, and the GitHub identity, but has no sudo.</li>
</ul>
<p>I did not create a fake third <code>orca</code> service user. Orca starts agents as child processes. A separate service user would either be unable to write the repositories or would need the same access as the runner. The meaningful boundary is that the account executing the agent is not allowed to become root.</p>
<p>Docker is rootless for the same reason. A user in the rootful Docker group is effectively root. Rootless Docker requires a little more setup, including user namespaces, subordinate UID/GID ranges, lingering, and an explicit <code>DOCKER_HOST</code>, but it preserves the security story.</p>
<h2 id="headless-orca-and-remote-access">Headless Orca and remote access</h2>
<p>The useful command is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>/opt/orca/orca-linux.AppImage serve <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --port <span style="color:#bd93f9">6768</span> <span style="color:#f1fa8c">\
</span></span></span><span style="display:flex;"><span>  --pairing-address 100.x.y.z
</span></span></code></pre></div><p><code>orca serve</code> keeps the runtime on the VM. I connect to it from the Orca desktop client through Tailscale. Orca also has an Android app that I paired with the same server. The repositories, projects, sessions, credentials, containers, and running agents remain on the VM.</p>
<p>This changed my daily life most. I can start an agent at home, close the computer, and later open Orca on my phone. I reconnect to the same projects and agents, read their state, answer a question, send another instruction, or start more work while I am away from my desk.</p>
<p>I also enabled Orca&rsquo;s voice feature. At my computer I can speak to each agent instead of typing every instruction. The interaction feels less like operating a development tool and more like checking in with workers who already have the project and its current state in front of them.</p>
<p>All projects run under the same server account, so they can see one another in my setup. I use that deliberately. An agent working in DazzHub or in the infrastructure project can open the blog repository and draft an article from the work it just inspected. That is unusually useful for me because the application, the factory, the infrastructure, and this blog document the same experiment.</p>
<p>Cross-project visibility is a choice, not a requirement of remote Orca. Another setup may need strict project boundaries, separate runner accounts, or separate servers. On my personal machine, sharing the workspace removes handoffs I would otherwise perform by copying notes between projects.</p>
<p>For persistence, I run Orca as a systemd service. The service has to provide the runner&rsquo;s rootless Docker socket explicitly because a system service does not inherit the interactive shell&rsquo;s <code>XDG_RUNTIME_DIR</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#ff79c6">[Service]</span>
</span></span><span style="display:flex;"><span><span style="color:#50fa7b">User</span><span style="color:#ff79c6">=</span><span style="color:#f1fa8c">dazztronic</span>
</span></span><span style="display:flex;"><span><span style="color:#50fa7b">Environment</span><span style="color:#ff79c6">=</span><span style="color:#f1fa8c">LIBGL_ALWAYS_SOFTWARE=1</span>
</span></span><span style="display:flex;"><span><span style="color:#50fa7b">Environment</span><span style="color:#ff79c6">=</span><span style="color:#f1fa8c">DOCKER_HOST=unix:///run/user/1000/docker.sock</span>
</span></span><span style="display:flex;"><span><span style="color:#50fa7b">ExecStart</span><span style="color:#ff79c6">=</span><span style="color:#f1fa8c">/opt/orca/orca-linux.AppImage serve --port 6768 --pairing-address 100.x.y.z</span>
</span></span><span style="display:flex;"><span><span style="color:#50fa7b">Restart</span><span style="color:#ff79c6">=</span><span style="color:#f1fa8c">on-failure</span>
</span></span></code></pre></div><p>The <code>LIBGL_ALWAYS_SOFTWARE</code> setting is necessary on a headless machine without a usable GPU. The system comes back after a reboot, and the agent runtime no longer depends on my desktop being open.</p>
<h2 id="the-server-had-one-particularly-strange-failure">The server had one particularly strange failure</h2>
<p>The headless server exposed an Orca problem that was invisible during the first start.</p>
<p><code>serve</code> started successfully, but the CLI commands used to inspect the runtime failed with <code>bad option: --no-sandbox</code>. Ubuntu restricts unprivileged user namespaces through AppArmor. Orca&rsquo;s AppImage detects that restriction and adds Electron&rsquo;s <code>--no-sandbox</code> fallback. That is reasonable for starting the full Electron application. The CLI starts the AppImage as Node with <code>ELECTRON_RUN_AS_NODE=1</code>, and Node does not understand the Electron flag.</p>
<p>The server looked healthy while the CLI was broken.</p>
<p>I kept the global Ubuntu restriction enabled and added a path-bound AppArmor profile that grants the Orca AppImage the user namespace capability it needs. After that, the CLI worked and the full server ran with the real Chromium sandbox instead of the fallback.</p>
<p>That was a useful lesson for the whole system: “the process started” is not the same as “the runtime works.” The smoke test is <code>orca status --json</code>, not a process list.</p>
<h2 id="observability-matters-once-agents-multiply">Observability matters once agents multiply</h2>
<p>When one agent runs on a laptop, I can often remember what happened. With Claude Code, Pi, and Codex on a server, each tool has its own local session logs and format. I want one place to answer questions such as:</p>
<ul>
<li>Which agent worked on this issue?</li>
<li>Which tools did it call?</li>
<li>Where did it retry?</li>
<li>How much did the run cost?</li>
<li>Did it stop because of a code failure, an environment failure, or a missing instruction?</li>
</ul>
<p>I am adding self-hosted Langfuse as an observer rather than replacing the agent runtimes. Claude Code&rsquo;s hooks, Pi&rsquo;s extension, and Codex&rsquo;s plugin can turn their existing session data into traces. The Langfuse stack runs separately with its own PostgreSQL, ClickHouse, Redis, MinIO, web service, and worker.</p>
<p>That stack is not free. It uses RAM, disk, and operational attention. Centralized traces also collect prompts, tool calls, paths, and accidental secrets, so observability increases both auditability and the value of what must be protected. I am treating it as infrastructure with a budget, not as a checkbox.</p>
<h2 id="what-i-still-do-myself">What I still do myself</h2>
<p>I am not pretending that Orca has removed me from software development.</p>
<p>I define what matters. I refine vague issues. I decide which work is safe to run in parallel. I inspect the plan and the diff. I read the failures that the agents cannot resolve. I review pull requests and approve merges. I decide when a blocked card is ready to try again.</p>
<p>The difference is that I no longer have to spend my attention on every keystroke or sit beside every running process. The system can carry work while I am away, and it leaves me places to inspect the result.</p>
<p>There are still important boundaries. Not every automation is fully proven end to end. Codex is installed but less integrated than Claude Code and Pi. Central logging has to be checked against real traces, not merely a successful hook installation. Resource limits, API limits, review capacity, and overlapping work remain real constraints. An unattended agent can still do the wrong thing quickly.</p>
<p>That is why I keep the factory&rsquo;s permissions narrow, isolate worktrees, run deterministic gates, record blocked states, and retain a human merge decision.</p>
<h2 id="i-do-not-want-to-go-back">I do not want to go back</h2>
<p>The thing I love about <a href="https://onorca.dev/">onorca.dev</a> is not that it makes an agent type faster. It changes what is possible to supervise.</p>
<p>I can give work to several agents. I can see where they are. I can let them use different models and tools. I can keep their work isolated. I can leave the computer. I can reconnect from my phone. I can add a coordinator, a board, a queue, scheduled actors, tests, and traces around the sessions.</p>
<p>The IDE was designed for me to operate the tools. Orca is designed for me to build a system in which agents operate the tools and I operate the system.</p>
<p>That is a long way from normal software development. It is also the first development workflow I have used where I genuinely do not want to do anything else anymore.</p>
<p>The next boundary is the uncomfortable one: deciding how much of the final review and merge process can become machine-governed without turning a green check into an excuse to stop thinking.</p>
]]></description><media:thumbnail url="https://blog.dazzlog.de/orcaorcaorca.png"/></item></channel></rss>