Claude Coding at Scale
My workflow for shipping production-level code at scale with Claude Code
15 min read · 3,088 words

For the past six or so months I have been experimenting with how I can Claude Code "at scale"—that is, produce large volumes of production-level code in a short period of time.
I'll go over the finalized workflow first, then I'll dive into the journey that landed me there. After, I'll go over how it fares compared to other methods I've tried.
Prerequisites
- Claude Code
- Superpowers
- Linear (or some other form of ticketing system)
- Gabe's create issues command
- Gabe's ticket command
The Workflow
- Plan it. Create a document detailing the high-level of what you want to achieve, why you want to achieve it, and how you want to achieve it.
- Enhance the plan. Run /brainstorming @[document], follow through with its questions.
- Decompose the plan. Run /create-issues on the resulting plan.
- Run the plan. Parallelize /ticket [issue] on the created issues, have the Claude sessions create PRs when finished.
- Review the output. Review and merge PRs, repeat from step 4 until all done.
Planning it

To have an effective implementation, one must know what they want. It's easy to just tell Claude "implement [feature]. Make no mistakes," but the specifics often get left up to interpretation. Claude might make a new, undesired migration, it might fuck up the services you so carefully built, or it might miss the mark completely on what you wanted.
When I write my PRDs to feed to Claude, I adhere to the following structure: introduction, current state, ideal state, technical details, design considerations, context for the agent.
Unfortunately, all of the PRDs I've written are under NDA, so while I can't show real examples, I'll use a fake scenario of something I've implemented in the past—quick data entry in my day tracking system.
Introduction
A sentence or two about the feature we are building.
We are integrating a system in our day tracker app to save items that the user has typed in before to show in a dropdown so the user doesn't need to re-type something multiple times.
Current State
Where the feature lies right now. Oftentimes I will omit this if the PRD is about a new feature. The current state section is good for giving context to the implementing agent(s) about how things are right now and how things should fit in once complete.
Good to include: current pain points, user story.
Right now, when a user wants to input data into the day tracker, it relies on an <input> tag. Over time, the user will find themselves typing in the same thing over and over into the field. This can get annoying for the user, and is prone to typos messing up the data.
Ideal State
A high-level of what the feature should look like when finished.
Good to include: user story, UI/UX flow.
When a user selects the field, it will open a combobox. The combobox contains every item (called "prefills") that they have inputted in the past for this field. The user also has the option to type something new. When the user does this and saves, the new item they typed will appear as an additional option the next time they select the field.
Technical Details
In this section you will want to include the actual technical implementation of what you want. It's okay to use pseudocode here, the nitty-gritty of the implementation is on Claude, not you.
New table app.prefills
create table app.prefills id uuid pk —generated via uuid repo user uuid not null fk app.users.id field uuid not null fk app.fields.id value text unique not nullGET /structure will also return prefill data.
StructureRepository getStructure() should join on app.prefills where prefills.field any of structures.fields.
Replace <input> on the tracking page w shadcn <Combobox>.
Design Considerations
Having drafted the plan, naturally you will have gone through different ideas on how the goal could've been achieved. Here is where you write what you thought of and why it didn't work.
Originally, I had thought about including the prefills as a text[] on its respective app.fields table. I decided against this as it would be intensive to write and intensive to query/modify a specific prefill.
I want to have it as a combobox instead of a modal/add button to save on space and speed up UX.
Context For the Agent
Any other context that the implementing agent should know.
Our Postgres deploy uses v17. UUID v7 is not natively supported by Postgres v17. Extend the new repository from the custom Uuidv7Repository to handle UUID v7.
ShadCN combobox: https://ui.shadcn.com/docs/components/radix/combobox
Enhancing the plan

Once you have the plan complete, use the Superpowers /brainstorming skill on the written file or Notion document.
The /brainstorming skill will take a rough draft/idea, drill down into the code, deduce technical implementation details, and surface any ambiguities/potential problems with your draft.
Once done, it will spit out a spec file. Read it, review it, then…
Decomposing the plan

…run the /create-issues command on that resulting file.
/create-issues [project] [spec] is a command I created that will decompose a spec file into atomized tickets, fully complete with tagging and blocking. The description of the ticket will contain all the information an agent needs to complete an item, including technical context, exact implementation details, goals and non-goals, and achievement criteria.
Running the plan

Once decomposed, I will go in to the Linear project, find any tickets not being blocked by anything, grab their IDs and run /ticket [id] in new Claude Code instance per ticket.
My /ticket command grabs the Linear ticket, creates a branch and worktree, completes the ticket, then opens a PR. Combined with Superpowers, the agent will automatically use TDD and perform a code review afterwards with a fresh subagent.
As items are atomized and blocking is featured in the Linear tickets, you can spawn multiple Claude Code sessions at once to run any unblocked tickets in parallel. I've been able to run up to five sessions at once for items as they didn't conflict with each other. The /create-issues command made it super easy to tell when conflicts and dependencies would happen.
Reviewing the output

After the PR is opened, it's time to review it. Read through and review the PR as you would with any human implementer. If you notice something wrong, go back to the Claude session and give the agent your comments. It will fix them then update the PR.
After the PR is finalized and looks good to you, merge it! Linear will mark the ticket as completed, more tickets will unblock, and you can repeat from the previous step until all tickets are unblocked and completed.
Voilà! Your work is complete.
Guardrails

To best perform, Claude is going to need some guardrails. These are language-dependent. I do most of my work in Typescript, so I will share the workflow I use for that. I don't know what the alternatives for other languages are, but I imagine they're similar.
ESLint, ESLint, ESLint
This is the best defense against slop code. Forcing Claude to adhere to a set of pre-defined rules so it doesn't spew absolute bullshit.
Most of my rules are from ESLint Unicorn on the recommended setting. Per-project, I will disable some of the rules here and there where I see fit. This specific plugin is great as they have detailed rationale behind each individual rule and detailed examples of each, so you can decide if the rule is worth including in your code.
I also have rules to keep files under 500 lines and functions under 75 lines. These are arbitrarily chosen values. The purpose of these is to keep files small and functions tight—as compact and atomized as possible. This makes it a lot easier for agents to work on issues and due to a debloated context, less likely to introduce adverse changes.
I am a stickler about casing and type safety, so I've got rules for those as well. Everything must be typed, no any outside of places where it may genuinely be needed, and undefined instead of null (rationale here). My casing rules (for TS)1 are as follows:
- Files are kebab-case
- Functions and variables are camelCase
- Types, interfaces, and React components are PascalCase
Prettier
I have Prettier run on every single file. This helps keep the formatting consistent for when a human does eventually have to go in and read/modify what the agent has written.
Precommit hooks
I run ESLint and Prettier via Husky as a precommit hook. If ESLint fails, then the commit fails, and Claude has to fix the issue before commit. This ensures that every single commit adheres to the quality and standards set before.
Regular Code Reviews

Every week or two I'll spin up a Codex agent in OpenCode (important) and have it review the codebase for any inefficiencies or improvements.
Deep-dive this codebase for any inefficiencies, architectural issues, code quality issues, abstraction opportunities, and anything else that can be improved. Use as many sub-agents as you would like. At the end, present me the list of surfaced issues, proposed solutions, and rationale behind them.
I ship a lot of code. I do my best to review every single line and pick out every single thing wrong that I can see, but at scale, as humans do, we tend to miss things that build up over time. By running code review every week or two, I can ensure that code stays clean and efficient.
By providing the rationale behind each issue, I can tell if it is actually an issue that needs to be solved or not. An example being: in my primary codebase at work, there exists a race condition that causes issues in a multi-instance setup. The solution requires a fair bit of logic change and migrations to two DB tables. However, the codebase only runs in a single-instance setup, so this race condition will never occur and can be safely ignored.
It is imperative that you do these code reviews with an agent other than your primary coding agent. The model weights behind different providers will be sensitive to different biases, Claude code review may not catch what Claude writes, but Codex will (and vice-versa).
CLAUDE.MD
The last part of this is my CLAUDE.MD file.
For each proposed change, examine the existing system and redesign it into the most elegant solution that would have emerged if the change had been a foundational assumption from the start.
Do not suppress errors, exceptions, or warnings. Do not ignore them. Fix them properly.
Always address me by "Spingle". Every message you send should contain my name at the end of the message.The first two parts are simple and self-explanatory. The third part's rationale is as follows—if Claude doesn't call me "Spingle", I know it is ignoring its CLAUDE.MD, and I know that it is ignoring my instructions about code quality (or anything else in my local CLAUDE.MD files).
How I got to this flow

Originally, the plan and enhance step were a single plan step. I had a Claude Code /spec-interview command which would take a few sentences of a rough idea, drill down into the code, and ask about 50–100 questions of technical implementation details. It was really in-depth and produced some really great features, but fuck did it take forever to get through its interrogation.
I eventually decided that it was easier to use the Superpowers /brainstorm command on a slightly more detailed spec file.
Originally everything was done within an MD file but I switched to using Notion as I found it easier to work with. I hooked up my Notion MCP to Claude Code so that I could give it a link to the Notion document and Claude would be able to read it.
The structure of the document evolved over time. Originally it was just a description of what I wanted to achieve. I later found that giving it specific technical details alleviated issues of me having to go and guide the agent in-flight towards my intended solution. Providing it with my design considerations also keeps the agent from going off the rails. Occasionally, without it, the agent would steer towards an implementation that I had deemed unworthy.
Originally decomposing the issues was not done within Linear. I had a custom /decompose-spec command which would go and decompose them into individual atomized .MD files, still complete with blocking and with parallelization. I decided to switch to Linear because that's what my job uses and I frankly found it easier to manage en masse.
It is still possible to use the /decompose-spec command and to manage tickets via files but that's up to you if you want to deal with the complexity.
For running the plans I had originally run multiple Claude Code instances in parallel, pointing them each to a work plan file. Having all of them running on the same branch got very hectic as oftentimes they would overwrite each other's code, and it was hard to review what each individual agent had done.
I switched to using work trees and branches for these parallelized instances. It was much easier to keep track of what was done by what agent. If I needed to roll something back because an agent fucked up their ticket, it was easy to do that in isolation.
The ticket command was created because I was too lazy to type every single time "Hey, work on this Linear ticket, create a branch and worktree, then create a PR and tear down the worktree when done." A good developer is a lazy developer.
I eventually got tired of having to manually split up files and functions that were too big, as well as steering Claude away from producing inefficient code. I decided to invest the time in researching and learning ESLint, and I found a plugin that I really liked and that seemed to produce good code.
I decided to throw these on Husky pre-commit hooks so that agents didn't push slop to my repo, and so that I didn't have to perform (as) regular codebase clean-ups.
How it compares to other methods

I will define three alternative workflows here to compare.
The beginner/guided Claude Code workflow is:
- You get an idea
- You open up Claude Code
- You guide it, prompt by prompt, towards the end goal
This one is the one that most people starting out with agentic coding use. Arguably, it gives you the finest control over the output. Every single change it makes is reviewed by a human, and it's easy to steer Claude in the intended direction.
The one-shot workflow is:
- You get an idea
- You open up plan mode on Claude and hash out the idea
- You let Claude rip at it until its done
- You review the code and clean up afterwards
Once one becomes comfortable with the guided workflow, one starts one-shotting implementations. You provide Claude with the context and goals upfront and Claude, in the same session, will work on it till the end. Afterwards, you can review it (or not) and merge the code.
The agent orchestrator workflow is:
- You get an idea
- You open up a planning agent
- You talk back and forth with the planning agent to develop a plan
- Once finished, the planning agent will delegate it to implementing agents to complete
- Depending on the setup, code review agents will review code before continuing to the next agent
Eventually, one will realize the one-shot workflow produces too much slop and it's tedious to go back and fix all the mistakes it made during implementation. The user will learn about Cline or Roo Code or the million other agent orchestrators2 and begin to use those to implement their code. Having specialized agents means each part of the workflow can be prompted to perform its specialized duty in the most efficient way.
Gabe's workflow (name TBD) takes it a step further where:
- You get an idea
- You plan it out with a planning agent
- You decompose it into real actionable tickets
- You manually open up an orchestrator (if using Superpowers) or an agent (if using regular Claude Code) and have it complete the task
- You do this in parallel
- You review the code yourself before merging
- You manually open up more orchestrators or agents and continue the cycle until all work is done
In terms of speed, I'd say it's a tie between the orchestrator workflow and Gabe's workflow. The guided workflow requires human-in-the-loop every step of the way, while the one-shot workflow can be the fastest, but its slop/correction potential is high enough that it pushes up the average time to completion. The agentic workflow and Gabe's workflow both tie here, as depending on the implementation either the agentic or Gabe's workflow will be able to parallelize work better. The review time is a factor here, as with the agentic workflow, reviewing at the end may reveal the agents went off the rails early, causing a bunch of redo.
In terms of quality, it's a tie between the guided workflow and Gabe's workflow. With guided, you review on every single change, so you can pick out exactly when something goes wrong and correct it. With Gabe's workflow, you correct on atomized PRs. Slightly up the chain, but still isolated enough to where mistakes won't build off each other. With the agentic workflow, code review agents may take the place of this, but having agents review code opens the door to inefficiencies in the model weights leaking through. The one-shot route has mistakes building off each other, opening the door to slopfest.
In terms of ease of use, the one-shot way is the simplest. By far. It is set and forget. Gabe's workflow requires a lot of manual orchestration that the agentic workflow takes care of (at the cost of potential quality), and the guided workflow requires the most orchestration of them all.
Ultimately, (obviously), I prefer my method the most. It gives me the best blend of speed and quality to produce production-ready code.
Conclusion
We are still very early on in the realm of mass agentic coding. As models get smarter, they become more capable of producing production-level code on their own, but in the meantime we must create systems and guardrails to make this process as efficient as possible.
I hope this writeup helped in creating your own system (or copying mine) and speeding up your development time.
In the future, I plan on working on a PR review agent to handle the code quality issues that ESLint cannot.
As much as I adore and prefer snake_case, the majority of the JS ecosystem contributors have landed on the vastly inferior camelCase as the default style of typing. I've found it easier to adhere to the conventions than be a stylistic leader in this regard, especially when working in a team environment.