A Claude Code mod that sets Claude's effort level for each turn, automatically. TypeSafe Jev scores your prompt on four narrow questions (reasoning depth, scope, stakes, ambiguity), and Jeffort maps the result onto an effort level. A fifth question asks whether the prompt only approves the previous one ("yes, go ahead"), in which case the previous level stands. The model is never touched.
I don't want to micromanage effort. On the newest models, changing it mid-session no longer throws away the prompt cache, but that only made switching cheap. It didn't make it something I want to keep doing by hand. Claude Code should adjust effort on its own, the way auto mode handles permissions.
Getting it wrong costs either way:
- Too high and you burn tokens on turns that didn't need them.
- Too low and the result can be below par, or need redoing, which costs more tokens than getting it right the first time.
Jeffort picks the level per turn, aiming for the best result and saving money where a turn doesn't need much. A Jev call costs very little next to the output tokens it can save.
If you normally run complex projects on medium, expect Jeffort to pick higher levels quite often. That isn't Jeffort overspending: it's the effort those turns needed, which a fixed medium was quietly under-serving.
I hope and expect Anthropic to ship auto-effort at some point, and I also hope auto-model follows. Jeffort leaves the model alone because switching models mid-session still rebuilds the whole cache.
The band, one row above the prompt, shows the Jeffort button, the level change, a short bar, and this session's tokens saved or spent extra. A drop reads Jeffort's level first, = means Jeffort agreed with your setting, and a boost reads yours first with Jeffort's in bold, in the theme's colour for max (red in Signal):
[ Jeffort ] medium ← high ███████░░░ ~10.5k saved
[ Jeffort ] medium → xhigh ██████▒▒▒▒ ~4.2k extra
[ Jeffort ] medium = medium ████████░░ ~2.1k saved
The bar shows tokens used against saved, or, with the Effort mix style, the share of turns at each level. All plugins share this band: Jeffort draws its row above whatever other plugins put there, and steps aside while Claude Code shows a feedback survey (answer or dismiss it with 0).
Outside the pane everything is in output tokens; dollar estimates and the detail live in the pane. Jeffort's status line under the prompt is used only for warnings, such as a missing key, and clears once a turn scores.
Not ready to let Jeffort change anything? /jeffort audit, or Audit only in the pane, scores every turn and records what Jeffort would have picked, while your own effort runs untouched. The band then reads audit · medium → would pick xhigh, and its bar shows what you ran against what Jeffort's picks would have saved or spent. Audit totals are kept apart from the live ones, for the session, the project and all projects, so you can compare before switching on.
It is also a cheap way to see how your effort is spread: the Effort mix style shows where Jeffort would have put each turn.
Click Jeffort for the pane: the On, Audit only and Off controls, this session's, this project's and all projects' totals with dollar estimates, and where this session's turns landed. It also lists the last few turns with the level Jeffort picked over your own:
The Appearance tab picks a theme and the band's bar style:
The same band and pane work in the Code tab, where the pane docks beside the transcript:
claude plugin marketplace add andrewstephenson-v1/Jeffort
claude plugin install jeffort@jeffort --scope userTo try a local clone for one session instead: claude --plugin-dir /path/to/Jeffort.
Jeffort needs a TypeSafe API key. Put it in a file in your home folder:
mkdir -p ~/.config/jeffort
printf 'TYPESAFE_API_KEY=your-key\nTYPESAFE_MODEL=jev-latest\n' > ~/.config/jeffort/.envJeffort looks in these places, in order, and takes the first value it finds for each variable:
- Process variables (
TYPESAFE_API_KEY,TYPESAFE_MODEL). .envorjeffort.envin the plugin's own folder..envorjeffort.envin~/.config/jeffort/.
Three things that catch people out:
- Your project's
.envis not read. Jeffort never opens files in the project you are working on, because they often hold unrelated secrets. Copy just the TypeSafe lines across:grep '^TYPESAFE_' /path/to/project/.env > ~/.config/jeffort/.env. - A
.envbeside the plugin only helps with--plugin-dir. An installed copy runs from Claude Code's plugin cache, which is not your clone, so a gitignored.envin the repo is not there. Use the home-folder file. - If Claude Code's permission rules block reading
.envfiles (for example aRead(**/.env)deny rule), name the filejeffort.envinstead. This is untested on a machine with such a rule, so tell me if it does not help.
If a turn shows Jeffort: no TYPESAFE_API_KEY found, none of those places had a key. Check with grep -c '^TYPESAFE_API_KEY=.' ~/.config/jeffort/.env, which should print 1. Jeffort rereads the files on each turn until it finds a key, so a fix applies on your next prompt with no reload.
TYPESAFE_MODEL is optional and defaults to jev-latest.
One request per scored turn, holding the prompt, the start of your previous prompt (up to 1,500 characters, so Jev can tell "ok, go ahead" from a new task), and the name of the Claude model that will answer. Before anything leaves your machine, Jeffort masks:
| In your prompt | Sent as |
|---|---|
| Pasted text | [pasted text: N chars] |
| Fenced code blocks | [code: N lines] |
| Inline code of 40 characters or more | [code] |
Keys and tokens (sk-…, ghp_…, xox…, AKIA…, JWTs, PEM keys, password=…, long hex or base64) |
<secret> |
| URLs and connection strings | <url> |
| E-mail addresses | <email> |
| IPv4 addresses | <ip> |
| Absolute and home paths | <path> |
A prompt longer than 4,000 characters keeps its first 3,000 and last 1,000. Slash commands are not sent at all. Short names in backticks and relative paths stay, because they say what kind of work it is. The masking is pattern-based, so an unusual secret format can still get through: check your company's policy before using Jeffort on work repositories.
/jefforttoggles it on and off./jeffort on,audit,offandpanealso work. The band has no on/off button: click Jeffort and use the pane's On, Audit only and Off./jeffort resetclears this session's and this project's totals, live and audit;/jeffort reset allclears every project and the overall totals.- Totals are kept for this session, this project and all projects. A project is the session's project root, keyed by its full path, so two folders with the same name stay separate. A git worktree counts as its own project.
- Appearance tab: Default, Signal, Mono, Colour-safe, Retro, or Match terminal.
- Settings (
/config): the lowest and highest level Jeffort may pick (maxis off by default), whether it sets effort for subagents too (on by default), and the highest level a subagent may get (one above the effort it inherited, by default). - Only lower effort (
/config, off by default): treats the effort you set as a ceiling. Jeffort still drops it for a quick question ("what does this flag do?" at low), but never raises it above your setting, for the main session or subagents. Use it when you set effort deliberately and only want help with the easy turns.
Jeffort only rewrites effort where Claude Code keeps the prompt cache across effort changes. On every other model, each effort level has its own cache, so a change would rebuild the whole conversation.
| Model | Keeps the cache from Claude Code | Released | Note |
|---|---|---|---|
| Fable 5.1 | 2.1.260 | 2026-09-03 | Earlier versions rebuilt the cache on every effort change |
| Opus 5.5 | 2.1.280 | 2026-09-22 | First release with the model |
| Sonnet 5.5 | 2.1.284 | 2026-09-28 | First release with the model |
That only holds with an Anthropic API key or a Claude subscription. It does not hold on Bedrock, Google Cloud's Agent Platform, a Claude apps gateway, with CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS set, or under an organization HIPAA configuration. Source: Claude Code docs, "Changing effort level".
Audit mode changes nothing, so it runs on any model and provider where the session has an effort level, including Bedrock, Vertex and older models.
Jeffort currently needs Claude Code 2.1.284 or later for all three models. It detects Bedrock, Vertex and gateways and does nothing there. For the setups it cannot see from the outside (CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS, an organization HIPAA configuration, an unusual gateway), it checks the API's own cache figures: if the prompt cache is written again after two effort changes in a row, Jeffort stops changing effort for the rest of the session and says so in the status line. /jeffort on resumes. The one-time rebuild on a conversation's first change does not count on its own.
It also leaves these alone, so your own /effort stands:
- Turns where Jev's confidence is below 0.3.
- Turns where Jev cannot be reached or errors.
Only prompts a person wrote are scored: typed, sent over Remote Control, given to claude -p or the SDK, or a scheduled prompt of your own. A turn started by anything else (a background task finishing, another session's message, a channel relay, a subagent reporting back) is not sent to Jev. It keeps the previous turn's level, or the session's effort if there is none yet. So does a prompt Jev reads as only approving the previous one ("yes, go ahead").
Measured on Opus 5.5: the first effort change in a conversation rebuilds about 22k tokens of cache, once. Later changes keep it. That one-time cost is subtracted from the net dollar figure in the pane; the band's token figure is output tokens only. Jeffort spots it as a large cache write on the first request of a turn whose level changed, so it is an estimate too: a compaction on such a turn can look the same.
Each subagent is scored once, on the task it was given, and keeps that level for its whole run. Its turns count toward the totals. It never counts as a cache rebuild, because a subagent starts a fresh conversation. A subagent on a model not listed above (Haiku, say) is left alone, except in audit mode, which changes nothing and so scores it too.
Jeffort only changes a subagent that inherited the session's effort. It cannot read an agent's definition, so it treats an effort other than the session's as one the definition set, and leaves it. The gap: an agent whose definition sets the same level as your session looks inherited and gets scored. Forks and teammates carry on the parent's conversation, so they are left alone too.
A subagent's task is usually a long, detailed brief, and Jev tends to read that as deep and wide work. Left alone, that sends most subagents to xhigh: one heavy multi-agent session ran 217 of 382 turns at xhigh against a medium setting. So a subagent may go at most one level above the effort it inherited. It is scored on the full scale and then capped, so its level means the same as the main loop's. Change it with Highest effort for subagents in /config: same uses the session's ceiling, or pick a fixed level.
Turn subagent scoring off with the Subagents too setting in /config.
Estimates. They assume fixed output-token ratios per effort level, relative to high: low 0.55, medium 0.75, high 1.0, xhigh 1.7, max 2.2. Low and xhigh are rounded from the coding benchmark in bench/ (0.58 and 1.80). Medium is interpolated and max is a guess: neither was measured. Dollar figures cover Opus 5.5 and Sonnet 5.5 only.
Audit estimates run the same ratios the other way: the tokens were measured at your effort, and the estimate is what Jeffort's pick would have produced. They leave out the one-time cache rebuild that switching on would cost (see When it acts).
bench/ holds two benchmarks, each comparing fixed effort levels against Jeffort on Opus 5.5:
bench/run.py: ten short questions.bench/agentic/run.py: eight coding tasks with file and shell tools, graded by tests.
bench/jev_picks.py is a survey rather than a benchmark: it records what Jeffort picks for 26 prompts, coding and not.
On the coding tasks Jeffort used about half the output tokens of xhigh, and every task passed. Every task also passed at low, so those tasks cannot show a quality loss from lower effort. One sample per cell.
claude plugin validate .
claude plugin test .hooks/register.tsx: the hooks module (scoring, band, pane)hooks/redact.ts: masks secrets, code, links and paths before a prompt goes to Jevhooks/policy.ts: Jev questions, level mapping, themes, savings maths (no engine calls)types/index.d.ts: state contracttests/:claude plugin testsuitedocs/ui-options.html: the UI options explored
MIT