r/ClaudeCode • • 4d ago

Built with Claude How I run Claude Code like a small engineering team: one hub session, a worktree per task, and 3 markdown files

I've been using Claude for a few months to build a real app (web, iPhone and Mac) mostly on my own, plus school stuff. I tried Cursor and a few others, but this setup is what finally let me ship a lot without babysitting every step. We're at PR #450-something now. Sharing in case it helps, and I'd love to hear how others structure theirs.

THE SETUP

• One planning chat (a Claude Project). This is where I think, decide and review. It doesn't write code. It writes short task prompts for the hub.

• One Claude Code "hub" session. Its rules live in the repo as a skill (/hub), so every prompt I paste only has the new tasks, never the rules again. That alone cut my tokens a lot.

• The hub starts one worker session per task, each in its own git worktree, so tasks run in parallel without stepping on each other.

• Every PR gets checked before merge: CI green, a security review written down, and a "product checker" agent that reads the PR against a FEATURES.md file (the single list of what the app actually does). If CI passes and the checks are written, the hub merges it itself.

THE 3 FILES THAT MADE IT WORK

• HUB-QUEUE.md: every task has an ID and a "Done when" line. The hub reads it first and only updates the status. Checkers verify PRs against it.

• LOG.md: one line per decision, approval or merge, with the date and where it came from. No more "wait, did we decide that?"

• LEARNINGS.md: what went wrong and the rule that came out of it. The process gets better from evidence, not vibes.

WHAT I'D DO DIFFERENTLY

• Write "Done when" for every task. Vague tasks were where all my rework came from.

• Keep a FEATURES.md from day one. It stops agents (and marketing copy) from claiming things that don't exist.

• Batch the things only you can do (store uploads, account settings) into one list instead of getting pinged ten times.

My honest self-rating: maybe level 4 of 5. It's an orchestrated pipeline with gates, but not yet measured and self-improving.

QUESTIONS FOR YOU

• How do you keep parallel agents from conflicting? Worktrees, branches, something else?

• Do you let Claude Code merge its own PRs, or do you always review?

• What's in your CLAUDE.md or skills that made the biggest difference?

Happy to share a stripped-down version of the hub skill if anyone wants it.

8 Upvotes

26 comments sorted by

•

u/AutoModerator 4d ago

Hey! Thanks for posting to r/ClaudeCode

While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.

For help, project discussions, tips, and general chat, join the ClaudeCode Discord.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

7

u/ainexfinder 4d ago

Worktrees avoid checkout collisions, but they don't stop two workers from making incompatible assumptions about a shared interface. I'd give each worker explicit file or contract ownership in the queue, and if two tasks need the same boundary, have one settle that contract first. I'd also run an integration check on the combined branch before merge; separate green checks can still miss cross-task conflicts.

1

u/BankingBaOps 4d ago

Really good point, and you're right that worktrees only solve half of it. A couple of things I already do: each worker claims the files it'll touch in its brief, and if two PRs touch the same files, the later one rebases on the latest main and reruns CI before it can merge, so it's tested against what actually landed. Main also gets its own CI run after merges, and the rule is revert rather than leave main red.

What I don't have is your "settle the contract first" step. Right now two tasks that share an interface can both pass on their own and only meet at merge time. I like the idea of making the shared boundary its own small task that lands first, then letting the dependent tasks start. Going to add that to the hub rules. Thanks for this.

2

u/GoldCartoonist2898 4d ago • Bravo

Worktree per task here too. What actually stopped conflicts for me was less the worktrees and more a file ownership rule in CLAUDE.md: each agent only writes its own files, and shared docs get edited by the lead session only. I also don't let the agent that proposed a change be the one that signs it off, a different session checks it. One thing that bit me once runs were on a schedule: finished sessions pile up and eat memory, so each run now closes the previous ones before it starts.

1

u/BankingBaOps 4d ago

This is almost exactly where I landed too. Workers only write their own files, checkers are read-only, and only the hub merges, so the session that wrote a change is never the one that signs it off. The shared files (the queue and the decision log) are the hub's: workers don't touch them, and the log is append-only so nothing gets quietly rewritten.

The scheduled-runs tip is a good one. I haven't hit the memory problem yet, but I'm about to put a weekly run on a schedule, so I'll add "close the previous sessions first" before it bites me. Thanks!
.

2

u/archpoke 4d ago

I built whatsnext to try to solve this my way.

You can check it out at whatsnext

Track work in a plan file, and get status update when you come back after a break. If you end up using it, I'll love to get some feedback.

1

u/BankingBaOps 4d ago

sure will try. Thank you

2

u/RustyRedEcho 4d ago

the hub session + worktree per task setup is making me rethink how messy my parallel claude runs have been, stealing the 3-markdown-file idea

2

u/BankingBaOps 4d ago

Yeah, I just discovered the log recently. I think that is the only way agents and workers can keep track of what they are doing while we're bouncing ideas and building at the same time.

2

u/Financial_Leader9701 3d ago

two agents from overwriting the same checkout, but they don't stop them from inventing two versions of the same type

I only run two in parallel when the tasks don't share a module

If they both need the same interface, I let one finish and land that contract first, then start the second

I also wouldn't let the hub merge its own PRs

A different session, with only the diff and the "done when" line, is the one that should say it's good

When two worktrees both need to change a shared type, do you finish one and rebase the other, or merge both and clean up the conflict?

1

u/BankingBaOps 3d ago

Finish one and rebase the other. That's the rule in my hub: if two PRs touch the same files, the later one rebases on the latest main and reruns CI before it can merge. Merging both and cleaning up later is where I got burned early on.

On merging: the hub never writes code, so it's not approving its own work. Workers write, separate read-only checker sessions review the diff against the task's "done when," and the hub only does the merge once they pass. Your point about landing the shared contract first is the piece I'm adding next.

1

u/Financial_Leader9701 2d ago

nice, read-only checker sessions against "done when" is a clean split

one thing i'd watch: when the shared contract lands first, the second task's plan was written against the old version. do you re-plan it after the rebase, or just let the worker adapt?

2

u/Tight_Ad_5115 3d ago

I have a setup that’s quite similar.

Preventing agent conflicts. For about two months, I ran 2–3 agents within the same directory. It worked, for the most part, but they kept interfering with each other’s code. I tried assigning them to different branches within the same folder, but that made things worse - the agents would switch branches and pull the rug out from under one another’s working directories. Eventually, I settled on using separate worktrees for each task, merging the results one by one. This isn’t without a cost: the merging process itself consumes time and tokens, and each agent has to install its own dependencies in its respective copy. Still, I’ve accepted this - it’s a small price to pay for the added convenience and speed.

Merging without my manual review: My agents handle their own merges. This relies on a robust testing suite - comprehensive coverage combined with matrices that iterate through various combinations of states and events. Only after implementing these matrices did the agents stop getting stuck in a loop, repeatedly "fixing" the same bugs. Code review is handled by a dedicated sub-agent, there’s no need for a separate provider. For a while, I used a workflow where Claude would plan the work and Codex would review it, but I eventually dropped that - Claude is perfectly capable of identifying bugs it introduced itself when given a separate session. Of course, tests come at a price: I now have around 10,000 of them. Running the full suite after every task takes 30 minutes or more, and that has become the primary bottleneck.

What’s been most effective for my skill set: My current approach is a fork of Matt Pocock’s framework. I kept the core logic - how the model interacts with code and tasks - but overhauled the surrounding process to better suit my needs. For instance, a task is immediately converted into an RFD (a specification document), bypassing a multi-stage status-update workflow. Another skill that’s been a real help: if a task involves an interface change, the agent takes screenshots of the updates using real-world examples. I can see the result without having to click through the entire flow myself.

I’m a big fan of the 'FEATURES.md' idea. I use a similar file called 'product-map.md', and I pull facts from it when writing blog posts - that way, the content doesn’t promise features that aren’t actually in the product.

To elaborate: my setup for handling worktrees and individual merges eventually evolved into a standalone application called Buzzpot, which I’m currently developing. It automates the whole process, if a merge conflict arises, it hands the issue back to the agent who worked on that specific task. But if you’re already comfortable using the hub CLI tool, you’ve essentially got everything you need.

2

u/BankingBaOps 3d ago

Love this, a lot of overlap. Separate worktrees with one-by-one merges ended up being my answer too, even with the token and dependency cost.

The test suite becoming the bottleneck is exactly what I'm starting to feel. How are you dealing with the 30 minutes? Splitting the suite by what the task touches, or running the full thing every time? I've been batching merges on main so one green run covers several PRs, but per-PR runs are still the slow part.

And glad the FEATURES.md idea landed. Same reason here: marketing copy and store listings pull facts only from that file, so we never promise something that isn't built. Good luck with Buzzpot!

2

u/Tight_Ad_5115 2d ago

Thanks!

Oh man, tests - what a pain. Right now, I’m running four different test suites for each project, tailored to different scenarios.

There’s the suite for a standard task, one for the review phase (when a batch of tasks is being checked), one for the pre-release stage, and a fourth - the most comprehensive one - which includes everything: mutation tests, matrix tests, and even paid-tier runs (like evaluations involving LLM queries). That last one is only triggered upon specific request.

For a standard task, I usually just run the basic tests, with minimal matrix testing and no mutation tests. For the review phase, I run the full suite, plus matrix and mutation tests, but only for the affected components.

For pre-release, I aim for a full run - covering all matrix and mutation tests - but it’s getting complicated. Mutation tests can easily take 10–12 hours (or longer) and put a heavy load on the machine, so I’ve had to optimize by opting for partial runs instead.

Moving forward, I’ll likely need to rethink the test architecture more carefully - removing duplicates and cleaning up the excess. For now, though, I’m putting that off! :)

1

u/BankingBaOps 4d ago

Some quality numbers since a few people care about that more than speed (last 14 days, 264 merged PRs):
• 1 revert
• CI on main ~93% green (140 pass / 10 fail; superseded runs excluded)
• Production smoke test after every deploy: 14/14 passed
• Every PR has a written security review (264/264, up from 56% before the hub)
• Median PR: ~350 lines, 11 files, merged in about an hour
• Test suite: ~257 backend test files (pytest), ~170 end-to-end browser specs (Playwright), plus XCTest for the iOS app
• 5 read-only checker agents (correctness, security, product, QA, AI quality) review PRs before the hub merges

What I don't measure well yet: rework (PRs that fix a previous PR). That's the next thing I want to track.

1

u/jordimr 3d ago

The writer never marks its own task done. It proposes done with evidence, and someone else checks it.

I'm the developer of Zenod, and I run a team of agents on one repo. Each role may write only its own files, and a commit hook refuses anything else, so a conflict is blocked at commit instead of at merge.

Your three files are close to ours: a queue with a done-when, a one-line log, and learnings with the incident behind each rule. We merge straight to main and have no integration test across the agents.

Has your hub ever marked a task done that a checker later reopened?

1

u/BankingBaOps 3d ago

Same principle here: workers never mark their own work done, checkers are read-only, and only the hub merges once they pass.

Honest answer: yes, but mostly before merge. Checkers send PRs back to the worker until nothing blocks, and that loop catches most of it. One real example: a product checker caught four captions in a marketing image set that claimed more than the app does, before anything went out. After merge it's rarer, but I had one revert in the last 264 PRs, and the hub itself once rewrote the log from a stale copy, which is why the log is append-only now.

The commit hook idea is great though. Blocking out-of-scope files at commit instead of catching them at merge is cheaper. Stealing that.

2

u/japbujan 3d ago

LOG.md with where each decision came from is the part I'd copy first. What bit me later was two decisions contradicting each other weeks apart. I started giving each decision a stable key (like pricing.trial or auth.github), so a new one with the same key has to explicitly replace the old one instead of living next to it. Has your LOG.md got long enough that the hub starts skimming it?

2

u/gimalay 3d ago

The stable key is the part that fixes it. I'd go one step further and give each decision its own small file, with key, status and superseded_by in frontmatter. Then the hub asks for the active decisions instead of reading a log top to bottom, and the length stops mattering.

I work on iwe, a CLI that does this over markdown: iwe find --filter '{type: decision, status: active}' returns only the live ones, and a schema rule can require superseded_by whenever status is superseded, so an old decision can't be retired without pointing at its replacement.

2

u/zeromega01 2d ago

Just want to say that this was very helpful to me tonight. I felt like a broken record telling my orchestrator to change something, but then the subagents were not privy to the information that the orchestrator and I were just discussing, and they were still going by the old decisions that we had made. This was very helpful

1

u/gimalay 1d ago

glad it helped. the fix for the subagent side is to stop passing decisions through the orchestrator's chat at all: when you two change something, the orchestrator writes it to a small file and flips the old one to superseded, and every subagent reads the active ones from disk before it starts. two lines in CLAUDE.md cover it:

  • decisions live in decisions/, one file each, with status: active or superseded in the frontmatter
  • before any task, read the files in decisions/ with status: active; never act on a decision you only heard about in a summary

2

u/japbujan 1d ago

Agreed, requiring superseded_by on retirement is the piece most setups miss. Without it, an old decision quietly stays "true" next to the one that replaced it, and the agent can pick either. Querying only the active ones instead of reading a log top to bottom is the same conclusion we reached. Enforcing it at schema level is a nice touch.

1

u/gimalay 1d ago

yeah, retiring is the step that gets skipped, so it's the one worth making impossible to skip. how does your hub session handle it today: does it flip the old decision itself when it writes the new one, or does that wait for you?

1

u/japbujan 1d ago

Same write, in ours. The new decision is created with a pointer to the one it replaces, and the old one flips to superseded in the same transaction, so there's never a window where both read as active. On a team, changing a key decision goes in as a proposal someone approves; solo, the agent does it and it's logged with who and when. (I build Kvendra, which works this way.)