[BUG] CronCreate: lacks predicate-gated execution and context isolation, leading to large unintended costs on repeated trivial checks
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [ ] I am using the latest version of Claude Code
What's Wrong?
CronCreate fires its prompt as a regular turn in the current Claude session. Every fire re-loads the full session context — system prompt, all in-scope CLAUDE.md files, and the entire prior conversation transcript — regardless of how trivial the prompt is. For a repeated low-information check (e.g., "is this directory empty?"), the dominant cost per fire is not the work itself but the conversation history that must be re-read by the model, which itself grows with every fire that gets appended to it. The cost-per-fire is roughly quadratic in the number of fires over a session's life, even when every fire is a no-op.
The tool's docstring frames CronCreate as a lightweight scheduling primitive and uses /5 * (every 5 min) as its first example, with no mention of this cost structure. The framing is misleading: "session-only" + "every 5 min" reads as cheap; in practice it is the most expensive combination possible.
What Should Happen?
wo improvements would fix this:
- Predicate-gated execution — an optional condition field the scheduler evaluates (without invoking the model) before deciding whether to enqueue the prompt. Only when the predicate is true does the model get called.
CronCreate(
cron="/5 *",
condition="ls agent_inbox/ | grep -v '^archive$\\|^README.md$' | grep -q .",
prompt="New files in agent_inbox/. Read them and propose handling.",
)
Predicate types worth supporting: shell command (exit 0 = true), file-existence / file-mtime tests, HTTP webhook, inotify-style filesystem event.
- Context isolation — an isolated_context: bool flag. When true, the prompt fires in a fresh sub-context (system prompt + cron prompt only, not the parent session's accumulated history). This is exactly the pattern the Agent tool already uses. A sensible default for recurring=True cron jobs would be isolated_context=True.
Until predicate-gating and isolation exist, the docstring should at minimum warn:
"Each fire is a full Claude turn that re-loads the host session's context. For frequently-firing repeated checks (every few minutes), strongly prefer OS-level cron / inotify / shell scripts; CronCreate's recurring mode is best suited to less-frequent (hourly or coarser) substantive tasks where the host session's context is genuinely needed."
Error Messages/Logs
No error or exception — the tool works as implemented. The problem is the cost structure and the absence of a warning about it. Observed figures from a real session:
Configuration: cron="7,18,29,40,51 * * * *" (every ~11 min), recurring=True, durable=False
~88 fires over ~16 hours of an active session, each producing a single-line "inbox empty" response
New work output per fire: one ls tool call + ~30 output tokens
Input cost per fire grew with each fire because every prior fire's prompt-and-response was appended to the session history
The 88 turns of no-signal output dominated the session's token cost and made context compaction fire repeatedly
Steps to Reproduce
Open a Claude Code session that is already doing substantive work (so the context is non-trivial).
Create a recurring cron to poll an empty directory:
CronCreate(
cron="7,18,29,40,51 ",
prompt="Run ls agent_inbox/. If empty, respond 'inbox empty'. Otherwise list files.",
recurring=True,
durable=False,
)
Leave the session running for several hours while doing other work in the same session.
Observe:
Each cron fire appends a full prompt+response turn to the session history.
Input token count per fire increases with each successive fire.
After ~20–30 fires the session history is dominated by repetitive "inbox empty" turns.
Context compaction begins triggering even though the substantive conversation hasn't grown that much.
Compare with a shell watcher that uses inotifywait or a polling script with an early-exit: the shell approach pays zero model cost on negative checks.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.116
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗