[FEATURE] Model selection when spawning a background task chip

Status Open
Maintainer reply None cached
Activity 5 comments · opened Jun 24, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

When a background task chip (the mcp__ccd_session__spawn_task suggestion) is accepted and spun off into its own local session + worktree in the Claude Code desktop app, there is no way to choose which model the new session runs on. It silently inherits the configured default (the settings model field, else the plan default).

This is a problem because spawned task sessions are frequently a different kind of work than the parent session that flagged them:

  • A quick mechanical cleanup flagged mid-Opus-session would be perfectly fine — and cheaper/faster — on Sonnet or Haiku.
  • Conversely, a flagged security issue or cross-layer bug may warrant Opus even if the parent session was running a cheaper tier.

Today the only recourse is to open the spawned session and run /model manually after it starts, which undercuts the "one click and walk away" value of task chips.

Proposed Solution

Allow the model to be chosen at chip-accept time. Either (or both) of:

  1. Model picker on the task-chip UI — a dropdown on the chip (defaulting to the inherited/default model) so the user can pick the tier before the session spins up.
  2. Optional model hint on spawn — let the suggesting session pass an optional model parameter via spawn_task, surfaced editably on the chip, so the agent that flagged the work can hint the appropriate tier.

Alternative Solutions

Current workaround: accept the chip, open the spawned session, and run /model <name> manually before doing any real work. This requires remembering to do it every time and wastes the unattended-spawn benefit. Setting a global default model in settings doesn't help because the whole point is that different chips want different tiers.

Priority

Low - Nice to have

Feature Category

Interactive mode (TUI)

Use Case Example

  1. I'm in an Opus session doing a complex refactor.
  2. Mid-task I notice an unrelated stale doc and a separate possible security issue; both get flagged as task chips.
  3. I want the stale-doc fix to run on Haiku (trivial, cheap) and the security investigation to run on Opus (warrants the strongest model).
  4. With this feature I'd set each chip's model before spawning, instead of opening both sessions and running /model by hand.
  5. This saves time and avoids accidentally running cheap work on an expensive tier (or vice versa).

Additional Context

Related: #65586 (programmatic model switch for an already-running session) — complementary but distinct: that request is about switching a live session's model via an API; this is about selecting the model at spawn time for a chip-created session.

View original on GitHub ↗

3 Comments

tjfunction412 · 3 months ago

Strong +1 — and one mechanism correction from empirical testing that I think sharpens this, plus a real-world impact data point.

The issue says spawned chips inherit "the settings model field, else the plan default." In testing on 2.1.104 (desktop), that's not what I observed — a model field in settings.json / settings.local.json / user settings had no effect. What actually determines the chip's model is the primary session's live model selector at the moment you click launch:

| Primary selector at launch | Chip booted as |
|---|---|
| Opus 4.8 | Opus 4.8 |
| Opus 4.8 (after app restart) | Opus 4.8 |
| Opus 4.8 (model set in ~/.claude/settings.json) | Opus 4.8 |
| Sonnet 5 (selector flipped before launch) | Sonnet 5 |

(Verified with four identical "identify your model, one reply, stop" spike chips. Restarts and worktree-vs-local start mode made no difference; only the live selector did.)

Why I'd argue this is more than "nice to have": because the only workaround is "flip the primary selector to the cheap model → launch → flip back," and there's zero per-chip signal of which model a chip will run, the failure mode is silent. In my case a full day of delegated executor work — intended to run Sonnet — actually ran on my primary (pricier) tier because the selector sat there at launch, and I didn't catch it until the usage dashboard. A per-chip selector that shows the chosen model on the chip before launch would turn a silent cost-inflation footgun into an explicit choice.

adamthehutt · 1 month ago

+1, with another angle on why this isn't just a cost optimization.

My common case is the inverse of the "cheap parent, expensive task" direction: I'm running Fable on a complicated multi-step project, and along the way the session notices a trivial unrelated fix and suggests it as a task chip. The chip then launches on Fable too, because that's what the primary selector is sitting on.

That's badly matched to the work. By the time the chip exists, the original session has already done the expensive part — it found the problem, understood the surrounding code, and wrote a fully-specified prompt describing exactly what to change. What's left is often a one-line cleanup. Spending a frontier-tier session on "apply this already-defined one-line edit" is pure overkill, and it happens silently every time.

The suggesting session is also the best-positioned party to make the call, since it knows how much of the thinking it already did. So option 2 in the proposal — an optional model hint passed through spawn_task, surfaced editably on the chip — would cover this well, as long as the chip shows the resulting model before launch and I can override it.

Concretely, what I'd want: choose the model per chip based on the nature of the task, not have every chip inherit whatever tier the parent happened to be on.

dmgsn1 · 1 month ago

Still present on Claude Code Desktop 1.40609.1.0 (Windows 11, CLI 2.1.261). Adding the mechanism behind it, since the thread so far has established the behavior empirically but not the cause — and one dimension of the problem I haven't seen mentioned.

The code path

In the renderer bundle (app/resources/ion-dist/assets/v1/c11959232-DM8o5ho4.js), the chip-start handler looks up the parent session record and copies its settings verbatim:

const l = Tu.getState().sessions.find(e => e.sessionId === r)   // the spawning session
// ...
const y = d
  ? { permissionMode: d.permissionMode, model: d.model, effort: d.effort, sourceBranch: void 0 }
  : { permissionMode: l?.permissionMode, model: l?.model, effort: l?.effort, sourceBranch: l?.sourceBranch }
// ...
await se({ sessionId: e, cwd: h, message: c.prompt, title: c.title, spawnedFrom: ...,
           model: y.model, effort: y.effort, permissionMode: b, ... })

Both start branches do this — local/worktree and cloud ($({ ..., model: y.model, ..., effort: y.effort })).

This confirms @tjfunction412's correction upthread: it is the parent session's live model, and settings.json is not consulted anywhere on this path.

Effort inherits too

effort: y.effort copies the parent's effort level along with the model, and I haven't seen that mentioned in any of the related reports. For anyone running a high effort level on their driving session, this is a larger multiplier than the model tier — and it compounds with it, since both land on the same chip.

Why settings and env can't work around it

The desktop passes the resolved model to the CLI as an explicit --model. CLI precedence is initialMainLoopModel() (the flag) → ANTHROPIC_MODEL → settings.json model, so the flag wins over both. That is the mechanism behind the "settings.json had no effect" results reported in #85868 and in the comment above — it isn't that settings are ignored, it's that they're outranked before they're ever reached.

The app already has the fallback this needs

resolveDefaultSessionModel() exists in the app and is already used by the scheduled-task, title-generation, and one-shot sampling paths. The chip path is the one that doesn't call it. So proposal 1 in the original post is a small change rather than new machinery — and resolveSessionModel already treats a "default" model as "resolve the default" for the scheduled-task sources, so the semantics are in place too.

For proposal 2, spawn_task's current input schema is title, prompt, tldr, cwd — adding optional model and effort hints would fit alongside cwd, which is already a "where/how should this run" parameter rather than task content.

One scoping note on the fix: permissionMode and sourceBranch inheritance seem worth keeping. Those describe where the work happens and are genuinely parent-derived; model and effort describe how expensive it is, and that's the part the parent shouldn't be deciding.

Showing cached comments. Read the full discussion on GitHub ↗