SLOPSHOPPER

plan-opus-upgrade

With CLAUDE_PLAN_OPUS=1, a main-loop request that is exactly sonnet at medium effort in plan mode is sent as opus at high effort. Any other model, effort, mode…

new
A shopper browsing a rack in a slop shop
README

dotclaudefiles

My personal Claude Code plugins repository. Contains multiple plugins for different workflows.

Available Plugins

PluginDescription
dotclaudefilesCommands, agents, skills, and configs I use daily

Install

# Add marketplace (once)
/plugin marketplace add DieGopherLT/dotclaudefiles

# Install plugin
/plugin install dotclaudefiles@diegopher

Setup Dotfiles (Optional)

⚠️ Warning: This will replace your local files with the repo version (backups are created automatically).

# Bash
./scripts/stow-claude.sh

# Fish
./scripts/stow-claude.fish

Status Line (Optional)

Want a status line? Use dotfiles/claude/.config/ccstatusline/settings.json with:

ccstatusline (Node.js) sirmalloc/ccstatusline - Feature-rich status line with extensive customization.

or

cc-status-line (Go) Install DieGopherLT/cc-status-line - Lightweight Go implementation with better performance.

They both look almost identical, Go version made by me includes a visual context indicator.

Update

/plugin marketplace update diegopher
/plugin install dotclaudefiles@diegopher

Uninstall

/plugin uninstall dotclaudefiles@diegopher

Diego (@DieGopherLT)

Source 1 files
hooks/register.ts 44 lines
1import type { Register } from 'claude-code'
2
3// turn.step takes the resolved id, as e.model carries it: the 'opus' alias is
4// refused by the API. shortcut: pinned id, bump it when a newer Opus ships.
5const PLAN_MODEL = 'claude-opus-5-5'
6
7export const register: Register = on => {
8  // shortcut: one transcript line per decision change to verify the mode and
9  // model strings live, drop once confirmed.
10  let lastDecision = ''
11  let permissionMode: string | undefined
12  let isEnabled: Promise<boolean> | undefined
13
14  // Every classic event carries the live permission mode; Shift+Tab and
15  // Enter/ExitPlanMode show up at the next one, before the next model request.
16  on('classic.*', async ($, e, next) => {
17    permissionMode = e.permission_mode
18    return next(e)
19  })
20
21  on('turn.step', async function* ($, e, next) {
22    isEnabled ??= $.env.get('CLAUDE_PLAN_OPUS').then(value => value === '1')
23
24    // Only the exact session default (sonnet at medium) is upgraded, so an
25    // explicit /model or /effort choice is never overridden.
26    const isUpgrade =
27      (await isEnabled) &&
28      e.agentId === undefined &&
29      permissionMode === 'plan' &&
30      /sonnet/i.test(e.model) &&
31      e.effort === 'medium'
32
33    if (e.agentId === undefined) {
34      const decision = `mode=${permissionMode} model=${e.model} effort=${e.effort} upgraded=${isUpgrade}`
35      if (decision !== lastDecision) {
36        lastDecision = decision
37        $.ui.log(`plan-opus-upgrade: ${decision}`)
38      }
39    }
40
41    return yield* next(isUpgrade ? { ...e, model: PLAN_MODEL, effort: 'high' } : e)
42  })
43}
44