Claude says "this should take about 2 days." You finish in 12 minutes.
LLMs have zero feedback between what they promise and what actually happens. claude-eta creates that loop: it times every task, learns your velocity, and feeds real data back into Claude before it responds.
After 10 tasks of the same type, ETAs appear automatically — calibrated on YOUR project.
- You type a prompt
- claude-eta classifies it, starts a timer, injects your velocity stats
- Claude works. Tool calls, file ops, errors counted silently.
- Task completes. Real duration recorded. Next estimate improves.
- After 10 tasks of the same type, ETAs appear automatically at the start of Claude's responses.
Walk-forward replay over real, single-developer task history.
- p80 coverage at prompt typically lands in the 75–80% target range (target: ~80%, since p80 is by definition the value the real duration should fall at or below 80% of the time).
- MdAPE (median absolute % error) sits in the 70–95% range depending on the evaluator stage (
prompt/first edit/first bash) — expected for a single-user dataset and tightens as task volume grows.
The exact numbers, the per-stage breakdown, and the version they were captured at live in docs/eval-snapshot.md, refreshed at each release. Run /eta eval to compute the same report on your own local task history.
When Claude hits the same error 3+ times, claude-eta detects the pattern and intervenes:
- At 3x: warning injected at the next prompt
- At 5x: blocks and forces a strategy change
The key: it fingerprints error CONTENT, not just count. TDD (different errors each time) won't trigger it.
When Claude says "2 days" for a 10-minute task, the bullshit detector corrects inline using your measured project data.
- Node.js >= 18
- Claude Code CLI (latest recommended)
- macOS, Linux, Windows (WSL)
Tested with the current Claude Code CLI. The working install flow is:
claude plugin marketplace add mmmprod/claude-eta
claude plugin install claude-etaIn any already-open Claude Code session, run /reload-plugins before trying /eta.
Fallback from a local checkout:
git clone https://github.com/mmmprod/claude-eta.git
cd claude-eta
claude plugin marketplace add ./
claude plugin install claude-eta --scope localCurrent Claude Code uses claude plugin install, not claude plugin add.
claude plugin marketplace update claude-eta && claude plugin update claude-eta@claude-etaThen restart Claude Code or run /reload-plugins.
claude plugin uninstall claude-etaLocal data stays under ${CLAUDE_PLUGIN_DATA} (typically ~/.claude/plugins/data/claude-eta-*/) until you delete it manually.
| Command | What it does |
|---|---|
/eta |
Current session: active task, completed count, durations, tool calls |
/eta history |
Last 20 completed tasks with real durations and classifications |
/eta stats |
Averages by task type: median duration, tool calls, files touched |
/eta insights |
9 deep analyses: timing patterns, model trends, error overhead, fatigue |
/eta eval |
Offline walk-forward accuracy report on your own data |
/eta inspect |
Raw view of stored data: project fingerprint, turn count, latest entry |
/eta auto |
Auto-ETA status and per-type accuracy |
/eta auto on/off |
Toggle automatic ETA injection at the start of Claude's responses |
/eta compare |
Read-only comparison against community baselines |
/eta contribute |
Preview anonymized data (dry run, requires /eta community on first) |
/eta contribute --confirm |
Upload anonymized data |
/eta community on/off |
Enable or disable community sharing consent |
/eta export |
Save anonymized data locally as JSON |
/eta recap |
Today's daily journal summary |
/eta help |
Full command list |
--max-turns |
claude-eta | |
|---|---|---|
| Detection | Counts turns blindly | Fingerprints error content |
| Trigger | After N turns (any turns) | After 3x same error |
| Response | Kills the session | Injects correction context |
| False positives | Cuts long legitimate sessions | Only fires on repeated identical errors |
| Learning | None | Learns your project's patterns over time |
--max-turns 20 stops Claude after 20 turns whether it's stuck or productive.
claude-eta only intervenes when the same error repeats, and instead of killing the session, it tells Claude what's going wrong and asks it to change strategy.
They're complementary: use --max-turns as a hard ceiling, use claude-eta
for intelligent early intervention.
Everything is local by default. No cloud. No telemetry. No upload unless you explicitly opt in.
/eta inspect shows the current stored view.
/eta contribute is manual and opt-in only. It previews exactly what would be sent before upload.
See SECURITY.md for the full storage and community-data details.
claude-eta hooks run on every Claude Code lifecycle event. Typical overhead is 30–50ms per hook on modern hardware (dominated by Node.js cold start).
Run ./scripts/bench-hooks.sh to measure on your machine.
PostToolUse is the hot path. It reads and writes a single small JSON file (~1KB). No historical data is loaded. No stats are computed.
How the loop detector works
TDD (normal): edit -> test fail A -> fix -> test fail B -> fix -> pass
Repair loop: edit -> test fail A -> edit -> test fail A -> edit -> test fail A
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
claude-eta detects this pattern
The key difference: in a loop, the same error keeps returning. claude-eta fingerprints error content, normalizing away paths, numbers, and quoted values so structurally identical failures match.
Auto-ETA (opt-in estimated duration at response start)
/eta auto on enables automatic ETA injection when claude-eta has enough local calibration for the task type.
/eta auto shows whether the feature is active and how accurate its recent p80 upper-bound coverage has been.
Community baselines
/eta compare is read-only and fetches aggregate community baselines.
/eta contribute stays blocked until you explicitly run /eta community on.
Only anonymized per-task aggregates are sent. Prompts, code, file paths, event logs, and project names are not uploaded.
Self-hosting community baselines
To point /eta compare and /eta contribute at your own Supabase project, set:
CLAUDE_ETA_SUPABASE_URLCLAUDE_ETA_SUPABASE_KEY
The shipped anon key is intentionally public and restricted to INSERT velocity_records
and SELECT baselines_cache.
Insights (9 analyses)
/eta insights surfaces deeper patterns once enough task history exists:
- task type breakdowns
- tool and file-operation correlations
- timing patterns
- model and workflow trends
MIT

