Desktop scheduled tasks: model selection broken end-to-end (spawns ignore user settings; documented picker absent; MCP tool lacks model param)
Bug report: Desktop scheduled tasks — model selection broken end-to-end
Environment: Claude Desktop (macOS) 1.24012.9, claude-code CLI 2.1.219+, macOS Darwin 25.5.0.
Two desktop profiles under one account, each with its own scheduled-task registry.
Summary
There is currently no working way to control which model a desktop scheduled task runs on, and scheduled-task spawns only sometimes honor user settings.
Three independent defects compound:
1. Scheduled-task spawns ignore user settings on most runs (primary bug)
User settings: "model": "best", "effortLevel": "xhigh", "fallbackModel": ["claude-opus-5"], no env overrides, no managed settings.
Across 148 scheduler-spawned sessions (Jun 3 – Sep 3) the session records show exactly two spawn profiles:
- Profile A (116 sessions): stamps the newest Opus
[1m]model, noeffortkey, nosessionSettings. Ignores user settings entirely. Never once produced Fable 5 (consistent with nofable[1m]variant existing). - Profile B (32 sessions): inherits user settings and the app's live ultracode state (
sessionSettings: {"ultracode": true},effort: "xhigh", model resolving per thebestalias →claude-fable-5). Every observed Fable run is Profile B.
Which profile a run gets flips per run, not per task — e.g. on 2026-09-03 the 07:53 task spawned Profile B (claude-fable-5, ultracode) and the 08:24 task spawned Profile A (claude-opus-5[1m]), same build, same profile, 31 minutes apart.
Selection is recorded nowhere (task store, session records, settings) and matches no documented behavior.
2. The documented Edit-form model picker is absent
desktop-scheduled-tasks docs: "The instructions input includes pickers for the permission mode and model."
In build 1.24012.9 the Edit form shows no model picker. No changelog entry indicates when this feature shipped or its gating.
3. The documented "ask Claude" fallback cannot work
Same docs say the task model can be changed "through the Edit form or ask Claude."
The update_scheduled_task / create_scheduled_task MCP tools accept onlytaskId, prompt, description, cronExpression, fireAt, enabled, notifyOnCompletion — no model parameter (schema re-fetched 2026-08-03, 2026-08-21, 2026-09-03; unchanged).
The task store (claude-code-sessions/<account>/<profile>/scheduled-tasks.json) carries no model-like key on any of 20 task entries across both profiles.
Impact
Users who need a specific model on unattended scheduled runs (e.g. Fable 5 with Opus fallback) cannot get it deterministically:
~78% of runs draw Profile A and silently execute on a model the user did not choose, at default effort, with ultracode orchestration silently absent.
Headless runs surface no notice of any of this.
Requests
- Make all scheduled-task spawns resolve model/effort from user settings (or document why Profile A exists and how to disable it).
- Ship the per-task model picker the docs already describe, or correct the docs.
- Add
model(and ideallyeffort) parameters toupdate_scheduled_task/create_scheduled_taskso the documented "ask Claude" path works.
Evidence available on request
Full session-record analysis (148 spawns with timestamps/models/effort/sessionSettings), task-store dumps from both profiles, settings history with backups.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Root cause located in the desktop bundle + a working workaround (Windows, Desktop 1.46388.1 / CLI 2.1.260)
I can confirm all three defects on Windows 11 and add two findings that may help triage:
1. Why the picked model is never persisted. In
resources/app.asarthe model resolver has an early return for exactly the two scheduled-task actions:The create/update paths assign
model: i ? i(t.model, "scheduled_task_create") : t.model, so the value becomesundefinedand the store never gets amodelfield (0 of 36 tasks here). The same code is present in the staged 1.46388.2.2. Why runs ignore user settings ("Profile A"). Observed process command line of a scheduled-task session (
Get-CimInstance Win32_Process):The app passes the literal alias
default. The CLI resolvesdefaultby account type (Max → Opus) and--modeloverrides themodelsetting, so"model": "sonnet"in settings.json can never apply. The warm-session path normalizes"default"to "no flag" (d = l.push === "default" ? void 0 : l.push), which is when settings.json does apply — that matches the per-run flip between Profile A and B.3. Workaround that works (measured). Because
defaultis documented as overridable byANTHROPIC_DEFAULT_MODEL, putting it into the settingsenvblock redirects every--model defaultlaunch:| launch | modelUsage |
|---|---|
|
claude -p … --model default| claude-opus-5[1m] || same, settings
{"env":{"ANTHROPIC_DEFAULT_MODEL":"claude-sonnet-5"}}| claude-sonnet-5 ||
ANTHROPIC_MODEL=claude-sonnet-5+--model default| claude-opus-5[1m] (flag wins, as documented) |Over 48 scheduled runs (02–04 Sep) before the workaround, 100 % had Opus in the top-level session despite
"model": "sonnet". Verified on a real scheduled run today (04 Sep, "Run now" on a task): the app still spawned--model default, and the first assistant message ran onclaude-sonnet-5.A fix on the app side would be to stop discarding the model for
scheduled_task_create/updateand to pass the resolved model (or nothing) instead of the literaldefaultwhen a task has no model. Happy to share the full measurement scripts.Repro/measurement scripts (as promised above): https://gist.github.com/Suchspezi/52aa1a2a3e53aed4265b96086846ac36
Both are read-only, scan
~/.claude/projects/*/*.jsonl, no dependencies.modell-audit.jsgives the per-day model/switch breakdown;cron-subagent-audit.jsgives the top-level-vs-subagent token split used in the numbers above.Confirming on macOS 26.5.1 (arm64), Claude Code CLI 2.1.92, Desktop app, consistent with the early-return finding above.
Symptom: the per-routine model picker shows
Sonnet 5. Setting it to Opus 5 does not stick — it is back onSonnet 5on the next look, matchingCl()returning early forscheduled_task_create/scheduled_task_update.User settings are ignored too:
Both scheduled tasks still run on Sonnet 5.
Supporting detail: neither task's
SKILL.mdfrontmatter contains amodel:key at all — onlyname:anddescription:. Consistent with the selection never being written anywhere, rather than being written and then overridden at spawn time.Why this matters beyond model choice: these two routines perform unattended production server maintenance (security updates, service restarts, reboot decisions on a live e-commerce VPS). Silently running them on a different model than the one deliberately configured is a correctness concern, not just a cost or preference one — and there is currently no way to tell from the UI that the selection was discarded.
Workaround for anyone hitting this: write the task prompt so it does not depend on model strength — spell out every non-obvious decision explicitly rather than leaving it to judgement.