How I ship for my company's platform on (almost) autopilot

My learnings from developing solo for a year

16 October 2026

Pixel drawing: a laptop at home at night with three terminal panes, the orchestrator in blue and two builders in orange, and a phone in green receiving a ping

As many of us do, I try to keep up with news on AI. There are swarms of posts boasting about how LLMs have skyrocketed productivity and how everyone is seemingly “shipping constantly”. Many of the tips in those posts didn’t survive when it came to production-grade work, at least for me. I wanted to write this post since I have something that genuinely works for me.

This post is about our IoT platform (IoT servers and web-based dashboard). I develop our embedded software & hardware as well, which is subject to its own post.

Most of the strategies and concepts, if not all, described here is not novel. In fact, many of them are just SDLC best practices. I cherish only the fact that I was able to align them well enough within an AI-assisted development process to produce results I am confident about.

I am not an expert. This is only intended as practical tips that work for me, merely as my accumulation of experience going back and forth with AI-assisted building.

I anticipate more than half of these tips will expire (or be superseded) within 6 months. 2 years ago, “prompt engineering” was all the hype. Then, models and harnesses got better. Now, “context engineering” is the hype, to manage larger or continued tasks across sessions. All this will likely face the same fate, albeit quicker.

About me

I started my own business as a third-year CompSci student at Northwestern. We digitalize hygiene monitoring in hospitals and food businesses with our IoT platform, called YIKA. The hardware, firmware, and software is all built in-house.

I wrote code when I first founded the company. Then I was off the keyboard for a few years, managing the business. In the past year, I have been running the company solo, product first. I came back to building, just as the job of building itself was changing. Why me and my board decided to run it solo is a future post.

A one-person company cannot live in one person’s head, so over time I was able to build a system that remembers, checks and reports. This post covers a piece of our product-related efforts.

How I ship a task today to production

Two touch points

  1. I point at a task. The “orchestrator” agent scopes it for my review. I go back and forth with the orchestrator agent as needed. Once I approve, it sends the work to “builder” agents on my frontend and backend repositories (either or both, depending on the task).
  2. I hear back when the task is complete and proven on staging, with production PRs open. Then I review and approve the production merge.

Everything between those points runs without me.

Who is who

Orchestrator, frontend builder, backend builder: all three are Claude Code sessions. Same tool, each started in a different folder. No custom harness: the custom part is the skills, hooks and rule files.

Claude Code does have an agent teams feature (still experimental). I chose not to use it because a team lives inside one lead session: a teammate starts without the history of the work, the lead approves its plan automatically, and the team is gone when the session ends. My builders live in their own repos and keep their own rules/lessons. A fresh start is exactly what I want for reviewers and exactly what I don’t for builders.

The setup

I make the decisions; one orchestrator runs the restMemory for the builders, amnesia for the reviewersAlways-on laptop at home, in tmux panesMephone or laptopover SSHdecisionspingsOrchestratorscopes, briefs, checksmemory: lessons from mistakesFresh reviewersno memory, on purposework on an isolated copyBackend builderown repo, own rules & lessonsFrontend builderown repo, own rules & lessonsdirect messagesI make the decisions;one orchestrator runs the restMemory for the builders, amnesia for the reviewersAlways-on laptop at home,in tmux panesMephone or laptopover SSHdecisionspingsOrchestratorscopes, briefs, checksmemory: lessons from mistakesdirect messagesBackend builderown repo,own rules & lessonsFrontend builderown repo,own rules & lessonsFresh reviewersno memory, on purposework on an isolated copy

I have a second laptop at home, online 24/7 (like a VPS). The orchestrator and the two builders live in terminal panes on it. I connect over SSH from my laptop or my Claude app on the phone. I get pings when something needs me. So the trio keeps working while I’m away from the desk, and all of it runs on one Claude subscription, next to everything else I use Claude for.

I always communicate with the orchestrator. Orchestrator <--> builders communicate directly (thanks to Claude Code’s cross-session messaging) with each other.

This is what it looks like mid-task: the orchestrator on top, the two builders below.

The workflow

Most of my time and my attention goes into the scope for each task. The rest of the pipeline is designed as “Swiss cheese”, i.e. layers to ensure that scope is realized as intended, without error. One layer’s error gets caught in the subsequent one.

I find colliding agents against each other is a smart principle for this purpose. This pipeline has matured over time, such that the holes rarely line up now = errors and deviations get caught before they are shipped.

An error must slip through eight layers to reach a customerEight layers before release, two after, and the holes rarely line up.an errorstopped hereScope reviewThe wrong problem, one-way decisions, missing casesDispatch with pushbackWrong instructions, and wrong premises inside questionsPlan and failing testsA misunderstood requirement, before any code existsCode review, then refutersBugs in the code; refuters drop the invented findingsLocal walkWhat tests cannot see: the screen as a person sees itPipeline checksEvery test, lint and guard script. Red code cannot merge.Staging walkDeploy and settings problemsMy production mergeThe outcome the task should show: I test it myselfreleased: customers can see it from hereProduction walkReal data and real usersOutcome reviewWhether we built the right thing: did customers change?who catches it:meorchestratorbuildersmachineAn error must slip through eight layersto reach a customerEight layers before release, two after,and the holes rarely line up.an errorstopped hereScope reviewThe wrong problem, one-waydecisions, missing casesDispatch with pushbackWrong instructions, and wrongpremises inside questionsPlan and failing testsA misunderstood requirement,before any code existsCode review, then refutersBugs in the code; refuters dropthe invented findingsLocal walkWhat tests cannot see:the screen as a person sees itPipeline checksEvery test, lint and guard script.Red code cannot merge.Staging walkDeploy and settings problemsMy production mergeThe outcome the task should show:I test it myselfreleased: customers cansee it from hereProduction walkReal data and real usersOutcome reviewWhether we built the right thing:did customers change?who catches it:meorchestratorbuildersmachine

Step 0. Scoping work

This is the place that demands insight, original thinking, and reasoning from my side. I remain on the reviewing and approving side of the work in every other part of the workflow, besides this one.

Every task starts the same way. I point at the task I want to tackle with the scope task skill, and the orchestrator asks me about the why. Then it reads the code and drafts a spec. My specs are straightforward:

For any UI/UX change, the orchestrator creates a mockup first for my review. For any logic/overall backend change, every case maps to an outcome and each case becomes a test.

Before I see the final spec, the orchestrator attacks its own spec with ephemeral subagents. Each reviewer gets one angle and its own isolated copy of the code:

Nothing reaches me without evidenceHow a task is checked against the backlog, drafted, and attacked before I read itBacklog sweepdoes a task like this already exist?Draft specevery case maps to exactly one outcomeSix reviewers, one angle each, each on an isolated copyOne-way doorsWhat does this makeimpossible later?Who sees whatWho now sees somethingthey could not before?Backlog conflictWhich other tasks touchthe same code or screens?ReachabilityCan every new screenbe reached, and left?DuplicationDoes anything now existin two places?FalsifiabilityCan the checklist be tickedwhile it is still broken?Evidence?DroppednoyesRefuterstry to prove each finding wrongDroppedproven wrongsurvivesRankedby one question: can we undo it?I read the specNothing reaches me without evidenceHow a task is checked against the backlog,drafted, and attacked before I read itBacklog sweepdoes a task like this already exist?Draft specevery case maps to exactly one outcomeSix reviewers, one angle each,each on an isolated copyOne-way doorsWhat does this makeimpossible later?Who sees whatWho now sees somethingthey could not before?Backlog conflictWhich other tasks touchthe same code or screens?ReachabilityCan every new screenbe reached, and left?DuplicationDoes anything now existin two places?FalsifiabilityCan the checklist be tickedwhile it is still broken?Evidence?DroppednoyesRefuterstry to prove each finding wrongDroppedproven wrongsurvivesRankedby one question: can we undo it?I read the spec

I came to learn that a reviewer, unsupervised, can invent a concern for free, and an invented concern costs a round of my attention. When prompted, models are inclined to always find “something” instead of giving nothing. That’s why findings should be sifted: ones without evidence are dropped, and refuters try to prove each finding wrong. Lastly, the survived findings are ranked based on whether we can undo it later.

scope-task.mdorchestrator skill · trimmed starter, copy and adapt
---
name: scope-task
description: Turn a backlog item into a spec an agent can build from
---
Scope this task: $ARGUMENTS

1. Ask me, one question at a time: why does this exist, what is true
   today and after, what it unlocks, what outcome we expect and when
   we check it. Never invent an answer.
2. If it changes a screen: find where it lives in the code, draw a
   mockup, name how a user gets in and out. Wait for my OK.
3. Sweep the backlog by name: which item is closest, and why this is
   not a duplicate of it.
4. Read the code to understand the task, not to solve it.
5. Draft the definition of done as checks someone can run.
6. Before you show me, attack the spec. One fresh subagent per angle,
   each on its own copy of the code:
   - What does this make impossible later?
   - Who now sees something they could not before?
   - Which other backlog items touch the same code or screens?
     (Never run this one yourself: the author shares the blind spot.)
   - Can every new screen be reached, and left?
   - Does anything now exist in two places?
   - Can the checklist be ticked while it is still broken?
   Drop findings without evidence. Give the rest to a refuter told to
   disprove each one. Rank what survives by: can we undo it after we ship?
7. Show me the full spec. Write it only after I say yes.

Step 1. Dispatch: suggestions, not orders

When a task is ready to execute, the orchestrator gives the builder(s) goals and constraints, not orders. The builder(s) creates and owns the plan. Everything the orchestrator says comes in one of three kinds:

  1. A decision we made which is binding
  2. A constraint learned from a failure which has a pointer to that occurence
  3. A technical note from the orchestrator’s own reading of the code.

It is important that technical notes remain suggestive. In earlier iterations of this workflow, when my orchestrator wrote technical claims, many of them did bounce back from builders, but in some cases they were accepted as is, and a wrong claim stated with confidence costed rounds of my attention.

While models have some backbone and stand their ground, to avoid any failures, every dispatch from orchestrator ends the same way: “Push back if this does not make sense. If a question I asked carries an assumption, challenge the assumption first.” A wrong premise hidden in a question shapes the whole investigation.

This is also why another important principle is separation of concerns across the work. I experienced that scoping, cracking the implementation, and verifying in a single session is not feasible (at least with today’s LLMs), hence why I have an orchestrator and builders separately in the first place.

dispatch-template.mdorchestrator message to a builder · trimmed starter, copy and adapt
TASK-<id> · <name>

THE TASK. Read the spec: <path>. You own <the part this builder owns>.
- DECISIONS (binding): <list>. If one does not make sense, push back at
  the plan stop.
- CONSTRAINTS (firm, each with its source): <list>.
- NOTES (my reading of the code, suggestions only): verify each one.

PLAN AND FAILING TESTS, ONE STOP. Send your plan and the failing tests
together. Do not implement until I review them. The plan names every
file you will change and the test that covers each item of the
definition of done.

GATE. After implementation: code review at first green, then every
check the pipeline runs. Zero skipped, no retries. Account for every
command, run or not. Never change a test to match what the code does
without a diagnosis.

COMMIT. Do not commit or push until I approve the diff.

REPORT. Message me at every stop. Never end a turn without a report or
a question.

PUSH BACK. Push back if this does not make sense. If a question I asked
carries an assumption, challenge the assumption first.

Step 2. Test-driven development, and the rubber-stamping problem

The first thing builders do per the dispatch is to write their plan on how to execute the task and write failing tests about the given task. The builders report back to the orchestrator with their plan and tests. Orchestrator reviews them, and gives the go-ahead with corrections or nudges where needed.

Now, LLMs like to write a LOT of tests, and a high pass count feels like safety. Early on, the orchestrator treated it that way: it approved a set of tests because the builder’s summary said “22 tests across 6 groups”, all green. I asked one question: “Did you check the test file and verify?” It had not. That question started four checks toward knowing what a green test really tells you.

Four questions for any green test1What does it actually check?Read the assertion, not the pass count. “Something is visible” is not “the right value is shown”.2Is the fake data true?A mock is a claim about the world. Only a walk on the real system checks it.3What state makes it fail?If nobody can name one, the test cannot fail.4Have I seen it fail?Break the guarded code on a throwaway copy, watch the test go red, then delete the copy.Four questions for any green test1What does it actually check?Read the assertion, not the pass count.“Something is visible” is not“the right value is shown”.2Is the fake data true?A mock is a claim about the world.Only a walk on the real system checks it.3What state makes it fail?If nobody can name one, the test cannot fail.4Have I seen it fail?Break the guarded code on a throwaway copy,watch the test go red, then delete the copy.

I ask you to try this: on a throwaway copy, break the code your most trusted test protects. If the test stays green, you learned something cheap.

Step 3. Build, review, refute

Once the builders get the green light, they work on the code until their (new and existing) test suite passes. Afterwards, they invoke a simple code review skill, which spawns a fresh reviewer agent.

Again, the reviewer’s findings then go to a refuter agent whose job is to disprove each one. It is wise to separate concerns: the builder, the reviewer, the refuter being separate agents help them collide against each other, which provides the best results.

The number of reviewers depends on the change: one for a small, mechanical diff; two or three, each with its own lens, for anything that touches auth, data or a new endpoint. Every finding that survives ends one of three ways: fixed (with a failing test first), filed as tech debt, or rejected with the evidence that disproves it. Nothing is left floating.

review-and-refute.mdbuilder skill · trimmed starter, copy and adapt
---
name: review-and-refute
description: Review my diff with fresh reviewers before commit
---
1. Capture the diff and the requirement.
2. Size it. Small and mechanical: 1 reviewer. A new endpoint, a
   migration, an auth or security surface, or a big diff: 2 to 3
   reviewers, one lens each (correctness, security, maintainability).
3. Spawn each reviewer as a FRESH subagent. Give it only the diff, the
   requirement and the review dimensions, never your own reasoning.
   Tell it: "Assume this change is wrong. Report findings with
   file:line and why."
4. A reviewer that must run or change anything works on its own copy
   (a git worktree), never on my working tree. When reviewers return,
   check the tree yourself. Never trust a reviewer's "I restored it".
5. Send the findings to a refuter whose job is to disprove each one.
6. Report HIGH / MEDIUM / LOW with file:line. Fix nothing until I say
   go. Every finding ends fixed (failing test first), filed, or
   rejected with evidence.

Step 4. Walks as final verification

Tests check the code, and walks check what a person sees and what a customer gets.

After reviews, depending on the shape of the task, the orchestrator walks the change utilizing Claude in Chrome on the local machine, on the staging environment, and finally in production to verify everything landed as expected.

A walk means the orchestrator opens the app in Chrome and uses it like a person would. It clicks through every screen the task touches, takes screenshots at phone, tablet and desktop widths, and checks each one against the spec.

Walks also taught me to look at the whole screen, not just the change. When I made our platform work on phones, the new version passed every check, the orchestrator’s walk included. Then I spent ten minutes with it on my own phone and found broken tables: some had lost their name column, and some headers broke one letter per line. Both problems were right there in the orchestrator’s screenshots, but it had judged each one only for the feature it was checking.

Step 5. Outcome review: the product layer

Every layer so far asks if we built the thing right. Only this one asks whether we built the right thing.

Each task has its expected outcome (if any) and when to check for that outcome. When the date comes, the corresponding session shows the review as due and I look. If nothing changed, that is a finding too.

Here is one that is active right now. Our platform users are nursing chiefs and infection control managers in hospital ICUs, the people who check the reports and follow progress. By habit, they don’t sit at a computer much and would rather check in on the go. Fewer check-ins mean slower feedback loops.

So I made the whole platform work on a phone: easier to check in, more often, with tighter feedback loops, and in the end better compliance. I just shipped it. The expected outcome comes in two waves: first, more daily active users over the next four weeks; then, as a second wave, a rise in compliance rates. The orchestrator keeps a reminder so I can evaluate results against expectations.

The learning loop

Every learning leaves a rule. When something goes wrong, if codifiable, it is written down for the subsequent sessions.

The rules do grow, which is also a problem. A rule file that grows without limit stops being followed, which is why rules get pruned whenever a new candidate is there.

If a rule still fails, because an agent follows it one day and not the next, the rule becomes a structure.

Every mistake leaves something behindA rule that still fails becomes structureA mistakecaught by a layer,or by meA rulewritten down withthe story behind itRead at startevery session loadsit before any workStructureif it still fails:script, copy or gatethe same mistake gets harder to repeatEvery mistake leaves something behindA rule that still fails becomes structureA mistakecaught by a layer,or by meA rulewritten down withthe story behind itRead at startevery session loadsit before any workStructureif it still fails:script, copy or gatethe same mistake gets harder to repeat

Most of this workflow runs on instructions: the prompts, the rules, and the skills. Instructions are cheap and flexible, and agents follow them most of the time. And “most of the time” is a problem.

A reviewer agent once deleted a live line of code to test a theory. Then it reported that it had restored everything. It had not. I caught it only because the tool flagged a changed file. So this is why every reviewer works on an isolated copy of the code.

Another example: my agents kept writing long, winding rules and specs (especially during Opus 5 times). No amount of instructions or CLAUDE.md helped. So I moved it into a hook: every rule or spec file an agent writes is checked against Simplified Technical English (STE), and any sentence over 25 words is sent back to be rewritten.

Climb only as high as the cost of being wrongThe higher the level, the less the outcome depends on an agent choosing to complyhigher cost of being wrong5A humanmy scope approval, and the production merge4A gate refusesisolated copies, commit and push hooks, the merge pipelineabove: enforced · below: trusted3A check reportsscripts that run, flag and measure, but do not block2A written ruleloaded at the start of every session1An instruction“restore every file, then check”Climb only as high asthe cost of being wrongThe higher the level, the less the outcome dependson an agent choosing to complyhigher cost of being wrong5A humanmy scope approval, and the production merge4A gate refusesisolated copies, commit and push hooks,the merge pipelineabove: enforced · below: trusted3A check reportsscripts that run, flag and measure,but do not block2A written ruleloaded at the start of every session1An instruction“restore every file, then check”
The ladder · from an instruction to a human

So every rule sits on one of five levels, from a plain instruction up to my own approval. The higher the level, the less the outcome depends on an agent choosing to comply. I pick the level with the same question that ranks the scope review: can we undo it? Wording stays an instruction. Data, production and other people’s work get a gate, or me.

How I got here

I stopped reading code and started reading proofWhat I read at each stage, from founding to todayWriting the codemy own editor,when I founded the companyfew years awayReading every lineCursorReading the codeClaude Codein the editorReading the proofspecs, tests andscreenshots,in the terminalTwo touchpointsthe scope andthe production mergeI stopped reading code andstarted reading proofWhat I read at each stage, from founding to todayTwo touchpointsthe scope andthe production mergeReading the proofspecs, tests andscreenshots,in the terminalReading the codeClaude Codein the editorReading every lineCursorfew years awayWriting the codemy own editor,when I founded the company

I did not design this system in one go:

  1. I first started coding again with Cursor on small internal tools. I was reading every line it wrote.
  2. When Anthropic launched Opus 4.5 last year, I made my move to Claude Code as a VS Code extension. One agent built the frontend pages and another built the backend, each with the plan first and the tests first. I still read the code, and I wasn’t confident to move to terminal. And our platform had working pages for months before an orchestrator existed.
  3. Then I started to copy the builder agents’ plans into a separate Claude chat to cross-check plans as a second opinion. That was the first collision. The chat began to keep a memory and a recap as sessions went. Then I moved these chats to Claude Code with its own repository: a backlog, specs, and skills to start and end sessions. I was its message bus, since I tried direct messaging between sessions, but the efforts then were experimental and carrying messages by hand was simpler.
  4. As the harness and the models became better, and as I was able to arm the guardrails I described, the need to read the code decreased, and I switched to terminal with a tmux setup.
  5. When Anthropic shipped cross-session messaging, with some fine-tuning on the orchestration, I gained confidence to pull myself out of the relaying mechanism and reach the two touch-point mechanism.

This is how much of my time a shipped task costs has changed over time (on average) this year:

My hours per task fell with each workflow changeMy task records · my hours per shipped task, Jan to Oct 2026Jan–MarApr–JunJul–AugSep–Octthe orchestratorgets its own repoagents messageeach other directlyJan–Mar: 13.6 h of my time per task, on averageApr–Jun: 3.2 h of my time per task, on averageJul–Aug: 3.4 h of my time per task, on averageSep–Oct: 0.84 h of my time per task, on averageabout 14 habout 3 hunder 1 hMy hours per task fell witheach workflow changeMy task records · my hours per shipped task,Jan to Oct 2026Jan–MarApr–JunJul–AugSep–Octthe orchestratorgets its own repoagents messageeach other directlyJan–Mar: 13.6 h of my time per task, on averageApr–Jun: 3.2 h of my time per task, on averageJul–Aug: 3.4 h of my time per task, on averageSep–Oct: 0.84 h of my time per task, on averageabout 14 habout 3 hunder 1 h

Trade-offs

None of this comes free. Three costs I pay on purpose:

  1. More belts and braces means a task takes longer from start to finish. Not my time, which went down, but the calendar time. Every layer adds a wait: the scope review, the plan and failing tests stop, fresh reviewers and refuters, three walks, staging before production. That being said, I’d rather ship a day later than ship something a customer finds broken.
  2. By default, I ship tasks one after another, not in parallel. Not because I can’t: I did build parallel lanes with worktrees, and they worked. But I found myself chasing agents and asking what had happened since my last message. Day to day, one at a time suits me anyway. I have plenty of other work as a founder, so I’m never waiting on the agents. I carry on with my day and come back at my touch points.
  3. The machine needs upkeep. The skills, hooks and rule files are a product of their own. Lessons get written down, rules get pruned when they pile up, and a rule that keeps failing becomes structure. That is time not spent on the platform. I budget for it on purpose: about 80% of my time goes into the work, and 20% into improving how the work gets done.

I hope you found this valuable! More to follow.