# dsh-codex-model-effort-selector > A **Codex-desktop-style "model + reasoning effort" selector** for > [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH): > it replaces the compact model seat above the composer with a Codex-style > popover — one trigger, two panes.       > This image and every other screenshot below are rendered from the plugin's > **real CSS and class names**, extracted verbatim from `client.js` by > `test/make-readme-shots.mjs` (only the React runtime is replaced). They are not > hand-drawn mockups. [中文说明](README.md) · **English** --- ## Table of contents - [What it is](#what-it-is) - [Features](#features) - [Install](#install) - [Usage](#usage) - [Compatibility & known limitations](#compatibility--known-limitations) - [Development](#development) - [Project layout](#project-layout) - [Docs](#docs) - [FAQ](#faq) - [Credits & license](#credits--license) --- ## What it is DSH ships a tiny model button above the composer. This plugin **takes over that seat** (via `priority: -1`) and opens a Codex-style popover with two panes: | Pane | Contents | |---|---| | **Reasoning effort** | A pixel-replica Codex effort slider: evenly spaced stops, one colour per stop, a violet stardust rail at Ultra | | **Model list** | A provider-grouped two-level drill-down (provider → models + search), each row badged with its level count | One trigger drives both, exactly like the Codex desktop app. **The geometry is not eyeballed.** Card height, rail position and size, knob diameter, tick dots and row pitch were all measured **frame-by-frame from a 93-frame recording of the Codex desktop app** (the recording is 1.385×, so `CSS px = recorded px ÷ 1.385`); colours were sampled the same way. Full measurements are in [`docs/SPEC.md`](docs/SPEC.md). --- ## Features ### Reasoning-effort pane  - **Evenly spaced stops**: re-ordered to whatever levels the model actually declares — as many stops as the model has. The Codex ladder holds up to 7: `off → minimal → low → medium → high → xhigh → Ultra` - **One colour per stop**: fill, rail tint, heading ink and the collapsed trigger all change together — hue advances monotonically from blue `216.6°` to violet `263.9°`, instead of only Ultra being special - **Drag tracks the pointer**: while dragging the knob follows continuously (**no snapping**); snapping happens on release - **Keyboard**: `←/→` or `↑/↓` move one stop, `Home`/`End` jump to either end - **Ultra**: the rail switches to an animated violet gradient plus 22 stardust particles, and shows a "consumes quota faster" warning for 1.8 s - **Fast toggle** (⚡): visual only — it does **not** change real speed or usage - **Reset** button: restores the model's default level #### Fast on / off  The same `high` level, side by side — the ⚡ turns from an outline into a solid bolt, the rail lights up with stardust particles, and the collapsed seat grows its own ⚡. None of it changes real speed or usage. ### Model pane (two-level drill-down)  | Level | Contents | |---|---| | **First** | Provider list; **the provider holding the current model carries a blue dot on the right**. Each row is just provider name + dot + trailing chevron | | **Second** | Slides in after tapping a provider: back button + provider title + search box + that provider's models | - Each model row carries an **"N levels" badge**; models without reasoning support are greyed out as "unsupported"; the current model shows a check mark - **Search**: case-insensitive, with **non-contiguous in-order character matching** (the same rule the official menu uses) - **Switching model lands on the middle level**: `floor(n/2)` — 4 levels → the 3rd; models with no levels omit the `reasoningEffort` key entirely (absent means "no opinion", which differs from an explicit `null`) - **Provider load failures are surfaced**, not swallowed: once this plugin shadows the official seat, the official per-provider failure messages become its responsibility — a failing row reads `{name} failed to load: {message}` instead of a blank panel - `Escape` **steps back one level at a time**: second → first → effort pane → closed ### Two details that are easy to miss  - **The Fast tooltip is a `position:fixed` layer**: as a child of the popover it would be clipped by `overflow:hidden`, so it is rendered as a fixed layer and positioned dynamically - **The Ultra warning's timing**: the moment you cross **into** Ultra from a non-Ultra level, the middle column and both tool buttons fade out while the warning fades in with a single sweep (1.1 s, 0.2 s delay); it then **stays for 1.8 s** before fading back to the level heading. So the warning appears **immediately** rather than after 1.8 s. Staying on Ultra does not re-trigger it, and leaving Ultra restores the heading **instantly** (no need to wait out the 1.8 s) ### Dark mode  Same layout, same real CSS as the other shots — rendered on the shipped dark surfaces: the seven levels live, the Ultra warning state and the collapsed seats. In the dark theme **the entire palette is re-solved against the shipped dark surfaces**: - **Theme detection reads the official signal**: the `data-ds-dark-theme` attribute on `
` (set by the official theme boot script; every shipped dark token keys off that same selector). It deliberately does **not** use `prefers-color-scheme` — when the user pins "dark" while the OS is light, the media query disagrees with the palette actually in force. A `MutationObserver` subscription recolours **live** when the theme is switched in settings, no reload needed - **All seven stops re-solved**: v1.0.0's light inks all fall below AA on the dark card (`high` reached only 1.83:1 — practically invisible). The dark table keeps the same hue axis (blue → violet) but luminance now **rises** with effort — on a dark card, "darker" means "less visible" - **The rail becomes an inset groove** `#232324`: the pale `#e8e7e8` was an 11.3:1 glare bar on the dark card - **The knob becomes a bright puck**: the token it inherited resolved to `#2c2c2e` in dark, nearly identical to the track — the knob simply vanished - **The Ultra warning sweep inverts**: the light theme sweeps a dark band over violet text, which drops below contrast on a dark card, so dark sweeps a light band; all 15 gradient stops were lifted above the track floor too - The light theme is **bit-for-bit unchanged**: both palettes are validated against every WCAG floor by `test/palette.mjs` (24 assertions), with a regression guard against light values leaking back into the dark table ### Accessibility & robustness - `role="slider"` with `aria-valuemin/max/now/valuetext`; the popover carries `aria-expanded`/`aria-haspopup`/`aria-busy` and is `inert` while closed - Every fill and ink clears its WCAG floor **in both themes** (asserted per-item by `test/palette.mjs`, once per palette) - **Dark mode**: see [the section above](#dark-mode) — official signal detection, shipped dark surfaces, live recolouring on theme switch - **Fail-open**: it registers no host hooks, emits no events and touches no official classes or text. If any anchor is unrecognisable (directory not ready, not its own session, subagent session) it **does nothing**, leaving the official UI intact --- ## Install ### Requirements - DSH `0.2.1-rc.2` (also runs on `0.2.0-rc.2`; the label child slot degrades gracefully) - **No build step**: `client.js` *is* the release artifact — hand-written and statically auditable ### Option 1 — DSH Desktop plugin panel (recommended) The `desktop` profile is managed exclusively by Electron, so it cannot be installed from the CLI. Use the panel: 1. Copy this directory anywhere on your machine (**do not move or delete it afterwards**) 2. Open DSH Desktop → **Settings → Plugins → Add plugin** 3. Enter **the full path of this directory** (not a zip, not `package.json`) 4. Tick the trust confirmation → **Install** → **Enable now** 5. If prompted to restart, **fully quit and reopen** DSH Desktop ### Option 2 — command line (non-desktop profiles only) ```powershell dsh plugin --profile web add link:"