· 15 min read · By Mehul Prajapati

How I Ran Claude Code Overnight

283 issues and 631 screenshots from an overnight QA run. I used Fable 5.1 to work on the fixes before my Claude Max limits reset.

Claude Codedeveloper workflowAI agentsfaster development

I had two Claude Max accounts on the $200 plan, with two days left before the limits reset. I had just built an app, so I decided to use the remaining limit to test it properly.

The QA run filed 283 issues in ten hours and saved 631 screenshots. I then used Fable 5.1 to work on the fixes overnight. The cloud session's handoff reported 120 issues fixed, with more work left for local sessions.

Here is how I set up the testing, passed the reports to the fixing session and checked what came back.

How did I divide the QA work?

I had a mobile app, an admin panel and an API to check. I split the QA work by area: mobile screens, admin pages, API behaviour, accessibility and complete user journeys. The sweep used up to five subagents at a time.

Each agent needed something more useful than a request to find bugs. The project had screen cards describing the route, data, components, states, test IDs and acceptance criteria. There were 49 cards. These gave the agents something to compare the running app against.

I also had the local services, mobile test environments and a browser available. The task was to open the app, follow a flow and record what happened. For an API issue, the report needed the request and response. For a screen issue, it needed a screenshot or a short video.

I used the same report format across the sweep: screen, platform, severity, steps, expected result, actual result and evidence. That made the next session's job easier. It could read the issue and try the same steps without asking me to explain what the QA agent had seen.

The reports went into GitHub issues. I kept the screenshots and videos on a separate evidence branch in the private repository, with links inside each issue. That also made the evidence available to the fixing session.

What did the QA run find?

The ten-hour run created 283 issues. The evidence folder contains 631 screenshots: 597 PNG files and 34 JPG files. Reproduction videos were saved separately.

Some findings needed a second look before anyone changed code. A screenshot could show a layout problem without proving that a button was unusable. A test tool could also fail to tap something that worked when tested another way.

One review caught exactly that. A report said a clipped control was dead to taps. The visible part still worked; the automated tap had landed outside it. The clipping was real, but the report overstated what was broken.

Design reports needed care too. Some agents had compared the app with an earlier design sketch that had never been approved as the final reference. A difference from that sketch was not enough to justify changing a screen.

I kept the issue count as 283 reports. I did not treat it as 283 separate root causes or assume every proposed fix was necessary. The screenshots and reproduction steps let another session check the report before starting work.

How did I work on the fixes overnight?

I used Claude Fable 5.1 for the overnight fixing work. The cloud session could read the GitHub issues and their evidence while local work continued.

Related issues were grouped together. Each group included the full issue descriptions, screenshot links and the files that session was allowed to change. A fresh agent could start from those records instead of needing the previous agent's whole conversation.

The fixing instruction was to leave a useful comment on each issue: what was wrong, what changed, which commits contained the change, what was tested and what still needed checking. Issues were meant to stay open for verification. The person or session making a change was not supposed to accept its own result.

That rule did not hold everywhere. Some commit messages used GitHub's closing keywords, which closed issues when the branch merged. I needed the merge process to follow the same rule as the prompt.

The cloud handoff reported that it had worked on 163 issues and fixed 120. The merged pull request contained 130 commits. The handoff and PR summary used different fix counts, so 120 is the reported handoff result, not a count I independently proved in that run.

There was still work left. The handoff recorded unfinished groups of issues and explained where the next sessions should continue. That record mattered when the work moved back to local sessions: they could start from the fixes already made instead of building the same changes again.

The fuller cloud environment scripts were never fully deployed and verified. The public versions say that at the top. A setup script is only useful once the app actually starts in that environment.

What happened when I checked the fixes?

I sent fix claims to a separate reviewer with the original issue and the changed code. Its job was to try to disprove the claim. Could it still reproduce the bug? Had the change covered every symptom in the report? Was there a check the fixing session could not run?

One batch confirmed 14 of 34 claims. Another confirmed 19 of 27. Those were results from those batches, not an accuracy score for every Claude Code task.

I wanted the review result written back to the issue. When a fix failed, the next attempt could use the reason it failed. Otherwise a new session could read the same original report and make the same incomplete change.

I also had to check claims about the environment. One local session said no Android emulator was available because it had looked in the usual SDK folder and found nothing. The SDK was installed somewhere else. Once the session used the available emulator, it could test the screen and catch a remaining text-clipping problem.

These checks were part of finishing the work. The overnight run gave me reports and code changes to work through. I still needed to see the affected screen or API behave correctly before calling the issue fixed.

What should Claude read before it starts?

I keep a CLAUDE.md file in the project root. It points to the files that explain how to work on the project. My version contains just these three lines:

CLAUDE.md

@AGENTS.md
@STATE.md
@RULES.md

The @ tells Claude Code to read another file. AGENTS.md holds the project instructions. STATE.md says what was last checked. RULES.md records mistakes I want to avoid. Claude Code supports these file imports.

This gives a new session a starting point. I can ask it to fix a bug without pasting the same project explanation again. I still write the task clearly. The files explain the project; the prompt explains what I need now.

I have put the files at https://github.com/eagerminds-ai/claude-code-harness. The code examples in this post are short extracts from those files or the original project. I removed private details. Some example values are placeholders that you need to replace.

I also kept repeatable tasks in skills. Brief searched for earlier answers; checkpoint saved the active task; the delivery skill covered handoffs; dev-reference listed checks before declaring a tool unavailable. Path-scoped rules under .claude/rules held instructions for the files being edited. Plugins supplied other tools and skills. I explain that setup in more detail in My Claude Code Setup for Faster Development.

How do I let more than one session work at once?

I give each writer a separate git worktree. A worktree is another working folder for the same repository. It lets a session work on its own branch without changing the files another session is editing.

Claude Code supports this through claude --worktree. I also give each session a clear area to work in. This was the mobile package instruction:

apps/mobile/CLAUDE.md

You may only edit files under `apps/mobile/`. Cross-package needs (contracts, db, tokens) are
change requests in `specs/contract-changes.md`, never edits.

In plain English, finish your part and ask for shared changes instead of making them in someone else's files. I still check the diff before accepting the work. The instruction alone cannot stop every unwanted edit.

Separate source folders are only part of the setup. Sessions can still share dependencies, a database or a port. My early setup shared node_modules through links and caused problems. Hard links also share file contents, so they are not safe copies for tools that change those files.

I would install dependencies separately where they can change, give sessions different ports and agree on test data before starting. Shared decision files also need an owner. Two sessions once chose the same decision number even though they used different worktrees.

Which checks should run automatically?

I use hooks for checks tied to an event, such as starting a session or running a tool. That means I do not have to type the same reminder every time.

This is the state-check part of the public settings file:

.claude/settings.json

{
  "hooks": {
    "SessionStart": [{
      "matcher": "startup|resume",
      "hooks": [{
        "type": "command",
        "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/check-state.sh state",
        "timeout": 60
      }]
    }]
  }
}

Copy scripts/check-state.sh and scripts/check-state.py as well. The check uses Bash and Python 3; live GitHub checks need gh. Merge the hook into existing settings so you keep any hooks already there.

SessionStart shows the state check when the session starts or resumes. A failed check here does not stop the whole session. PreToolUse works before a tool call and can deny it. InstructionsLoaded records which instruction files loaded. These events have different jobs. The hook reference explains their behaviour.

The repository also has an AWS region check. A query in the wrong region once returned nothing and was treated as an access problem. The hook checks direct AWS commands, but it does not check every possible shell script. Test the commands you expect it to handle.

How do I stop the same mistake from coming back?

When a mistake repeats, I add it to RULES.md. Each row says what went wrong, how often it happened, what might catch it and what result I should check.

Here is a row from the public version:

RULES.md

| R2 | Green is not done | 13 | `AGENTS.md`; `.github/pull_request_template.md` | Observed behavior and exit code |

The number 13 is the count from my original project. Reset it when you copy the template. Your file should describe your own mistakes.

One example explains this row. Typecheck and 88 unit tests passed while every API route returned a 500 error. The test runner could load imports that failed when the real app ran. Later, lint returned exit code 1 for five days while five pull requests described it as clean.

That changed my completion check. I read the command output and its exit code, then try the affected feature. A message saying everything passed is not enough.

If the same failure can be caught by a script, I would add that check. Writing the instruction again may help, but an automatic check is easier to repeat. Some checks still need a person. The rule file should say that plainly.

What had I tried before this QA run?

Before this QA sweep, I had tried a different overnight setup: a four-lane runner. The 283 QA reports and the cloud fixes described above came from separate runs.

The runner had three builder lanes: API, mobile and admin. A fourth lane reviewed changes and ran checks before merging. A lane was a script with its own worktree, not a person keeping one long chat open all night.

The script picked an issue, started a fresh claude -p session and passed in the task and instructions. Fresh context meant each job had to receive the information it needed. The previous conversation was not its task list.

The original prompt began like this:

tools/autonomy/prompts/_common.md

You are one lane of an autonomous build running unattended overnight. Nobody is watching this
session. There is no human to ask. You get ONE GitHub issue (appended below), a fresh context,
and a worktree already checked out on branch `issue/<n>` from origin/main. Build it, prove it,
commit it. The lane pushes and hands it to a separate reviewer you will never talk to.

That is a historical excerpt. The current public runner has been changed to stop on failures and keep unfinished work for inspection.

GitHub labels showed whether an issue was ready, in progress or waiting for review. Local files recorded lane status and logs. The merge step was shell code after review and command checks. That made the steps visible, but it still depended on the checks being useful.

Why did I stop that runner?

The four-lane runner ran on the night of 2-3 September. Its gate logs contain 26 merges. The builder logs contain 215 completed run records. The mobile lane logged 63 crashes, and I stopped the runner the next morning.

A worktree with unfinished changes caused repeated failures when the script tried to move to the next task. Restarting the process without dealing with that work did not solve the problem. It kept returning to the same failure.

Another bug was in the limit detector. It searched for the text 429 and matched those digits inside a session ID. A completed 130-turn run was treated as a rate-limit failure and sent back to the queue.

That is why I would check the result's actual status instead of searching for a few digits anywhere in the output. A command can finish successfully while the script handling its result makes the wrong decision.

The public adaptation stops a failed lane. It keeps the worktree for inspection and requires explicit setup before live use. I have not run that adaptation against a live application queue. It is a starting point to adapt, not an unattended service I can promise will run all night.

How did I follow the work from my phone?

I used Remote Control to follow local Claude Code sessions. You can start it with /remote-control from a session or use claude --remote-control. The session continues running on your computer.

The earlier four-lane runner's runbook described a separate monitoring session, called the concierge, which checked lane status and brought decisions back to me. It used /loop for repeated checks. The saved records contain decision rounds, but the pasted loop prompt was stored as a hash. I cannot recover its exact wording.

The idea is simple: keep a short view of what finished, what failed and what needs a decision. The phone helps me read that view without sitting at the terminal. It does not make the work independent of my computer or remove the need to answer a real product question.

I would keep those updates short. A useful update names the issue, the problem and the decision needed. A long dump of every tool call makes it harder to notice when a session is stuck.

Why do I keep the starting instructions short?

Claude needs useful information, but it does not need every old discussion before every task. I once loaded the project instructions together with long task, mistake and decision records. Old information still led to wrong answers.

On 8 September, the project records show starting context dropping from 146,463 tokens to about 4,500 after the files were reorganised. Tokens are the pieces of text the model processes. By the later check, the imports had grown back to about 8,100 tokens.

Those are estimates from the project records, not a speed test. The later figure came from file size divided by four. What matters for this setup is the habit: update current notes instead of adding to them forever.

Detailed instructions can sit near the files they concern. Old decisions can stay in a searchable folder. The starting files should help Claude choose its next action without first reading the whole project history.

How would I try this in another project?

I would start with one clearly described issue and one worker. The worker needs the project instructions, its own working folder, a way to start the app and a check for the result.

I would run that job while I am there to watch. Read the output, inspect the files and try the result. If the setup fails on one task, adding more workers only gives me more failures to sort through.

Next, I would try the review step separately. Give it the original issue and the changed code. Make sure it reports missing checks instead of quietly treating them as passed.

Only then would I add more work. Separate jobs that do not depend on each other, and write down which files each worker owns. Keep shared decisions with one owner. Make it clear how a worker reports a blocked task.

My rule for an overnight run: Before adding more agents, make one complete job easy to start, check and recover. More activity is useful only when I can tell what it produced.

The setup is meant to reduce repeated work. I have not measured a 10x speed increase. I would judge it by completed changes, the time spent checking them and the mistakes I still have to fix.

What do the project numbers tell me?

The setup came from an 18-day rebuild with 951 commits, 573 issues and 50 merged pull requests. Four of those pull requests came from Codex branches; the other 46 came from Claude Code. Those numbers describe the work recorded, not a test showing how much faster one person became.

The apps remain on internal testing tracks only. They have not been publicly released, by the client's instruction. The source code, messages and screenshots stay private. The public repository contains the setup files and cleaned examples.

I use the failures in those records to explain why the checks exist. You can copy the approach without copying the whole project or running the same number of agents.

FAQ

Were all 283 issues fixed overnight?

No. The QA run filed 283 reports. The cloud handoff reported 120 issues fixed, and local sessions continued the remaining work and verification.

How did a fixing session know what the QA agent had found?

Each GitHub issue included reproduction steps, the expected and actual result, and links to screenshots or videos. The handoff grouped related issues and listed the files each session could change.

Can I close my laptop and keep a local run going?

Remote Control connects to a session on your computer, so the local process must keep running. The cloud fixing session used a separate environment.

Where can I get the setup files?

The public repository linked below has the instructions, rules, skills, hooks and runner examples. The app code and QA evidence are private. Read the setup instructions and adapt the examples to your project.

Built in the open at github.com/eagerminds-ai/claude-code-harness.

One last thing

Have a product stuck in your head? Let's get it shipped.