Know before you delegate. Agent ETA gives Codex and Claude Code tasks an honest time range, explains what is driving it, and learns from completed runs without sending prompts or source code to an analytics service.
View the public dashboard · Read the methodology · View the source
Agent ETA is a planning forecast, not a deadline, progress bar, or correctness guarantee. It predicts when the agent is likely to return control.
- About — the modeled midpoint: about half of comparable runs should finish sooner.
- Allow up to — a practical planning bound: about four in five should finish sooner once your history supports that coverage.
- A stage forecast — Orient → Reason → Change → Verify → Deliver.
- Explainable drivers — ranked by marginal minutes, including scope, ambiguity, verification loops, deployment, and a deliberately weak repository-size prior.
- Personal calibration — similar local runs correct the center and upper quantiles without double-counting overlapping cohorts or learning from implausible stop boundaries.
| Surface | Best for | Persists raw prompts or code? |
|---|---|---|
| Web | Public aggregate timing dashboard and private run overview | No |
| CLI | Scripts, terminals, and JSON output | No |
| MCP | Letting Codex or Claude Code request an estimate | No |
| Plugin + hooks | Automatic forecasts and calibration at task boundaries | No |
@agent-eta/core |
Embedding the deterministic engine in another product | Never; the package has no I/O |
The public aggregate dashboard needs no account:
Open the Agent ETA dashboard →
The Overview compares each original ETA with actual time and reports planning-range coverage and median error. Plugin users can import the privacy-safe local runs.jsonl; raw prompts and repository identities are never added to browser or cloud history.
To run every surface from source, use Node.js 24 or newer:
git clone https://github.com/danielsinewe/AgentEstimate.git
cd AgentEstimate
npm ci
npm run buildnode packages/integration/dist/cli.mjs estimate \
"Add passkey login, verify it in the browser, and deploy it" \
--provider codex \
--model gpt-5.6-sol \
--effort high \
--speed standardRead private prompts from stdin if you do not want them in shell history:
node packages/integration/dist/cli.mjs estimate \
--provider claude \
--model sonnet \
--effort high \
--cwd "$PWD" < task.txtUseful local status commands:
node packages/integration/dist/cli.mjs calibrate
node packages/integration/dist/cli.mjs history --limit 20
node packages/integration/dist/cli.mjs estimate "Audit auth" --jsonTo keep the private cloud history and public aggregate current, sign in on the Overview, turn on private sync, and click Copy connection. Then run:
pbpaste | agent-eta sync connectThat one-time connection uploads completed derived metrics and retries automatically after later runs. Check it with agent-eta sync status, retry immediately with agent-eta sync now, or remove the local credential with agent-eta sync disconnect. Delivery is idempotent: retrying the same run does not create a second sample.
Historical JSONL import exists for experiments, but provider transcript formats are not stable APIs:
node packages/integration/dist/cli.mjs history-import /path/to/history.jsonl --provider autoRegister the built stdio server with Codex:
codex mcp add agent-eta -- node "$PWD/packages/integration/dist/mcp.mjs"Or with Claude Code:
claude mcp add --scope user agent-eta -- node "$PWD/packages/integration/dist/mcp.mjs"The server exposes three read-only tools:
estimate_taskreturns the range, stages, input clarity, spread, and top drivers.current_runreads the latest non-stale hook-tracked run for a repository.calibration_statusreports sample counts, median error, and observed midpoint and planning-bound coverage.
Audit a candidate calibration against every completed local run without training on that run itself:
agent-eta backtestThe report compares the original forecasts with leave-one-out candidate forecasts, including median error and 50%/80% coverage targets. High coverage is not automatically good: ranges that catch nearly every run are too wide to be useful.
MCP is excellent for asking for an estimate. Hooks are what make run capture automatic; an agent can otherwise choose not to call an MCP tool.
The build copies the runtime into the self-contained plugin bundle. Load it for a local session with:
claude --plugin-dir "$PWD/plugins/agent-eta"Then send any prompt. The bundled skill, MCP server, and lifecycle hooks work together: the prompt-submit hook computes the return-time range, then gives the agent a privacy-safe developer instruction to show one short line—⏱ About … · allow up to …—before any other reply or tool call. The final answer repeats that original forecast once so it remains visible after progress updates collapse. If estimation fails, Agent ETA says so visibly and lets the prompt continue. Completion hooks record elapsed outcomes for local calibration.
After installing or updating the plugin, start a new session, open /hooks, and trust the reviewed Agent ETA hooks. Codex records trust against the exact hook version, so updates require one fresh review. Then send Reply only OK; the first line should begin with ⏱ About. That canary verifies the plugin, hook, and first-response behavior together. If it only says OK, the hook is not active. AGENTS.md, CLAUDE.md, memory, skills, and MCP alone cannot provide the same lifecycle guarantee.
For workflows that must never start without a forecast, launch Codex or Claude Code with strict mode enabled:
AGENT_ETA_STRICT=1 codex
AGENT_ETA_STRICT=1 claudeStrict mode blocks only when Agent ETA cannot calculate a forecast. Normal mode remains fail-visible and continues the prompt.
The bundle also contains a Codex plugin manifest for personal or team marketplaces. This repository intentionally remains an application repository rather than a marketplace registry; the manual MCP setup above is the checkout-agnostic Codex path.
import { estimateTask } from '@agent-eta/core';
const forecast = estimateTask({
prompt: 'Add a settings form and verify it in the browser.',
provider: 'codex',
model: 'gpt-5.6-sol',
effort: 'high',
speed: 'standard',
repo: { fileCount: 420, linesOfCode: 82_000, testFileCount: 34 },
});
console.log(forecast.formatted.p50, forecast.formatted.p80);The core is deterministic for the same input, seed, and calibration samples. It performs no filesystem, database, telemetry, or network operations.
Agent ETA is an explainable reference-class model, not an opaque claim of machine-learning precision.
- It classifies the task and separates bounded micro-edits from vague product-level work.
- It estimates five stages separately: Orient, Reason, Change, Verify, and Deliver.
- It applies provider/model, effort, and speed interactions. Fast mode only compresses model-bound work; tests and deployments do not magically run faster.
- It adds a capped logarithmic repository prior. Repository size can lengthen orientation, but it cannot dominate the task itself.
- It prices interactions between sequential test, browser, service, and deployment loops.
- It runs 1,600 deterministic correlated simulations with an explicit rework-tail state and reports P25, P50, P80, P95, and the mean.
- Similar local outcomes contribute once through a robust similarity weight; enough history can correct P80/P95 coverage separately from the median.
The full rationale, source review, equations, and known limitations are in docs/research.md.
Raw prompts are processed in memory and are not copied into Agent ETA history. Source files are only sampled locally to derive aggregate repository measurements; file contents are not persisted. Stored runs contain:
- provider, normalized model, effort, and speed;
- derived prompt counts and categories, never prompt fragments;
- aggregate repository metrics, never paths or source text;
- forecast quantiles, timestamps, elapsed duration, and outcome;
- install-salted identifiers for runs, sessions, and repositories.
The web app stores derived calibration samples in that browser's localStorage and includes a reset control. An account is optional. If you sign in and turn on private sync, only the allowlisted derived run fields are stored in Agent ETA's isolated schema in the shared Supabase project. Signing in or enabling sync never uploads existing browser or plugin history. Browser history requires a separate explicit import; plugin history requires a separate one-time connection code. Plugin delivery uses a revocable credential stored with owner-only permissions, retries an idempotent outbox, and never sends prompts, source code, repository names, paths, sessions, or account IDs. Cloud history can be exported or deleted, and deleting Agent ETA data never deletes the shared login identity.
Benchmark contribution is a second, independent opt-in for future completed runs. Contributions stay tied to your private account so you can retract them; raw rows are never public. A service-only aggregation can publish grouped results only after a cohort contains at least 25 runs from 20 distinct contributors. Prompts, code, repository names, paths, and individual runs are not part of the public dataset.
The landing-page dashboard is a separate owner-published snapshot. Only explicitly enabled owners are included, and the public table contains aggregate counts, medians, coverage, and task/provider breakdowns—never user IDs, run IDs, or individual records. Eligible updates are pushed live, with a 30-second polling fallback and a refresh whenever the page becomes visible again.
The CLI/plugin store defaults to ~/.agent-eta/runs.jsonl, or $XDG_DATA_HOME/agent-eta/runs.jsonl when configured. Codex/Claude plugin data directories override that location; an explicit AGENT_ETA_DATA_DIR takes highest priority. On supported systems the directory is created with mode 0700 and the files with mode 0600.
Hook payloads do not consistently expose the active model, effort, or speed setting. Agent ETA uses any values the host supplies and keeps fallback configuration out of the short user-facing forecast. For exact passive forecasts, set AGENT_ETA_MODEL, AGENT_ETA_EFFORT, and AGENT_ETA_SPEED (standard or fast) in the environment that launches Codex or Claude Code; AGENT_ETA_PROVIDER can be set to codex or claude when host detection is unavailable. AGENT_ETA_STRICT=1 blocks a prompt only when no forecast can be produced.
There is no passive product telemetry in the web app, core engine, CLI, hooks, or MCP server. Cloud delivery starts only after the user turns on private sync and explicitly connects the plugin. Benchmark contribution remains a second, separate opt-in.
npm run dev # local web app
npm run test # unit tests
npm run typecheck # TypeScript project checks
npm run lint # Oxlint, warnings denied
npm run build # core + integration + plugin runtime + web
npm run check # complete release gateRepository layout:
apps/web/ Public dashboard and private run overview
packages/core/ Pure forecasting and calibration engine
packages/integration/ CLI, hooks, repository profiler, history, and MCP
plugins/agent-eta/ Codex/Claude Code plugin bundle
docs/research.md Evidence, model design, and limitations
Use About for a rough expectation. Use Allow up to for a meeting, a handoff, or deciding whether to start another task. A wide gap is useful information: reduce ambiguity, specify verification, or split the work before delegating. The structured API keeps the technical field names p50 and p80 for compatibility.
Do not read “80% by 14 minutes” as “80% complete after 11 minutes.” It is a pre-run distribution over comparable outcomes, not a live completion percentage. Until your observed P80 coverage approaches 80%, treat the interval as a structured heuristic rather than a calibrated probability.