Today while going through a discussion on Claude, I got to know that Claude now has another cool feature called /loop. I have been playing with it for a few hours now and I already love it.

But there is one thing I think is it’s biggest hidden limitation. Let’s try to have a deeper look into it.

When I read about the Claude Code /loop first, I got an interesting idea from it’s documentation. I thought I was being clever.

I have a deploy pipeline that usually takes fifteen minutes. Instead of refreshing the dashboard every minute, I asked Claude to watch it.

So I ran:

/loop 5m check if the deployment finished

Claude confirmed the schedule and I could see that the job was created with five-minute interval.

It looked perfect to me. I was very excited already. Then I moved on to something else.

I was using Claude Code to review a diff in the same session. I asked Claude to explain a stack trace. It was just a normal workflow.

Then I noticed that the deploy finished. But, Claude said nothing even after ten minutes passed.

At that point I stopped thinking about the deploy and started wondering if the scheduler had silently died. Because the entire point of the loop was simple: check every five minutes.

And the deployment had clearly finished during that window.

The first thing I checked

The first thing in my mind was about the interval I had set. I had learnt before that the Cron syntax is notorious for weird rounding rules. Especially when shorthand units get converted to cron expressions.

So I assumed /loop 5m might not actually mean five minutes and maybe it got rounded, or maybe it converted strangely.

The next thing I did was getting a list of tasks and checking for the schedule. Everything looked correct and I could see there was five-minute cadence.

Next theory I had was about expiration. Claude Code scheduled tasks expire automatically after three days. But this job was only a few minutes old. So that wasn’t it either.

Then I thought maybe the scheduler had probably fired. But the prompt never ran.

Now I started to search about: “Why didn’t the scheduled prompt execute?”

The mental model that caused the confusion

Funny thing is that I learnt that my guesses were all wrong. I thought the scheduler behaved like cron.

Cron means a job fires exactly when the clock says it should. 10:05 means 10:05.

If the interval is five minutes, the system runs the task every five minutes. Even if other things are happening on the machine.

But Claude Code’s scheduler doesn’t work that way. It can’t interrupt itself and that is something that made everything different for me.

What the scheduler actually does

Claude’s scheduler checks every second for tasks that are due. When a task becomes due, the scheduler queues it. But the prompt only executes between conversation turns and not during them.

It means if Claude is already generating a response when the scheduled time arrives, the task waits. The scheduler is technically correct. The timing just slides because of this concept.

That means a five-minute loop might run like this:

10:00  scheduled
10:05  due → Claude busy → queued
10:07  Claude finishes response → task runs
10:10  next due

Nothing is broken. The execution simply waits for Claude to become idle.

A scheduled Claude task doesn’t run on time. It runs when Claude is free.

Why that explains the timing mismatch with Claude scheduler

When my deployment finished, I was asking Claude something else and it was a long prompt. The scheduler noticed the task was due and it queued the job.

But Claude was still generating the previous response. So the scheduled check waited.

By the time Claude finished the conversation turn, the deploy had already been complete for several minutes. The job still ran but after the time I expected.

And because I stopped watching, I never saw the result.

Why the docs make this easy to miss

The documentation does mention this behavior. But it’s easy to skim past the implication.

The scheduler description says tasks run between conversation turns. That sounds like a harmless implementation detail. But it actually changes the mental model completely.

Because it means /loop behaves like a cooperative scheduler and not a real-time timer. It always defer work if the worker is busy.

You could see similar things in systems like: event loops, queue workers as well. Claude’s scheduler follows the same pattern.

What happens if Claude is busy for a long time

There’s another subtle consequence which I can think of is the missed intervals don’t stack.

If Claude is busy for fifteen minutes and your loop runs every five minutes, you don’t get three executions afterward, actually you get one. The scheduler only queues one task instance. Which makes the system behave even more like a queue.

At first I treated the delay like a bug just like a normal debugging instinct. If a scheduled job doesn’t run on time, something must be broken. But the scheduler wasn’t failing. The system was behaving exactly the way a cooperative queue should behave.

The question I still don’t know the answer to

What I don’t know yet is how this behaves under heavy usage.

For example:

If several tasks become due while Claude is busy, how aggressively does the queue coalesce them? Does it drop duplicates? Does it delay them all equally?

Right now I treat the scheduler as best-effort timing, not precise timing and that assumption has held up so far.

What I do differently now

I still use /loop but now I think of it a little differently. If timing precision matters, I run the automation outside Claude using real cron. But if I’m using /loop, I assume the check might run slightly later than scheduled.

Learning this concept solves a lot of confusion. Because once you see the scheduler as a queue slot instead of a timer, the behavior stops looking strange and it becomes predictable.

Runnable takeaway

If a scheduled task appears late, check whether Claude was already generating a response when the scheduled time arrived. One quick way to observe this behavior is to run a loop and intentionally trigger a long response.

/loop 1m echo "scheduler check"

Then ask Claude a prompt that produces a long explanation. Watch when the loop message appears.

If Claude is still generating a response when the minute passes, the scheduled task will wait. It will only execute after Claude finishes.

That delay is the expected behavior. Not a bug.