Skip to content

feat(web): pick Codex and Claude effort with an effort dial - #551

Draft
incognitojam wants to merge 8 commits into
mainfrom
styal/effort-dial
Draft

incognitojam wants to merge 8 commits into
mainfrom
styal/effort-dial

Conversation

@incognitojam

@incognitojam incognitojam commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Note

For Codex and Claude, the composer's model pill now opens an effort dial: a slider over four levels, Light, Standard, Deep and Ultra. Each level picks a model and reasoning effort from a fixed table, across both providers when both are set up. The separate effort menu goes away for those providers.

Problem

The effort menu listed every reasoning level each model offers, so it was easy to run Opus 5.5 at xhigh or max, or Fable when a cheaper model would do. Benchmarks don't back those choices. On FrontierCode, Opus 5.5 at medium matches max at about an eighth of the cost. Choosing well also meant knowing which provider and model suit each kind of task, and for users with both subscriptions that choice decides whose usage a thread spends.

Change

Levels. packages/shared/src/effortDial.ts resolves each level to a provider, model and effort:

Level Both providers, new thread Claude only, or a Claude thread Codex only, or a Codex thread
Light GPT-6.1-Sol, medium Sonnet 5.5, high GPT-6.1-Sol, low
Standard Opus 5.5, medium Opus 5.5, medium GPT-6.1-Sol, medium
Deep Opus 5.5, high Opus 5.5, high GPT-6.1-Sol, xhigh
Ultra Fable 5.1, high Fable 5.1, high GPT-6-Astra, xhigh
  • Each cell is an ordered list, so a CLI without the newest model falls back. With Codex before 0.159, for example, GPT-6.1-Sol levels move to GPT-6-Sol or GPT-6-Astra.
  • A model chosen from the model list that the tables don't cover stays selected; the levels change only its effort (low, medium, high, xhigh, or the nearest it offers).
  • The choices follow benchmarks run through the real Codex and Claude Code harnesses where available.

Composer. This follows the Codex app's picker:

  • The pill shows the model and level, for example "Claude Opus 5.5 Deep", or the raw effort when the selection matches no level. Its tooltip names the model and its effort.
  • The popover follows the ChatGPT picker: a model row showing the effort on top, then the level names over a chunky slider, then a speed toggle. Clicking a name also selects its level. The thumb and fill animate between levels with a 150ms transform transition, which is off when reduced motion is on.
  • The model row opens a short list: Default, then the current built-in Codex and Claude models (no legacy or custom models, and only the thread's provider once it has started), then All models, which opens the existing full picker.
    • Choosing a model switches the slider to that model's own efforts (Low to Max or Ultracode), and the pill shows the raw effort. This is how to run, say, Opus at xhigh.
    • Choosing Default returns to the levels. If the current selection matches no level, it moves to Standard.
    • The mode is a client setting (effortControl, levels or custom).
  • Speed is Claude's fast mode or Codex's service tier, which previously lived in the effort menu. Its usual setting is labelled "Normal" so it doesn't read as the Standard level. A cost icon on Fast shows the provider's description on hover:
    • Codex: from its catalog, for example "2x speed, increased usage".
    • Claude: the manifest's fast mode option now carries a description taken from Claude Code's own wording: "Same model, faster output. Billed to usage credits rather than your plan's included usage."
    • Neither provider gives a numeric price ratio.
  • Keyboard: the model picker keybinding and /model open the full model list directly.
  • Context window: each model's default applies (1M for Opus 5.5 and Fable 5.1, 200k for Sonnet 5.5). A thread that already chose a size keeps it.

Started threads. Levels stay on the thread's provider. Stops that would switch its model have a dashed ring. Choosing one says the next turn re-reads the whole conversation. Effort-only changes apply without a restart (Claude since #541).

Unchanged.

  • Other providers keep their effort menu.
  • The settings panels (project default model, text generation model) keep the full pickers.
  • The server is untouched: a level writes an ordinary model selection.

Docs: a new "Effort levels" section in the composer guide, a bullet in the styal differences page, and the effort-dial fork ledger entry.

Not in this PR:

  • Mobile: its thread settings sheet still shows the raw effort choices.
  • Usage notes and pacing: for example Fable's weekly allowance on Ultra.
  • Keybindings to step between levels.

Evidence

The screenshots come from a dev server with isolated state and real Codex 0.159 and Claude Code providers. Thread names come from earlier testing.

Before: the effort menu After: new thread at Light
Before: effort menu listing Low to Ultrathink plus context window After: level names over the slider at Light, resolving to GPT-6.1-Sol with a speed toggle
Started Claude thread, light theme Narrow footer
Light theme: Deep selected in a Sonnet thread, with dashed rings on stops that switch model and the model-switch note Narrow footer: the pill shows only the level, with the dial open above it
Dial at Standard Model list
Model row with effort above the level names and a chunky slider at Standard Short model list: Default, current Codex and Claude models, All models
A chosen model's own efforts Fast cost note
GPT-6.1-Sol chosen: the slider covers its own efforts, at Ultra Hovering Fast on Opus 5.5 shows how Claude bills fast mode

Validation

  • New thread, both providers ready (browser automation against the dev server): the slider moved the pill through Light (GPT-6.1-Sol medium), Standard (Opus 5.5 medium), Deep (Opus 5.5 high) and Ultra (Fable 5.1 high). The speed toggle appears only for models that offer it. The model row opens the model list, and reopening the pill returns to the dial. No console or page errors.
  • Started Claude thread on Sonnet 5.5 at low: the pill showed "Low" with no level selected. Every level stayed on Claude, and Standard, Deep and Ultra carried the model-switch note.
  • Selection matching no level: choosing Light worked. It initially didn't, because the hidden input already rested on that stop; the panel now also applies stops on click.
  • Narrow footer and light theme: checked in screenshots.
  • Animation: sampled the thumb's transform every ~30ms after moving from Standard to Deep. It eased from 81px to 163px and settled within about 160ms.
  • Tooltip: hovering the model name shows "Claude Opus 5.5, high effort".
  • Model list: the list showed Default plus GPT-6.1-Sol, GPT-6-Astra, GPT-6-Luna, Opus 5.5, Fable 5.1 and Sonnet 5.5, with no legacy models.
    • Choosing GPT-6.1-Sol showed "GPT-6.1-Sol Medium" and a slider over its own efforts. Its top effort, Ultra, gave "GPT-6.1-Sol Ultra".
    • The list then checked GPT-6.1-Sol, not Default.
    • All models opened the full picker.
    • Choosing Default returned to "Claude Opus 5.5 Standard".
    • An earlier build confirmed that the mode survives a reload.
  • Fast cost note: hovering the icon showed Codex's catalog text for GPT-6.1-Sol and the manifest text for Opus 5.5. The Claude text shows only with this branch's manifest; the dev check ran with provider update checks off, because the server otherwise prefers the published manifest from main.
  • Tests: packages/shared/src/effortDial.test.ts covers the tables, provider locking, fallbacks, models off the tables, and instance choice. apps/web/src/components/chat/effortDial.logic.test.ts covers which models the dial offers and the speed control. The existing ProviderModelPicker and source-control writing settings suites pass.
  • Checks: web typecheck, lint (no new warnings), format, and ledger check.
  • Not verified: mobile, which is unchanged, and the desktop shell, which uses the same web code.

Written by an agent (Claude Code, claude-opus-5-5).

Four levels, Light to Ultra, each resolve to a Codex or Claude model and
reasoning effort from fixed tables: one per provider for locked threads
and single-provider setups, and a cross-provider table for new threads
when both are ready. A model the tables do not cover keeps its model and
only changes effort.
The model pill opens a Faster to Smarter slider over the four levels,
with the resolved model and a speed toggle. The model row opens the
model list, and the model picker keybinding and /model go straight to it.
The separate effort menu goes away for Codex and Claude; other providers
keep it. In a started thread, levels stay on its provider and levels
that switch model are marked.
@incognitojam incognitojam added the preview:web Deploy a hosted-web preview to Cloudflare Workers for this PR on every push. label Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Web preview

https://styal-web-pr-551.cameron-clough.workers.dev (for de952a6)

Open this exact URL; the hosted-app origin is baked in at build time. Pair a server into it with styal pair --tailscale, or paste a host and pairing code under Settings → Connections.

The preview is deleted when this PR closes or the preview label is removed.

The level names sit over their stops and select them on click, the thumb
and fill animate between levels, the usual speed is called Normal so it
does not read as the Standard level, and the model pill's tooltip names
the model and its effort instead of repeating the label.
The manifest's fast mode option now says it runs the same model faster
and is billed to usage credits rather than the plan's included usage,
matching Claude Code's own wording.
An Effort toggle in the dial switches between the four levels and the
selected model's own reasoning efforts, remembered as a client setting.
A cost icon on Fast shows the provider's description of what faster
output costs.
@github-actions github-actions Bot added the 📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. label Sep 30, 2026
The dial's model row opens a list of Default and the current Codex and
Claude models, like the ChatGPT picker, instead of a separate Effort
toggle. Choosing a model switches the slider to its own efforts and
Default returns to the levels; All models opens the full picker. The
model row moves above a chunkier slider.

This branch was successfully deployed

1 active deployment
web-preview — de952a67 Deployed Sep 30, 2026 by incognitojam via Deploy web preview #225
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. preview:web Deploy a hosted-web preview to Cloudflare Workers for this PR on every push. size:XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant