DEV Community

Cover image for Why Claude Code Stops Halfway Through Long Tasks—and the Harness I Built to Keep It Moving
Orwa Mahmoud
Orwa Mahmoud

Posted on Edited on

Why Claude Code Stops Halfway Through Long Tasks—and the Harness I Built to Keep It Moving

I kept giving Claude Code long task lists, stepping away, and coming back to find it had completed the easy parts and stopped before the difficult ones.

Sometimes it was worse.

Claude would work until 2 AM, ask one non-critical question, and then sit idle for six hours until I woke up at 8.

The question was usually reasonable, but it was not truly blocking. Claude could have chosen a safe default, continued working, and left the decision for me to review later.

That is a harness problem, not only a model problem. The layer around the agent loop decides what “done” means, when the run may stop, and what happens when human input is unavailable.

That problem led me to create Nightshift, an open-source reliability harness plugin for long unattended Claude Code sessions.


Update (v0.6, July 2026): the night the API died

Since publishing this, the other overnight killer got its fix. Claude had elevated errors across multiple models one evening — API Error: 500, 529 Overloaded — right as I was about to start an overnight run. That is the failure no prompt can fix: once a session dies on an API error, nothing inside it can restart it. And I was not going to sit up watching status.claude.com.

nightshift now ships a night watchman — a small process outside the session that wakes every 10 minutes and reads only the session's own signals: its transcript, its recorded process, Claude Code's session roster. A session that died — or one wedged with an API error as the transcript's last word — gets claude --resume fired into the same conversation, and the watchman keeps knocking until the API answers. Esc or Ctrl-C always wins: it revives the endings nobody chose, never the ones you did. In the morning the whole night is one thread — the error, the revival, the finished work — with a direct link back to it.

Full details: orwamahmoud.com/nightshift · repo: github.com/orwa-mahmoud/claude-nightshift


Keeping the task outside the conversation

Nightshift uses a persistent Markdown punch list as the source of truth.

# Nightshift Punch List

- [ ] Add rate limiting
- [ ] Add tests for failed login attempts
- [ ] Update the API documentation
- [ ] Run the full test suite
Enter fullscreen mode Exit fullscreen mode

Claude works through the list one item at a time.

Because the work is stored in a file rather than only inside the current context window, the session can recover after context compaction, interruption, or restart.

Preventing quiet early exits

Nightshift includes a stop hook that checks the punch list whenever Claude tries to finish.

If unchecked items remain, the normal stop is blocked and Claude is instructed to continue.

The shift ends only when:

  • every item is completed
  • the deadline is reached
  • an optional stall limit is reached
  • or the owner explicitly stops it

If no stall limit is configured, stalled work stays held and visibly flagged rather than quietly clocking out.

This is stronger than simply prompting Claude to “continue until finished” because the completion condition is checked against persistent state.

Non-blocking questions should not stop the night

Most human-in-the-loop systems pause the agent whenever it has a question.

That makes sense for destructive or high-risk decisions. It does not make sense for every naming choice, implementation preference, or reversible decision.

During a Nightshift session, non-blocking questions are parked with the default Claude chose.

## Parking Lot

- Question: Should the endpoint return 200 or 201?
- Default used: 201, matching the existing creation endpoints.
- Review later: Confirm API consistency.
Enter fullscreen mode Exit fullscreen mode

Claude continues working, and the developer reviews those decisions in the morning.

The goal is not to remove human oversight. It is to make some of that oversight asynchronous instead of forcing the whole session to wait.

Guardrails for unattended work

Long-running autonomy needs clear boundaries.

Nightshift can mechanically enforce restrictions such as:

  • blocking git push
  • denying dangerous commands
  • protecting selected directories
  • checking diffs for secret-like content
  • enforcing a specific Git identity
  • preventing non-blocking questions from pausing the shift

A prompt saying “do not push” is helpful.

A hook that rejects git push is stronger.

These guardrails are not a security sandbox, but they reduce the risk of relying only on the model to remember every instruction.

Verification before completion

A checked box is still a claim made by the agent.

Nightshift cannot guarantee that the implementation is correct or replace code review. What it can do is enforce a more disciplined workflow:

  1. implement the change
  2. run the relevant verification
  3. inspect the result
  4. commit the completed item
  5. mark the checkbox complete

Verification can include commands such as:

npm test
npm run lint
npm run typecheck
Enter fullscreen mode Exit fullscreen mode

Nightshift also encourages one commit per completed item, making the run easier to inspect or partially revert.

Resumability and receipts

Nightshift stores operational state inside .nightshift/, including punch lists, parked questions, logs, deadlines, stop signals, and completion snapshots.

This state can have its own local Git history, separate from the main project repository.

That gives the developer two different records:

  • project commits showing what changed
  • Nightshift receipts showing what happened during the run

If the session is interrupted, a new session can inspect the same state and continue from the remaining work.

What Nightshift does not solve

Nightshift does not eliminate hallucinations.

It does not guarantee that:

  • every completed item is actually correct
  • tests cover every requirement
  • every chosen default is good
  • every unsafe command will be detected
  • a poorly written task list will produce a good result

It adds persistence, constraints, verification habits, resumability, and visibility around Claude Code.

Human review is still required.

Installation

Inside Claude Code:

/plugin marketplace add orwa-mahmoud/claude-nightshift
/plugin install nightshift
Enter fullscreen mode Exit fullscreen mode

Then initialize it inside your project:

/nightshift:setup
Enter fullscreen mode Exit fullscreen mode

Review the generated punch list and start the shift:

/nightshift:start
Enter fullscreen mode Exit fullscreen mode

Overview and FAQ:

https://orwamahmoud.com/nightshift/

Nightshift is free, open source, and MIT licensed.

Contributions, issues, and feedback are welcome:

https://github.com/orwa-mahmoud/claude-nightshift

Top comments (5)

Collapse
 
alexshev profile image
Alex Shev

Long-task harnesses are going to matter more as agents move from demos to real maintenance work. The key detail for me is not only keeping the agent moving, but preserving enough state that a resumed run knows what was already verified and what is still uncertain.

Collapse
 
orwamahmoud profile image
Orwa Mahmoud

that is one of the main reasons Nightshift keeps its state in files rather than only in the conversation. Completed and open work stays in the punch list, each item can define its own verification requirements, and unresolved decisions are preserved in a parking lot with the default that was taken. The instructions and gates are plain Markdown, so teams can make the retained evidence as lightweight or strict as they need.

Collapse
 
alexshev profile image
Alex Shev

File-backed state is underrated for exactly that reason. Conversation memory is convenient, but a punch list, parking lot, and verification notes give the next run something inspectable to resume from. Plain Markdown is a good choice because teams can actually review it.

Collapse
 
zira125 profile image
Zira

The persistent punch list is useful, but I would make progress monotonic rather than treating a checked box as completion. For each item, record the base commit, files changed, verification command and result, then require the next session to re-check that receipt before continuing. That turns compaction or restart recovery into a replayable state transition, and it also makes a stalled run distinguishable from a task that was marked done without evidence.

Collapse
 
orwamahmoud profile image
Orwa Mahmoud

That’s close to the current contract: the skill requires each item to pass its gate, get its own commit, and only then be checked. The state is persisted, but that sequence is still prompt-enforced.

What you’re proposing is a stronger mechanical layer: recording the base commit, changed files, verification command/result, then replaying that receipt on resume. That could be a useful optional strict mode. Feel free to check the code—contributions or a PR exploring it would be very welcome.