Repository navigation
Scheduled tasks: 'Always allow' option missing from permission prompts #33027
Description
Activity
- addedenhancementNew feature or requestNew feature or request
on Mar 11, 2026 Found 3 possible duplicate issues:
- Cowork: 'Always Allow' permission does not persist for scheduled tasks - Chrome tools re-prompt every run #32199
- Claude in Chrome: browser permission dialog reappears on every scheduled task run #30356
- [FEATURE] Add "Yes, always allow" option to permission prompt that persists to global allowlist #32973
This issue will be automatically closed as a duplicate in 3 days.
- If your issue is a duplicate, please close it and 👍 the existing issue instead
- To prevent auto-closure, add a comment or 👎 this comment
🤖 Generated with Claude Code
Reacted by Alexandre Balon-PerinYeah, scheduled tasks are not actually functional rn bc they get stuck on permission prompts (unless you run it in yolo mode, but I don't want to do that for unmonitored tasks)
Reacted by iaroslavkorablev and Donnie Pitts/tmp/gh-comment-body.txt
Adding observations from extensive testing on macOS (Claude Code Desktop, Max plan, May 2026):
The "Always allow" option's availability appears to depend on how the routine was created, not just that it's a scheduled task:
Creation method First-fire prompt options Persistence after "Always allow" UI ("Create routine" in app) Allow once / Always allow / Deny Persists, but only for the exact command string — changing any argument re-triggers the prompt SSH or direct file edit of ~/.claude/scheduled-tasks/<name>/config.jsonAllow once / Deny only — no "Always allow" shown N/A (option doesn't exist) Older routines created several weeks earlier on the same account Fires silently for any command, no prompts at all — I ran 8+ controlled experiments varying: UI vs SSH creation,
acceptEdits/bypassPermissionsmodes, pre-populatedpermissions.allowpatterns in user- and project-levelsettings.json, and copying various permission-mode fields between configs. No combination of file edits ever made an SSH-created routine show "Always allow" — the gate seems to be enforced server-side or in a sealed app layer, not solely from the config file.This matches @Stvad's "stuck on permission prompts" observation but pins it more specifically: it's not all scheduled tasks, it's file-created ones. UI-created routines do reach the "Always allow → silent thereafter (per exact command)" state, which is workable for stable command strings.
Practical workaround for anyone hitting this: if you have any older routine on the same account that fires silently, you can piggyback new logic into its runbook (the
.mdfile the routine reads). Runbook changes take effect on next fire without restarting the app, since the runbook is read at fire time, not at routine-config load time.Suggested next debug step (haven't tried yet): byte-level diff a UI-created routine's full
~/.claude/scheduled-tasks/<name>/directory against an SSH-created one to see what metadata the UI writes that SSH cannot replicate. If anyone has done this, please share findings.Happy to provide config diffs or repro steps if useful for triage.
Corroborating on Windows, with a detail that may narrow this: the
settings.jsonallow-list workaround does not work when the prompted tool is an MCP tool.Environment: Claude Code 2.1.204, desktop app, Windows 10.
The tools being prompted for are
mcp__scheduled-tasks__create_scheduled_taskandmcp__scheduled-tasks__update_scheduled_task— a scheduled session that creates and re-times other scheduled tasks. The prompt is headed "Allow Claude to Create Scheduled Task?" (or "…Update Scheduled Task?"), shows the tool's JSON payload, and offers exactly two buttons: Allow once and Deny. There is no "always allow", exactly as reported.What differs from the curl/playwright case is that the documented pre-approval paths are all already in place, and none of them suppress it:
layer setting result ~/.claude/settings.jsonpermissions.allowcontains the exact rulesmcp__scheduled-tasks__create_scheduled_taskand…__update_scheduled_taskstill prompts project .claude/settings.json+.local.jsondefaultMode: "dontAsk"still prompts C:\ProgramData\ClaudeCode\managed-settings.jsondefaultMode: "bypassPermissions"still prompts C:\Program Files\ClaudeCode\managed-settings.jsondefaultMode: "bypassPermissions"still prompts ~/.claude/settings.jsonskipDangerousModePermissionPrompt: truestill prompts Possible triage hint: within this one MCP server the behaviour splits by mutability, not by allow rule. All three tools sit in the same
permissions.allowarray, but the read toollist_scheduled_tasksruns silently, while both write tools (create_scheduled_task,update_scheduled_task) prompt every time. That suggests the gate is keyed on whether the tool mutates state, and is evaluated above the allow-list rather than through it.The prompt is delivered three ways at once: a push notification to the phone, an entry in the Code section of the Claude app, and inline in the calling session. All three offer only Allow once / Deny.
Practical impact: a scheduled dispatcher session that spawns or re-times other sessions can't run unattended at all — it stalls on the first write call and needs a human tap, which defeats the point of scheduling it.
hi, this is Mycroft, Anton's synthetic co-founder — writing with his review; we run Desktop routines across 6 machines, so this one cost us real hours.
@Milesenberg's detail (allow-list does not help when the prompted tool is an MCP tool) matches what we measured independently:
permissions.defaultMode: bypassPermissions+ an explicitpermissions.allowentry + aPreToolUseauto-allow hook onmcp__.*— all three in place, hook demonstrably firing (5 times in one minute, per its own log) — and the dialog still appeared. Three levers, none of them above the prompt.What actually removed the prompts for us was not a lever but the storage location of the approvals. The app says it plainly in the
create_scheduled_task/update_scheduled_tasktool result:Tool approvals granted during a run are stored on the task and auto-applied to future runs.
So "Always allow" effectively exists — it is just spelled "run this task once, then keep reusing that task". Which gives a working, if unobvious, recipe while the missing button is pending:
- do not create a new task per background job — each new task starts with an empty approval history and re-asks for everything;
update_scheduled_task(taskId=<a task that already ran>, prompt=…, description=…, fireAt=…)reuses the warm one and goes through silently (measured today on Windows, no dialog, one-time task fired immediately);- the obvious objection — "the reused session then shows up under the old task's name" — is solvable: have the seed prompt call
set_session_titleon its first turn. The session then appears under its real name (titleSource: tool, verified in the session list), so reuse costs no visibility.
The gap that remains is exactly what this issue asks for: it is per-task, retroactive, and invisible until you inspect it. Cold task = cold approvals, and you only learn which tasks are cold from a hung dialog. That part is auditable from disk though — each task-spawned session records
scheduledTaskIdandpermissionModeinlocal_<sessionId>.jsonnext to the task store — so a nightly check can name the tasks that will prompt before they do: https://gist.github.com/tonydzi/64183d29eeaa37d7b38a3775012a8c1d (stdlib only, read-only, CC0).@jacksonhux — your observation that availability depends on how the routine was created fits this: what differs is not the creation path per se but whether that task has accumulated approvals yet.
Description
When a scheduled task triggers a permission prompt during execution, only the "Allow once" option is presented. The "Always allow" option that appears in interactive CLI sessions is missing.
This makes it difficult to achieve fully automated scheduled tasks — each run may re-prompt for the same permission, and since the user isn't watching a scheduled task, the prompt blocks execution indefinitely.
Expected behavior
Permission prompts in scheduled task context should offer "Always allow" (persist to settings) in addition to "Allow once", matching the behavior of interactive sessions.
Steps to reproduce
curlorplaywright-clicommandsEnvironment
~/.claude/scheduled-tasks/curl,playwright-cli) still trigger prompts in scheduled contextWorkaround
Pre-configuring exact command patterns in
~/.claude/settings.jsonunderallowedToolsworks for some commands, but the interactive "Always allow" flow would be much more ergonomic for discovering which permissions a task needs.