Skip to content

Repository files navigation

claude-effort-kit

CI License: MIT Python Claude Code Zero deps

Stop burning Opus quota on tasks Haiku could solve.

A tiny, opinionated kit for Claude Code that suggests the right model and effort level before you send your prompt — and tells you when your quota is likely to reset when you hit the wall.

🎯 Model + Effort suggestion (auto)

Recommended model: Sonnet 4.6
Effort: Medium
Reason: targeted bugfix

> Switch manually: Cmd+Shift+I (model) · Cmd+Shift+E (effort)
> Rule: bugfix

No accounts. No API. No telemetry. Local files only.


Why

Claude Code lets you switch model (Cmd+Shift+I) and effort (Cmd+Shift+E) per session, but nobody actually does it because there's no nudge. So Opus gets used for one-line CRUD prompts and the 5-hour rolling quota burns out before lunch.

claude-effort-kit injects a one-block suggestion into every prompt so the choice is in your face. You still pull the trigger.

What's in the box

Component Role
hooks/model_effort_suggest.py UserPromptSubmit hook — pattern-matches your prompt against a YAML matrix and prints a model/effort recommendation
bin/quota_reset.py Heuristic estimator of your Anthropic 5-hour rolling reset, based on local CLI activity logs
rules/model-effort-suggest.md A short rule file that tells the assistant to acknowledge the suggestion at task start
config/matrix.yaml The decision matrix — fully editable. FR + EN keywords by default

Total surface: ~400 lines, zero runtime dependencies (PyYAML used if available, fallback parser otherwise).

Install

git clone https://github.com/<you>/claude-effort-kit.git
cd claude-effort-kit
bash install.sh

The installer:

  1. Backs up ~/.claude/settings.json
  2. Adds a UserPromptSubmit hook entry pointing to this repo
  3. Copies the rule into ~/.claude/rules/
  4. Appends @rules/model-effort-suggest.md to your ~/.claude/CLAUDE.md
  5. Symlinks quota_reset.py into ~/.claude/bin/

Idempotent. Re-run any time. To remove: bash uninstall.sh.

Usage

Hook (automatic)

Once installed, every prompt you send in Claude Code triggers the hook. If the prompt matches a rule, the assistant sees a markdown block at the top of its turn:

🎯 Model + Effort suggestion (auto)
Recommended model: Opus 4.7 1M
Effort: Very High
Reason: architecture / strategic / regulatory — high ambiguity

The assistant typically acknowledges and proposes the switch. You decide.

Quota estimator (manual)

When you hit "Limite d'utilisation atteinte":

~/.claude/bin/quota_reset.py
📊 Anthropic quota — local estimate
─────────────────────────────────
  Burst started     : 2026-05-06T14:52+02:00
  Last activity     : 2026-05-06T19:44+02:00
  Estimated reset   : 2026-05-06T19:52+02:00
  Time to reset     : ~8min
  Events in window  : 2061
  Window            : 5.0h rolling
─────────────────────────────────
  ⚠️  Source = local CLI activity only. claude.ai web usage not visible.

Limitations:

  • Sees CLI activity only — claude.ai web usage is not visible
  • Counts events, not tokens — actual reset may come earlier
  • Treats consecutive events with gaps under window/3 as one burst

Customize the matrix

Copy the bundled matrix to a user-level override:

mkdir -p ~/.claude/effort-kit
cp config/matrix.yaml ~/.claude/effort-kit/matrix.yaml
$EDITOR ~/.claude/effort-kit/matrix.yaml

The hook checks in this order:

  1. $CLAUDE_EFFORT_KIT_MATRIX (explicit env override)
  2. ~/.claude/effort-kit/matrix.yaml (per-user)
  3. <repo>/config/matrix.yaml (bundled default)

Matrix shape

version: 1
rules:
  - id: my-rule
    patterns:
      - "regex one"
      - "regex two"
    model: "Sonnet 4.6"
    effort: "Medium"
    reason: "short justification"

Rules are tried top-to-bottom; the first match wins. Patterns are case-insensitive Python regex.

Bundled rules (default)

Rule Model Effort Trigger examples
architecture Opus 4.7 1M Very High "refonte archi", "design system", "compliance"
long-context Opus 4.7 1M High "monorepo", "migration", "1m context"
deep-debug Sonnet 4.6 High "race condition", "deadlock", "flaky"
lookup Haiku 4.5 Low "what is", "explique", "summary"
mechanical-code Sonnet 4.6 High "CRUD", "endpoint", "écris des tests"
refactor Sonnet 4.6 Medium "refactor", "rename", "extract"
bugfix Sonnet 4.6 Medium "fix", "corrige", "error"
ops-deploy Sonnet 4.6 Medium "deploy", "ci/cd", "docker"
strategic-discussion Opus 4.7 1M Very High "stratégie", "trade-off", "decision"

How it fits into Claude Code

┌─ user types prompt
│
├─ Claude Code fires UserPromptSubmit hook
│   └─ model_effort_suggest.py reads stdin → matches matrix → writes suggestion to stdout
│
├─ stdout is injected as additional context for the assistant
│
└─ assistant sees the suggestion + your prompt → can acknowledge before answering

The hook is read-only, deterministic, and exits 0 in every failure path. A broken matrix never blocks your chat.

Development

# run tests (needs pytest + pyyaml)
pip install pytest pyyaml
pytest tests/ -v

# run install/uninstall smoke
bash tests/test_install.sh

CI runs both jobs on Ubuntu + macOS, Python 3.10 / 3.11 / 3.12.

FAQ

Does this affect my Anthropic API spend? No. The hook runs locally before your prompt is sent. It adds a small amount of context (the suggestion block) but no extra round-trip.

Can I disable the suggestion for a specific prompt? Phrase your prompt so it doesn't match any rule, or use /caveman stop-style markers in your team's matrix to short-circuit.

Why YAML, not TOML / JSON? YAML reads better for keyword lists. The hook ships with a tiny fallback parser so PyYAML is optional.

The reset estimator is wrong / off by an hour. The 5-hour window is rolling, not aligned to the hour. The estimator returns burst_start + window, which is the earliest reset; partial capacity may return sooner. claude.ai web usage is invisible to the estimator.

License

MIT. See LICENSE.

About

Suggests optimal Claude model + effort per prompt, and estimates your 5h rolling quota reset. Local hook for Claude Code.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages